- Fixed the freeing of memory from boot load drivers.
[reactos.git] / reactos / ntoskrnl / io / buildirp.c
1 /* $Id: buildirp.c,v 1.35 2003/10/12 17:05:44 hbirr Exp $
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.QuadPart = 0;
144 }
145 }
146 else if (MajorFunction == IRP_MJ_WRITE)
147 {
148 StackPtr->Parameters.Write.Length = Length;
149 if (StartingOffset!=NULL)
150 {
151 StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
152 }
153 else
154 {
155 StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
156 }
157 }
158
159 Irp->UserIosb = IoStatusBlock;
160
161 return(Irp);
162 }
163
164
165 /*
166 * @implemented
167 */
168 PIRP STDCALL
169 IoBuildDeviceIoControlRequest(ULONG IoControlCode,
170 PDEVICE_OBJECT DeviceObject,
171 PVOID InputBuffer,
172 ULONG InputBufferLength,
173 PVOID OutputBuffer,
174 ULONG OutputBufferLength,
175 BOOLEAN InternalDeviceIoControl,
176 PKEVENT Event,
177 PIO_STATUS_BLOCK IoStatusBlock)
178 /*
179 * FUNCTION: Allocates and sets up an IRP to be sent to drivers
180 * ARGUMENTS:
181 * IoControlCode = Device io control code
182 * DeviceObject = Device object to send the irp to
183 * InputBuffer = Buffer from which data will be read by the driver
184 * InputBufferLength = Length in bytes of the input buffer
185 * OutputBuffer = Buffer into which data will be written by the driver
186 * OutputBufferLength = Length in bytes of the output buffer
187 * InternalDeviceIoControl = Determines weather
188 * IRP_MJ_INTERNAL_DEVICE_CONTROL or
189 * IRP_MJ_DEVICE_CONTROL will be used
190 * Event = Event used to notify the caller of completion
191 * IoStatusBlock (OUT) = Storage for the result of the operation
192 * RETURNS: The IRP allocated on success, or
193 * NULL on failure
194 */
195 {
196 PIRP Irp;
197 PIO_STACK_LOCATION StackPtr;
198 ULONG BufferLength;
199
200 DPRINT("IoBuildDeviceIoRequest(IoControlCode %x, DeviceObject %x, "
201 "InputBuffer %x, InputBufferLength %x, OutputBuffer %x, "
202 "OutputBufferLength %x, InternalDeviceIoControl %x "
203 "Event %x, IoStatusBlock %x\n",IoControlCode,DeviceObject,
204 InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength,
205 InternalDeviceIoControl,Event,IoStatusBlock);
206
207 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
208 if (Irp==NULL)
209 {
210 return(NULL);
211 }
212
213 Irp->UserEvent = Event;
214 Irp->UserIosb = IoStatusBlock;
215 DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
216 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
217
218 StackPtr = IoGetNextIrpStackLocation(Irp);
219 StackPtr->MajorFunction = InternalDeviceIoControl ?
220 IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
221 StackPtr->MinorFunction = 0;
222 StackPtr->Flags = 0;
223 StackPtr->Control = 0;
224 StackPtr->DeviceObject = DeviceObject;
225 StackPtr->FileObject = NULL;
226 StackPtr->CompletionRoutine = NULL;
227 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
228 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
229 StackPtr->Parameters.DeviceIoControl.OutputBufferLength =
230 OutputBufferLength;
231
232 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
233 {
234 case METHOD_BUFFERED:
235 DPRINT("Using METHOD_BUFFERED!\n");
236
237 if (InputBufferLength > OutputBufferLength)
238 {
239 BufferLength = InputBufferLength;
240 }
241 else
242 {
243 BufferLength = OutputBufferLength;
244 }
245 if (BufferLength)
246 {
247 Irp->AssociatedIrp.SystemBuffer = (PVOID)
248 ExAllocatePoolWithTag(NonPagedPool,BufferLength, TAG_SYS_BUF);
249
250 if (Irp->AssociatedIrp.SystemBuffer == NULL)
251 {
252 IoFreeIrp(Irp);
253 return(NULL);
254 }
255 }
256
257 if (InputBuffer && InputBufferLength)
258 {
259 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
260 InputBuffer,
261 InputBufferLength);
262 }
263 Irp->UserBuffer = OutputBuffer;
264 break;
265
266 case METHOD_IN_DIRECT:
267 DPRINT("Using METHOD_IN_DIRECT!\n");
268
269 /* build output buffer (control buffer) */
270 if (OutputBuffer && OutputBufferLength)
271 {
272 Irp->AssociatedIrp.SystemBuffer = (PVOID)
273 ExAllocatePoolWithTag(NonPagedPool,OutputBufferLength,
274 TAG_SYS_BUF);
275
276
277 if (Irp->AssociatedIrp.SystemBuffer == NULL)
278 {
279 IoFreeIrp(Irp);
280 return(NULL);
281 }
282 Irp->UserBuffer = OutputBuffer;
283 }
284
285 /* build input buffer (data transfer buffer) */
286 if (InputBuffer && InputBufferLength)
287 {
288 Irp->MdlAddress = IoAllocateMdl(InputBuffer,
289 InputBufferLength,
290 FALSE,
291 FALSE,
292 Irp);
293 MmProbeAndLockPages (Irp->MdlAddress,UserMode,IoReadAccess);
294 }
295 break;
296
297 case METHOD_OUT_DIRECT:
298 DPRINT("Using METHOD_OUT_DIRECT!\n");
299
300 /* build input buffer (control buffer) */
301 if (InputBuffer && InputBufferLength)
302 {
303 Irp->AssociatedIrp.SystemBuffer = (PVOID)
304 ExAllocatePoolWithTag(NonPagedPool,InputBufferLength,
305 TAG_SYS_BUF);
306
307 if (Irp->AssociatedIrp.SystemBuffer==NULL)
308 {
309 IoFreeIrp(Irp);
310 return(NULL);
311 }
312
313 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
314 InputBuffer,
315 InputBufferLength);
316 }
317
318 /* build output buffer (data transfer buffer) */
319 if (OutputBuffer && OutputBufferLength)
320 {
321 Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
322 OutputBufferLength,
323 FALSE,
324 FALSE,
325 Irp);
326 MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess);
327 }
328 break;
329
330 case METHOD_NEITHER:
331 DPRINT("Using METHOD_NEITHER!\n");
332
333 Irp->UserBuffer = OutputBuffer;
334 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
335 break;
336 }
337
338 return(Irp);
339 }
340
341
342 /*
343 * @implemented
344 */
345 PIRP STDCALL
346 IoBuildSynchronousFsdRequest(ULONG MajorFunction,
347 PDEVICE_OBJECT DeviceObject,
348 PVOID Buffer,
349 ULONG Length,
350 PLARGE_INTEGER StartingOffset,
351 PKEVENT Event,
352 PIO_STATUS_BLOCK IoStatusBlock)
353 /*
354 * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
355 * level driver(s)
356 * ARGUMENTS:
357 * MajorFunction = Major function code, one of IRP_MJ_READ,
358 * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
359 * DeviceObject = Target device object
360 * Buffer = Buffer containing data for a read or write
361 * Length = Length in bytes of the information to be transferred
362 * StartingOffset = Offset to begin the read/write from
363 * Event (OUT) = Will be set when the operation is complete
364 * IoStatusBlock (OUT) = Set to the status of the operation
365 * RETURNS: The IRP allocated on success, or
366 * NULL on failure
367 */
368 {
369 PIRP Irp;
370
371 DPRINT("IoBuildSynchronousFsdRequest(MajorFunction %x, DeviceObject %x, "
372 "Buffer %x, Length %x, StartingOffset %x, Event %x, "
373 "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length,
374 StartingOffset,Event,IoStatusBlock);
375
376 Irp = IoBuildAsynchronousFsdRequest(MajorFunction,
377 DeviceObject,
378 Buffer,
379 Length,
380 StartingOffset,
381 IoStatusBlock );
382 if (Irp==NULL)
383 {
384 return(NULL);
385 }
386
387 Irp->UserEvent = Event;
388
389 return(Irp);
390 }
391
392
393 PIRP
394 IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction,
395 PDEVICE_OBJECT DeviceObject,
396 PMDL Mdl,
397 PLARGE_INTEGER StartingOffset,
398 PKEVENT Event,
399 PIO_STATUS_BLOCK IoStatusBlock,
400 BOOLEAN PagingIo)
401 /*
402 * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower
403 * level driver(s)
404 * ARGUMENTS:
405 * MajorFunction = Major function code, one of IRP_MJ_READ,
406 * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN
407 * DeviceObject = Target device object
408 * Buffer = Buffer containing data for a read or write
409 * Length = Length in bytes of the information to be transferred
410 * StartingOffset = Offset to begin the read/write from
411 * Event (OUT) = Will be set when the operation is complete
412 * IoStatusBlock (OUT) = Set to the status of the operation
413 * RETURNS: The IRP allocated on success, or
414 * NULL on failure
415 */
416 {
417 PIRP Irp;
418 PIO_STACK_LOCATION StackPtr;
419
420 DPRINT("IoBuildSynchronousFsdRequestWithMdl(MajorFunction %x, "
421 "DeviceObject %x, "
422 "Mdl %x, StartingOffset %x, Event %x, "
423 "IoStatusBlock %x\n",MajorFunction,DeviceObject,Mdl,
424 StartingOffset,Event,IoStatusBlock);
425
426 Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
427 if (Irp==NULL)
428 {
429 return(NULL);
430 }
431
432 Irp->UserEvent = Event;
433 Irp->UserIosb = IoStatusBlock;
434 DPRINT("Irp->UserIosb %x\n", Irp->UserIosb);
435 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
436 if (PagingIo)
437 {
438 Irp->Flags = IRP_PAGING_IO;
439 }
440 else
441 {
442 Irp->Flags = 0;
443 }
444
445 StackPtr = IoGetNextIrpStackLocation(Irp);
446 StackPtr->MajorFunction = MajorFunction;
447 StackPtr->MinorFunction = 0;
448 StackPtr->Flags = 0;
449 StackPtr->Control = 0;
450 StackPtr->DeviceObject = DeviceObject;
451 StackPtr->FileObject = NULL;
452 StackPtr->CompletionRoutine = NULL;
453
454 Irp->MdlAddress = Mdl;
455 Irp->UserBuffer = NULL;
456 Irp->AssociatedIrp.SystemBuffer = NULL;
457
458 if (MajorFunction == IRP_MJ_READ)
459 {
460 if (StartingOffset != NULL)
461 {
462 StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
463 }
464 else
465 {
466 StackPtr->Parameters.Read.ByteOffset.QuadPart = 0;
467 }
468 StackPtr->Parameters.Read.Length = MmGetMdlByteCount(Mdl);
469 }
470 else
471 {
472 if (StartingOffset!=NULL)
473 {
474 StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
475 }
476 else
477 {
478 StackPtr->Parameters.Write.ByteOffset.QuadPart = 0;
479 }
480 StackPtr->Parameters.Write.Length = MmGetMdlByteCount(Mdl);
481 }
482
483 return(Irp);
484 }
485
486 /* EOF */