none
One driver - multiple devices = Crash 0xCE? RRS feed

  • Question

  • My driver has to support a PC Card that may be connected to PCMCIA or a USB adapter, and I intended to do that with the same driver since it widely performs the same code in both cases. The main differences are found in the AddDevice where I look if PC card is connected to USB or PCMCIA, and the routine that access the PC card itself (most likely subsequent calls int the IRP_MJ_READ and IRP_MJ_WRITE IRPs).

    This seems to work so far if I only use PCMCIA or the USB adapter as long as i reboot before swapping. But when I'm trying to use both, the system crashes with error 0xCE (DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS). It is not necessary that both of are (phyiscally) attached at the same time - it also happens if I (phsically) attach PCMCIA and remove it again, and then (physically) attach the USB adapter. The crash mostly occours when I attach the device (sometimes it works until detach).

    I tried to debug using the Kernel Debugger, but at the moment I don't understand what is going wrong here. It seems that there is something in conflict with the other. Is it wrong not allowed to handel different (but similar) devices with the same driver?

    Differences in overview:

    • INF contains different AddService for USB and PCMCIA (one Section PCCDrvPCM and another PCCDrvUSB, the sections itselfs only in DisplayName and Dependencies)
    • For PCMCIA, INF contains a LogConfigOverride for the PCMCIA memory window
    • AddDevice looks at the PnP ID and remembers the "bus type" (USB, PCMCIA) which will be stord in the DriverObjectExtension. This is used later to differ the handling of HW related IRPs.
    • On HW access (reads/writes) they are directed to PCMCIA directly, for USB we have to send IRPs known by the lower driver

    I hope you can help me, thanks in before.

    Willi K.


    • Edited by Willi K Thursday, April 16, 2015 3:18 PM
    Thursday, April 16, 2015 3:16 PM

Answers

  • First it helps incredibly on a crash to have the !analyze -v for the dump.  A couple of things I would do to change your code.  First up the size of the NameBuf, you calculate it rather weirdly since you are creating it with the sizeof(DEV_NAME) which will give you byte size, but the declaration is the number of ushorts.  I would dump your current code approach and declare the NameBuf to be a reasonable size, say 20.  Then use RtlUnicodeStringPrintf to fill in the name.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Friday, April 24, 2015 1:32 PM

