MSDN:
Tail.Overlay.Thread
Is a pointer to the caller's thread control block. Higher-level drivers that allocate IRPs for lower-level removable-media drivers must set this field in the IRPs they allocate. Otherwise, the FSD cannot determine which thread to notify if the underlying device driver indicates that the media requires verification.
还是MSDN:
Tail.Overlay.ListEntry
If a driver manages its own internal queues of IRPs, it uses this field to link one IRP to the next. These links can be used only while the driver is holding the IRP in its queue or is processing the IRP
不过后面那句限定条件, 究竟什么意思我不明白,可以翻翻WRK怎么用的
看看crash dump, 我手边没WRK,google了下ReactOS:
00300 VOID
00301 NTAPI
00302 KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode,
00303 IN PKEXCEPTION_FRAME ExceptionFrame,
00304 IN PKTRAP_FRAME TrapFrame)
00305 {
00306 PKTHREAD Thread = KeGetCurrentThread();
00307 PKPROCESS Process = Thread->ApcState.Process;
00308 PKTRAP_FRAME OldTrapFrame;
00309 PLIST_ENTRY ApcListEntry;
00310 PKAPC Apc;
00311 KLOCK_QUEUE_HANDLE ApcLock;
00312 PKKERNEL_ROUTINE KernelRoutine;
00313 PVOID NormalContext;
00314 PKNORMAL_ROUTINE NormalRoutine;
00315 PVOID SystemArgument1;
00316 PVOID SystemArgument2;
00317 ASSERT_IRQL_EQUAL(APC_LEVEL);
00318
00319 /* Save the old trap frame and set current one */
00320 OldTrapFrame = Thread->TrapFrame;
00321 Thread->TrapFrame = TrapFrame;
00322
00323 /* Clear Kernel APC Pending */
00324 Thread->ApcState.KernelApcPending = FALSE;
00325
00326 /* Check if Special APCs are disabled */
00327 if (Thread->SpecialApcDisable) goto Quickie;
00328
00329 /* Do the Kernel APCs first */
00330 while (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
00331 {
00332 /* Lock the APC Queue */
00333 KiAcquireApcLockAtApcLevel(Thread, &ApcLock);
00334
00335 /* Check if the list became empty now */
00336 if (IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
00337 {
00338 /* It is, release the lock and break out */
00339 KiReleaseApcLock(&ApcLock);
00340 break;
00341 }
00342
00343 /* Kernel APC is not pending anymore */
00344 Thread->ApcState.KernelApcPending = FALSE;
00345
00346 /* Get the next Entry */
00347 ApcListEntry = Thread->ApcState.ApcListHead[KernelMode].Flink;
00348 Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
00349
00350 /* Save Parameters so that it's safe to free the Object in the Kernel Routine*/
00351 NormalRoutine = Apc->NormalRoutine;
00352 KernelRoutine = Apc->KernelRoutine;
00353 NormalContext = Apc->NormalContext;
00354 SystemArgument1 = Apc->SystemArgument1;
00355 SystemArgument2 = Apc->SystemArgument2;
00356
00357 /* Special APC */
00358 if (!NormalRoutine)
00359 {
00360 /* Remove the APC from the list */
00361 RemoveEntryList(ApcListEntry);
00362 Apc->Inserted = FALSE;
00363
00364 /* Release the APC lock */
00365 KiReleaseApcLock(&ApcLock);
00366
00367 /* Call the Special APC */
00368 KernelRoutine(Apc,
00369 &NormalRoutine,
00370 &NormalContext,
00371 &SystemArgument1,
00372 &SystemArgument2);
00373
00374 /* Make sure it returned correctly */
00375 if (KeGetCurrentIrql() != ApcLock.OldIrql)
00376 {
00377 KeBugCheckEx(IRQL_UNEXPECTED_VALUE,
00378 (KeGetCurrentIrql() << 16) |
00379 (ApcLock.OldIrql << 8),
00380 (ULONG_PTR)KernelRoutine,
00381 (ULONG_PTR)Apc,
00382 (ULONG_PTR)NormalRoutine);
00383 }
00384 }
00385 else
00386 {
00387 /* Normal Kernel APC, make sure it's safe to deliver */
00388 if ((Thread->ApcState.KernelApcInProgress) ||
00389 (Thread->KernelApcDisable))
00390 {
00391 /* Release lock and return */
00392 KiReleaseApcLock(&ApcLock);
00393 goto Quickie;
00394 }
00395
00396 /* Dequeue the APC */
00397 RemoveEntryList(ApcListEntry);
00398 Apc->Inserted = FALSE;
00399
00400 /* Go back to APC_LEVEL */
00401 KiReleaseApcLock(&ApcLock);
00402
00403 /* Call the Kernel APC */
00404 KernelRoutine(Apc,
00405 &NormalRoutine,
00406 &NormalContext,
00407 &SystemArgument1,
00408 &SystemArgument2);
00409
00410 /* Make sure it returned correctly */
00411 if (KeGetCurrentIrql() != ApcLock.OldIrql)
00412 {
00413 KeBugCheckEx(IRQL_UNEXPECTED_VALUE,
00414 (KeGetCurrentIrql() << 16) |
00415 (ApcLock.OldIrql << 8),
00416 (ULONG_PTR)KernelRoutine,
00417 (ULONG_PTR)Apc,
00418 (ULONG_PTR)NormalRoutine);
00419 }
00420
00421 /* Check if there still is a Normal Routine */
00422 if (NormalRoutine)
00423 {
00424 /* At Passive Level, an APC can be prempted by a Special APC */
00425 Thread->ApcState.KernelApcInProgress = TRUE;
00426 KeLowerIrql(PASSIVE_LEVEL);
00427
00428 /* Call and Raise IRQL back to APC_LEVEL */
00429 NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
00430 KeRaiseIrql(APC_LEVEL, &ApcLock.OldIrql);
00431 }
00432
00433 /* Set Kernel APC in progress to false and loop again */
00434 Thread->ApcState.KernelApcInProgress = FALSE;
00435 }
00436 }
00437
00438 /* Now we do the User APCs */
00439 if ((DeliveryMode == UserMode) &&
00440 !(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
00441 (Thread->ApcState.UserApcPending))
00442 {
00443 /* Lock the APC Queue */
00444 KiAcquireApcLockAtApcLevel(Thread, &ApcLock);
00445
00446 /* It's not pending anymore */
00447 Thread->ApcState.UserApcPending = FALSE;
00448
00449 /* Check if the list became empty now */
00450 if (IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))
00451 {
00452 /* It is, release the lock and break out */
00453 KiReleaseApcLock(&ApcLock);
00454 goto Quickie;
00455 }
00456
00457 /* Get the actual APC object */
00458 ApcListEntry = Thread->ApcState.ApcListHead[UserMode].Flink;
00459 Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
00460
00461 /* Save Parameters so that it's safe to free the Object in the Kernel Routine*/
00462 NormalRoutine = Apc->NormalRoutine;
00463 KernelRoutine = Apc->KernelRoutine;
00464 NormalContext = Apc->NormalContext;
00465 SystemArgument1 = Apc->SystemArgument1;
00466 SystemArgument2 = Apc->SystemArgument2;
00467
00468 /* Remove the APC from Queue, and release the lock */
00469 RemoveEntryList(ApcListEntry);
00470 Apc->Inserted = FALSE;
00471 KiReleaseApcLock(&ApcLock);
00472
00473 /* Call the kernel routine */
00474 KernelRoutine(Apc,
00475 &NormalRoutine,
00476 &NormalContext,
00477 &SystemArgument1,
00478 &SystemArgument2);
00479
00480 /* Check if there's no normal routine */
00481 if (!NormalRoutine)
00482 {
00483 /* Check if more User APCs are Pending */
00484 KeTestAlertThread(UserMode);
00485 }
00486 else
00487 {
00488 /* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
00489 KiInitializeUserApc(ExceptionFrame,
00490 TrapFrame,
00491 NormalRoutine,
00492 NormalContext,
00493 SystemArgument1,
00494 SystemArgument2);
00495 }
00496 }
00497
00498 Quickie:
00499 /* Make sure we're still in the same process */
00500 if (Process != Thread->ApcState.Process)
00501 {
00502 /* Erm, we got attached or something! BAD! */
00503 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
00504 (ULONG_PTR)Process,
00505 (ULONG_PTR)Thread->ApcState.Process,
00506 Thread->ApcStateIndex,
00507 KeGetCurrentPrcb()->DpcRoutineActive);
00508 }
00509
00510 /* Restore the trap frame */
00511 Thread->TrapFrame = OldTrapFrame;
00512 }