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