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