BSOne.SFC/eCrmHE/example/lockusb.c

112 lines
3.1 KiB
C

void lockUsb(char* letter)
{
try
{
char szRootPath[16] = { 0 };
sprintf(szRootPath, "%s:\\", letter);
//char szRootPath[] = "D:\\"; // "X:\" -> for GetDriveType
//char szDevicePath[] = "D:"; // "X:" -> for QueryDosDevice
char szDevicePath[16] = { 0 };
sprintf(szDevicePath, "%s:", letter);
//char szVolumeAccessPath[] = "\\\\.\\D:"; // "\\.\X:" -> to open the volume
char szVolumeAccessPath[16] = { 0 };
sprintf(szVolumeAccessPath, "\\\\.\\%s:", letter);
//szVolumeAccessPath[4] = DriveLetter;
long DeviceNumber = -1;
// open the storage volume
HANDLE hVolume = CreateFileA(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE)
{
return;
}
// get the volume's device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if (res)
{
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if (DeviceNumber == -1)
{
return;
}
// get the drive type which is required to match the device numbers correctely
UINT DriveType = GetDriveTypeA(szRootPath);
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
char szDosDeviceName[168];
res = QueryDosDeviceA(szDevicePath, szDosDeviceName, 168);
if (!res)
{
return;
}
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName);
if (DevInst == 0)
{
return;
}
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
WCHAR VetoNameW[MAX_PATH];
VetoNameW[0] = 0;
bool bSuccess = false;
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
DEVINST DevInstParent = 0;
res = CM_Get_Parent(&DevInstParent, DevInst, 0);
//WriteLog("target : %s", szDosDeviceName);
for (long tries = 1; tries <= 3; tries++)
{
VetoNameW[0] = 0;
// CM_Query_And_Remove_SubTree doesn't work for restricted users
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP)
res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
bSuccess = (res == CR_SUCCESS && VetoType == PNP_VetoTypeUnknown);
if (bSuccess)
{
break;
}
Sleep(500); // required to give the next tries a chance!
}
//WriteLog("success : %d", bSuccess);
if (bSuccess)
{
sendData(TYPE_USBDISCONNECTED, szDosDeviceName);
return;
}
/*
if (VetoNameW[0])
{
WriteLog("VetoName=%ws)\n\n", VetoNameW);
}
*/
}
catch (TCHAR * pszError)
{
}
}