help! BSOD with DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS

Dear all:
I’m writing a virtual device driver (belongs to NT legacy driver) which
runs in Windows XP SP2, it works well during it’s working lifecycle
(including loading driver, working, until to unload it), but after unloading
it, sometimes BSOD with code 0xCE, namely
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.
I’m wonder what operations happen after unloading driver, it seems that
driver runs a invalid address(CS:EIP points to 0xFFFF) after just now
leaving “Unload” routine scope, and BSOD doesn’t happen every time.
So, how do I cancel the pending operations? I have set counter in every
IRP, in fact, I deal with the routines associated IRP_MJ_CREATE,
IRP_MJ_CLOSE, IRP_MJ_DEVICE_CONTROL as below:

/* Pseudocode routine framwork*/

NTSTATUS XxxDispatchRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
// 1. Increasing IRP counts
pDevExtension->nIrpCount++; // pDevExtension points to device
extension

// 2. Dealing with IRP and finishing it.
… // some codes
IoCompleteRequest(Irp, IO_NO_INCREMENT); // finishing IRP

// 3. Decreasing IRP counts
pDevExtension->nIrpCount–;

return status; // e.g. return STATUS_SUCCESS;
}

In “Unload” routinue, I wait for IRP count decrease to zero, then continue.
I was puzzled how to solve it.

The following is the analysis of WinDbg, and the “Procon.sys” is my driver’s
name.

kd> !analyze -v
*******************************************************************************
*
*
* Bugcheck Analysis
*
*
*
*******************************************************************************

DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
A driver unloaded without cancelling timers, DPCs, worker threads, etc.
The broken driver’s name is displayed on the screen.
Arguments:
Arg1: f887479e, memory referenced
Arg2: 00000000, value 0 = read operation, 1 = write operation
Arg3: f887479e, If non-zero, the instruction address which referenced the
bad memory
address.
Arg4: 00000000, Mm internal code.

Debugging Details:

READ_ADDRESS: f887479e

FAULTING_IP:
Procon+579e
f887479e ?? ???

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0xCE

PROCESS_NAME: vmware-authd.ex

TRAP_FRAME: b90e1c74 – (.trap 0xffffffffb90e1c74)
ErrCode = 00000000
eax=00000000 ebx=f88727b4 ecx=00000000 edx=80010031 esi=00e8f72c
edi=b90e1d64
eip=f887479e esp=b90e1ce8 ebp=b90e1ce8 iopl=0 nv up ei pl zr na pe
nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00000246
<unloaded_procon.sys>+0x579e:
f887479e ?? ???
Resetting default scope

IP_MODULE_UNLOADED:
Procon+579e
f887479e ?? ???

LAST_CONTROL_TRANSFER: from 80524fa0 to 8053454e

FAILED_INSTRUCTION_ADDRESS:
Procon+579e
f887479e ?? ???

STACK_TEXT:
b90e1c10 80524fa0 00000050 f887479e 00000000 nt!KeBugCheckEx+0x1b
b90e1c5c 804e2718 00000000 f887479e 00000000 nt!MmAccessFault+0x6f5
b90e1c5c f887479e 00000000 f887479e 00000000 nt!KiTrap0E+0xcc
WARNING: Frame IP not in any known module. Following frames may be wrong.
b90e1ce4 b90e1d4c f8872ae8 81c4db18 f8872add <unloaded_procon.sys>+0x579e
b90e1d4c 804df7ec 00000005 01290048 00010000 0xb90e1d4c
b90e1d4c 0000003b 00000005 01290048 00010000 nt!KiFastCallEntry+0xf8
00000001 00000000 00000000 00000000 00000000 0x3b

STACK_COMMAND: kb

FOLLOWUP_IP:
Procon+579e
f887479e ?? ???

SYMBOL_STACK_INDEX: 3

FOLLOWUP_NAME: MachineOwner

SYMBOL_NAME: Procon+579e

MODULE_NAME: Procon

IMAGE_NAME: Procon.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 0

FAILURE_BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e

BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e

Followup: MachineOwner
---------

Thanks for your help!
Best regards,
Gray</unloaded_procon.sys></unloaded_procon.sys>

Do you by chance have any DPCs, Timers, or Work Items in your driver design?
Have these been properly drained before unloading the driver?

Does your driver ‘publish’ any other callbacks to other system entities that
it is failing to revoke?

To find what entry-point your driver is being called at, simply reload the
symbols for your driver at the ‘unloaded’ address. In Windbg this command
is

.reload /unl

Good Luck,
Dave Cattley
Consulting Engineer
Systems Software Development

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Gray
Sent: Saturday, March 29, 2008 4:24 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] help! BSOD with
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS

Dear all:
I’m writing a virtual device driver (belongs to NT legacy driver) which
runs in Windows XP SP2, it works well during it’s working lifecycle
(including loading driver, working, until to unload it), but after unloading

it, sometimes BSOD with code 0xCE, namely
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.
I’m wonder what operations happen after unloading driver, it seems that
driver runs a invalid address(CS:EIP points to 0xFFFF) after just now
leaving “Unload” routine scope, and BSOD doesn’t happen every time.
So, how do I cancel the pending operations? I have set counter in every
IRP, in fact, I deal with the routines associated IRP_MJ_CREATE,
IRP_MJ_CLOSE, IRP_MJ_DEVICE_CONTROL as below:

/* Pseudocode routine framwork*/

NTSTATUS XxxDispatchRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
// 1. Increasing IRP counts
pDevExtension->nIrpCount++; // pDevExtension points to device
extension

// 2. Dealing with IRP and finishing it.
… // some codes
IoCompleteRequest(Irp, IO_NO_INCREMENT); // finishing IRP

