unit DEncryptAip; 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, PngImageList; const WM_CLICK_DECRYPT = WM_USER + 8548; type PDrmEnt = ^TDrmEnt; TDrmEnt = record sDir, sExt, sFName: String; bDrm: Boolean; nImgIdx: Integer; end; TDlgEncryptAip = 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_: TPngImageList; vtListOldWndProc_: TWndMethod; AipExtList_, CheckFList_, FIconIdxList_: 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 DlgEncryptAip: TDlgEncryptAip; 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, CrmUtil, Tocsg.Safe, Soap.EncdDecd; resourcestring RS_MsgAddFile = '먼저 파일을 추가해 주십시오.'; RS_NoTgFile = '변환 할 파일이 없습니다.'; RS_Q_DrmDec = 'MIP 암호화를 적용 하시겠습니까?'; RS_MsgError = '작업을 준비하는 중 오류가 발생했습니다.'; RS_CompleteWork1 = '작업을 완료했습니다.'; RS_CompleteWork2 = '(성공 : %d, 실패 : %d, 무시 : %d)'; RS_Q_Clear = '목록을 초기화 하시겠습니까?'; RS_SelExceptFile = '제외 할 파일을 선택해 주십시오.'; RS_Q_ExceptFile = '선택한 파일들을 제외 하시겠습니까?'; RS_NoExceptFile = '제외 할 파일이 없습니다.'; RS_DrmFileDragDrop = '대상 파일을 드래그/드롭 해주십시오.'; {$R *.dfm} Constructor TDlgEncryptAip.Create(aOwner: TComponent); var hSysIcons: THandle; begin Inherited Create(aOwner); FIconIdxList_ := TStringList.Create; FIconIdxList_.CaseSensitive := false; FileImageList_ := TPngImageList.Create(Self); vtList.Images := FileImageList_; AipExtList_ := TStringList.Create; AipExtList_.CaseSensitive := false; SplitString(AIP_EXTS, '|', AipExtList_); 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); end; procedure TDlgEncryptAip.CreateParams(var Params: TCreateParams); begin Inherited CreateParams(Params); Params.ExStyle := WS_EX_APPWINDOW; end; Destructor TDlgEncryptAip.Destroy; begin FreeAndNil(FIconIdxList_); FreeAndNil(AipExtList_); FreeAndNil(CheckFList_); Inherited; end; function TDlgEncryptAip.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 not pData.bDrm then Inc(Result); pNode := vtList.GetNext(pNode); end; finally vtList.EndUpdate; end; end; procedure TDlgEncryptAip.AddFile(sPath: String); var pData: PDrmEnt; begin try if AipExtList_.IndexOf(GetFileExt(sPath)) = -1 then exit; 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 := IsAipEncryted(sPath, 'C:\ProgramData\HE\AEN\'); except pData.bDrm := false; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddFile()'); end; end; procedure TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.btnEncryptClick(Sender: TObject); var nSuccess, nFail, nNorCnt: Integer; pNode: PVirtualNode; pData: PDrmEnt; sPath, sCpPath, sAipLabelId, sLName, sTaskDir, 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 not pData.bDrm then begin try bResult := false; sPath := pData.sDir + pData.sFName; h := gMgSvc.FindAipMdWnd; if h <> 0 then begin sAipLabelId := GetDefAipLabelId(CUSTOMER_TYPE = CUSTOMER_DEV); sAipPath := GetSameFileNameInc(sTaskDir + '$TmpA' + ExtractFileName(sPath)); O := SO; O.S['src'] := sPath; 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, sAipPath + '@') then // 원본 백업 // MoveFile()을 사용하면 파일 권한이 바뀐다.. 일반 사용자 권한이 추가되며, 쓰기 권한이 사라짐 25_1230 08:54:48 kku if CopyFile(PChar(sPath), PChar(sAipPath + '@'), false) then // 원본 백업 begin DeleteFile(sPath); sCpPath := ConvAipEncExt(sPath); if CheckMsPfileExt(sCpPath) then begin if CheckAipEncSign(sAipPath) then sCpPath := sCpPath + '.pfile'; end; // if MoveFile_wait(sAipPath, sCpPath) then if CopyFile(PChar(sAipPath), PChar(sCpPath), false) then begin DeleteFile(sAipPath); DeleteFile(sAipPath + '@'); ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := PREVENT_DRM_ENCRYPT; LogInfo.sSummary := '[AIP] ' + ExtractFileName(sPath); LogInfo.sPath := sPath; gMgSvc.SendEventLogEx(@LogInfo); Inc(nSuccess); bResult := true; pData.bDrm := true; end else begin // MoveFile_wait(sAipPath + '@', sPath); if CopyFile(PChar(sAipPath + '@'), PChar(sPath), false) then DeleteFile(sAipPath + '@'); end; end; end; end; if FileExists(sAipPath) then DeleteFile(sAipPath); if gMgSvc.PrefModel.AipEncMSec > 0 then Sleep(gMgSvc.PrefModel.AipEncMSec); 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 TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.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 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 TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var pData: PDrmEnt; begin pData := Sender.GetNodeData(Node); Finalize(pData^); end; procedure TDlgEncryptAip.vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); begin HintText := vtList.Text[Node, Column]; end; procedure TDlgEncryptAip.vtListGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); var pData: PDrmEnt; sIPath, sExt: String; begin case Kind of ikNormal, ikSelected: begin if Column = 1 then begin pData := Sender.GetNodeData(Node); if pData.nImgIdx = -1 then begin sExt := GetFileExt(pData.sFName); pData.nImgIdx := FIconIdxList_.IndexOf(sExt); if pData.nImgIdx = -1 then begin sIPath := GetRunExePathDir + DIR_CACHE + sExt + '.ico'; if FileExists(sIPath) then begin var ico: TIcon := TIcon.Create; ico.LoadFromFile(sIPath); pData.nImgIdx := FileImageList_.AddIcon(ico); FIconIdxList_.AddObject(sExt, TObject(pData.nImgIdx)); ico.Free; end else begin var sHlpExe: String := GetRunExePathDir + DIR_CONF + EXE_HLP; var O: ISuperObject := SO; O.I['RcvWnd'] := Handle; O.I['Cmd'] := HPCMD_REQ_FILEICON; O.S['P'] := pData.sDir + pData.sFName; O.I['N'] := LONGLONG(Node); O.S['E'] := sExt; SaveJsonObjToFile(O, GetRunExePathDir + DIR_CONF + DAT_PARAM); {$IFDEF DEBUG} ExecutePath(sHlpExe); {$ELSE} ExecuteAppAsUser('explorer.exe', sHlpExe, '', SW_SHOWNORMAL); {$ENDIF} exit; end; end else pData.nImgIdx := LONGLONG(FIconIdxList_.Objects[pData.nImgIdx]); end; ImageIndex := pData.nImgIdx; end; end; end; end; procedure TDlgEncryptAip.vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(TDrmEnt); end; procedure TDlgEncryptAip.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 TDlgEncryptAip.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 TDlgEncryptAip.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; HPCMD_REQ_FILEICON : begin O := SO(Copy(PChar(pCpData.lpData), 1, pCpData.cbData)); var pNode: PVirtualNode := PVirtualNode(O.I['N']); var sExt: String := O.S['E']; var pBuf: TBytes := DecodeBase64(O.S['D']); if ForceDirectories(GetRunExePathDir + DIR_CACHE) then begin var ms: TMemoryStream; Guard(ms, TMemoryStream.Create); ms.Write(pBuf[0], Length(pBuf)); var ico: TIcon; Guard(ico, TIcon.Create); ms.Position := 0; ico.LoadFromStream(ms); ms.Position := 0; ms.SaveToFile(GetRunExePathDir + DIR_CACHE + sExt + '.ico'); if pNode <> nil then vtList.RepaintNode(pNode); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. process_WM_COPYDATA(), dwData=%d', [dwData])); end; end; end.