BSOne.SFC/eCrmHE/DLL_Bs1shl/BS1Shell.pas

525 lines
14 KiB
Plaintext

unit BS1Shell;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, ActiveX, Classes, ComObj, StdVcl, Winapi.ShlObj,
System.SysUtils;
type
// TBSOneShell = class(TComObject, IShellExtInit, IExplorerCommand)
TBSOneShell = class(TComObject, IShellExtInit, IContextMenu)
protected
{ IShellExtInit }
function IShellExtInit.Initialize = ShellInitialize; // 이름을 오버로딩해야함
// 이게 오버로딩된 함수
function ShellInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; stdcall;
{ IContextMenu }
function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult; stdcall;
function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
function GetCommandString(idCmd: UINT_PTR; uFlags: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult; stdcall;
end;
TBSOneShellFac = class(TComObjectFactory)
public
procedure UpdateRegistry(Register: Boolean); override;
end;
const
Class_BSOneShell: TGUID = '{FD43588C-B83F-4157-8D58-30A5BE32F46D}'; // '{0AAB383E-E7A7-4200-AB02-3FBCEEAF94DE}';
implementation
uses
System.Win.ComServ, Winapi.ShellAPI, superobject, System.Win.Registry, Tocsg.Safe, Tocsg.Registry, Tocsg.Path,
GlobalDefine,
Tocsg.Shell,
Vcl.Graphics, Vcl.Imaging.pngimage, System.IniFiles, Tocsg.Win32, Condition, Tocsg.Strings;
var
_SelFileList: TStringList = nil;
_SelTaskList: TStringList = nil;
_AipExtList: TStringList = nil;
_nCmdDrmEnc: Integer = -1;
_nCmdDrmDec: Integer = -1;
_nCmdPrtExp: Integer = -1;
_nCmdSc2Aip: Integer = -1;
_nCmdAip2Sc: Integer = -1;
_nCmdAipEnc: Integer = -1;
_nCmdAipDec: Integer = -1;
// 선택된 파일명을 받아오는 부분. Drag&Drop 형태로 받아온다는 걸 이해하자.
function TBSOneShell.ShellInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
var
Medium: TStgMedium;
FE: TFormatETC;
nCnt, nLen, i: Integer;
sPath: String;
begin
Result := S_FALSE;
if lpdobj = nil then
exit;
// 드롭된 파일명을 풀어냄
with FE do
begin
cfFormat := CF_HDROP;
ptd := nil;
dwAspect := DVASPECT_CONTENT;
lIndex := -1;
tymed := TYMED_HGLOBAL;
end;
if Failed(lpdobj.GetData(FE, Medium)) then
exit;
if _SelFileList <> nil then
begin
_SelFileList.Clear;
try
nCnt := DragQueryFile(Medium.hGlobal, DWORD(-1), nil, MAX_PATH);
for i := 0 to nCnt - 1 do
begin
nLen := DragQueryFile(Medium.hGlobal, i, nil, 0) + 1;
SetLength(sPath, nLen);
DragQueryFile(Medium.hGlobal, i, PChar(sPath), nLen);
if sPath[nLen] = #0 then
SetLength(sPath, nLen - 1);
// 파일만 추가
if FileExists(sPath) then
_SelFileList.Add(sPath);
// else if DirectoryExists(sPath) then
// _SelFileList.Add(sPath)
end;
finally
ReleaseStgMedium(Medium);
end;
if _SelFileList.Count > 0 then
Result := S_OK;
end;
end;
function MakeHResult(Severity, Facility: LongWord; Code: Word): HRESULT;
begin
Result := HRESULT((Severity shl 31) or (Facility shl 16) or Code);
end;
function TBSOneShell.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult;
function GetPngResFromFile(sPath: String; sId: String): TPngImage;
var
hInst: THandle;
res: TResourceStream;
ms: TMemoryStream;
begin
Result := nil;
if not FileExists(sPath) then
exit;
hInst := LoadLibraryEx(PChar(sPath), 0, LOAD_LIBRARY_AS_DATAFILE);
if hInst <> 0 then
begin
try
Guard(res, TResourceStream.Create(hInst, sId, 'raw'));
if res <> nil then
begin
Guard(ms, TMemoryStream.Create);
res.SaveToStream(ms);
ms.Position := 0;
Result := TPngImage.Create;
Result.LoadFromStream(ms);
// Result.SaveToFile('C:\Users\kku\Desktop\' + sId + '.ico');
end;
except
// ..
if Result <> nil then
FreeAndNil(Result);
end;
end;
FreeLibrary(hInst);
end;
var
hMenuTasks : Cardinal;
MenuInfo: TMenuItemInfo;
sPath,
sDrm1, sDrm2, sPrint: String;
png: TPngImage;
bmp: TBitmap;
nAddMenuCnt: Integer;
begin
Result := S_OK;
if (_SelFileList = nil) or (_SelFileList.Count = 0) then
exit;
if _SelTaskList = nil then
exit;
if (_AipExtList <> nil) and (_AipExtList.Count = 0) then
SplitString(AIP_EXTS, '|', _AipExtList);
// 더블클릭 제외 (일반적 실행)
if (uFlags and CMF_DEFAULTONLY) <> 0 then
exit;
nAddMenuCnt := 0;
// InsertMenu(Menu, indexMenu, MF_SEPARATOR or MF_BYPOSITION, 0, nil); // SEPARATOR // 안먹힌다
if InsertMenu(Menu, indexMenu, MF_SEPARATOR or MF_BYPOSITION, 0, nil) then
begin
Inc(indexMenu);
Inc(nAddMenuCnt);
end;
sPath := GetProgramFilesDir + DIR_HE + EXE_HE;
if not FileExists(sPath) then
sPath := 'C:\taskToCSG\eCrmHE\OUT_Release - Win64\eCrmHomeEdition.exe';
if MutexExists(MUTEX_SHELL_MIPENC) then
begin
if _AipExtList.IndexOf(GetFileExt(_SelFileList[0])) <> -1 then
begin
sDrm1 := '문서 암호화';
sDrm2 := '문서 암호화 해제';
var hSub: HMENU := 0;
var bAddSub: Boolean := false;
// if MutexExists(MUTEX_SHELL_DRMENC) then
begin
if hSub = 0 then
hSub := CreatePopupMenu;
if InsertMenu(hSub, 0, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, PChar(sDrm1)) then
begin
Guard(png, GetPngResFromFile(sPath, 'RS_DRMLOCK'));
if png <> nil then
begin
bmp := TBitmap.Create;
bmp.Assign(png);
// SetMenuItemBitmaps(hSub, 101, MF_BYPOSITION, bmp.Handle, bmp.Handle);
var mii: MENUITEMINFO;
ZeroMemory(@mii, SizeOf(mii));
mii.cbSize := SizeOf(mii);
mii.fMask := MIIM_BITMAP;
mii.hbmpItem := bmp.Handle;
// SetMenuItemBitmaps() 보다 SetMenuItemInfo() 권장됨 25_1217 10:35:37 kku
SetMenuItemInfo(hSub, idCmdFirst + nAddMenuCnt, false, mii);
end;
_nCmdAipEnc := nAddMenuCnt;
Inc(nAddMenuCnt);
bAddSub := true;
end;
end;
// 구분선
// AppendMenu(hSub, MF_SEPARATOR, 0, nil);
// AppendMenu(hSub, MF_STRING, 3004, '설정');
if MutexExists(MUTEX_SHELL_DRMDEC) then
begin
if hSub = 0 then
hSub := CreatePopupMenu;
if InsertMenu(hSub, 1, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, PChar(sDrm2)) then
begin
Guard(png, GetPngResFromFile(sPath, 'RS_DRMUNLOCK'));
if png <> nil then
begin
bmp := TBitmap.Create;
bmp.Assign(png);
// SetMenuItemBitmaps(hSub, 102, MF_BYPOSITION, bmp.Handle, bmp.Handle);
var mii: MENUITEMINFO;
ZeroMemory(@mii, SizeOf(mii));
mii.cbSize := SizeOf(mii);
mii.fMask := MIIM_BITMAP;
mii.hbmpItem := bmp.Handle;
// SetMenuItemBitmaps() 보다 SetMenuItemInfo() 권장됨 25_1217 10:35:37 kku
SetMenuItemInfo(hSub, idCmdFirst + nAddMenuCnt, false, mii);
end;
_nCmdAipDec := nAddMenuCnt;
Inc(nAddMenuCnt);
bAddSub := true;
end;
end;
if bAddSub then
begin
if InsertMenu(Menu, indexMenu, MF_BYPOSITION or MF_POPUP, hSub, PChar('문서 암호화/해제')) then
begin
Inc(indexMenu);
// Inc(nAddMenuCnt); // cmd id가 없는건 추가 갯수에 포함하면 안된다 25_1217 kku
end;
end;
end;
// CUSTOMER_TYPE := GetRegValueAsInteger(HKEY_CURRENT_USER, REG_HE, 'CT');
// case CUSTOMER_TYPE of
// CUSTOMER_HCA :
// begin
// if InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, 'SC-DRM → AIP') then
// begin
// Guard(png, GetPngResFromFile(sPath, 'RS_DRMLOCK'));
// if png <> nil then
// begin
// bmp := TBitmap.Create;
// bmp.Assign(png);
// SetMenuItemBitmaps(Menu, indexMenu, MF_BYPOSITION, bmp.Handle, bmp.Handle);
// end;
//
// _nCmdSc2Aip := nAddMenuCnt;
// Inc(indexMenu);
// Inc(nAddMenuCnt);
// end;
//
// if InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, 'AIP → SC-DRM') then
// begin
// Guard(png, GetPngResFromFile(sPath, 'RS_DRMLOCK'));
// if png <> nil then
// begin
// bmp := TBitmap.Create;
// bmp.Assign(png);
// SetMenuItemBitmaps(Menu, indexMenu, MF_BYPOSITION, bmp.Handle, bmp.Handle);
// end;
//
// _nCmdAip2Sc := nAddMenuCnt;
// Inc(indexMenu);
// Inc(nAddMenuCnt);
// end;
// end;
// end;
end else begin
if IsBS1Display then
begin
sDrm1 := 'BSOne으로 DRM 적용';
sDrm2 := 'BSOne으로 DRM 해제';
end else begin
sDrm1 := 'QS-eCRM으로 DRM 적용';
sDrm2 := 'QS-eCRM으로 DRM 해제';
end;
if MutexExists(MUTEX_SHELL_DRMENC) then
begin
if InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, PChar(sDrm1)) then
begin
Guard(png, GetPngResFromFile(sPath, 'RS_DRMLOCK'));
if png <> nil then
begin
bmp := TBitmap.Create;
bmp.Assign(png);
SetMenuItemBitmaps(Menu, indexMenu, MF_BYPOSITION, bmp.Handle, bmp.Handle);
end;
_nCmdDrmEnc := nAddMenuCnt;
Inc(indexMenu);
Inc(nAddMenuCnt);
end;
end;
if MutexExists(MUTEX_SHELL_DRMDEC) then
begin
if InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, PChar(sDrm2)) then
begin
Guard(png, GetPngResFromFile(sPath, 'RS_DRMUNLOCK'));
if png <> nil then
begin
bmp := TBitmap.Create;
bmp.Assign(png);
SetMenuItemBitmaps(Menu, indexMenu, MF_BYPOSITION, bmp.Handle, bmp.Handle);
end;
_nCmdDrmDec := nAddMenuCnt;
Inc(indexMenu);
Inc(nAddMenuCnt);
end;
end;
end;
if MutexExists(MUTEX_SHELL_EXPT_PRTWATER) then
begin
sPrint := '프린트 워터마크 예외신청';
if InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst + nAddMenuCnt, PChar(sPrint)) then
begin
Guard(png, GetPngResFromFile(sPath, 'RS_DRMUNLOCK'));
if png <> nil then
begin
bmp := TBitmap.Create;
bmp.Assign(png);
SetMenuItemBitmaps(Menu, indexMenu, MF_BYPOSITION, bmp.Handle, bmp.Handle);
end;
_nCmdPrtExp := nAddMenuCnt;
Inc(indexMenu);
Inc(nAddMenuCnt);
end;
end;
if InsertMenu(Menu, indexMenu, MF_SEPARATOR or MF_BYPOSITION, 0, nil) then
begin
Inc(indexMenu);
Inc(nAddMenuCnt);
end;
// 메뉴 앞에 작은 아이콘 이미지 추가
//SetMenuItemBitmaps(Menu, 0, MF_BYPOSITION, bBitmap, bBitmap);
// 추가한 항목의 개수
Result := MakeHResult(SEVERITY_SUCCESS, 0, nAddMenuCnt);;
end;
function TBSOneShell.GetCommandString(idCmd: UINT_PTR; uFlags: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult;
var
nCnt: Integer;
begin
if idCmd = 0 then
begin
// if _SelFileList <> nil then
// nCnt := _SelFileList.Count
// else
// nCnt := 0;
//
// // 커서가 메뉴항목 위로 올라올 때 상태표시줄에 표시할 문자열 요청
// if uFlags = GCS_HELPTEXT then
// StrLCopy(pszName, LPSTR(Format('[%s] 목록에 추가될 항목 수 : %d', [APP_NAME, nCnt])), cchMax);
Result := NOERROR;
end else
Result := E_INVALIDARG;
end;
function TBSOneShell.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
sPgPath,
sTempPath: String;
exInfo: ShellExecuteInfo;
O, OA: ISuperObject;
ss: TStringStream;
i, nCmdOffset: Integer;
ini: TIniFile;
hMain: HWND;
begin
Result := E_INVALIDARG;
if HiWord(Integer(lpici.lpVerb)) <> 0 then
exit;
// 처음엔 메뉴 아이디 (dwCmd, idCmd) 인줄 알았는데 아니었다...
// 일반 메뉴든 서브 메뉴든 상관없이,
// 메뉴를 추가한 순서대로 인덱스 번호가 메겨지는것 같다... 0부터 시작.. 18_1127 23:08:35 kku
nCmdOffset := LoWord(NativeUInt(lpici.lpVerb));
if (_SelFileList = nil) or (_SelFileList.Count = 0) then
exit;
if _SelTaskList = nil then
exit;
sPgPath := GetProgramFilesDir + DIR_HE;
if not FileExists(sPgPath + EXE_HE) then
exit;
if not FileExists(sPgPath + INI_HE) then
exit;
begin
Guard(ini, TIniFile.Create(sPgPath + INI_HE));
hMain := StrToInt64Def(ini.ReadString('Config', 'MW', '0'), 0);
if hMain = 0 then
exit;
end;
OA := TSuperObject.Create(stArray);
for i := 0 to _SelFileList.Count - 1 do
OA.AsArray.Add(_SelFileList[i]);
O := SO;
if nCmdOffset = _nCmdDrmEnc then
O.I['Cmd'] := 1
else if nCmdOffset = _nCmdDrmDec then
O.I['Cmd'] := 2
else if nCmdOffset = _nCmdPrtExp then
O.I['Cmd'] := 3
else if nCmdOffset = _nCmdSc2Aip then
O.I['Cmd'] := 4
else if nCmdOffset = _nCmdAip2Sc then
O.I['Cmd'] := 5
else if nCmdOffset = _nCmdAipEnc then
O.I['Cmd'] := 6
else if nCmdOffset = _nCmdAipDec then
O.I['Cmd'] := 7;
O.O['Files'] := OA;
O.S['Dir'] := AnsiString(lpici.lpDirectory);
ss := TStringStream.Create(O.AsString, TEncoding.UTF8);
try
sTempPath := sPgPath[1] + ':\ProgramData\HE\Task\';
if ForceDirectories(sTempPath) then
begin
sTempPath := sTempPath + 'bs1.$shl';
if FileExists(sTempPath) then
DeleteFile(sTempPath);
ss.SaveToFile(sTempPath);
PostMessage(hMain, WM_REQUEST_DRM, 0, 0);
end;
finally
ss.Free;
end;
Result := S_OK;
end;
{ TBSOneShellFac }
procedure TBSOneShellFac.UpdateRegistry(Register: Boolean);
begin
if Register then
begin
inherited UpdateRegistry(Register);
// * : 전체 파일
// Directory : 디렉토리
// Drive : 드라이브
// Folder : 폴더
CreateRegKey('*\shellex\ContextMenuHandlers\BSOne', '', GUIDToString(Class_BSOneShell));
CreateRegKey('Directory\shellex\ContextMenuHandlers\BSOne', '', GUIDToString(Class_BSOneShell));
end else begin
DeleteRegKey('Directory\shellex\ContextMenuHandlers\BSOne');
DeleteRegKey('*\shellex\ContextMenuHandlers\BSOne');
inherited UpdateRegistry(Register);
end;
end;
initialization
_SelFileList := TStringList.Create;
_SelTaskList := TStringList.Create;
_AipExtList := TStringList.Create;
_AipExtList.CaseSensitive := false;
TBSOneShellFac.Create(ComServer, TBSOneShell, Class_BSOneShell,
'BSOneShell', 'BSOne', ciMultiInstance, tmApartment);
finalization
FreeAndNil(_AipExtList);
FreeAndNil(_SelTaskList);
FreeAndNil(_SelFileList);
end.