// 3. Decreasing IRP counts
pDevExtension->nIrpCount–;

return status; // e.g. return STATUS_SUCCESS;
}

In “Unload” routinue, I wait for IRP count decrease to zero, then continue.
I was puzzled how to solve it.

The following is the analysis of WinDbg, and the “Procon.sys” is my driver’s

name.

kd> !analyze -v
****************************************************************************
***
*
*
* Bugcheck Analysis
*
*
*
****************************************************************************
***

DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
A driver unloaded without cancelling timers, DPCs, worker threads, etc.
The broken driver’s name is displayed on the screen.
Arguments:
Arg1: f887479e, memory referenced
Arg2: 00000000, value 0 = read operation, 1 = write operation
Arg3: f887479e, If non-zero, the instruction address which referenced the
bad memory
address.
Arg4: 00000000, Mm internal code.

Debugging Details:

READ_ADDRESS: f887479e

FAULTING_IP:
Procon+579e
f887479e ?? ???

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0xCE

PROCESS_NAME: vmware-authd.ex

TRAP_FRAME: b90e1c74 – (.trap 0xffffffffb90e1c74)
ErrCode = 00000000
eax=00000000 ebx=f88727b4 ecx=00000000 edx=80010031 esi=00e8f72c
edi=b90e1d64
eip=f887479e esp=b90e1ce8 ebp=b90e1ce8 iopl=0 nv up ei pl zr na pe
nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00000246
<unloaded_procon.sys>+0x579e:
f887479e ?? ???
Resetting default scope

IP_MODULE_UNLOADED:
Procon+579e
f887479e ?? ???

LAST_CONTROL_TRANSFER: from 80524fa0 to 8053454e

FAILED_INSTRUCTION_ADDRESS:
Procon+579e
f887479e ?? ???

STACK_TEXT:
b90e1c10 80524fa0 00000050 f887479e 00000000 nt!KeBugCheckEx+0x1b
b90e1c5c 804e2718 00000000 f887479e 00000000 nt!MmAccessFault+0x6f5
b90e1c5c f887479e 00000000 f887479e 00000000 nt!KiTrap0E+0xcc
WARNING: Frame IP not in any known module. Following frames may be wrong.
b90e1ce4 b90e1d4c f8872ae8 81c4db18 f8872add <unloaded_procon.sys>+0x579e
b90e1d4c 804df7ec 00000005 01290048 00010000 0xb90e1d4c
b90e1d4c 0000003b 00000005 01290048 00010000 nt!KiFastCallEntry+0xf8
00000001 00000000 00000000 00000000 00000000 0x3b

STACK_COMMAND: kb

FOLLOWUP_IP:
Procon+579e
f887479e ?? ???

SYMBOL_STACK_INDEX: 3

FOLLOWUP_NAME: MachineOwner

SYMBOL_NAME: Procon+579e

MODULE_NAME: Procon

IMAGE_NAME: Procon.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 0

FAILURE_BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e

BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e

Followup: MachineOwner
---------

Thanks for your help!
Best regards,
Gray


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</unloaded_procon.sys></unloaded_procon.sys>

Thanks David Cattley very much at first!
I had tried to do some change to improve my driver program.

Phase 1: My driver’s datastruct about device extension includes
Doubly-linked list, spin lock(to synchronize list), event, hanle, and other
fundamental types of C language(such as LONG, BOOLEAN etc.).
I initialize list, event, spin lock at “DriverEntry” routine, but DDK
document and MSDN don’t tell me how to release them. So we don’t need
release them, right? To access doubly-linked list synchronously, I call
“KeAcquireSpinLock”, then deal with works, then call “KeReleaseSpinLock”
immediately. Even in “Unload” routine, I used spin lock too. I found it easy
to BSOD when I test it with loading driver and unloading driver frequently.

Phase 2: I don’t use spin lock to synchronize list, but DPCs.
When I need synchronize list, I raise the priority of IRQL to
DISPATCH_LEVEL, then assign DPCs to other CPU, then access doubly-linked
list, and then lower priority to origin value. After adjusting, BSOD happens
lower too.
So, it puzzles me. why spin lock is easier to BSOD ?
My DPCs has release before unloading driver, and I don’t use timers,
threads, only event.
I had released doubly-linked in “Unload” routine, DDK document don’t tell me
how to release event so I don’t release it.(maybe it don’t need release:))
At last, I delete symbolic link and device, then reach the tail scope of
“Unload” routine.

I don’t ‘publish’ any other callbacks to other system entities too.

When I debug my driver with SoftICE, all routines work well, even run to
tail line of “Unload” routine.
The error code of BSOD is
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS,
what I need to release now?

Thansk.