All replies

  • I would rethink your architecture, trying to handle this with one driver is going to be messy.  If you really have a lot of shared code between the two models, you might consider a model of a simple driver to handle the hardware, and a filter driver that contains the common code.  The filter driver would receive the requests and in the cases where they need to go to hardware forward the request to the device it attached to, which would be either USB or PCMCIA specific.

    Are you writing this driver with KMDF?  The problems that result in error DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS is pretty much taken care of automatically with KMDF but are quite common with WDM (which is why KMDF was created). 

    I would seriously consider breaking this into at least two drivers (one for USB and one for PCMCIA) or three with the filter as mentioned above if you really have a lot of shared code.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Thursday, April 16, 2015 3:30 PM
  • did you run !analyze -v and read the output? it will tell you what operation you left pending. make sure you have the right symbols.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, April 16, 2015 6:14 PM
  • Hello Don,

    maybe you are right. Please keep in mind that is the first time that I am working on a windows driver project. In addition to that, my base was existing code, that (unfortunately) was not well explained. With other words I am glad that I got most of the functionality working at all. Last but not least I am not familiar with filter drivers at the moment. Besides that I learned until yet I fear that things get more complicated then they are already are (to me), and maybe nothing works any more in the end. I hope you understand...

    Regarding the driver model I am not sure, but because of it's complexicity and amount of code I assume that it is WDM - are there some characteristics which I can use to determine the model exactly.

    Friday, April 17, 2015 4:47 PM
  • The "!anal<ze -v" showed something about locks. I assume that this is caused because the tags used for the RemoveLocks and MemoryAllocation where the same (for different services). The Unload of the driver was caused by a error in IoGetDeviceObjectPointer since I specified a non-existing device name.

    I try to use different tags now - I will tell you if it did the job. This brought me to another question: I can differ the source in the RegistryPath passed in DriverEntry by looking for the respective service name. Is there a function like strstr for Kernel mode software? The only way I currently found is to walk through the RegistryPath buffer and use RtlCompareMemory(&(pRegPath->Buffer[n], L"String", sizeof(L"String)), but this seems to be a comlicated method.

    Friday, April 17, 2015 4:57 PM
  • No there is not an equivalent of strstr, but you could walk the string from the back looking for the backslash then create a new UNICODE_STRING structure that points to the piece after the backslash and compare that.  That is the way that most people do this type of checking on strings. 


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Friday, April 17, 2015 5:13 PM
  • A KMDF driver will have WdfDriverCreate in the DriverEntry routine.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Friday, April 17, 2015 5:14 PM
  • post the output of !analyze -v back to the forum if you need help understanding what is going on

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, April 17, 2015 10:30 PM
  • Yes, that is what I did. There are different dependencies for the two devices (PCMCIA, driver fo USB/PCMCIA adapter), this is why I specified a seperate service for each of them (two in number).

    During debugging it seemed that the driver's binary get's completely unloaded even if the other device is still using it. The DriverUnload routine has completed before the crash occoured, and I could see that there were some IOCTL_DISK_CKECK_VERIFY from the device that was still attached before the crash occured.

    I tried to use "different" binaries (in meaning of copied the compiled file twice and gave them different names). It seems that the problem does not occour any more.

    Can you explain why it works if I'm going to use files with different names (the contens are the same, of course)? I currently have not enogh HW to test it, but what happens if I use two of that USB adaptors - will the system crash again if I detach one of them?

    Tuesday, April 21, 2015 11:54 AM
  • It sounds like you have a reference problem.  Basically, when you are getting the remove request for the device the driver's reference count is dropping to zero at which point the driver is unloaded.  Having it as two binaries eliminates the problem, in the case you describe.  I don't know if you have the capability but testing with two of the same device (i.e. both with the same connection) probably will show the same problem.

    I you use windbg you can use the !object command on the driver object (or any other object for that matter) to see what the reference count is.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Tuesday, April 21, 2015 12:39 PM
  • I got a second USB device now. I can attach/detach in different order them without running into a system crash (keep in mind: I still using files with different names for PCMCIA and USB).

    Now I have another situation:

    I used different device names for PCMCIA and USB for IoCreateDevice, which will result in a STATUS_OBJECT_NAME_COLLISION (of course).

    When I try IoCreateDevice with NULL in DeviceName, the device is not mounted properly any more (I can see the drive in explorer, but cannot access it).

    Next I intended to add a number to the device name (\Device\DevUSB0, DevUSB1,...), but I could not figure out how to append the number from within a loop - it crashed in RtlToUnicodeString - what is wrong here?

    #define DEV_NAME  L"\\Device\\DevUSB"
    #define MAX_DRIVS 8
    
    UNICODE_STRING   DevName;
    UNICODE_STRING   DevNum;
    WCHAR            NameBuf[sizeof(DEV_NAME) + 1];
    WCHAR            NumBuf[10];    /* 9 digits + \0 */
    ULONG            Loop;
    
    RtlInitEmptyUnicodeString(&DevName, NameBuf, sizoef(NameBuf));
    RtlInitEmptyUnicodeString(&DevNum, NumBuf, sizoef(NumBuf));
     
    For(Loop = 0; Loop < MAX_DRIVES)
    {
        RtlCopyUnicodeString(&DevName, DEV_NAME);
        RtlIntegerToUnicodeString(Loop, 10, &DevNum);      /* --> Crash 0xBE */
        RltAppendUnicodeStringToString(&DevName, &DevNum);
    
        ...
    }
    
    
    RtlFreeUnicodeString(&NameBuf);
    RtlFreeUnicodeString(&NumBuf);

    Friday, April 24, 2015 1:19 PM
  • First it helps incredibly on a crash to have the !analyze -v for the dump.  A couple of things I would do to change your code.  First up the size of the NameBuf, you calculate it rather weirdly since you are creating it with the sizeof(DEV_NAME) which will give you byte size, but the declaration is the number of ushorts.  I would dump your current code approach and declare the NameBuf to be a reasonable size, say 20.  Then use RtlUnicodeStringPrintf to fill in the name.


    Don Burn Windows Driver Consulting Website: http://www.windrvr.com

    Friday, April 24, 2015 1:32 PM