Getting the unique volume name for an unmounted drive

J

Jordan

This message is being reposted from Microsoft's Managed Newsgroup
win32.programmer.wmi per the recommendation of the Microsoft rep in
that thread.

I've been experimenting with programmatic control of drive letter
mappings, and am able to successfully unmount and remount volumes onto
new drive letters. For example, I can move an optical drive from a
defaulted e: to g:. During my testing, I unmounted every drive but the
fixed (boot) hard disk. However, if a drive was left unmounted after
program termination, I no longer had the unique volume ID (of the form
"\\?\Volume{GUID}\") required to programmatically remount it. I found
that I could manually remount the removable drives using the Disk
Management snap-in in the MMC. However, I have been unable to
determine any way to remount my a: (floppy) drive as it doesn't show up
in the Disk Management snap-in.

Device Manager is able to see it, and the drivers are fine. Removing
the device in the Device Manager and running the Add New Hardware
wizard result in it appearing fine again in the Device Manager, but it
still isn't mounted.

The question I'd most like to get answered is: How can I get the
unique volume IDs for unmounted drives (without a drive letter
assignment)?

Short of getting answer to that, I'd appreciate finding out how to
restore my a: floppy disk mapping.

I got a response from Microsoft that using the Win32_VOLUME class will
solve my problem, but is only available on Windows Server 2003, which
most of us (myself included) aren't using.

Thanks,
Jordan
 
P

Pegasus \(MVP\)

Jordan said:
This message is being reposted from Microsoft's Managed Newsgroup
win32.programmer.wmi per the recommendation of the Microsoft rep in
that thread.

I've been experimenting with programmatic control of drive letter
mappings, and am able to successfully unmount and remount volumes onto
new drive letters. For example, I can move an optical drive from a
defaulted e: to g:. During my testing, I unmounted every drive but the
fixed (boot) hard disk. However, if a drive was left unmounted after
program termination, I no longer had the unique volume ID (of the form
"\\?\Volume{GUID}\") required to programmatically remount it. I found
that I could manually remount the removable drives using the Disk
Management snap-in in the MMC. However, I have been unable to
determine any way to remount my a: (floppy) drive as it doesn't show up
in the Disk Management snap-in.

Device Manager is able to see it, and the drivers are fine. Removing
the device in the Device Manager and running the Add New Hardware
wizard result in it appearing fine again in the Device Manager, but it
still isn't mounted.

The question I'd most like to get answered is: How can I get the
unique volume IDs for unmounted drives (without a drive letter
assignment)?

Short of getting answer to that, I'd appreciate finding out how to
restore my a: floppy disk mapping.

I got a response from Microsoft that using the Win32_VOLUME class will
solve my problem, but is only available on Windows Server 2003, which
most of us (myself included) aren't using.

Thanks,
Jordan

Simple: Run the command "mountvol" from the Command Prompt
to show you every volume name.
 
J

Jordan

Thanks, it worked! That's unbelievable that MS couldn't tell me that.
But, is there a way to do it programmatically (rather than
command-line)? I.e., in Win32 C++ (VS 2005)?
 
P

Pegasus \(MVP\)

You need to ask this question in a C++ newsgroup. You can,
of course, shell out to a Command Processor and use mountvol.exe
but there are probably more elegant ways.
 
S

shura

////////////////////////////////////////////////////////////////
// June of 2006.
// If this code works, it was written by Alexander Mamaev
// If not, I don't know who wrote it.
//
// This file contains example of using the following functions:
// - QueryDosDevice
// - FindFirstVolume/FindNextVolume/FindVolumeClose
// -
FindFirstVolumeMountPoint/FindNextVolumeMountPoint/FindVolumeMountPointClose
////////////////////////////////////////////////////////////////

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <malloc.h>

#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))


///////////////////////////////////////////////////////////
// GetVolumeDosDevice
//
// Returns drive letter for given volume
// or '*' if no drive letter
///////////////////////////////////////////////////////////
static WCHAR
GetVolumeDosDevice(
IN PCWSTR Volume
)
{
WCHAR buffer1[100];
WCHAR buffer2[100];
WCHAR Let[3];

if ( '\\' == Volume[0]
&& '\\' == Volume[1]
&& '?' == Volume[2]
&& '\\' == Volume[3]
&& QueryDosDeviceW( Volume + 4, buffer2, ARRSIZE(buffer2) ) )
{
Volume = buffer2;
}

for ( Let[0] = 'A', Let[1] = ':', Let[2] = 0; Let[0] <= L'Z'; Let[0]
+= 1 )
{
if ( QueryDosDeviceW( Let, buffer1, ARRSIZE(buffer1) )
&& 0 == _wcsicmp(buffer1, Volume) )
{
return Let[0];
}
}

return '*';
}

static const WCHAR szDriveTypes[][10]={
L"Unknown",
L"NoRoot",
L"Removable",
L"Fixed",
L"Remote",
L"CdRom",
L"RamDisk"
};

//
// Be sure that array szDriveType corresponds DRIVE_XXX constants
//
C_ASSERT( 0 == DRIVE_UNKNOWN );
C_ASSERT( 1 == DRIVE_NO_ROOT_DIR );
C_ASSERT( 2 == DRIVE_REMOVABLE );
C_ASSERT( 3 == DRIVE_FIXED );
C_ASSERT( 4 == DRIVE_REMOTE );
C_ASSERT( 5 == DRIVE_CDROM );
C_ASSERT( 6 == DRIVE_RAMDISK );

C_ASSERT( 7 == ARRSIZE(szDriveTypes) );



///////////////////////////////////////////////////////////
// program entry point
//
///////////////////////////////////////////////////////////
int
main(
IN int argc,
IN char **argv
)
{
WCHAR szVolume[100];
VOLUME_DISK_EXTENTS* VolumeExtents = (VOLUME_DISK_EXTENTS*)_alloca(
512 );
HANDLE f;

UNREFERENCED_PARAMETER( argc );
UNREFERENCED_PARAMETER( argv );

//
// Do not show error when there is no media in floppy drive
//
SetErrorMode( SEM_FAILCRITICALERRORS );

//
// Enumerate volumes with FindFirstVolume/FindNextVolume/FindVolumeClose
//
f = FindFirstVolumeW( szVolume, ARRSIZE(szVolume) );
if ( INVALID_HANDLE_VALUE != f )
{
wprintf( L"\nVolumes:\n" );

do
{
UINT Len;
HANDLE h;
DWORD DriveType;
WCHAR szMountPoint[100];
WCHAR VolumeNameBuffer[64];
WCHAR FileSystemNameBuffer[64];
WCHAR DriveLetter;

//
// Get the length of volume to add/remove last slash
// FindFirstVolume/FindNextVolume always returns volume with last
slash
//
Len = wcslen(szVolume);
if ( 0 == Len )
{
wprintf( L"Impossible!\n" );
continue;
}

wprintf( L"%s\n", szVolume );

//
// Get general volume information
//
if ( GetVolumeInformationW( szVolume, VolumeNameBuffer,
ARRSIZE(VolumeNameBuffer),
NULL, NULL, NULL,
FileSystemNameBuffer,
ARRSIZE(FileSystemNameBuffer) ) )
{
wprintf( L" FileSystem : %s\n", FileSystemNameBuffer );
wprintf( L" Label : %s\n", VolumeNameBuffer );
}

//
// Get drive type (compare with IOCTL_DISK_GET_DRIVE_GEOMETRY)
//
DriveType = GetDriveTypeW( szVolume );
wprintf( L" DriveType : %s\n", szDriveTypes[DriveType >=
ARRSIZE(szDriveTypes)? DRIVE_UNKNOWN : DriveType ] );

//
// Remove last slash
//
szVolume[Len-1] = 0;

//
// Get another name of volume
//
wprintf( L" Links : " );
if ( QueryDosDeviceW( szVolume + 4, szMountPoint,
ARRSIZE(szMountPoint) ) )
wprintf( L" %s,", szMountPoint );

//
// Get drive letter
//
DriveLetter = GetVolumeDosDevice( szVolume );
wprintf( L" %c:\n", DriveLetter );

//
// Enumerate mount points (Last slash is required)
//
szVolume[Len-1] = '\\';
h = FindFirstVolumeMountPointW( szVolume, szMountPoint,
ARRSIZE(szMountPoint) );
if ( INVALID_HANDLE_VALUE != h )
{
wprintf( L"This volume contains mount points:\n" );
do {
WCHAR szTmp[100];
//
// szMount point is root relative path. Create absolute path
//
_snwprintf( szTmp, ARRSIZE(szTmp), L"%c:\\%s", DriveLetter,
szMountPoint );
szTmp[ARRSIZE(szTmp)-1] = 0;
if ( GetVolumeNameForVolumeMountPointW( szTmp, szMountPoint,
ARRSIZE(szMountPoint) ) )
wprintf( L" %s => %s\n", szTmp, szMountPoint );
else
wprintf( L" %s => \"Unknown\"\n", szTmp );
} while( FindNextVolumeMountPointW( h, szMountPoint,
ARRSIZE(szMountPoint) ) );
FindVolumeMountPointClose( h );
}

//
// Open volume to get usefull information (No last slash)
//
szVolume[Len-1] = 0;
h = CreateFileW( szVolume, MAXIMUM_ALLOWED,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( INVALID_HANDLE_VALUE != h )
{
DISK_GEOMETRY dg;
PARTITION_INFORMATION info;
GET_LENGTH_INFORMATION vlen;
DWORD i, Tmp;

//
// Get media type (compare with GetDriveTypeW)
//
if ( DeviceIoControl( h, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL,
0, &dg, sizeof(dg), &Tmp, NULL )
&& Tmp >= sizeof(dg) )
{
wprintf( L" Media type : %s\n", RemovableMedia == dg.MediaType
? L"Removable media other than floppy"
: FixedMedia == dg.MediaType
? L"Fixed hard disk"
: L"Unknown" );
}

//
// Get volume length (Requires Windows XP)
//
if ( DeviceIoControl( h, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0,
&vlen, sizeof(vlen), &Tmp, NULL )
&& Tmp >= sizeof(vlen) )
{
wprintf( L" Length : %lu.%02lu Gb\n",
(DWORD)(vlen.Length.QuadPart >> 30),
(DWORD)((((vlen.Length.QuadPart&0x3FFFFFFF) +
0x5FFFFF) * 100) >> 30) );
}

//
// Only for basic volumes
//
if ( DeviceIoControl( h, IOCTL_DISK_GET_PARTITION_INFO, NULL,
0, &info, sizeof(info), &Tmp, NULL )
&& Tmp >= sizeof(info) )
{
wprintf( L" Partition : type 0x%lx, number %lu, length
%lu.%02lu Gb, boot \"%s\"\n",
(DWORD)info.PartitionType, info.PartitionNumber,
(DWORD)(info.PartitionLength.QuadPart >> 30),
(DWORD)((((info.PartitionLength.QuadPart&0x3FFFFFFF)
+ 0x5FFFFF) * 100) >> 30),
info.BootIndicator? L"yes" : L"no" );
}

//
// Get layout of volume
//
if ( DeviceIoControl( h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0, VolumeExtents, 512, &Tmp, NULL )
&& Tmp >= sizeof(*VolumeExtents) )
{
wprintf( L" Volume consists of %lu extent(s)\n",
VolumeExtents->NumberOfDiskExtents );
for ( i = 0; i < VolumeExtents->NumberOfDiskExtents; i++ )
{
UINT64 Start =
VolumeExtents->Extents.StartingOffset.QuadPart;
UINT64 End =
VolumeExtents->Extents.StartingOffset.QuadPart +
VolumeExtents->Extents.ExtentLength.QuadPart;
wprintf( L" %i: disk %lu, [0x%I64x 0x%I64x) bytes =
[0x%lx 0x%lx) sectors\n", i,
VolumeExtents->Extents.DiskNumber,
Start, End, (DWORD)(Start>>9), (DWORD)(End>>9) );
}
}

CloseHandle( h );
}

wprintf( L"\n" );
} while ( FindNextVolumeW(f, szVolume, ARRSIZE(szVolume) ) );

FindVolumeClose( f );
}

//
// Exit to Windows
//
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top