“David R. Cattley” ???:xxxxx@ntdev…
> Do you by chance have any DPCs, Timers, or Work Items in your driver
> design?
> Have these been properly drained before unloading the driver?
>
> Does your driver ‘publish’ any other callbacks to other system entities
> that
> it is failing to revoke?
>
> To find what entry-point your driver is being called at, simply reload the
> symbols for your driver at the ‘unloaded’ address. In Windbg this
> command
> is
>
> .reload /unl
>
> Good Luck,
> Dave Cattley
> Consulting Engineer
> Systems Software Development
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Gray
> Sent: Saturday, March 29, 2008 4:24 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] help! BSOD with
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
>
> Dear all:
> I’m writing a virtual device driver (belongs to NT legacy driver) which
> runs in Windows XP SP2, it works well during it’s working lifecycle
> (including loading driver, working, until to unload it), but after
> unloading
>
> it, sometimes BSOD with code 0xCE, namely
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.
> I’m wonder what operations happen after unloading driver, it seems that
> driver runs a invalid address(CS:EIP points to 0xFFFF) after just now
> leaving “Unload” routine scope, and BSOD doesn’t happen every time.
> So, how do I cancel the pending operations? I have set counter in every
> IRP, in fact, I deal with the routines associated IRP_MJ_CREATE,
> IRP_MJ_CLOSE, IRP_MJ_DEVICE_CONTROL as below:
>
> /* Pseudocode routine framwork*/
>
> NTSTATUS XxxDispatchRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
> {
> // 1. Increasing IRP counts
> pDevExtension->nIrpCount++; // pDevExtension points to device
> extension
>
> // 2. Dealing with IRP and finishing it.
> … // some codes
> IoCompleteRequest(Irp, IO_NO_INCREMENT); // finishing IRP
>
> // 3. Decreasing IRP counts
> pDevExtension->nIrpCount–;
>
> return status; // e.g. return STATUS_SUCCESS;
> }
>
> In “Unload” routinue, I wait for IRP count decrease to zero, then
> continue.
> I was puzzled how to solve it.
>
> The following is the analysis of WinDbg, and the “Procon.sys” is my
> driver’s
>
> name.
>
> kd> !analyze -v
> *************************************************************************
>

> *
> *
> * Bugcheck Analysis
> *
> *
> *
> *************************************************************************
>

>
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
> A driver unloaded without cancelling timers, DPCs, worker threads, etc.
> The broken driver’s name is displayed on the screen.
> Arguments:
> Arg1: f887479e, memory referenced
> Arg2: 00000000, value 0 = read operation, 1 = write operation
> Arg3: f887479e, If non-zero, the instruction address which referenced the
> bad memory
> address.
> Arg4: 00000000, Mm internal code.
>
> Debugging Details:
> ------------------
>
>
> READ_ADDRESS: f887479e
>
> FAULTING_IP:
> Procon+579e
> f887479e ?? ???
>
> DEFAULT_BUCKET_ID: DRIVER_FAULT
>
> BUGCHECK_STR: 0xCE
>
> PROCESS_NAME: vmware-authd.ex
>
> TRAP_FRAME: b90e1c74 – (.trap 0xffffffffb90e1c74)
> ErrCode = 00000000
> eax=00000000 ebx=f88727b4 ecx=00000000 edx=80010031 esi=00e8f72c
> edi=b90e1d64
> eip=f887479e esp=b90e1ce8 ebp=b90e1ce8 iopl=0 nv up ei pl zr na pe
> nc
> cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
> efl=00000246
> <unloaded_procon.sys>+0x579e:
> f887479e ?? ???
> Resetting default scope
>
> IP_MODULE_UNLOADED:
> Procon+579e
> f887479e ?? ???
>
> LAST_CONTROL_TRANSFER: from 80524fa0 to 8053454e
>
> FAILED_INSTRUCTION_ADDRESS:
> Procon+579e
> f887479e ?? ???
>
> STACK_TEXT:
> b90e1c10 80524fa0 00000050 f887479e 00000000 nt!KeBugCheckEx+0x1b
> b90e1c5c 804e2718 00000000 f887479e 00000000 nt!MmAccessFault+0x6f5
> b90e1c5c f887479e 00000000 f887479e 00000000 nt!KiTrap0E+0xcc
> WARNING: Frame IP not in any known module. Following frames may be wrong.
> b90e1ce4 b90e1d4c f8872ae8 81c4db18 f8872add <unloaded_procon.sys>+0x579e
> b90e1d4c 804df7ec 00000005 01290048 00010000 0xb90e1d4c
> b90e1d4c 0000003b 00000005 01290048 00010000 nt!KiFastCallEntry+0xf8
> 00000001 00000000 00000000 00000000 00000000 0x3b
>
>
> STACK_COMMAND: kb
>
> FOLLOWUP_IP:
> Procon+579e
> f887479e ?? ???
>
> SYMBOL_STACK_INDEX: 3
>
> FOLLOWUP_NAME: MachineOwner
>
> SYMBOL_NAME: Procon+579e
>
> MODULE_NAME: Procon
>
> IMAGE_NAME: Procon.sys
>
> DEBUG_FLR_IMAGE_TIMESTAMP: 0
>
> FAILURE_BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e
>
> BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e
>
> Followup: MachineOwner
> ---------
>
>
> Thanks for your help!
> Best regards,
> Gray
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
></unloaded_procon.sys></unloaded_procon.sys>

I suggest you learn how to use the debugging tools.

Even SoftIce (which you should abandon in favor of WinDbg) allows you to
load symbols at a specified address. I have not used it in years and don’t
remember how to do it, however.

As for the other information below (Phase 2), sorry. This is a bit of a
mess. Go study the samples in the DDK. Go read the DDK documentation on
usage of SpinLocks, DPCs, etc. Get a good book on NT Kernel Development.

Good Luck,
-dave

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Gray
Sent: Saturday, March 29, 2008 10:06 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] help! BSOD with
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS

Thanks David Cattley very much at first!
I had tried to do some change to improve my driver program.

Phase 1: My driver’s datastruct about device extension includes
Doubly-linked list, spin lock(to synchronize list), event, hanle, and other
fundamental types of C language(such as LONG, BOOLEAN etc.).
I initialize list, event, spin lock at “DriverEntry” routine, but DDK
document and MSDN don’t tell me how to release them. So we don’t need
release them, right? To access doubly-linked list synchronously, I call
“KeAcquireSpinLock”, then deal with works, then call “KeReleaseSpinLock”
immediately. Even in “Unload” routine, I used spin lock too. I found it easy

to BSOD when I test it with loading driver and unloading driver frequently.

