/**************************************************************************************************/
/* */
/* Copyright (c) 2007 Microsoft Corporation. All Rights Reserved */
/* */
/**************************************************************************************************/
#pragma warning( disable : 4201 ) // nonstandard extension used : nameless strut/union
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <tchar.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <initguid.h>
#include <devguid.h>
#define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))
#define arraysize(p) (sizeof(p)/sizeof((p)[0]))
CONST GUID *DiskClassesToClean[2] = {
&GUID_DEVCLASS_DISKDRIVE,
&GUID_DEVCLASS_VOLUME
};
/**************************************************************************************************/
/* */
/* The user must be member of Administrator group and must have backup and restore permissions */
/* (SE_BACKUP_NAME and SE_RESTORE_NAME). No check for these is performed in this example. */
/* */
/**************************************************************************************************/
int
__cdecl
main(
IN int ArgC,
IN char * pArgV[]
)
{
HDEVINFO DeviceInfoSet;
SP_DEVINFO_DATA DeviceInfoData;
ULONG DevicesRemoved = 0,
i,
MemberIndex,
Status,
Problem,
ulClassesToCleanIdx;
BOOL bDoRemove = TRUE;
CONFIGRET cr;
TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
OSVERSIONINFO osvi;
const GUID ** ClassesToClean;
//
// Parse parameters.
//
for (i = 1; i < (ULONG)ArgC; i++) {
//
// Check for help.
//
if ( (lstrcmpi(pArgV[i], TEXT("-?")) == 0) ||
(lstrcmpi(pArgV[i], TEXT("/?")) == 0) ){
printf("\nCleanUp will remove phantom storage device nodes from this machine.\n\n");
printf("Usage: CleanUp \n");
printf("\twhere /n displays but does not remove the phantom devnodes.\n");
printf("\nBackup and Restore privileges are required to run this utility.\n");
return 0;
}
//
// Check for -n, which means just list the devices that we would remove.
//
if ( (lstrcmpi(pArgV[i], TEXT("-n")) == 0) ||
(lstrcmpi(pArgV[i], TEXT("/n")) == 0) ) {
bDoRemove = FALSE;
}
}
//
// Run only on Windows XP/2003 (version 5.1) or later.
//
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi)) {
printf("CleanUp: Unable to verify Windows version, exiting...\n");
return -1;
}
if ((osvi.dwMajorVersion == 5) &&
((osvi.dwMinorVersion == 1) || (osvi.dwMinorVersion == 2))) {
}
else if (osvi.dwMajorVersion>=6) {
}
else
{
printf("CleanUp: This utility is designed to run on Windows XP/2003 and later\n");
return -1;
}
ClassesToClean = DiskClassesToClean;
ulClassesToCleanIdx = arraysize(DiskClassesToClean);
for (i=0; (i<ulClassesToCleanIdx) && (bDoRemove); i++) {
DeviceInfoSet = SetupDiGetClassDevs(ClassesToClean[i],
NULL,
NULL,
0
);
if (INVALID_HANDLE_VALUE!=DeviceInfoSet) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
MemberIndex = 0;
while (SetupDiEnumDeviceInfo(DeviceInfoSet,
MemberIndex++,
&DeviceInfoData
)) {
//
// Determine whether this device is a phantom.
//
cr = CM_Get_DevNode_Status(&Status,
&Problem,
DeviceInfoData.DevInst,
0
);
if ((cr == CR_NO_SUCH_DEVINST) ||
(cr == CR_NO_SUCH_VALUE)) {
//
// This is a phantom. Now get the DeviceInstanceId so we
// can display this as output, then delete the phantom if requested.
//
if (CM_Get_Device_ID(DeviceInfoData.DevInst,
DeviceInstanceId,
SIZECHARS(DeviceInstanceId),
0) == CR_SUCCESS) {
if (bDoRemove) {
printf("DevNodePhantomCleaner: %s will be removed.\n",
DeviceInstanceId);
//
// Call DIF_REMOVE to remove the device's hardware
// and software registry keys.
//
if (SetupDiCallClassInstaller(DIF_REMOVE,
DeviceInfoSet,
&DeviceInfoData
)) {
DevicesRemoved++;
} else {
printf("CleanUp: Error 0x%X removing phantom\n",
GetLastError);
}
} else {
printf("CleanUp: %s would have been removed.\n",
DeviceInstanceId);
}
}
}
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
}
return DevicesRemoved;
}