+IoBuildAsynchronousFsdRequest()
[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 input buffer (control buffer) */
264         if (InputBuffer && InputBufferLength)
265           {
266              Irp->AssociatedIrp.SystemBuffer = (PVOID)
267                ExAllocatePoolWithTag(NonPagedPool,InputBufferLength, 
268                                      TAG_SYS_BUF);
269              
270              if (Irp->AssociatedIrp.SystemBuffer == NULL)
271                {
272                   IoFreeIrp(Irp);
273                   return(NULL);
274                }
275
276              RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
277                            InputBuffer,
278                            InputBufferLength);
279           }
280         
281          /* build output buffer (data transfer buffer) */
282         if (OutputBuffer && OutputBufferLength)
283           {
284              Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
285                                              OutputBufferLength,
286                                              FALSE,
287                                              FALSE,
288                                              Irp);
289              MmProbeAndLockPages (Irp->MdlAddress,UserMode,IoReadAccess);
290           }
291         break;
292         
293       case METHOD_OUT_DIRECT:
294         DPRINT("Using METHOD_OUT_DIRECT!\n");
295         
296         /* build input buffer (control buffer) */
297         if (InputBuffer && InputBufferLength)
298           {
299             Irp->AssociatedIrp.SystemBuffer = (PVOID)
300                ExAllocatePoolWithTag(NonPagedPool,InputBufferLength, 
301                                      TAG_SYS_BUF);
302              
303              if (Irp->AssociatedIrp.SystemBuffer==NULL)
304                {
305                   IoFreeIrp(Irp);
306                   return(NULL);
307                }
308              
309             RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
310                           InputBuffer,
311                           InputBufferLength);
312           }
313         
314         /* build output buffer (data transfer buffer) */
315          if (OutputBuffer && OutputBufferLength)
316           {
317              Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
318                                              OutputBufferLength,
319                                              FALSE,
320                                              FALSE,
321                                             Irp);
322              MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
323           }
324         break;
325         
326       case METHOD_NEITHER:
327         DPRINT("Using METHOD_NEITHER!\n");
328         
329         Irp->UserBuffer = OutputBuffer;
330         StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
331         break;
332      }
333
334    return(Irp);
335 }
336
337
338 PIRP STDCALL
339 IoBuildSynchronousFsdRequest(ULONG MajorFunction,
340                                   PDEVICE_OBJECT DeviceObject,
341                                   PVOID Buffer,
342                                   ULONG Length,
343                                   PLARGE_INTEGER StartingOffset,
344                                   PKEVENT Event,
345                                   PIO_STATUS_BLOCK IoStatusBlock)
346 /*
347  * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
348  * level driver(s)
349  * ARGUMENTS:
350  *        MajorFunction = Major function code, one of IRP_MJ_READ,
351  *                        IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
352  *        DeviceObject = Target device object
353  *        Buffer = Buffer containing data for a read or write
354  *        Length = Length in bytes of the information to be transferred
355  *        StartingOffset = Offset to begin the read/write from
356  *        Event (OUT) = Will be set when the operation is complete
357  *        IoStatusBlock (OUT) = Set to the status of the operation
358  * RETURNS: The IRP allocated on success, or
359  *          NULL on failure
360  */
361 {
362    PIRP Irp;
363    PIO_STACK_LOCATION StackPtr;
364    
365    DPRINT("IoBuildSynchronousFsdRequest(MajorFunction %x, DeviceObject %x, "
366           "Buffer %x, Length %x, StartingOffset %x, Event %x, "
367           "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length,
368           StartingOffset,Event,IoStatusBlock);
369    
370    Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
371    if (Irp==NULL)
372      {
373         return(NULL);
374      }
375    
376    Irp->UserEvent = Event;
377    Irp->UserIosb = IoStatusBlock;
378    DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
379    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
380
381    StackPtr = IoGetNextIrpStackLocation(Irp);
382    StackPtr->MajorFunction = MajorFunction;
383    StackPtr->MinorFunction = 0;
384    StackPtr->Flags = 0;
385    StackPtr->Control = 0;
386    StackPtr->DeviceObject = DeviceObject;
387    StackPtr->FileObject = NULL;
388    StackPtr->CompletionRoutine = NULL;
389    
390    if (Buffer != NULL)
391      {
392         IoPrepareIrpBuffer(Irp,
393                            DeviceObject,
394                            Buffer,
395                            Length,
396                            MajorFunction);
397      }
398    
399    if (MajorFunction == IRP_MJ_READ)
400      {
401        if (StartingOffset != NULL)
402          {
403             StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
404          }
405        else
406          {
407             StackPtr->Parameters.Read.ByteOffset.QuadPart = 0;
408          }
409         StackPtr->Parameters.Read.Length = Length;
410      }
411    else
412      {
413        if (StartingOffset!=NULL)
414          {
415             StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
416          }
417        else
418          {
419             StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
420          }
421         StackPtr->Parameters.Write.Length = Length;
422      }
423
424    return(Irp);
425 }
426
427
428 PIRP 
429 IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction,
430                                     PDEVICE_OBJECT DeviceObject,
431                                     PMDL Mdl,
432                                     PLARGE_INTEGER StartingOffset,
433                                     PKEVENT Event,
434                                     PIO_STATUS_BLOCK IoStatusBlock,
435                                     BOOLEAN PagingIo)
436 /*
437  * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
438  * level driver(s)
439  * ARGUMENTS:
440  *        MajorFunction = Major function code, one of IRP_MJ_READ,
441  *                        IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
442  *        DeviceObject = Target device object
443  *        Buffer = Buffer containing data for a read or write
444  *        Length = Length in bytes of the information to be transferred
445  *        StartingOffset = Offset to begin the read/write from
446  *        Event (OUT) = Will be set when the operation is complete
447  *        IoStatusBlock (OUT) = Set to the status of the operation
448  * RETURNS: The IRP allocated on success, or
449  *          NULL on failure
450  */
451 {
452    PIRP Irp;
453    PIO_STACK_LOCATION StackPtr;
454    
455    DPRINT("IoBuildSynchronousFsdRequestWithMdl(MajorFunction %x, "
456           "DeviceObject %x, "
457           "Mdl %x, StartingOffset %x, Event %x, "
458           "IoStatusBlock %x\n",MajorFunction,DeviceObject,Mdl,
459           StartingOffset,Event,IoStatusBlock);
460    
461    Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
462    if (Irp==NULL)
463      {
464         return(NULL);
465      }
466    
467    Irp->UserEvent = Event;
468    Irp->UserIosb = IoStatusBlock;
469    DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
470    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
471    if (PagingIo)
472      {
473        Irp->Flags = IRP_PAGING_IO;
474      }
475    else
476      {
477        Irp->Flags = 0;
478      }
479    
480    StackPtr = IoGetNextIrpStackLocation(Irp);
481    StackPtr->MajorFunction = MajorFunction;
482    StackPtr->MinorFunction = 0;
483    StackPtr->Flags = 0;
484    StackPtr->Control = 0;
485    StackPtr->DeviceObject = DeviceObject;
486    StackPtr->FileObject = NULL;
487    StackPtr->CompletionRoutine = NULL;
488    
489    Irp->MdlAddress = Mdl;
490    /* FIXME: 'Irp->UserBuffer=NULL' was here from reactos but we need some
491     * buffer at 'Irp->UserBuffer' for fastfat.sys - what to use else?
492     */
493    Irp->UserBuffer = MmGetSystemAddressForMdl(Mdl);
494    Irp->AssociatedIrp.SystemBuffer = NULL;
495       
496    if (MajorFunction == IRP_MJ_READ)
497      {
498        if (StartingOffset != NULL)
499          {
500             StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
501          }
502        else
503          {
504             StackPtr->Parameters.Read.ByteOffset.QuadPart = 0;
505          }
506         StackPtr->Parameters.Read.Length = MmGetMdlByteCount(Mdl);
507      }
508    else
509      {
510        if (StartingOffset!=NULL)
511          {
512             StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
513          }
514        else
515          {
516             StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
517          }
518         StackPtr->Parameters.Write.Length = MmGetMdlByteCount(Mdl);
519      }
520
521    return(Irp);
522 }
523
524 /* EOF */