Phase 2: I don’t use spin lock to synchronize list, but DPCs.
When I need synchronize list, I raise the priority of IRQL to
DISPATCH_LEVEL, then assign DPCs to other CPU, then access doubly-linked
list, and then lower priority to origin value. After adjusting, BSOD happens

lower too.
So, it puzzles me. why spin lock is easier to BSOD ?
My DPCs has release before unloading driver, and I don’t use timers,
threads, only event.
I had released doubly-linked in “Unload” routine, DDK document don’t tell me

how to release event so I don’t release it.(maybe it don’t need release:))
At last, I delete symbolic link and device, then reach the tail scope of
“Unload” routine.

I don’t ‘publish’ any other callbacks to other system entities too.

When I debug my driver with SoftICE, all routines work well, even run to
tail line of “Unload” routine.
The error code of BSOD is
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS,
what I need to release now?

Thansk.

“David R. Cattley” ???:xxxxx@ntdev…
> Do you by chance have any DPCs, Timers, or Work Items in your driver
> design?
> Have these been properly drained before unloading the driver?
>
> Does your driver ‘publish’ any other callbacks to other system entities
> that
> it is failing to revoke?
>
> To find what entry-point your driver is being called at, simply reload the
> symbols for your driver at the ‘unloaded’ address. In Windbg this
> command
> is
>
> .reload /unl
>
> Good Luck,
> Dave Cattley
> Consulting Engineer
> Systems Software Development
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Gray
> Sent: Saturday, March 29, 2008 4:24 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] help! BSOD with
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS
>
> Dear all:
> I’m writing a virtual device driver (belongs to NT legacy driver) which
> runs in Windows XP SP2, it works well during it’s working lifecycle
> (including loading driver, working, until to unload it), but after
> unloading
>
> it, sometimes BSOD with code 0xCE, namely
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.
> I’m wonder what operations happen after unloading driver, it seems that
> driver runs a invalid address(CS:EIP points to 0xFFFF) after just now
> leaving “Unload” routine scope, and BSOD doesn’t happen every time.
> So, how do I cancel the pending operations? I have set counter in every
> IRP, in fact, I deal with the routines associated IRP_MJ_CREATE,
> IRP_MJ_CLOSE, IRP_MJ_DEVICE_CONTROL as below:
>
> /* Pseudocode routine framwork*/
>
> NTSTATUS XxxDispatchRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
> {
> // 1. Increasing IRP counts
> pDevExtension->nIrpCount++; // pDevExtension points to device
> extension
>
> // 2. Dealing with IRP and finishing it.
> … // some codes
> IoCompleteRequest(Irp, IO_NO_INCREMENT); // finishing IRP
>
> // 3. Decreasing IRP counts
> pDevExtension->nIrpCount–;
>
> return status; // e.g. return STATUS_SUCCESS;
> }
>
> In “Unload” routinue, I wait for IRP count decrease to zero, then
> continue.
> I was puzzled how to solve it.
>
> The following is the analysis of WinDbg, and the “Procon.sys” is my
> driver’s
>
> name.
>
> kd> !analyze -v
>
*************************************************************************
>

> *
> *
> * Bugcheck Analysis
> *
> *
> *
>
*************************************************************************
>

>
> DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
> A driver unloaded without cancelling timers, DPCs, worker threads, etc.
> The broken driver’s name is displayed on the screen.
> Arguments:
> Arg1: f887479e, memory referenced
> Arg2: 00000000, value 0 = read operation, 1 = write operation
> Arg3: f887479e, If non-zero, the instruction address which referenced the
> bad memory
> address.
> Arg4: 00000000, Mm internal code.
>
> Debugging Details:
> ------------------
>
>
> READ_ADDRESS: f887479e
>
> FAULTING_IP:
> Procon+579e
> f887479e ?? ???
>
> DEFAULT_BUCKET_ID: DRIVER_FAULT
>
> BUGCHECK_STR: 0xCE
>
> PROCESS_NAME: vmware-authd.ex
>
> TRAP_FRAME: b90e1c74 – (.trap 0xffffffffb90e1c74)
> ErrCode = 00000000
> eax=00000000 ebx=f88727b4 ecx=00000000 edx=80010031 esi=00e8f72c
> edi=b90e1d64
> eip=f887479e esp=b90e1ce8 ebp=b90e1ce8 iopl=0 nv up ei pl zr na pe
> nc
> cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
> efl=00000246
> <unloaded_procon.sys>+0x579e:
> f887479e ?? ???
> Resetting default scope
>
> IP_MODULE_UNLOADED:
> Procon+579e
> f887479e ?? ???
>
> LAST_CONTROL_TRANSFER: from 80524fa0 to 8053454e
>
> FAILED_INSTRUCTION_ADDRESS:
> Procon+579e
> f887479e ?? ???
>
> STACK_TEXT:
> b90e1c10 80524fa0 00000050 f887479e 00000000 nt!KeBugCheckEx+0x1b
> b90e1c5c 804e2718 00000000 f887479e 00000000 nt!MmAccessFault+0x6f5
> b90e1c5c f887479e 00000000 f887479e 00000000 nt!KiTrap0E+0xcc
> WARNING: Frame IP not in any known module. Following frames may be wrong.
> b90e1ce4 b90e1d4c f8872ae8 81c4db18 f8872add <unloaded_procon.sys>+0x579e
> b90e1d4c 804df7ec 00000005 01290048 00010000 0xb90e1d4c
> b90e1d4c 0000003b 00000005 01290048 00010000 nt!KiFastCallEntry+0xf8
> 00000001 00000000 00000000 00000000 00000000 0x3b
>
>
> STACK_COMMAND: kb
>
> FOLLOWUP_IP:
> Procon+579e
> f887479e ?? ???
>
> SYMBOL_STACK_INDEX: 3
>
> FOLLOWUP_NAME: MachineOwner
>
> SYMBOL_NAME: Procon+579e
>
> MODULE_NAME: Procon
>
> IMAGE_NAME: Procon.sys
>
> DEBUG_FLR_IMAGE_TIMESTAMP: 0
>
> FAILURE_BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e
>
> BUCKET_ID: 0xCE_VRF_BAD_IP_Procon+579e
>
> Followup: MachineOwner
> ---------
>
>
> Thanks for your help!
> Best regards,
> Gray
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
>


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer</unloaded_procon.sys></unloaded_procon.sys>

