BSOne.SFC/Tocsg.Module/Bs1Flt/bs1dc_Delphi/bs1DeviceControl - 복사본.pas

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.