Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenirp.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/iomgr/irp.c 00005 * PURPOSE: IRP Handling Functions 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Gunnar Dalsnes 00008 * Filip Navara (navaraf@reactos.org) 00009 */ 00010 00011 /* INCLUDES ****************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 PIRP IopDeadIrp; 00018 00019 /* PRIVATE FUNCTIONS ********************************************************/ 00020 00021 VOID 00022 NTAPI 00023 IopFreeIrpKernelApc(IN PKAPC Apc, 00024 IN PKNORMAL_ROUTINE *NormalRoutine, 00025 IN PVOID *NormalContext, 00026 IN PVOID *SystemArgument1, 00027 IN PVOID *SystemArgument2) 00028 { 00029 /* Free the IRP */ 00030 IoFreeIrp(CONTAINING_RECORD(Apc, IRP, Tail.Apc)); 00031 } 00032 00033 VOID 00034 NTAPI 00035 IopAbortIrpKernelApc(IN PKAPC Apc) 00036 { 00037 /* Free the IRP */ 00038 IoFreeIrp(CONTAINING_RECORD(Apc, IRP, Tail.Apc)); 00039 } 00040 00041 NTSTATUS 00042 NTAPI 00043 IopCleanupFailedIrp(IN PFILE_OBJECT FileObject, 00044 IN PKEVENT EventObject OPTIONAL, 00045 IN PVOID Buffer OPTIONAL) 00046 { 00047 PAGED_CODE(); 00048 00049 /* Dereference the event */ 00050 if (EventObject) ObDereferenceObject(EventObject); 00051 00052 /* Free a buffer, if any */ 00053 if (Buffer) ExFreePool(Buffer); 00054 00055 /* If this was a file opened for synch I/O, then unlock it */ 00056 if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject); 00057 00058 /* Now dereference it and return */ 00059 ObDereferenceObject(FileObject); 00060 return STATUS_INSUFFICIENT_RESOURCES; 00061 } 00062 00063 VOID 00064 NTAPI 00065 IopAbortInterruptedIrp(IN PKEVENT EventObject, 00066 IN PIRP Irp) 00067 { 00068 KIRQL OldIrql; 00069 BOOLEAN CancelResult; 00070 LARGE_INTEGER Wait; 00071 PAGED_CODE(); 00072 00073 /* Raise IRQL to APC */ 00074 KeRaiseIrql(APC_LEVEL, &OldIrql); 00075 00076 /* Check if nobody completed it yet */ 00077 if (!KeReadStateEvent(EventObject)) 00078 { 00079 /* First, cancel it */ 00080 CancelResult = IoCancelIrp(Irp); 00081 KeLowerIrql(OldIrql); 00082 00083 /* Check if we cancelled it */ 00084 if (CancelResult) 00085 { 00086 /* Wait for the IRP to be cancelled */ 00087 Wait.QuadPart = -100000; 00088 while (!KeReadStateEvent(EventObject)) 00089 { 00090 /* Delay indefintely */ 00091 KeDelayExecutionThread(KernelMode, FALSE, &Wait); 00092 } 00093 } 00094 else 00095 { 00096 /* No cancellation done, so wait for the I/O system to kill it */ 00097 KeWaitForSingleObject(EventObject, 00098 Executive, 00099 KernelMode, 00100 FALSE, 00101 NULL); 00102 } 00103 } 00104 else 00105 { 00106 /* We got preempted, so give up */ 00107 KeLowerIrql(OldIrql); 00108 } 00109 } 00110 00111 VOID 00112 NTAPI 00113 IopDisassociateThreadIrp(VOID) 00114 { 00115 KIRQL OldIrql, LockIrql; 00116 PETHREAD IrpThread; 00117 PLIST_ENTRY IrpEntry; 00118 PIO_ERROR_LOG_PACKET ErrorLogEntry; 00119 PDEVICE_OBJECT DeviceObject = NULL; 00120 PIO_STACK_LOCATION IoStackLocation; 00121 00122 /* First, raise to APC to protect IrpList */ 00123 KeRaiseIrql(APC_LEVEL, &OldIrql); 00124 00125 /* Get the Thread and check the list */ 00126 IrpThread = PsGetCurrentThread(); 00127 if (IsListEmpty(&IrpThread->IrpList)) 00128 { 00129 /* It got completed now, so quit */ 00130 KeLowerIrql(OldIrql); 00131 return; 00132 } 00133 00134 /* Ensure no one will come disturb */ 00135 LockIrql = KeAcquireQueuedSpinLock(LockQueueIoCompletionLock); 00136 00137 /* Get the misbehaving IRP */ 00138 IrpEntry = IrpThread->IrpList.Flink; 00139 IopDeadIrp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry); 00140 IOTRACE(IO_IRP_DEBUG, 00141 "%s - Deassociating IRP %p for %p\n", 00142 __FUNCTION__, 00143 IopDeadIrp, 00144 IrpThread); 00145 00146 /* Don't cancel the IRP if it's already been completed far */ 00147 if (IopDeadIrp->CurrentLocation == (IopDeadIrp->StackCount + 2)) 00148 { 00149 /* Return */ 00150 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock, LockIrql); 00151 KeLowerIrql(OldIrql); 00152 return; 00153 } 00154 00155 /* Disown the IRP! */ 00156 IopDeadIrp->Tail.Overlay.Thread = NULL; 00157 RemoveHeadList(&IrpThread->IrpList); 00158 InitializeListHead(&IopDeadIrp->ThreadListEntry); 00159 00160 /* Get the stack location and check if it's valid */ 00161 IoStackLocation = IoGetCurrentIrpStackLocation(IopDeadIrp); 00162 if (IopDeadIrp->CurrentLocation <= IopDeadIrp->StackCount) 00163 { 00164 /* Get the device object */ 00165 DeviceObject = IoStackLocation->DeviceObject; 00166 } 00167 00168 KeReleaseQueuedSpinLock(LockQueueIoCompletionLock, LockIrql); 00169 /* Lower IRQL now, since we have the pointers we need */ 00170 KeLowerIrql(OldIrql); 00171 00172 /* Check if we can send an Error Log Entry*/ 00173 if (DeviceObject) 00174 { 00175 /* Allocate an entry */ 00176 ErrorLogEntry = IoAllocateErrorLogEntry(DeviceObject, 00177 sizeof(IO_ERROR_LOG_PACKET)); 00178 if (ErrorLogEntry) 00179 { 00180 /* Write the entry */ 00181 ErrorLogEntry->ErrorCode = IO_DRIVER_CANCEL_TIMEOUT; 00182 IoWriteErrorLogEntry(ErrorLogEntry); 00183 } 00184 } 00185 } 00186 00187 VOID 00188 NTAPI 00189 IopCleanupIrp(IN PIRP Irp, 00190 IN PFILE_OBJECT FileObject) 00191 { 00192 PMDL Mdl; 00193 IOTRACE(IO_IRP_DEBUG, 00194 "%s - Cleaning IRP %p for %p\n", 00195 __FUNCTION__, 00196 Irp, 00197 FileObject); 00198 00199 /* Check if there's an MDL */ 00200 while ((Mdl = Irp->MdlAddress)) 00201 { 00202 /* Clear all of them */ 00203 Irp->MdlAddress = Mdl->Next; 00204 IoFreeMdl(Mdl); 00205 } 00206 00207 /* Check if the IRP has system buffer */ 00208 if (Irp->Flags & IRP_DEALLOCATE_BUFFER) 00209 { 00210 /* Free the buffer */ 00211 ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer, TAG_SYS_BUF); 00212 } 00213 00214 /* Check if this IRP has a user event, a file object, and is async */ 00215 if ((Irp->UserEvent) && 00216 !(Irp->Flags & IRP_SYNCHRONOUS_API) && 00217 (FileObject)) 00218 { 00219 /* Dereference the User Event */ 00220 ObDereferenceObject(Irp->UserEvent); 00221 } 00222 00223 /* Check if we have a file object and this isn't a create operation */ 00224 if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION)) 00225 { 00226 /* Dereference the file object */ 00227 ObDereferenceObject(FileObject); 00228 } 00229 00230 /* Free the IRP */ 00231 IoFreeIrp(Irp); 00232 } 00233 00234 VOID 00235 NTAPI 00236 IopCompleteRequest(IN PKAPC Apc, 00237 IN PKNORMAL_ROUTINE* NormalRoutine, 00238 IN PVOID* NormalContext, 00239 IN PVOID* SystemArgument1, 00240 IN PVOID* SystemArgument2) 00241 { 00242 PFILE_OBJECT FileObject; 00243 PIRP Irp; 00244 PMDL Mdl, NextMdl; 00245 PVOID Port = NULL, Key = NULL; 00246 BOOLEAN SignaledCreateRequest = FALSE; 00247 00248 /* Get data from the APC */ 00249 FileObject = (PFILE_OBJECT)*SystemArgument1; 00250 Irp = CONTAINING_RECORD(Apc, IRP, Tail.Apc); 00251 IOTRACE(IO_IRP_DEBUG, 00252 "%s - Completing IRP %p for %p\n", 00253 __FUNCTION__, 00254 Irp, 00255 FileObject); 00256 00257 /* Sanity check */ 00258 ASSERT(Irp->IoStatus.Status != (NTSTATUS)0xFFFFFFFF); 00259 00260 /* Check if we have a file object */ 00261 if (*SystemArgument2) 00262 { 00263 /* Check if we're reparsing */ 00264 if ((Irp->IoStatus.Status == STATUS_REPARSE) && 00265 (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)) 00266 { 00267 /* We should never get this yet */ 00268 DPRINT1("Reparse support not yet present!\n"); 00269 while (TRUE); 00270 } 00271 } 00272 00273 /* Handle Buffered case first */ 00274 if (Irp->Flags & IRP_BUFFERED_IO) 00275 { 00276 /* Check if we have an input buffer and if we succeeded */ 00277 if ((Irp->Flags & IRP_INPUT_OPERATION) && 00278 (Irp->IoStatus.Status != STATUS_VERIFY_REQUIRED) && 00279 !(NT_ERROR(Irp->IoStatus.Status))) 00280 { 00281 /* Copy the buffer back to the user */ 00282 RtlCopyMemory(Irp->UserBuffer, 00283 Irp->AssociatedIrp.SystemBuffer, 00284 Irp->IoStatus.Information); 00285 } 00286 00287 /* Also check if we should de-allocate it */ 00288 if (Irp->Flags & IRP_DEALLOCATE_BUFFER) 00289 { 00290 /* Deallocate it */ 00291 ExFreePool(Irp->AssociatedIrp.SystemBuffer); 00292 } 00293 } 00294 00295 /* Now we got rid of these two... */ 00296 Irp->Flags &= ~(IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); 00297 00298 /* Check if there's an MDL */ 00299 for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl) 00300 { 00301 /* Free it */ 00302 NextMdl = Mdl->Next; 00303 IoFreeMdl(Mdl); 00304 } 00305 00306 /* No MDLs left */ 00307 Irp->MdlAddress = NULL; 00308 00309 /* 00310 * Check if either the request was completed without any errors 00311 * (but warnings are OK!), or if it was completed with an error, but 00312 * did return from a pending I/O Operation and is not synchronous. 00313 */ 00314 if (!(NT_ERROR(Irp->IoStatus.Status)) || 00315 (NT_ERROR(Irp->IoStatus.Status) && 00316 (Irp->PendingReturned) && 00317 !(IsIrpSynchronous(Irp, FileObject)))) 00318 { 00319 /* Get any information we need from the FO before we kill it */ 00320 if ((FileObject) && (FileObject->CompletionContext)) 00321 { 00322 /* Save Completion Data */ 00323 Port = FileObject->CompletionContext->Port; 00324 Key = FileObject->CompletionContext->Key; 00325 } 00326 00327 /* Use SEH to make sure we don't write somewhere invalid */ 00328 _SEH2_TRY 00329 { 00330 /* Save the IOSB Information */ 00331 *Irp->UserIosb = Irp->IoStatus; 00332 } 00333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00334 { 00335 /* Ignore any error */ 00336 } 00337 _SEH2_END; 00338 00339 /* Check if we have an event or a file object */ 00340 if (Irp->UserEvent) 00341 { 00342 /* At the very least, this is a PKEVENT, so signal it always */ 00343 KeSetEvent(Irp->UserEvent, 0, FALSE); 00344 00345 /* Check if we also have a File Object */ 00346 if (FileObject) 00347 { 00348 /* Check if this is an Asynch API */ 00349 if (!(Irp->Flags & IRP_SYNCHRONOUS_API)) 00350 { 00351 /* Dereference the event */ 00352 ObDereferenceObject(Irp->UserEvent); 00353 } 00354 00355 /* 00356 * Now, if this is a Synch I/O File Object, then this event is 00357 * NOT an actual Executive Event, so we won't dereference it, 00358 * and instead, we will signal the File Object 00359 */ 00360 if ((FileObject->Flags & FO_SYNCHRONOUS_IO) && 00361 !(Irp->Flags & IRP_OB_QUERY_NAME)) 00362 { 00363 /* Signal the file object and set the status */ 00364 KeSetEvent(&FileObject->Event, 0, FALSE); 00365 FileObject->FinalStatus = Irp->IoStatus.Status; 00366 } 00367 00368 /* 00369 * This could also be a create operation, in which case we want 00370 * to make sure there's no APC fired. 00371 */ 00372 if (Irp->Flags & IRP_CREATE_OPERATION) 00373 { 00374 /* Clear the APC Routine and remember this */ 00375 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 00376 SignaledCreateRequest = TRUE; 00377 } 00378 } 00379 } 00380 else if (FileObject) 00381 { 00382 /* Signal the file object and set the status */ 00383 KeSetEvent(&FileObject->Event, 0, FALSE); 00384 FileObject->FinalStatus = Irp->IoStatus.Status; 00385 00386 /* 00387 * This could also be a create operation, in which case we want 00388 * to make sure there's no APC fired. 00389 */ 00390 if (Irp->Flags & IRP_CREATE_OPERATION) 00391 { 00392 /* Clear the APC Routine and remember this */ 00393 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 00394 SignaledCreateRequest = TRUE; 00395 } 00396 } 00397 00398 /* Update transfer count for everything but create operation */ 00399 if (!(Irp->Flags & IRP_CREATE_OPERATION)) 00400 { 00401 if (Irp->Flags & IRP_WRITE_OPERATION) 00402 { 00403 /* Update write transfer count */ 00404 IopUpdateTransferCount(IopWriteTransfer, 00405 (ULONG)Irp->IoStatus.Information); 00406 } 00407 else if (Irp->Flags & IRP_READ_OPERATION) 00408 { 00409 /* Update read transfer count */ 00410 IopUpdateTransferCount(IopReadTransfer, 00411 (ULONG)Irp->IoStatus.Information); 00412 } 00413 else 00414 { 00415 /* Update other transfer count */ 00416 IopUpdateTransferCount(IopOtherTransfer, 00417 (ULONG)Irp->IoStatus.Information); 00418 } 00419 } 00420 00421 /* Now that we've signaled the events, de-associate the IRP */ 00422 IopUnQueueIrpFromThread(Irp); 00423 00424 /* Now check if a User APC Routine was requested */ 00425 if (Irp->Overlay.AsynchronousParameters.UserApcRoutine) 00426 { 00427 /* Initialize it */ 00428 KeInitializeApc(&Irp->Tail.Apc, 00429 KeGetCurrentThread(), 00430 CurrentApcEnvironment, 00431 IopFreeIrpKernelApc, 00432 IopAbortIrpKernelApc, 00433 (PKNORMAL_ROUTINE)Irp-> 00434 Overlay.AsynchronousParameters.UserApcRoutine, 00435 Irp->RequestorMode, 00436 Irp-> 00437 Overlay.AsynchronousParameters.UserApcContext); 00438 00439 /* Queue it */ 00440 KeInsertQueueApc(&Irp->Tail.Apc, Irp->UserIosb, NULL, 2); 00441 } 00442 else if ((Port) && 00443 (Irp->Overlay.AsynchronousParameters.UserApcContext)) 00444 { 00445 /* We have an I/O Completion setup... create the special Overlay */ 00446 Irp->Tail.CompletionKey = Key; 00447 Irp->Tail.Overlay.PacketType = IopCompletionPacketIrp; 00448 KeInsertQueue(Port, &Irp->Tail.Overlay.ListEntry); 00449 } 00450 else 00451 { 00452 /* Free the IRP since we don't need it anymore */ 00453 IoFreeIrp(Irp); 00454 } 00455 00456 /* Check if we have a file object that wasn't part of a create */ 00457 if ((FileObject) && !(SignaledCreateRequest)) 00458 { 00459 /* Dereference it, since it's not needed anymore either */ 00460 ObDereferenceObjectDeferDelete(FileObject); 00461 } 00462 } 00463 else 00464 { 00465 /* 00466 * Either we didn't return from the request, or we did return but this 00467 * request was synchronous. 00468 */ 00469 if ((Irp->PendingReturned) && (FileObject)) 00470 { 00471 /* So we did return with a synch operation, was it the IRP? */ 00472 if (Irp->Flags & IRP_SYNCHRONOUS_API) 00473 { 00474 /* Yes, this IRP was synchronous, so return the I/O Status */ 00475 *Irp->UserIosb = Irp->IoStatus; 00476 00477 /* Now check if the user gave an event */ 00478 if (Irp->UserEvent) 00479 { 00480 /* Signal it */ 00481 KeSetEvent(Irp->UserEvent, 0, FALSE); 00482 } 00483 else 00484 { 00485 /* No event was given, so signal the FO instead */ 00486 KeSetEvent(&FileObject->Event, 0, FALSE); 00487 } 00488 } 00489 else 00490 { 00491 /* 00492 * It's not the IRP that was synchronous, it was the FO 00493 * that was opened this way. Signal its event. 00494 */ 00495 FileObject->FinalStatus = Irp->IoStatus.Status; 00496 KeSetEvent(&FileObject->Event, 0, FALSE); 00497 } 00498 } 00499 00500 /* Now that we got here, we do this for incomplete I/Os as well */ 00501 if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION)) 00502 { 00503 /* Dereference the File Object unless this was a create */ 00504 ObDereferenceObjectDeferDelete(FileObject); 00505 } 00506 00507 /* 00508 * Check if this was an Executive Event (remember that we know this 00509 * by checking if the IRP is synchronous) 00510 */ 00511 if ((Irp->UserEvent) && 00512 (FileObject) && 00513 !(Irp->Flags & IRP_SYNCHRONOUS_API)) 00514 { 00515 /* This isn't a PKEVENT, so dereference it */ 00516 ObDereferenceObject(Irp->UserEvent); 00517 } 00518 00519 /* Now that we've signaled the events, de-associate the IRP */ 00520 IopUnQueueIrpFromThread(Irp); 00521 00522 /* Free the IRP as well */ 00523 IoFreeIrp(Irp); 00524 } 00525 } 00526 00527 /* FUNCTIONS *****************************************************************/ 00528 00529 /* 00530 * @implemented 00531 */ 00532 PIRP 00533 NTAPI 00534 IoAllocateIrp(IN CCHAR StackSize, 00535 IN BOOLEAN ChargeQuota) 00536 { 00537 PIRP Irp = NULL; 00538 USHORT Size = IoSizeOfIrp(StackSize); 00539 PKPRCB Prcb; 00540 UCHAR Flags = 0; 00541 PNPAGED_LOOKASIDE_LIST List = NULL; 00542 PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; 00543 00544 /* Set Charge Quota Flag */ 00545 if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED; 00546 00547 /* FIXME: Implement Lookaside Floats */ 00548 00549 /* Figure out which Lookaside List to use */ 00550 if ((StackSize <= 8) && (ChargeQuota == FALSE)) 00551 { 00552 /* Set Fixed Size Flag */ 00553 Flags = IRP_ALLOCATED_FIXED_SIZE; 00554 00555 /* See if we should use big list */ 00556 if (StackSize != 1) 00557 { 00558 Size = IoSizeOfIrp(8); 00559 ListType = LookasideLargeIrpList; 00560 } 00561 00562 /* Get the PRCB */ 00563 Prcb = KeGetCurrentPrcb(); 00564 00565 /* Get the P List First */ 00566 List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P; 00567 00568 /* Attempt allocation */ 00569 List->L.TotalAllocates++; 00570 Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead); 00571 00572 /* Check if the P List failed */ 00573 if (!Irp) 00574 { 00575 /* Let the balancer know */ 00576 List->L.AllocateMisses++; 00577 00578 /* Try the L List */ 00579 List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L; 00580 List->L.TotalAllocates++; 00581 Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead); 00582 } 00583 } 00584 00585 /* Check if we have to use the pool */ 00586 if (!Irp) 00587 { 00588 /* Did we try lookaside and fail? */ 00589 if (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses++; 00590 00591 /* Check if we should charge quota */ 00592 if (ChargeQuota) 00593 { 00594 /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */ 00595 /* FIXME */ 00596 Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP); 00597 } 00598 else 00599 { 00600 /* Allocate the IRP With no Quota charge */ 00601 Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP); 00602 } 00603 00604 /* Make sure it was sucessful */ 00605 if (!Irp) return(NULL); 00606 } 00607 else 00608 { 00609 /* In this case there is no charge quota */ 00610 Flags &= ~IRP_QUOTA_CHARGED; 00611 } 00612 00613 /* Now Initialize it */ 00614 IoInitializeIrp(Irp, Size, StackSize); 00615 00616 /* Set the Allocation Flags */ 00617 Irp->AllocationFlags = Flags; 00618 00619 /* Return it */ 00620 IOTRACE(IO_IRP_DEBUG, 00621 "%s - Allocated IRP %p with allocation flags %lx\n", 00622 __FUNCTION__, 00623 Irp, 00624 Flags); 00625 return Irp; 00626 } 00627 00628 /* 00629 * @implemented 00630 */ 00631 PIRP 00632 NTAPI 00633 IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction, 00634 IN PDEVICE_OBJECT DeviceObject, 00635 IN PVOID Buffer, 00636 IN ULONG Length, 00637 IN PLARGE_INTEGER StartingOffset, 00638 IN PIO_STATUS_BLOCK IoStatusBlock) 00639 { 00640 PIRP Irp; 00641 PIO_STACK_LOCATION StackPtr; 00642 00643 /* Allocate IRP */ 00644 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00645 if (!Irp) return NULL; 00646 00647 /* Get the Stack */ 00648 StackPtr = IoGetNextIrpStackLocation(Irp); 00649 00650 /* Write the Major function and then deal with it */ 00651 StackPtr->MajorFunction = (UCHAR)MajorFunction; 00652 00653 /* Do not handle the following here */ 00654 if ((MajorFunction != IRP_MJ_FLUSH_BUFFERS) && 00655 (MajorFunction != IRP_MJ_SHUTDOWN) && 00656 (MajorFunction != IRP_MJ_PNP) && 00657 (MajorFunction != IRP_MJ_POWER)) 00658 { 00659 /* Check if this is Buffered IO */ 00660 if (DeviceObject->Flags & DO_BUFFERED_IO) 00661 { 00662 /* Allocate the System Buffer */ 00663 Irp->AssociatedIrp.SystemBuffer = 00664 ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYS_BUF); 00665 if (!Irp->AssociatedIrp.SystemBuffer) 00666 { 00667 /* Free the IRP and fail */ 00668 IoFreeIrp(Irp); 00669 return NULL; 00670 } 00671 00672 /* Set flags */ 00673 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 00674 00675 /* Handle special IRP_MJ_WRITE Case */ 00676 if (MajorFunction == IRP_MJ_WRITE) 00677 { 00678 /* Copy the buffer data */ 00679 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length); 00680 } 00681 else 00682 { 00683 /* Set the Input Operation flag and set this as a User Buffer */ 00684 Irp->Flags |= IRP_INPUT_OPERATION; 00685 Irp->UserBuffer = Buffer; 00686 } 00687 } 00688 else if (DeviceObject->Flags & DO_DIRECT_IO) 00689 { 00690 /* Use an MDL for Direct I/O */ 00691 Irp->MdlAddress = IoAllocateMdl(Buffer, 00692 Length, 00693 FALSE, 00694 FALSE, 00695 NULL); 00696 if (!Irp->MdlAddress) 00697 { 00698 /* Free the IRP and fail */ 00699 IoFreeIrp(Irp); 00700 return NULL; 00701 } 00702 00703 /* Probe and Lock */ 00704 _SEH2_TRY 00705 { 00706 /* Do the probe */ 00707 MmProbeAndLockPages(Irp->MdlAddress, 00708 KernelMode, 00709 MajorFunction == IRP_MJ_READ ? 00710 IoWriteAccess : IoReadAccess); 00711 } 00712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00713 { 00714 /* Free the IRP and its MDL */ 00715 IoFreeMdl(Irp->MdlAddress); 00716 IoFreeIrp(Irp); 00717 00718 /* Fail */ 00719 _SEH2_YIELD(return NULL); 00720 } 00721 _SEH2_END; 00722 } 00723 else 00724 { 00725 /* Neither, use the buffer */ 00726 Irp->UserBuffer = Buffer; 00727 } 00728 00729 /* Check if this is a read */ 00730 if (MajorFunction == IRP_MJ_READ) 00731 { 00732 /* Set the parameters for a read */ 00733 StackPtr->Parameters.Read.Length = Length; 00734 StackPtr->Parameters.Read.ByteOffset = *StartingOffset; 00735 } 00736 else if (MajorFunction == IRP_MJ_WRITE) 00737 { 00738 /* Otherwise, set write parameters */ 00739 StackPtr->Parameters.Write.Length = Length; 00740 StackPtr->Parameters.Write.ByteOffset = *StartingOffset; 00741 } 00742 } 00743 00744 /* Set the Current Thread and IOSB */ 00745 Irp->UserIosb = IoStatusBlock; 00746 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00747 00748 /* Return the IRP */ 00749 IOTRACE(IO_IRP_DEBUG, 00750 "%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n", 00751 __FUNCTION__, 00752 Irp, 00753 MajorFunction, 00754 Buffer, 00755 DeviceObject); 00756 return Irp; 00757 } 00758 00759 /* 00760 * @implemented 00761 */ 00762 PIRP 00763 NTAPI 00764 IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, 00765 IN PDEVICE_OBJECT DeviceObject, 00766 IN PVOID InputBuffer, 00767 IN ULONG InputBufferLength, 00768 IN PVOID OutputBuffer, 00769 IN ULONG OutputBufferLength, 00770 IN BOOLEAN InternalDeviceIoControl, 00771 IN PKEVENT Event, 00772 IN PIO_STATUS_BLOCK IoStatusBlock) 00773 { 00774 PIRP Irp; 00775 PIO_STACK_LOCATION StackPtr; 00776 ULONG BufferLength; 00777 00778 /* Allocate IRP */ 00779 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00780 if (!Irp) return NULL; 00781 00782 /* Get the Stack */ 00783 StackPtr = IoGetNextIrpStackLocation(Irp); 00784 00785 /* Set the DevCtl Type */ 00786 StackPtr->MajorFunction = InternalDeviceIoControl ? 00787 IRP_MJ_INTERNAL_DEVICE_CONTROL : 00788 IRP_MJ_DEVICE_CONTROL; 00789 00790 /* Set the IOCTL Data */ 00791 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode; 00792 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; 00793 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 00794 OutputBufferLength; 00795 00796 /* Handle the Methods */ 00797 switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) 00798 { 00799 /* Buffered I/O */ 00800 case METHOD_BUFFERED: 00801 00802 /* Select the right Buffer Length */ 00803 BufferLength = InputBufferLength > OutputBufferLength ? 00804 InputBufferLength : OutputBufferLength; 00805 00806 /* Make sure there is one */ 00807 if (BufferLength) 00808 { 00809 /* Allocate the System Buffer */ 00810 Irp->AssociatedIrp.SystemBuffer = 00811 ExAllocatePoolWithTag(NonPagedPool, 00812 BufferLength, 00813 TAG_SYS_BUF); 00814 if (!Irp->AssociatedIrp.SystemBuffer) 00815 { 00816 /* Free the IRP and fail */ 00817 IoFreeIrp(Irp); 00818 return NULL; 00819 } 00820 00821 /* Check if we got a buffer */ 00822 if (InputBuffer) 00823 { 00824 /* Copy into the System Buffer */ 00825 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 00826 InputBuffer, 00827 InputBufferLength); 00828 } 00829 00830 /* Write the flags */ 00831 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 00832 if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION; 00833 00834 /* Save the Buffer */ 00835 Irp->UserBuffer = OutputBuffer; 00836 } 00837 else 00838 { 00839 /* Clear the Flags and Buffer */ 00840 Irp->Flags = 0; 00841 Irp->UserBuffer = NULL; 00842 } 00843 break; 00844 00845 /* Direct I/O */ 00846 case METHOD_IN_DIRECT: 00847 case METHOD_OUT_DIRECT: 00848 00849 /* Check if we got an input buffer */ 00850 if (InputBuffer) 00851 { 00852 /* Allocate the System Buffer */ 00853 Irp->AssociatedIrp.SystemBuffer = 00854 ExAllocatePoolWithTag(NonPagedPool, 00855 InputBufferLength, 00856 TAG_SYS_BUF); 00857 if (!Irp->AssociatedIrp.SystemBuffer) 00858 { 00859 /* Free the IRP and fail */ 00860 IoFreeIrp(Irp); 00861 return NULL; 00862 } 00863 00864 /* Copy into the System Buffer */ 00865 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, 00866 InputBuffer, 00867 InputBufferLength); 00868 00869 /* Write the flags */ 00870 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; 00871 } 00872 else 00873 { 00874 /* Clear the flags */ 00875 Irp->Flags = 0; 00876 } 00877 00878 /* Check if we got an output buffer */ 00879 if (OutputBuffer) 00880 { 00881 /* Allocate the System Buffer */ 00882 Irp->MdlAddress = IoAllocateMdl(OutputBuffer, 00883 OutputBufferLength, 00884 FALSE, 00885 FALSE, 00886 Irp); 00887 if (!Irp->MdlAddress) 00888 { 00889 /* Free the IRP and fail */ 00890 IoFreeIrp(Irp); 00891 return NULL; 00892 } 00893 00894 /* Probe and Lock */ 00895 _SEH2_TRY 00896 { 00897 /* Do the probe */ 00898 MmProbeAndLockPages(Irp->MdlAddress, 00899 KernelMode, 00900 IO_METHOD_FROM_CTL_CODE(IoControlCode) == 00901 METHOD_IN_DIRECT ? 00902 IoReadAccess : IoWriteAccess); 00903 } 00904 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00905 { 00906 /* Free the MDL */ 00907 IoFreeMdl(Irp->MdlAddress); 00908 00909 /* Free the input buffer and IRP */ 00910 if (InputBuffer) ExFreePool(Irp->AssociatedIrp.SystemBuffer); 00911 IoFreeIrp(Irp); 00912 00913 /* Fail */ 00914 _SEH2_YIELD(return NULL); 00915 } 00916 _SEH2_END; 00917 } 00918 break; 00919 00920 case METHOD_NEITHER: 00921 00922 /* Just save the Buffer */ 00923 Irp->UserBuffer = OutputBuffer; 00924 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; 00925 } 00926 00927 /* Now write the Event and IoSB */ 00928 Irp->UserIosb = IoStatusBlock; 00929 Irp->UserEvent = Event; 00930 00931 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */ 00932 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00933 IoQueueThreadIrp(Irp); 00934 00935 /* Return the IRP */ 00936 IOTRACE(IO_IRP_DEBUG, 00937 "%s - Built IRP %p with IOCTL, Buffers, DO %lx %p %p %p\n", 00938 __FUNCTION__, 00939 Irp, 00940 IoControlCode, 00941 InputBuffer, 00942 OutputBuffer, 00943 DeviceObject); 00944 return Irp; 00945 } 00946 00947 /* 00948 * @implemented 00949 */ 00950 PIRP 00951 NTAPI 00952 IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, 00953 IN PDEVICE_OBJECT DeviceObject, 00954 IN PVOID Buffer, 00955 IN ULONG Length, 00956 IN PLARGE_INTEGER StartingOffset, 00957 IN PKEVENT Event, 00958 IN PIO_STATUS_BLOCK IoStatusBlock) 00959 { 00960 PIRP Irp; 00961 00962 /* Do the big work to set up the IRP */ 00963 Irp = IoBuildAsynchronousFsdRequest(MajorFunction, 00964 DeviceObject, 00965 Buffer, 00966 Length, 00967 StartingOffset, 00968 IoStatusBlock ); 00969 if (!Irp) return NULL; 00970 00971 /* Set the Event which makes it Syncronous */ 00972 Irp->UserEvent = Event; 00973 00974 /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */ 00975 IoQueueThreadIrp(Irp); 00976 return Irp; 00977 } 00978 00979 /* 00980 * @implemented 00981 */ 00982 BOOLEAN 00983 NTAPI 00984 IoCancelIrp(IN PIRP Irp) 00985 { 00986 KIRQL OldIrql; 00987 PDRIVER_CANCEL CancelRoutine; 00988 IOTRACE(IO_IRP_DEBUG, 00989 "%s - Canceling IRP %p\n", 00990 __FUNCTION__, 00991 Irp); 00992 ASSERT(Irp->Type == IO_TYPE_IRP); 00993 00994 /* Acquire the cancel lock and cancel the IRP */ 00995 IoAcquireCancelSpinLock(&OldIrql); 00996 Irp->Cancel = TRUE; 00997 00998 /* Clear the cancel routine and get the old one */ 00999 CancelRoutine = (PVOID)IoSetCancelRoutine(Irp, NULL); 01000 if (CancelRoutine) 01001 { 01002 /* We had a routine, make sure the IRP isn't completed */ 01003 if (Irp->CurrentLocation > (Irp->StackCount + 1)) 01004 { 01005 /* It is, bugcheck */ 01006 KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP, 01007 (ULONG_PTR)Irp, 01008 (ULONG_PTR)CancelRoutine, 01009 0, 01010 0); 01011 } 01012 01013 /* Set the cancel IRQL And call the routine */ 01014 Irp->CancelIrql = OldIrql; 01015 CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp); 01016 return TRUE; 01017 } 01018 01019 /* Otherwise, release the cancel lock and fail */ 01020 IoReleaseCancelSpinLock(OldIrql); 01021 return FALSE; 01022 } 01023 01024 /* 01025 * @implemented 01026 */ 01027 VOID 01028 NTAPI 01029 IoCancelThreadIo(IN PETHREAD Thread) 01030 { 01031 KIRQL OldIrql; 01032 ULONG Retries = 3000; 01033 LARGE_INTEGER Interval; 01034 PLIST_ENTRY ListHead, NextEntry; 01035 PIRP Irp; 01036 PAGED_CODE(); 01037 01038 /* Windows isn't using given thread, but using current. */ 01039 Thread = PsGetCurrentThread(); 01040 01041 IOTRACE(IO_IRP_DEBUG, 01042 "%s - Canceling IRPs for Thread %p\n", 01043 __FUNCTION__, 01044 Thread); 01045 01046 /* Raise to APC to protect the IrpList */ 01047 KeRaiseIrql(APC_LEVEL, &OldIrql); 01048 01049 /* Start by cancelling all the IRPs in the current thread queue. */ 01050 ListHead = &Thread->IrpList; 01051 NextEntry = ListHead->Flink; 01052 while (ListHead != NextEntry) 01053 { 01054 /* Get the IRP */ 01055 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 01056 01057 /* Cancel it */ 01058 IoCancelIrp(Irp); 01059 01060 /* Move to the next entry */ 01061 NextEntry = NextEntry->Flink; 01062 } 01063 01064 /* Wait 100 milliseconds */ 01065 Interval.QuadPart = -1000000; 01066 01067 /* Wait till all the IRPs are completed or cancelled. */ 01068 while (!IsListEmpty(&Thread->IrpList)) 01069 { 01070 /* Now we can lower */ 01071 KeLowerIrql(OldIrql); 01072 01073 /* Wait a short while and then look if all our IRPs were completed. */ 01074 KeDelayExecutionThread(KernelMode, FALSE, &Interval); 01075 01076 /* 01077 * Don't stay here forever if some broken driver doesn't complete 01078 * the IRP. 01079 */ 01080 if (!(Retries--)) 01081 { 01082 /* Print out a message and remove the IRP */ 01083 DPRINT1("Broken driver did not complete!\n"); 01084 IopDisassociateThreadIrp(); 01085 } 01086 01087 /* Raise the IRQL Again */ 01088 KeRaiseIrql(APC_LEVEL, &OldIrql); 01089 } 01090 01091 /* We're done, lower the IRQL */ 01092 KeLowerIrql(OldIrql); 01093 } 01094 01095 /* 01096 * @implemented 01097 */ 01098 #undef IoCallDriver 01099 NTSTATUS 01100 NTAPI 01101 IoCallDriver(IN PDEVICE_OBJECT DeviceObject, 01102 IN PIRP Irp) 01103 { 01104 /* Call fastcall */ 01105 return IofCallDriver(DeviceObject, Irp); 01106 } 01107 01108 #define IoCallDriver IofCallDriver 01109 01110 /* 01111 * @implemented 01112 */ 01113 #undef IoCompleteRequest 01114 VOID 01115 NTAPI 01116 IoCompleteRequest(IN PIRP Irp, 01117 IN CCHAR PriorityBoost) 01118 { 01119 /* Call the fastcall */ 01120 IofCompleteRequest(Irp, PriorityBoost); 01121 } 01122 01123 #define IoCompleteRequest IofCompleteRequest 01124 01125 /* 01126 * @implemented 01127 */ 01128 VOID 01129 NTAPI 01130 IoEnqueueIrp(IN PIRP Irp) 01131 { 01132 /* This is the same as calling IoQueueThreadIrp */ 01133 IoQueueThreadIrp(Irp); 01134 } 01135 01136 /* 01137 * @implemented 01138 */ 01139 NTSTATUS 01140 FASTCALL 01141 IofCallDriver(IN PDEVICE_OBJECT DeviceObject, 01142 IN PIRP Irp) 01143 { 01144 PDRIVER_OBJECT DriverObject; 01145 PIO_STACK_LOCATION StackPtr; 01146 01147 /* Make sure this is a valid IRP */ 01148 ASSERT(Irp->Type == IO_TYPE_IRP); 01149 01150 /* Get the Driver Object */ 01151 DriverObject = DeviceObject->DriverObject; 01152 01153 /* Decrease the current location and check if */ 01154 Irp->CurrentLocation--; 01155 if (Irp->CurrentLocation <= 0) 01156 { 01157 /* This IRP ran out of stack, bugcheck */ 01158 KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR)Irp, 0, 0, 0); 01159 } 01160 01161 /* Now update the stack location */ 01162 StackPtr = IoGetNextIrpStackLocation(Irp); 01163 Irp->Tail.Overlay.CurrentStackLocation = StackPtr; 01164 01165 /* Get the Device Object */ 01166 StackPtr->DeviceObject = DeviceObject; 01167 01168 /* Call it */ 01169 return DriverObject->MajorFunction[StackPtr->MajorFunction](DeviceObject, 01170 Irp); 01171 } 01172 01173 FORCEINLINE 01174 VOID 01175 IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation) 01176 { 01177 IoStackLocation->MinorFunction = 0; 01178 IoStackLocation->Flags = 0; 01179 IoStackLocation->Control &= SL_ERROR_RETURNED; 01180 IoStackLocation->Parameters.Others.Argument1 = 0; 01181 IoStackLocation->Parameters.Others.Argument2 = 0; 01182 IoStackLocation->Parameters.Others.Argument3 = 0; 01183 IoStackLocation->FileObject = NULL; 01184 } 01185 01186 /* 01187 * @implemented 01188 */ 01189 VOID 01190 FASTCALL 01191 IofCompleteRequest(IN PIRP Irp, 01192 IN CCHAR PriorityBoost) 01193 { 01194 PIO_STACK_LOCATION StackPtr, LastStackPtr; 01195 PDEVICE_OBJECT DeviceObject; 01196 PFILE_OBJECT FileObject; 01197 PETHREAD Thread; 01198 NTSTATUS Status; 01199 PMDL Mdl, NextMdl; 01200 ULONG MasterCount; 01201 PIRP MasterIrp; 01202 ULONG Flags; 01203 NTSTATUS ErrorCode = STATUS_SUCCESS; 01204 IOTRACE(IO_IRP_DEBUG, 01205 "%s - Completing IRP %p\n", 01206 __FUNCTION__, 01207 Irp); 01208 01209 /* Make sure this IRP isn't getting completed twice or is invalid */ 01210 if ((Irp->CurrentLocation) > (Irp->StackCount + 1)) 01211 { 01212 /* Bugcheck */ 01213 KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR)Irp, 0, 0, 0); 01214 } 01215 01216 /* Some sanity checks */ 01217 ASSERT(Irp->Type == IO_TYPE_IRP); 01218 ASSERT(!Irp->CancelRoutine); 01219 ASSERT(Irp->IoStatus.Status != STATUS_PENDING); 01220 ASSERT(Irp->IoStatus.Status != (NTSTATUS)0xFFFFFFFF); 01221 01222 /* Get the last stack */ 01223 LastStackPtr = (PIO_STACK_LOCATION)(Irp + 1); 01224 if (LastStackPtr->Control & SL_ERROR_RETURNED) 01225 { 01226 /* Get the error code */ 01227 ErrorCode = PtrToUlong(LastStackPtr->Parameters.Others.Argument4); 01228 } 01229 01230 /* 01231 * Start the loop with the current stack and point the IRP to the next stack 01232 * and then keep incrementing the stack as we loop through. The IRP should 01233 * always point to the next stack location w.r.t the one currently being 01234 * analyzed, so completion routine code will see the appropriate value. 01235 * Because of this, we must loop until the current stack location is +1 of 01236 * the stack count, because when StackPtr is at the end, CurrentLocation is +1. 01237 */ 01238 for (StackPtr = IoGetCurrentIrpStackLocation(Irp), 01239 Irp->CurrentLocation++, 01240 Irp->Tail.Overlay.CurrentStackLocation++; 01241 Irp->CurrentLocation <= (Irp->StackCount + 1); 01242 StackPtr++, 01243 Irp->CurrentLocation++, 01244 Irp->Tail.Overlay.CurrentStackLocation++) 01245 { 01246 /* Set Pending Returned */ 01247 Irp->PendingReturned = StackPtr->Control & SL_PENDING_RETURNED; 01248 01249 /* Check if we failed */ 01250 if (!NT_SUCCESS(Irp->IoStatus.Status)) 01251 { 01252 /* Check if it was changed by a completion routine */ 01253 if (Irp->IoStatus.Status != ErrorCode) 01254 { 01255 /* Update the error for the current stack */ 01256 ErrorCode = Irp->IoStatus.Status; 01257 StackPtr->Control |= SL_ERROR_RETURNED; 01258 LastStackPtr->Parameters.Others.Argument4 = UlongToPtr(ErrorCode); 01259 LastStackPtr->Control |= SL_ERROR_RETURNED; 01260 } 01261 } 01262 01263 /* Check if there is a Completion Routine to Call */ 01264 if ((NT_SUCCESS(Irp->IoStatus.Status) && 01265 (StackPtr->Control & SL_INVOKE_ON_SUCCESS)) || 01266 (!NT_SUCCESS(Irp->IoStatus.Status) && 01267 (StackPtr->Control & SL_INVOKE_ON_ERROR)) || 01268 (Irp->Cancel && 01269 (StackPtr->Control & SL_INVOKE_ON_CANCEL))) 01270 { 01271 /* Clear the stack location */ 01272 IopClearStackLocation(StackPtr); 01273 01274 /* Check for highest-level device completion routines */ 01275 if (Irp->CurrentLocation == (Irp->StackCount + 1)) 01276 { 01277 /* Clear the DO, since the current stack location is invalid */ 01278 DeviceObject = NULL; 01279 } 01280 else 01281 { 01282 /* Otherwise, return the real one */ 01283 DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; 01284 } 01285 01286 /* Call the completion routine */ 01287 Status = StackPtr->CompletionRoutine(DeviceObject, 01288 Irp, 01289 StackPtr->Context); 01290 01291 /* Don't touch the Packet in this case, since it might be gone! */ 01292 if (Status == STATUS_MORE_PROCESSING_REQUIRED) return; 01293 } 01294 else 01295 { 01296 /* Otherwise, check if this is a completed IRP */ 01297 if ((Irp->CurrentLocation <= Irp->StackCount) && 01298 (Irp->PendingReturned)) 01299 { 01300 /* Mark it as pending */ 01301 IoMarkIrpPending(Irp); 01302 } 01303 01304 /* Clear the stack location */ 01305 IopClearStackLocation(StackPtr); 01306 } 01307 } 01308 01309 /* Check if the IRP is an associated IRP */ 01310 if (Irp->Flags & IRP_ASSOCIATED_IRP) 01311 { 01312 /* Get the master IRP and count */ 01313 MasterIrp = Irp->AssociatedIrp.MasterIrp; 01314 MasterCount = InterlockedDecrement(&MasterIrp->AssociatedIrp.IrpCount); 01315 01316 /* Free the MDLs */ 01317 for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl) 01318 { 01319 /* Go to the next one */ 01320 NextMdl = Mdl->Next; 01321 IoFreeMdl(Mdl); 01322 } 01323 01324 /* Free the IRP itself */ 01325 IoFreeIrp(Irp); 01326 01327 /* Complete the Master IRP */ 01328 if (!MasterCount) IofCompleteRequest(MasterIrp, PriorityBoost); 01329 return; 01330 } 01331 01332 /* We don't support this yet */ 01333 ASSERT(Irp->IoStatus.Status != STATUS_REPARSE); 01334 01335 /* Check if we have an auxiliary buffer */ 01336 if (Irp->Tail.Overlay.AuxiliaryBuffer) 01337 { 01338 /* Free it */ 01339 ExFreePool(Irp->Tail.Overlay.AuxiliaryBuffer); 01340 Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 01341 } 01342 01343 /* Check if this is a Paging I/O or Close Operation */ 01344 if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) 01345 { 01346 /* Handle a Close Operation or Sync Paging I/O */ 01347 if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION)) 01348 { 01349 /* Set the I/O Status and Signal the Event */ 01350 Flags = Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO); 01351 *Irp->UserIosb = Irp->IoStatus; 01352 KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE); 01353 01354 /* Free the IRP for a Paging I/O Only, Close is handled by us */ 01355 if (Flags) IoFreeIrp(Irp); 01356 } 01357 else 01358 { 01359 #if 0 01360 /* Page 166 */ 01361 KeInitializeApc(&Irp->Tail.Apc 01362 &Irp->Tail.Overlay.Thread->Tcb, 01363 Irp->ApcEnvironment, 01364 IopCompletePageWrite, 01365 NULL, 01366 NULL, 01367 KernelMode, 01368 NULL); 01369 KeInsertQueueApc(&Irp->Tail.Apc, 01370 NULL, 01371 NULL, 01372 PriorityBoost); 01373 #else 01374 /* Not implemented yet. */ 01375 DPRINT1("Not supported!\n"); 01376 while (TRUE); 01377 #endif 01378 } 01379 01380 /* Get out of here */ 01381 return; 01382 } 01383 01384 /* Unlock MDL Pages, page 167. */ 01385 Mdl = Irp->MdlAddress; 01386 while (Mdl) 01387 { 01388 MmUnlockPages(Mdl); 01389 Mdl = Mdl->Next; 01390 } 01391 01392 /* Check if we should exit because of a Deferred I/O (page 168) */ 01393 if ((Irp->Flags & IRP_DEFER_IO_COMPLETION) && !(Irp->PendingReturned)) 01394 { 01395 /* 01396 * Return without queuing the completion APC, since the caller will 01397 * take care of doing its own optimized completion at PASSIVE_LEVEL. 01398 */ 01399 return; 01400 } 01401 01402 /* Get the thread and file object */ 01403 Thread = Irp->Tail.Overlay.Thread; 01404 FileObject = Irp->Tail.Overlay.OriginalFileObject; 01405 01406 /* Make sure the IRP isn't canceled */ 01407 if (!Irp->Cancel) 01408 { 01409 /* Initialize the APC */ 01410 KeInitializeApc(&Irp->Tail.Apc, 01411 &Thread->Tcb, 01412 Irp->ApcEnvironment, 01413 IopCompleteRequest, 01414 NULL, 01415 NULL, 01416 KernelMode, 01417 NULL); 01418 01419 /* Queue it */ 01420 KeInsertQueueApc(&Irp->Tail.Apc, 01421 FileObject, 01422 NULL, /* This is used for REPARSE stuff */ 01423 PriorityBoost); 01424 } 01425 else 01426 { 01427 /* The IRP just got canceled... does a thread still own it? */ 01428 if (Thread) 01429 { 01430 /* Yes! There is still hope! Initialize the APC */ 01431 KeInitializeApc(&Irp->Tail.Apc, 01432 &Thread->Tcb, 01433 Irp->ApcEnvironment, 01434 IopCompleteRequest, 01435 NULL, 01436 NULL, 01437 KernelMode, 01438 NULL); 01439 01440 /* Queue it */ 01441 KeInsertQueueApc(&Irp->Tail.Apc, 01442 FileObject, 01443 NULL, /* This is used for REPARSE stuff */ 01444 PriorityBoost); 01445 } 01446 else 01447 { 01448 /* Nothing left for us to do, kill it */ 01449 ASSERT(Irp->Cancel); 01450 IopCleanupIrp(Irp, FileObject); 01451 } 01452 } 01453 } 01454 01455 NTSTATUS 01456 NTAPI 01457 IopSynchronousCompletion(IN PDEVICE_OBJECT DeviceObject, 01458 IN PIRP Irp, 01459 IN PVOID Context) 01460 { 01461 if (Irp->PendingReturned) 01462 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 01463 return STATUS_MORE_PROCESSING_REQUIRED; 01464 } 01465 01466 /* 01467 * @implemented 01468 */ 01469 BOOLEAN 01470 NTAPI 01471 IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject, 01472 IN PIRP Irp) 01473 { 01474 KEVENT Event; 01475 NTSTATUS Status; 01476 01477 /* Check if next stack location is available */ 01478 if (Irp->CurrentLocation < Irp->StackCount) 01479 { 01480 /* No more stack location */ 01481 return FALSE; 01482 } 01483 01484 /* Initialize event */ 01485 KeInitializeEvent(&Event, NotificationEvent, FALSE); 01486 01487 /* Copy stack location for next driver */ 01488 IoCopyCurrentIrpStackLocationToNext(Irp); 01489 01490 /* Set a completion routine, which will signal the event */ 01491 IoSetCompletionRoutine(Irp, IopSynchronousCompletion, &Event, TRUE, TRUE, TRUE); 01492 01493 /* Call next driver */ 01494 Status = IoCallDriver(DeviceObject, Irp); 01495 01496 /* Check if irp is pending */ 01497 if (Status == STATUS_PENDING) 01498 { 01499 /* Yes, wait for its completion */ 01500 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 01501 } 01502 01503 /* Return success */ 01504 return TRUE; 01505 } 01506 01507 /* 01508 * @implemented 01509 */ 01510 VOID 01511 NTAPI 01512 IoFreeIrp(IN PIRP Irp) 01513 { 01514 PNPAGED_LOOKASIDE_LIST List; 01515 PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; 01516 PKPRCB Prcb; 01517 IOTRACE(IO_IRP_DEBUG, 01518 "%s - Freeing IRPs %p\n", 01519 __FUNCTION__, 01520 Irp); 01521 01522 /* Make sure the Thread IRP list is empty and that it OK to free it */ 01523 ASSERT(Irp->Type == IO_TYPE_IRP); 01524 ASSERT(IsListEmpty(&Irp->ThreadListEntry)); 01525 ASSERT(Irp->CurrentLocation >= Irp->StackCount); 01526 01527 /* If this was a pool alloc, free it with the pool */ 01528 if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE)) 01529 { 01530 /* Free it */ 01531 ExFreePoolWithTag(Irp, TAG_IRP); 01532 } 01533 else 01534 { 01535 /* Check if this was a Big IRP */ 01536 if (Irp->StackCount != 1) ListType = LookasideLargeIrpList; 01537 01538 /* Get the PRCB */ 01539 Prcb = KeGetCurrentPrcb(); 01540 01541 /* Use the P List */ 01542 List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P; 01543 List->L.TotalFrees++; 01544 01545 /* Check if the Free was within the Depth or not */ 01546 if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) 01547 { 01548 /* Let the balancer know */ 01549 List->L.FreeMisses++; 01550 01551 /* Use the L List */ 01552 List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L; 01553 List->L.TotalFrees++; 01554 01555 /* Check if the Free was within the Depth or not */ 01556 if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) 01557 { 01558 /* All lists failed, use the pool */ 01559 List->L.FreeMisses++; 01560 ExFreePoolWithTag(Irp, TAG_IRP); 01561 Irp = NULL; 01562 } 01563 } 01564 01565 /* The free was within the Depth */ 01566 if (Irp) 01567 { 01568 InterlockedPushEntrySList(&List->L.ListHead, 01569 (PSLIST_ENTRY)Irp); 01570 } 01571 } 01572 } 01573 01574 /* 01575 * @implemented 01576 */ 01577 IO_PAGING_PRIORITY 01578 FASTCALL 01579 IoGetPagingIoPriority(IN PIRP Irp) 01580 { 01581 IO_PAGING_PRIORITY Priority; 01582 ULONG Flags; 01583 01584 /* Get the flags */ 01585 Flags = Irp->Flags; 01586 01587 /* Check what priority it has */ 01588 if (Flags & IRP_CLASS_CACHE_OPERATION) 01589 { 01590 /* High priority */ 01591 Priority = IoPagingPriorityHigh; 01592 } 01593 else if (Flags & IRP_PAGING_IO) 01594 { 01595 /* Normal priority */ 01596 Priority = IoPagingPriorityNormal; 01597 } 01598 else 01599 { 01600 /* Invalid -- not a paging IRP */ 01601 Priority = IoPagingPriorityInvalid; 01602 } 01603 01604 /* Return the priority */ 01605 return Priority; 01606 } 01607 01608 /* 01609 * @implemented 01610 */ 01611 PEPROCESS 01612 NTAPI 01613 IoGetRequestorProcess(IN PIRP Irp) 01614 { 01615 /* Return the requestor process */ 01616 if (Irp->Tail.Overlay.Thread) 01617 { 01618 return Irp->Tail.Overlay.Thread->ThreadsProcess; 01619 } 01620 01621 return NULL; 01622 } 01623 01624 /* 01625 * @implemented 01626 */ 01627 ULONG 01628 NTAPI 01629 IoGetRequestorProcessId(IN PIRP Irp) 01630 { 01631 PEPROCESS Process; 01632 01633 /* Return the requestor process' id */ 01634 if ((Process = IoGetRequestorProcess(Irp))) 01635 { 01636 return PtrToUlong(Process->UniqueProcessId); 01637 } 01638 01639 return 0; 01640 } 01641 01642 /* 01643 * @implemented 01644 */ 01645 NTSTATUS 01646 NTAPI 01647 IoGetRequestorSessionId(IN PIRP Irp, 01648 OUT PULONG pSessionId) 01649 { 01650 PEPROCESS Process; 01651 01652 /* Return the session */ 01653 if ((Process = IoGetRequestorProcess(Irp))) 01654 { 01655 // FIXME: broken 01656 *pSessionId = PtrToUlong(Process->Session); 01657 return STATUS_SUCCESS; 01658 } 01659 01660 *pSessionId = (ULONG)-1; 01661 return STATUS_UNSUCCESSFUL; 01662 } 01663 01664 /* 01665 * @implemented 01666 */ 01667 PIRP 01668 NTAPI 01669 IoGetTopLevelIrp(VOID) 01670 { 01671 /* Return the IRP */ 01672 return (PIRP)PsGetCurrentThread()->TopLevelIrp; 01673 } 01674 01675 /* 01676 * @implemented 01677 */ 01678 VOID 01679 NTAPI 01680 IoInitializeIrp(IN PIRP Irp, 01681 IN USHORT PacketSize, 01682 IN CCHAR StackSize) 01683 { 01684 /* Clear it */ 01685 IOTRACE(IO_IRP_DEBUG, 01686 "%s - Initializing IRP %p\n", 01687 __FUNCTION__, 01688 Irp); 01689 RtlZeroMemory(Irp, PacketSize); 01690 01691 /* Set the Header and other data */ 01692 Irp->Type = IO_TYPE_IRP; 01693 Irp->Size = PacketSize; 01694 Irp->StackCount = StackSize; 01695 Irp->CurrentLocation = StackSize + 1; 01696 Irp->ApcEnvironment = KeGetCurrentThread()->ApcStateIndex; 01697 Irp->Tail.Overlay.CurrentStackLocation = (PIO_STACK_LOCATION)(Irp + 1) + StackSize; 01698 01699 /* Initialize the Thread List */ 01700 InitializeListHead(&Irp->ThreadListEntry); 01701 } 01702 01703 /* 01704 * @implemented 01705 */ 01706 BOOLEAN 01707 NTAPI 01708 IoIsOperationSynchronous(IN PIRP Irp) 01709 { 01710 BOOLEAN SynchIO; 01711 BOOLEAN ForceAsync; 01712 01713 /* If the IRP requests synchronous paging I/O, if the file object was opened 01714 for synchronous I/O, if the IRP_SYNCHRONOUS_API flag is set in the IRP 01715 the operation is synchronous */ 01716 SynchIO = (IoGetCurrentIrpStackLocation(Irp)->FileObject->Flags & FO_SYNCHRONOUS_IO) || 01717 (Irp->Flags & IRP_SYNCHRONOUS_API) || (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO); 01718 01719 /* If the IRP requests asynchronous paging I/O, the operation is asynchronous, 01720 even if one of the above conditions is true */ 01721 ForceAsync = (Irp->Flags & IRP_PAGING_IO) && !(Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO); 01722 01723 /* Check the flags */ 01724 if (SynchIO && !ForceAsync) 01725 { 01726 /* Synch API or Paging I/O is OK, as is Sync File I/O */ 01727 return TRUE; 01728 } 01729 01730 /* Otherwise, it is an asynchronous operation. */ 01731 return FALSE; 01732 } 01733 01734 /* 01735 * @unimplemented 01736 */ 01737 BOOLEAN 01738 NTAPI 01739 IoIsValidNameGraftingBuffer(IN PIRP Irp, 01740 IN PREPARSE_DATA_BUFFER ReparseBuffer) 01741 { 01742 UNIMPLEMENTED; 01743 return FALSE; 01744 } 01745 01746 /* 01747 * @implemented 01748 */ 01749 PIRP 01750 NTAPI 01751 IoMakeAssociatedIrp(IN PIRP Irp, 01752 IN CCHAR StackSize) 01753 { 01754 PIRP AssocIrp; 01755 IOTRACE(IO_IRP_DEBUG, 01756 "%s - Associating IRP %p\n", 01757 __FUNCTION__, 01758 Irp); 01759 01760 /* Allocate the IRP */ 01761 AssocIrp = IoAllocateIrp(StackSize, FALSE); 01762 if (!AssocIrp) return NULL; 01763 01764 /* Set the Flags */ 01765 AssocIrp->Flags |= IRP_ASSOCIATED_IRP; 01766 01767 /* Set the Thread */ 01768 AssocIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; 01769 01770 /* Associate them */ 01771 AssocIrp->AssociatedIrp.MasterIrp = Irp; 01772 return AssocIrp; 01773 } 01774 01775 /* 01776 * @implemented 01777 */ 01778 VOID 01779 NTAPI 01780 IoQueueThreadIrp(IN PIRP Irp) 01781 { 01782 IOTRACE(IO_IRP_DEBUG, 01783 "%s - Queueing IRP %p\n", 01784 __FUNCTION__, 01785 Irp); 01786 01787 /* Use our inlined routine */ 01788 IopQueueIrpToThread(Irp); 01789 } 01790 01791 /* 01792 * @implemented 01793 * Reference: Chris Cant's "Writing WDM Device Drivers" 01794 */ 01795 VOID 01796 NTAPI 01797 IoReuseIrp(IN OUT PIRP Irp, 01798 IN NTSTATUS Status) 01799 { 01800 UCHAR AllocationFlags; 01801 IOTRACE(IO_IRP_DEBUG, 01802 "%s - Reusing IRP %p\n", 01803 __FUNCTION__, 01804 Irp); 01805 01806 /* Make sure it's OK to reuse it */ 01807 ASSERT(!Irp->CancelRoutine); 01808 ASSERT(IsListEmpty(&Irp->ThreadListEntry)); 01809 01810 /* Get the old flags */ 01811 AllocationFlags = Irp->AllocationFlags; 01812 01813 /* Reinitialize the IRP */ 01814 IoInitializeIrp(Irp, Irp->Size, Irp->StackCount); 01815 01816 /* Duplicate the data */ 01817 Irp->IoStatus.Status = Status; 01818 Irp->AllocationFlags = AllocationFlags; 01819 } 01820 01821 /* 01822 * @implemented 01823 */ 01824 VOID 01825 NTAPI 01826 IoSetTopLevelIrp(IN PIRP Irp) 01827 { 01828 /* Set the IRP */ 01829 PsGetCurrentThread()->TopLevelIrp = (ULONG_PTR)Irp; 01830 } 01831 01832 #if defined (_WIN64) 01833 BOOLEAN 01834 NTAPI 01835 IoIs32bitProcess( 01836 IN PIRP Irp OPTIONAL) 01837 { 01838 UNIMPLEMENTED; 01839 return FALSE; 01840 } 01841 #endif Generated on Sat May 26 2012 04:26:33 for ReactOS by
1.7.6.1
|