> I initialize list, event, spin lock at “DriverEntry” routine, but DDK

document and MSDN don’t tell me how to release them. So we don’t need
release them, right?

Yes.

InitializeListHead, KeInitializeSpinLock and KeInitializeEvent require no undo,
they do not allocate anything and do not change the global state, they just
fill the structures.

Phase 2: I don’t use spin lock to synchronize list, but DPCs.

Why not use spinlocks?


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Dear Dave and Maxim Shatskih, thanks you very much!
Please allow me to explain them.

First, I announce I don’t debase WinDbg, in fact, I used it for period of
time, I had only one PC, so I used WinDbg to remote debug driver in virtual
PC.
Oh, it’s a nightmare! It’s so snail-slow that I can’t bear it. every time
restart windows, I must wait for even quarter.
But SoftICE change the phase. I can debug driver in single PC and fell it’s
sharp :slight_smile: so dear dave can try it if you want.
Without doubt, WinDbg developed by Microsoft should be powerful in Windows
platforms, but it is not a good choice for single PC.
Er, The advantage of WinDbg is powerful function, shortcoming is slower
feedback.
The SoftICE can respond very fast in single PC.
OVER.

Second, why don’t I use spin lock, and what it is means about phase 2.
My computer have only single CPU, Spin lock is only useful for SMP.
In order to let driver work well not only for a per-CPU context, but also
SMP. I use the method in this way, namely, phase 2, but I recount it so
simple that guys misconstrue it. :slight_smile:
To walk doubly-linked lists of processes in a safe manner, I must raise
current thread context to DISPATCH_LEVEL so that it isn’t be pre-empted,
threads can run on other CPUs (if PC has many CPUs) in the same PC, to
avoid pre-emption, we must raise all CPUs to DISPATCH_LEVEL too. The only
IRQLs higher than DISPATCH_LEVEL are DIRQLs(Device IRQLs), but these are for
processing device hardware interrupts. If we raise the IRQLs to
DISPATCH_LEVEL for all CPUs on the machine, we should be relatively safe.
So, I can use “KeGetCurrentIrql” to raise IRQL to DISPATCH_LEVEL, then we
elevate the IRQL of all other CPUs, a DPC call will do the trick.
A great benefit of DPCs is that they run at DISPATCH_LEVEL, and we can
specify which CPU they run on, so I create a DPC for each of the other CPU.

// Pseudocode
VOID RaiseIrqls()
{
// 1. init and allocate nonpagepool for DPCs

// 2. Raise other CPUs IRQL to DISPATCH_LEVEL by DPC
for (i = 0; i < NumberOfCPUs; i++)
{
if (i != CurrentCPU)
{
// init DPC, assign CPU for the DPC, queue
}
}

// 3. Wait for all other CPUs raise IRQL to DISPATCH_LEVEL
while (NumberOfRaiseCPU != NumberOfCPUs)
{
__asm nop
}

// 4. Now, All CPUs reach DISPATCH_LEVEL
}

You can know how to lower IRQLs by opposite way.
Thanks for dave’s suggestion sincerely, but I must read the fucking relative
books and documents again :slight_smile:

Best regards,
Gray

“Maxim S. Shatskih” ???:xxxxx@ntdev…
>> I initialize list, event, spin lock at “DriverEntry” routine, but DDK
>> document and MSDN don’t tell me how to release them. So we don’t need
>> release them, right?
>
> Yes.
>
> InitializeListHead, KeInitializeSpinLock and KeInitializeEvent require no
> undo,
> they do not allocate anything and do not change the global state, they
> just
> fill the structures.
>
>> Phase 2: I don’t use spin lock to synchronize list, but DPCs.
>
> Why not use spinlocks?
>
> –
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>

“David R. Cattley” ???:xxxxx@ntdev…
>I suggest you learn how to use the debugging tools.
>
> Even SoftIce (which you should abandon in favor of WinDbg) allows you to
> load symbols at a specified address. I have not used it in years and
> don’t
> remember how to do it, however.
>
> As for the other information below (Phase 2), sorry. This is a bit of a
> mess. Go study the samples in the DDK. Go read the DDK documentation on
> usage of SpinLocks, DPCs, etc. Get a good book on NT Kernel Development.
>
> Good Luck,
> -dave

  1. You can use WinDbg at one machine. VMware or VirtualPC allows it. I
    used SoftICE for long years and was happy with it but its development
    stopped and it doesn’t work anymore at XP SP2 with the latest hotfixes.

  2. Sorry, it looks crazy. First, if you machine has one or more CPUs is
    not important. You never know where your driver will run so you should
    always develope SMP safe code. Spinlocks are designed for this purpose
    and what you did seems as reinvented wheel which is worse in all aspect
    than the original one. In addition, there are interlocked operations for
    working with lists so you don’t even need spinlocks. I agree with your
    conclusion. Read The Fine Manuals :slight_smile:

  3. Follow Dave’s advice, load symbols for unloaded module and try to
    find what code was running when it crashes. It usually gives a very good
    advice what is wrong. If you don’t know how to do it with SI (I already
    forgot it), simply analyse crashdump using WinDbg.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Gray
