mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 02:07:07 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
315
CPP/7zip/UI/Explorer/DllExports.cpp
Executable file
315
CPP/7zip/UI/Explorer/DllExports.cpp
Executable file
@@ -0,0 +1,315 @@
|
||||
// DLLExports.cpp
|
||||
//
|
||||
// Notes:
|
||||
// Win2000:
|
||||
// If I register at HKCR\Folder\ShellEx then DLL is locked.
|
||||
// otherwise it unloads after explorer closing.
|
||||
// but if I call menu for desktop items it's locked all the time
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <locale.h>
|
||||
|
||||
#include <initguid.h>
|
||||
#include <windows.h>
|
||||
#include <ShlGuid.h>
|
||||
#include <OleCtl.h>
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Windows/DLL.h"
|
||||
#include "Windows/Registry.h"
|
||||
|
||||
#include "../../IPassword.h"
|
||||
#include "../../FileManager/LangUtils.h"
|
||||
#include "../Agent/Agent.h"
|
||||
|
||||
#include "ContextMenu.h"
|
||||
#include "OptionsDialog.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
#ifndef _UNICODE
|
||||
bool g_IsNT = false;
|
||||
#endif
|
||||
|
||||
LONG g_DllRefCount = 0; // Reference count of this DLL.
|
||||
|
||||
static LPCWSTR kShellExtName = L"7-Zip Shell Extension";
|
||||
static LPCTSTR kClsidMask = TEXT("CLSID\\%s");
|
||||
static LPCTSTR kClsidInprocMask = TEXT("CLSID\\%s\\InprocServer32");
|
||||
static LPCTSTR kApprovedKeyPath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved");
|
||||
|
||||
// #define ODS(sz) OutputDebugString(L#sz)
|
||||
|
||||
class CShellExtClassFactory:
|
||||
public IClassFactory,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
CShellExtClassFactory() { InterlockedIncrement(&g_DllRefCount); }
|
||||
~CShellExtClassFactory() { InterlockedDecrement(&g_DllRefCount); }
|
||||
|
||||
|
||||
MY_UNKNOWN_IMP1_MT(IClassFactory)
|
||||
|
||||
STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, void**);
|
||||
STDMETHODIMP LockServer(BOOL);
|
||||
};
|
||||
|
||||
STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
|
||||
REFIID riid, void **ppvObj)
|
||||
{
|
||||
// ODS("CShellExtClassFactory::CreateInstance()\r\n");
|
||||
*ppvObj = NULL;
|
||||
if (pUnkOuter)
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
|
||||
CZipContextMenu *shellExt;
|
||||
try
|
||||
{
|
||||
shellExt = new CZipContextMenu();
|
||||
}
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
if (shellExt == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT res = shellExt->QueryInterface(riid, ppvObj);
|
||||
if (res != S_OK)
|
||||
delete shellExt;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */)
|
||||
{
|
||||
return S_OK; // Check it
|
||||
}
|
||||
|
||||
static bool IsItWindowsNT()
|
||||
{
|
||||
OSVERSIONINFO versionInfo;
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
|
||||
if (!::GetVersionEx(&versionInfo))
|
||||
return false;
|
||||
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
|
||||
{
|
||||
// setlocale(LC_COLLATE, ".ACP");
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
g_hInstance = hInstance;
|
||||
// ODS("In DLLMain, DLL_PROCESS_ATTACH\r\n");
|
||||
#ifdef _UNICODE
|
||||
if (!IsItWindowsNT())
|
||||
return FALSE;
|
||||
#else
|
||||
g_IsNT = IsItWindowsNT();
|
||||
#endif
|
||||
}
|
||||
else if (dwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
// ODS("In DLLMain, DLL_PROCESS_DETACH\r\n");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Used to determine whether the DLL can be unloaded by OLE
|
||||
|
||||
STDAPI DllCanUnloadNow(void)
|
||||
{
|
||||
// ODS("In DLLCanUnloadNow\r\n");
|
||||
return (g_DllRefCount == 0 ? S_OK : S_FALSE);
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||||
{
|
||||
// ODS("In DllGetClassObject\r\n");
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(rclsid, CLSID_CZipContextMenu))
|
||||
{
|
||||
CShellExtClassFactory *cf;
|
||||
try
|
||||
{
|
||||
cf = new CShellExtClassFactory;
|
||||
}
|
||||
catch(...) { return E_OUTOFMEMORY; }
|
||||
if (cf == 0)
|
||||
return E_OUTOFMEMORY;
|
||||
HRESULT res = cf->QueryInterface(riid, ppv);
|
||||
if (res != S_OK)
|
||||
delete cf;
|
||||
return res;
|
||||
}
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
// return _Module.GetClassObject(rclsid, riid, ppv);
|
||||
}
|
||||
|
||||
static BOOL GetStringFromIID(CLSID clsid, LPTSTR s, int size)
|
||||
{
|
||||
LPWSTR pwsz;
|
||||
if (StringFromIID(clsid, &pwsz) != S_OK)
|
||||
return FALSE;
|
||||
if(!pwsz)
|
||||
return FALSE;
|
||||
#ifdef UNICODE
|
||||
lstrcpyn(s, pwsz, size);
|
||||
#else
|
||||
WideCharToMultiByte(CP_ACP, 0, pwsz, -1, s, size, NULL, NULL);
|
||||
#endif
|
||||
CoTaskMemFree(pwsz);
|
||||
s[size - 1] = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HKEY hRootKey;
|
||||
LPCTSTR SubKey;
|
||||
LPCWSTR ValueName;
|
||||
LPCWSTR Data;
|
||||
} CRegItem;
|
||||
|
||||
static BOOL RegisterServer(CLSID clsid, LPCWSTR title)
|
||||
{
|
||||
TCHAR clsidString[MAX_PATH];
|
||||
if (!GetStringFromIID(clsid, clsidString, MAX_PATH))
|
||||
return FALSE;
|
||||
|
||||
UString modulePath;
|
||||
if (!NDLL::MyGetModuleFileName(g_hInstance, modulePath))
|
||||
return FALSE;
|
||||
|
||||
CRegItem clsidEntries[] =
|
||||
{
|
||||
HKEY_CLASSES_ROOT, kClsidMask, NULL, title,
|
||||
HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePath,
|
||||
HKEY_CLASSES_ROOT, kClsidInprocMask, L"ThreadingModel", L"Apartment",
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
//register the CLSID entries
|
||||
for(int i = 0; clsidEntries[i].hRootKey; i++)
|
||||
{
|
||||
TCHAR subKey[MAX_PATH];
|
||||
wsprintf(subKey, clsidEntries[i].SubKey, clsidString);
|
||||
NRegistry::CKey key;
|
||||
if (key.Create(clsidEntries[i].hRootKey, subKey, NULL,
|
||||
REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR)
|
||||
return FALSE;
|
||||
key.SetValue(clsidEntries[i].ValueName, clsidEntries[i].Data);
|
||||
}
|
||||
|
||||
if(IsItWindowsNT())
|
||||
{
|
||||
NRegistry::CKey key;
|
||||
if (key.Create(HKEY_LOCAL_MACHINE, kApprovedKeyPath, NULL,
|
||||
REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR)
|
||||
key.SetValue(GetUnicodeString(clsidString), title);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI DllRegisterServer(void)
|
||||
{
|
||||
return RegisterServer(CLSID_CZipContextMenu, kShellExtName) ? S_OK: SELFREG_E_CLASS;
|
||||
}
|
||||
|
||||
static BOOL UnregisterServer(CLSID clsid)
|
||||
{
|
||||
TCHAR clsidString[MAX_PATH];
|
||||
if (!GetStringFromIID(clsid, clsidString, MAX_PATH))
|
||||
return FALSE;
|
||||
|
||||
TCHAR subKey[MAX_PATH];
|
||||
wsprintf(subKey, kClsidInprocMask, clsidString);
|
||||
RegDeleteKey(HKEY_CLASSES_ROOT, subKey);
|
||||
|
||||
wsprintf (subKey, kClsidMask, clsidString);
|
||||
RegDeleteKey(HKEY_CLASSES_ROOT, subKey);
|
||||
|
||||
if(IsItWindowsNT())
|
||||
{
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kApprovedKeyPath, 0, KEY_SET_VALUE, &hKey) == NOERROR)
|
||||
{
|
||||
RegDeleteValue(hKey, clsidString);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI DllUnregisterServer(void)
|
||||
{
|
||||
return UnregisterServer(CLSID_CZipContextMenu) ? S_OK: SELFREG_E_CLASS;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(
|
||||
const GUID *classID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject)
|
||||
{
|
||||
LoadLangOneTime();
|
||||
COM_TRY_BEGIN
|
||||
*outObject = 0;
|
||||
if (*classID == CLSID_CAgentArchiveHandler)
|
||||
{
|
||||
if (*interfaceID == IID_IFolderManager)
|
||||
{
|
||||
CMyComPtr<IFolderManager> manager = new CArchiveFolderManager;
|
||||
*outObject = manager.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
if (*classID == CLSID_CSevenZipOptions)
|
||||
{
|
||||
if (*interfaceID == IID_IPluginOptions)
|
||||
{
|
||||
CMyComPtr<IPluginOptions> options = new CSevenZipOptions;
|
||||
*outObject = options.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDAPI GetPluginProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
::VariantClear((tagVARIANT *)value);
|
||||
switch(propID)
|
||||
{
|
||||
case NPlugin::kName:
|
||||
if ((value->bstrVal = ::SysAllocString(L"7-Zip")) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
case NPlugin::kClassID:
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(
|
||||
(const char *)&CLSID_CAgentArchiveHandler, sizeof(GUID))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
case NPlugin::kOptionsClassID:
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(
|
||||
(const char *)&CLSID_CSevenZipOptions, sizeof(GUID))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
/*
|
||||
case NArchive::kType:
|
||||
propVariant = UINT32(0);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user