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