Sent: Saturday, March 29, 2008 9:22 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] help! BSOD with
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS

Dear Dave and Maxim Shatskih, thanks you very much!
Please allow me to explain them.

First, I announce I don’t debase WinDbg, in fact, I used it
for period of
time, I had only one PC, so I used WinDbg to remote debug
driver in virtual
PC.
Oh, it’s a nightmare! It’s so snail-slow that I can’t bear
it. every time
restart windows, I must wait for even quarter.
But SoftICE change the phase. I can debug driver in single PC
and fell it’s
sharp :slight_smile: so dear dave can try it if you want.
Without doubt, WinDbg developed by Microsoft should be
powerful in Windows
platforms, but it is not a good choice for single PC.
Er, The advantage of WinDbg is powerful function,
shortcoming is slower
feedback.
The SoftICE can respond very fast in single PC.
OVER.

Second, why don’t I use spin lock, and what it is means about phase 2.
My computer have only single CPU, Spin lock is only useful for SMP.
In order to let driver work well not only for a per-CPU
context, but also
SMP. I use the method in this way, namely, phase 2, but I
recount it so
simple that guys misconstrue it. :slight_smile:
To walk doubly-linked lists of processes in a safe manner, I
must raise
current thread context to DISPATCH_LEVEL so that it isn’t be
pre-empted,
threads can run on other CPUs (if PC has many CPUs) in the
same PC, to
avoid pre-emption, we must raise all CPUs to DISPATCH_LEVEL
too. The only
IRQLs higher than DISPATCH_LEVEL are DIRQLs(Device IRQLs),
but these are for
processing device hardware interrupts. If we raise the IRQLs to
DISPATCH_LEVEL for all CPUs on the machine, we should be
relatively safe.
So, I can use “KeGetCurrentIrql” to raise IRQL to
DISPATCH_LEVEL, then we
elevate the IRQL of all other CPUs, a DPC call will do the trick.
A great benefit of DPCs is that they run at DISPATCH_LEVEL,
and we can
specify which CPU they run on, so I create a DPC for each of
the other CPU.

// Pseudocode
VOID RaiseIrqls()
{
// 1. init and allocate nonpagepool for DPCs

// 2. Raise other CPUs IRQL to DISPATCH_LEVEL by DPC
for (i = 0; i < NumberOfCPUs; i++)
{
if (i != CurrentCPU)
{
// init DPC, assign CPU for the DPC, queue
}
}

// 3. Wait for all other CPUs raise IRQL to DISPATCH_LEVEL
while (NumberOfRaiseCPU != NumberOfCPUs)
{
__asm nop
}

// 4. Now, All CPUs reach DISPATCH_LEVEL
}

You can know how to lower IRQLs by opposite way.
Thanks for dave’s suggestion sincerely, but I must read the
fucking relative
books and documents again :slight_smile:

Best regards,
Gray

“Maxim S. Shatskih” ???:xxxxx@ntdev…
> >> I initialize list, event, spin lock at “DriverEntry”
> routine, but DDK
> >> document and MSDN don’t tell me how to release them. So we
> don’t need
> >> release them, right?
> >
> > Yes.
> >
> > InitializeListHead, KeInitializeSpinLock and
> KeInitializeEvent require no
> > undo,
> > they do not allocate anything and do not change the global
> state, they
> > just
> > fill the structures.
> >
> >> Phase 2: I don’t use spin lock to synchronize list, but DPCs.
> >
> > Why not use spinlocks?
> >
> > –
> > Maxim Shatskih, Windows DDK MVP
> > StorageCraft Corporation
> > xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> >
>
>
> “David R. Cattley” ???:xxxxx@ntdev…
> >I suggest you learn how to use the debugging tools.
> >
> > Even SoftIce (which you should abandon in favor of WinDbg)
> allows you to
> > load symbols at a specified address. I have not used it
> in years and
> > don’t
> > remember how to do it, however.
> >
> > As for the other information below (Phase 2), sorry. This
> is a bit of a
> > mess. Go study the samples in the DDK. Go read the DDK
> documentation on
> > usage of SpinLocks, DPCs, etc. Get a good book on NT
> Kernel Development.
> >
> > Good Luck,
> > -dave
>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer
>

Wow, that is super. In order to avoid using a simple spinlock you have
implement a processor corral. Fascinating. What the heck are you working
on? Is it intended to be a real product?

On Sat, Mar 29, 2008 at 4:21 PM, Gray wrote:

