2192 lines
78 KiB
Plaintext
2192 lines
78 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ Tocsg.Driver }
|
|
{ }
|
|
{ Copyright (C) 2022 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit Tocsg.Driver;
|
|
|
|
interface
|
|
|
|
uses
|
|
Winapi.Windows, EM.winioctl, System.Classes, System.SysUtils, Tocsg.Obj;
|
|
|
|
const
|
|
FAIL_EJECT = '!FAIL';
|
|
METHOD_BUFFERED = 0;
|
|
METHOD_IN_DIRECT = 1;
|
|
METHOD_OUT_DIRECT = 2;
|
|
METHOD_NEITHER = 3;
|
|
|
|
IOCTL_DISK_BASE = FILE_DEVICE_DISK;
|
|
|
|
IOCTL_VOLUME_BASE = DWORD('V');
|
|
{$EXTERNALSYM IOCTL_VOLUME_BASE}
|
|
|
|
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = (
|
|
(IOCTL_VOLUME_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
(0 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS}
|
|
|
|
/////// GPT를 인식하기 위해 추가 2011-02-10 sunk
|
|
IOCTL_DISK_GET_PARTITION_INFO = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
|
|
($0001 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_PARTITION_INFO}
|
|
|
|
IOCTL_DISK_SET_PARTITION_INFO = (
|
|
(IOCTL_DISK_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or
|
|
($0002 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_SET_PARTITION_INFO}
|
|
|
|
IOCTL_DISK_GET_DRIVE_LAYOUT = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
|
|
($0003 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_DRIVE_LAYOUT}
|
|
|
|
IOCTL_DISK_SET_DRIVE_LAYOUT = (
|
|
(IOCTL_DISK_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or
|
|
($0004 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_SET_DRIVE_LAYOUT}
|
|
|
|
IOCTL_VOLUME_IS_CLUSTERED = (
|
|
(IOCTL_VOLUME_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
(12 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_VOLUME_IS_CLUSTERED}
|
|
|
|
IOCTL_DISK_GET_PARTITION_INFO_EX = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0012 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_PARTITION_INFO_EX}
|
|
|
|
IOCTL_DISK_SET_PARTITION_INFO_EX = (
|
|
(IOCTL_DISK_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or
|
|
($0013 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_SET_PARTITION_INFO_EX}
|
|
|
|
IOCTL_DISK_GET_DRIVE_LAYOUT_EX = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0014 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_DRIVE_LAYOUT_EX}
|
|
|
|
IOCTL_DISK_SET_DRIVE_LAYOUT_EX = (
|
|
(IOCTL_DISK_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or
|
|
($0015 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_SET_DRIVE_LAYOUT_EX}
|
|
|
|
IOCTL_STORAGE_GET_DEVICE_NUMBER = (
|
|
(IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0420 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_STORAGE_GET_DEVICE_NUMBER}
|
|
|
|
IOCTL_DISK_GET_LENGTH_INFO = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
|
|
($0017 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_LENGTH_INFO}
|
|
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = (
|
|
(IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0028 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_DISK_GET_DRIVE_GEOMETRY_EX}
|
|
|
|
IOCTL_STORAGE_QUERY_PROPERTY = (
|
|
(IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0500 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_STORAGE_QUERY_PROPERTY}
|
|
|
|
IOCTL_STORAGE_GET_MEDIA_TYPES_EX = (
|
|
(IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0301 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_STORAGE_GET_MEDIA_TYPES_EX}
|
|
|
|
IOCTL_STORAGE_MEDIA_REMOVAL = (
|
|
(IOCTL_STORAGE_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
|
|
($0201 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_STORAGE_MEDIA_REMOVAL}
|
|
|
|
IOCTL_STORAGE_EJECTION_CONTROL = $2D0940;//CTL_CODE(IOCTL_STORAGE_BASE, $0250, METHOD_BUFFERED, FILE_ANY_ACCESS); //$2D0940
|
|
{$EXTERNALSYM IOCTL_STORAGE_EJECTION_CONTROL}
|
|
|
|
IOCTL_STORAGE_EJECT_MEDIA = (
|
|
(IOCTL_STORAGE_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
|
|
($0202 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM IOCTL_STORAGE_EJECT_MEDIA}
|
|
|
|
FSCTL_LOCK_VOLUME = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0006 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_LOCK_VOLUME}
|
|
|
|
FSCTL_UNLOCK_VOLUME = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0007 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_UNLOCK_VOLUME}
|
|
|
|
FSCTL_DISMOUNT_VOLUME = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0008 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_DISMOUNT_VOLUME}
|
|
|
|
FSCTL_IS_VOLUME_MOUNTED = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($000A shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_IS_VOLUME_MOUNTED}
|
|
|
|
FSCTL_FILESYSTEM_GET_STATISTICS = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0018 shl 2) or METHOD_BUFFERED); // FILESYSTEM_STATISTICS
|
|
{$EXTERNALSYM FSCTL_FILESYSTEM_GET_STATISTICS}
|
|
|
|
FSCTL_GET_NTFS_VOLUME_DATA = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0019 shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_GET_NTFS_VOLUME_DATA}
|
|
|
|
FSCTL_GET_NTFS_FILE_RECORD = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($001A shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_GET_NTFS_FILE_RECORD}
|
|
|
|
FSCTL_GET_VOLUME_BITMAP = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($001B shl 2) or METHOD_NEITHER);
|
|
{$EXTERNALSYM FSCTL_GET_VOLUME_BITMAP}
|
|
|
|
FSCTL_GET_RETRIEVAL_POINTERS = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($001C shl 2) or METHOD_NEITHER);
|
|
{$EXTERNALSYM FSCTL_GET_RETRIEVAL_POINTERS}
|
|
|
|
FSCTL_MOVE_FILE = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_SPECIAL_ACCESS shl 14) or
|
|
($001D shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_MOVE_FILE}
|
|
|
|
FSCTL_IS_VOLUME_DIRTY = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($001E shl 2) or METHOD_BUFFERED);
|
|
{$EXTERNALSYM FSCTL_IS_VOLUME_DIRTY}
|
|
|
|
FSCTL_ALLOW_EXTENDED_DASD_IO = (
|
|
(FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or
|
|
($0020 shl 2) or METHOD_NEITHER);
|
|
{$EXTERNALSYM FSCTL_ALLOW_EXTENDED_DASD_IO}
|
|
|
|
GUID_DEVINTERFACE_DISK: TGUID = (
|
|
D1:$53f56307; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_DISK}
|
|
GUID_DEVINTERFACE_CDROM: TGUID = (
|
|
D1:$53f56308; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
// GUID_DEVINTERFACE_CDROM: TGUID = '{53f56308-b6bf-11d0-94f2-00a0c91efb8b}';
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_CDROM}
|
|
GUID_DEVINTERFACE_PARTITION: TGUID = (
|
|
D1:$53f5630a; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_PARTITION}
|
|
GUID_DEVINTERFACE_TAPE: TGUID = (
|
|
D1:$53f5630b; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_TAPE}
|
|
GUID_DEVINTERFACE_WRITEONCEDISK: TGUID = (
|
|
D1:$53f5630c; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_WRITEONCEDISK}
|
|
GUID_DEVINTERFACE_VOLUME: TGUID = (
|
|
D1:$53f5630d; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_VOLUME}
|
|
GUID_DEVINTERFACE_MEDIUMCHANGER: TGUID = (
|
|
D1:$53f56310; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_MEDIUMCHANGER}
|
|
GUID_DEVINTERFACE_FLOPPY: TGUID = (
|
|
D1:$53f56311; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_FLOPPY}
|
|
GUID_DEVINTERFACE_CDCHANGER: TGUID = (
|
|
D1:$53f56312; D2:$b6bf; D3:$11d0; D4:($94, $f2, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_CDCHANGER}
|
|
GUID_DEVINTERFACE_STORAGEPORT: TGUID = (
|
|
D1:$2accfe60; D2:$c130; D3:$11d2; D4:($b0, $82, $00, $a0, $c9, $1e, $fb, $8b));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_STORAGEPORT}
|
|
GUID_DEVINTERFACE_COMPORT: TGUID = (
|
|
D1:$86e0d1e0; D2:$8089; D3:$11d0; D4:($9c, $e4, $08, $00, $3e, $30, $1f, $73));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_COMPORT}
|
|
GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR: TGUID = (
|
|
D1:$4D36E978; D2:$E325; D3:$11CE; D4:($BF, $C1, $08, $00, $2B, $E1, $03, $18));
|
|
{$EXTERNALSYM GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR}
|
|
|
|
GUID_DEVCLASS_NET: TGUID = (
|
|
D1:$4d36e972; D2:$e325; D3:$11ce; D4:($bf, $c1, $08, $00, $2b, $e1, $03, $18));
|
|
{$EXTERNALSYM GUID_DEVCLASS_NET}
|
|
|
|
GUID_DEVCLASS_BLUETOOTH: TGUID = (
|
|
D1:$e0cbf06c; D2:$cd8b; D3:$4647; D4:($bb, $8a, $26, $3b, $43, $f0, $f9, $74));
|
|
{$EXTERNALSYM GUID_DEVCLASS_BLUETOOTH}
|
|
|
|
GUID_DEVCLASS_USB: TGUID = (
|
|
D1:$36fc9e60; D2:$c465; D3:$11cf; D4:($80, $56, $44, $45, $53, $54, $00, $00));
|
|
{$EXTERNALSYM GUID_DEVCLASS_USB}
|
|
|
|
GUID_DEVCLASS_USB_DEVICE: TGUID = (
|
|
D1:$88bae032; D2:$5a81; D3:$49f0; D4:($bc, $3d, $a4, $ff, $13, $82, $16, $d6));
|
|
{$EXTERNALSYM GUID_DEVCLASS_USB}
|
|
|
|
GUID_DEVCLASS_WPD: TGUID = (
|
|
D1:$eec5ad98; D2:$8080; D3:$425f; D4:($92, $2a, $da, $bf, $3d, $e3, $f6, $9a));
|
|
{$EXTERNALSYM GUID_DEVCLASS_WPD}
|
|
|
|
DIGCF_DEFAULT = $00000001;
|
|
DIGCF_PRESENT = $00000002;
|
|
DIGCF_ALLCLASSES = $00000004;
|
|
DIGCF_PROFILE = $00000008;
|
|
DIGCF_DEVICEINTERFACE = $00000010;
|
|
|
|
SPDRP_DEVICEDESC = $00000000; // 설명
|
|
SPDRP_HARDWAREID = $00000001;
|
|
SPDRP_COMPATIBLEIDS = $00000002;
|
|
SPDRP_UNUSED0 = $00000003;
|
|
SPDRP_SERVICE = $00000004;
|
|
SPDRP_UNUSED1 = $00000005;
|
|
SPDRP_UNUSED2 = $00000006;
|
|
SPDRP_CLASS = $00000007;
|
|
SPDRP_CLASSGUID = $00000008;
|
|
SPDRP_DRIVER = $00000009;
|
|
SPDRP_CONFIGFLAGS = $0000000A;
|
|
SPDRP_MFG = $0000000B; // 업체명
|
|
SPDRP_FRIENDLYNAME = $0000000C;
|
|
SPDRP_LOCATION_INFORMATION = $0000000D;
|
|
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = $0000000E;
|
|
SPDRP_CAPABILITIES = $0000000F;
|
|
SPDRP_UI_NUMBER = $00000010;
|
|
SPDRP_UPPERFILTERS = $00000011;
|
|
SPDRP_LOWERFILTERS = $00000012;
|
|
SPDRP_BUSTYPEGUID = $00000013;
|
|
SPDRP_LEGACYBUSTYPE = $00000014;
|
|
SPDRP_BUSNUMBER = $00000015;
|
|
SPDRP_ENUMERATOR_NAME = $00000016;
|
|
SPDRP_SECURITY = $00000017;
|
|
SPDRP_SECURITY_SDS = $00000018;
|
|
SPDRP_DEVTYPE = $00000019;
|
|
SPDRP_EXCLUSIVE = $0000001A;
|
|
SPDRP_CHARACTERISTICS = $0000001B;
|
|
SPDRP_ADDRESS = $0000001C;
|
|
SPDRP_UI_NUMBER_DESC_FORMAT = $0000001D;
|
|
SPDRP_DEVICE_POWER_DATA = $0000001E;
|
|
SPDRP_REMOVAL_POLICY = $0000001F;
|
|
SPDRP_LOCATION_PATHS = $00000023;
|
|
SPDRP_BASE_CONTAINERID = $00000024;
|
|
SPDRP_MAXIMUM_PROPERTY = $00000025;
|
|
|
|
DN_ROOT_ENUMERATED = $00000001; // Was enumerated by ROOT
|
|
DN_DRIVER_LOADED = $00000002; // Has Register_Device_Driver
|
|
DN_ENUM_LOADED = $00000004; // Has Register_Enumerator
|
|
DN_STARTED = $00000008; // Is currently configured
|
|
DN_MANUAL = $00000010; // Manually installed
|
|
DN_NEED_TO_ENUM = $00000020; // May need reenumeration
|
|
DN_NOT_FIRST_TIME = $00000040; // Has received a config
|
|
DN_HARDWARE_ENUM = $00000080; // Enum generates hardware ID
|
|
DN_LIAR = $00000100; // Lied about can reconfig once
|
|
DN_HAS_MARK = $00000200; // Not CM_Create_DevInst lately
|
|
DN_HAS_PROBLEM = $00000400; // Need device installer
|
|
DN_FILTERED = $00000800; // Is filtered
|
|
DN_MOVED = $00001000; // Has been moved
|
|
DN_DISABLEABLE = $00002000; // Can be disabled
|
|
DN_REMOVABLE = $00004000; // Can be removed
|
|
DN_PRIVATE_PROBLEM = $00008000; // Has a private problem
|
|
DN_MF_PARENT = $00010000; // Multi function parent
|
|
DN_MF_CHILD = $00020000; // Multi function child
|
|
DN_WILL_BE_REMOVED = $00040000; // DevInst is being removed
|
|
|
|
CR_SUCCESS = 0;
|
|
CM_PROB_NOT_CONFIGURED = $00000001; // no config for device
|
|
CM_PROB_DEVLOADER_FAILED = $00000002; // service load failed
|
|
CM_PROB_OUT_OF_MEMORY = $00000003; // out of memory
|
|
CM_PROB_ENTRY_IS_WRONG_TYPE = $00000004; //
|
|
CM_PROB_LACKED_ARBITRATOR = $00000005; //
|
|
CM_PROB_BOOT_CONFIG_CONFLICT = $00000006; // boot config conflict
|
|
CM_PROB_FAILED_FILTER = $00000007; //
|
|
CM_PROB_DEVLOADER_NOT_FOUND = $00000008; // Devloader not found
|
|
CM_PROB_INVALID_DATA = $00000009; // Invalid ID
|
|
CM_PROB_FAILED_START = $0000000A; //
|
|
CM_PROB_LIAR = $0000000B; //
|
|
CM_PROB_NORMAL_CONFLICT = $0000000C; // config conflict
|
|
CM_PROB_NOT_VERIFIED = $0000000D; //
|
|
CM_PROB_NEED_RESTART = $0000000E; // requires restart
|
|
CM_PROB_REENUMERATION = $0000000F; //
|
|
CM_PROB_PARTIAL_LOG_CONF = $00000010; //
|
|
CM_PROB_UNKNOWN_RESOURCE = $00000011; // unknown res type
|
|
CM_PROB_REINSTALL = $00000012; //
|
|
CM_PROB_REGISTRY = $00000013; //
|
|
CM_PROB_VXDLDR = $00000014; // WINDOWS 95 ONLY
|
|
CM_PROB_WILL_BE_REMOVED = $00000015; // devinst will remove
|
|
CM_PROB_DISABLED = $00000016; // devinst is disabled
|
|
CM_PROB_DEVLOADER_NOT_READY = $00000017; // Devloader not ready
|
|
CM_PROB_DEVICE_NOT_THERE = $00000018; // device doesn't exist
|
|
CM_PROB_MOVED = $00000019; //
|
|
CM_PROB_TOO_EARLY = $0000001A; //
|
|
CM_PROB_NO_VALID_LOG_CONF = $0000001B; // no valid log config
|
|
CM_PROB_FAILED_INSTALL = $0000001C; // install failed
|
|
CM_PROB_HARDWARE_DISABLED = $0000001D; // device disabled
|
|
CM_PROB_CANT_SHARE_IRQ = $0000001E; // can't share IRQ
|
|
CM_PROB_FAILED_ADD = $0000001F; // driver failed add
|
|
CM_PROB_DISABLED_SERVICE = $00000020; // service's Start = 4
|
|
CM_PROB_TRANSLATION_FAILED = $00000021; // resource translation failed
|
|
CM_PROB_NO_SOFTCONFIG = $00000022; // no soft config
|
|
CM_PROB_BIOS_TABLE = $00000023; // device missing in BIOS table
|
|
CM_PROB_IRQ_TRANSLATION_FAILED = $00000024; // IRQ translator failed
|
|
CM_PROB_FAILED_DRIVER_ENTRY = $00000025; // DriverEntry() failed.
|
|
CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD = $00000026; // Driver should have unloaded.
|
|
CM_PROB_DRIVER_FAILED_LOAD = $00000027; // Driver load unsuccessful.
|
|
CM_PROB_DRIVER_SERVICE_KEY_INVALID = $00000028; // Error accessing driver's service key
|
|
CM_PROB_LEGACY_SERVICE_NO_DEVICES = $00000029; // Loaded legacy service created no devices
|
|
CM_PROB_DUPLICATE_DEVICE = $0000002A; // Two devices were discovered with the same name
|
|
CM_PROB_FAILED_POST_START = $0000002B; // The drivers set the device state to failed
|
|
CM_PROB_HALTED = $0000002C; // This device was failed post start via usermode
|
|
CM_PROB_PHANTOM = $0000002D; // The devinst currently exists only in the registry
|
|
CM_PROB_SYSTEM_SHUTDOWN = $0000002E; // The system is shutting down
|
|
CM_PROB_HELD_FOR_EJECT = $0000002F; // The device is offline awaiting removal
|
|
CM_PROB_DRIVER_BLOCKED = $00000030; // One or more drivers is blocked from loading
|
|
CM_PROB_REGISTRY_TOO_LARGE = $00000031; // System hive has grown too large
|
|
CM_PROB_SETPROPERTIES_FAILED = $00000032; // Failed to apply one or more registry properties
|
|
CM_PROB_WAITING_ON_DEPENDENCY = $00000033; // Device is stalled waiting on a dependency to start
|
|
CM_PROB_UNSIGNED_DRIVER = $00000034; // Failed load driver due to unsigned image.
|
|
CM_PROB_USED_BY_DEBUGGER = $00000035; // Device is being used by kernel debugger
|
|
CM_PROB_DEVICE_RESET = $00000036; // Device is being reset
|
|
CM_PROB_CONSOLE_LOCKED = $00000037; // Device is blocked while console is locked
|
|
CM_PROB_NEED_CLASS_CONFIG = $00000038; // Device needs extended class configuration to start
|
|
CM_PROB_GUEST_ASSIGNMENT_FAILED = $00000039; // Assignment to guest partition failed
|
|
|
|
CM_REMOVE_UI_OK = $00000000;
|
|
CM_REMOVE_UI_NOT_OK = $00000001;
|
|
CM_REMOVE_NO_RESTART = $00000002;
|
|
CM_REMOVE_BITS = $00000003;
|
|
|
|
DIF_SELECTDEVICE = $00000001;
|
|
DIF_INSTALLDEVICE = $00000002;
|
|
DIF_ASSIGNRESOURCES = $00000003;
|
|
DIF_PROPERTIES = $00000004;
|
|
DIF_REMOVE = $00000005;
|
|
DIF_FIRSTTIMESETUP = $00000006;
|
|
DIF_FOUNDDEVICE = $00000007;
|
|
DIF_SELECTCLASSDRIVERS = $00000008;
|
|
DIF_VALIDATECLASSDRIVERS = $00000009;
|
|
DIF_INSTALLCLASSDRIVERS = $0000000A;
|
|
DIF_CALCDISKSPACE = $0000000B;
|
|
DIF_DESTROYPRIVATEDATA = $0000000C;
|
|
DIF_VALIDATEDRIVER = $0000000D;
|
|
DIF_DETECT = $0000000F;
|
|
DIF_INSTALLWIZARD = $00000010;
|
|
DIF_DESTROYWIZARDDATA = $00000011;
|
|
DIF_PROPERTYCHANGE = $00000012;
|
|
DIF_ENABLECLASS = $00000013;
|
|
DIF_DETECTVERIFY = $00000014;
|
|
DIF_INSTALLDEVICEFILES = $00000015;
|
|
DIF_UNREMOVE = $00000016;
|
|
DIF_SELECTBESTCOMPATDRV = $00000017;
|
|
DIF_ALLOW_INSTALL = $00000018;
|
|
DIF_REGISTERDEVICE = $00000019;
|
|
DIF_NEWDEVICEWIZARD_PRESELECT = $0000001A;
|
|
DIF_NEWDEVICEWIZARD_SELECT = $0000001B;
|
|
DIF_NEWDEVICEWIZARD_PREANALYZE = $0000001C;
|
|
DIF_NEWDEVICEWIZARD_POSTANALYZE = $0000001D;
|
|
DIF_NEWDEVICEWIZARD_FINISHINSTALL = $0000001E;
|
|
DIF_UNUSED1 = $0000001F;
|
|
DIF_INSTALLINTERFACES = $00000020;
|
|
DIF_DETECTCANCEL = $00000021;
|
|
DIF_REGISTER_COINSTALLERS = $00000022;
|
|
DIF_ADDPROPERTYPAGE_ADVANCED = $00000023;
|
|
DIF_ADDPROPERTYPAGE_BASIC = $00000024;
|
|
DIF_RESERVED1 = $00000025;
|
|
DIF_TROUBLESHOOTER = $00000026;
|
|
DIF_POWERMESSAGEWAKE = $00000027;
|
|
DIF_ADDREMOTEPROPERTYPAGE_ADVANCED = $00000028;
|
|
DIF_UPDATEDRIVER_UI = $00000029;
|
|
DIF_FINISHINSTALL_ACTION = $0000002A;
|
|
DIF_RESERVED2 = $00000030;
|
|
|
|
DICS_FLAG_GLOBAL = $00000001; // make change in all hardware profiles
|
|
DICS_FLAG_CONFIGSPECIFIC = $00000002; // make change in specified profile only
|
|
DICS_FLAG_CONFIGGENERAL = $00000004; // 1 or more hardware profile-specific
|
|
|
|
DICS_ENABLE = $00000001;
|
|
DICS_DISABLE = $00000002;
|
|
DICS_PROPCHANGE = $00000003;
|
|
DICS_START = $00000004;
|
|
DICS_STOP = $00000005;
|
|
// changes to follow.
|
|
|
|
//
|
|
// Support for GUID Partition Table (GPT) disks.
|
|
//
|
|
|
|
//
|
|
// There are currently two ways a disk can be partitioned. With a traditional
|
|
// AT-style master boot record (PARTITION_STYLE_MBR) and with a new, GPT
|
|
// partition table (PARTITION_STYLE_GPT). RAW is for an unrecognizable
|
|
// partition style. There are a very limited number of things you can
|
|
// do with a RAW partititon.
|
|
//
|
|
|
|
type
|
|
GUID = TGUID;
|
|
{$NODEFINE GUID}
|
|
LPGUID = ^GUID;
|
|
{$NODEFINE LPGUID}
|
|
CLSID = TGUID;
|
|
{$NODEFINE CLSID}
|
|
|
|
ULONG64 = Int64;
|
|
{$EXTERNALSYM ULONG64}
|
|
PULONG64 = ^ULONG64;
|
|
{$EXTERNALSYM PULONG64}
|
|
DWORD64 = Int64;
|
|
{$EXTERNALSYM DWORD64}
|
|
PDWORD64 = ^DWORD64;
|
|
{$EXTERNALSYM PDWORD64}
|
|
UINT64 = Int64;
|
|
{$EXTERNALSYM UINT64}
|
|
PUINT64 = ^UINT64;
|
|
{$EXTERNALSYM PUINT64}
|
|
|
|
PPREVENT_MEDIA_REMOVAL = ^PREVENT_MEDIA_REMOVAL;
|
|
{$EXTERNALSYM PPREVENT_MEDIA_REMOVAL}
|
|
_PREVENT_MEDIA_REMOVAL = record
|
|
PreventMediaRemoval: ByteBool;
|
|
end;
|
|
{$EXTERNALSYM _PREVENT_MEDIA_REMOVAL}
|
|
PREVENT_MEDIA_REMOVAL = _PREVENT_MEDIA_REMOVAL;
|
|
{$EXTERNALSYM PREVENT_MEDIA_REMOVAL}
|
|
TPreventMediaRemoval = PREVENT_MEDIA_REMOVAL;
|
|
PPreventMediaRemoval = PPREVENT_MEDIA_REMOVAL;
|
|
|
|
PSTORAGE_DEVICE_NUMBER = ^STORAGE_DEVICE_NUMBER;
|
|
{$EXTERNALSYM PSTORAGE_DEVICE_NUMBER}
|
|
_STORAGE_DEVICE_NUMBER = record
|
|
//
|
|
// The FILE_DEVICE_XXX type for this device.
|
|
//
|
|
DeviceType: DEVICE_TYPE;
|
|
//
|
|
// The number of this device
|
|
//
|
|
DeviceNumber: DWORD;
|
|
//
|
|
// If the device is partitionable, the partition number of the device.
|
|
// Otherwise -1
|
|
//
|
|
PartitionNumber: DWORD;
|
|
end;
|
|
{$EXTERNALSYM _STORAGE_DEVICE_NUMBER}
|
|
STORAGE_DEVICE_NUMBER = _STORAGE_DEVICE_NUMBER;
|
|
{$EXTERNALSYM STORAGE_DEVICE_NUMBER}
|
|
TStorageDeviceNumber = STORAGE_DEVICE_NUMBER;
|
|
PStorageDeviceNumber = PSTORAGE_DEVICE_NUMBER;
|
|
|
|
|
|
_PARTITION_STYLE = (
|
|
PARTITION_STYLE_MBR,
|
|
PARTITION_STYLE_GPT,
|
|
PARTITION_STYLE_RAW);
|
|
{$EXTERNALSYM _PARTITION_STYLE}
|
|
PARTITION_STYLE = _PARTITION_STYLE;
|
|
{$EXTERNALSYM PARTITION_STYLE}
|
|
TPartitionStyle = PARTITION_STYLE;
|
|
|
|
//
|
|
// The following structure defines information in a GPT partition that is
|
|
// not common to both GPT and MBR partitions.
|
|
//
|
|
|
|
PPARTITION_INFORMATION_GPT = ^PARTITION_INFORMATION_GPT;
|
|
{$EXTERNALSYM PPARTITION_INFORMATION_GPT}
|
|
_PARTITION_INFORMATION_GPT = record
|
|
PartitionType: GUID; // Partition type. See table 16-3.
|
|
PartitionId: GUID; // Unique GUID for this partition.
|
|
Attributes: DWORD64; // See table 16-4.
|
|
Name: array [0..35] of WCHAR; // Partition Name in Unicode.
|
|
end;
|
|
{$EXTERNALSYM _PARTITION_INFORMATION_GPT}
|
|
PARTITION_INFORMATION_GPT = _PARTITION_INFORMATION_GPT;
|
|
{$EXTERNALSYM PARTITION_INFORMATION_GPT}
|
|
TPartitionInformationGpt = PARTITION_INFORMATION_GPT;
|
|
PPartitionInformationGpt = PPARTITION_INFORMATION_GPT;
|
|
|
|
|
|
{
|
|
_PREVENT_MEDIA_REMOVAL = record
|
|
PreventMediaRemoval : Boolean;
|
|
end;
|
|
PREVENT_MEDIA_REMOVAL = _PREVENT_MEDIA_REMOVAL;
|
|
}
|
|
|
|
//
|
|
// The following are GPT partition attributes applicable for any
|
|
// partition type. These attributes are not OS-specific
|
|
//
|
|
|
|
const
|
|
GPT_ATTRIBUTE_PLATFORM_REQUIRED = $0000000000000001;
|
|
{$EXTERNALSYM GPT_ATTRIBUTE_PLATFORM_REQUIRED}
|
|
|
|
//
|
|
// The following are GPT partition attributes applicable when the
|
|
// PartitionType is PARTITION_BASIC_DATA_GUID.
|
|
//
|
|
|
|
GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER = DWORD($8000000000000000);
|
|
{$EXTERNALSYM GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER}
|
|
GPT_BASIC_DATA_ATTRIBUTE_HIDDEN = $4000000000000000;
|
|
{$EXTERNALSYM GPT_BASIC_DATA_ATTRIBUTE_HIDDEN}
|
|
GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY = $1000000000000000;
|
|
{$EXTERNALSYM GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY}
|
|
|
|
//
|
|
// The following structure defines information in an MBR partition that is not
|
|
// common to both GPT and MBR partitions.
|
|
//
|
|
|
|
type
|
|
PPARTITION_INFORMATION_MBR = ^PARTITION_INFORMATION_MBR;
|
|
{$EXTERNALSYM PPARTITION_INFORMATION_MBR}
|
|
_PARTITION_INFORMATION_MBR = record
|
|
PartitionType: BYTE;
|
|
BootIndicator: BOOLEAN;
|
|
RecognizedPartition: BOOLEAN;
|
|
HiddenSectors: DWORD;
|
|
end;
|
|
{$EXTERNALSYM _PARTITION_INFORMATION_MBR}
|
|
PARTITION_INFORMATION_MBR = _PARTITION_INFORMATION_MBR;
|
|
{$EXTERNALSYM PARTITION_INFORMATION_MBR}
|
|
TPartitionInformationMbr = PARTITION_INFORMATION_MBR;
|
|
PPartitionInformationMbr = PPARTITION_INFORMATION_MBR;
|
|
|
|
//
|
|
// The structure SET_PARTITION_INFO_EX is used with the ioctl
|
|
// IOCTL_SET_PARTITION_INFO_EX to set information about a specific
|
|
// partition. Note that for MBR partitions, you can only set the partition
|
|
// signature, whereas GPT partitions allow setting of all fields that
|
|
// you can get.
|
|
//
|
|
|
|
SET_PARTITION_INFORMATION_MBR = SET_PARTITION_INFORMATION;
|
|
{$EXTERNALSYM SET_PARTITION_INFORMATION_MBR}
|
|
TSetPartitionInformationMbr = SET_PARTITION_INFORMATION_MBR;
|
|
SET_PARTITION_INFORMATION_GPT = PARTITION_INFORMATION_GPT;
|
|
{$EXTERNALSYM SET_PARTITION_INFORMATION_GPT}
|
|
TSetPartitionInformationGpt = SET_PARTITION_INFORMATION_GPT;
|
|
|
|
PSET_PARTITION_INFORMATION_EX = ^SET_PARTITION_INFORMATION_EX;
|
|
{$EXTERNALSYM PSET_PARTITION_INFORMATION_EX}
|
|
_SET_PARTITION_INFORMATION_EX = record
|
|
PartitionStyle: PARTITION_STYLE;
|
|
case Integer of
|
|
0: (Mbr: SET_PARTITION_INFORMATION_MBR);
|
|
1: (Gpt: SET_PARTITION_INFORMATION_GPT);
|
|
end;
|
|
{$EXTERNALSYM _SET_PARTITION_INFORMATION_EX}
|
|
SET_PARTITION_INFORMATION_EX = _SET_PARTITION_INFORMATION_EX;
|
|
{$EXTERNALSYM SET_PARTITION_INFORMATION_EX}
|
|
TSetPartitionInformationEx = SET_PARTITION_INFORMATION_EX;
|
|
PSetPartitionInformationEx = PSET_PARTITION_INFORMATION_EX;
|
|
|
|
//
|
|
// The structure CREATE_DISK_GPT with the ioctl IOCTL_DISK_CREATE_DISK
|
|
// to initialize an virgin disk with an empty GPT partition table.
|
|
//
|
|
|
|
PCREATE_DISK_GPT = ^CREATE_DISK_GPT;
|
|
{$EXTERNALSYM PCREATE_DISK_GPT}
|
|
_CREATE_DISK_GPT = record
|
|
DiskId: GUID; // Unique disk id for the disk.
|
|
MaxPartitionCount: DWORD; // Maximim number of partitions allowable.
|
|
end;
|
|
{$EXTERNALSYM _CREATE_DISK_GPT}
|
|
CREATE_DISK_GPT = _CREATE_DISK_GPT;
|
|
{$EXTERNALSYM CREATE_DISK_GPT}
|
|
TCreateDiskGpt = CREATE_DISK_GPT;
|
|
PCreateDiskGpt = PCREATE_DISK_GPT;
|
|
|
|
//
|
|
// The structure CREATE_DISK_MBR with the ioctl IOCTL_DISK_CREATE_DISK
|
|
// to initialize an virgin disk with an empty MBR partition table.
|
|
//
|
|
|
|
PCREATE_DISK_MBR = ^CREATE_DISK_MBR;
|
|
{$EXTERNALSYM PCREATE_DISK_MBR}
|
|
_CREATE_DISK_MBR = record
|
|
Signature: DWORD;
|
|
end;
|
|
{$EXTERNALSYM _CREATE_DISK_MBR}
|
|
CREATE_DISK_MBR = _CREATE_DISK_MBR;
|
|
{$EXTERNALSYM CREATE_DISK_MBR}
|
|
TCreateDiskMbr = CREATE_DISK_MBR;
|
|
PCreateDiskMbr = PCREATE_DISK_MBR;
|
|
|
|
PCREATE_DISK = ^CREATE_DISK;
|
|
{$EXTERNALSYM PCREATE_DISK}
|
|
_CREATE_DISK = record
|
|
PartitionStyle: PARTITION_STYLE;
|
|
case Integer of
|
|
0: (Mbr: CREATE_DISK_MBR);
|
|
1: (Gpt: CREATE_DISK_GPT);
|
|
end;
|
|
{$EXTERNALSYM _CREATE_DISK}
|
|
CREATE_DISK = _CREATE_DISK;
|
|
{$EXTERNALSYM CREATE_DISK}
|
|
TCreateDisk = CREATE_DISK;
|
|
PCreateDisk = PCREATE_DISK;
|
|
|
|
//
|
|
// The structure GET_LENGTH_INFORMATION is used with the ioctl
|
|
// IOCTL_DISK_GET_LENGTH_INFO to obtain the length, in bytes, of the
|
|
// disk, partition, or volume.
|
|
//
|
|
|
|
PGET_LENGTH_INFORMATION = ^GET_LENGTH_INFORMATION;
|
|
{$EXTERNALSYM PGET_LENGTH_INFORMATION}
|
|
_GET_LENGTH_INFORMATION = record
|
|
Length: LARGE_INTEGER;
|
|
end;
|
|
{$EXTERNALSYM _GET_LENGTH_INFORMATION}
|
|
GET_LENGTH_INFORMATION = _GET_LENGTH_INFORMATION;
|
|
{$EXTERNALSYM GET_LENGTH_INFORMATION}
|
|
TGetLengthInformation = GET_LENGTH_INFORMATION;
|
|
PGetLengthInformation = PGET_LENGTH_INFORMATION;
|
|
|
|
//
|
|
// The PARTITION_INFORMATION_EX structure is used with the
|
|
// IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
|
|
// IOCTL_DISK_GET_PARTITION_INFO_EX and IOCTL_DISK_GET_PARTITION_INFO_EX calls.
|
|
//
|
|
|
|
PPARTITION_INFORMATION_EX = ^PARTITION_INFORMATION_EX;
|
|
{$EXTERNALSYM PPARTITION_INFORMATION_EX}
|
|
_PARTITION_INFORMATION_EX = record
|
|
PartitionStyle: PARTITION_STYLE;
|
|
StartingOffset: LARGE_INTEGER;
|
|
PartitionLength: LARGE_INTEGER;
|
|
PartitionNumber: DWORD;
|
|
RewritePartition: BOOLEAN;
|
|
case Integer of
|
|
0: (Mbr: PARTITION_INFORMATION_MBR);
|
|
1: (Gpt: PARTITION_INFORMATION_GPT);
|
|
end;
|
|
{$EXTERNALSYM _PARTITION_INFORMATION_EX}
|
|
PARTITION_INFORMATION_EX = _PARTITION_INFORMATION_EX;
|
|
{$EXTERNALSYM PARTITION_INFORMATION_EX}
|
|
TPartitionInformationEx = PARTITION_INFORMATION_EX;
|
|
PPartitionInformationEx = PPARTITION_INFORMATION_EX;
|
|
|
|
//
|
|
// GPT specific drive layout information.
|
|
//
|
|
|
|
PDRIVE_LAYOUT_INFORMATION_GPT = ^DRIVE_LAYOUT_INFORMATION_GPT;
|
|
{$EXTERNALSYM PDRIVE_LAYOUT_INFORMATION_GPT}
|
|
_DRIVE_LAYOUT_INFORMATION_GPT = record
|
|
DiskId: GUID;
|
|
StartingUsableOffset: LARGE_INTEGER;
|
|
UsableLength: LARGE_INTEGER;
|
|
MaxPartitionCount: DWORD;
|
|
end;
|
|
{$EXTERNALSYM _DRIVE_LAYOUT_INFORMATION_GPT}
|
|
DRIVE_LAYOUT_INFORMATION_GPT = _DRIVE_LAYOUT_INFORMATION_GPT;
|
|
{$EXTERNALSYM DRIVE_LAYOUT_INFORMATION_GPT}
|
|
TDriveLayoutInformationGpt = DRIVE_LAYOUT_INFORMATION_GPT;
|
|
PDriveLayoutInformationGpt = PDRIVE_LAYOUT_INFORMATION_GPT;
|
|
|
|
//
|
|
// MBR specific drive layout information.
|
|
//
|
|
|
|
PDRIVE_LAYOUT_INFORMATION_MBR = ^DRIVE_LAYOUT_INFORMATION_MBR;
|
|
{$EXTERNALSYM PDRIVE_LAYOUT_INFORMATION_MBR}
|
|
_DRIVE_LAYOUT_INFORMATION_MBR = record
|
|
Signature: DWORD;
|
|
end;
|
|
{$EXTERNALSYM _DRIVE_LAYOUT_INFORMATION_MBR}
|
|
DRIVE_LAYOUT_INFORMATION_MBR = _DRIVE_LAYOUT_INFORMATION_MBR;
|
|
{$EXTERNALSYM DRIVE_LAYOUT_INFORMATION_MBR}
|
|
TDriveLayoutInformationMbr = DRIVE_LAYOUT_INFORMATION_MBR;
|
|
PDriveLayoutInformationMbr = PDRIVE_LAYOUT_INFORMATION_MBR;
|
|
|
|
//
|
|
// The structure DRIVE_LAYOUT_INFORMATION_EX is used with the
|
|
// IOCTL_SET_DRIVE_LAYOUT_EX and IOCTL_GET_DRIVE_LAYOUT_EX calls.
|
|
//
|
|
|
|
PDRIVE_LAYOUT_INFORMATION_EX = ^DRIVE_LAYOUT_INFORMATION_EX;
|
|
{$EXTERNALSYM PDRIVE_LAYOUT_INFORMATION_EX}
|
|
_DRIVE_LAYOUT_INFORMATION_EX = record
|
|
PartitionStyle: DWORD;
|
|
PartitionCount: DWORD;
|
|
Union: record
|
|
case Integer of
|
|
0: (Mbr: DRIVE_LAYOUT_INFORMATION_MBR);
|
|
1: (Gpt: DRIVE_LAYOUT_INFORMATION_GPT);
|
|
end;
|
|
PartitionEntry: array [0..0] of PARTITION_INFORMATION_EX;
|
|
end;
|
|
{$EXTERNALSYM _DRIVE_LAYOUT_INFORMATION_EX}
|
|
DRIVE_LAYOUT_INFORMATION_EX = _DRIVE_LAYOUT_INFORMATION_EX;
|
|
{$EXTERNALSYM DRIVE_LAYOUT_INFORMATION_EX}
|
|
TDriveLayoutInformationEx = DRIVE_LAYOUT_INFORMATION_EX;
|
|
PDriveLayoutInformationEx = PDRIVE_LAYOUT_INFORMATION_EX;
|
|
/////// GPT를 인식하기 위해 추가 2011-02-10 sunk
|
|
|
|
// 파일 클러스터 관련 -----------------------------------------------------
|
|
type
|
|
//
|
|
// Structure for FSCTL_GET_VOLUME_BITMAP
|
|
//
|
|
|
|
PSTARTING_LCN_INPUT_BUFFER = ^STARTING_LCN_INPUT_BUFFER;
|
|
{$EXTERNALSYM PSTARTING_LCN_INPUT_BUFFER}
|
|
STARTING_LCN_INPUT_BUFFER = record
|
|
StartingLcn: LARGE_INTEGER;
|
|
end;
|
|
{$EXTERNALSYM STARTING_LCN_INPUT_BUFFER}
|
|
TStartingLcnInputBuffer = STARTING_LCN_INPUT_BUFFER;
|
|
PStartingLcnInputBuffer = PSTARTING_LCN_INPUT_BUFFER;
|
|
|
|
PVOLUME_BITMAP_BUFFER = ^VOLUME_BITMAP_BUFFER;
|
|
{$EXTERNALSYM PVOLUME_BITMAP_BUFFER}
|
|
VOLUME_BITMAP_BUFFER = record
|
|
StartingLcn: LARGE_INTEGER;
|
|
BitmapSize: LARGE_INTEGER;
|
|
Buffer: array [0..0] of BYTE;
|
|
end;
|
|
{$EXTERNALSYM VOLUME_BITMAP_BUFFER}
|
|
TVolumeBitmapBuffer = VOLUME_BITMAP_BUFFER;
|
|
PVolumeBitmapBuffer = PVOLUME_BITMAP_BUFFER;
|
|
|
|
//
|
|
// Structure for FSCTL_GET_RETRIEVAL_POINTERS
|
|
//
|
|
|
|
PSTARTING_VCN_INPUT_BUFFER = ^STARTING_VCN_INPUT_BUFFER;
|
|
{$EXTERNALSYM PSTARTING_VCN_INPUT_BUFFER}
|
|
STARTING_VCN_INPUT_BUFFER = record
|
|
StartingVcn: LARGE_INTEGER;
|
|
end;
|
|
{$EXTERNALSYM STARTING_VCN_INPUT_BUFFER}
|
|
TStartingVcnInputBuffer = STARTING_VCN_INPUT_BUFFER;
|
|
PStartingVcnInputBuffer = PSTARTING_VCN_INPUT_BUFFER;
|
|
|
|
TRPBExtends = record
|
|
NextVcn: LARGE_INTEGER;
|
|
Lcn: LARGE_INTEGER;
|
|
end;
|
|
|
|
PRETRIEVAL_POINTERS_BUFFER = ^RETRIEVAL_POINTERS_BUFFER;
|
|
{$EXTERNALSYM PRETRIEVAL_POINTERS_BUFFER}
|
|
RETRIEVAL_POINTERS_BUFFER = record
|
|
ExtentCount: DWORD;
|
|
StartingVcn: LARGE_INTEGER;
|
|
Extends: array [0..0] of TRPBExtends;
|
|
end;
|
|
{$EXTERNALSYM RETRIEVAL_POINTERS_BUFFER}
|
|
TRetrievalPointersBuffer = RETRIEVAL_POINTERS_BUFFER;
|
|
PRetrievalPointersBuffer = PRETRIEVAL_POINTERS_BUFFER;
|
|
|
|
//
|
|
// Structures for FSCTL_GET_NTFS_FILE_RECORD
|
|
//
|
|
|
|
PNTFS_FILE_RECORD_INPUT_BUFFER = ^NTFS_FILE_RECORD_INPUT_BUFFER;
|
|
{$EXTERNALSYM PNTFS_FILE_RECORD_INPUT_BUFFER}
|
|
NTFS_FILE_RECORD_INPUT_BUFFER = record
|
|
FileReferenceNumber: LARGE_INTEGER;
|
|
end;
|
|
{$EXTERNALSYM NTFS_FILE_RECORD_INPUT_BUFFER}
|
|
TNtfsFileRecordInputBuffer = NTFS_FILE_RECORD_INPUT_BUFFER;
|
|
PNtfsFileRecordInputBuffer = PNTFS_FILE_RECORD_INPUT_BUFFER;
|
|
|
|
PNTFS_FILE_RECORD_OUTPUT_BUFFER = ^NTFS_FILE_RECORD_OUTPUT_BUFFER;
|
|
{$EXTERNALSYM PNTFS_FILE_RECORD_OUTPUT_BUFFER}
|
|
NTFS_FILE_RECORD_OUTPUT_BUFFER = record
|
|
FileReferenceNumber: LARGE_INTEGER;
|
|
FileRecordLength: DWORD;
|
|
FileRecordBuffer: array [0..0] of BYTE;
|
|
end;
|
|
{$EXTERNALSYM NTFS_FILE_RECORD_OUTPUT_BUFFER}
|
|
TNtfsFileRecordOutputBuffer = NTFS_FILE_RECORD_OUTPUT_BUFFER;
|
|
PNtfsFileRecordOutputBuffer = PNTFS_FILE_RECORD_OUTPUT_BUFFER;
|
|
|
|
//
|
|
// Structure for FSCTL_MOVE_FILE
|
|
//
|
|
|
|
PMOVE_FILE_DATA = ^MOVE_FILE_DATA;
|
|
{$EXTERNALSYM PMOVE_FILE_DATA}
|
|
MOVE_FILE_DATA = record
|
|
FileHandle: THandle;
|
|
StartingVcn: LARGE_INTEGER;
|
|
StartingLcn: LARGE_INTEGER;
|
|
ClusterCount: DWORD;
|
|
end;
|
|
{$EXTERNALSYM MOVE_FILE_DATA}
|
|
TMoveFileData = MOVE_FILE_DATA;
|
|
PMoveFileData = PMOVE_FILE_DATA;
|
|
|
|
|
|
// 추가 22_0616 16:13:02 kku ---------------------------------------------------
|
|
PHDEVINFO = ^HDEVINFO;
|
|
HDEVINFO = THandle;
|
|
PCONFIGRET = ^CONFIGRET;
|
|
CONFIGRET = DWORD;
|
|
PDEVINST = ^DEVINST;
|
|
DEVINST = DWORD;
|
|
PPNP_VETO_TYPE = ^PNP_VETO_TYPE;
|
|
PNP_VETO_TYPE = DWORD;
|
|
HMACHINE = THandle;
|
|
|
|
PSPDeviceInterfaceData = ^TSPDeviceInterfaceData;
|
|
// 64bit에서는 packed 처리하면 안된다.. 22_0616 23:18:35 kku
|
|
SP_DEVICE_INTERFACE_DATA = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
cbSize : DWORD;
|
|
InterfaceClassGuid : TGUID;
|
|
Flags : DWORD;
|
|
Reserved : ULONG_PTR;
|
|
end;
|
|
TSPDeviceInterfaceData = SP_DEVICE_INTERFACE_DATA;
|
|
|
|
PSPDeviceInterfaceDetailDataA = ^TSPDeviceInterfaceDetailDataA;
|
|
PSPDeviceInterfaceDetailDataW = ^TSPDeviceInterfaceDetailDataW;
|
|
SP_DEVICE_INTERFACE_DETAIL_DATA_A = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
cbSize : DWORD;
|
|
DevicePath : array [0..0] of AnsiChar;
|
|
end;
|
|
SP_DEVICE_INTERFACE_DETAIL_DATA_W = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
cbSize : DWORD;
|
|
DevicePath : array [0..0] of WideChar;
|
|
end;
|
|
|
|
TSPDeviceInterfaceDetailDataA = SP_DEVICE_INTERFACE_DETAIL_DATA_A;
|
|
TSPDeviceInterfaceDetailDataW = SP_DEVICE_INTERFACE_DETAIL_DATA_W;
|
|
TSPDeviceInterfaceDetailData = TSPDeviceInterfaceDetailDataW;
|
|
PSPDeviceInterfaceDetailData = ^TSPDeviceInterfaceDetailDataW;
|
|
|
|
PSPDevInfoData = ^TSPDevInfoData;
|
|
SP_DEVINFO_DATA = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
cbSize : DWORD;
|
|
ClassGuid : TGUID;
|
|
DevInst : DWORD;
|
|
Reserved : ULONG_PTR;
|
|
end;
|
|
TSPDevInfoData = SP_DEVINFO_DATA;
|
|
|
|
DI_FUNCTION = UINT;
|
|
PSPClassInstallHeader = ^TSPClassInstallHeader;
|
|
SP_CLASSINSTALL_HEADER = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
cbSize: DWORD;
|
|
InstallFunction: DI_FUNCTION;
|
|
end;
|
|
TSPClassInstallHeader = SP_CLASSINSTALL_HEADER;
|
|
|
|
PSPPropChangeParams = ^TSPPropChangeParams;
|
|
SP_PROPCHANGE_PARAMS = {$IFNDEF WIN64} packed {$ENDIF} record
|
|
ClassInstallHeader: TSPClassInstallHeader;
|
|
StateChange: DWORD;
|
|
Scope: DWORD;
|
|
HwProfile: DWORD;
|
|
end;
|
|
TSPPropChangeParams = SP_PROPCHANGE_PARAMS;
|
|
|
|
function SetupDiGetClassDevsW(ClassGuid: PGUID; const Enumerator: PWideChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external 'SetupApi.dll' name 'SetupDiGetClassDevsW';
|
|
function SetupDiGetClassDevsA(ClassGuid: PGUID; const Enumerator: PAnsiChar; hwndParent:HWND; Flags: DWORD): HDEVINFO; stdcall; external 'SetupApi.dll' name 'SetupDiGetClassDevsA';
|
|
function SetupDiGetClassDevs(ClassGuid: PGUID; const Enumerator: PChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external 'SetupApi.dll' name 'SetupDiGetClassDevsW';
|
|
|
|
function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO;
|
|
MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiEnumDeviceInfo';
|
|
|
|
function SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet: HDEVINFO;
|
|
const DeviceInfoData: TSPDevInfoData; Property_: DWORD;
|
|
var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD;
|
|
var RequiredSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceRegistryPropertyA';
|
|
function SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet: HDEVINFO;
|
|
const DeviceInfoData: TSPDevInfoData; Property_: DWORD;
|
|
var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD;
|
|
var RequiredSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceRegistryPropertyW';
|
|
function SetupDiGetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO;
|
|
const DeviceInfoData: TSPDevInfoData; Property_: DWORD;
|
|
var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD;
|
|
var RequiredSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceRegistryPropertyW';
|
|
|
|
function SetupDiSetClassInstallParamsA(DeviceInfoSet: HDEVINFO;
|
|
DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader;
|
|
ClassInstallParamsSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiSetClassInstallParamsA';
|
|
function SetupDiSetClassInstallParamsW(DeviceInfoSet: HDEVINFO;
|
|
DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader;
|
|
ClassInstallParamsSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiSetClassInstallParamsW';
|
|
function SetupDiSetClassInstallParams(DeviceInfoSet: HDEVINFO;
|
|
DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader;
|
|
ClassInstallParamsSize: DWORD): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiSetClassInstallParamsW';
|
|
|
|
function SetupDiCallClassInstaller(InstallFunction: DI_FUNCTION;
|
|
DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData): LongBool; stdcall; external 'SetupApi.dll' name 'SetupDiCallClassInstaller';
|
|
|
|
function SetupDiEnumDeviceInterfaces(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData;
|
|
const InterfaceClassGuid: TGUID; MemberIndex: DWORD; var DeviceInterfaceData: TSPDeviceInterfaceData): BOOL; stdcall; external 'SetupApi.dll';
|
|
|
|
function SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet: HDEVINFO; DeviceInterfaceData: PSPDeviceInterfaceData;
|
|
DeviceInterfaceDetailData: PSPDeviceInterfaceDetailData; DeviceInterfaceDetailDataSize: DWORD;
|
|
var RequiredSize: DWORD; Device: PSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailW';
|
|
function SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet: HDEVINFO; DeviceInterfaceData: PSPDeviceInterfaceData;
|
|
DeviceInterfaceDetailData: PSPDeviceInterfaceDetailDataA; DeviceInterfaceDetailDataSize: DWORD;
|
|
var RequiredSize: DWORD; Device: PSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailA';
|
|
function SetupDiGetDeviceInterfaceDetail(DeviceInfoSet: HDEVINFO; DeviceInterfaceData: PSPDeviceInterfaceData;
|
|
DeviceInterfaceDetailData: PSPDeviceInterfaceDetailData; DeviceInterfaceDetailDataSize: DWORD;
|
|
var RequiredSize: DWORD; Device: PSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiGetDeviceInterfaceDetailW';
|
|
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiDestroyDeviceInfoList';
|
|
|
|
function SetupDiGetDeviceInstanceId(
|
|
DeviceInfoSet: HDEVINFO;
|
|
const DeviceInfoData: SP_DEVINFO_DATA;
|
|
DeviceInstanceId: PWideChar;
|
|
DeviceInstanceIdSize: DWORD;
|
|
var RequiredSize: DWORD
|
|
): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceInstanceIdW';
|
|
|
|
function SetupDiRemoveDevice(DeviceInfoSet: HDEVINFO; var DeviceInfoData: TSPDevInfoData): BOOL; stdcall; external 'SetupApi.dll' name 'SetupDiRemoveDevice';
|
|
|
|
function CM_Get_Parent(var dnDevInstParent: DEVINST; dnDevInst: DEVINST; ulFlags: ULONG): CONFIGRET; stdcall; external 'CfgMgr32.dll';
|
|
function CM_Query_And_Remove_SubTreeW(dnAncestor: DEVINST; pVetoType: PPNP_VETO_TYPE; pszVetoName: PWideChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTreeW';
|
|
function CM_Query_And_Remove_SubTreeA(dnAncestor: DEVINST;pVetoType: PPNP_VETO_TYPE; pszVetoName: PAnsiChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTreeA';
|
|
function CM_Query_And_Remove_SubTree(dnAncestor: DEVINST;pVetoType: PPNP_VETO_TYPE; pszVetoName: PChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Query_And_Remove_SubTreeW';
|
|
function CM_Request_Device_EjectW(dnDevInst: DEVINST; pVetoType: PPNP_VETO_TYPE; pszVetoName: PWideChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Request_Device_EjectW';
|
|
function CM_Request_Device_EjectA(dnDevInst: DEVINST; pVetoType: PPNP_VETO_TYPE; pszVetoName: PAnsiChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Request_Device_EjectA';
|
|
function CM_Request_Device_Eject(dnDevInst: DEVINST; pVetoType: PPNP_VETO_TYPE; pszVetoName: PChar;
|
|
ulNameLength: ULONG; ulFlags: ULONG):CONFIGRET; stdcall; external 'SetupApi.dll' name 'CM_Request_Device_EjectW';
|
|
|
|
function CM_Get_Device_IDA(dnDevInst: DEVINST; Buffer: PAnsiChar;
|
|
BufferLen: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Get_Device_IDA';
|
|
function CM_Get_Device_IDW(dnDevInst: DEVINST; Buffer: PWideChar;
|
|
BufferLen: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Get_Device_IDW';
|
|
function CM_Get_Device_ID(dnDevInst: DEVINST; Buffer: PChar;
|
|
BufferLen: ULONG; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Get_Device_IDW';
|
|
|
|
function CM_Get_DevNode_Status(var ulStatus: ULONG; var ulProblemNumber: ULONG;
|
|
dnDevInst: DEVINST; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Get_DevNode_Status';
|
|
function CM_Get_DevNode_Status_Ex(var ulStatus: ULONG; var ulProblemNumber: ULONG;
|
|
dnDevInst: DEVINST; ulFlags: ULONG; hMachine: HMACHINE): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Get_DevNode_Status_Ex';
|
|
|
|
// 추가 22_0616 16:13:02 kku ---------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------
|
|
function CTL_CODE(const dwDeviceType, dwFunc, dwMethod, dwAccess: DWORD): DWORD;
|
|
function ConvSerialToStr(sSerNum: AnsiString): AnsiString;
|
|
|
|
|
|
type
|
|
TTgDriver = class(TTgObject)
|
|
protected
|
|
sDeviceName_: String;
|
|
hDevice_: THandle;
|
|
|
|
function GetDeviceHandle: THandle; virtual;
|
|
public
|
|
Constructor Create; virtual;
|
|
Destructor Destroy; override;
|
|
|
|
function OpenDevice(const sDeviceName: String;
|
|
dwDesireAccess: DWORD = GENERIC_READ or GENERIC_WRITE;
|
|
dwShareMode: DWORD = FILE_SHARE_READ or FILE_SHARE_WRITE;
|
|
dwFlagsAndAttributes: DWORD = 0): Integer; virtual;
|
|
function CloseDevice: Boolean; virtual;
|
|
|
|
function ReadIO(dwCode: DWORD; pBuf: Pointer;
|
|
dwSize: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
function WriteIO(dwCode: DWORD; pBuf: Pointer;
|
|
dwSize: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
function ReadWriteIO(dwCode: DWORD; pInBuf: Pointer; dwInSize: DWORD;
|
|
pOutBuf: Pointer; dwOutSize: DWORD;
|
|
pdwByteReturn: PDWORD = nil): Boolean;
|
|
|
|
function IsOpen: Boolean; virtual;
|
|
|
|
property Handle: THandle read GetDeviceHandle;
|
|
property DeviceName: String read sDeviceName_;
|
|
end;
|
|
|
|
{
|
|
var
|
|
IOCTL_DISK_GET_LENGTH_INFO: DWORD;
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: DWORD;
|
|
IOCTL_STORAGE_QUERY_PROPERTY: DWORD;
|
|
IOCTL_STORAGE_GET_MEDIA_TYPES_EX: DWORD;
|
|
IOCTL_STORAGE_EJECTION_CONTROL: DWORD;
|
|
IOCTL_STORAGE_MEDIA_REMOVAL: DWORD;
|
|
IOCTL_STORAGE_EJECT_MEDIA: DWORD;
|
|
FSCTL_DISMOUNT_VOLUME : DWORD;
|
|
FSCTL_LOCK_VOLUME : DWORD;
|
|
FSCTL_UNLOCK_VOLUME : DWORD;
|
|
FSCTL_IS_VOLUME_MOUNTED:DWORD;
|
|
FSCTL_ALLOW_EXTENDED_DASD_IO : DWORD;
|
|
//IOCTL_STORAGE_EJECT_MEDIA : DWORD;
|
|
|
|
IOCTL_WDMAUD_OPEN_DEVICE : DWORD = $1d8014;
|
|
IOCTL_WDMAUD_REMOVE_DEVICE : DWORD = $1d8008;
|
|
IOCTL_WDMAUD_AUX_GET_VOLUME : DWORD = $1d801c;
|
|
|
|
//IOCTL_STORAGE_GET_DEVICE_NUMBER : DWORD = $2D1080;
|
|
}
|
|
|
|
type
|
|
PDriveInfo = ^TDriveInfo;
|
|
TDriveInfo = record
|
|
sDrive,
|
|
sSerial,
|
|
sClass,
|
|
sClassGuid,
|
|
sDesc,
|
|
sInstanceId,
|
|
sFriendlyName: String;
|
|
llSize: LONGLONG;
|
|
nDiskNum: Integer;
|
|
end;
|
|
|
|
function FlushDriveBuffers(const sDrive: String): Boolean;
|
|
function DeviceIoCtrl(hDevice : DWORD; dwCode: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
function GetDriveDetail(sDrive: String; pInfo: PDriveInfo; bAddInfo: Boolean = false): Boolean;
|
|
function ForceEjectDrive(sDrive: String): Boolean;
|
|
function EjectDrive(sDrive: String; aIgrList: TStringList = nil; bOnlyUsb: Boolean = true; bForceEject: Boolean = false): String;
|
|
function EjectDrive2(sDrive: String; aIgrList: TStringList = nil; bOnlyUsb: Boolean = true; bForceEject: Boolean = false; bForceEjectFirst: Boolean = false): String; // 내장 cdrom 제거 23_0223 16:23:32 kku
|
|
function SetUsbDevEnableByDevPath(sDevPath: String; bVal: Boolean): Boolean;
|
|
function RemoveUsbDevEnableByDevPath(sDevPath: String): Integer;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Tocsg.Path,
|
|
Tocsg.Safe, Tocsg.Exception, Tocsg.Convert, Tocsg.Disk, Tocsg.Trace,
|
|
Tocsg.Shell, Tocsg.Process;
|
|
|
|
//CTL_CODE(IOCTL_STORAGE_BASE, $0250, METHOD_BUFFERED, FILE_READ_ACCESS);
|
|
function CTL_CODE(const dwDeviceType, dwFunc, dwMethod, dwAccess: DWORD): DWORD;
|
|
begin
|
|
Result := (dwDeviceType shl 16) or
|
|
(dwAccess shl 14) or
|
|
(dwFunc shl 2) or
|
|
dwMethod;
|
|
end;
|
|
|
|
function ConvSerialToStr(sSerNum: AnsiString): AnsiString;
|
|
var
|
|
i, nStrLen: Integer;
|
|
sPair: AnsiString;
|
|
B: Byte;
|
|
Ch: AnsiChar Absolute B;
|
|
begin
|
|
Result := '';
|
|
nStrLen := Length(sSerNum);
|
|
|
|
if Odd(nStrLen) then
|
|
exit;
|
|
|
|
i := 1;
|
|
|
|
while i < nStrLen do
|
|
begin
|
|
sPair := Copy(sSerNum, i, 2);
|
|
HexToBin(PAnsiChar(sPair), PAnsiChar(@B), 1);
|
|
Result := Result + AnsiChar(B);
|
|
Inc(i, 2);
|
|
end;
|
|
|
|
i := 1;
|
|
|
|
nStrLen := Length(Result);
|
|
while i < nStrLen do
|
|
begin
|
|
Ch := Result[i];
|
|
Result[i] := Result[i + 1];
|
|
Result[i + 1] := Ch;
|
|
Inc(i, 2);
|
|
end;
|
|
end;
|
|
|
|
{ TTgDriver }
|
|
|
|
Constructor TTgDriver.Create;
|
|
begin
|
|
Inherited Create;
|
|
|
|
hDevice_ := 0;
|
|
end;
|
|
|
|
Destructor TTgDriver.Destroy;
|
|
begin
|
|
CloseDevice;
|
|
|
|
Inherited;
|
|
end;
|
|
|
|
function TTgDriver.GetDeviceHandle: THandle;
|
|
begin
|
|
Result := hDevice_;
|
|
end;
|
|
|
|
// 성공 - 0, 그외 실패
|
|
function TTgDriver.OpenDevice(const sDeviceName: String;
|
|
dwDesireAccess: DWORD = GENERIC_READ or GENERIC_WRITE;
|
|
dwShareMode: DWORD = FILE_SHARE_READ or FILE_SHARE_WRITE;
|
|
dwFlagsAndAttributes: DWORD = 0): Integer;
|
|
var
|
|
h: THandle;
|
|
begin
|
|
if hDevice_ <> 0 then
|
|
CloseDevice;
|
|
|
|
if sDeviceName = '' then
|
|
begin
|
|
Result := ERROR_FILE_NOT_FOUND;
|
|
exit;
|
|
end;
|
|
|
|
// if (GetVersion and $ff) >= 5 then
|
|
// sDeviceName := '\\.\Global\' + sDriverName
|
|
// else
|
|
// sDeviceName := '\\.\' + sDriverName;
|
|
|
|
h := CreateFile(PChar(sDeviceName),
|
|
dwDesireAccess,
|
|
dwShareMode,
|
|
nil,
|
|
OPEN_EXISTING,
|
|
dwFlagsAndAttributes,//FILE_FLAG_NO_BUFFERING or FILE_FLAG_SEQUENTIAL_SCAN,
|
|
0);
|
|
|
|
if h = INVALID_HANDLE_VALUE then
|
|
begin
|
|
Result := GetLastError;
|
|
exit;
|
|
end;
|
|
|
|
hDevice_ := h;
|
|
sDeviceName_ := sDeviceName;
|
|
|
|
// 일단 플러시 실패해도 상관없으니깐 그냥 실행만 시켜준다.
|
|
// 09_1111 추가 sunk
|
|
// if FlushFileBuffers(h) then // 물리 디스크는 안되나부다..
|
|
// _Trace('OpenDevice() - FlushFileBuffers .. success')
|
|
// else
|
|
// _Trace('OpenDevice() - FlushFileBuffers .. fail');
|
|
|
|
Result := ERROR_SUCCESS;
|
|
end;
|
|
|
|
function TTgDriver.CloseDevice: Boolean;
|
|
begin
|
|
Result := false;
|
|
|
|
if hDevice_ <> 0 then
|
|
begin
|
|
CloseHandle(hDevice_);
|
|
hDevice_ := 0;
|
|
|
|
Result := true;
|
|
end;
|
|
end;
|
|
|
|
function TTgDriver.ReadIO(dwCode: DWORD; pBuf: Pointer;
|
|
dwSize: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
var
|
|
dwByteReturned: DWORD;
|
|
begin
|
|
Result := false;
|
|
|
|
if hDevice_ = 0 then
|
|
exit;
|
|
|
|
dwByteReturned := 0;
|
|
|
|
Result := DeviceIoControl(hDevice_,
|
|
dwCode,
|
|
nil,
|
|
0,
|
|
pBuf,
|
|
dwSize,
|
|
dwByteReturned,
|
|
nil);
|
|
|
|
if Result and (pdwByteReturn <> nil) then
|
|
pdwByteReturn^ := dwByteReturned;
|
|
end;
|
|
|
|
function TTgDriver.WriteIO(dwCode: DWORD; pBuf: Pointer;
|
|
dwSize: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
var
|
|
dwByteReturned: DWORD;
|
|
begin
|
|
Result := false;
|
|
|
|
if hDevice_ = 0 then
|
|
exit;
|
|
|
|
Result := DeviceIoControl(hDevice_,
|
|
dwCode,
|
|
pBuf,
|
|
dwSize,
|
|
nil,
|
|
0,
|
|
dwByteReturned,
|
|
nil);
|
|
|
|
if Result and (pdwByteReturn <> nil) then
|
|
pdwByteReturn^ := dwByteReturned;
|
|
end;
|
|
|
|
// 드라이버에 데이터 보내고 받기
|
|
// 성공 - bytereturn
|
|
// 드라이버가 열러있지 않음, 오류 - -1
|
|
function TTgDriver.ReadWriteIO(dwCode: DWORD; pInBuf: Pointer; dwInSize: DWORD;
|
|
pOutBuf: Pointer; dwOutSize: DWORD;
|
|
pdwByteReturn: PDWORD = nil): Boolean;
|
|
var
|
|
dwByteReturned: DWORD;
|
|
begin
|
|
Result := false;
|
|
|
|
if hDevice_ = 0 then
|
|
exit;
|
|
|
|
Result := DeviceIoControl(hDevice_,
|
|
dwCode,
|
|
pInBuf,
|
|
dwInSize,
|
|
pOutBuf,
|
|
dwOutSize,
|
|
dwByteReturned,
|
|
nil);
|
|
|
|
if Result and (pdwByteReturn <> nil) then
|
|
pdwByteReturn^ := dwByteReturned;
|
|
end;
|
|
|
|
function TTgDriver.IsOpen: Boolean;
|
|
begin
|
|
Result := (hDevice_ <> 0) and (hDevice_ <> INVALID_HANDLE_VALUE);
|
|
end;
|
|
|
|
function FlushDriveBuffers(const sDrive: String): Boolean;
|
|
var
|
|
hVolume: THandle;
|
|
sDrivePath: String;
|
|
begin
|
|
Result := false;
|
|
sDrivePath := Format('\\.\%s:', [sDrive[1]]);
|
|
hVolume := CreateFile(PChar(sDrivePath),
|
|
GENERIC_READ or GENERIC_WRITE,
|
|
FILE_SHARE_READ or FILE_SHARE_WRITE,
|
|
nil,
|
|
OPEN_EXISTING,
|
|
0,
|
|
0);
|
|
|
|
if hVolume < 1 then
|
|
exit;
|
|
|
|
Result := FlushFileBuffers(hVolume);
|
|
CloseHandle(hVolume);
|
|
end;
|
|
|
|
function DeviceIoCtrl(hDevice : DWORD; dwCode: DWORD; pdwByteReturn: PDWORD = nil): Boolean;
|
|
var
|
|
dwByteReturned: DWORD;
|
|
begin
|
|
Result := false;
|
|
|
|
if hDevice = 0 then
|
|
exit;
|
|
|
|
Result := DeviceIoControl(hDevice,
|
|
dwCode,
|
|
nil,
|
|
0,
|
|
nil,
|
|
0,
|
|
dwByteReturned,
|
|
nil);
|
|
|
|
if Result and (pdwByteReturn <> nil) then
|
|
pdwByteReturn^ := dwByteReturned;
|
|
end;
|
|
|
|
function GetDevPropertyStr(hDev: HDEVINFO; spdd: TSPDevInfoData; dwProperty: DWORD): String;
|
|
var
|
|
c: Integer;
|
|
pBuf: Pointer;
|
|
dwBufSize,
|
|
dwPropertyRegDataType: DWORD;
|
|
begin
|
|
Result := '';
|
|
try
|
|
pBuf := nil;
|
|
dwBufSize := 0;
|
|
try
|
|
while not SetupDiGetDeviceRegistryProperty(hDev, spdd,
|
|
dwProperty, dwPropertyRegDataType, pBuf, dwBufSize, dwBufSize) do
|
|
begin
|
|
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
|
|
begin
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
pBuf := AllocMem(dwBufSize);
|
|
end else break;
|
|
end;
|
|
|
|
if pBuf <> nil then
|
|
Result := String(PChar(pBuf));
|
|
finally
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(E, 'Fail .. GetDevPropertyStr()');
|
|
end;
|
|
end;
|
|
|
|
function GetDeviceInstanceId(hDev: HDEVINFO; spdd: TSPDevInfoData): string;
|
|
var
|
|
ReqSize: DWORD;
|
|
Buffer: array of Char; // 동적 배열 사용
|
|
begin
|
|
Result := '';
|
|
ReqSize := 0;
|
|
|
|
// 1. 필요한 버퍼 크기 구하기
|
|
// 함수가 False를 리턴하고 GetLastError가 ERROR_INSUFFICIENT_BUFFER일 때 정상
|
|
if not SetupDiGetDeviceInstanceId(hDev, spdd, nil, 0, ReqSize) then
|
|
begin
|
|
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
|
|
end;
|
|
|
|
if ReqSize = 0 then Exit;
|
|
|
|
// 2. 버퍼 메모리 할당
|
|
SetLength(Buffer, ReqSize);
|
|
|
|
// 3. 실제 데이터 가져오기
|
|
if SetupDiGetDeviceInstanceId(hDev, spdd, @Buffer[0], ReqSize, ReqSize) then
|
|
begin
|
|
// PChar로 변환하여 델파이 스트링에 담기
|
|
Result := PChar(@Buffer[0]);
|
|
Result := Trim(Result); // 혹시 모를 공백 제거
|
|
end;
|
|
end;
|
|
|
|
function GetDriveDetail(sDrive: String; pInfo: PDriveInfo; bAddInfo: Boolean = false): Boolean;
|
|
var
|
|
sVol: String;
|
|
Drv: TTgDriver;
|
|
sdn: STORAGE_DEVICE_NUMBER;
|
|
dwIdx,
|
|
dwLen: DWORD;
|
|
DevGuid: TGuid;
|
|
hDev: HDEVINFO;
|
|
sdid: TSPDeviceInterfaceData;
|
|
pBuf: TBytes;
|
|
spdd: TSPDevInfoData;
|
|
DevInstParent: DEVINST;
|
|
sDevName: array [0..255] of Char;
|
|
begin
|
|
Result := false;
|
|
|
|
ZeroMemory(pInfo, SizeOf(TDriveInfo));
|
|
pInfo.sDrive := sDrive;
|
|
pInfo.nDiskNum := -1;
|
|
pInfo.llSize := GetDriveSize(sDrive);
|
|
// if pInfo.llSize = 0 then
|
|
// begin
|
|
// var DrvEx: TDriveExtent := GetDriveExtent(sDrive);
|
|
// pInfo.llSize := DrvEx.liExtentLength.QuadPart;
|
|
// end;
|
|
|
|
if sDrive = '' then
|
|
exit;
|
|
|
|
sVol := Format('\\.\%s:', [sDrive[1]]);
|
|
Guard(Drv, TTgDriver.Create);
|
|
if Drv.OpenDevice(sVol, 0) <> ERROR_SUCCESS then
|
|
exit;
|
|
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
exit;
|
|
Drv.CloseDevice;
|
|
|
|
if sdn.DeviceNumber = -1 then
|
|
exit;
|
|
pInfo.nDiskNum := sdn.DeviceNumber;
|
|
|
|
case GetDriveType(PChar(sDrive)) of
|
|
// DRIVE_FIXED,
|
|
// DRIVE_REMOVABLE : DevGuid := GUID_DEVINTERFACE_DISK;
|
|
DRIVE_CDROM : DevGuid := GUID_DEVINTERFACE_CDROM;
|
|
else DevGuid := GUID_DEVINTERFACE_DISK;
|
|
end;
|
|
|
|
hDev := SetupDiGetClassDevs(@DevGuid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
|
|
if hDev = INVALID_HANDLE_VALUE then
|
|
exit;
|
|
|
|
try
|
|
dwIdx := 0;
|
|
while True do
|
|
begin
|
|
ZeroMemory(@sdid, SizeOf(sdid));
|
|
sdid.cbSize := SizeOf(sdid);
|
|
if not SetupDiEnumDeviceInterfaces(hDev, nil, DevGuid, dwIdx, sdid) then
|
|
break;
|
|
|
|
SetupDiGetDeviceInterfaceDetail(hDev, @sdid, nil, 0, dwLen, nil);
|
|
if (dwLen > 0) and (dwLen < 204800) then
|
|
begin
|
|
SetLength(pBuf, dwLen);
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]).cbSize := SizeOf(TSPDeviceInterfaceDetailData);
|
|
|
|
ZeroMemory(@spdd, SizeOf(spdd));
|
|
spdd.cbSize := SizeOf(spdd);
|
|
|
|
if SetupDiGetDeviceInterfaceDetail(hDev, @sdid,
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]), dwLen, dwLen, @spdd) then
|
|
begin
|
|
if Drv.OpenDevice(PChar(@pBuf[4]), 0) = ERROR_SUCCESS then
|
|
begin
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
exit;
|
|
Drv.CloseDevice;
|
|
|
|
if sdn.DeviceNumber = pInfo.nDiskNum then
|
|
begin
|
|
pInfo.sFriendlyName := GetDevPropertyStr(hDev, spdd, SPDRP_FRIENDLYNAME);
|
|
pInfo.sInstanceId := GetDeviceInstanceId(hDev, spdd);
|
|
|
|
if bAddInfo then
|
|
begin
|
|
pInfo.sClass := GetDevPropertyStr(hDev, spdd, SPDRP_CLASS);
|
|
pInfo.sClassGuid := GetDevPropertyStr(hDev, spdd, SPDRP_CLASSGUID);
|
|
pInfo.sDesc := GetDevPropertyStr(hDev, spdd, SPDRP_DEVICEDESC);
|
|
end;
|
|
|
|
ZeroMemory(@sDevName, SizeOf(sDevName));
|
|
CM_Get_Parent(DevInstParent, spdd.DevInst, 0);
|
|
CM_Get_Device_ID(DevInstParent, sDevName, 256, 0);
|
|
|
|
pInfo.sSerial := sDevName;
|
|
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc(dwIdx);
|
|
end;
|
|
finally
|
|
SetupDiDestroyDeviceInfoList(hDev);
|
|
end;
|
|
end;
|
|
|
|
// for BS1
|
|
function ForceEjectDrive(sDrive: String): Boolean;
|
|
var
|
|
sEjectMd: String;
|
|
begin
|
|
TTgTrace.T('ForceEjectDrive() ..', 1);
|
|
Result := false;
|
|
try
|
|
// if not DirectoryExists(sDrive) then
|
|
// exit;
|
|
|
|
sEjectMd := GetRunExePathDir + 'Bs1uef.dat';
|
|
if not FileExists(sEjectMd) then
|
|
sEjectMd := GetRunExePathDir + 'conf\Bs1uef.dat';
|
|
|
|
if FileExists(sEjectMd) then
|
|
begin
|
|
ExecuteAppWaitUntilTerminate(sEjectMd, Format('%s: -f', [sDrive[1]]), SW_HIDE, 10000);
|
|
if not DirectoryExists(sDrive) then
|
|
Result := true;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(E, 'Fail .. ForceEjectDrive()');
|
|
end;
|
|
end;
|
|
|
|
function LockAndDismountVolume(const DriveLetter: Char): Boolean;
|
|
var
|
|
h: THandle;
|
|
bytes: DWORD;
|
|
path: string;
|
|
i: Integer;
|
|
begin
|
|
path := Format('\\.\%s:', [UpCase(DriveLetter)]);
|
|
h := CreateFile(PChar(path), GENERIC_READ or GENERIC_WRITE,
|
|
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
|
|
if h = INVALID_HANDLE_VALUE then Exit(False);
|
|
try
|
|
// 락은 충돌 잦으니 여러 번 재시도
|
|
for i := 1 to 20 do
|
|
if DeviceIoControl(h, FSCTL_LOCK_VOLUME, nil, 0, nil, 0, bytes, nil) then Break
|
|
else Sleep(150); // 잠시 대기 후 재시도
|
|
|
|
if not DeviceIoControl(h, FSCTL_LOCK_VOLUME, nil, 0, nil, 0, bytes, nil) then
|
|
Exit(False);
|
|
|
|
// 언마운트(파일시스템 분리)
|
|
Result := DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, nil, 0, nil, 0, bytes, nil);
|
|
finally
|
|
CloseHandle(h);
|
|
end;
|
|
end;
|
|
|
|
function EjectDrive(sDrive: String; aIgrList: TStringList = nil;
|
|
bOnlyUsb: Boolean = true; bForceEject: Boolean = false): String;
|
|
var
|
|
sVol: String;
|
|
sDevName: array [0..255] of Char;
|
|
Drv: TTgDriver;
|
|
sdn: STORAGE_DEVICE_NUMBER;
|
|
dwIdx,
|
|
dwLen: DWORD;
|
|
VetoType: PNP_VETO_TYPE;
|
|
sVetoName: PChar;
|
|
nType, nDiskNum: Integer;
|
|
DevGuid: TGuid;
|
|
hDev: HDEVINFO;
|
|
sdid: TSPDeviceInterfaceData;
|
|
pBuf: TBytes;
|
|
spdd: TSPDevInfoData;
|
|
DevInstParent: DEVINST;
|
|
bIsCdRom,
|
|
bSuccess: Boolean;
|
|
DrvEx: TDriveExtent;
|
|
i: Integer;
|
|
begin
|
|
Result := FAIL_EJECT;
|
|
|
|
if sDrive = '' then
|
|
begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. 1');
|
|
exit;
|
|
end;
|
|
|
|
// bIsCdRom := GetDriveType(PChar(sDrive)) = DRIVE_CDROM;
|
|
sVol := Format('\\.\%s:', [sDrive[1]]);
|
|
Guard(Drv, TTgDriver.Create);
|
|
if Drv.OpenDevice(sVol, 0) <> ERROR_SUCCESS then
|
|
begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. 2');
|
|
exit;
|
|
end;
|
|
|
|
ZeroMemory(@sdn, SizeOf(sdn));
|
|
sdn.DeviceNumber := 999;
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
exit;
|
|
Drv.CloseDevice;
|
|
nDiskNum := sdn.DeviceNumber;
|
|
|
|
// DrvEx := GetDriveExtent(sDrive);
|
|
// if DrvEx.liExtentLength.QuadPart = 0 then
|
|
// begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. Size null .. Drive=%s', [sDrive]);
|
|
// exit;
|
|
// end;
|
|
|
|
// nDiskNum := DrvEx.dwDiskNumber;
|
|
if (nDiskNum = -1) or (nDiskNum = 999) then
|
|
begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. Not found disknum .. Drive=%s', [sDrive], 1);
|
|
exit;
|
|
end;
|
|
|
|
// TTgTrace.T('EjectDrive() .. Drive=%s, DiskNum=%d', [sDrive, nDiskNum], 1);
|
|
|
|
nType := GetDriveType(PChar(sDrive));
|
|
case nType of
|
|
DRIVE_FIXED,
|
|
DRIVE_REMOVABLE : DevGuid := GUID_DEVINTERFACE_DISK;
|
|
DRIVE_CDROM : DevGuid := GUID_dEVINTERFACE_CDROM;
|
|
end;
|
|
|
|
hDev := SetupDiGetClassDevs(@DevGuid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
|
|
if hDev = INVALID_HANDLE_VALUE then
|
|
begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. 5');
|
|
exit;
|
|
end;
|
|
|
|
try
|
|
dwIdx := 0;
|
|
while True do
|
|
begin
|
|
ZeroMemory(@sdid, SizeOf(sdid));
|
|
sdid.cbSize := SizeOf(sdid);
|
|
if not SetupDiEnumDeviceInterfaces(hDev, nil, DevGuid, dwIdx, sdid) then
|
|
break;
|
|
|
|
// TTgTrace.T('EjectDrive() .. SetupDiGetDeviceInterfaceDetail .. Init');
|
|
SetupDiGetDeviceInterfaceDetail(hDev, @sdid, nil, 0, dwLen, nil);
|
|
if (dwLen > 0) and (dwLen < 204800) then
|
|
begin
|
|
SetLength(pBuf, dwLen);
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]).cbSize := SizeOf(TSPDeviceInterfaceDetailData);
|
|
|
|
ZeroMemory(@spdd, SizeOf(spdd));
|
|
spdd.cbSize := SizeOf(spdd);
|
|
|
|
if SetupDiGetDeviceInterfaceDetail(hDev, @sdid,
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]), dwLen, dwLen, @spdd) then
|
|
begin
|
|
// TTgTrace.T('EjectDrive() .. SetupDiGetDeviceInterfaceDetail .. Success');
|
|
if Drv.OpenDevice(PChar(@pBuf[4]), 0) = ERROR_SUCCESS then
|
|
begin
|
|
// TTgTrace.T('EjectDrive() .. OpenDevice .. Success');
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
begin
|
|
// TTgTrace.T('EjectDrive() .. ReadIO .. Fail');
|
|
exit;
|
|
end;
|
|
// TTgTrace.T('EjectDrive() .. ReadIO .. Success, DiskNum=%d', [sdn.DeviceNumber]);
|
|
Drv.CloseDevice;
|
|
|
|
if sdn.DeviceNumber = nDiskNum then
|
|
begin
|
|
DevInstParent := 0;
|
|
ZeroMemory(@sDevName, SizeOf(sDevName));
|
|
CM_Get_Parent(DevInstParent, spdd.DevInst, 0);
|
|
CM_Get_Device_ID(DevInstParent, sDevName, 256, 0);
|
|
|
|
// TTgTrace.T('EjectDrive() .. DevName=%s', [sDevName]);
|
|
|
|
// if bIsCdRom and (Pos('CDROM', UpperCase(sDevName)) = 0) then
|
|
// begin
|
|
// TTgTrace.T('EjectDrive() .. No CDROM, DiskNum=%d', [sdn.DeviceNumber]);
|
|
// Inc(dwIdx);
|
|
// continue;
|
|
// end;
|
|
|
|
// TTgTrace.T('EjectDrive() .. Found CDROM, DiskNum=%d', [sdn.DeviceNumber]);
|
|
// if bOnlyUsb and (Pos('USB', UpperCase(sDevName)) <> 1) then
|
|
// begin
|
|
// TTgTrace.T('Fail .. EjectDrive() .. 7');
|
|
// exit;
|
|
// end;
|
|
|
|
if aIgrList <> nil then
|
|
begin
|
|
// if aIgrList.CaseSensitive then
|
|
// aIgrList.CaseSensitive := false;
|
|
// if aIgrList.IndexOf(sDevName) <> -1 then
|
|
// begin
|
|
// Result := '';
|
|
// exit;
|
|
// end;
|
|
|
|
// 비교방식 변경 25_0324 10:12:22 kku
|
|
var sChkDevName: String := UpperCase(sDevName);
|
|
for i := 0 to aIgrList.Count - 1 do
|
|
if Pos(UpperCase(aIgrList[i]), sDevName) > 0 then
|
|
begin
|
|
Result := '';
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
// TTgTrace.T('EjectDrive() .. DevName=%s, DiskNum=%d', [sDevName, nDiskNum], 1);
|
|
|
|
VetoType := 0;
|
|
sVetoName := nil;
|
|
|
|
// var ss: TStringStream;
|
|
// Guard(ss, TStringStream.Create('', TEncoding.ANSI));
|
|
// if GetCmdTextToStream('mountvol.exe', Format('%s: /L', [sDrive[1]]), ss, 5000) then
|
|
// begin
|
|
// ExecutePath('mountvol.exe', Format('%s: /D', [sDrive[1]]));
|
|
// Sleep(500);
|
|
// bSuccess := CM_Request_Device_Eject(DevInstParent, @VetoType, sVetoName, MAX_PATH, 0) = CR_SUCCESS;
|
|
// ExecutePath('mountvol.exe', Format('%s: %s', [sDrive[1], StringReplace(Trim(ss.DataString), #13#10, '', [rfReplaceAll])]));
|
|
//// if not DirectoryExists(sDrive) then
|
|
//// Result := sDevName;
|
|
// end;
|
|
|
|
// LockAndDismountVolume(sDrive[1]);
|
|
|
|
bSuccess := CM_Request_Device_Eject(DevInstParent, @VetoType, sVetoName, MAX_PATH, 0) = CR_SUCCESS;
|
|
if bSuccess and (VetoType = 0) then
|
|
begin
|
|
// ShowMessage(Format('%d - %s', [sdn.DeviceNumber, sDevName]));
|
|
Result := sDevName;
|
|
end else begin
|
|
TTgTrace.T('Fail .. EjectDrive() .. VetoType=%d, LastError=%d', [VetoType, GetLastError], 1);
|
|
|
|
if bForceEject then
|
|
begin
|
|
if ForceEjectDrive(sDrive) then
|
|
Result := sDevName;
|
|
end;
|
|
|
|
// ExecutePath('mountvol.exe', Format('%s: /P', [sDrive[1]]));
|
|
// Sleep(500);
|
|
// if not DirectoryExists(sDrive) then
|
|
// begin
|
|
// Result := sDevName;
|
|
// end;
|
|
end;
|
|
exit;
|
|
end;
|
|
end;
|
|
// else
|
|
// TTgTrace.T('EjectDrive() .. OpenDevice .. Fail');
|
|
end;
|
|
// else
|
|
// TTgTrace.T('EjectDrive() .. SetupDiGetDeviceInterfaceDetail .. Fail');
|
|
end;
|
|
Inc(dwIdx);
|
|
end;
|
|
finally
|
|
SetupDiDestroyDeviceInfoList(hDev);
|
|
end;
|
|
|
|
// if Result = FAIL_EJECT then
|
|
// TTgTrace.T('Fail .. EjectDrive() .. end');
|
|
end;
|
|
|
|
function EjectDrive2(sDrive: String; aIgrList: TStringList = nil; bOnlyUsb: Boolean = true; bForceEject: Boolean = false; bForceEjectFirst: Boolean = false): String;
|
|
var
|
|
sVol: String;
|
|
sDevName: array [0..255] of Char;
|
|
Drv: TTgDriver;
|
|
sdn: STORAGE_DEVICE_NUMBER;
|
|
dwIdx,
|
|
dwLen: DWORD;
|
|
VetoType: PNP_VETO_TYPE;
|
|
sVetoName: PChar;
|
|
nType, nDiskNum: Integer;
|
|
DevGuid: TGuid;
|
|
hDev: HDEVINFO;
|
|
sdid: TSPDeviceInterfaceData;
|
|
pBuf: TBytes;
|
|
spdd: TSPDevInfoData;
|
|
DevInstParent: DEVINST;
|
|
bSuccess: Boolean;
|
|
DrvEx: TDriveExtent;
|
|
i: Integer;
|
|
begin
|
|
Result := FAIL_EJECT;
|
|
|
|
if sDrive = '' then
|
|
exit;
|
|
|
|
sVol := Format('\\.\%s:', [sDrive[1]]);
|
|
Guard(Drv, TTgDriver.Create);
|
|
if Drv.OpenDevice(sVol, 0) <> ERROR_SUCCESS then
|
|
exit;
|
|
|
|
ZeroMemory(@sdn, SizeOf(sdn));
|
|
sdn.DeviceNumber := 999;
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
exit;
|
|
Drv.CloseDevice;
|
|
//
|
|
nDiskNum := sdn.DeviceNumber;
|
|
|
|
// nDiskNum := GetDriveExtent(sDrive).dwDiskNumber;
|
|
|
|
// DrvEx := GetDriveExtent(sDrive);
|
|
// if DrvEx.liExtentLength.QuadPart = 0 then
|
|
// begin
|
|
// TTgTrace.T('Fail .. EjectDrive2() .. Size null .. Drive=%s', [sDrive]);
|
|
// exit;
|
|
// end;
|
|
// nDiskNum := DrvEx.dwDiskNumber;
|
|
|
|
if (nDiskNum = -1) or (nDiskNum = 999) then
|
|
begin
|
|
TTgTrace.T('Fail .. EjectDrive2() .. Not found disknum .. Drive=%s', [sDrive], 1);
|
|
exit;
|
|
end;
|
|
|
|
TTgTrace.T('EjectDrive2() .. Drive=%s, DiskNum=%d', [sDrive, nDiskNum], 1);
|
|
// TTgTrace.T('EjectDrive2() .. Drive=%s, DiskNum=%d', [sDrive, nDiskNum]);
|
|
|
|
nType := GetDriveType(PChar(sDrive));
|
|
case nType of
|
|
DRIVE_FIXED,
|
|
DRIVE_REMOVABLE : DevGuid := GUID_DEVINTERFACE_DISK;
|
|
DRIVE_CDROM : DevGuid := GUID_DEVINTERFACE_CDROM;
|
|
end;
|
|
|
|
hDev := SetupDiGetClassDevs(@DevGuid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
|
|
if hDev = INVALID_HANDLE_VALUE then
|
|
exit;
|
|
|
|
try
|
|
dwIdx := 0;
|
|
while True do
|
|
begin
|
|
ZeroMemory(@sdid, SizeOf(sdid));
|
|
sdid.cbSize := SizeOf(sdid);
|
|
if not SetupDiEnumDeviceInterfaces(hDev, nil, DevGuid, dwIdx, sdid) then
|
|
break;
|
|
|
|
SetupDiGetDeviceInterfaceDetail(hDev, @sdid, nil, 0, dwLen, nil);
|
|
if (dwLen > 0) and (dwLen < 204800) then
|
|
begin
|
|
SetLength(pBuf, dwLen);
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]).cbSize := SizeOf(TSPDeviceInterfaceDetailData);
|
|
|
|
ZeroMemory(@spdd, SizeOf(spdd));
|
|
spdd.cbSize := SizeOf(spdd);
|
|
|
|
if SetupDiGetDeviceInterfaceDetail(hDev, @sdid,
|
|
PSPDeviceInterfaceDetailData(@pBuf[0]), dwLen, dwLen, @spdd) then
|
|
begin
|
|
if Drv.OpenDevice(PChar(@pBuf[4]), 0) = ERROR_SUCCESS then
|
|
begin
|
|
if not Drv.ReadIO(IOCTL_STORAGE_GET_DEVICE_NUMBER, @sdn, SizeOf(sdn), @dwLen) then
|
|
exit;
|
|
Drv.CloseDevice;
|
|
|
|
if sdn.DeviceNumber = nDiskNum then
|
|
begin
|
|
DevInstParent := 0;
|
|
ZeroMemory(@sDevName, SizeOf(sDevName));
|
|
CM_Get_Parent(DevInstParent, spdd.DevInst, 0);
|
|
CM_Get_Device_ID(DevInstParent, sDevName, 256, 0);
|
|
|
|
// if Pos('CDROM', UpperCase(sDevName)) = 0 then
|
|
// begin
|
|
// Inc(dwIdx);
|
|
// continue;
|
|
// end;
|
|
|
|
if bOnlyUsb and (Pos('USB', UpperCase(sDevName)) <> 1) then
|
|
exit;
|
|
|
|
TTgTrace.T('EjectDrive2() .. DevName=%s, DiskNum=%d', [sDevName, nDiskNum], 1);
|
|
// TTgTrace.T('EjectDrive() .. DevName=%s, DiskNum=%d', [sDevName, nDiskNum]);
|
|
|
|
if aIgrList <> nil then
|
|
begin
|
|
// if aIgrList.CaseSensitive then
|
|
// aIgrList.CaseSensitive := false;
|
|
// if aIgrList.IndexOf(sDevName) <> -1 then
|
|
// begin
|
|
// Result := '';
|
|
// exit;
|
|
// end;
|
|
|
|
// 비교방식 변경 25_0324 10:12:22 kku
|
|
var sChkDevName: String := UpperCase(sDevName);
|
|
for i := 0 to aIgrList.Count - 1 do
|
|
if Pos(UpperCase(aIgrList[i]), sDevName) > 0 then
|
|
begin
|
|
Result := '';
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
VetoType := 0;
|
|
sVetoName := nil;
|
|
if bForceEjectFirst then
|
|
begin
|
|
if ForceEjectDrive(sDrive) then
|
|
begin
|
|
Result := sDevName;
|
|
exit;
|
|
end else
|
|
bSuccess := CM_Query_And_Remove_SubTree(DevInstParent, @VetoType, sVetoName, MAX_PATH, CM_REMOVE_NO_RESTART) = CR_SUCCESS;
|
|
end else begin
|
|
bSuccess := CM_Query_And_Remove_SubTree(DevInstParent, @VetoType, sVetoName, MAX_PATH, CM_REMOVE_NO_RESTART) = CR_SUCCESS; // EjectDrive()와 다른점 23_0223 16:24:47 kku
|
|
// bSuccess := CM_Query_And_Remove_SubTree(DevInstParent, nil, nil, 0, CM_REMOVE_NO_RESTART) = CR_SUCCESS; // EjectDrive()와 다른점 23_0223 16:24:47 kku
|
|
end;
|
|
|
|
if bSuccess and (VetoType = 0) then
|
|
begin
|
|
// ShowMessage(Format('%d - %s', [sdn.DeviceNumber, sDevName]));
|
|
Result := sDevName;
|
|
end else begin
|
|
TTgTrace.T('Fail .. EjectDrive2() .. VetoType=%d, LastError=%d', [VetoType, GetLastError], 1);
|
|
|
|
if bForceEject then
|
|
begin
|
|
if ForceEjectDrive(sDrive) then
|
|
Result := sDevName;
|
|
end;
|
|
// var ss: TStringStream;
|
|
// Guard(ss, TStringStream.Create('', TEncoding.ANSI));
|
|
// if GetCmdTextToStream('mountvol.exe', Format('%s: /P', [sDrive[1]]), ss, 5000) then
|
|
// begin
|
|
// ExecutePath('mountvol.exe', Format('%s: /P', [sDrive[1]]));
|
|
// Sleep(500);
|
|
// if not DirectoryExists(sDrive) then
|
|
// Result := sDevName;
|
|
// end;
|
|
end;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc(dwIdx);
|
|
end;
|
|
finally
|
|
SetupDiDestroyDeviceInfoList(hDev);
|
|
end;
|
|
end;
|
|
|
|
function SetUsbDevEnableByDevPath(sDevPath: String; bVal: Boolean): Boolean;
|
|
var
|
|
hDev: HDEVINFO;
|
|
sdd: TSPDevInfoData;
|
|
i, c: Integer;
|
|
dwBufSize,
|
|
dwStatus, dwProblem,
|
|
dwPropertyRegDataType: DWORD;
|
|
pBuf: Pointer;
|
|
sInfo: String;
|
|
InfoList: TStringList;
|
|
begin
|
|
Result := false;
|
|
|
|
try
|
|
hDev := SetupDiGetClassDevs(@GUID_DEVCLASS_USB, nil, 0, DIGCF_PRESENT);
|
|
if hDev = INVALID_HANDLE_VALUE then
|
|
exit;
|
|
|
|
pBuf := nil;
|
|
try
|
|
ZeroMemory(@sdd, SizeOf(sdd));
|
|
sdd.cbSize := SizeOf(sdd);
|
|
|
|
Guard(InfoList, TStringList.Create);
|
|
|
|
i := 0;
|
|
while SetupDiEnumDeviceInfo(hDev, i, sdd) do
|
|
begin
|
|
dwBufSize := 0;
|
|
if pBuf <> nil then
|
|
begin
|
|
FreeMem(pBuf);
|
|
pBuf := nil;
|
|
end;
|
|
|
|
while not SetupDiGetDeviceRegistryProperty(hDev, sdd,
|
|
SPDRP_HARDWAREID, dwPropertyRegDataType, pBuf, dwBufSize, dwBufSize) do
|
|
begin
|
|
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
|
|
begin
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
pBuf := AllocMem(dwBufSize);
|
|
end else break;
|
|
end;
|
|
|
|
if pBuf <> nil then
|
|
begin
|
|
sInfo := '';
|
|
InfoList.Clear;
|
|
for c := 0 to (dwBufSize div 2) - 1 do
|
|
begin
|
|
if PChar(pBuf)[c] = #0 then
|
|
begin
|
|
if sInfo <> '' then
|
|
begin
|
|
InfoList.Add(sInfo);
|
|
sInfo := '';
|
|
end;
|
|
end else
|
|
sInfo := sInfo + PChar(pBuf)[c];
|
|
end;
|
|
|
|
if sInfo <> '' then
|
|
InfoList.Add(sInfo);
|
|
|
|
for c := 0 to InfoList.Count - 1 do
|
|
begin
|
|
if Pos(InfoList[c], sDevPath) > 0 then
|
|
begin
|
|
dwStatus := 0;
|
|
dwProblem := 0;
|
|
|
|
if CM_Get_DevNode_Status(dwStatus, dwProblem, sdd.DevInst, 0) = CR_SUCCESS then
|
|
begin
|
|
var PropChangeParams: TSPPropChangeParams;
|
|
ZeroMemory(@PropChangeParams, SizeOf(PropChangeParams));
|
|
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
|
|
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
|
|
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
|
|
PropChangeParams.StateChange := BooleanToInt(bVal, DICS_ENABLE, DICS_DISABLE);
|
|
|
|
if SetupDiSetClassInstallParams(hDev, @sdd, PSPClassInstallHeader(@PropChangeParams), SizeOf(PropChangeParams)) then
|
|
begin
|
|
// 64bit OS 에서는 64bit 프로그램 에서만 실행 가능하다 22_0621 13:59:21 kku
|
|
Result := SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDev, @sdd);
|
|
end;
|
|
end;
|
|
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Inc(i);
|
|
end;
|
|
|
|
finally
|
|
SetupDiDestroyDeviceInfoList(hDev);
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(E, 'Fail .. SetUsbDevEnableByDevPath()');
|
|
end;
|
|
end;
|
|
|
|
// Result .. -1 = Fail API, 0 = Not found, 1 = Success, 2 = Fail Remove
|
|
function _RemoveUsbDevEnableByDevPath(pClassGuid: PGUID; sDevPath: String): Integer;
|
|
var
|
|
hDev: HDEVINFO;
|
|
sdd: TSPDevInfoData;
|
|
i, c: Integer;
|
|
dwBufSize,
|
|
dwStatus, dwProblem,
|
|
dwPropertyRegDataType: DWORD;
|
|
pBuf: Pointer;
|
|
sInfo: String;
|
|
InfoList: TStringList;
|
|
begin
|
|
Result := -1;
|
|
|
|
try
|
|
hDev := SetupDiGetClassDevs(pClassGuid, nil, 0, DIGCF_PRESENT);
|
|
if hDev = INVALID_HANDLE_VALUE then
|
|
exit;
|
|
|
|
pBuf := nil;
|
|
try
|
|
ZeroMemory(@sdd, SizeOf(sdd));
|
|
sdd.cbSize := SizeOf(sdd);
|
|
|
|
Guard(InfoList, TStringList.Create);
|
|
|
|
i := 0;
|
|
while SetupDiEnumDeviceInfo(hDev, i, sdd) do
|
|
begin
|
|
dwBufSize := 0;
|
|
if pBuf <> nil then
|
|
begin
|
|
FreeMem(pBuf);
|
|
pBuf := nil;
|
|
end;
|
|
|
|
while not SetupDiGetDeviceRegistryProperty(hDev, sdd,
|
|
SPDRP_HARDWAREID, dwPropertyRegDataType, pBuf, dwBufSize, dwBufSize) do
|
|
begin
|
|
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
|
|
begin
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
pBuf := AllocMem(dwBufSize);
|
|
end else break;
|
|
end;
|
|
|
|
if pBuf <> nil then
|
|
begin
|
|
sInfo := '';
|
|
InfoList.Clear;
|
|
for c := 0 to (dwBufSize div 2) - 1 do
|
|
begin
|
|
if PChar(pBuf)[c] = #0 then
|
|
begin
|
|
if sInfo <> '' then
|
|
begin
|
|
InfoList.Add(sInfo);
|
|
sInfo := '';
|
|
end;
|
|
end else
|
|
sInfo := sInfo + PChar(pBuf)[c];
|
|
end;
|
|
|
|
if sInfo <> '' then
|
|
InfoList.Add(sInfo);
|
|
|
|
for c := 0 to InfoList.Count - 1 do
|
|
begin
|
|
if Pos(InfoList[c], sDevPath) > 0 then
|
|
begin
|
|
dwStatus := 0;
|
|
dwProblem := 0;
|
|
|
|
if CM_Get_DevNode_Status(dwStatus, dwProblem, sdd.DevInst, 0) = CR_SUCCESS then
|
|
begin
|
|
if SetupDiRemoveDevice(hDev, sdd) then
|
|
Result := 1
|
|
else
|
|
Result := 2;
|
|
end;
|
|
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Inc(i);
|
|
end;
|
|
Result := 0;
|
|
finally
|
|
SetupDiDestroyDeviceInfoList(hDev);
|
|
if pBuf <> nil then
|
|
FreeMem(pBuf);
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(E, 'Fail .. SetUsbDevEnableByDevPath()');
|
|
end;
|
|
end;
|
|
|
|
function RemoveUsbDevEnableByDevPath(sDevPath: String): Integer;
|
|
begin
|
|
Result := _RemoveUsbDevEnableByDevPath(@GUID_DEVCLASS_USB, sDevPath);
|
|
if Result = 0 then
|
|
begin
|
|
// 애플 장치는 여기로 (범용 직렬 버스 장치) 따로 잡힌다... 그래서 별도 추가 처리 22_0707 09:23:40 kku
|
|
Result := _RemoveUsbDevEnableByDevPath(@GUID_DEVCLASS_USB_DEVICE, sDevPath);
|
|
end;
|
|
if Result = 0 then
|
|
begin
|
|
// MTP 장치등... 추가 23_0323 13:47:12 kku
|
|
Result := _RemoveUsbDevEnableByDevPath(@GUID_DEVCLASS_WPD, sDevPath);
|
|
end;
|
|
end;
|
|
|
|
{
|
|
initialization
|
|
IOCTL_DISK_GET_LENGTH_INFO := CTL_CODE(IOCTL_DISK_BASE, $0017, METHOD_BUFFERED, FILE_READ_ACCESS);
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX := CTL_CODE(IOCTL_DISK_BASE, $0028, METHOD_BUFFERED, FILE_ANY_ACCESS);
|
|
IOCTL_STORAGE_QUERY_PROPERTY := CTL_CODE(IOCTL_STORAGE_BASE, $0500, METHOD_BUFFERED, FILE_ANY_ACCESS);//$2D1400
|
|
IOCTL_STORAGE_GET_MEDIA_TYPES_EX := CTL_CODE(IOCTL_STORAGE_BASE, $0301, METHOD_BUFFERED, FILE_ANY_ACCESS);
|
|
IOCTL_STORAGE_MEDIA_REMOVAL := CTL_CODE(IOCTL_STORAGE_BASE, $0201, METHOD_BUFFERED, FILE_READ_ACCESS);
|
|
IOCTL_STORAGE_EJECTION_CONTROL := $2D0940;//CTL_CODE(IOCTL_STORAGE_BASE, $0250, METHOD_BUFFERED, FILE_ANY_ACCESS); //$2D0940
|
|
IOCTL_STORAGE_EJECT_MEDIA := CTL_CODE(IOCTL_STORAGE_BASE, $0202, METHOD_BUFFERED, FILE_READ_ACCESS);
|
|
|
|
FSCTL_DISMOUNT_VOLUME := CTL_CODE(FILE_DEVICE_FILE_SYSTEM,8,METHOD_BUFFERED,FILE_ANY_ACCESS);
|
|
FSCTL_LOCK_VOLUME := CTL_CODE(FILE_DEVICE_FILE_SYSTEM,6,METHOD_BUFFERED,FILE_ANY_ACCESS);
|
|
FSCTL_UNLOCK_VOLUME := CTL_CODE(FILE_DEVICE_FILE_SYSTEM,7,METHOD_BUFFERED,FILE_ANY_ACCESS);
|
|
FSCTL_IS_VOLUME_MOUNTED := CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10,METHOD_BUFFERED,FILE_ANY_ACCESS);
|
|
FSCTL_ALLOW_EXTENDED_DASD_IO := CTL_CODE(FILE_DEVICE_FILE_SYSTEM,32,METHOD_BUFFERED,FILE_ANY_ACCESS);
|
|
//IOCTL_STORAGE_MEDIA_REMOVAL := ($2d shl 16) or (1 shl 14) or ($201 shl 2) or 0;
|
|
//IOCTL_STORAGE_EJECT_MEDIA := ($2d shl 16) or (1 shl 14) or ($202 shl 2) or 0;
|
|
}
|
|
|
|
end.
|
|
|