Created
August 28, 2015 23:17
-
-
Save reinsteam/189da02f9e8b66ddb35e to your computer and use it in GitHub Desktop.
Sample code of volumes enumeration to get physical and logical sector alignment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma warning (push) | |
/* 4820: '<struct-name>' : 'n' bytes padding added after data member '<member-name>'*/ | |
# pragma warning (disable : 4820) | |
# pragma warning (disable : 4255 4668) | |
# include <windows.h> | |
# include <stdio.h> | |
#pragma warning (pop) | |
typedef unsigned u32; | |
#ifndef NO_INLINE | |
# define NO_INLINE __declspec(noinline) | |
#endif | |
static u32 _max_align_phys = 0; | |
static u32 _max_align_logic = 0; | |
static NO_INLINE u32 is_volume_guid_valid(const char * guid, u32 guid_size) | |
{ | |
return ( guid[0] == '\\' && guid[1] == '\\' && guid[2] == '?' && guid[3] == '\\' && guid[guid_size - 1] == '\\'); | |
} | |
static NO_INLINE u32 volume_guid_to_name(char * guid, u32 guid_size, char * name, u32 name_size) | |
{ | |
DWORD size = 0; | |
guid[ guid_size - 1 ] = '\0'; | |
size = QueryDosDevice(&guid[4], name, name_size); | |
guid[ guid_size - 1 ] = '\\'; | |
return size; | |
} | |
static NO_INLINE u32 volume_guid_to_path(const char * name, u32 name_size, char * path, u32 path_size) | |
{ | |
((void)name_size); | |
if ( GetVolumePathNamesForVolumeName(name, path, path_size, &path_size) ) | |
{ | |
return path_size; | |
} | |
return 0; | |
} | |
static NO_INLINE u32 sector_desc(const char * name, u32 * align_phys, u32 * align_logic) | |
{ | |
STORAGE_PROPERTY_QUERY query; | |
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc; | |
DWORD bytes; | |
u32 result = 0; | |
HANDLE device = CreateFile(name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); | |
if ( device != INVALID_HANDLE_VALUE ) | |
{ | |
query.PropertyId = StorageAccessAlignmentProperty; | |
query.QueryType = PropertyStandardQuery; | |
if ( DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &desc, sizeof(desc), &bytes, 0) ) | |
{ | |
*align_phys = desc.BytesPerPhysicalSector; | |
*align_logic = desc.BytesPerLogicalSector; | |
result = 1; | |
} | |
CloseHandle(device); | |
} | |
return result; | |
} | |
typedef void (*on_partition)(char * guid, u32 guid_size); | |
static NO_INLINE void enumerate_partitions(char * guid, u32 guid_size, on_partition cback) | |
{ | |
HANDLE handle = FindFirstVolume(guid, guid_size); | |
if ( handle != INVALID_HANDLE_VALUE ) | |
{ | |
cback( guid, (u32)strlen(guid) ); | |
while ( FindNextVolume(handle, guid, guid_size) ) | |
{ | |
cback( guid, (u32)strlen(guid) ); | |
} | |
FindVolumeClose(handle); | |
} | |
} | |
static NO_INLINE void partition(char * guid, u32 guid_size) | |
{ | |
u32 align_phys = 0; | |
u32 align_logic = 0; | |
char name[32]; | |
char path[32]; | |
u32 name_size = 0; | |
u32 path_size = 0; | |
if ( is_volume_guid_valid(guid, guid_size) ) | |
{ | |
name_size = volume_guid_to_name(guid, guid_size, name, sizeof(name)); | |
path_size = volume_guid_to_path(guid, guid_size, path, sizeof(path)); | |
} | |
guid[ guid_size - 1 ] = '\0'; | |
if ( sector_desc(guid, &align_phys, &align_logic) ) | |
{ | |
_max_align_phys = (align_phys > _max_align_phys ) ? align_phys : _max_align_phys; | |
_max_align_logic = (align_logic > _max_align_logic) ? align_logic : _max_align_logic; | |
} | |
printf("%s | %-23s | %-6s | %12u bytes | %11u bytes |\n", guid, name, path, align_phys, align_logic); | |
} | |
int main(void) | |
{ | |
char guid[128]; | |
printf("%-48s | %-23s | %-6s | %s | %s |\n", "GUID", "Name", "Path", "Physical Alignment", "Logical Alignment"); | |
enumerate_partitions(guid, sizeof(guid), &partition); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment