* Make rshell.dll able to register its classes and support CoCreateInstance.

svn path=/trunk/; revision=65757
This commit is contained in:
David Quintana 2014-12-20 16:04:45 +00:00
parent b8416cd7f3
commit a620535b0f
3 changed files with 173 additions and 0 deletions

View file

@ -31,6 +31,7 @@ target_link_libraries(rshell
add_importlibs(rshell
uxtheme
shlwapi
advapi32
shell32
comctl32
gdi32

View file

@ -39,10 +39,84 @@ public:
CRShellModule gModule;
CAtlWinModule gWinModule;
HINSTANCE g_hRShell;
static LSTATUS inline _RegSetStringValueW(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpStringData)
{
DWORD dwStringDataLen = lstrlenW(lpStringData);
return RegSetValueExW(hKey, lpValueName, 0, REG_SZ, (BYTE *) lpStringData, 2 * (dwStringDataLen + 1));
}
static HRESULT RegisterComponent(REFGUID clsid, LPCWSTR szDisplayName)
{
WCHAR szFilename[MAX_PATH];
WCHAR szClsid[MAX_PATH];
WCHAR szRoot[MAX_PATH];
if (!StringFromGUID2(clsid, szClsid, _countof(szClsid)))
return E_FAIL;
if (!GetModuleFileNameW(g_hRShell, szFilename, _countof(szFilename)))
return E_FAIL;
HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid);
if (FAILED(hr))
return hr;
DWORD dwDisposition;
HKEY hkRoot;
if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, NULL, 0, KEY_WRITE, 0, &hkRoot, &dwDisposition) != 0)
return E_FAIL;
HKEY hkServer;
_RegSetStringValueW(hkRoot, NULL, szDisplayName);
if (RegCreateKeyExW(hkRoot, L"InprocServer32", 0, NULL, 0, KEY_SET_VALUE, 0, &hkServer, &dwDisposition) != 0)
{
RegCloseKey(hkRoot);
return E_FAIL;
}
_RegSetStringValueW(hkServer, NULL, szFilename);
_RegSetStringValueW(hkServer, L"ThreadingModel", L"Both");
RegCloseKey(hkServer);
RegCloseKey(hkRoot);
return S_OK;
}
static HRESULT UnregisterComponent(REFGUID clsid)
{
WCHAR szClsid[MAX_PATH];
WCHAR szRoot[MAX_PATH];
HKEY hkRoot;
if (!StringFromGUID2(clsid, szClsid, _countof(szClsid)))
return E_FAIL;
HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid);
if (FAILED(hr))
return hr;
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, KEY_WRITE, &hkRoot) != 0)
return E_FAIL;
RegDeleteKeyW(hkRoot, L"InprocServer32");
RegCloseKey(hkRoot);
RegDeleteKeyW(HKEY_CLASSES_ROOT, szRoot);
return S_OK;
}
STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hRShell = hInstance;
/* HACK - the global constructors don't run, so I placement new them here */
new (&gModule) CRShellModule;
new (&gWinModule) CAtlWinModule;
@ -58,3 +132,97 @@ STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
}
return TRUE;
}
HRESULT
WINAPI
DllCanUnloadNow(void)
{
gModule.DllCanUnloadNow();
return S_FALSE;
}
STDAPI
DllRegisterServer(void)
{
RegisterComponent(CLSID_StartMenu, L"Shell Start Menu");
RegisterComponent(CLSID_MenuDeskBar, L"Shell Menu Desk Bar");
RegisterComponent(CLSID_MenuBand, L"Shell Menu Band");
RegisterComponent(CLSID_MenuBandSite, L"Shell Menu Band Site");
RegisterComponent(CLSID_MergedFolder, L"Merged Shell Folder");
return S_OK;
}
STDAPI
DllUnregisterServer(void)
{
UnregisterComponent(CLSID_StartMenu);
UnregisterComponent(CLSID_MenuDeskBar);
UnregisterComponent(CLSID_MenuBand);
UnregisterComponent(CLSID_MenuBandSite);
UnregisterComponent(CLSID_MergedFolder);
return S_OK;
}
class CRShellClassFactory :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IClassFactory
{
private:
CLSID m_Clsid;
public:
CRShellClassFactory() {}
virtual ~CRShellClassFactory() {}
HRESULT Initialize(REFGUID clsid)
{
m_Clsid = clsid;
return S_OK;
}
/* IClassFactory */
virtual HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
{
*ppvObject = NULL;
if (IsEqualCLSID(m_Clsid, CLSID_StartMenu))
return CStartMenu_Constructor(riid, ppvObject);
if (IsEqualCLSID(m_Clsid, CLSID_MenuDeskBar))
return CMenuDeskBar_Constructor(riid, ppvObject);
if (IsEqualCLSID(m_Clsid, CLSID_MenuBand))
return CMenuBand_Constructor(riid, ppvObject);
if (IsEqualCLSID(m_Clsid, CLSID_MenuBandSite))
return CMenuSite_Constructor(riid, ppvObject);
if (IsEqualCLSID(m_Clsid, CLSID_MergedFolder))
return CMergedFolder_Constructor(riid, ppvObject);
return E_NOINTERFACE;
}
virtual HRESULT WINAPI LockServer(BOOL fLock)
{
return E_NOTIMPL;
}
BEGIN_COM_MAP(CRShellClassFactory)
COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
END_COM_MAP()
};
STDAPI
DllGetClassObject(
REFCLSID rclsid,
REFIID riid,
LPVOID *ppv)
{
if (!ppv)
return E_INVALIDARG;
*ppv = NULL;
return ShellObjectCreatorInit<CRShellClassFactory>(rclsid, riid, ppv);
}

View file

@ -1,3 +1,7 @@
@ stdcall DllCanUnloadNow()
@ stdcall DllGetClassObject(ptr ptr ptr)
@ stdcall DllRegisterServer()
@ stdcall DllUnregisterServer()
@ stdcall CStartMenu_Constructor(ptr ptr)
@ stdcall CMenuDeskBar_Constructor(ptr ptr);
@ stdcall CMenuSite_Constructor(ptr ptr);