Link to home
Start Free TrialLog in
Avatar of danli020797
danli020797

asked on

IODeleteDevice and my unload routine?

I am writing my first wdm driver and one thing confuses me. I call IodeleteDevice when I get a critical error from within DriverEntry and somehow this IODeleteDevice makes a call to my unload routine. (I use Softice to debug and set a breakpoint in my unload routine.). And from an example of Art Baker's book , " the Windows NT Device Driver Book",
the IoDeleteDevice gets called from the unload routine, will this create a recursive call between IoDeleteDevice and XXUnload? I guess not. But I don't know the relationship between them. Is the call to the unload routine because there is no more device connecting to the driver? Can
you give me an idea? Or where can I find the answer?
In my driver I need to do some cleaning job in the unload routine and I need reference from deviceExtension, but after Iodeletedevice, everything is gone and I get the blue screen.
Thanks
Avatar of tflai
tflai

Does your DriverEntry() look something like this?

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
 
    PDEVICE_OBJECT deviceObject = NULL;
    NTSTATUS status;
    UNICODE_STRING uniNtNameString;
    UNICODE_STRING uniWin32NameString;
 
    KdPrint( ("LDUNLD: Entered the Load/Unload driver!\n") );
 
    //
    // Create counted string version of our device name.
    //
 
    RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
 
    //
    // Create the device object
    //
 
    status = IoCreateDevice(
                 DriverObject,
                 0,                     // We don't use a device extension
                 &uniNtNameString,
                 FILE_DEVICE_UNKNOWN,
                 0,                     // No standard device characteristics
                 FALSE,                 // This isn't an exclusive device
                 &deviceObject
                 );
 
    if ( NT_SUCCESS(status) )
    {
 
        //
        // Create dispatch points for create/open, close, unload.
        //
 
        DriverObject->MajorFunction[IRP_MJ_CREATE] = LdUnldOpen;
        DriverObject->MajorFunction[IRP_MJ_CLOSE] = LdUnldClose;
        DriverObject->DriverUnload = LdUnldUnload;
 
        KdPrint( ("LDUNLD: just about ready!\n") );
 
        //
        // Create counted string version of our Win32 device name.
        //
     
        RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
     
        //
        // Create a link from our device name to a name in the Win32 namespace.
        //
         
        status = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
 
        if (!NT_SUCCESS(status))
        {
            KdPrint( ("LDUNLD: Couldn't create the symbolic link\n") );
 
            IoDeleteDevice( DriverObject->DeviceObject );
        }
        else
        {
            KdPrint( ("LDUNLD: All initialized!\n") );
        }
    }
    else
    {
        KdPrint( ("LDUNLD: Couldn't create the device\n") );
    }
    return status;
}

ASKER CERTIFIED SOLUTION
Avatar of tflai
tflai

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of danli020797

ASKER

My DriverEntry is almost same as yours. IOCreateDevice and IOCreateUnprotectedSymbolicLink are run successfully. Afterwards, I allocate memory for my device and I call the IODeleteDevice while I can't allocate the memory for whatever reason. The pointer to these memory will be stored in deviceExtension so I need the deviceExtension in my unload routine.
Why don't you have a global context pointer instead of putting everything in the device object structure?  Something like a pMyDriverContext that pointing to a MY_DRIVER_CONTEXT created during DriverEntry().
I know I can use a global pointer.
But what I need is more of the general understanding of the wdm driver. Such as, why a IODeleteDevice(..) call will invoke My_Unload(..) from DriverEntry and not from My_Unload(..)?
On your previous question about why crashing:
A driver must release certain resources for which the driver supplied storage in its device extension before it calls IoDeleteDevice. For example, if the driver stores the pointer to its interrupt object(s) in the device extension, it must call IoDisconnectInterrupt before IoDeleteDevice.
When IoDeleteDevice is called, there cannot be any outstanding references to the device being deleted nor any attached devices. If there are, a system erorr occurs.
On you question about why:
What type of driver are you talking about?  If it's network, only NDIS will call your My_Unload(...).
danli,
After some more looking up, I believe I was wrong about IoDeleteDevice().  It does not call the unload function.  Maybe you should try something like marshalling IRP to it with major function UNLOAD.  Let me know about your progress.  Thanks.
I believe IoDeleteDevice() shouldn't call My_Unload(). But to verify that, I tested the sample program came with the WDMDDK beta3, under ..\src\wdm\sys\, I force the Drvshell_createobject() return an error(put ntStatus = STATUS_INSUFFICIENT_RESOURCES before return ntStatus). And I put a breakpoint in My_Unload(), I use SoftIce 3.2. After I executed the IoDeleteDevice(), the debugger jumped into My_Unload(). Strange, isn't it. Since I added more condition checking in My_Unload(), it wouldn't crash there. Maybe the SoftIce can not handle the debugging of new Window 98 WDM stuff yet. Also, returning an error from my driver's DriverEntry() shouldn't prevend the booting of the system, but it failed to boot whenever DriverEntry() returned an error. Do you think the value of the error has anything to do with this?
BTW, I heard that Fraser, Goldberg and Hanrahan had a book about NT driver, do you know if it's available?
Thanks
Hmm...  You should talk to people at NuMega see if SoftIce 3.2 can handle WDM drivers.  I think it should though...

About failing DriverEntry:
"A DriverEntry routine that will fail initialization must free any NT objects, system resources, and registry resources it has already set up before it returns control. It should reset the driver's Dispatch entry points in the driver object for IRP_MJ_FLUSH_BUFFERS and/or IRP_MJ_SHUTDOWN to NULL if the driver supports these requests. If it already called IoRegisterShutdownNotification, the DriverEntry routine must call IoUnregisterShutdownNotification before it fails initialization.
If a driver will fail initialization, the DriverEntry routine also should log an error or have IoReportResourceUsage log a hardware resource conflict error on a device driver's behalf before DriverEntry returns control."

The book, it haven't came out the last time I checked.  You can go to AMAZON.COM to check for the latest availability.