unit bs1DeviceControl; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ComCtrls, System.Generics.Collections, DeviceGuard.Logic; // ºÐ¸®ÇÑ ·ÎÁ÷ À¯´Ö »ç¿ë type // UI °ü¸®¸¦ À§ÇÑ Wrapper Ŭ·¡½º TUIItem = class public Panel: TPanel; RadioGroup: TRadioGroup; GuidStr: string; constructor Create(APanel: TPanel; ARadio: TRadioGroup; AGuid: string); end; TForm1 = class(TForm) PanelTop: TPanel; BtnApply: TButton; MemoLog: TMemo; ScrollBoxDevices: TScrollBox; Splitter1: TSplitter; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure BtnApplyClick(Sender: TObject); private FEngine: TDeviceGuardEngine; FUIList: TObjectList; // UI °´Ã¼ °ü¸®¿ë procedure AddDeviceUI(const Name, GuidStr: string; IsBT: Boolean = False); procedure OnEngineLog(const Msg: string); procedure OnEnginePopup(const Msg: string); procedure OnPolicyChanged(Sender: TObject); // ¶óµð¿À ¹öư º¯°æ À̺¥Æ® public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} // ÀåÄ¡ GUID »ó¼ö (UI¿¡¼­ µî·Ï¿ë) const 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_WPD = '{eec5ad98-8080-425f-922a-dabf3de3f69a}'; GUID_DEVCLASS_DISKDRIVE = '{4d36e967-e325-11ce-bfc1-08002be10318}'; { TUIItem } constructor TUIItem.Create(APanel: TPanel; ARadio: TRadioGroup; AGuid: string); begin Panel := APanel; RadioGroup := ARadio; GuidStr := AGuid; end; { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin Caption := 'Unified Device Guard (Thread Based)'; // 1. ¿£Áø »ý¼º ¹× À̺¥Æ® ¿¬°á FEngine := TDeviceGuardEngine.Create; FEngine.OnLog := OnEngineLog; FEngine.OnPopup := OnEnginePopup; FUIList := TObjectList.Create; // 2. ÀåÄ¡ ¹× UI µî·Ï AddDeviceUI('Bluetooth (Detail)', GUID_DEVCLASS_BLUETOOTH, True); AddDeviceUI('USB Host', GUID_DEVCLASS_USB); AddDeviceUI('Serial/Parallel', GUID_DEVCLASS_PORTS); AddDeviceUI('Modem', GUID_DEVCLASS_MODEM); AddDeviceUI('Network', GUID_DEVCLASS_NET); AddDeviceUI('Portable (MTP)', GUID_DEVCLASS_WPD); AddDeviceUI('Disk Drive', GUID_DEVCLASS_DISKDRIVE); OnEngineLog('½Ã½ºÅÛ ÃʱâÈ­ ¿Ï·á. ´ë±â Áß...'); end; procedure TForm1.FormDestroy(Sender: TObject); begin FEngine.Stop; // ½º·¹µå Á¾·á ´ë±â FEngine.Free; FUIList.Free; end; procedure TForm1.AddDeviceUI(const Name, GuidStr: string; IsBT: Boolean); var Pnl: TPanel; Lbl: TLabel; Rg: TRadioGroup; begin // A. ¿£Áø¿¡ Á¤Ã¥ µî·Ï (ÃʱⰪ: psLog) FEngine.AddPolicy(Name, GuidStr, IsBT); // B. UI »ý¼º Pnl := TPanel.Create(ScrollBoxDevices); Pnl.Parent := ScrollBoxDevices; Pnl.Align := alTop; Pnl.Height := 60; Pnl.BevelOuter := bvNone; Pnl.Margins.Bottom := 2; Pnl.AlignWithMargins := True; Lbl := TLabel.Create(Pnl); Lbl.Parent := Pnl; Lbl.Caption := Name; if IsBT then Lbl.Caption := Name + sLineBreak + '(Key/Mouse Allowed)'; Lbl.Align := alLeft; Lbl.Layout := tlCenter; Lbl.Width := 200; Lbl.Font.Style := [fsBold]; Rg := TRadioGroup.Create(Pnl); Rg.Parent := Pnl; Rg.Align := alClient; Rg.Caption := ''; Rg.Columns := 3; Rg.Items.Add('¸ðµÎ Çã¿ë'); Rg.Items.Add('Á¤Ã¥ Â÷´Ü'); Rg.Items.Add('·Î±×'); Rg.ItemIndex := 2; // Default: Log // ¡Ú Áß¿ä: ¶óµð¿À ¹öư Ŭ¸¯ ½Ã Áï½Ã ¾÷µ¥ÀÌÆ®Çϵµ·Ï À̺¥Æ® ¿¬°á Rg.OnClick := OnPolicyChanged; // ³ªÁß¿¡ ¾î¶² GUIDÀÎÁö ¾Ë±â À§ÇØ Tag³ª º°µµ ¸®½ºÆ®¿¡ ÀúÀå // ¿©±â¼­´Â º°µµ ¸®½ºÆ®(TUIItem) »ç¿ë FUIList.Add(TUIItem.Create(Pnl, Rg, GuidStr)); end; // ¡Ú UI º¯°æ ½Ã ½Ç½Ã°£À¸·Î ¿£Áø¿¡ ¹Ý¿µÇÏ´Â ºÎºÐ procedure TForm1.OnPolicyChanged(Sender: TObject); var Rg: TRadioGroup; GuidStr: string; NewState: TPolicyState; begin Rg := Sender as TRadioGroup; GuidStr := ''; // ÇØ´ç ¶óµð¿À ±×·ìÀÇ ÁÖÀÎ(GUID) ã±â for var UI in FUIList do begin if UI.RadioGroup = Rg then begin GuidStr := UI.GuidStr; Break; end; end; if GuidStr = '' then Exit; case Rg.ItemIndex of 0: NewState := psAllow; 1: NewState := psBlock; else NewState := psLog; end; // ¿£Áø API È£Ãâ (½º·¹µå ¾ÈÀü) FEngine.UpdatePolicy(GuidStr, NewState); end; procedure TForm1.BtnApplyClick(Sender: TObject); begin if BtnApply.Caption = '°¨½Ã ½ÃÀÛ' then begin FEngine.Start; // ½º·¹µå ½ÃÀÛ BtnApply.Caption := '°¨½Ã ÁßÁö'; OnEngineLog('°¨½Ã ½º·¹µå°¡ ½ÃÀ۵Ǿú½À´Ï´Ù.'); end else begin FEngine.Stop; // ½º·¹µå Á¾·á BtnApply.Caption := '°¨½Ã ½ÃÀÛ'; OnEngineLog('°¨½Ã°¡ ÁßÁöµÇ¾ú½À´Ï´Ù.'); end; end; // ¿£Áø¿¡¼­ ¿À´Â ·Î±× ¸Þ½ÃÁö ó¸® (Queue/Synchronize¸¦ ÅëÇØ ¾ÈÀüÇÏ°Ô UI ½º·¹µå¿¡¼­ ½ÇÇàµÊ) procedure TForm1.OnEngineLog(const Msg: string); begin MemoLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss', Now), Msg])); SendMessage(MemoLog.Handle, WM_VSCROLL, SB_BOTTOM, 0); end; procedure TForm1.OnEnginePopup(const Msg: string); begin // Æ®·¹ÀÌ ¸Þ½ÃÁö µîÀ» ¶ç¿ì°Å³ª »óŹ٠ǥ½Ã // ShowMessage´Â ½º·¹µå ºí·ÎÅ·À» À¯¹ßÇÒ ¼ö ÀÖÀ¸¹Ç·Î ÁÖÀÇÇØ¼­ »ç¿ë // ¿©±â¼­´Â ŸÀÌÆ²¹Ù ±ôºýÀÓ µîÀ¸·Î ´ëü °¡´É Form1.Caption := '°æ°í: ' + Msg; end; end.