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