unit DKess2AipDrm; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Menus; const WM_CLICK_DECRYPT = WM_USER + 8548; type PDrmEnt = ^TDrmEnt; TDrmEnt = record sDir, sExt, sFName: String; bDrm: Boolean; nImgIdx: Integer; end; TDlgKess2AipDrm = class(TForm) pnTop: TPanel; pnClient: TPanel; vtList: TVirtualStringTree; btnEncrypt: TButton; Label1: TLabel; popFun: TPopupMenu; miDelFile: TMenuItem; miDelNoDrm: TMenuItem; N1: TMenuItem; miClear: TMenuItem; btnAddFile: TButton; btnAddDir: TButton; OpenDialog: TOpenDialog; FileOpenDialog: TFileOpenDialog; procedure vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); procedure vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure vtListPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); procedure vtListGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); procedure vtListAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure miDelFileClick(Sender: TObject); procedure miDelNoDrmClick(Sender: TObject); procedure btnEncryptClick(Sender: TObject); procedure vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure miClearClick(Sender: TObject); procedure btnAddFileClick(Sender: TObject); procedure btnAddDirClick(Sender: TObject); private { Private declarations } FileImageList_: TImageList; vtListOldWndProc_: TWndMethod; CheckFList_: TStringList; procedure vtListWndProc(var msg: TMessage); function CountNorFile: Integer; procedure AddFile(sPath: String); procedure ExtrctFilesFromDir(sDir: String); public { Public declarations } Constructor Create(aOwner: TComponent); override; procedure CreateParams(var Params: TCreateParams); override; // 작업표시줄에 표시 Destructor Destroy; override; procedure AddFiles(aList: TStringList); procedure process_WM_COPYDATA(var msg: TMessage); Message WM_COPYDATA; end; var DlgKess2AipDrm: TDlgKess2AipDrm; implementation uses {$IFDEF _HE_} ManagerService, ManagerModel, {$ENDIF} Tocsg.Convert, Tocsg.Shell, Winapi.ShellAPI, Tocsg.Path, GlobalDefine, Condition, Tocsg.Files, Tocsg.Strings, Tocsg.VTUtil, superobject, DefineHelper, Define, Tocsg.Exception, Tocsg.Process, Tocsg.Trace, Tocsg.AIP, Tocsg.Kess, CrmUtil; resourcestring RS_MsgAddFile = '먼저 파일을 추가해 주십시오.'; RS_NoTgFile = '변환 할 파일이 없습니다.'; RS_Q_DrmDec = '암호화를 변환 하시겠습니까?'; RS_MsgError = '작업을 준비하는 중 오류가 발생했습니다.'; RS_CompleteWork1 = '작업을 완료했습니다.'; RS_CompleteWork2 = '(성공 : %d, 실패 : %d, 무시 : %d)'; RS_Q_Clear = '목록을 초기화 하시겠습니까?'; RS_SelExceptFile = '제외 할 파일을 선택해 주십시오.'; RS_Q_ExceptFile = '선택한 파일들을 제외 하시겠습니까?'; RS_NoExceptFile = '제외 할 파일이 없습니다.'; RS_DrmFileDragDrop = '대상 파일을 드래그/드롭 해주십시오.'; {$R *.dfm} Constructor TDlgKess2AipDrm.Create(aOwner: TComponent); var hSysIcons: THandle; begin Inherited Create(aOwner); FileImageList_ := TImageList.Create(Self); FileImageList_.ShareImages := true; FileImageList_.BlendColor := clHighlight; hSysIcons := GetShellImageHandle; if hSysIcons <> 0 then begin FileImageList_.Handle := hSysIcons; vtList.Images := FileImageList_; end; CheckFList_ := TStringList.Create; CheckFList_.CaseSensitive := false; vtListOldWndProc_ := vtList.WindowProc; vtList.WindowProc := vtListWndProc; DragAcceptFiles(vtList.Handle, true); ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD); ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); ChangeWindowMessageFilter(WM_COPYGLOBALDATA, MSGFLT_ADD); ASSERT(CUSTOMER_TYPE = CUSTOMER_KDNVN); end; procedure TDlgKess2AipDrm.CreateParams(var Params: TCreateParams); begin Inherited CreateParams(Params); Params.ExStyle := WS_EX_APPWINDOW; end; Destructor TDlgKess2AipDrm.Destroy; begin FreeAndNil(CheckFList_); Inherited; end; function TDlgKess2AipDrm.CountNorFile: Integer; var pData: PDrmEnt; pNode: PVirtualNode; begin Result := 0; vtList.BeginUpdate; try pNode := vtList.GetFirst; while pNode <> nil do begin pData := vtList.GetNodeData(pNode); if pData.bDrm then Inc(Result); pNode := vtList.GetNext(pNode); end; finally vtList.EndUpdate; end; end; procedure TDlgKess2AipDrm.AddFile(sPath: String); var pData: PDrmEnt; begin try if CheckFList_.IndexOf(sPath) <> -1 then exit; CheckFList_.Add(sPath); pData := VT_AddChildData(vtList); pData.sDir := ExtractFilePath(sPath); pData.sFName := ExtractFileName(sPath); pData.sExt := GetFileExt(pData.sFName).ToUpper; pData.nImgIdx := -1; try pData.bDrm := KCT_IsEncrypt(sPath) = RESULT_SUCCESS; except pData.bDrm := false; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddFile()'); end; end; procedure TDlgKess2AipDrm.AddFiles(aList: TStringList); var sPath: String; i: Integer; begin vtList.BeginUpdate; try for i := 0 to aList.Count - 1 do begin sPath := aList[i]; if not FileExists(sPath) then continue; AddFile(sPath); end; finally vtList.EndUpdate; end; end; procedure TDlgKess2AipDrm.ExtrctFilesFromDir(sDir: String); var wfd: TWin32FindData; hSc: THandle; sPath: String; begin sDir := IncludeTrailingPathDelimiter(sDir); sPath := sDir + '*.*'; hSc := FindFirstFile(PChar(sPath), wfd); if hSc = INVALID_HANDLE_VALUE then exit; try Repeat if (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') then if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0) then begin ExtrctFilesFromDir(sDir + wfd.cFileName); end else begin AddFile(sDir + wfd.cFileName); end; Until not FindNextFile(hSc, wfd); finally WinApi.Windows.FindClose(hSc); end; end; procedure TDlgKess2AipDrm.btnAddDirClick(Sender: TObject); var O: ISuperObject; sExe: String; ProcInfo: TProcessInformation; Label LB_Direct; begin try sExe := GetRunExePathDir + DIR_CONF + EXE_HLP; if FileExists(sExe) then begin O := SO; O.I['RcvWnd'] := Handle; O.I['Cmd'] := HPCMD_SELECT_FOLDER; O.I['Ctrl'] := 1; SaveJsonObjToFile(O, GetRunExePathDir + DIR_CONF + DAT_PARAM); // ProcInfo := ExecuteApp(sExe, '', SW_SHOWNORMAL); ProcInfo := ExecuteAppAsUser('explorer.exe', sExe, '', SW_SHOWNORMAL); if ProcInfo.dwProcessId = 0 then goto LB_Direct; end else begin LB_Direct : {$IFDEF _HE_} if FileOpenDialog.FileName = '' then FileOpenDialog.DefaultFolder := Format('C:\Users\%s\Desktop', [gMgSvc.UserName]); {$ENDIF} if FileOpenDialog.Execute then begin ExtrctFilesFromDir(FileOpenDialog.FileName); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. btnAddDirClick()'); end; end; procedure TDlgKess2AipDrm.btnAddFileClick(Sender: TObject); var i: Integer; O: ISuperObject; sExe: String; ProcInfo: TProcessInformation; Label LB_Direct; begin try sExe := GetRunExePathDir + DIR_CONF + EXE_HLP; if FileExists(sExe) then begin O := SO; O.I['RcvWnd'] := Handle; O.I['Cmd'] := HPCMD_SELECT_FILE; O.I['Ctrl'] := 99; O.S['Filter'] := 'All files|*.*'; SaveJsonObjToFile(O, GetRunExePathDir + DIR_CONF + DAT_PARAM); ProcInfo := ExecuteAppAsUser('explorer.exe', sExe, '', SW_SHOWNORMAL); if ProcInfo.dwProcessId = 0 then goto LB_Direct; end else begin LB_Direct : {$IFDEF _HE_} if (OpenDialog.Files.Count = 0) or (OpenDialog.FileName = '') then OpenDialog.InitialDir := Format('C:\Users\%s\Desktop', [gMgSvc.UserName]); {$ENDIF} if OpenDialog.Execute(Handle) then begin vtList.BeginUpdate; try for i := 0 to OpenDialog.Files.Count - 1 do AddFile(OpenDialog.Files[i]); finally vtList.EndUpdate; end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. btnAddFileClick()'); end; end; procedure TDlgKess2AipDrm.btnEncryptClick(Sender: TObject); var nSuccess, nFail, nNorCnt: Integer; pNode: PVirtualNode; pData: PDrmEnt; sPath, sFName, sCpPath, sAipLabelId, sLName, sExt, sTaskDir, sDecPath, sAipPath: String; bResult: Boolean; h: HWND; O: ISuperObject; nResult: Integer; LogInfo: TLogInfo; begin if vtList.RootNodeCount = 0 then begin MessageBox(Handle, PChar(RS_MsgAddFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; if CountNorFile = 0 then begin MessageBox(Handle, PChar(RS_NoTgFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; sTaskDir := 'C:\ProgramData\HE\Tasked\'; DeleteDir(sTaskDir); if not ForceDirectories(sTaskDir) then begin MessageBox(Handle, PChar(RS_MsgError), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; vtList.BeginUpdate; try nSuccess := 0; nFail := 0; nNorCnt := 0; pNode := vtList.GetFirst; while pNode <> nil do begin pData := vtList.GetNodeData(pNode); pNode := vtList.GetNext(pNode); if pData.bDrm then begin try bResult := false; sPath := pData.sDir + pData.sFName; if KCT_IsEncrypt(sPath) <> RESULT_SUCCESS then begin pData.bDrm := false; Inc(nNorCnt); continue; end; sDecPath := GetSameFileNameInc(sTaskDir + '$Tmpd' + ExtractFileName(sPath)); if KCT_Decrypt(sPath, 2, sDecPath) = RESULT_SUCCESS then begin h := gMgSvc.FindAipMdWnd; if h <> 0 then begin sAipLabelId := GetDefAipLabelId(CUSTOMER_TYPE = CUSTOMER_DEV); sFName := ExtractFileName(sPath); if (sFName <> '') then begin sLName := ''; if sFName[1] = '(' then sLName := GetCapsuleStr('(', ')', sFName) else if sFName[1] = '[' then sLName := GetCapsuleStr('[', ']', sFName); if sLName <> '' then begin sLName := StringReplace(sLName.ToLower, ' ', '', [rfReplaceAll]); // 공백제거 if (sLName = '일반') or (sLName = '一般') or (sLName = 'generalpurpose') or (sLName = 'ommaviyfoydalanishuchun') or (sLName = 'общедоступный') then sAipLabelId := '7c1e97b0-1625-488a-a30c-4f2188693461' else if (sLName = '대외비') or (sLName = '对外保密') or (sLName = 'confidential') or (sLName = 'ichkifoydalanish') or (sLName = 'длявнутреннего пользования') then sAipLabelId := 'e7bd3a2c-b905-4bdb-8892-e6cd8d1eb00b' else if (sLName = '기밀') or (sLName = '机密') or (sLName = 'secret') or (sLName = 'sirli') or (sLName = 'секретный') then sAipLabelId := '7d1539f9-8f3b-4cbd-b787-7ae1b30eae22' else if (sLName = '극비') or (sLName = '绝密') or (sLName = 'topsecret') or (sLName = 'judamaxfiy') or (sLName = 'строгосекретный') then sAipLabelId := 'b40a7c1a-5443-458b-9215-2abda0acc4a4'; end; end; sAipPath := GetSameFileNameInc(sTaskDir + '$TmpA' + ExtractFileName(sPath)); O := SO; O.S['src'] := sDecPath; O.S['dst'] := sAipPath; O.S['lid'] := sAipLabelId; if gMgSvc.Email <> '' then O.S['mail'] := gMgSvc.Email; nResult := SendData(h, 5, O.AsString); // _Trace('SetAipLabel() .. Result=%d, Path=%s, EncPath=%s', [nResult, sPath, sEncPath]); // 0 : 레이블 추출, 1 : 암호화, 2 : 복호화, 3 : 암호화 확인, 4 : 레이블 확인, 5 : 레이블 설정, 6 : 레이블 확인, 7 : 레이블 제거 if (nResult = 10) and FileExists(sAipPath) then begin if MoveFile_wait(sPath, sDecPath + '@') then // 원본 백업 begin sCpPath := ConvAipEncExt(sPath); if CheckMsPfileExt(sCpPath) then begin if CheckAipEncSign(sAipPath) then sCpPath := sCpPath + '.pfile'; end; if MoveFile_wait(sAipPath, sCpPath) then begin DeleteFile(sDecPath + '@'); ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := PREVENT_DRM_ENCRYPT; LogInfo.sSummary := '[KESS → AIP] ' + ExtractFileName(sPath); LogInfo.sPath := sPath; gMgSvc.SendEventLogEx(@LogInfo); Inc(nSuccess); bResult := true; pData.bDrm := false; end else begin MoveFile_wait(sDecPath + '@', sPath); end; end; end; end; if FileExists(sDecPath) then DeleteFile(sDecPath); if FileExists(sAipPath) then DeleteFile(sAipPath); end else Inc(nFail); except // .. end; if not bResult then Inc(nFail); end else Inc(nNorCnt); end; finally DeleteDir(sTaskDir); vtList.EndUpdate; end; MessageBox(Handle, PChar(Format(RS_CompleteWork1+#13+#10+RS_CompleteWork2, [nSuccess, nFail, nNorCnt])), PChar(Caption), MB_ICONINFORMATION or MB_OK); end; procedure TDlgKess2AipDrm.miClearClick(Sender: TObject); begin if MessageBox(Handle, PChar(RS_Q_Clear), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; CheckFList_.Clear; VT_Clear(vtList); end; procedure TDlgKess2AipDrm.miDelFileClick(Sender: TObject); var pNode: PVirtualNode; pData: PDrmEnt; nIdx: Integer; begin pNode := vtList.GetFirstSelected; if pNode = nil then begin MessageBox(Handle, PChar(RS_SelExceptFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; if MessageBox(Handle, PChar(RS_Q_ExceptFile), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; vtList.BeginUpdate; try while pNode <> nil do begin pData := vtList.GetNodeData(pNode); nIdx := CheckFList_.IndexOf(pData.sDir + pData.sFName); if nIdx <> -1 then CheckFList_.Delete(nIdx); pNode := vtList.GetNextSelected(pNode); end; vtList.DeleteSelectedNodes; finally vtList.EndUpdate; end; end; procedure TDlgKess2AipDrm.miDelNoDrmClick(Sender: TObject); var pNode, pDNode: PVirtualNode; pData: PDrmEnt; nIdx: Integer; begin pNode := vtList.GetFirst; if pNode = nil then begin MessageBox(Handle, PChar(RS_NoExceptFile), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; vtList.BeginUpdate; try while pNode <> nil do begin pData := vtList.GetNodeData(pNode); if not pData.bDrm then begin pDNode := pNode; end else pDNode := nil; pNode := vtList.GetNext(pNode); if pDNode <> nil then vtList.DeleteNode(pDNode); end; finally vtList.EndUpdate; end; end; procedure TDlgKess2AipDrm.vtListWndProc(var msg: TMessage); procedure ExtrctFilesFromDir(sDir: String); var wfd: TWin32FindData; hSc: THandle; sPath: String; begin sDir := IncludeTrailingPathDelimiter(sDir); sPath := sDir + '*.*'; hSc := FindFirstFile(PChar(sPath), wfd); if hSc = INVALID_HANDLE_VALUE then exit; try Repeat if (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') then if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0) then begin ExtrctFilesFromDir(sDir + wfd.cFileName); end else begin AddFile(sDir + wfd.cFileName); end; Until not FindNextFile(hSc, wfd); finally WinApi.Windows.FindClose(hSc); end; end; var sPath: String; nCnt: Integer; i, nLen: Integer; pNode: PVirtualNode; pData: PDrmEnt; begin if msg.Msg = WM_DROPFILES then begin nCnt := DragQueryFile(msg.WParam, DWORD(-1), nil, MAX_PATH); vtList.BeginUpdate; try for i := 0 to nCnt - 1 do begin nLen := DragQueryFile(msg.WParam, i, nil, 0) + 1; SetLength(sPath, nLen); DragQueryFile(msg.WParam, i, PChar(sPath), nLen); sPath := DeleteNullTail(sPath); if FileExists(sPath) then AddFile(sPath) else if DirectoryExists(sPath) then ExtrctFilesFromDir(sPath); end; finally vtList.EndUpdate; end; DragFinish(msg.WParam); exit; end; vtListOldWndProc_(msg); end; procedure TDlgKess2AipDrm.vtListAfterPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); var nX, nY, nW, nH: Integer; msg: String; begin if CUSTOMER_TYPE <> CUSTOMER_SERVE1 then // 서브원은 권한때문에 드래그드롭을 못함 24_0711 08:47:40 kku begin if TVirtualStringTree(Sender).RootNodeCount = 0 then begin TargetCanvas.Font.Color := clGray; msg := RS_DrmFileDragDrop; nW := TargetCanvas.TextWidth(msg); nH := TargetCanvas.TextHeight(msg); if Sender.Width > nW then nX := (Sender.Width div 2) - (nW div 2) else nX := 0; if Sender.Height > nH then nY := (Sender.Height div 2) - (nH div 2) - 20 else nY := 0; TargetCanvas.TextOut(nX, nY, msg); end; end; end; procedure TDlgKess2AipDrm.vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); var pNode: PVirtualNode; begin pNode := vtList.GetNodeAt(MousePos); miDelFile.Visible := pNode <> nil; miClear.Visible := vtList.RootNodeCount > 0; end; procedure TDlgKess2AipDrm.vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var pData: PDrmEnt; begin pData := Sender.GetNodeData(Node); Finalize(pData^); end; procedure TDlgKess2AipDrm.vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); begin HintText := vtList.Text[Node, Column]; end; procedure TDlgKess2AipDrm.vtListGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); var pData: PDrmEnt; begin case Kind of ikNormal, ikSelected: begin if Column = 1 then begin pData := Sender.GetNodeData(Node); if pData.nImgIdx = -1 then pData.nImgIdx := GetShellImageIndex_path(pData.sDir + pData.sFName); ImageIndex := pData.nImgIdx; end; end; end; end; procedure TDlgKess2AipDrm.vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(TDrmEnt); end; procedure TDlgKess2AipDrm.vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var pData: PDrmEnt; begin pData := Sender.GetNodeData(Node); case Column of 0 : CellText := IntToStr(Node.Index + 1); 1 : CellText := pData.sFName; 2 : CellText := pData.sExt; 3 : CellText := BooleanToStr(pData.bDrm, 'O', 'X'); 4 : CellText := pData.sDir; end; end; procedure TDlgKess2AipDrm.vtListPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); var pData: PDrmEnt; begin if not (vsSelected in Node.States) then begin pData := Sender.GetNodeData(Node); if pData.bDrm then TargetCanvas.Font.Color := clGreen; end; end; procedure TDlgKess2AipDrm.process_WM_COPYDATA(var msg: TMessage); var dwData: DWORD; pCpData: PCopyDataStruct; O: ISuperObject; sTemp: String; i: Integer; begin msg.Result := 0; dwData := 0; pCpData := PCopyDataStruct(msg.LParam); try dwData := pCpData.dwData; case dwData of HPCMD_SELECT_FILE : begin O := SO(Copy(PChar(pCpData.lpData), 1, pCpData.cbData)); if (O.O['List'] <> nil) and (O.O['List'].DataType = stArray) then begin for i := 0 to O.A['List'].Length - 1 do AddFile(O.A['List'].S[i]); end; // 일반권한으로 실행해서 안 지워진다.. 그래서 후처리 추가 22_0614 12:40:00 kku sTemp := GetRunExePathDir + DIR_CONF + DAT_PARAM; if FileExists(sTemp) then DeleteFile(sTemp); end; HPCMD_SELECT_FOLDER : begin O := SO(Copy(PChar(pCpData.lpData), 1, pCpData.cbData)); ExtrctFilesFromDir(O.S['Path']); // 일반권한으로 실행해서 안 지워진다.. 그래서 후처리 추가 22_0614 12:40:00 kku sTemp := GetRunExePathDir + DIR_CONF + DAT_PARAM; if FileExists(sTemp) then DeleteFile(sTemp); end; end; except on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. process_WM_COPYDATA(), dwData=%d', [dwData])); end; end; end.