6b01632a75a3590e8c9b33484134204da0ef433d
[reactos.git] / reactos / ntoskrnl / io / buildirp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/buildirp.c
5 * PURPOSE: Building various types of irp
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 * Fixed IO method handling 04/03/99
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 NTSTATUS IoPrepareIrpBuffer(PIRP Irp,
22 PDEVICE_OBJECT DeviceObject,
23 PVOID Buffer,
24 ULONG Length,
25 ULONG MajorFunction)
26 /*
27 * FUNCTION: Prepares the buffer to be used for an IRP
28 */
29 {
30 Irp->UserBuffer = Buffer;
31 if (DeviceObject->Flags & DO_BUFFERED_IO)
32 {
33 DPRINT("Doing buffer i/o\n");
34 Irp->AssociatedIrp.SystemBuffer = (PVOID)
35 ExAllocatePool(NonPagedPool,Length);
36 if (Irp->AssociatedIrp.SystemBuffer==NULL)
37 {
38 IoFreeIrp(Irp);
39 return(STATUS_NOT_IMPLEMENTED);
40 }
41 /* FIXME: should copy buffer in on other ops */
42 if (MajorFunction == IRP_MJ_WRITE)
43 {
44 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length);
45 }
46 }
47 if (DeviceObject->Flags & DO_DIRECT_IO)
48 {
49 DPRINT("Doing direct i/o\n");
50
51 Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
52 if (MajorFunction == IRP_MJ_READ)
53 {
54 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
55 }
56 else
57 {
58 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoReadAccess);
59 }
60 Irp->UserBuffer = NULL;
61 Irp->AssociatedIrp.SystemBuffer = NULL;
62 }
63 return(STATUS_SUCCESS);
64 }
65
66 PIRP IoBuildFilesystemControlRequest(ULONG MinorFunction,
67 PDEVICE_OBJECT DeviceObject,
68 PKEVENT UserEvent,
69 PIO_STATUS_BLOCK IoStatusBlock,
70 PDEVICE_OBJECT DeviceToMount)
71 /*
72 * FUNCTION: Allocates and sets up a filesystem control IRP
73 * ARGUMENTS:
74 * MinorFunction = Type of filesystem control
75 * DeviceObject = Device object to send the request to
76 * UserEvent = Event used to notify the caller of completion
77 * IoStatusBlock (OUT) = Used to return the status of the operation
78 * DeviceToMount = Device to mount (for the IRP_MN_MOUNT_DEVICE
79 * request)
80 */
81 {
82 PIRP Irp;
83 PIO_STACK_LOCATION StackPtr;
84
85 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
86 if (Irp==NULL)
87 {
88 return(NULL);
89 }
90
91 Irp->UserIosb = IoStatusBlock;
92 Irp->UserEvent = UserEvent;
93
94 StackPtr = IoGetNextIrpStackLocation(Irp);
95 StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
96 StackPtr->MinorFunction = MinorFunction;
97 StackPtr->Flags = 0;
98 StackPtr->Control = 0;
99 StackPtr->DeviceObject = DeviceObject;
100 StackPtr->FileObject = NULL;
101 StackPtr->CompletionRoutine = NULL;
102
103 switch(MinorFunction)
104 {
105 case IRP_MN_USER_FS_REQUEST:
106 break;
107
108 case IRP_MN_MOUNT_VOLUME:
109 StackPtr->Parameters.Mount.Vpb = DeviceObject->Vpb;
110 StackPtr->Parameters.Mount.DeviceObject = DeviceToMount;
111 break;
112
113 case IRP_MN_VERIFY_VOLUME:
114 break;
115
116 case IRP_MN_LOAD_FILE_SYSTEM:
117 break;
118 }
119 return(Irp);
120 }
121
122 PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction,
123 PDEVICE_OBJECT DeviceObject,
124 PVOID Buffer,
125 ULONG Length,
126 PLARGE_INTEGER StartingOffset,
127 PIO_STATUS_BLOCK IoStatusBlock)
128 /*
129 * FUNCTION: Allocates and sets up an IRP to be sent to lower level drivers
130 * ARGUMENTS:
131 * MajorFunction = One of IRP_MJ_READ, IRP_MJ_WRITE,
132 * IRP_MJ_FLUSH_BUFFERS or IRP_MJ_SHUTDOWN
133 * DeviceObject = Device object to send the irp to
134 * Buffer = Buffer into which data will be read or written
135 * Length = Length in bytes of the irp to be allocated
136 * StartingOffset = Starting offset on the device
137 * IoStatusBlock (OUT) = Storage for the result of the operation
138 * RETURNS: The IRP allocated on success, or
139 * NULL on failure
140 */
141 {
142 PIRP Irp;
143 PIO_STACK_LOCATION StackPtr;
144
145 DPRINT("IoBuildAsynchronousFsdRequest(MajorFunction %x, DeviceObject %x, "
146 "Buffer %x, Length %x, StartingOffset %x, "
147 "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length,
148 StartingOffset,IoStatusBlock);
149
150 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
151 if (Irp==NULL)
152 {
153 return(NULL);
154 }
155
156 StackPtr = IoGetNextIrpStackLocation(Irp);
157 StackPtr->MajorFunction = MajorFunction;
158 StackPtr->MinorFunction = 0;
159 StackPtr->Flags = 0;
160 StackPtr->Control = 0;
161 StackPtr->DeviceObject = DeviceObject;
162 StackPtr->FileObject = NULL;
163 StackPtr->CompletionRoutine = NULL;
164 StackPtr->Parameters.Write.Length = Length;
165
166 if (MajorFunction == IRP_MJ_READ || MajorFunction == IRP_MJ_WRITE)
167 {
168 Irp->UserBuffer = (LPVOID)Buffer;
169 if (DeviceObject->Flags&DO_BUFFERED_IO)
170 {
171 DPRINT("Doing buffer i/o\n",0);
172 Irp->AssociatedIrp.SystemBuffer = (PVOID)
173 ExAllocatePool(NonPagedPool,Length);
174 if (Irp->AssociatedIrp.SystemBuffer==NULL)
175 {
176 return(NULL);
177 }
178 }
179 if (DeviceObject->Flags&DO_DIRECT_IO)
180 {
181 DPRINT("Doing direct i/o\n",0);
182
183 Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length);
184 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
185 Irp->UserBuffer = NULL;
186 Irp->AssociatedIrp.SystemBuffer = NULL;
187 }
188 if (StartingOffset!=NULL)
189 {
190 StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
191 }
192 else
193 {
194 StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
195 }
196 }
197
198 Irp->UserIosb = IoStatusBlock;
199
200 return(Irp);
201 }
202
203 PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode,
204 PDEVICE_OBJECT DeviceObject,
205 PVOID InputBuffer,
206 ULONG InputBufferLength,
207 PVOID OutputBuffer,
208 ULONG OutputBufferLength,
209 BOOLEAN InternalDeviceIoControl,
210 PKEVENT Event,
211 PIO_STATUS_BLOCK IoStatusBlock)
212 /*
213 * FUNCTION: Allocates and sets up an IRP to be sent to drivers
214 * ARGUMENTS:
215 * IoControlCode = Device io control code
216 * DeviceObject = Device object to send the irp to
217 * InputBuffer = Buffer from which data will be read by the driver
218 * InputBufferLength = Length in bytes of the input buffer
219 * OutputBuffer = Buffer into which data will be written by the driver
220 * OutputBufferLength = Length in bytes of the output buffer
221 * InternalDeviceIoControl = Determines weather
222 * IRP_MJ_INTERNAL_DEVICE_CONTROL or
223 * IRP_MJ_DEVICE_CONTROL will be used
224 * Event = Event used to notify the caller of completion
225 * IoStatusBlock (OUT) = Storage for the result of the operation
226 * RETURNS: The IRP allocated on success, or
227 * NULL on failure
228 */
229 {
230 PIRP Irp;
231 PIO_STACK_LOCATION StackPtr;
232 ULONG BufferLength;
233
234 DPRINT("IoBuildDeviceIoRequest(IoControlCode %x, DeviceObject %x, "
235 "InputBuffer %x, InputBufferLength %x, OutputBuffer %x, "
236 "OutputBufferLength %x, InternalDeviceIoControl %x "
237 "Event %x, IoStatusBlock %x\n",IoControlCode,DeviceObject,
238 InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength,
239 InternalDeviceIoControl,Event,IoStatusBlock);
240
241 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
242 if (Irp==NULL)
243 {
244 return(NULL);
245 }
246
247 Irp->UserEvent = Event;
248 Irp->UserIosb = IoStatusBlock;
249
250 StackPtr = IoGetNextIrpStackLocation(Irp);
251 StackPtr->MajorFunction = InternalDeviceIoControl ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
252 StackPtr->MinorFunction = 0;
253 StackPtr->Flags = 0;
254 StackPtr->Control = 0;
255 StackPtr->DeviceObject = DeviceObject;
256 StackPtr->FileObject = NULL;
257 StackPtr->CompletionRoutine = NULL;
258 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
259 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
260 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
261
262 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
263 {
264 case METHOD_BUFFERED:
265 DPRINT("Using METHOD_BUFFERED!\n");
266
267 BufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength;
268 if (BufferLength)
269 {
270 Irp->AssociatedIrp.SystemBuffer = (PVOID)
271 ExAllocatePool(NonPagedPool,BufferLength);
272
273 if (Irp->AssociatedIrp.SystemBuffer==NULL)
274 {
275 IoFreeIrp(Irp);
276 return(NULL);
277 }
278 }
279
280 if (InputBuffer && InputBufferLength)
281 {
282 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
283 InputBuffer,
284 InputBufferLength);
285 }
286 Irp->UserBuffer = OutputBuffer;
287 break;
288
289 case METHOD_IN_DIRECT:
290 DPRINT("Using METHOD_IN_DIRECT!\n");
291
292 /* build input buffer (control buffer) */
293 if (InputBuffer && InputBufferLength)
294 {
295 Irp->AssociatedIrp.SystemBuffer = (PVOID)
296 ExAllocatePool(NonPagedPool,InputBufferLength);
297
298 if (Irp->AssociatedIrp.SystemBuffer==NULL)
299 {
300 IoFreeIrp(Irp);
301 return(NULL);
302 }
303
304 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
305 InputBuffer,
306 InputBufferLength);
307 }
308
309 /* build output buffer (data transfer buffer) */
310 if (OutputBuffer && OutputBufferLength)
311 {
312 Irp->MdlAddress = IoAllocateMdl (OutputBuffer,OutputBufferLength,FALSE,FALSE,Irp);
313 MmProbeAndLockPages (Irp->MdlAddress,UserMode,IoReadAccess);
314 }
315 break;
316
317 case METHOD_OUT_DIRECT:
318 DPRINT("Using METHOD_OUT_DIRECT!\n");
319
320 /* build input buffer (control buffer) */
321 if (InputBuffer && InputBufferLength)
322 {
323 Irp->AssociatedIrp.SystemBuffer = (PVOID)
324 ExAllocatePool(NonPagedPool,InputBufferLength);
325
326 if (Irp->AssociatedIrp.SystemBuffer==NULL)
327 {
328 IoFreeIrp(Irp);
329 return(NULL);
330 }
331
332 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
333 InputBuffer,
334 InputBufferLength);
335 }
336
337 /* build output buffer (data transfer buffer) */
338 if (OutputBuffer && OutputBufferLength)
339 {
340 Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
341 OutputBufferLength,
342 FALSE,
343 FALSE,
344 Irp);
345 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
346 }
347 break;
348
349 case METHOD_NEITHER:
350 DPRINT("Using METHOD_NEITHER!\n");
351
352 Irp->UserBuffer = OutputBuffer;
353 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
354 break;
355 }
356
357 return(Irp);
358 }
359
360 PIRP IoBuildSynchronousFsdRequest(ULONG MajorFunction,
361 PDEVICE_OBJECT DeviceObject,
362 PVOID Buffer,
363 ULONG Length,
364 PLARGE_INTEGER StartingOffset,
365 PKEVENT Event,
366 PIO_STATUS_BLOCK IoStatusBlock)
367 /*
368 * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
369 * level driver(s)
370 * ARGUMENTS:
371 * MajorFunction = Major function code, one of IRP_MJ_READ,
372 * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
373 * DeviceObject = Target device object
374 * Buffer = Buffer containing data for a read or write
375 * Length = Length in bytes of the information to be transferred
376 * StartingOffset = Offset to begin the read/write from
377 * Event (OUT) = Will be set when the operation is complete
378 * IoStatusBlock (OUT) = Set to the status of the operation
379 * RETURNS: The IRP allocated on success, or
380 * NULL on failure
381 */
382 {
383 PIRP Irp;
384 PIO_STACK_LOCATION StackPtr;
385
386 DPRINT("IoBuildSynchronousFsdRequest(MajorFunction %x, DeviceObject %x, "
387 "Buffer %x, Length %x, StartingOffset %x, Event %x, "
388 "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length,
389 StartingOffset,Event,IoStatusBlock);
390
391 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
392 if (Irp==NULL)
393 {
394 return(NULL);
395 }
396
397 Irp->UserEvent = Event;
398 Irp->UserIosb = IoStatusBlock;
399
400 StackPtr = IoGetNextIrpStackLocation(Irp);
401 StackPtr->MajorFunction = MajorFunction;
402 StackPtr->MinorFunction = 0;
403 StackPtr->Flags = 0;
404 StackPtr->Control = 0;
405 StackPtr->DeviceObject = DeviceObject;
406 StackPtr->FileObject = NULL;
407 StackPtr->CompletionRoutine = NULL;
408
409 if (Buffer != NULL)
410 {
411 IoPrepareIrpBuffer(Irp,
412 DeviceObject,
413 Buffer,
414 Length,
415 MajorFunction);
416 }
417
418 if (MajorFunction == IRP_MJ_READ)
419 {
420 if (StartingOffset != NULL)
421 {
422 StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
423 }
424 else
425 {
426 StackPtr->Parameters.Read.ByteOffset.QuadPart = 0;
427 }
428 StackPtr->Parameters.Read.Length = Length;
429 }
430 else
431 {
432 if (StartingOffset!=NULL)
433 {
434 StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
435 }
436 else
437 {
438 StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
439 }
440 StackPtr->Parameters.Write.Length = Length;
441 }
442
443 return(Irp);
444 }
445