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