FreeRDP
irp.c
1 
23 #include <freerdp/config.h>
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <winpr/crt.h>
30 #include <winpr/stream.h>
31 
32 #include <freerdp/utils/rdpdr_utils.h>
33 
34 #include "rdpdr_main.h"
35 #include "devman.h"
36 #include "irp.h"
37 
43 static UINT irp_free(IRP* irp)
44 {
45  if (!irp)
46  return CHANNEL_RC_OK;
47 
48  if (irp->input)
49  Stream_Release(irp->input);
50  if (irp->output)
51  Stream_Release(irp->output);
52 
53  winpr_aligned_free(irp);
54  return CHANNEL_RC_OK;
55 }
56 
62 static UINT irp_complete(IRP* irp)
63 {
64  size_t pos = 0;
65  rdpdrPlugin* rdpdr = NULL;
66  UINT error = 0;
67 
68  WINPR_ASSERT(irp);
69  WINPR_ASSERT(irp->output);
70  WINPR_ASSERT(irp->devman);
71 
72  rdpdr = (rdpdrPlugin*)irp->devman->plugin;
73  WINPR_ASSERT(rdpdr);
74 
75  pos = Stream_GetPosition(irp->output);
76  Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4);
77  Stream_Write_UINT32(irp->output, irp->IoStatus); /* IoStatus (4 bytes) */
78  Stream_SetPosition(irp->output, pos);
79 
80  error = rdpdr_send(rdpdr, irp->output);
81  irp->output = NULL;
82 
83  irp_free(irp);
84  return error;
85 }
86 
87 IRP* irp_new(DEVMAN* devman, wStreamPool* pool, wStream* s, wLog* log, UINT* error)
88 {
89  IRP* irp = NULL;
90  DEVICE* device = NULL;
91  UINT32 DeviceId = 0;
92 
93  WINPR_ASSERT(devman);
94  WINPR_ASSERT(pool);
95  WINPR_ASSERT(s);
96 
97  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
98  {
99  if (error)
100  *error = ERROR_INVALID_DATA;
101  return NULL;
102  }
103 
104  Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
105  device = devman_get_device_by_id(devman, DeviceId);
106 
107  if (!device)
108  {
109  if (error)
110  *error = ERROR_DEV_NOT_EXIST;
111 
112  return NULL;
113  }
114 
115  irp = (IRP*)winpr_aligned_malloc(sizeof(IRP), MEMORY_ALLOCATION_ALIGNMENT);
116 
117  if (!irp)
118  {
119  WLog_Print(log, WLOG_ERROR, "_aligned_malloc failed!");
120  if (error)
121  *error = CHANNEL_RC_NO_MEMORY;
122  return NULL;
123  }
124 
125  ZeroMemory(irp, sizeof(IRP));
126 
127  Stream_Read_UINT32(s, irp->FileId); /* FileId (4 bytes) */
128  Stream_Read_UINT32(s, irp->CompletionId); /* CompletionId (4 bytes) */
129  Stream_Read_UINT32(s, irp->MajorFunction); /* MajorFunction (4 bytes) */
130  Stream_Read_UINT32(s, irp->MinorFunction); /* MinorFunction (4 bytes) */
131 
132  Stream_AddRef(s);
133  irp->input = s;
134  irp->device = device;
135  irp->devman = devman;
136 
137  irp->output = StreamPool_Take(pool, 256);
138  if (!irp->output)
139  {
140  WLog_Print(log, WLOG_ERROR, "Stream_New failed!");
141  irp_free(irp);
142  if (error)
143  *error = CHANNEL_RC_NO_MEMORY;
144  return NULL;
145  }
146 
147  if (!rdpdr_write_iocompletion_header(irp->output, DeviceId, irp->CompletionId, 0))
148  {
149  irp_free(irp);
150  if (error)
151  *error = CHANNEL_RC_NO_MEMORY;
152  return NULL;
153  }
154 
155  irp->Complete = irp_complete;
156  irp->Discard = irp_free;
157 
158  irp->thread = NULL;
159  irp->cancelled = FALSE;
160 
161  if (error)
162  *error = CHANNEL_RC_OK;
163 
164  return irp;
165 }