/* * PROJECT: ReactOS shell extensions * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) * COPYRIGHT: Copyright 2014 Giannis Adamopoulos */ #include #include #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H #define COBJMACROS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { extern HINSTANCE shell32_hInstance; HRESULT WINAPI RSHELL_CStartMenu_CreateInstance(REFIID riid, void **ppv); HRESULT WINAPI RSHELL_CMenuDeskBar_CreateInstance(REFIID riid, LPVOID *ppv); HRESULT WINAPI RSHELL_CMenuSite_CreateInstance(REFIID riid, LPVOID *ppv); HRESULT WINAPI RSHELL_CMenuBand_CreateInstance(REFIID riid, LPVOID *ppv); HRESULT WINAPI RSHELL_CMergedFolder_CreateInstance(REFIID riid, LPVOID *ppv); } DWORD WINAPI WinList_Init(void) { /* do something here (perhaps we may want to add our own implementation fo win8) */ return 0; } class CRShellModule : public CComModule { public: }; CRShellModule gModule; CAtlWinModule gWinModule; HINSTANCE shell32_hInstance = NULL; 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(shell32_hInstance, 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) { shell32_hInstance = hInstance; gModule.Init(NULL, hInstance, NULL); DisableThreadLibraryCalls(hInstance); } else if (dwReason == DLL_PROCESS_DETACH) { shell32_hInstance = NULL; gModule.Term(); } return TRUE; } HRESULT WINAPI DllCanUnloadNow(void) { gModule.DllCanUnloadNow(); return S_FALSE; } STDAPI DllRegisterServer(void) { #if 0 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"); RegisterComponent(CLSID_RebarBandSite, L"Shell Rebar Band Site"); #endif RegisterComponent(CLSID_QuickLaunchBand, L"Quick Launch"); RegisterComCat(); return S_OK; } STDAPI DllUnregisterServer(void) { #if 0 UnregisterComponent(CLSID_StartMenu); UnregisterComponent(CLSID_MenuDeskBar); UnregisterComponent(CLSID_MenuBand); UnregisterComponent(CLSID_MenuBandSite); UnregisterComponent(CLSID_MergedFolder); UnregisterComponent(CLSID_RebarBandSite); #endif UnregisterComponent(CLSID_QuickLaunchBand); UnregisterComCat(); 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 RSHELL_CStartMenu_CreateInstance(riid, ppvObject); if (IsEqualCLSID(m_Clsid, CLSID_MenuDeskBar)) return RSHELL_CMenuDeskBar_CreateInstance(riid, ppvObject); if (IsEqualCLSID(m_Clsid, CLSID_MenuBand)) return RSHELL_CMenuBand_CreateInstance(riid, ppvObject); if (IsEqualCLSID(m_Clsid, CLSID_MenuBandSite)) return RSHELL_CMenuSite_CreateInstance(riid, ppvObject); if (IsEqualCLSID(m_Clsid, CLSID_MergedFolder)) return RSHELL_CMergedFolder_CreateInstance(riid, ppvObject); if (IsEqualCLSID(m_Clsid, CLSID_QuickLaunchBand)) return ShellObjectCreator(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); } VOID WINAPI ShowFolderOptionsDialog(UINT Page, BOOL Async) { char buf[MAX_PATH]; wsprintfA(buf, "rundll32.exe shell32.dll,Options_RunDLL %u", Page); WinExec(buf, SW_SHOW); }