Python and GetVolumeInformationW and GetDriveTypeW: list all disks and get disk info and filesystem flags
Question: I what to know how to get a list of working drives in python(Windows) works but gets a list of all the posable drives i what a list of all the currently plugged in/working drives Solution: Use this line of code You can also use your approach and filter for Question: I am unable to get the disks name and disk state details using python: Solution: Answering to you question, below code gives you the disks names and disk state I’ve also added an attribute that automatically checks the return value and raises Windows exception based on the GetLastError() code, and an enumeration to process the flags into a readable format: Output example: Solution 2: For future reference, I’ll leave the complete code here on how to list all disks and get their fstab-like information Output (Just replaces disk serial with zeros):
Python and GetVolumeInformationW and GetDriveTypeW: list all disks and get disk info and filesystem flags
On python3 using the windows API: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationw
How to get these values (file_system_flags, max_component_length and serial_number), through this function GetVolumeInformationW , without installing any other external modules?
import ctypes kernel32 = ctypes.windll.kernel32 volumeNameBuffer = ctypes.create_unicode_buffer(1024) fileSystemNameBuffer = ctypes.create_unicode_buffer(1024) serial_number = None max_component_length = None file_system_flags = None target_disk = 'C:\\' rc = kernel32.GetVolumeInformationW( ctypes.c_wchar_p(target_disk), volumeNameBuffer, ctypes.sizeof(volumeNameBuffer), serial_number, max_component_length, file_system_flags, fileSystemNameBuffer, ctypes.sizeof(fileSystemNameBuffer) ) mount_point = target_disk[:-1] disk_label = volumeNameBuffer.value fs_type = fileSystemNameBuffer.value max_length = max_component_length flags = file_system_flags serial = serial_number print(mount_point, disk_label, fs_type, max_length, flags, serial)
Complement: And how do I convert filesystem flags into human readable format?
my_disk_flag = 0x3e706ff hex_flags = [0x00000002, 0x00000001, 0x20000000, 0x00000010, 0x00040000, 0x00000008, 0x00080000, 0x00100000, 0x00020000, 0x00800000, 0x00400000, 0x00010000, 0x01000000, 0x00000080, 0x00000040, 0x00200000, 0x02000000, 0x00000004, 0x00008000, 0x00000020, 0x08000000] str_flags = ['FILE_CASE_PRESERVED_NAMES', 'FILE_CASE_SENSITIVE_SEARCH', 'FILE_DAX_VOLUME', 'FILE_FILE_COMPRESSION', 'FILE_NAMED_STREAMS', 'FILE_PERSISTENT_ACLS', 'FILE_READ_ONLY_VOLUME', 'FILE_SEQUENTIAL_WRITE_ONCE', 'FILE_SUPPORTS_ENCRYPTION', 'FILE_SUPPORTS_EXTENDED_ATTRIBUTES', 'FILE_SUPPORTS_HARD_LINKS', 'FILE_SUPPORTS_OBJECT_IDS', 'FILE_SUPPORTS_OPEN_BY_FILE_ID', 'FILE_SUPPORTS_REPARSE_POINTS', 'FILE_SUPPORTS_SPARSE_FILES', 'FILE_SUPPORTS_TRANSACTIONS', 'FILE_SUPPORTS_USN_JOURNAL', 'FILE_UNICODE_ON_DISK', 'FILE_VOLUME_IS_COMPRESSED', 'FILE_VOLUME_QUOTAS', 'FILE_SUPPORTS_BLOCK_REFCOUNTING']
Create an instance of the type and pass it by reference. It is equivalent to declaring a local variable in C and passing its address, e.g. DWORD flags; and passing as &flags to be an output parameter.
It also help ctypes error checking by declaring the .argtypes and .restype of the function call, which is similar to declaring a C prototype. ctypes.wintypes has many pre-defined types for Windows.
I’ve also added an .errcheck attribute that automatically checks the return value and raises Windows exception based on the GetLastError() code, and an enumeration to process the flags into a readable format:
import ctypes as ct from ctypes import wintypes as w from enum import IntFlag class FSFlags(IntFlag): FILE_CASE_SENSITIVE_SEARCH = 0x00000001 FILE_CASE_PRESERVED_NAMES = 0x00000002 FILE_UNICODE_ON_DISK = 0x00000004 FILE_PERSISTENT_ACLS = 0x00000008 FILE_FILE_COMPRESSION = 0x00000010 FILE_VOLUME_QUOTAS = 0x00000020 FILE_SUPPORTS_SPARSE_FILES = 0x00000040 FILE_SUPPORTS_REPARSE_POINTS = 0x00000080 FILE_VOLUME_IS_COMPRESSED = 0x00008000 FILE_SUPPORTS_OBJECT_IDS = 0x00010000 FILE_SUPPORTS_ENCRYPTION = 0x00020000 FILE_NAMED_STREAMS = 0x00040000 FILE_READ_ONLY_VOLUME = 0x00080000 FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000 FILE_SUPPORTS_TRANSACTIONS = 0x00200000 FILE_SUPPORTS_HARD_LINKS = 0x00400000 FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000 FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 FILE_SUPPORTS_USN_JOURNAL = 0x02000000 FILE_SUPPORTS_BLOCK_REFCOUNTING = 0x08000000 FILE_DAX_VOLUME = 0x20000000 def validate(result,func,args): if not result: raise ct.WinError(ct.get_last_error()) return None dll = ct.WinDLL('kernel32',use_last_error=True) dll.GetVolumeInformationW.argtypes = w.LPCWSTR,w.LPWSTR,w.DWORD,w.LPDWORD,w.LPDWORD,w.LPDWORD,w.LPWSTR,w.DWORD dll.GetVolumeInformationW.restype = w.BOOL dll.GetVolumeInformationW.errcheck = validate volumeNameBuffer = ct.create_unicode_buffer(w.MAX_PATH + 1) fileSystemNameBuffer = ct.create_unicode_buffer(w.MAX_PATH + 1) serial_number = w.DWORD() max_component_length = w.DWORD() file_system_flags = w.DWORD() target_disk = 'c:\\' dll.GetVolumeInformationW(target_disk, volumeNameBuffer, ct.sizeof(volumeNameBuffer), ct.byref(serial_number), ct.byref(max_component_length), ct.byref(file_system_flags), fileSystemNameBuffer, ct.sizeof(fileSystemNameBuffer)) mount_point = target_disk[:-1] disk_label = volumeNameBuffer.value fs_type = fileSystemNameBuffer.value max_length = max_component_length.value flags = FSFlags(file_system_flags.value) serial = serial_number.value print(f'\n\n\n\n\n')
mount_point='c:' disk_label='' fs_type='NTFS' max_length=255 flags= serial=3465270344
For future reference, I’ll leave the complete code here on how to list all disks and get their fstab-like information
import ctypes as ct import string from ctypes import wintypes as w from enum import IntFlag from pathlib import Path class FSFlags(IntFlag): FILE_CASE_SENSITIVE_SEARCH = 0x00000001 FILE_CASE_PRESERVED_NAMES = 0x00000002 FILE_UNICODE_ON_DISK = 0x00000004 FILE_PERSISTENT_ACLS = 0x00000008 FILE_FILE_COMPRESSION = 0x00000010 FILE_VOLUME_QUOTAS = 0x00000020 FILE_SUPPORTS_SPARSE_FILES = 0x00000040 FILE_SUPPORTS_REPARSE_POINTS = 0x00000080 FILE_VOLUME_IS_COMPRESSED = 0x00008000 FILE_SUPPORTS_OBJECT_IDS = 0x00010000 FILE_SUPPORTS_ENCRYPTION = 0x00020000 FILE_NAMED_STREAMS = 0x00040000 FILE_READ_ONLY_VOLUME = 0x00080000 FILE_SEQUENTIAL_WRITE_ONCE = 0x00100000 FILE_SUPPORTS_TRANSACTIONS = 0x00200000 FILE_SUPPORTS_HARD_LINKS = 0x00400000 FILE_SUPPORTS_EXTENDED_ATTRIBUTES = 0x00800000 FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 FILE_SUPPORTS_USN_JOURNAL = 0x02000000 FILE_SUPPORTS_BLOCK_REFCOUNTING = 0x08000000 FILE_DAX_VOLUME = 0x20000000 def validate(result,func,args): if not result: raise ct.WinError(ct.get_last_error()) return None dll = ct.WinDLL('kernel32',use_last_error=True) dll.GetVolumeInformationW.argtypes = w.LPCWSTR,w.LPWSTR,w.DWORD,w.LPDWORD,w.LPDWORD,w.LPDWORD,w.LPWSTR,w.DWORD dll.GetVolumeInformationW.restype = w.BOOL dll.GetVolumeInformationW.errcheck = validate volumeNameBuffer = ct.create_unicode_buffer(w.MAX_PATH + 1) fileSystemNameBuffer = ct.create_unicode_buffer(w.MAX_PATH + 1) serial_number = w.DWORD() max_component_length = w.DWORD() file_system_flags = w.DWORD() lst_available_disks = [f':\\' for d in string.ascii_uppercase if Path(f':\\').exists()] lst_disk_types = ['DRIVE_UNKNOWN', 'DRIVE_NO_ROOT_DIR', 'DRIVE_REMOVABLE', 'DRIVE_FIXED', 'DRIVE_REMOTE', 'DRIVE_CDROM', 'DRIVE_RAMDISK'] for target_disk in lst_available_disks: disk_type_index = dll.GetDriveTypeW(target_disk) dll.GetVolumeInformationW(target_disk, volumeNameBuffer, ct.sizeof(volumeNameBuffer), ct.byref(serial_number), ct.byref(max_component_length), ct.byref(file_system_flags), fileSystemNameBuffer, ct.sizeof(fileSystemNameBuffer)) mount_point = target_disk disk_label = volumeNameBuffer.value fs_type = fileSystemNameBuffer.value max_length = max_component_length.value flags = FSFlags(file_system_flags.value) serial = serial_number.value if 'FILE_READ_ONLY_VOLUME' in str(flags): read_write_status = 'ro' else: read_write_status = 'rw' extra_tab_label = '' if len(disk_label) < 8: extra_tab_label = '\t' extra_tab_type = '' if len(lst_disk_types[disk_type_index]) < 12: extra_tab_type = '\t' print(f'\t\t\t\t\t,\t\n')
Output (Just replaces disk serial with zeros):
Win10 C:\ NTFS 255 0000000000 rw,DRIVE_FIXED flags=D:\ FAT32 255 0000000000 rw,DRIVE_FIXED flags= DRV061107 E:\ CDFS 110 0000000000 ro,DRIVE_CDROM flags= Ventoy F:\ exFAT 255 0000000000 rw,DRIVE_REMOVABLE flags= VTOYEFI G:\ FAT 255 0000000000 rw,DRIVE_REMOVABLE flags=
Hottest 'ctypes' Answers, Teams. Q&A for work. Connect and share knowledge within a single location that is structured and easy to search. Learn more