209 lines
5.4 KiB
Plaintext
209 lines
5.4 KiB
Plaintext
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<TUIItem>; // 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<TUIItem>.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.
|