|
|
#include "precomp.h"
#pragma hdrstop
#define BUFFERSIZE 1024
typedef struct _DEVICEINFO { BOOL DevNodeStarted; } DEVICEINFO, *PDEVICEINFO;
BOOL IsDriverLoaded( PTSTR ServiceName ) { NTSTATUS Status; BOOL bObjectIsLoaded = FALSE; UCHAR Buffer[BUFFERSIZE]; UNICODE_STRING UnicodeStringDriver, UnicodeStringServiceName; OBJECT_ATTRIBUTES Attributes; HANDLE DirectoryHandle; POBJECT_DIRECTORY_INFORMATION DirInfo; POBJECT_NAME_INFORMATION NameInfo; ULONG Context = 0; ULONG ReturnedLength;
RtlZeroMemory(Buffer, BUFFERSIZE); RtlInitUnicodeString(&UnicodeStringServiceName, ServiceName); RtlInitUnicodeString(&UnicodeStringDriver, TEXT("\\Driver"));
InitializeObjectAttributes(&Attributes, &UnicodeStringDriver, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenDirectoryObject(&DirectoryHandle, DIRECTORY_QUERY, &Attributes );
if (!NT_SUCCESS(Status)) { printf("NtOpenDirectoryObject failed with 0x%X\n", Status); goto clean0; }
//
// Get the actual name of the object directory object.
//
NameInfo = (POBJECT_NAME_INFORMATION)&Buffer[0]; if (!NT_SUCCESS(Status = NtQueryObject(DirectoryHandle, ObjectNameInformation, NameInfo, BUFFERSIZE, (PULONG)NULL))) { printf( "Unexpected error obtaining actual object directory name\n" ); printf( "Error was: %X\n", Status ); goto clean0; }
//
// Grab the driver objects in chuncks instead of one at a time.
//
for (Status = NtQueryDirectoryObject(DirectoryHandle, &Buffer, BUFFERSIZE, FALSE, FALSE, &Context, &ReturnedLength ); NT_SUCCESS(Status) && !bObjectIsLoaded; Status = NtQueryDirectoryObject(DirectoryHandle, &Buffer, BUFFERSIZE, FALSE, FALSE, &Context, &ReturnedLength )) { if (!NT_SUCCESS(Status)) { if (Status != STATUS_NO_MORE_FILES) { printf("NtQueryDirectoryObject failed with 0x%X\n", Status); } break; }
DirInfo = (POBJECT_DIRECTORY_INFORMATION)&Buffer[0];
while (TRUE) { //
// Check if there is another record. If there isn't, then get out
// of the loop now.
//
if (DirInfo->Name.Length == 0) { break; }
if (RtlCompareUnicodeString(&UnicodeStringServiceName, &(DirInfo->Name), TRUE) == 0) { bObjectIsLoaded = TRUE; break; }
DirInfo = (POBJECT_DIRECTORY_INFORMATION)(((PUCHAR)DirInfo) + sizeof(OBJECT_DIRECTORY_INFORMATION)); }
RtlZeroMemory(Buffer, BUFFERSIZE); }
clean0: NtClose(DirectoryHandle);
return bObjectIsLoaded; } BOOL RestartDevicesUsingService( LPTSTR ServiceName ) { BOOL b = TRUE; CONFIGRET cr; DEVNODE DevNode; BOOL bIsDriverLoaded; INT count, i; TCHAR VetoName[512]; ULONG VetoNameLength; PNP_VETO_TYPE VetoType; ULONG Status, Problem; ULONG BufferLen; OSVERSIONINFO osvi; PTSTR Buffer = NULL; PTSTR p; PDEVICEINFO DeviceInfo = NULL;
printf("Stopping all devices that are using the service %ws\n", ServiceName);
try { bIsDriverLoaded = IsDriverLoaded(ServiceName);
printf("%ws %ws loaded\n", ServiceName, bIsDriverLoaded ? TEXT("is") : TEXT("is NOT") );
//
// If this service is not loaded then we don't need to do anything.
//
if (!bIsDriverLoaded) { goto clean0; } //
// Find out how large a buffer it will take to hold all the devices that
// are using this service.
//
if (((cr = CM_Get_Device_ID_List_Size(&BufferLen, ServiceName, CM_GETIDLIST_FILTER_SERVICE )) != CR_SUCCESS) || (BufferLen == 0)) { if (cr != CR_SUCCESS) { b = FALSE; printf("CM_Get_Device_ID_List_Size failed with 0x%X\n", cr); } else { printf("There are no devices using this service!\n"); } goto clean0; } Buffer = LocalAlloc(LPTR, BufferLen*sizeof(TCHAR)); if (Buffer == NULL) { b = FALSE; goto clean0; } //
// Get all of the devices that are using this service.
//
if (CM_Get_Device_ID_List(ServiceName, Buffer, BufferLen, CM_GETIDLIST_FILTER_SERVICE | CM_GETIDLIST_DONOTGENERATE ) != CR_SUCCESS) { b = FALSE; goto clean0; }
//
// Count up how many devices we are dealing with.
//
count = 0; for (p = Buffer; *p; p += (lstrlen(p) + 1)) { count++; }
if (count == 0) { printf("There are no devices using this service!\n"); goto clean0; }
printf("%d devices are using this service\n", count);
//
// Allocate an array of our DEVICEINFO structures so we can keep
// track of the Devnodes and whether a device was started or not
// before we tried to unloade the specified driver.
//
DeviceInfo = LocalAlloc(LPTR, count*sizeof(DEVICEINFO));
if (DeviceInfo == NULL) { b = FALSE; goto clean0; }
//
// Enumerate through all of the devices and stop each one.
//
for (p=Buffer, i=0; *p; p+=(lstrlen(p) + 1),i++) { printf("Stopping device %ws\n", p);
if ((cr = CM_Locate_DevNode(&DevNode, p, 0)) == CR_SUCCESS) { if ((CM_Get_DevNode_Status(&Status, &Problem, DevNode, 0) == CR_SUCCESS) && (Status & DN_STARTED)) { DeviceInfo[i].DevNodeStarted = TRUE; } else { printf("\tdevice is not started...skipping\n"); DeviceInfo[i].DevNodeStarted = FALSE; continue; }
//
// We will pass in the VetoType and VetoName to
// CM_Query_And_Remove_Subtree so we can log while a specific
// device could not be stopped. This will also prevent the
// kernel from poping up a dialog telling the user that the
// device could not be removed.
//
// NOTE: It is important to note that on Whistler we pass in the
// CM_REMOVE_NO_RESTART flag. This ensures that the devnode
// will not be restarted until we call CM_Setup_DevNode to
// restart it at a later time. Without this flag (like in
// Windows 2000) it is possible for the device to restart again
// due to some other program or driver triggering a
// reenumeration.
//
VetoNameLength = sizeof(VetoName)/sizeof(TCHAR); cr = CM_Query_And_Remove_SubTree(DevNode, &VetoType, VetoName, VetoNameLength, CM_QUERY_REMOVE_UI_NOT_OK ); if (cr == CR_REMOVE_VETOED) { //
// Someone vetoed the removal of this device!
//
// This is here for logging purposes only. If no logging is
// required then there is no need for this check.
//
printf("\tVetoed 0x%X %ws\n", VetoType, VetoName); } if (cr != CR_SUCCESS) { //
// If we couldn't stop one of the devices then we might as well
// stop since we are going to need a reboot.
//
printf("\tFailed with 0x%X!\n", cr); b = FALSE; break; } } else { //
// If we couldn't locate one of the devices then there is no need to
// continue through the list since a reboot will be needed.
//
printf("\tCouldn't locate the devnode, error 0x%X!\n", cr); b = FALSE; break; } }
printf("\n");
if (b) { bIsDriverLoaded = IsDriverLoaded(ServiceName); printf("%ws %ws loaded\n\n", ServiceName, bIsDriverLoaded ? TEXT("is") : TEXT("is NOT") );
//
// If the driver did not unload, even after we stopped all the
// devices using it, the we need to reboot!
//
if (bIsDriverLoaded) { b = FALSE; } } //
// At this point we need to enumerate through all the devices once again
// and restart them all. It doesn't matter whether we succeeded or not in
// stopping them all, we still need to restart them.
//
for (p=Buffer, i=0; *p; p+=(lstrlen(p) + 1), i++) { printf("Starting device %ws\n", p);
if ((cr = CM_Locate_DevNode(&DevNode, p, 0)) == CR_SUCCESS) { //
// NOTE: For Whistler we will call CM_Setup_DevNode with the
// CM_SETUP_DEVNODE_RESET flag which will clear the
// CM_REMOVE_NO_RESTART flag we set earlier. These two flags
// ensure that the devnode will not get restarted by some other
// program or driver until we want them to.
//
if ((cr = CM_Setup_DevNode(DevNode, CM_SETUP_DEVNODE_READY)) == CR_SUCCESS) { //
// We successfully restarted the device, lets make sure that it
// started and doesn't have any problems. We will only make
// this check if the device was started before.
//
if (DeviceInfo[i].DevNodeStarted == TRUE) { if ((CM_Get_DevNode_Status(&Status, &Problem, DevNode, 0) != CR_SUCCESS) || !(Status & DN_STARTED)) { //
// We couldn't get the status of this device, or it did not
// restart properly, so we will need to reboot.
//
printf("\tDevice could not be restarted!\n"); b = FALSE; } } } else { //
// We couldn't restart this device, so we will need to reboot.
//
printf("\tDevice could not be restarted, error 0x%X!\n", cr); b = FALSE; } } else { //
// We couldn't locate the devnode to restart it.
//
printf("\tCouldn't locate the devnode, error 0x%X!\n", cr); b = FALSE; } }
printf("%ws %ws loaded\n", ServiceName, IsDriverLoaded(ServiceName) ? TEXT("is") : TEXT("is NOT") );
} except(EXCEPTION_EXECUTE_HANDLER) { Buffer = Buffer; DeviceInfo = DeviceInfo; b = FALSE; }
clean0:
if (Buffer) { LocalFree(Buffer); }
if (DeviceInfo) { LocalFree(DeviceInfo); }
return b; }
int __cdecl wmain( IN int argc, IN char *argv[] ) { SC_HANDLE hServiceManager; ENUM_SERVICE_STATUS ServiceStatus[1000]; DWORD ResumeHandle = 0; DWORD cbBytesNeeded, cbServicesReturned; UINT i;
hServiceManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if (hServiceManager) {
if (EnumServicesStatus(hServiceManager, SERVICE_DRIVER, SERVICE_ACTIVE, ServiceStatus, sizeof(ServiceStatus), &cbBytesNeeded, &cbServicesReturned, &ResumeHandle) || (GetLastError() == ERROR_MORE_DATA)) {
for (i=0; i<cbServicesReturned; i++) { printf("\n\n***********************************************************\n"); printf("%ws\n", ServiceStatus[i].lpServiceName); RestartDevicesUsingService(ServiceStatus[i].lpServiceName); printf("***********************************************************\n"); } }
CloseServiceHandle(hServiceManager); } }
|