BSOne.SFC/Tocsg.Module/TocsgDRM/DLL_TocsgDRM/TgDrmHook.pas

922 lines
29 KiB
Plaintext

{*******************************************************}
{ }
{ TgDrmHook }
{ }
{ Copyright (C) 2022 kku }
{ }
{*******************************************************}
unit TgDrmHook;
interface
uses
System.SysUtils, System.Classes, Tocsg.DllEntry, Tocsg.CommonData,
GlobalDefine, Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, Tocsg.Trace,
WinAPI.Foundation.Collections, System.Generics.Collections, Tocsg.DRM.Encrypt;
type
PDrmFileInfo = ^TDrmFileInfo;
TDrmFileInfo = record
hFile: THandle;
sOrgPath,
sDecPath: String;
bModified: Boolean;
Head: TTgDrmHead;
end;
TTgDrmHook = class(TTgDllEntry)
private
SharedData_: TTgFileMapping<TSharedData>;
hShellHook_: HHook;
Trace_: TTgTrace;
dtCreate_: TDateTime;
// sPass_,
sTgPNames_,
sLogPath_: String;
hRecentWnd_: HWND;
bInitOk_,
bUseBoxedApp_,
bIsMsOffice_,
bForceEncSave_: Boolean;
// DrmFileList_: TStringList;
DcDecPath_: TDictionary<String,String>;
bBlockCap_: Boolean;
DrmExtList_: TStringList;
DcDrmFI_: TDictionary<THandle,PDrmFileInfo>;
RecentDrmFI_: TDrmFileInfo; // MS오피스 저장 파일 암호화를 위함
sRecentOpenFile_: String;
ProcList_: TList<PPointer>;
procedure Log(sLog: String);
function InstallHook: Integer;
function UnInstallHook: Integer;
procedure AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String);
procedure DoInterceptCreate;
procedure DoInterceptRemove;
procedure OnBeforeLog(aSender: TObject);
procedure OnAfterLog(aSender: TObject);
function GetActive: Boolean;
function GetRcvWnd: LONGLONG;
procedure OnDrmFileNotify(Sender: TObject; const Item: PDrmFileInfo; Action: TCollectionNotification);
public
Constructor Create;
Destructor Destroy; override;
property Active: Boolean read GetActive;
property RcvWnd: LONGLONG read GetRcvWnd;
end;
THandleStreamEx = class(THandleStream)
protected
llSize_: LONGLONG;
function GetSize: Int64; override;
public
Constructor Create(aHandle: THandle; llSize: LONGLONG);
end;
TFun_CreateFileA = function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
TFun_CreateFileW = function(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
TFun_CloseHandle = function(hFile: THandle): BOOL; stdcall;
TFun_ReadFile = function(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD;
var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
TFun_WriteFile = function(hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD;
var lpNumberOfBytesWritten: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
TFun_WriteFileEx = function(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD;
const lpOverlapped: TOverlapped; lpCompletionRoutine: FARPROC): BOOL; stdcall;
function InstallDrmHook: Integer; export; stdcall;
function UnInstallDrmHook: Integer; export; stdcall;
implementation
uses
BoxedAppSDK_Static,
// BoxedAppSDK_DLL,
DDetours, Vcl.Graphics, Vcl.Imaging.pngimage, Vcl.Imaging.jpeg, Tocsg.Safe,
Tocsg.Path, Tocsg.Strings, Tocsg.Process, Winapi.DwmApi, Vcl.Forms,
Tocsg.WndUtil, Tocsg.Exception, Tocsg.Encrypt, Tocsg.Shell, Tocsg.Files;
var
_TgDrmHook: TTgDrmHook = nil;
_bLogProcessing: Boolean = false;
_bInternalOpen: Boolean = false;
ozCreateFileA: TFun_CreateFileA = nil;
ozCreateFileW: TFun_CreateFileW = nil;
ozCloseHandle: TFun_CloseHandle = nil;
ozReadFile: TFun_ReadFile = nil;
ozWriteFile: TFun_WriteFile = nil;
ozWriteFileEx: TFun_WriteFileEx = nil;
{ THandleStreamEx }
Constructor THandleStreamEx.Create(aHandle: THandle; llSize: LONGLONG);
begin
Inherited Create(aHandle);
llSize_ := llSize;
end;
function THandleStreamEx.GetSize: Int64;
begin
Result := llSize_;
end;
function ProcessEncFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline;
var
ms: TMemoryStream;
// enc: TTgEncrypt;
dec: TTgDrmDec;
fh: THandleStreamEx;
dwTemp: DWORD;
sChkPath,
sExt, sFName,
sVirtualPath: String;
hFile: THandle;
llSize: LONGLONG;
bDecSuccess: Boolean;
h: HWND;
// fs: TFileStream;
pDrmFI: PDrmFileInfo;
DrmHead: TTgDrmHead;
i: Integer;
begin
Result := 0;
case dwDesiredAccess of
0, $80, GENERIC_WRITE : exit;
end;
// if sPath.StartsWith('\??\') then
// Delete(sPath, 1, 4);
if Assigned(_TgDrmHook) and
(not _bLogProcessing and not _bInternalOpen) then
begin
// if BoxedAppSDK_IsVirtualFile(PChar(sPath)) then
// begin
// sVirtualPath := sPath;
// end else
// if _TgDrmHook.DcDecPath_.ContainsKey(sPath) then
// begin
// sVirtualPath := _TgDrmHook.DcDecPath_[sPath];
// end else
begin
// if _TgDrmHook.sRecentOpenFile_ <> sPath then
// begin
// _TgDrmHook.sRecentOpenFile_ := sPath;
// exit;
// end;
// _TgDrmHook.Log(Format('ProcessEncFile() .. Path=%s', [sPath]));
sVirtualPath := '';
bDecSuccess := false;
sFName := ExtractFileName(sPath);
if sFName = '' then
exit;
if CompareText(sFName, 'desktop.ini') = 0 then
exit;
if _TgDrmHook.bIsMsOffice_ and sFName.StartsWith('~$') then
exit;
sExt := GetFileExt(sFName);
if sExt = '' then
exit;
if _TgDrmHook.DrmExtList_.IndexOf(sExt) = -1 then
exit;
_TgDrmHook.Log(Format('Check Ext .. FName=%s, dwDesiredAccess=%X, ' +
'dwShareMode=%X, dwCreationDisposition=%X, dwFlagsAndAttributes=%X',
[sFName, dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes]));
// _TgDrmHook.Log(Format('Check Ext Success .. FName=%s', [sFName]));
fh := nil;
hFile := 0;
try
// hFile := ozCreateFileW(
// PChar(sPath),
// GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
// if (hFile = 0) or (hFile = INVALID_HANDLE_VALUE) then
// exit;
_bInternalOpen := true;
ms := TMemoryStream.Create;
try
if _TgDrmHook.bIsMsOffice_ and (_TgDrmHook.RecentDrmFI_.sOrgPath <> '') and
(CompareText(_TgDrmHook.RecentDrmFI_.sOrgPath, sPath) = 0) and
not TTgEncrypt.CheckSign(sPath, SIG_DRM) then
begin
_TgDrmHook.RecentDrmFI_.sOrgPath := '';
if MoveFile_wait(sPath, sPath + '_tmp', 3) then
begin
var enc: TTgDrmEnc;
Guard(enc, TTgDrmEnc.Create(sPath));
with _TgDrmHook.RecentDrmFI_.Head do
begin
if enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHostName, sPartName, sPgName, dwCustomerCode) then
if enc.EncryptFromFile(PASS_DRM_DATA, sPath + '_tmp') then
DeleteFile(PChar(sPath + '_tmp'));
end;
end;
end;
// if not GetFileSizeEx(hFile, llSize) then
// exit;
// if llSize = 0 then
// exit;
// Guard(fh, THandleStreamEx.Create(hFile, llSize));
// fs := TFileStream.Create(sPath, fmOpenRead or fmShareDenyNone);
// _TgDrmHook.Log(Format('FileSize=%d', [fs.Size]));
dec := TTgDrmDec.Create(sPath);
try
if not dec.CheckSig(SIG_DRM) then
begin
// _TgDrmHook.Log(Format('Fail .. CheckSign(), FName=%s', [sFName]));
exit;
end else begin
_TgDrmHook.Log(Format('Success .. CheckSign(), FName=%s', [sFName]));
end;
if not dec.ExtrHead(PASS_DRM_HEAD) then
begin
_TgDrmHook.Log('Fail .. ExtrHead()');
exit;
end;
DrmHead := dec.Head;
if not dec.DecryptToStream(PASS_DRM_DATA, ms) then
begin
_TgDrmHook.Log('Fail .. DecryptToStream()');
exit;
end;
finally
FreeAndNil(dec);
end;
bDecSuccess := true;
finally
if hFile <> 0 then
begin
ozCloseHandle(hFile);
hFile := 0;
end;
if bDecSuccess then
begin
// {$IF True}
if _TgDrmHook.bUseBoxedApp_ then
begin
sVirtualPath := '@TgDRM\' + ExtractFilePath(sPath) + sFName;
// sVirtualPath := ExtractFilePath(sPath) + Format('#%d_%s', [GetTickCount, sFName]);
// 가상 파일 생성
hFile := BoxedAppSDK_CreateVirtualFile(PChar(sVirtualPath),
GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, 0);
// GENERIC_WRITE, dwShareMode, lpSecurityAttributes, CREATE_NEW, dwFlagsAndAttributes {FILE_ATTRIBUTE_HIDDEN}, hTemplateFile);
end else begin
// sVirtualPath := ExtractFilePath(sPath) + Format('#1_%s', [sFName]);
sVirtualPath := ExtractFilePath(sPath) + Format('#%d_%s', [GetTickCount, sFName]);
// 가상 파일 생성
hFile := ozCreateFileW(PChar(sVirtualPath),
GENERIC_WRITE or GENERIC_READ, 0, nil, CREATE_ALWAYS { CREATE_NEW } ,
FILE_ATTRIBUTE_HIDDEN or FILE_FLAG_DELETE_ON_CLOSE, 0);
// FILE_ATTRIBUTE_HIDDEN, 0);
// hFile := ozCreateFileW(PChar(sVirtualPath), GENERIC_WRITE or GENERIC_READ, 0, lpSecurityAttributes, dwCreationDisposition or CREATE_ALWAYS,
// dwFlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE, hTemplateFile);
end;
if (hFile <> 0) and (hFile <> INVALID_HANDLE_VALUE) then
begin
WriteFile(hFile, ms.Memory^, ms.Size, dwTemp, nil);
if FileSeek(hFile, 0, 0) = 0 then
Result := hFile
else
CloseHandle(hFile);
// ExecutePath('C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe', '"' + sVirtualPath + '"');
// Result := 1;
// _TgDrmHook.DcDecPath_.Add(sPath, sVirtualPath);
// if _TgDrmHook.DrmFileList_.IndexOf(sFName) = -1 then
// _TgDrmHook.DrmFileList_.Add(sFName);
end;
end;
ms.Free;
_bInternalOpen := false;
end;
except
// ..
sVirtualPath := '';
end;
end;
try
if Result <> 0 then
exit;
if sVirtualPath <> '' then
begin
// Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, 0, lpSecurityAttributes, dwCreationDisposition,
// dwFlagsAndAttributes, hTemplateFile);
Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, 0, lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes or FILE_FLAG_DELETE_ON_CLOSE, hTemplateFile);
// Result := ozCreateFileW(PChar(sVirtualPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
// dwFlagsAndAttributes, hTemplateFile);
end;
finally
if (Result <> 0) and (Result <> INVALID_HANDLE_VALUE) then
begin
if _TgDrmHook.DcDrmFI_.ContainsKey(Result) then
begin
_TgDrmHook.Log('Fail .. ProcessEncFile() .. Already Handle??');
{$IFDEF DEBUG}
ASSERT(false);
{$ELSE}
exit;
{$ENDIF};
end;
New(pDrmFI);
ZeroMemory(pDrmFI, SizeOf(TDrmFileInfo));
pDrmFI.hFile := Result;
pDrmFI.sOrgPath := sPath;
pDrmFI.sDecPath := sVirtualPath;
pDrmFI.Head := DrmHead;
pDrmFI.bModified := true;
_TgDrmHook.DcDrmFI_.Add(Result, pDrmFI);
end;
end;
end;
end;
function ProcessNorFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline;
var
sFName, sExt, sEncPath: String;
pInfo: PDrmFileInfo;
dec: TTgDrmDec;
DrmHead: TTgDrmHead;
begin
Result := 0;
exit;
if _TgDrmHook.bIsMsOffice_ then
begin
_bInternalOpen := true;
try
sFName := ExtractFileName(sPath);
if sFName = '' then
exit;
if not sFName.StartsWith('~$') then
exit;
sExt := GetFileExt(sFName);
if sExt = '' then
exit;
if _TgDrmHook.DrmExtList_.IndexOf(sExt) = -1 then
exit;
_TgDrmHook.Log(Format('ProcessNorFile() .. 1sEncPath=%s', [ExtractFilePath(sPath) + sFName]));
Delete(sFName, 1, 2);
sEncPath := ExtractFilePath(sPath) + sFName;
_TgDrmHook.Log(Format('ProcessNorFile() .. 2sEncPath=%s', [sEncPath]));
if not FileExists(sEncPath) then
exit;
_TgDrmHook.Log('ProcessNorFile() .. 1');
dec := TTgDrmDec.Create(sEncPath);
try
if not dec.CheckSig(SIG_DRM) then
exit;
if not dec.ExtrHead(PASS_DRM_HEAD) then
exit;
DrmHead := dec.Head;
finally
dec.Free;
end;
_TgDrmHook.Log('ProcessNorFile() .. 2');
Result := ozCreateFileW(PChar(sPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, hTemplateFile);
if (Result <> 0) and (Result <> INVALID_HANDLE_VALUE) then
begin
New(pInfo);
ZeroMemory(pInfo, SizeOf(TDrmFileInfo));
pInfo.hFile := Result;
pInfo.sOrgPath := sEncPath;
pInfo.sDecPath := sPath;
pInfo.Head := DrmHead;
// pInfo.bModified := true;
_TgDrmHook.DcDrmFI_.Add(Result, pInfo);
_TgDrmHook.Log(Format('ProcessNorFile() .. Path=%s', [sPath]));
end;
finally
_bInternalOpen := false;
end;
end;
end;
function ProcessCreateFile(sPath: String; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; inline;
begin
Result := ProcessEncFile(sPath, dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
if Result = 0 then
begin
Result := ProcessNorFile(sPath, dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
if Result = 0 then
Result := ozCreateFileW(PChar(sPath), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, hTemplateFile);
end;
end;
function CreateFileAHook(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
begin
// Result := ozCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
// dwFlagsAndAttributes, hTemplateFile);
Result := ProcessCreateFile(StrPas(lpFileName), dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
end;
function CreateFileWHook(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall;
begin
// Result := ozCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
// dwFlagsAndAttributes, hTemplateFile);
Result := ProcessCreateFile(StrPas(lpFileName), dwDesiredAccess, dwShareMode,
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
end;
function CloseHandleHook(hFile: THandle): BOOL; stdcall;
var
pInfo: PDrmFileInfo;
enc: TTgDrmEnc;
hs: THandleStreamEx;
llSize: LONGLONG;
ms: TMemoryStream;
begin
try
if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then
begin
pInfo := _TgDrmHook.DcDrmFI_[hFile];
_bInternalOpen := true;
_TgDrmHook.Log(Format('CloseHandleHook() .. ProcessEncHandle, OrgPath=%s', [pInfo.sOrgPath]));
_TgDrmHook.Log(Format('CloseHandleHook() .. ProcessEncHandle, DecPath=%s', [pInfo.sDecPath]));
try
if _TgDrmHook.bForceEncSave_ or pInfo.bModified then
begin
if _TgDrmHook.bIsMsOffice_ then
begin
_TgDrmHook.RecentDrmFI_.sOrgPath := pInfo.sOrgPath;
_TgDrmHook.RecentDrmFI_.Head := pInfo.Head;
end else begin
if not GetFileSizeEx(hFile, llSize) then
begin
_TgDrmHook.Log('CloseHandleHook() .. Fail .. GetFileSizeEx()');
exit;
end;
Guard(hs, THandleStreamEx.Create(hFile, llSize));
hs.Position := 0;
Guard(enc, TTgDrmEnc.Create(pInfo.sOrgPath));
with pInfo.Head do
begin
if enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHostName,
sPartName, sPgName, dwCustomerCode) then
begin
if enc.EncryptFromStream(PASS_DRM_DATA, hs) then
_TgDrmHook.Log('CloseHandleHook() .. Success .. EncryptFromStream()')
else
_TgDrmHook.Log('CloseHandleHook() .. Fail .. EncryptFromStream()');
end else
_TgDrmHook.Log('CloseHandleHook() .. Fail .. SetHaed()');
end;
end;
end else
_TgDrmHook.Log(Format('CloseHandleHook() .. Not Modify.. DecPath=%s', [pInfo.sDecPath]));
finally
_TgDrmHook.DcDrmFI_.Remove(hFile);
_bInternalOpen := false;
end;
end;
Result := ozCloseHandle(hFile);
except
on E: Exception do
ETgException.TraceException(E, 'Fail .. CloseHandleHook()');
end;
end;
function ReadFileHook(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD;
var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
begin
_TgDrmHook.Log(Format('ReadFileHook() .. Postion=%d', [FileSeek(hFile, 0, 1)]));
Result := ozReadFile(hFile, Buffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
end;
function WriteFileHook(hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD;
var lpNumberOfBytesWritten: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
begin
Result := ozWriteFile(hFile, Buffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
if Result and _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then
// if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then
begin
_TgDrmHook.Log('WriteFileHook()');
_TgDrmHook.DcDrmFI_[hFile].bModified := true;
end;
end;
function WriteFileExHook(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD;
const lpOverlapped: TOverlapped; lpCompletionRoutine: FARPROC): BOOL; stdcall;
begin
Result := ozWriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine);
if Result and _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then
// if _TgDrmHook.DcDrmFI_.ContainsKey(hFile) then
begin
_TgDrmHook.Log('WriteFileExHook()');
_TgDrmHook.DcDrmFI_[hFile].bModified := true;
end;
end;
function process_WH_SHELL(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if Assigned(_TgDrmHook) then
begin
try
try
if nCode >= HC_ACTION then
case nCode of
// HSHELL_ACCESSIBILITYSTATE : ; // Windows 2000/XP: accessibility 상태가 변경되었음
// HSHELL_APPCOMMAND : ; // Windows 2000/XP: 사용자의 입력 이벤트에 의해서 WM_APPCOMMAND 가 발생한 경우다
// HSHELL_ACTIVATESHELLWINDOW : ; // 쉘 메인 윈도우가 활성화 되어야 하는 경우다
// HSHELL_GETMINRECT : ; // 윈도우가 최소화/최대화된 경우다
// HSHELL_LANGUAGE : ; // 키보드 언어가 변경되거나 새로운 키보드 레이아웃이 로드된 경우다
// HSHELL_TASKMAN : ; // 사용자가 태스크 리스트를 선택한 경우다. 테스트해 본 결과 Ctrl + Esc 키를 누른 경우 훅 프로시저가 호출되었다. 시작 버튼을 눌렀을 때엔 호출되지 않는다
HSHELL_WINDOWACTIVATED, // : ; // 탑 레벨 윈도우의 활성화 상태가 변경된 경우다
HSHELL_WINDOWCREATED, // : ; // 탑 레벨 윈도우가 생성된 경우다. 이 훅이 호출되는 시점에 윈도우는 생성된 상태다
HSHELL_REDRAW : // 태스크바에 있는 윈도우 타이틀이 새로 그려지는 경우다
begin
// if _TgDrmHook.hRecentWnd_ <> wParam then
// begin
// _TgDrmHook.hRecentWnd_ := wParam;
// if SetWindowDisplayAffinity(_TgDrmHook.hRecentWnd_, 1) then
// _TgDrmHook.Log(Format('Success .. SetWindowDisplayAffinity(), Title="%s"', [GetWindowCaption(_TgDrmHook.hRecentWnd_)]))
// end;
end;
HSHELL_WINDOWDESTROYED : ; // 탑 레벨 윈도우가 파괴된 경우다. 이 훅이 호출되는 시점에 윈도우는 존재한다
HSHELL_WINDOWREPLACED : ; // Windows XP: 탑 레벨 윈도우가 대체(replaced)된 경우다
end;
except
exit;
end;
finally
Result := CallNextHookEx(_TgDrmHook.hShellHook_, nCode, wParam, lParam);
end;
end else
Result := 0;
end;
{ TTgDrmHook }
Constructor TTgDrmHook.Create;
procedure GetStartTime;
var
ftCreate,
ftExit,
ftKernel,
ftUser: TFileTime;
nDosTime: Integer;
begin
dtCreate_ := 0;
GetProcessTimes(GetCurrentProcess, ftCreate, ftExit, ftKernel, ftUser);
if FileTimeToLocalFileTime(ftCreate, ftCreate) then
if FileTimeToDosDateTime(ftCreate, LongRec(nDosTime).Hi, LongRec(nDosTime).Lo) then
dtCreate_ := FileDateToDateTime(nDosTime);
end;
var
AppList: TStringList;
begin
Inherited Create;
ASSERT(_TgDrmHook = nil);
_TgDrmHook := Self;
bInitOk_ := false;
bForceEncSave_ := false;
bUseBoxedApp_ := false;
GetStartTime;
hShellHook_ := 0;
sRecentOpenFile_ := '';
DrmExtList_ := TStringList.Create;
DrmExtList_.CaseSensitive := false;
SplitString(DRM_EXTS, '|', DrmExtList_);
ProcList_ := TList<PPointer>.Create;
DcDrmFI_ := TDictionary<THandle,PDrmFileInfo>.Create;
DcDrmFI_.OnValueNotify := OnDrmFileNotify;
ZeroMemory(@RecentDrmFI_, SizeOf(RecentDrmFI_));
SharedData_ := TTgFileMapping<TSharedData>.Create(MAP_FILENAME_APIHOOK, SizeOf(TSharedData));
if SharedData_.IsAvailable then
begin
// sPass_ := SharedData_.Data.sPass;
sTgPNames_ := UpperCase(SharedData_.Data.sTgPNames);
sLogPath_ := SharedData_.Data.sLogPath;
end;
// DrmFileList_ := TStringList.Create;
// DrmFileList_.CaseSensitive := false;
DcDecPath_ := TDictionary<String,String>.Create;
bBlockCap_ := false;
Guard(AppList, TStringList.Create);
AppList.CaseSensitive := false;
Trace_ := nil;
SplitString(sTgPNames_, '|', AppList);
if AppList.IndexOf(ModuleName) <> -1 then
begin
var sMdName: String := LowerCase(ModuleName);
// HWP는 중간 저장할때 마다 바로 파일에 쓰지 않고 파일에 닫힐때 파일에 쓴다.
// 그래서 파일쓰기 체그가 되지 않아서 이렇게 무조건 저장시 암호화 기능을 ON 한다 22_1017 13:47:26 kku
if (sMdName = 'winword.exe') or (sMdName = 'excel.exe') or
(sMdName = 'powerpnt.exe') then
bIsMsOffice_ := true
else
bForceEncSave_ := CompareText(ModuleName, 'hwp.exe') = 0;
{$IFDEF DEBUG}
Trace_ := TTgTrace.Create(ExtractFilePath(sLogPath_), ExtractFileName(sLogPath_));
Trace_.OnBeforeLog := OnBeforeLog;
Trace_.OnAfterLog := OnAfterLog;
{$ENDIF}
bUseBoxedApp_ := CompareText('Acrobat.exe', ModuleName) = 0;
// InstallHook;
DoInterceptCreate;
end;
end;
Destructor TTgDrmHook.Destroy;
begin
// UnInstallHook;
DoInterceptRemove;
_TgDrmHook := nil;
FreeAndNil(SharedData_);
if Trace_ <> nil then
FreeAndNil(Trace_);
// FreeAndNil(DrmFileList_);
FreeAndNil(DcDecPath_);
FreeAndNil(DcDrmFI_);
FreeAndNil(ProcList_);
FreeAndNil(DrmExtList_);
Inherited;
end;
procedure TTgDrmHook.OnBeforeLog(aSender: TObject);
begin
_bLogProcessing := true;
end;
procedure TTgDrmHook.OnAfterLog(aSender: TObject);
begin
_bLogProcessing := false;
end;
function TTgDrmHook.GetActive: Boolean;
begin
try
if SharedData_.IsAvailable then
Result := SharedData_.Data.bActive
else
Result := false;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. GetActive()');
end;
end;
function TTgDrmHook.GetRcvWnd: LONGLONG;
begin
try
if SharedData_.IsAvailable then
Result := SharedData_.Data.llRcvWnd
else
Result := 0;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. GetRcvWnd()');
end;
end;
procedure TTgDrmHook.OnDrmFileNotify(Sender: TObject; const Item: PDrmFileInfo; Action: TCollectionNotification);
begin
if Action = cnRemoved then
Dispose(Item);
end;
procedure TTgDrmHook.AddInterceptAPI(var aProcDest: Pointer; aProcSrc, aProcHook: Pointer; sProcName: String);
begin
if aProcDest = nil then
begin
aProcDest := InterceptCreate(aProcSrc, aProcHook);
if aProcDest <> nil then
begin
Log(Format('>>> InterceptCreate() - %s <<<', [sProcName]));
ProcList_.Add(@aProcDest);
end else
Log(Format('>>> Fail .. InterceptCreate() - %s <<<', [sProcName]));
end;
end;
procedure TTgDrmHook.DoInterceptCreate;
var
bLoadBx: Boolean;
// nTryCnt: Integer;
Label
LB_LoadBx;
begin
Log('DoInterceptCreate()');
DoInterceptRemove;
Log('DoInterceptCreate() .. 0');
if bUseBoxedApp_ then
begin
Log('UseBoxedApp...');
// nTryCnt := 0;
bLoadBx := false;
LB_LoadBx :
try
// Init BoxedApp SDK
BoxedAppSDK_SetContext('21f2f010-06e4-465f-af8f-cde6a3752c39');
Log('DoInterceptCreate() .. 1');
BoxedAppSDK_Init;
Log('DoInterceptCreate() .. 2');
// Allow injection BoxedApp engine into child processes
// BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES, TRUE);
// BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__HIDE_VIRTUAL_FILES_FROM_FILE_DIALOG, TRUE);
BoxedAppSDK_EnableOption(DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL, TRUE);
Log('DoInterceptCreate() .. 3');
bLoadBx := true;
except
Log('Fail .. BoxedAppSDK');
end;
if not bLoadBx then
begin
Sleep(10);
goto LB_LoadBx;
end;
end;
AddInterceptAPI(@ozCreateFileA, @CreateFileA, @CreateFileAHook, 'CreateFileA');
AddInterceptAPI(@ozCreateFileW, @CreateFileW, @CreateFileWHook, 'CreateFileW');
AddInterceptAPI(@ozCloseHandle, @CloseHandle, @CloseHandleHook, 'CloseHandle');
// AddInterceptAPI(@ozReadFile, @ReadFile, @ReadFileHook, 'ReadFile');
AddInterceptAPI(@ozWriteFile, @WriteFile, @WriteFileHook, 'WriteFile');
AddInterceptAPI(@ozWriteFileEx, @WriteFileEx, @WriteFileExHook, 'WriteFileEx');
bInitOk_ := true;
end;
procedure TTgDrmHook.DoInterceptRemove;
procedure RemoveAPI(var aProc: Pointer); inline;
begin
if aProc <> nil then
begin
InterceptRemove(aProc);
aProc := nil;
end;
end;
var
i: Integer;
begin
if bInitOk_ then
begin
Log('DoInterceptRemove()');
for i := 0 to ProcList_.Count - 1 do
RemoveAPI(ProcList_[i]^);
ProcList_.Clear;
// BoxedAppSDK_Exit;
bInitOk_ := false;
end;
end;
procedure TTgDrmHook.Log(sLog: String);
begin
if Trace_ <> nil then
Trace_.T('(%s) %s', [ModuleName, sLog]);
end;
function TTgDrmHook.InstallHook: Integer;
begin
Log('InstallHook');
try
hShellHook_ := SetWindowsHookEx(WH_SHELL, process_WH_SHELL, HInstance, 0);
if hShellHook_ = 0 then
begin
Log('SetWindowsHookEx(WH_SHELL) fail!!');
Result := 2;
exit;
end;
except
exit;
end;
// if (hCbtHook_ <> 0) and (hShellHook_ <> 0) then
Result := 0;
// else
// Result := -2;
end;
function TTgDrmHook.UnInstallHook: Integer;
begin
Log('UnInstallHook');
try
if hShellHook_ <> 0 then
begin
Log('UnhookWindowsHookEx(ShellHook)');
UnhookWindowsHookEx(hShellHook_);
hShellHook_ := 0;
end;
except
hShellHook_ := 0;
end;
Result := 0;
end;
function InstallDrmHook: Integer;
begin
Result := -1;
if Assigned(_TgDrmHook) then
Result := _TgDrmHook.InstallHook;
end;
function UnInstallDrmHook: Integer;
begin
Result := -1;
if Assigned(_TgDrmHook) then
Result := _TgDrmHook.UnInstallHook;
end;
exports
InstallDrmHook, UnInstallDrmHook;
end.