Rameez Usmani
Rameez Usmani

Reputation: 147

Detect if exe is running from a USB

I am writing an app using windows API that needs to check on startup that it is running from a USB device. What I have achieved so far

Here is my code to do the above 2 tasks

HDEVINFO hdevinfo = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE,NULL, NULL, DIGCF_PRESENT);
if (hdevinfo == INVALID_HANDLE_VALUE) {
    WriteLog(L"hdevinfo is INVALID_HANDLE_VALUE");
    return USB_PROT_ERROR;
}
DWORD MemberIndex = 0;
SP_DEVINFO_DATA sp_devinfo_data;
ZeroMemory(&sp_devinfo_data, sizeof(sp_devinfo_data));
sp_devinfo_data.cbSize = sizeof(sp_devinfo_data);
while (SetupDiEnumDeviceInfo(hdevinfo, MemberIndex, &sp_devinfo_data)) {
    DWORD PropertyRegDataType;
    DWORD RequiredSize;
    TCHAR PropertyBuffer[500];
    //get the name of this device
    if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sp_devinfo_data, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &PropertyRegDataType, (PBYTE)&PropertyBuffer, sizeof(PropertyBuffer), &RequiredSize)) {
        WriteLog(L"Device name: %s", PropertyBuffer);
        DWORD PropertyValue;
        //get removal policy for this device
        if (SetupDiGetDeviceRegistryProperty(hdevinfo, &sp_devinfo_data, SPDRP_REMOVAL_POLICY, &PropertyRegDataType, (PBYTE)&PropertyValue, sizeof(PropertyValue), &RequiredSize)) {
            if (PropertyValue == CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL) {
                //not removable
                WriteLog(L"Not Removable");
            }
            else {
                //removable
                WriteLog("Removable");
            }
        }
    }
}

On my PC with 1 HARD DRIVE and 1 USB DRIVE attached, I get this output:

Device name: \Device\00000031
Not Removable

Device name: \Device\00000070
Removable

From the output it is clear that \Device\00000070 is my USB device. And from My Computer I can see that my USB device is mounted on H drive

What I want to achieve now is

OR

After some debugging I found that \Device\HarddiskVolume9 is my USB but you can see in the output that it always show "Not Removable". So if I can find out that \Device\HarddiskVolume9 belongs to \Device\00000070 then that will also work for me as I can then easily use Volume management functions to find the drive letter for \Device\HarddiskVolume9 and match with the drive letter of the executable.

I want to do this using C/C++ Windows API without using any 3rd party library and no .NET code.

Upvotes: 7

Views: 837

Answers (1)

Michael Haephrati
Michael Haephrati

Reputation: 4245

Windows API function GetDriveType returns the following:

DRIVE_UNKNOWN - 0 - The drive type cannot be determined.

DRIVE_NO_ROOT_DIR - 1 - The root path is invalid; for example, there is no volume mounted at the specified path.

DRIVE_REMOVABLE - 2 - The drive has removable media; for example, a floppy drive, thumb drive, or flash card reader.

DRIVE_FIXED - 3 - The drive has fixed media; for example, a hard disk drive or flash drive.

DRIVE_REMOTE - 4 - The drive is a remote (network) drive.

DRIVE_CDROM - 5 - The drive is a CD-ROM drive.

DRIVE_RAMDISK - 6 - The drive is a RAM disk.

So I would use the following code, checking if the return value is equal to (2) - Removable:

#include <windows.h>
int main()
{
    wchar_t basePath[1024]{ L"" }, volName[1024]{ L"" };
    GetModuleFileName(NULL, basePath, 1024);
    GetVolumePathName(basePath, volName, 1024);

    UINT type = GetDriveType(volName);
    if (type == 2)
    {
        MessageBox(NULL, L"You are running from a flash drive (USB)",L"",MB_OK);
    }
    else
    {
        MessageBox(NULL, L"You are NOT running from a flash drive (USB)",L"", MB_OK);

    }
}

Upvotes: 1

Related Questions