BSOne.SFC/Tocsg.Lib/VCL/Tocsg.Driver.pas

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.