507 lines
14 KiB
Plaintext
507 lines
14 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ Tocsg.KvFilter }
|
|
{ }
|
|
{ Copyright (C) 2022 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit Tocsg.KvFilter;
|
|
|
|
interface
|
|
|
|
{$IFNDEF _HE_}
|
|
{$DEFINE _IMG_PARSER_}
|
|
{$ENDIF}
|
|
|
|
uses
|
|
{$IFDEF _IMG_PARSER_}
|
|
imageen, iexMetaHelpers,
|
|
{$ENDIF}
|
|
Tocsg.Obj, System.SysUtils, System.Classes, WinAPI.Windows,
|
|
Tocsg.KvFilter.Types, Tocsg.KvFilter.adinfo, Tocsg.Thread;
|
|
|
|
const
|
|
DLL_KVFILTER = 'kvfilter.dll';
|
|
DLL_KVHWP = 'kvhvp.dll';
|
|
EXE_KV_TASK = 'kvoop.exe';
|
|
EXE_KV_HWP = 'KvCttSchw.exe';
|
|
|
|
// * KeyView Filter interface revision. To be assigned to KV_GetFilterInterfaceEx().
|
|
KVFLTINTERFACE_REVISION = 6;
|
|
|
|
type
|
|
// KvSetTimeout() 때문에 필요없어짐 22_0720 10:20:35 kku
|
|
// TThdKvFilterTimeout = class(TTgThread)
|
|
// protected
|
|
// nTOMilSec_: Integer;
|
|
// dwResetTick_: DWORD;
|
|
// procedure Execute; override;
|
|
// public
|
|
// Constructor Create(nTOSec: Integer);
|
|
//
|
|
// procedure ResetTimeout;
|
|
// procedure EndTimeout;
|
|
// end;
|
|
|
|
TKvFilter = class(TTgObject)
|
|
private
|
|
{$IFDEF _IMG_PARSER_}
|
|
bDoFree_: Boolean;
|
|
ImgEn_: TImageEn;
|
|
{$ENDIF}
|
|
nLastError_: Integer;
|
|
hKvFilter_: THandle;
|
|
KvCtrl_: TKvFltInterfaceEx;
|
|
MemAllocator_: TKVMemoryStream;
|
|
pFilter_: Pointer;
|
|
|
|
FnKV_GetFilterInterfaceEx_: TKV_GetFilterInterfaceEx;
|
|
FnKV_GetKvErrorCodeEx_: TKV_GetKvErrorCodeEx;
|
|
FnKV_FilterConfig_: TKV_FilterConfig;
|
|
|
|
nFilterTOSec_: Integer;
|
|
bUseHwpDll_: Boolean;
|
|
// ThdTimeout_: TThdKvFilterTimeout;
|
|
|
|
sKvBinDir_,
|
|
sKvHwpExe_: String;
|
|
bProcAnsi_: Boolean; // 영문윈도우에서 한글 깨지는 현상 보완을 위함 24_0514 09:17:24 kku
|
|
public
|
|
Constructor Create(sDllDir: String = ''; nFilterTOSec: Integer = 0); // nFilterTOSec 필터 타임아웃 추가 22_0720 07:43:25 kku
|
|
Destructor Destroy; override;
|
|
|
|
procedure DoSummaryInfo(sSrcFile: String; aList: TStrings);
|
|
function GetDocInfoFile(sSrcFile: String): TAdDocInfo;
|
|
function FilterFile(sSrcFile, sDstFile: String): KVErrorCode;
|
|
|
|
property FilterTOSec: Integer write nFilterTOSec_;
|
|
property UseHwpDll: Boolean write bUseHwpDll_;
|
|
property KvBinDir: String read sKvBinDir_;
|
|
property KvLastError: Integer read nLastError_;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
CttSchDefine,
|
|
Tocsg.Exception, Tocsg.Convert, Tocsg.DateTime, Tocsg.Process, Tocsg.Path,
|
|
superobject, Tocsg.Files, GlobalDefine;
|
|
|
|
function _Malloc(pX: Pointer{PKvMemoryStream}; cb: LONGLONG): Pointer; pascal;
|
|
begin
|
|
Result := AllocMem(cb);
|
|
// GetMem(Result, cb);
|
|
end;
|
|
|
|
procedure _Free(pX: Pointer{PKvMemoryStream}; ptr: Pointer); pascal;
|
|
begin
|
|
FreeMem(ptr);
|
|
end;
|
|
|
|
function _Realloc(pX: Pointer{PKvMemoryStream}; ptr: Pointer; cb: LONGLONG): Pointer; pascal;
|
|
begin
|
|
ReallocMem(ptr, cb);
|
|
Result := ptr;
|
|
// Result := ReallocMemory(ptr, cb);
|
|
end;
|
|
|
|
function _Calloc(pX: Pointer{PKvMemoryStream}; ne, s: LONGLONG): Pointer; pascal;
|
|
begin
|
|
Result := AllocMem(ne);
|
|
ZeroMemory(Result, s);
|
|
// GetMem(Result, ne);
|
|
// ZeroMemory(Result, s);
|
|
end;
|
|
|
|
{ TThdKvFilterTimeout }
|
|
|
|
//Constructor TThdKvFilterTimeout.Create(nTOSec: Integer);
|
|
//begin
|
|
// Inherited Create;
|
|
// nTOMilSec_ := nTOSec * 1000;
|
|
// dwResetTick_ := 0;
|
|
// StartThread;
|
|
//end;
|
|
//
|
|
//procedure TThdKvFilterTimeout.ResetTimeout;
|
|
//begin
|
|
// Lock;
|
|
// try
|
|
// dwResetTick_ := GetTickCount;
|
|
// finally
|
|
// Unlock;
|
|
// end;
|
|
//end;
|
|
//
|
|
//procedure TThdKvFilterTimeout.EndTimeout;
|
|
//begin
|
|
// Lock;
|
|
// try
|
|
// dwResetTick_ := 0;
|
|
// finally
|
|
// Unlock;
|
|
// end;
|
|
//end;
|
|
//
|
|
//procedure TThdKvFilterTimeout.Execute;
|
|
//var
|
|
// dwResetTick: DWORD;
|
|
//begin
|
|
// while not Terminated and not GetWorkStop do
|
|
// begin
|
|
// if nTOMilSec_ > 0 then
|
|
// begin
|
|
// try
|
|
// Lock;
|
|
// try
|
|
// dwResetTick := dwResetTick_;
|
|
// finally
|
|
// Unlock;
|
|
// end;
|
|
//
|
|
// if dwResetTick > 0 then
|
|
// begin
|
|
// if (GetTickCount - dwResetTick) > nTOMilSec_ then
|
|
// begin
|
|
// // 두번 죽여야 됨 22_0720 08:54:56 kku
|
|
// TerminateProcessByName(EXE_KV_TASK);
|
|
// Sleep(1000);
|
|
// TerminateProcessByName(EXE_KV_TASK);
|
|
// EndTimeout;
|
|
// end;
|
|
// end;
|
|
// except
|
|
// on E: Exception do
|
|
// ETgException.TraceException(Self, E, 'Fail .. Execute()');
|
|
// end;
|
|
// end;
|
|
// Sleep(1000);
|
|
// end;
|
|
//end;
|
|
|
|
{$IFDEF _IMG_PARSER_}
|
|
function ImgToTxtFile(sSrcPath: String; sDstPath: String): Boolean;
|
|
var
|
|
sOcr: String;
|
|
StrList: TStringList;
|
|
begin
|
|
Result := false;
|
|
sOcr := GetRunExePathDir + DIR_CONF + EXE_OCR;
|
|
if not FileExists(sOcr) then
|
|
sOcr := GetRunExePathDir + EXE_OCR;
|
|
|
|
if FileExists(sOcr) then
|
|
begin
|
|
if ForceDirectories(ExtractFilePath(sDstPath)) then
|
|
begin
|
|
ExecuteAppWaitUntilTerminate(sOcr, Format('"%s" "%s"', [sSrcPath, sDstPath]), SW_HIDE);
|
|
Result := FileExists(sDstPath);
|
|
end;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{ TKvFilter}
|
|
|
|
Constructor TKvFilter.Create(sDllDir: String = ''; nFilterTOSec: Integer = 0);
|
|
|
|
procedure InitProcedure;
|
|
var
|
|
sDllPath: String;
|
|
nResult: KVErrorCode;
|
|
begin
|
|
if sDllDir = '' then
|
|
begin
|
|
sDllDir := GetRunExePathDir;
|
|
if not FileExists(sDllDir + DLL_KVFILTER) then
|
|
sDllDir := sDllDir + 'bin\';
|
|
end else
|
|
sDllDir := IncludeTrailingPathDelimiter(sDllDir);
|
|
sDllPath := sDllDir + DLL_KVFILTER;
|
|
|
|
if FileExists(sDllDir + DLL_KVHWP) and
|
|
FileExists(GetRunExePathDir + EXE_KV_HWP) then
|
|
sKvHwpExe_ := GetRunExePathDir + EXE_KV_HWP;
|
|
|
|
hKvFilter_ := LoadLibrary(PChar(sDllPath));
|
|
if hKvFilter_ = 0 then
|
|
begin
|
|
_Trace('Fail .. LoadLibrary(), Path="%s"', [sDllPath]);
|
|
nLastError_ := KVERR_DLLNotFound;
|
|
exit;
|
|
end;
|
|
sKvBinDir_ := sDllPath;
|
|
|
|
FnKV_GetFilterInterfaceEx_ := GetProcAddress(hKvFilter_, 'KV_GetFilterInterfaceEx');
|
|
if not Assigned(FnKV_GetFilterInterfaceEx_) then
|
|
begin
|
|
_Trace('Fail .. KV_GetFilterInterfaceEx() is NULL, Path="%s"', [sDllPath]);
|
|
nLastError_ := KVERR_General;
|
|
exit;
|
|
end;
|
|
|
|
FnKV_GetKvErrorCodeEx_ := GetProcAddress(hKvFilter_, 'KV_GetKvErrorCodeEx');
|
|
if not Assigned(FnKV_GetKvErrorCodeEx_) then
|
|
begin
|
|
_Trace('Fail .. KV_GetKvErrorCodeEx() is NULL, Path="%s"', [sDllPath]);
|
|
nLastError_ := KVERR_General;
|
|
exit;
|
|
end;
|
|
|
|
FnKV_FilterConfig_ := GetProcAddress(hKvFilter_, 'KV_FilterConfig');
|
|
if not Assigned(FnKV_FilterConfig_) then
|
|
begin
|
|
_Trace('Fail .. KV_FilterConfig() is NULL, Path="%s"', [sDllPath]);
|
|
nLastError_ := KVERR_General;
|
|
exit;
|
|
end;
|
|
|
|
nResult := FnKV_GetFilterInterfaceEx_(@KvCtrl_, KVFLTINTERFACE_REVISION);
|
|
if nResult <> KVERR_Success then
|
|
begin
|
|
_Trace('Fail .. KV_GetFilterInterfaceEx() .. ErrCode=%d, Path="%s"', [nResult, sDllPath]);
|
|
nLastError_ := nResult;
|
|
exit;
|
|
end;
|
|
|
|
MemAllocator_.pMemoryStreamPrivateData := nil;
|
|
MemAllocator_.KvMalloc := _Malloc;
|
|
MemAllocator_.KvFree := _Free;
|
|
MemAllocator_.KvRealloc := _Realloc;
|
|
MemAllocator_.KvCalloc := _Calloc;
|
|
pFilter_ := KvCtrl_.KvInit(@MemAllocator_, nil, PAnsiChar(AnsiString(sDllDir)), KVCS_UTF8, 0);
|
|
end;
|
|
|
|
begin
|
|
Inherited Create;
|
|
|
|
bProcAnsi_ := GetUserDefaultLangID <> 1042;
|
|
sKvHwpExe_ := '';
|
|
nLastError_ := 0;
|
|
nFilterTOSec_ := nFilterTOSec;
|
|
if nFilterTOSec_ = 0 then
|
|
nFilterTOSec_ := 7;
|
|
ZeroMemory(@KvCtrl_, SizeOf(KvCtrl_));
|
|
pFilter_ := nil;
|
|
bUseHwpDll_ := true;
|
|
InitProcedure;
|
|
|
|
if pFilter_ <> nil then
|
|
KvCtrl_.KvSetTimeout(pFilter_, nFilterTOSec_);
|
|
|
|
{$IFDEF _IMG_PARSER_}
|
|
ImgEn_ := TImageEn.Create(nil);
|
|
bDoFree_ := true;
|
|
// bDoFree_ := false;
|
|
// if aImgEn <> nil then
|
|
// begin
|
|
// ImgEn_ := aImgEn;
|
|
// end else begin
|
|
// ImgEn_ := nil;
|
|
//// ImgEn_ := TImageEn.Create(nil);
|
|
//// bDoFree_ := true;
|
|
// end;
|
|
{$ENDIF}
|
|
|
|
// ThdTimeout_ := TThdKvFilterTimeout.Create(nFilterTOSec_);
|
|
end;
|
|
|
|
Destructor TKvFilter.Destroy;
|
|
begin
|
|
// TerminateProcessByName(EXE_KV_TASK); // 이거 하고 두번째 TKvFilter.Destroy() 시 KvShutdown() 에서 크러쉬 됨 22_0720 10:28:30 kku
|
|
// FreeAndNil(ThdTimeout_);
|
|
try
|
|
// 여기서 크러쉬가 나는데... 원인을 찾을때까지는 봉인한다.
|
|
// 해제 시 앱이 강제종료 되는 치면적인 문제 있음
|
|
|
|
// 이거 안하면 릭이 발생함... 22_0712 16:06:12 kku
|
|
// if (pFilter_ <> nil) and Assigned(KvCtrl_.KvShutdown) then
|
|
// KvCtrl_.KvShutdown(pFilter_);
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(Self, E, 'Fail .. Destroy() - KvShutdown()');
|
|
end;
|
|
|
|
if hKvFilter_ <> 0 then
|
|
FreeLibrary(hKvFilter_);
|
|
|
|
// KvShutdown() 처리를 안하면 kvoop.exe가 남아 있다.. 그래서 처리 추가 22_0720 10:37:07 kku
|
|
TerminateProcessByName(EXE_KV_TASK);
|
|
|
|
{$IFDEF _IMG_PARSER_}
|
|
if (ImgEn_ <> nil) and bDoFree_ then
|
|
FreeAndNil(ImgEn_);
|
|
{$ENDIF}
|
|
|
|
Inherited;
|
|
end;
|
|
|
|
procedure TKvFilter.DoSummaryInfo(sSrcFile: String; aList: TStrings);
|
|
var
|
|
si: TKVSummaryInfoEx;
|
|
i: Integer;
|
|
sInfo: String;
|
|
pEnt: PKvSumInfoElemEx;
|
|
ft: TFileTime;
|
|
begin
|
|
aList.Clear;
|
|
|
|
try
|
|
if (pFilter_ <> nil) and
|
|
Assigned(KvCtrl_.KvGetOLESummaryInfoFile) and
|
|
Assigned(KvCtrl_.KvFreeOLESummaryInfo) then
|
|
begin
|
|
ZeroMemory(@si, SizeOf(si));
|
|
if KvCtrl_.KvGetOLESummaryInfoFile(pFilter_, PAnsiChar(AnsiString(sSrcFile)), @si) <> KVERR_Success then
|
|
begin
|
|
_Trace('Fail .. DoSummaryInfo() .. 1');
|
|
exit;
|
|
end;
|
|
|
|
try
|
|
if si.nElem = 0 then
|
|
exit;
|
|
|
|
for i := 0 to si.nElem - 1 do
|
|
begin
|
|
pEnt := PKvSumInfoElemEx(NativeInt(si.pElem) + (SizeOf(TKvSumInfoElemEx) * i));
|
|
if pEnt.nIsValid = 0 then
|
|
continue;
|
|
sInfo := Format('%d %d ', [pEnt.nIsValid, pEnt.nType]);
|
|
|
|
case pEnt.nType of
|
|
KV_String : sInfo := sInfo + Format('"%s"', [PUTF8Char(pEnt.pData)]);
|
|
KV_Int4 : sInfo := sInfo + Format('%d', [Integer(pEnt.pData)]);
|
|
KV_DateTime :
|
|
begin
|
|
CopyMemory(@ft, pEnt.pData, 8);
|
|
if i = 9 then
|
|
begin
|
|
sInfo := sInfo + Format('%d Minutes', [LONGLONG(ft) div 600000000]);
|
|
end else begin
|
|
sInfo := sInfo + DateTimeToStr(ConvFileTimeToDateTime(ft));
|
|
end;
|
|
end;
|
|
KV_ClipBoard : sInfo := sInfo + 'Clipboard data';
|
|
KV_Bool : sInfo := sInfo + BooleanToStr(Integer(pEnt.pData) <> 0, 'true', 'false');
|
|
KV_Unicode : sInfo := sInfo + Format('U"%s"', [PChar(pEnt.pData)]);
|
|
KV_IEEE8 : sInfo := sInfo + Format('%f', [pEnt.pData]);
|
|
KV_Other : sInfo := sInfo + 'Other';
|
|
else sInfo := sInfo + Format('Bad element type! - %d', [pEnt.nType]);
|
|
end;
|
|
|
|
aList.Add(sInfo + Format(' %s', [BooleanToStr(pEnt.nIsValid = 1, AnsiString(pEnt.pcType), '(null)')]));
|
|
end;
|
|
finally
|
|
KvCtrl_.KvFreeOLESummaryInfo(pFilter_, @si);
|
|
end;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(Self, E, 'Fail .. DoSummaryInfo()');
|
|
end;
|
|
end;
|
|
|
|
function TKvFilter.GetDocInfoFile(sSrcFile: String): TAdDocInfo;
|
|
begin
|
|
ZeroMemory(@Result, SizeOf(Result));
|
|
if (pFilter_ <> nil) and Assigned(KvCtrl_.KvGetDocInfoFile) then
|
|
KvCtrl_.KvGetDocInfoFile(pFilter_, PAnsiChar(AnsiString(sSrcFile)), @Result);
|
|
end;
|
|
|
|
function TKvFilter.FilterFile(sSrcFile, sDstFile: String): KVErrorCode;
|
|
var
|
|
sExt,
|
|
sTemp: String;
|
|
begin
|
|
// _Trace('FilterFile() .. Path=%s', [sSrcFile]);
|
|
// if not FileExists(sSrcFile) then
|
|
// begin
|
|
// Result := -2;
|
|
// exit;
|
|
// end;
|
|
|
|
Result := -1;
|
|
try
|
|
sExt := GetFileExt(sSrcFile).ToUpper;
|
|
if (sExt = 'TXT') or (sExt = 'LOG') or (sExt = 'HTML') or
|
|
(sExt = 'HTM') or (sExt = 'XML') or (sExt = 'JSON') or
|
|
(sExt = 'CSV') or (sExt = 'INI') then
|
|
begin
|
|
if CopyFile(PChar(sSrcFile), PChar(sDstFile), false) then
|
|
Result := KVERR_Success
|
|
else
|
|
Result := KVERR_CreateOutputFileFailed;
|
|
end else
|
|
{$IFDEF _IMG_PARSER_}
|
|
if (sExt = 'DCM') and (ImgEn_ <> nil) and ImgEn_.IO.LoadFromFile(sSrcFile) then
|
|
begin
|
|
var StrList: TStringList := TStringList.Create;
|
|
try
|
|
ImgEn_.IO.Params.Dicom_WriteToStrings(StrList, [diProprietary, diChildTags]);
|
|
if StrList.Text <> '' then
|
|
begin
|
|
StrList.SaveToFile(sDstFile, TEncoding.UTF8);
|
|
Result := KVERR_Success;
|
|
end;
|
|
finally
|
|
FreeAndNil(StrList);
|
|
end;
|
|
end else
|
|
if (Pos(sExt, OCR_IMG_EXTS) > 0) and ImgToTxtFile(sSrcFile, sDstFile) then
|
|
begin
|
|
Result := KVERR_Success;
|
|
end else
|
|
{$ENDIF}
|
|
if (pFilter_ <> nil) and Assigned(KvCtrl_.KvFilterFile) then
|
|
begin
|
|
if bUseHwpDll_ and (sKvHwpExe_ <> '') and
|
|
(sExt = 'HWP') or (sExt = 'HWPX') then
|
|
begin
|
|
Result := -2;
|
|
sTemp := GetRunExePathDir + '$KvHvpInfo.j$on';
|
|
var O: ISuperObject := SO;
|
|
O.S['Src'] := sSrcFile;
|
|
O.S['Dest'] := sDstFile;
|
|
if SaveJsonObjToFile(O, sTemp) then
|
|
begin
|
|
ExecuteAppWaitUntilTerminate(sKvHwpExe_, Format('"%s"', [sTemp]), SW_HIDE, 5000);
|
|
if FileExists(sDstFile) then
|
|
Result := KVERR_Success;
|
|
end;
|
|
end else begin
|
|
// ThdTimeout_.ResetTimeout;
|
|
// Result := KvCtrl_.KvFilterFile(pFilter_, PAnsiChar(AnsiString(sSrcFile)), PAnsiChar(AnsiString(sDstFile)), nil);
|
|
// ThdTimeout_.EndTimeout;
|
|
|
|
if bProcAnsi_ then
|
|
begin
|
|
var sBkPath: UTF8String := 'C:\ProgramData\HE\kvansi\';
|
|
if ForceDirectories(sBkPath) then
|
|
begin
|
|
sBkPath := sBkPath + IntToStr(GetTickCount);
|
|
try
|
|
Result := KvCtrl_.KvFilterFile(pFilter_, PUTF8Char(UTF8String(sSrcFile)), PUTF8Char(UTF8String(sBkPath)), nil);
|
|
if Result = KVERR_Success then
|
|
MoveFile_wait(sBkPath, sDstFile);
|
|
finally
|
|
if FileExists(sBkPath) then
|
|
DeleteFileA(PAnsiChar(sBkPath));
|
|
end;
|
|
end;
|
|
end else
|
|
Result := KvCtrl_.KvFilterFile(pFilter_, PUTF8Char(UTF8String(sSrcFile)), PUTF8Char(UTF8String(sDstFile)), nil);
|
|
end;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
ETgException.TraceException(Self, E, 'Fail .. FilterFile()');
|
|
Result := -99;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|