From a620535b0f14e82f029ff7d7f66a2829f8efdfe8 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Sat, 20 Dec 2014 16:04:45 +0000 Subject: [PATCH] [RSHELL] * Make rshell.dll able to register its classes and support CoCreateInstance. svn path=/trunk/; revision=65757 --- reactos/base/shell/rshell/CMakeLists.txt | 1 + reactos/base/shell/rshell/misc.cpp | 168 +++++++++++++++++++++++ reactos/base/shell/rshell/rshell.spec | 4 + 3 files changed, 173 insertions(+) diff --git a/reactos/base/shell/rshell/CMakeLists.txt b/reactos/base/shell/rshell/CMakeLists.txt index 8dc681e63e1..cb54c196af0 100644 --- a/reactos/base/shell/rshell/CMakeLists.txt +++ b/reactos/base/shell/rshell/CMakeLists.txt @@ -31,6 +31,7 @@ target_link_libraries(rshell add_importlibs(rshell uxtheme shlwapi + advapi32 shell32 comctl32 gdi32 diff --git a/reactos/base/shell/rshell/misc.cpp b/reactos/base/shell/rshell/misc.cpp index 33bfac2c447..f2b835da2bb 100644 --- a/reactos/base/shell/rshell/misc.cpp +++ b/reactos/base/shell/rshell/misc.cpp @@ -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, + 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(rclsid, riid, ppv); +} diff --git a/reactos/base/shell/rshell/rshell.spec b/reactos/base/shell/rshell/rshell.spec index 09fbfdff1b0..f29d1e50e82 100644 --- a/reactos/base/shell/rshell/rshell.spec +++ b/reactos/base/shell/rshell/rshell.spec @@ -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);