525 lines
14 KiB
Plaintext
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.
|