> Dear Dave and Maxim Shatskih, thanks you very much!
> Please allow me to explain them.
>
> First, I announce I don’t debase WinDbg, in fact, I used it for period of
> time, I had only one PC, so I used WinDbg to remote debug driver in
> virtual
> PC.
> Oh, it’s a nightmare! It’s so snail-slow that I can’t bear it. every time
> restart windows, I must wait for even quarter.
> But SoftICE change the phase. I can debug driver in single PC and fell
> it’s
> sharp :slight_smile: so dear dave can try it if you want.
> Without doubt, WinDbg developed by Microsoft should be powerful in Windows
> platforms, but it is not a good choice for single PC.
> Er, The advantage of WinDbg is powerful function, shortcoming is slower
> feedback.
> The SoftICE can respond very fast in single PC.
> OVER.
>
> Second, why don’t I use spin lock, and what it is means about phase 2.
> My computer have only single CPU, Spin lock is only useful for SMP.
> In order to let driver work well not only for a per-CPU context, but also
> SMP. I use the method in this way, namely, phase 2, but I recount it so
> simple that guys misconstrue it. :slight_smile:
> To walk doubly-linked lists of processes in a safe manner, I must raise
> current thread context to DISPATCH_LEVEL so that it isn’t be pre-empted,
> threads can run on other CPUs (if PC has many CPUs) in the same PC, to
> avoid pre-emption, we must raise all CPUs to DISPATCH_LEVEL too. The only
> IRQLs higher than DISPATCH_LEVEL are DIRQLs(Device IRQLs), but these are
> for
> processing device hardware interrupts. If we raise the IRQLs to
> DISPATCH_LEVEL for all CPUs on the machine, we should be relatively safe.
> So, I can use “KeGetCurrentIrql” to raise IRQL to DISPATCH_LEVEL, then we
> elevate the IRQL of all other CPUs, a DPC call will do the trick.
> A great benefit of DPCs is that they run at DISPATCH_LEVEL, and we can
> specify which CPU they run on, so I create a DPC for each of the other
> CPU.
>
> // Pseudocode
> VOID RaiseIrqls()
> {
> // 1. init and allocate nonpagepool for DPCs
>
> // 2. Raise other CPUs IRQL to DISPATCH_LEVEL by DPC
> for (i = 0; i < NumberOfCPUs; i++)
> {
> if (i != CurrentCPU)
> {
> // init DPC, assign CPU for the DPC, queue
> }
> }
>
> // 3. Wait for all other CPUs raise IRQL to DISPATCH_LEVEL
> while (NumberOfRaiseCPU != NumberOfCPUs)
> {
> __asm nop
> }
>
> // 4. Now, All CPUs reach DISPATCH_LEVEL
> }
>
> You can know how to lower IRQLs by opposite way.
> Thanks for dave’s suggestion sincerely, but I must read the fucking
> relative
> books and documents again :slight_smile:
>
> Best regards,
> Gray
>
>
>
>
> “Maxim S. Shatskih” ???:xxxxx@ntdev…
> >> I initialize list, event, spin lock at “DriverEntry” routine, but DDK
> >> document and MSDN don’t tell me how to release them. So we don’t need
> >> release them, right?
> >
> > Yes.
> >
> > InitializeListHead, KeInitializeSpinLock and KeInitializeEvent require
> no
> > undo,
> > they do not allocate anything and do not change the global state, they
> > just
> > fill the structures.
> >
> >> Phase 2: I don’t use spin lock to synchronize list, but DPCs.
> >
> > Why not use spinlocks?
> >
> > –
> > Maxim Shatskih, Windows DDK MVP
> > StorageCraft Corporation
> > xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> >
>
>
> “David R. Cattley” ???:xxxxx@ntdev…
> >I suggest you learn how to use the debugging tools.
> >
> > Even SoftIce (which you should abandon in favor of WinDbg) allows you to
> > load symbols at a specified address. I have not used it in years and
> > don’t
> > remember how to do it, however.
> >
> > As for the other information below (Phase 2), sorry. This is a bit of a
> > mess. Go study the samples in the DDK. Go read the DDK documentation
> on
> > usage of SpinLocks, DPCs, etc. Get a good book on NT Kernel
> Development.
> >
> > Good Luck,
> > -dave
>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Mark Roddy

> Thanks for dave’s suggestion sincerely, but I must read

the fucking relative books and documents again :slight_smile:

Only time will tell. I re-read them regularly and have been doing so for
over 16 years. I learn something every time I do. Maybe it is because I
can’t remember anything anymore…

Based on what you have described as a solution, I think you might benefit
from another trip through the sections on Synchronization, IRQL, and SMP
best practices. It is called a “Deferred Procecedure Call” because the
execution needs to be “Deferred”. The dictionary defines Defer as “to put
off, or delay”. Well, that is exactly what they are intended for - to “put
off” or “delay” execution of procedure until a later time or some condition
is met. Sure they have all sorts of clever side-effects you can leverage
like using targeted DPCs to capture all of the CPUs in a system to ensure
they do not do anything but that is an aberration of the intended purpose.
A spinlock is the correct mechanism to synchronize (serialize) a resource
against access by multiple CPUs. An mutex (fast mutex, wait lock, event,
etc.) is the correct way to serialize a resource against access by multiple
threads. The distinction is in NT comes from the concept of IRQL. Yes,
DPCs execute at DISPATCH_LEVEL. There are PASSIVE_LEVEL Deferred Execution
objects too, they are called Work Items.

But you seem to have it all figured out. I’m sorry to have wasted your
time.

Good Luck,
-dave

“Maxim S. Shatskih” ???:xxxxx@ntdev…
>> I initialize list, event, spin lock at “DriverEntry” routine, but DDK
>> document and MSDN don’t tell me how to release them. So we don’t need
>> release them, right?
>
> Yes.
>
> InitializeListHead, KeInitializeSpinLock and KeInitializeEvent require no
> undo,
> they do not allocate anything and do not change the global state, they
> just
> fill the structures.
>
>> Phase 2: I don’t use spin lock to synchronize list, but DPCs.
>
> Why not use spinlocks?
>
> –
> Maxim Shatskih, Windows DDK MVP
> StorageCraft Corporation
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>

“David R. Cattley” ???:xxxxx@ntdev…
>I suggest you learn how to use the debugging tools.
>
> Even SoftIce (which you should abandon in favor of WinDbg) allows you to
> load symbols at a specified address. I have not used it in years and
> don’t
> remember how to do it, however.
>
> As for the other information below (Phase 2), sorry. This is a bit of a
> mess. Go study the samples in the DDK. Go read the DDK documentation on
> usage of SpinLocks, DPCs, etc. Get a good book on NT Kernel Development.
>
> Good Luck,
> -dave


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

