284 lines
7.8 KiB
C++
284 lines
7.8 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
wsbvol.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Definitions for volume support routines
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ran Kalach [rankala] 27, January 2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include <stdafx.h>
|
||
|
#include <wsbvol.h>
|
||
|
|
||
|
// Internal functions
|
||
|
static HRESULT FindMountPoint(IN PWSTR enumName, IN PWSTR volumeName, OUT PWSTR firstMountPoint, IN ULONG maxSize);
|
||
|
|
||
|
HRESULT
|
||
|
WsbGetFirstMountPoint(
|
||
|
IN PWSTR volumeName,
|
||
|
OUT PWSTR firstMountPoint,
|
||
|
IN ULONG maxSize
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Find one Mount Point path (if exists) for the given volume
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
volumeName - The volume name to search mount path for.
|
||
|
It should have the \\?\volume{GUID}\ format
|
||
|
firstMountPoint - Buffer for the output mount point path
|
||
|
maxSize - Buffer size
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
S_OK - If at least one Mount Point is found
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HRESULT hr = S_FALSE;
|
||
|
WCHAR name[10];
|
||
|
UCHAR driveLetter;
|
||
|
|
||
|
WCHAR tempName[MAX_PATH];
|
||
|
WCHAR driveName[10];
|
||
|
FILE_FS_DEVICE_INFORMATION DeviceInfo;
|
||
|
IO_STATUS_BLOCK StatusBlock;
|
||
|
HANDLE hDrive = NULL ;
|
||
|
NTSTATUS status;
|
||
|
|
||
|
WsbTraceIn(OLESTR("WsbGetFirstMountPoint"), OLESTR("volume name = <%ls>"), volumeName);
|
||
|
|
||
|
name[1] = ':';
|
||
|
name[2] = '\\';
|
||
|
name[3] = 0;
|
||
|
|
||
|
driveName[0] = '\\';
|
||
|
driveName[1] = '\\';
|
||
|
driveName[2] = '.';
|
||
|
driveName[3] = '\\';
|
||
|
driveName[5] = ':';
|
||
|
driveName[6] = 0;
|
||
|
|
||
|
for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++) {
|
||
|
name[0] = driveLetter;
|
||
|
|
||
|
// Exclude network drives
|
||
|
if (! GetVolumeNameForVolumeMountPoint(name, tempName, MAX_PATH)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Verify that the drive is not removable or floppy,
|
||
|
// this is required to avoid popups when the drive is empty
|
||
|
driveName[4] = driveLetter;
|
||
|
hDrive = CreateFile(driveName,
|
||
|
FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
0,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
0);
|
||
|
if (hDrive == INVALID_HANDLE_VALUE) {
|
||
|
// Can't open it - won't search on it
|
||
|
WsbTrace(OLESTR("WsbGetFirstMountPoint: Could not open volume %ls, status = %lu - Skipping it!\n"), driveName, GetLastError());
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
status = NtQueryVolumeInformationFile(hDrive,
|
||
|
&StatusBlock,
|
||
|
(PVOID) &DeviceInfo,
|
||
|
sizeof(FILE_FS_DEVICE_INFORMATION),
|
||
|
FileFsDeviceInformation);
|
||
|
if (!NT_SUCCESS(status)) {
|
||
|
// Can't query it - won't search on it
|
||
|
WsbTrace(OLESTR("WsbGetFirstMountPoint: Could not query information for volume %ls, status = %ld - Skipping it!\n"), driveName, (LONG)status);
|
||
|
CloseHandle(hDrive);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ((DeviceInfo.Characteristics & FILE_FLOPPY_DISKETTE) || (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)) {
|
||
|
// Skip removable/floppy drives
|
||
|
WsbTrace(OLESTR("WsbGetFirstMountPoint: Skipping removable/floppy volume %ls\n"), driveName);
|
||
|
CloseHandle(hDrive);
|
||
|
continue;
|
||
|
}
|
||
|
CloseHandle(hDrive);
|
||
|
WsbTrace(OLESTR("WsbGetFirstMountPoint: Checking mount points on volume %ls\n"), driveName);
|
||
|
|
||
|
// Check mount points on drive
|
||
|
hr = FindMountPoint(name, volumeName, firstMountPoint, maxSize);
|
||
|
if (S_OK == hr) {
|
||
|
// Looking for only one mount point
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WsbTraceOut(OLESTR("WsbGetFirstMountPoint"), OLESTR("hr = <%ls> mount point = <%ls>"), WsbHrAsString(hr), firstMountPoint);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
FindMountPoint(
|
||
|
IN PWSTR enumName,
|
||
|
IN PWSTR volumeName,
|
||
|
OUT PWSTR firstMountPoint,
|
||
|
IN ULONG maxSize
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Find one Mount Point path (if exists) for the given volume on the given enumeration-volume
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
enumName - Volume to enumerate, i.e. search for a mount point on it
|
||
|
which corresponds to the given volume
|
||
|
volumeName - The volume name to search mount path for.
|
||
|
It should have the \\?\volume{GUID}\ format
|
||
|
firstMountPoint - Buffer for the output mount point path
|
||
|
maxSize - Buffer size
|
||
|
|
||
|
Comments:
|
||
|
Avoid the standard HSM try-catch paradigm for performance, especially since this
|
||
|
function is recursive
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
S_OK - if at least one Mount Point is found
|
||
|
S_FALSE - Otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HANDLE hEnum;
|
||
|
WCHAR *enumVolumeName = NULL;
|
||
|
WCHAR *volumeMountPoint = NULL;
|
||
|
WCHAR *mountPointPath = NULL;
|
||
|
|
||
|
WCHAR c1, c2;
|
||
|
WCHAR *linkName1 = NULL;
|
||
|
WCHAR *linkName2 = NULL;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
enumVolumeName = (WCHAR*)WsbAlloc(MAX_PATH * sizeof(WCHAR));
|
||
|
if (NULL == enumVolumeName) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
volumeMountPoint = (WCHAR*)WsbAlloc(maxSize * sizeof(WCHAR));
|
||
|
if (NULL == volumeMountPoint) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
mountPointPath = (WCHAR*)WsbAlloc((maxSize + wcslen(enumName)) * sizeof(WCHAR));
|
||
|
if (NULL == mountPointPath) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (! GetVolumeNameForVolumeMountPoint(enumName, enumVolumeName, MAX_PATH)) {
|
||
|
DWORD dwErr = GetLastError();
|
||
|
hr = HRESULT_FROM_WIN32(dwErr);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (!wcscmp(enumVolumeName, volumeName)) {
|
||
|
// The volume to enumerate on is the one we are looking for
|
||
|
wcscpy(firstMountPoint, enumName);
|
||
|
hr = S_OK;
|
||
|
goto exit;
|
||
|
} else {
|
||
|
linkName1 = (WCHAR*)WsbAlloc((maxSize * 2) * sizeof(WCHAR));
|
||
|
if (NULL == linkName1) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
linkName2 = (WCHAR*)WsbAlloc((maxSize * 2) * sizeof(WCHAR));
|
||
|
if (NULL == linkName1) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
c1 = enumVolumeName[48];
|
||
|
c2 = volumeName[48];
|
||
|
enumVolumeName[48] = 0;
|
||
|
volumeName[48] = 0;
|
||
|
|
||
|
if (QueryDosDevice(&enumVolumeName[4], linkName1, maxSize*2) &&
|
||
|
QueryDosDevice(&volumeName[4], linkName2, maxSize*2)) {
|
||
|
|
||
|
if (!wcscmp(linkName1, linkName2)) {
|
||
|
wcscpy(firstMountPoint, enumName);
|
||
|
enumVolumeName[48] = c1;
|
||
|
volumeName[48] = c2;
|
||
|
hr = S_OK;
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
enumVolumeName[48] = c1;
|
||
|
volumeName[48] = c2;
|
||
|
}
|
||
|
|
||
|
hEnum = FindFirstVolumeMountPoint(enumVolumeName, volumeMountPoint, maxSize);
|
||
|
if (hEnum == INVALID_HANDLE_VALUE) {
|
||
|
hr = S_FALSE;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
for (;;) {
|
||
|
wcscpy(mountPointPath, enumName);
|
||
|
wcscat(mountPointPath, volumeMountPoint);
|
||
|
|
||
|
// Enumerate on the mount path we found
|
||
|
hr = FindMountPoint(mountPointPath, volumeName, firstMountPoint, maxSize);
|
||
|
if (S_OK == hr) {
|
||
|
// Found one mount point path, no need to continue
|
||
|
FindVolumeMountPointClose(hEnum);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (! FindNextVolumeMountPoint(hEnum, volumeMountPoint, maxSize)) {
|
||
|
FindVolumeMountPointClose(hEnum);
|
||
|
hr = S_FALSE;
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
if (enumVolumeName) {
|
||
|
WsbFree(enumVolumeName);
|
||
|
}
|
||
|
if (volumeMountPoint) {
|
||
|
WsbFree(volumeMountPoint);
|
||
|
}
|
||
|
if (mountPointPath) {
|
||
|
WsbFree(mountPointPath);
|
||
|
}
|
||
|
if (linkName1) {
|
||
|
WsbFree(linkName1);
|
||
|
}
|
||
|
if (linkName2) {
|
||
|
WsbFree(linkName2);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|