Starting from Trunk. Im using the driver and application posted to bug 3501. Calling the program once causes (base/system/services/rpcserver.c:2511) RStartServiceA() called ---> MyDriver - Entered DriverEntry ---> MyDriver - Creating Device ---> MyDriver - Creating SymLink ---> MyDriver - Functions set and Devices created ---> MyDriver - Entered Driver unload! ---> MyDriver - PDRIVER_OBJECT 81688ec8 ---> MyDriver - Deleted SymLink ---> MyDriver - Deleted Device Entered debugger on last-chance exception (Exception Code: 0xc0000005) (Page Fault) Memory at 0x808C9F90 could not be read: Page not present. kdb:> bt Command '7t' is unknown. kdb:> bt Eip: Frames: <00000000> This is caused by MmUnloadSystemImage(DriverObject->DriverSection); line in function IopUnloadDriver at /ntoskrnl/io/iomgr/driver.c We are passing DriverSection that has never been set to a value. In MmUnloadSystemImage the first line is PLDR_DATA_TABLE_ENTRY LdrEntry = ImageHandle; and then second line is PVOID BaseAddress = LdrEntry->DllBase; which is line 686. Hence Crash To fix add this patch Index: /ntoskrnl/io/iomgr/driver.c =================================================================== --- driver.c (revision 34399) +++ driver.c (working copy) @@ -1716,6 +1716,8 @@ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); return; } + /* Store the ModuleObject in the Drivers Section */ + DriverObject->DriverSection=ModuleObject; } /* We have a driver for this DeviceNode */ Then run program again we get this (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 359 (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 375 (subsystems/win32/csrss/win32csr/guiconsole.c:2186) received event Console 00930808 GuiData 009308E0 X 80 Y 25 (base/system/services/rpcserver.c:2511) RStartServiceA() called ---> MyDriver - Entered DriverEntry ---> MyDriver - Creating Device ---> MyDriver - Creating SymLink ---> MyDriver - Functions set and Devices created ---> MyDriver - Entered Driver unload! ---> MyDriver - PDRIVER_OBJECT 81689190 ---> MyDriver - Deleted SymLink ---> MyDriver - Deleted Device err:(dll/win32/advapi32/service/scm.c:665) RDeleteService() failed (Error 5) ed for simple PIDL's only! fixme:(dll/win32/shell32/shlexec.c:1373) flags ignored: 0x0000000c (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 359 2186) received event Console 00930808 GuiData 009308E0 X 80 Y 25 err:(dll/win32/advapi32/service/scm.c:637) RCreateServiceW() failed (Error 1073) WARNING: MmLockPagableSectionByHandle at ntoskrnl/mm/drvlck.c:43 is UNIMPLEMENTED! WARNING: MmUnlockPagableImageSection at ntoskrnl/mm/drvlck.c:79 is UNIMPLEMENTED! So my driver is loaded and unloaded. But running the program again, the program shows message box failed to create service. So lets see why, since ive already tracked this down I know. Modify in file /base/system/services/rpcserver.c in at line 398 in function RDeleteService if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, STANDARD_RIGHTS_REQUIRED)) Change to add some debugging before the return of ERROR_ACCESS_DENIED So restarting and rerunning program Get this (base/system/services/rpcserver.c:2513) RStartServiceA() called ---> MyDriver - Entered DriverEntry ---> MyDriver - Creating Device ---> MyDriver - Creating SymLink ---> MyDriver - Functions set and Devices created ---> MyDriver - Entered Driver unload! ---> MyDriver - PDRIVER_OBJECT 816892f0 ---> MyDriver - Deleted SymLink ---> MyDriver - Deleted Device (base/system/services/rpcserver.c:400) Access Denied err:(dll/win32/advapi32/service/scm.c:665) RDeleteService() failed (Error 5) The only access check should be for DELETE not STANDARD_RIGHTS_REQUIRED, i verified in win2k and XP. So make the change keep the same format of the line. if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, DELETE)) return ERROR_ACCESS_DENIED; make changes and try again. This time we get the same MessageBox about failt to create service. Again I already know why. Bring up registry editor in ROS and check HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services Youll still see the TestDrv.sys in there. This is because RDeleteService doesnt really delete anything. So we need to change the RDeleteService in base/system/services/rpcserver.c to actually delete things, though this a quick fix. DWORD RDeleteService( handle_t BindingHandle, SC_RPC_HANDLE hService) { PSERVICE_HANDLE hSvc; PSERVICE lpService; DWORD dwError = ERROR_SUCCESS; //i changed to = ERROR_SUCCESS HKEY hServicesKey = NULL; //i added DPRINT1("RDeleteService() called\n"); if (ScmShutdown) return ERROR_SHUTDOWN_IN_PROGRESS; hSvc = (PSERVICE_HANDLE)hService; if (!hSvc || hSvc->Handle.Tag != SERVICE_TAG) return ERROR_INVALID_HANDLE; if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, DELETE)) return ERROR_ACCESS_DENIED; lpService = hSvc->ServiceEntry; if (lpService == NULL) { DPRINT1("lpService == NULL!\n"); return ERROR_INVALID_HANDLE; } /* FIXME: Acquire service database lock exclusively */ /* Fail if the service doesn't exists! */ if (ScmGetServiceEntryByName(lpService->lpServiceName) == NULL) { return ERROR_SERVICE_DOES_NOT_EXIST; } /* Check if the service has been marked for deletion */ if (lpService->bDeleted) { /* Check if the service is still running */ if (lpService->Status.dwCurrentState == SERVICE_RUNNING) { /* Cannot delete a service that is still running. */ DPRINT1("The service has already been marked for delete!\n"); return ERROR_SERVICE_MARKED_FOR_DELETE; } } /* Check if the service is still runnning */ if (lpService->Status.dwCurrentState == SERVICE_RUNNING) { /* Mark service for delete as we cant delete a service thats running */ lpService->bDeleted = TRUE; dwError = ScmMarkServiceForDelete(lpService); } else { /* Now we can delete the service from the registry */ /* Open the Services Reg key */ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services", 0, KEY_READ, &hServicesKey); if (dwError != ERROR_SUCCESS) return dwError; /* FIXME Need to handle load order and dependencies */ /* Delete the service key */ dwError = RegDeleteKey(hServicesKey, lpService->lpServiceName); RegCloseKey(hServicesKey); if (dwError != ERROR_SUCCESS) return dwError; /* Remove it from the List */ RemoveEntryList(&lpService->ServiceListEntry); /* Free the memory asociated to the DisplayName */ HeapFree(GetProcessHeap(),0,lpService->lpDisplayName); } return dwError; } Now again we run once and the second time we run program, we get BugCheck. Runs are designated by the RStartService() called base/system/services/rpcserver.c:2553) RStartServiceA() called ---> MyDriver - Entered DriverEntry ---> MyDriver - Creating Device ---> MyDriver - Creating SymLink ---> MyDriver - Functions set and Devices created ---> MyDriver - Entered Driver unload! ---> MyDriver - PDRIVER_OBJECT 81688f00 ---> MyDriver - Deleted SymLink ---> MyDriver - Deleted Device (base/system/services/rpcserver.c:389) RDeleteService() called ed for simple PIDL's only! fixme:(dll/win32/shell32/shlexec.c:1373) flags ignored: 0x0000000c (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 359 (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 375 (subsystems/win32/csrss/win32csr/guiconsole.c:2186) received event Console 00930808 GuiData 009308E0 X 80 Y 25 (base/system/services/rpcserver.c:2553) RStartServiceA() called ---> MyDriver - Entered Driver unload! ---> MyDriver - PDRIVER_OBJECT 81688f00 ---> MyDriver - Deleted SymLink ---> MyDriver - Deleted Device (ntoskrnl/ps/thread.c:121) PS: Unhandled Kernel Mode Exception Pointers = 0x9D71F704 (ntoskrnl/ps/thread.c:123) Code c0000005 Addr 8083C7C0 Info0 00000000 Info1 0000001D Info2 0000001D Info3 8085DF3A *** Fatal System Error: 0x0000007e (0xC0000005,0x8083C7C0,0x9D71FBD8,0x9D71F808) Entered debugger on embedded INT3 at 0x0008:0x808acfd8. kdb:> bt Eip: Frames: <9db5e374> Line 888 in IoDeleteDevice is if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED) So out DeviceObject must be crap. Now in the debugger, check the mods, My drivers not there. So the drivers image did get unloaded. But the kernel object for the driver was never deleted because of what I already discussed with fireball Status = ObInsertObject(DriverObject, NULL, FILE_READ_DATA, OBJ_KERNEL_HANDLE, NULL, &hDriver); Details in bug 3473 The OBJ_KERNEL_HANDLE is wrong here. A function gets called in here that changes the PointerCount to the value of OBJ_KERNEL_HANDLE. Also the IopLoadUnloadDriver function uses an existing object that it found in the Object Directory with the function IopGetDriverObject because the object wasnt deleted. So the drivers DriverEntry never gets called (hence the missing debugging message from the driver on the second run) and no device is ever created. Throw a debugging line in the function for when the IopGetDriverObject finds a Object. Heres some debugging STARTING SERVICE (base/system/services/rpcserver.c:1452) RCreateServiceW() called (base/system/services/rpcserver.c:1698) RCreateServiceW() done (Error 0) (base/system/services/rpcserver.c:2573) RStartServiceA() called (ntoskrnl/io/iomgr/device.c:713) Enterd Create Device (ntoskrnl/io/iomgr/device.c:880) Returning (ntoskrnl/io/iomgr/driver.c:1728) Using existing DriverObject 81688190 --->MyDRIVER - Entered Driver unload! --->MyDRIVER - PDRIVER_OBJECT from IoManager 81688190 --->MyDRIVER - Deleted SymLink --->MyDRIVER - Deleted Device (ntoskrnl/io/iomgr/device.c:895) IoDeleteDevice with DeviceObject 0 (ntoskrnl/ps/thread.c:121) PS: Unhandled Kernel Mode Exception Pointers = 0x9D71F704 (ntoskrnl/ps/thread.c:123) Code c0000005 Addr 8083C7E2 Info0 00000000 Info1 0000001D Info2 0000001D Info3 8085E03A Couldnt understand how the drivers unload routine could be called if the image isnt loaded. Doesnt make sense to me. But anyway, contiuning on. So we fix this problem. in /ntoskrnl/io/iomgr/driver.c The function IopCreateDriver Status = ObInsertObject(DriverObject, NULL, FILE_READ_DATA, 0, NULL, &hDriver); Now this time the same BugCheck happens, the object is still not being deleted and we are getting a bad pointer from function IopGetDriverObject, to a driverobject thats garbage. Somewhere we dont Deref, a missed one. Look at all the function that ref driverobject the function and found these that arent obviously derefed. ObReferenceObjectByName in IopGetDriverObject thats not released and again in IopCreateDriver also ObReferenceObject in CreateDevice in device.c So thats 3 including the one in the function itself that needs to be released. So i added four derefs with debuggin to show the objects PointerCount going to zero using ObDereferenceObject which returns the count. (base/system/services/rpcserver.c:2553) RStartServiceA() called --->MyDRIVER - Entered DriverEntry --->MyDRIVER - Creating Device --->MyDRIVER - Creating SymLink --->MyDRIVER - Functions set and Devices created --->MyDRIVER - Entered Driver unload! --->MyDRIVER - PDRIVER_OBJECT 81689030 --->MyDRIVER - Deleted SymLink --->MyDRIVER - Deleted Device (ntoskrnl/io/iomgr/driver.c:1117) Ref: 3 (ntoskrnl/io/iomgr/driver.c:1118) Ref: 2 (ntoskrnl/io/iomgr/driver.c:1122) Ref: 1 (ntoskrnl/io/iomgr/driver.c:1123) Ref: 0 (base/system/services/rpcserver.c:389) RDeleteService() called ed for simple PIDL's only! fixme:(dll/win32/shell32/shlexec.c:1373) flags ignored: 0x0000000c (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoleResize X 544 Y 359 (subsystems/win32/csrss/win32csr/guiconsole.c:1542) GuiConsoY 25 (base/system/services/rpcserver.c:2553) RStartServiceA() called Assertion 'ObjectHeader->NameInfoOffset != 0' failed at ntoskrnl/ob/obdir.c line 202 Entered debugger on embedded INT3 at 0x0008:0x808ad062. kdb:> bt Eip: Frames: kdb:> Indeed the count goes to 0 on the first run. But we crash still when running the program a second time. The cause is the Assertion. This is from the call IopGetDriverObject where we check if its already in the object directory. You can see the assertion happens in LookupEntryDirectory when it finds the driver object. So it hasnt been removed from the object directory. Add the following /* Make the object temporary */ ObMakeTemporaryObject(DriverObject); /* Dereference one more time to have the object manager delete the object */ ObDereferenceObject(DriverObject); to function IopUnloadDriver in /ntoskrnl/io/iomgr/driver.c, place them at the end of this function right before the return STATUS_SUCCESS; statement. The second part of this fix is we still need a call that will delete the object from the object directory. And add the following /* Remove the object from the object directory */ ObpDeleteNameCheck(Object); to the function ObpDeleteObject in /ntoskrnl/ob/oblife.c, place it at the end right before the code /* Now de-allocate all object members */ ObpDeallocateObject(Object); These changes fixes this for me resolve the issues.