BSOne.SFC/Tocsg.Module/Bs1Flt/bs1dc_Delphi/DeviceGuard.Logic.pas

1331 lines
42 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

unit DeviceGuard.Logic;
interface
uses
System.SysUtils, System.Classes, System.Generics.Collections, System.SyncObjs,
System.JSON, System.IOUtils, System.StrUtils,
Winapi.Windows, Winapi.Messages, Winapi.ActiveX,
Winapi.Bluetooth,
Tocsg.Obj, Tocsg.Driver, Tocsg.Path, Tocsg.Trace,
Bs1PolicyUnit,
Bs1FltCtrl;
const
// SetupAPI & CfgMgr »ó¼ö
DN_DRIVER_LOADED = $00000002;
DN_STARTED = $00000008;
DN_DISABLEABLE = $00002000;
DN_HAS_PROBLEM = $00000400;
CR_SUCCESS = $00000000;
// Property IDs
SPDRP_DEVICEDESC = $00000000;
SPDRP_HARDWAREID = $00000001;
SPDRP_COMPATIBLEIDS = $00000002;
SPDRP_SERVICE = $00000004;
SPDRP_CLASS = $00000007;
SPDRP_CLASSGUID = $00000008;
SPDRP_FRIENDLYNAME = $0000000C;
SPDRP_SECURITY = $00000017;
SPDRP_ENUMERATOR_NAME = $00000016; // ¿­°ÅÀÚ À̸§ (USB, PCI µî)
SPDRP_REMOVAL_POLICY = $0000001F;
SPDRP_INSTALL_STATE = $00000022;
DICS_ENABLE = 1;
DICS_DISABLE = 2;
DICS_PROPCHANGE = 3;
DICS_START = 4;
DICS_STOP = 5;
DICS_FLAG_GLOBAL = 1;
DICS_FLAG_CONFIGSPECIFIC = 2;
DIF_REMOVE = $00000005;
DIF_PROPERTYCHANGE = $00000012;
// Bluetooth Classes
COD_MAJOR_AUDIO = 4;
COD_MAJOR_PHONE = 2;
COD_MAJOR_PERIPHERAL = 5;
COD_MAJOR_WEARABLE = 7;
GUID_DEVCLASS_USB = '{36fc9e60-c465-11cf-8056-444553540000}';
GUID_DEVCLASS_PORTS = '{4d36e978-e325-11ce-bfc1-08002be10318}';
GUID_DEVCLASS_MODEM = '{4d36e96d-e325-11ce-bfc1-08002be10318}';
GUID_DEVCLASS_BLUETOOTH = '{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}';
GUID_DEVCLASS_NET = '{4d36e972-e325-11ce-bfc1-08002be10318}';
GUID_DEVCLASS_INFRARED = '{6bdd1fc5-810f-11d0-bec7-08002be2092f}';
GUID_DEVCLASS_1394 = '{6bdd1fc1-810f-11d0-bec7-08002be2092f}';
GUID_DEVCLASS_PCMCIA = '{4d36e977-e325-11ce-bfc1-08002be10318}';
GUID_DEVCLASS_WPD = '{eec5ad98-8080-425f-922a-dabf3de3f69a}';
GUID_DEVCLASS_DISKDRIVE = '{4d36e967-e325-11ce-bfc1-08002be10318}';
CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL = 1;
CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL = 2;
CM_INSTALL_STATE_FAILED_INSTALL = 2;
DICLASSPROP_INSTALLER = $00000002;
type
HDEVINFO = THandle;
DEVINST = DWORD;
// TPolicyState = (
// psAllow = 0;
// psBlock,
// psLog,
// psLogNone
// );
DEVPROPKEY = record
fmtid: TGUID;
pid: DWORD;
end;
PDEVPROPKEY = ^DEVPROPKEY;
DEVPROPTYPE = DWORD;
PSPClassInstallHeader = ^TSPClassInstallHeader;
TSPClassInstallHeader = packed record
cbSize: DWORD;
InstallFunction: DWORD;
end;
PSPPropChangeParams = ^TSPPropChangeParams;
TSPPropChangeParams = packed record
ClassInstallHeader: TSPClassInstallHeader;
StateChange: DWORD;
Scope: DWORD;
HwProfile: DWORD;
end;
PSPDevInfoListDetailData = ^TSPDevInfoListDetailData;
TSPDevInfoListDetailData = packed record
cbSize: DWORD;
ClassGuid: TGUID;
RemoteMachineHandle: THandle;
RemoteMachineName: array [0..255] of Char; // SP_MAX_MACHINENAME_LENGTH
end;
TDeviceInfoDTO = record
Index: Integer;
DevInst: DWORD;
ClassGuid: TGUID;
Desc: string;
HardwareID: string;
Service: string;
DeviceClass: string;
Enumerator: string;
RemovalPolicy: DWORD;
IsStarted: Boolean;
FriendlyName: string;
ParentId: string;
function GetMainHardwareID: string;
end;
TLogEvent = procedure(const Msg: string) of object;
TGuardThread = class(TThread)
private
FOwnerEngine: TObject;
procedure DoLog(const Msg: string);
procedure ShowPopup(const Msg: string);
protected
procedure Execute; override;
public
constructor Create(AOwnerEngine: TObject);
end;
TDeviceGuardEngine = class(TTgObject)
private
FThread: TGuardThread;
FScanEvent: TEvent;
FPolicyFilePath: string;
FOnLog: TLogEvent;
FOnPopup: TLogEvent;
FUseRestart: Boolean;
// ÇïÆÛ ÇÔ¼ö
function GetDeviceStringProperty(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; PropId: DWORD): string;
function GetDeviceStringPropertyDWORD(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): DWORD;
function SetDeviceState(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; Enable: Boolean): Boolean;
function GetDevicePropertyString(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA; const PropKey: DEVPROPKEY): string;
function GetClassPropertyString(const ClassGuid: TGUID; const PropKey: DEVPROPKEY): string;
function GetDeviceInstanceId(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA): string;
// [ÇÙ½É] ÀåÄ¡°¡ Á¤Ã¥°ú ÀÏÄ¡ÇÏ´ÂÁö °Ë»çÇÏ´Â ÇÔ¼ö
// function IsDeviceMatch(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; Policy: TPolicyItem; out DevName: string): Boolean;
procedure EnforceBluetoothPolicy(PolicyItem: TPolicyItem);
procedure ApplySingleMatch(Policy: TPolicyItem; Match: TMatchCriteria);
public
constructor Create;
destructor Destroy; override;
procedure Start;
procedure Stop;
procedure CreateDefaultPolicies;
function IsVirtualMachineDevice(const Info: TDeviceInfoDTO): Boolean;
function IsGeneralHIDDevice(const Info: TDeviceInfoDTO): Boolean;
function IsSystemOrCriticalDevice(const Info: TDeviceInfoDTO): Boolean;
procedure AllEnumSystemDevice;
// Á¤Ã¥ °ü¸®
// Ãʱâ Á¤Ã¥ µî·Ï (¸Þ¸ð¸®)
//procedure AddDefaultPolicy(const Name, GuidStr: string; IsBT: Boolean = False);
// [ÇÙ½É ±â´É]
procedure TriggerScan; // À̺¥Æ® ½Ã±×³Î ¹ß»ý
//procedure SavePolicyToFile; // ÇöÀç »óŸ¦ JSONÀ¸·Î ÀúÀå
//procedure LoadPolicyFromFile; // JSON¿¡¼­ Àо »óÅ ¾÷µ¥ÀÌÆ® ÈÄ ½ºÄµ Æ®¸®°Å
procedure EnforceSystemPolicy;
procedure CheckAndApplyPolicy(Policy: TPolicyItem);
procedure UsbPortApplyPolicy(state: TDeviceState);
function AddUsbPortExcept(const Vendor, Product,
Serial: string): Boolean;
property OnLog: TLogEvent read FOnLog write FOnLog;
property OnPopup: TLogEvent read FOnPopup write FOnPopup;
procedure UsbReStart;
function RestartDevice(hDevInfo: HDEVINFO; DevInfoData: SP_DEVINFO_DATA): Boolean;
function ScanForHardwareChanges: Boolean;
end;
function CM_Get_DevNode_Status(out pulStatus: DWORD; out pulProblemNumber: DWORD;
dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external 'cfgmgr32.dll' name 'CM_Get_DevNode_Status';
function CM_Locate_DevNode(var pdnDevInst: DEVINST; pDeviceID: PChar; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Locate_DevNodeW';
function CM_Reenumerate_DevNode(dnDevInst: DEVINST; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Reenumerate_DevNode';
function SetupDiGetDeviceInfoListDetail(DeviceInfoSet: HDEVINFO; DeviceInfoListDetailData: PSPDevInfoListDetailData): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceInfoListDetailW';
function SetupDiChangeState(DeviceInfoSet: HDEVINFO; DeviceInfoData: Pointer): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiChangeState';
var
gDeviceGuardEngine: TDeviceGuardEngine = nil;
DEVPKEY_Device_DeviceDesc: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 2);
DEVPKEY_Device_HardwareIds: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 3);
DEVPKEY_Device_Manufacturer: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 13);
DEVPKEY_Device_Parent: DEVPROPKEY = (fmtid: '{4340A6C5-93FA-4706-972C-7B648008A5A7}'; pid: 8);
DEVPKEY_Device_DriverDesc: DEVPROPKEY = (fmtid: '{A8B865DD-2E3D-4094-AD97-E593A708E5D3}'; pid: 2);
DEVPKEY_Device_BusReportedDeviceDesc: DEVPROPKEY = (fmtid: '{540B947E-8B40-45BC-A8A2-6A0B894CBDA2}'; pid: 4);
DEVPKEY_DeviceClass_Name: DEVPROPKEY = (fmtid: '{259ABFFC-50A7-47CE-AF08-68C9A7D73366}'; pid: 2);
function SetupDiGetDevicePropertyW(
DeviceInfoSet: HDEVINFO;
const DeviceInfoData: SP_DEVINFO_DATA;
const PropertyKey: DEVPROPKEY;
var PropertyType: DEVPROPTYPE;
PropertyBuffer: PByte; // ¹öÆÛ´Â Æ÷ÀÎÅÍ·Î Àü´Þ
PropertyBufferSize: DWORD;
var RequiredSize: DWORD;
Flags: DWORD
): BOOL; stdcall; external 'setupapi.dll';
function SetupDiGetClassPropertyW(
const ClassGuid: TGUID;
const PropertyKey: DEVPROPKEY;
var PropertyType: DEVPROPTYPE;
PropertyBuffer: PByte;
PropertyBufferSize: DWORD;
var RequiredSize: DWORD;
Flags: DWORD;
Reserved: PVOID
): BOOL; stdcall; external 'setupapi.dll';
function SetupDiGetDeviceInstanceId(
DeviceInfoSet: HDEVINFO;
const DeviceInfoData: SP_DEVINFO_DATA;
DeviceInstanceId: PWideChar;
DeviceInstanceIdSize: DWORD;
var RequiredSize: DWORD
): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceInstanceIdW';
implementation
{ TDeviceGuardEngine }
constructor TDeviceGuardEngine.Create;
var
path: string;
begin
gDeviceGuardEngine:= self;
FScanEvent := TEvent.Create(nil, False, False, '');
FThread := nil;
path:= GetRunExePathDir;
gBs1Policy:= TBs1Policy.Create;
gBs1Policy.LoadDataControlConfig;
if gBs1Policy.Policies.Count = 0 then
begin
//ShowMessage('ÀúÀåµÈ Á¤Ã¥ÀÌ ¾ø¾î ±âº» Á¤Ã¥À» »ý¼ºÇÕ´Ï´Ù.');
CreateDefaultPolicies;
end;
end;
destructor TDeviceGuardEngine.Destroy;
begin
Stop;
FScanEvent.Free;
gBs1Policy.Free;
inherited;
end;
procedure TDeviceGuardEngine.Start;
begin
if FThread <> nil then Exit;
FThread := TGuardThread.Create(Self);
FThread.Start;
end;
procedure TDeviceGuardEngine.Stop;
begin
if FThread <> nil then
begin
FThread.Terminate;
FScanEvent.SetEvent;
FThread.WaitFor;
FreeAndNil(FThread);
end;
end;
procedure TDeviceGuardEngine.CreateDefaultPolicies;
var
P: TPolicyItem;
begin
//µå¶óÀ̺ê Á¦¾î
P := gBs1Policy.CreatePolicy('BDC_CDROM', BDC_CDROM);
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('BDC_FLOOPY', BDC_FLOOPY);
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('BDC_USB_DISK', BDC_USB_DISK);
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('BDC_NETWORKDRIVEOUT', BDC_NETWORKDRIVEOUT);
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('BDC_NETWORKDRIVEIN', BDC_NETWORKDRIVEIN);
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('BDC_EXTERNALHDD', BDC_EXTERNALHDD);
gBs1Policy.AddPolicyObject(P);
///
///
//
// P := gBs1Policy.CreatePolicy('PCMCIA', BDC_PCMCIA);
// P.AddMatch(SPDRP_SERVICE, 'PCMCIA', 'PCI');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('SERIAL', BDC_SERIAL);
// P.AddMatch(SPDRP_SERVICE, 'Serial', 'ACPI');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('1394', BDC_1394);
// P.AddMatch(SPDRP_SERVICE, '1394', '1394');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('IRDA', BDC_IRDA);
// P.AddMatch(SPDRP_SERVICE, 'IRDA', 'IRDA');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('WIBRO', BDC_WIBRO);
// P.AddMatch(SPDRP_SERVICE, 'WIBRO', 'WIBRO');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('PARALLEL', BDC_PARALLEL);
// P.AddMatch(SPDRP_SERVICE, 'parport', 'ACPI');
// gBs1Policy.AddPolicyObject(P);
//
// P := gBs1Policy.CreatePolicy('MODEM', BDC_MODEM);
// P.AddMatch(SPDRP_SERVICE, 'MODEM', 'MODEM');
// gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('USB', BDC_USB);
P.AddMatch(SPDRP_SERVICE, 'USBSTOR', 'USB');
P.AddMatch(SPDRP_SERVICE, 'USBAAPL', 'USB');
P.AddMatch(SPDRP_SECURITY, 'Apple', 'USB');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('MTP', BDC_MTP, GUID_DEVCLASS_WPD);
P.AddMatch(SPDRP_HARDWAREID, '_mtp', 'USB');
P.AddMatch(SPDRP_COMPATIBLEIDS, '_mtp', 'USB');
P.AddMatch(SPDRP_DEVICEDESC, 'apple', 'USB');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('TETHERING', BDC_TETHERING);
P.AddMatch(SPDRP_SERVICE, 'usb_rndisx', 'USB');
P.AddMatch(SPDRP_SERVICE, 'usb_rndisk', 'USB');
P.AddMatch(SPDRP_SERVICE, 'Netaapl', 'USB');
P.AddMatch(SPDRP_SERVICE, 'andnetndis', 'USB');
P.AddMatch(SPDRP_SERVICE, 'lgwqmindis', 'USB');
P.AddMatch(SPDRP_SERVICE, 'usbrndis6', 'USB');
P.AddMatch(SPDRP_SERVICE, 'BthPan', 'BTH');
P.AddMatch(SPDRP_SERVICE, 'RFCOMM', 'BTH');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('SDCARD', BDC_SDCARD);
P.AddMatch(SPDRP_SERVICE, 'risdxc', 'PCI');
P.AddMatch(SPDRP_SERVICE, 'disk', 'RISD');
P.AddMatch(SPDRP_SERVICE, 'sffdisk', 'SD');
P.AddMatch(SPDRP_SERVICE, 'sdbus', 'PCI');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('WIRELESS', BDC_WIRELESS);
P.AddMatch(SPDRP_SERVICE, 'mtkwlex', 'PCI');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('WEBCAM', BDC_WEBCAM);
P.AddMatch(SPDRP_SERVICE, 'usbvideo', 'USB');
gBs1Policy.AddPolicyObject(P);
P := gBs1Policy.CreatePolicy('Bluetooth', BDC_BLUETOOTH, '');
gBs1Policy.AddPolicyObject(P);
// P := gBs1Policy.CreatePolicy('Bluetooth File', BDC_BLUETOOTH_FILE, '');
// P.AddMatch(SPDRP_SERVICE, 'BTHUSB', 'USB');
// P.AddMatch(SPDRP_SERVICE, 'BTWUSB', 'USB');
// P.AddMatch(SPDRP_SERVICE, 'BTMUSB', 'USB');
gBs1Policy.AddPolicyObject(P);
end;
procedure TDeviceGuardEngine.TriggerScan;
begin
if FScanEvent <> nil then
FScanEvent.SetEvent;
end;
{
// -----------------------------------------------------------------------------
// [ÇÙ½É] ÀåÄ¡ ¸ÅĪ ·ÎÁ÷ (C++ SetStateControlDevNode ·ÎÁ÷ ±¸Çö)
// -----------------------------------------------------------------------------
function TDeviceGuardEngine.IsDeviceMatch(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; Policy: TPolicyItem; out DevName: string): Boolean;
var
DevEnum, DevPropVal: string;
begin
Result := False;
DevName := '';
// 1. Enumerator È®ÀÎ (¼³Á¤µÈ °æ¿ì¸¸)
// ¿¹: "PCI", "USB" µî
if Policy.targetEnumerator_ <> '' then
begin
DevEnum := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_ENUMERATOR_NAME).ToUpper;
// ºÎºÐ ÀÏÄ¡°¡ ¾Æ´Ï¶ó Á¤È®È÷ ÀÏÄ¡ÇØ¾ß ÇÔ (ÇÊ¿ä ½Ã Contains·Î º¯°æ °¡´É)
if DevEnum <> Policy.targetEnumerator_ then Exit;
end;
// 2. Property È®ÀÎ
// ¿¹: SPDRP_SERVICE °ªÀÌ "PCMCIA" ÀÎÁö È®ÀÎ
// ¿¹: SPDRP_CLASSGUID °ªÀÌ "..." ÀÎÁö È®ÀÎ
DevPropVal := GetDeviceStringProperty(DevInfoSet, DevData, Policy.matchPropType_).ToUpper;
// °ªÀÌ ºñ¾îÀÖÀ¸¸é ¸ÅĪ ½ÇÆÐ
if DevPropVal = '' then Exit;
// ºÎºÐ ¹®ÀÚ¿­ ¸ÅĪ (Contains) Çã¿ë -> GUID´Â Á¤È®È÷, À̸§Àº Æ÷ÇÔ µî À¯¿¬ÇϰÔ
if Pos(Policy.matchData_, DevPropVal) > 0 then
begin
// ¸ÅĪ ¼º°ø!
Result := True;
// ·Î±×¿ë À̸§ ÃßÃâ
DevName := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_FRIENDLYNAME);
if DevName = '' then DevName := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_DEVICEDESC);
end;
end;
}
function TDeviceGuardEngine.ScanForHardwareChanges: Boolean;
var
LDevInst: DEVINST;
status: CONFIGRET;
begin
LDevInst := 0;
//CM_LOCATE_DEVNODE_NORMAL = $00000000;
status := CM_Locate_DevNode(LDevInst, nil, $00000000);
if status <> CR_SUCCESS then
begin
_Trace(Format('[BS1]ScanForHardwareChanges, CM_Locate_DevNode failed: %x', [status]));
Result := False;
Exit;
end;
status := CM_Reenumerate_DevNode(LDevInst, 0);
if status <> CR_SUCCESS then
begin
_Trace(Format('[BS1]ScanForHardwareChanges, CM_Reenumerate_DevNode failed: %x', [status]));
Result := False;
Exit;
end;
Result := True;
end;
function TDeviceGuardEngine.RestartDevice(hDevInfo: HDEVINFO; DevInfoData: SP_DEVINFO_DATA): Boolean;
var
params: TSPPropChangeParams;
begin
FillChar(params, SizeOf(TSPPropChangeParams), 0);
params.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
params.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
params.StateChange := DICS_PROPCHANGE; // Restart (Stop -> Start)
params.Scope := DICS_FLAG_CONFIGSPECIFIC;
params.HwProfile := 0;
_Trace('[BS1] .... 1');
if not SetupDiSetClassInstallParams(hDevInfo, @DevInfoData, @params.ClassInstallHeader, SizeOf(TSPPropChangeParams)) then
begin
_Trace(Format('[BS1] SetupDiSetClassInstallParams Fail(%d)', [GetLastError]));
Result := False;
Exit;
end;
_Trace('[BS1] .... 2');
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DevInfoData) then
begin
_Trace(Format('[BS1] SetupDiCallClassInstaller Fail(%d)', [GetLastError]));
Result := False;
Exit;
end;
_Trace('[BS1] .... 3');
if not SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, @DevInfoData) then
begin
_Trace(Format('[BS1] SetupDiCallClassInstaller(DIF_REMOVE) Fail(%d)', [GetLastError]));
Result := False;
Exit;
end;
_Trace('[BS1] .... 4');
// ChangeState È£Ãâ
SetupDiChangeState(hDevInfo, @DevInfoData);
_Trace(Format('[BS1] SetupDiCallClassInstaller Succeed(%d)', [GetLastError]));
Result := True;
end;
procedure TDeviceGuardEngine.UsbReStart;
const
DIGCF_PRESENT = $00000002;
DIGCF_ALLCLASSES = $00000004;
var
hDevInfo: THandle;
DeviceInfoData: SP_DEVINFO_DATA;
devInfoListDetail: TSPDevInfoListDetailData;
devIndex: Integer;
sService: string;
sHardwareID: string;
sSecurity: string;
begin
// ÀåÄ¡ Á¤º¸ ¼¼Æ® °¡Á®¿À±â
hDevInfo := SetupDiGetClassDevs(nil, nil, 0, DIGCF_PRESENT or DIGCF_ALLCLASSES);
if hDevInfo = INVALID_HANDLE_VALUE then
begin
_Trace('[BS1] SetupDiGetClassDevs Failed');
Exit;
end;
try
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
devInfoListDetail.cbSize := SizeOf(TSPDevInfoListDetailData);
SetupDiGetDeviceInfoListDetail(hDevInfo, @devInfoListDetail);
devIndex := 0;
while SetupDiEnumDeviceInfo(hDevInfo, devIndex, DeviceInfoData) do
begin
// Class GUID ºñ±³ ({36FC9E60-C465-11CF-8056-444553540000})
if IsEqualGUID(DeviceInfoData.ClassGuid, StringToGUID(GUID_DEVCLASS_USB)) then
begin
// 1. Service ¸í È®ÀÎ (SPDRP_SERVICE)
sService := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_SERVICE);
_Trace(Format('[BS1] SPDRP_SERVICE = [%s]', [sService]));
if (SameText(sService, 'USBSTOR')) or (SameText(sService, 'USBAAPL')) then
begin
// 2. Hardware ID È®ÀÎ
sHardwareID := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_HARDWAREID);
_Trace(Format('[BS1] SPDRP_HARDWAREID = [%s]', [sHardwareID]));
// VID_05E3ÀÌ Æ÷ÇԵǾî ÀÖÁö ¾ÊÀ¸¸é Disable ó¸®
if Pos('VID_05E3', sHardwareID) = 0 then
begin
_Trace('[BS1] PASS~!');
// ¿øº» ·ÎÁ÷: Disable ¼öÇà
//SetDeviceState(hDevInfo, DeviceInfoData, True);
RestartDevice(hDevInfo, DeviceInfoData); // ¿øº» ÁÖ¼® 󸮵Ê
Inc(devIndex);
Continue;
end;
end;
// 3. Apple ÀåÄ¡ È®ÀÎ (SPDRP_SECURITY_SDS -> SPDRP_SECURITY)
sSecurity := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_SECURITY);
_Trace(Format('[BS1] SPDRP_SECURITY_SDS = [%s]', [sSecurity]));
// "Apple" ¹®ÀÚ¿­ÀÌ Æ÷ÇԵǰųª °°À¸¸é Restart
// C++ ¿øº»: memcmp(devID, "Apple", ...) -> Á¤È®È÷ "Apple"·Î ½ÃÀÛÇÏ´ÂÁö üũ
if Pos('Apple', sSecurity) > 0 then
begin
RestartDevice(hDevInfo, DeviceInfoData);
// SetDeviceState(hDevInfo, DeviceInfoData, True);
Inc(devIndex);
Continue;
end;
end;
Inc(devIndex);
end;
// Çϵå¿þ¾î º¯°æ »çÇ× °Ë»ö
ScanForHardwareChanges();
finally
SetupDiDestroyDeviceInfoList(hDevInfo);
end;
end;
procedure TDeviceGuardEngine.ApplySingleMatch(Policy: TPolicyItem; Match: TMatchCriteria);
var
hDevInfo: THandle;
DevInfoData: SP_DEVINFO_DATA;
Idx: DWORD;
ClassGuid: TGUID;
PClassGuid: PGUID;
Flags: DWORD;
Enumerator: PChar;
CurrentPropVal: string;
DevName: string;
dwStatus, dwProblem: DWORD;
bIsMatch: Boolean;
text: string;
IsLog: Boolean;
begin
PClassGuid := nil;
Flags := DIGCF_PRESENT;
Enumerator := nil;
// 1. GUID ¼³Á¤ (Á¤Ã¥ ·¹º§)
if Policy.targetGUID_ <> '' then
begin
ClassGuid := StringToGUID(Policy.targetGUID_);
PClassGuid := @ClassGuid;
end
else
begin
Flags := Flags or DIGCF_ALLCLASSES;
end;
// 2. Enumerator ¼³Á¤ (Match ·¹º§)
if Match.Enumerator <> '' then
Enumerator := PChar(Match.Enumerator);
hDevInfo := SetupDiGetClassDevs(PClassGuid, Enumerator, 0, Flags);
if hDevInfo = INVALID_HANDLE_VALUE then Exit;
try
Idx := 0;
DevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
while SetupDiEnumDeviceInfo(hDevInfo, Idx, DevInfoData) do
begin
bIsMatch := False;
// 3. MatchData ºñ±³
if Match.MatchData <> '' then
begin
CurrentPropVal := GetDeviceStringProperty(hDevInfo, DevInfoData, Match.PropType).ToUpper;
if (CurrentPropVal <> '') and (Pos(Match.MatchData.ToUpper, CurrentPropVal) > 0) then
bIsMatch := True;
end
else
bIsMatch := True; // µ¥ÀÌÅÍ ¾øÀ¸¸é ¹«Á¶°Ç ¸ÅĪ
//TGuardThread(FThread).DoLog(Format('(%s)(%d), Match.Enumerator : (%s) PropType : %x (PropVal: %s<>%s)', [Policy.name, DWORD(bIsMatch), Match.Enumerator, Match.PropType, Match.MatchData.ToUpper, CurrentPropVal]));
if bIsMatch then
begin
//USBSTOR\DISK&VEN_VENDORCO&PROD_PRODUCTCODE&REV_2.00\8328501217610604362&0
var friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
if friendlyName = '' then
friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
var HardwareID := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_HARDWAREID);
var DeviceClass := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_CLASS);
var Service := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_SERVICE);
var RemovalPolicy := GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_REMOVAL_POLICY);
var InstatllState:= GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_INSTALL_STATE);
var ParentId := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Parent);
var DeviceDriveDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DriverDesc);
var Manufacturer := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Manufacturer);
var DeviceDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DeviceDesc);
var InstanceId:= GetDeviceInstanceId(hDevInfo, DevInfoData);
//TGuardThread(FThread).DoLog(Format('InstanceId : %s', [InstanceId]));
// »óÅ Á¦¾î (Block/Allow)
if CM_Get_DevNode_Status(dwStatus, dwProblem, DevInfoData.DevInst, 0) = CR_SUCCESS then
begin
_Trace(Format('[BS1] CM_Get_DevNode_Status, dwStatus: %d' , [dwStatus]));
DevName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
if DevName = '' then DevName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
//TGuardThread(FThread).DoLog(Format('DevName : %s, state : %d', [DevName, DWORD(Policy.state_)]));
case Policy.state_ of
dsDisable:
begin
if (Policy.flag_ = DWORD(BDC_USB)) and gBs1Policy.IsUsbPortExcept(InstanceId) then
begin
_Trace('[BS1]' + text + '¿¹¿Ü' + ParentId);
text:= '------------------------> [Çã¿ë] ';
if ((dwStatus and DN_DISABLEABLE) <> 0) and ((dwStatus and DN_HAS_PROBLEM) <> 0) then
begin
if SetDeviceState(hDevInfo, DevInfoData, True) then
begin
IsLog:= True;
_Trace('[BS1]' + text + DevName);
end;
end;
break;
end
else
begin
text:= '------------------------> [Â÷´Ü] ';
if ((dwStatus and DN_DRIVER_LOADED) <> 0) and ((dwStatus and DN_STARTED) <> 0) then
begin
if SetDeviceState(hDevInfo, DevInfoData, False) then
begin
IsLog:= True;
_Trace(text + DevName);
// TGuardThread(FThread).ShowPopup(DevName);
end;
end;
end;
end;
dsReadOnly,
dsEnable:
begin
text:= '------------------------> [Çã¿ë] ';
if ((dwStatus and DN_DISABLEABLE) <> 0) and ((dwStatus and DN_HAS_PROBLEM) <> 0) then
begin
if SetDeviceState(hDevInfo, DevInfoData, True) then
begin
IsLog:= True;
_Trace('[BS1]' + text + DevName);
end;
end;
end;
end;
if Policy.isLog_ and IsLog then
begin
_Trace(Format('[BS1] [ŽÁö](%s) %s (Rule: %s)', [text, DevName, Policy.Name]));
_Trace(Format(
'[BS1] Service:%s, DeviceClass:%s, friendlyName:%s, HardwareID:%s', [Service, DeviceClass, friendlyName, HardwareID]));
_Trace(Format(
'[BS1] ParentId:%s, DeviceDriveDesc:%s, Manufacturer:%s, RemovalPolicy:%d, InstatllState:%d',
[ParentId, DeviceDriveDesc, Manufacturer, DWORD(RemovalPolicy), DWORD(InstatllState)]));
_Trace(Format('[BS1] InstanceId:%s', [InstanceId]));
_Trace('-----------------------------------------------------');
end;
IsLog:= False;
end
else
begin
_Trace(Format('[BS1] CM_Get_DevNode_Status Fail : %d', [GetLastError]));
end;
end;
Inc(Idx);
end;
finally
SetupDiDestroyDeviceInfoList(hDevInfo);
end;
end;
procedure TDeviceGuardEngine.CheckAndApplyPolicy(Policy: TPolicyItem);
begin
// Match Ç׸ñÀÌ ¾øÀ¸¸é ½ÇÇàÇÏÁö ¾ÊÀ½ (´Ü, ºí·çÅõ½º µî ¿¹¿Ü Á¦¿Ü)
// ¶Ç´Â Match°¡ ¾øÀ¸¸é Â÷´Ü/Çã¿ëÀ» ¸øÇϹǷΠÆÐ½º
if Policy.Matches_.Count = 0 then Exit;
_Trace(Format('[BS1] Enumerator : state(%d)', [DWORD(Policy.state_)]));
for var Match in Policy.Matches_ do
begin
_Trace(Format('[BS1] Enumerator : (%s) MatchData : (%s)', [Match.Enumerator, Match.MatchData]));
ApplySingleMatch(Policy, Match);
end;
end;
procedure TDeviceGuardEngine.UsbPortApplyPolicy(state: TDeviceState);
var
tmp : TPolicyItem;
begin
tmp:= gBs1Policy.GetPolicyItem(DWORD(BDC_USB));
tmp.state_:= state;
CheckAndApplyPolicy(tmp);
end;
function TDeviceGuardEngine.AddUsbPortExcept(const Vendor, Product, Serial: string): Boolean;
begin
gBs1Policy.AddUsbPortExcept(Vendor, Product, Serial);
end;
procedure TDeviceGuardEngine.EnforceSystemPolicy;
var
Policies: TObjectList<TPolicyItem>;
tmp : TPolicyItem;
begin
Policies := TObjectList<TPolicyItem>.Create(True);
// µî·ÏµÈ ¸ðµç Á¤Ã¥¿¡ ´ëÇØ ¼øÈ¸
try
if gBs1Policy <> nil then
begin
gBs1Policy.CopyPoliciesTo(Policies);
end;
for var Policy in Policies do
begin
// ºí·çÅõ½º´Â º°µµ ·ÎÁ÷
// if Policy.isBluetooth_ then
// begin
// EnforceBluetoothPolicy(Policy);
// Continue;
// end;
case Policy.flag_ of
DWORD(BDC_CDROM),
DWORD(BDC_FLOOPY),
DWORD(BDC_USB_DISK),
DWORD(BDC_NETWORKDRIVEOUT),
DWORD(BDC_NETWORKDRIVEIN),
DWORD(BDC_EXTERNALHDD):
continue;
end;
// ÀÏ¹Ý ÀåÄ¡ Á¦¾î (SetupDiGetClassDevs -> Enum -> Match)
// gBs1fltControl.SetPolicy(Policy.flag_, DWORD(Policy.state_), DWORD(Policy.isLog_));
// if (Policy.flag_ <> DWORD(BDC_MTP)) then
// begin
// end;
_Trace(Format('[BS1] EnforceSystemPolicy, flag(%d), state(%d),log(%d)', [DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_)]));
if (Policy.flag_ = DWORD(BDC_BLUETOOTH_FILE)) then
begin
continue;
end
else if (Policy.flag_ = DWORD(BDC_MTP)) then
begin
var state: TDeviceState;
var log: Boolean;
gBs1Policy.GetPolicyState(DWORD(BDC_USB), state, log);
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_USB, state(%d) log : (%d)', [DWORD(state), DWORD(log)]));
if (Policy.state_ = dsEnable) and (state = dsDisable) then
begin
// /CheckAndApplyPolicy(Policy);
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_MTP, dsEnable', []));
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
end
else
begin
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_MTP, dsDisable', []));
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
CheckAndApplyPolicy(Policy);
end;
continue;
end;
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
// else if (Policy.flag_ = DWORD(BDC_USB)) then
// begin
// if (TDeviceState(Policy.state_) = dsDisable) then
// begin
// if not FUseRestart then
// begin
// UsbReStart;
// FUseRestart:= True;
// end;
// OnLog('UsbReStart Sucess...');
// end
// else
// begin
// FUseRestart:= False;
// end;
//
// continue;
// end;
CheckAndApplyPolicy(Policy);
end;
finally
Policies.Free;
end;
end;
function TDeviceGuardEngine.IsVirtualMachineDevice(const Info: TDeviceInfoDTO): Boolean;
begin
// Á¦°ÅÁ¤Ã¥ 2¹øÀ̸鼭 ƯÁ¤ Ŭ·¡½ºÀÎ °æ¿ì (VMware, VirtualBox µî ¹æ¾î)
if Info.RemovalPolicy = CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL then
begin
// if SameText(Info.DeviceClass, 'Net') or
if SameText(Info.DeviceClass, 'Monitor') or
SameText(Info.DeviceClass, 'System') or
SameText(Info.DeviceClass, 'HDC') or
SameText(Info.DeviceClass, 'DiskDrive') or
SameText(Info.DeviceClass, 'MEDIA') or
SameText(Info.DeviceClass, 'Display') then
begin
Exit(True); // °Ç³Ê¶Ù¾î¾ß ÇÔ
end;
end;
Result := False;
end;
function TDeviceGuardEngine.IsGeneralHIDDevice(const Info: TDeviceInfoDTO): Boolean;
begin
// Űº¸µå, ¸¶¿ì½º µîÀº Àý´ë Â÷´ÜÇÏ¸é ¾È µÊ
if (Pos('KEYBOARD', UpperCase(Info.DeviceClass)) > 0) or
(Pos('MOUSE', UpperCase(Info.DeviceClass)) > 0) or
(SameText(Info.DeviceClass, 'HIDClass')) then
begin
Result := True;
end
else
Result := False;
end;
function TDeviceGuardEngine.IsSystemOrCriticalDevice(const Info: TDeviceInfoDTO): Boolean;
begin
// °íÁ¤ ÀåÄ¡ (Removal Policy 1)
if Info.RemovalPolicy = CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL then
Exit(True);
// ¿­°ÅÀÚ(Enumerator)¿Í ¼­ºñ½º/Ŭ·¡½º Á¶ÇÕ È®ÀÎ
if (SameText(Info.Enumerator, 'SCSI') and SameText(Info.Service, 'DISK')) or
(SameText(Info.Enumerator, 'PCI') and SameText(Info.Service, 'nvlddmkm')) or // NVIDIA ±×·¡ÇÈ
(SameText(Info.Enumerator, 'SCSI') and SameText(Info.DeviceClass, 'DiskDrive')) or
(SameText(Info.Enumerator, 'PCI') and SameText(Info.DeviceClass, 'Display')) then
begin
Exit(True);
end;
// ƯÁ¤ Ŭ·¡½º À̸§ È®ÀÎ (¼ÒÇÁÆ®¿þ¾î ÀåÄ¡, ¿Àµð¿À, ÇÁ¸°ÅÍ µî)
// MatchText¸¦ ¾²¸é OR ¿¬»êÀ» ¹è¿­·Î ±ò²ûÇÏ°Ô Ã³¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù.
if MatchText(Info.DeviceClass, ['AudioEndpoint',
'PrintQueue',
'SoftwareDevice',
'WSDPrintDevice',
'Image']) then
begin
Exit(True);
end;
Result := False;
end;
function TDeviceInfoDTO.GetMainHardwareID: string;
begin
// HardwareID´Â ¸ÖƼ½ºÆ®¸µÀ̹ǷΠù ¹øÂ° ÁÙ¸¸ °¡Á®¿À°Å³ª ÆÄ½Ì
// ¿¹: USB\VID_1234&PID_5678...
Result := HardwareID.Split([#0], TStringSplitOptions.ExcludeEmpty)[0];
end;
procedure TDeviceGuardEngine.AllEnumSystemDevice;
var
hDevInfo: THandle;
DevInfoData: SP_DEVINFO_DATA;
Idx: DWORD;
MatchedItem: TPolicyItem;
IsMatchFound: Boolean;
DevName: string;
Info: TDeviceInfoDTO;
UniqueKey: string;
dwStatus, dwProblem: DWORD;
InstatllState: DWORD;
begin
hDevInfo := SetupDiGetClassDevs(nil, nil, 0, DIGCF_PRESENT or DIGCF_ALLCLASSES);
if hDevInfo = INVALID_HANDLE_VALUE then Exit;
try
Idx := 0;
DevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
while SetupDiEnumDeviceInfo(hDevInfo, Idx, DevInfoData) do
begin
try
MatchedItem := nil;
IsMatchFound := False;
DevName := '';
Info.Index := Idx;
Info.friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
if Info.friendlyName = '' then
Info.friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
Info.HardwareID := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_HARDWAREID);
Info.DeviceClass := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_CLASS);
Info.Service := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_SERVICE);
Info.Enumerator := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_ENUMERATOR_NAME);
Info.RemovalPolicy := GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_REMOVAL_POLICY);
InstatllState:= GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_INSTALL_STATE);
Info.ParentId := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Parent);
var DeviceDriveDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DriverDesc);
var Manufacturer := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Manufacturer);
var DeviceDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DeviceDesc);
if Info.DeviceClass = '' then
Continue;
if InstatllState = CM_INSTALL_STATE_FAILED_INSTALL then
Continue;
if IsVirtualMachineDevice(Info) then Continue; // VM ¿¹¿Ü
if IsSystemOrCriticalDevice(Info) then Continue; // ½Ã½ºÅÛ ÀåÄ¡ ¿¹¿Ü
if IsGeneralHIDDevice(Info) then Continue; // Űº¸µå/¸¶¿ì½º ¿¹¿Ü
// ÀåÄ¡ ³ëµå »óÅ ȮÀÎ (Start ¿©ºÎ)
if CM_Get_DevNode_Status(dwStatus, dwProblem, DevInfoData.DevInst, 0) = CR_SUCCESS then
begin
Info.IsStarted := (dwStatus and DN_STARTED) <> 0;
end
else
Continue; // »óÅ ȮÀÎ ºÒ°¡ ÀåÄ¡´Â ÆÐ½º
UniqueKey := Info.GetMainHardwareID;
if FThread <> nil then
begin
_Trace(Format('[BS1] [Ŭ·¡½º ¸í] : Name : %s, Class : %s', [Info.DeviceClass, DevInfoData.ClassGuid.ToString]));
_Trace(
Format('[BS1] serviceName : %s || enumeratorName : %s || friendlyName: %s || HWID: %s || RemovalPolicy: %d || UniqueKey: %s',
[Info.Service, Info.Enumerator, Info.friendlyName, Info.HardwareID, Info.RemovalPolicy, UniqueKey]));
_Trace(
Format('[BS1] ParentId : %s || DeviceDriveDesc : %s || Manufacturer: %s || DeviceDesc: %s\n',
[Info.ParentId, DeviceDriveDesc, Manufacturer, DeviceDesc]));
end;
sleep(10);
finally
Inc(Idx);
end;
end;
finally
SetupDiDestroyDeviceInfoList(hDevInfo);
end;
end;
function TDeviceGuardEngine.GetDevicePropertyString(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA; const PropKey: DEVPROPKEY): string;
var
PropType: DEVPROPTYPE;
ReqSize: DWORD;
Buffer: array of Byte;
begin
Result := '';
ReqSize := 0;
// 1. Å©±â Á¶È¸
if not SetupDiGetDevicePropertyW(hDevInfo, DevData, PropKey, PropType, nil, 0, ReqSize, 0) then
begin
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
end;
if ReqSize = 0 then Exit;
// 2. µ¥ÀÌÅÍ Á¶È¸
SetLength(Buffer, ReqSize);
if SetupDiGetDevicePropertyW(hDevInfo, DevData, PropKey, PropType, @Buffer[0], ReqSize, ReqSize, 0) then
begin
// DEVPROP_TYPE_STRING È®ÀÎ ·ÎÁ÷ÀÌ ÇÊ¿äÇÒ ¼ö ÀÖÀ¸³ª, ¿©±â¼± ¹®ÀÚ¿­ÀÌ¶ó °¡Á¤ÇÏ°í º¯È¯
Result := TEncoding.Unicode.GetString(Buffer);
Result := Result.TrimRight([#0]); // NULL Á¾·á ¹®ÀÚ Á¦°Å
end;
end;
function TDeviceGuardEngine.GetClassPropertyString(const ClassGuid: TGUID; const PropKey: DEVPROPKEY): string;
var
PropType: DEVPROPTYPE;
ReqSize: DWORD;
Buffer: array of Byte;
begin
Result := '';
ReqSize := 0;
// 1. Å©±â Á¶È¸
if not SetupDiGetClassPropertyW(ClassGuid, PropKey, PropType, nil, 0, ReqSize, DICLASSPROP_INSTALLER, 0) then
begin
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
end;
if ReqSize = 0 then Exit;
// 2. µ¥ÀÌÅÍ Á¶È¸
SetLength(Buffer, ReqSize);
if SetupDiGetClassPropertyW(ClassGuid, PropKey, PropType, @Buffer[0], ReqSize, ReqSize, DICLASSPROP_INSTALLER, 0) then
begin
Result := TEncoding.Unicode.GetString(Buffer);
Result := Result.TrimRight([#0]);
end;
end;
function TDeviceGuardEngine.GetDeviceStringProperty(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): string;
var
Buffer: TBytes;
Size, ReqSize: DWORD;
DataType: DWORD;
dwPropertyRegDataType: DWORD;
begin
Result := '';
ReqSize := 0;
SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, dwPropertyRegDataType, nil, 0, ReqSize);
if (GetLastError = ERROR_INSUFFICIENT_BUFFER) and (ReqSize > 0) then
begin
SetLength(Buffer, ReqSize);
if SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, DataType, @Buffer[0], ReqSize, Size) then
if (DataType = REG_SZ) or (DataType = REG_MULTI_SZ) then
Result := TEncoding.Unicode.GetString(Buffer).Trim([#0]);
end;
end;
function TDeviceGuardEngine.GetDeviceStringPropertyDWORD(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): DWORD;
var
ReqSize, DataType: DWORD;
begin
Result := 0;
SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, DataType, @Result, SizeOf(DWORD), ReqSize);
end;
function TDeviceGuardEngine.GetDeviceInstanceId(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA): string;
var
ReqSize: DWORD;
Buffer: array of Char; // µ¿Àû ¹è¿­ »ç¿ë
begin
Result := '';
ReqSize := 0;
// 1. ÇÊ¿äÇÑ ¹öÆÛ Å©±â ±¸Çϱâ
// ÇÔ¼ö°¡ False¸¦ ¸®ÅÏÇϰí GetLastError°¡ ERROR_INSUFFICIENT_BUFFERÀÏ ¶§ Á¤»ó
if not SetupDiGetDeviceInstanceId(hDevInfo, DevData, 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(hDevInfo, DevData, @Buffer[0], ReqSize, ReqSize) then
begin
// PChar·Î º¯È¯ÇÏ¿© µ¨ÆÄÀÌ ½ºÆ®¸µ¿¡ ´ã±â
Result := PChar(@Buffer[0]);
Result := Trim(Result); // Ȥ½Ã ¸ð¸¦ °ø¹é Á¦°Å
end;
end;
function TDeviceGuardEngine.SetDeviceState(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; Enable: Boolean): Boolean;
var
PCP: SP_PROPCHANGE_PARAMS;
state : DWORD;
begin
FillChar(PCP, SizeOf(PCP), 0);
PCP.ClassInstallHeader.cbSize := SizeOf(PCP.ClassInstallHeader);
PCP.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
if Enable then
PCP.StateChange := DICS_ENABLE
else
PCP.StateChange := DICS_DISABLE;
PCP.Scope := DICS_FLAG_GLOBAL;
PCP.HwProfile := 0;
if not SetupDiSetClassInstallParams(DevInfoSet, @DevData, @PCP, SizeOf(PCP)) then
Exit(False);
Result := SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DevInfoSet, @DevData);
if Result then
begin
state:= DWORD(SetupDiChangeState(DevInfoSet, @DevData));
if state = 0 then
begin
_Trace('[BS1] SetupDiChangeState Fail : ' + GetLastError.ToString);
Result:= False;
end;
end
else
begin
_Trace('[BS1] SetupDiCallClassInstaller Fail : ' + GetLastError.ToString);
end;
end;
procedure TDeviceGuardEngine.EnforceBluetoothPolicy(PolicyItem: TPolicyItem);
var
SearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS;
DeviceInfo: BLUETOOTH_DEVICE_INFO;
DeviceHandle: HBLUETOOTH_DEVICE_FIND;
MajorClass: Cardinal;
IsTarget: Boolean;
begin
if PolicyItem.state_ = dsEnable then Exit;
FillChar(SearchParams, SizeOf(SearchParams), 0);
SearchParams.dwSize := SizeOf(SearchParams);
SearchParams.fReturnAuthenticated := True;
SearchParams.fReturnConnected := True;
SearchParams.fReturnRemembered := True;
SearchParams.fReturnUnknown := True;
SearchParams.fIssueInquiry := False;
FillChar(DeviceInfo, SizeOf(DeviceInfo), 0);
DeviceInfo.dwSize := SizeOf(DeviceInfo);
DeviceHandle := BluetoothFindFirstDevice(SearchParams, DeviceInfo);
if DeviceHandle = 0 then Exit;
try
repeat
MajorClass := (DeviceInfo.ulClassofDevice and $1F00) shr 8;
IsTarget := False;
// KCD_BLUETOOTH(Àüü) ¶Ç´Â KCD_BLUETOOTH_FILE(ÀϺÎ) µî¿¡ µû¶ó ·ÎÁ÷ ºÐ±â °¡´É
// ¿©±â¼± ±âÁ¸ ·ÎÁ÷´ë·Î ¿Àµð¿À/Æù/¿þ¾î·¯ºí Â÷´Ü
if (MajorClass = COD_MAJOR_AUDIO) or (MajorClass = COD_MAJOR_PHONE) or (MajorClass = COD_MAJOR_WEARABLE) then
IsTarget := True;
if MajorClass = COD_MAJOR_PERIPHERAL then IsTarget := False;
if IsTarget and (PolicyItem.state_ = dsDisable) then
begin
if BluetoothRemoveDevice(DeviceInfo.Address) = ERROR_SUCCESS then
begin
if FThread <> nil then
begin
_Trace('[BS1] [BT Â÷´Ü] ' + DeviceInfo.szName);
//TGuardThread(FThread).ShowPopup('BT: ' + DeviceInfo.szName);
end;
end;
end;
until not BluetoothFindNextDevice(DeviceHandle, DeviceInfo);
finally
BluetoothFindDeviceClose(DeviceHandle);
end;
end;
{ TGuardThread }
constructor TGuardThread.Create(AOwnerEngine: TObject);
begin
inherited Create(True);
FOwnerEngine := AOwnerEngine;
FreeOnTerminate := False;
end;
procedure TGuardThread.Execute;
var
Engine: TDeviceGuardEngine;
WaitResult: TWaitResult;
begin
Engine := TDeviceGuardEngine(FOwnerEngine);
while not Terminated do
begin
WaitResult := Engine.FScanEvent.WaitFor(INFINITE);
if Terminated then Break;
if WaitResult = wrSignaled then
begin
try
Engine.EnforceSystemPolicy;
except
on E: Exception do OutPutDebugStringW(PChar('[BS1] Scan Error: ' + E.Message));
end;
// ÀÚµ¿ ¸®¼Â À̺¥Æ®°¡ ¾Æ´Ï¸é ResetEvent È£Ãâ ÇÊ¿ä, ¿©±â¼± Create½Ã ÀÚµ¿ ¸®¼ÂÀ¸·Î ¼³Á¤ÇÔ
end;
end;
end;
procedure TGuardThread.DoLog(const Msg: string);
begin
if Terminated then Exit;
Queue(procedure begin
if Assigned(TDeviceGuardEngine(FOwnerEngine).OnLog) then
TDeviceGuardEngine(FOwnerEngine).OnLog(Msg);
end);
end;
procedure TGuardThread.ShowPopup(const Msg: string);
begin
if Terminated then Exit;
Queue(procedure begin
if Assigned(TDeviceGuardEngine(FOwnerEngine).OnPopup) then
TDeviceGuardEngine(FOwnerEngine).OnPopup(Msg);
end);
end;
end.