TrueCrypt代码 之 通过磁盘设备名获取到对应盘符

时间:2022-10-16 17:37:01

TrueCrypt 提供了一种通过驱动获取磁盘设备路径对应盘符的方法,需要依赖TrueCrypt驱动提供的CC_IOCTL_GET_RESOLVED_SYMLINK消息来获取,代码如下

BOOL ResolveSymbolicLink(LPCWSTR wzSymLinkName, PWSTR wzTargetName)
{
BOOL bResult;
DWORD dwBytesReturned;
RESOLVE_SYMLINK_STRUCT rsResolve;

memset(&rsResolve, 0, sizeof(rsResolve));
wcscpy((PWSTR)&rsResolve.SymLinkName, wzSymLinkName);

bResult = DeviceIoControl(g_hDriver, CC_IOCTL_GET_RESOLVED_SYMLINK, &rsResolve, sizeof(rsResolve), &rsResolve, sizeof(rsResolve), &dwBytesReturned, NULL);

wcscpy(wzTargetName, (PWSTR)&rsResolve.TargetName);

return bResult;
}

// Returns drive letter number assigned to device (-1 if none)
int GetDevicePathRealDriveNo(LPCWSTR lpDevicePath)
{
int nDriveNo;
WCHAR wzSymLinkName[CC_LONG_PATH + 1];
WCHAR wzTempTargetName[CC_LONG_PATH + 1];
WCHAR wzTargetName[CC_LONG_PATH + 1];

if (!ResolveSymbolicLink(lpDevicePath, wzTargetName))
{
wcscpy(wzTargetName, lpDevicePath);
}

for (nDriveNo = 0; nDriveNo < 26; nDriveNo++)
{
WCHAR wzDrive[] = { (WCHAR)('A' + nDriveNo), ':', 0 };
wcscpy(wzSymLinkName, L"\\DosDevices\\");
wcscat(wzSymLinkName, wzDrive);
ResolveSymbolicLink(wzSymLinkName, wzTempTargetName);
if (_wcsicmp(wzTargetName, wzTempTargetName) == 0)
{
return nDriveNo;
}
}

return -1;
}

这种方法在没有驱动时会比较麻烦,下面给大家提供一个不需要驱动的实现版本

int  FakeDosNameForDevice(LPCWSTR lpDevicePath, WCHAR *lpDosDevice, WCHAR *lpCFDevice)
{
static int g_iSeq = 1000;
swprintf(lpDosDevice, L"CnCrypt%d", g_iSeq++);

BOOL bDosLinkCreated = TRUE;
bDosLinkCreated = DefineDosDeviceW(DDD_RAW_TARGET_PATH, lpDosDevice, lpDevicePath);
if (!bDosLinkCreated)
{
return ERR_OS_ERROR;
}

swprintf(lpCFDevice, L"\\\\.\\%s", lpDosDevice);

return 0;
}


int RemoveFakeDosName(LPCWSTR lpDevicePath, LPCWSTR lpDosDevice)
{
BOOL bDosLinkRemoved = DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | DDD_REMOVE_DEFINITION, lpDosDevice, lpDevicePath);
if (!bDosLinkRemoved)
{
return ERR_OS_ERROR;
}

return 0;
}

int GetDevicePathRealDriveNo(LPCTSTR lpszPath)
{
int nDriveNo = -1;
int nStatus = ERR_SUCCESS;
HANDLE hDevice = INVALID_HANDLE_VALUE;
WCHAR szCFDevice[CC_LONG_PATH + 1] = { 0 };
WCHAR szDosDevice[CC_LONG_PATH + 1] = { 0 };

nStatus = FakeDosNameForDevice(lpszPath, szDosDevice, szCFDevice);
if (nStatus != ERR_SUCCESS)
{
goto error;
}

hDevice = CreateFile(szCFDevice, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
nStatus = ERR_OS_ERROR;
goto error;
}

DWORD dwBytesReturned;
STORAGE_DEVICE_NUMBER sdnTempDeviceNumber;
if (::DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdnTempDeviceNumber, sizeof(STORAGE_DEVICE_NUMBER), &dwBytesReturned, NULL))
{
for (int nTempDriveNo = 0; nTempDriveNo < 26; nTempDriveNo++)
{
WCHAR szDevice[32] = L"\\\\.\\X:";
szDevice[4] = WCHAR('A' + nTempDriveNo);
HANDLE hTempDevice = CreateFile(szDevice, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hTempDevice == INVALID_HANDLE_VALUE)
{
continue;
}

DWORD dwBytesReturned;
STORAGE_DEVICE_NUMBER sdnStorageDeviceNumber;
if (::DeviceIoControl(hTempDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdnStorageDeviceNumber, sizeof(STORAGE_DEVICE_NUMBER), &dwBytesReturned, NULL))
{
if (sdnStorageDeviceNumber.DeviceNumber == sdnTempDeviceNumber.DeviceNumber
&& sdnStorageDeviceNumber.PartitionNumber == sdnTempDeviceNumber.PartitionNumber)
{
nDriveNo = nTempDriveNo;
CloseHandle(hTempDevice);
break;
}
}
CloseHandle(hTempDevice);
}
}
else
{
VOLUME_DISK_EXTENTS deDiskExtents;
memset(&deDiskExtents, 0, sizeof(VOLUME_DISK_EXTENTS));
if (!::DeviceIoControl(hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0, &deDiskExtents, sizeof(VOLUME_DISK_EXTENTS), &dwBytesReturned, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
for (int nTempDriveNo = 0; nTempDriveNo < 26; nTempDriveNo++)
{
WCHAR szDevice[32] = L"\\\\.\\X:";
szDevice[4] = WCHAR('A' + nTempDriveNo);
HANDLE hTempDevice = CreateFile(szDevice, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hTempDevice == INVALID_HANDLE_VALUE)
{
continue;
}

VOLUME_DISK_EXTENTS deTempDiskExtents;
memset(&deTempDiskExtents, 0, sizeof(VOLUME_DISK_EXTENTS));
if (::DeviceIoControl(hTempDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0, &deTempDiskExtents, sizeof(VOLUME_DISK_EXTENTS), &dwBytesReturned, NULL))
{
if (deDiskExtents.NumberOfDiskExtents == deTempDiskExtents.NumberOfDiskExtents
&&deDiskExtents.Extents->StartingOffset.QuadPart == deTempDiskExtents.Extents->StartingOffset.QuadPart
&&deDiskExtents.Extents->ExtentLength.QuadPart == deTempDiskExtents.Extents->ExtentLength.QuadPart)
{
nDriveNo = nTempDriveNo;
CloseHandle(hTempDevice);
break;
}
}
CloseHandle(hTempDevice);
}
}
error:
DWORD dwError = GetLastError();
CloseHandle(hDevice);
RemoveFakeDosName(lpszPath, szDosDevice);
SetLastError(dwError);

return nDriveNo;
}