This is an all around mess, and that you seem to feel that you have it
under control is kind of disturbing, although not uncommon, but, should
you perhaps be interested in some symbols, then here’s how I remember
doing it in SI:

  1. Start ‘Loader32.exe’
  2. Choose ‘Load’ from the ‘File’ menu; I think it’s file; it may have
    another name.
  3. Break in to SI
  4. Type TABLE , where MODULENAME is the name of the symbol
    module you just loaded.

    Good luck,

    mm

    Gray wrote:
    > Dear Dave and Maxim Shatskih, thanks you very much!
    > Please allow me to explain them.
    >
    > First, I announce I don’t debase WinDbg, in fact, I used it for period of
    > time, I had only one PC, so I used WinDbg to remote debug driver in virtual
    > PC.
    > Oh, it’s a nightmare! It’s so snail-slow that I can’t bear it. every time
    > restart windows, I must wait for even quarter.
    > But SoftICE change the phase. I can debug driver in single PC and fell it’s
    > sharp :slight_smile: so dear dave can try it if you want.
    > Without doubt, WinDbg developed by Microsoft should be powerful in Windows
    > platforms, but it is not a good choice for single PC.
    > Er, The advantage of WinDbg is powerful function, shortcoming is slower
    > feedback.
    > The SoftICE can respond very fast in single PC.
    > OVER.
    >
    > Second, why don’t I use spin lock, and what it is means about phase 2.
    > My computer have only single CPU, Spin lock is only useful for SMP.
    > In order to let driver work well not only for a per-CPU context, but also
    > SMP. I use the method in this way, namely, phase 2, but I recount it so
    > simple that guys misconstrue it. :slight_smile:
    > To walk doubly-linked lists of processes in a safe manner, I must raise
    > current thread context to DISPATCH_LEVEL so that it isn’t be pre-empted,
    > threads can run on other CPUs (if PC has many CPUs) in the same PC, to
    > avoid pre-emption, we must raise all CPUs to DISPATCH_LEVEL too. The only
    > IRQLs higher than DISPATCH_LEVEL are DIRQLs(Device IRQLs), but these are for
    > processing device hardware interrupts. If we raise the IRQLs to
    > DISPATCH_LEVEL for all CPUs on the machine, we should be relatively safe.
    > So, I can use “KeGetCurrentIrql” to raise IRQL to DISPATCH_LEVEL, then we
    > elevate the IRQL of all other CPUs, a DPC call will do the trick.
    > A great benefit of DPCs is that they run at DISPATCH_LEVEL, and we can
    > specify which CPU they run on, so I create a DPC for each of the other CPU.
    >
    > // Pseudocode
    > VOID RaiseIrqls()
    > {
    > // 1. init and allocate nonpagepool for DPCs
    >
    > // 2. Raise other CPUs IRQL to DISPATCH_LEVEL by DPC
    > for (i = 0; i < NumberOfCPUs; i++)
    > {
    > if (i != CurrentCPU)
    > {
    > // init DPC, assign CPU for the DPC, queue
    > }
    > }
    >
    > // 3. Wait for all other CPUs raise IRQL to DISPATCH_LEVEL
    > while (NumberOfRaiseCPU != NumberOfCPUs)
    > {
    > __asm nop
    > }
    >
    > // 4. Now, All CPUs reach DISPATCH_LEVEL
    > }
    >
    > You can know how to lower IRQLs by opposite way.
    > Thanks for dave’s suggestion sincerely, but I must read the fucking relative
    > books and documents again :slight_smile:
    >
    > Best regards,
    > Gray
    >
    >
    >
    >
    > “Maxim S. Shatskih” ???:xxxxx@ntdev…
    >>> I initialize list, event, spin lock at “DriverEntry” routine, but DDK
    >>> document and MSDN don’t tell me how to release them. So we don’t need
    >>> release them, right?
    >> Yes.
    >>
    >> InitializeListHead, KeInitializeSpinLock and KeInitializeEvent require no
    >> undo,
    >> they do not allocate anything and do not change the global state, they
    >> just
    >> fill the structures.
    >>
    >>> Phase 2: I don’t use spin lock to synchronize list, but DPCs.
    >> Why not use spinlocks?
    >>
    >> –
    >> Maxim Shatskih, Windows DDK MVP
    >> StorageCraft Corporation
    >> xxxxx@storagecraft.com
    >> http://www.storagecraft.com
    >>
    >>
    >
    >
    > “David R. Cattley” ???:xxxxx@ntdev…
    >> I suggest you learn how to use the debugging tools.
    >>
    >> Even SoftIce (which you should abandon in favor of WinDbg) allows you to
    >> load symbols at a specified address. I have not used it in years and
    >> don’t
    >> remember how to do it, however.
    >>
    >> As for the other information below (Phase 2), sorry. This is a bit of a
    >> mess. Go study the samples in the DDK. Go read the DDK documentation on
    >> usage of SpinLocks, DPCs, etc. Get a good book on NT Kernel Development.
    >>
    >> Good Luck,
    >> -dave
    >
    >
    >
    >

Dear all:
I have got the solution about this problem, it’s owned to everyone’s
help.
Yesterday, I did nothing but contemplated and reviewed the code, I found
the bug finally.
I want to thank dave, I benefit by your advice. You are a good mentor.
Thank Maxim Shatskih, MM, Michal Vodicka, thanks for your detailed
answer. Thanks Mark Roddy too :slight_smile:

I draw a conclusion. First, when encountering problem, observation and
illation are very important, the details maybe come from assistant tools,
such as WinDbg, SoftICE, etc. experienced expert will get most valuable
info, so mastering the tools is necessary.
Second, I’m NOT a expert, so I must review my codes and think over the
design, refactoring, exclude “good” code. At last, I can find latent bugs
and find a way.
Third, reading the documents and communion :slight_smile:

Thanks all.

Your sincerely,
Gray