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