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

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;
}


你可能感兴趣的:(TrueCrypt代码 之 通过磁盘设备名获取到对应盘符)