Reactos
at master 264 lines 6.7 kB view raw
1/* 2 * PROJECT: ReactOS shell extensions 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) 5 * COPYRIGHT: Copyright 2014 Giannis Adamopoulos 6 */ 7 8 9#include <stdio.h> 10#include <tchar.h> 11 12#define WIN32_NO_STATUS 13#define _INC_WINDOWS 14#define COM_NO_WINDOWS_H 15 16#define COBJMACROS 17 18#include <windef.h> 19#include <winbase.h> 20#include <winreg.h> 21#include <wingdi.h> 22#include <winnls.h> 23#include <wincon.h> 24#include <shellapi.h> 25#include <shlobj.h> 26#include <shlobj_undoc.h> 27#include <shlwapi.h> 28#include <shlguid_undoc.h> 29#include <uxtheme.h> 30#include <strsafe.h> 31 32#include <atlbase.h> 33#include <atlcom.h> 34#include <atlwin.h> 35#include <undocshell.h> 36#include <undocuser.h> 37 38#include <shellutils.h> 39 40#include <CQuickLaunchBand.h> 41 42#include <wine/debug.h> 43 44extern "C" 45{ 46 extern HINSTANCE shell32_hInstance; 47 48 HRESULT WINAPI RSHELL_CStartMenu_CreateInstance(REFIID riid, void **ppv); 49 HRESULT WINAPI RSHELL_CMenuDeskBar_CreateInstance(REFIID riid, LPVOID *ppv); 50 HRESULT WINAPI RSHELL_CMenuSite_CreateInstance(REFIID riid, LPVOID *ppv); 51 HRESULT WINAPI RSHELL_CMenuBand_CreateInstance(REFIID riid, LPVOID *ppv); 52 HRESULT WINAPI RSHELL_CMergedFolder_CreateInstance(REFIID riid, LPVOID *ppv); 53} 54 55class CRShellModule : public CComModule 56{ 57public: 58}; 59 60CRShellModule gModule; 61CAtlWinModule gWinModule; 62 63HINSTANCE shell32_hInstance = NULL; 64 65static LSTATUS inline _RegSetStringValueW(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpStringData) 66{ 67 DWORD dwStringDataLen = lstrlenW(lpStringData); 68 69 return RegSetValueExW(hKey, lpValueName, 0, REG_SZ, (BYTE *) lpStringData, 2 * (dwStringDataLen + 1)); 70} 71 72static HRESULT RegisterComponent(REFGUID clsid, LPCWSTR szDisplayName) 73{ 74 WCHAR szFilename[MAX_PATH]; 75 WCHAR szClsid[MAX_PATH]; 76 WCHAR szRoot[MAX_PATH]; 77 78 if (!StringFromGUID2(clsid, szClsid, _countof(szClsid))) 79 return E_FAIL; 80 81 if (!GetModuleFileNameW(shell32_hInstance, szFilename, _countof(szFilename))) 82 return E_FAIL; 83 84 HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid); 85 if (FAILED(hr)) 86 return hr; 87 88 DWORD dwDisposition; 89 HKEY hkRoot; 90 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, NULL, 0, KEY_WRITE, 0, &hkRoot, &dwDisposition) != 0) 91 return E_FAIL; 92 93 HKEY hkServer; 94 95 _RegSetStringValueW(hkRoot, NULL, szDisplayName); 96 97 if (RegCreateKeyExW(hkRoot, L"InprocServer32", 0, NULL, 0, KEY_SET_VALUE, 0, &hkServer, &dwDisposition) != 0) 98 { 99 RegCloseKey(hkRoot); 100 return E_FAIL; 101 } 102 103 _RegSetStringValueW(hkServer, NULL, szFilename); 104 _RegSetStringValueW(hkServer, L"ThreadingModel", L"Both"); 105 106 RegCloseKey(hkServer); 107 RegCloseKey(hkRoot); 108 return S_OK; 109} 110 111static HRESULT UnregisterComponent(REFGUID clsid) 112{ 113 WCHAR szClsid[MAX_PATH]; 114 WCHAR szRoot[MAX_PATH]; 115 HKEY hkRoot; 116 117 if (!StringFromGUID2(clsid, szClsid, _countof(szClsid))) 118 return E_FAIL; 119 120 HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid); 121 if (FAILED(hr)) 122 return hr; 123 124 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, KEY_WRITE, &hkRoot) != 0) 125 return E_FAIL; 126 127 RegDeleteKeyW(hkRoot, L"InprocServer32"); 128 RegCloseKey(hkRoot); 129 130 RegDeleteKeyW(HKEY_CLASSES_ROOT, szRoot); 131 132 return S_OK; 133} 134 135STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad) 136{ 137 if (dwReason == DLL_PROCESS_ATTACH) 138 { 139 shell32_hInstance = hInstance; 140 141 gModule.Init(NULL, hInstance, NULL); 142 DisableThreadLibraryCalls(hInstance); 143 } 144 else if (dwReason == DLL_PROCESS_DETACH) 145 { 146 shell32_hInstance = NULL; 147 gModule.Term(); 148 } 149 return TRUE; 150} 151 152HRESULT 153WINAPI 154DllCanUnloadNow(void) 155{ 156 gModule.DllCanUnloadNow(); 157 return S_FALSE; 158} 159 160STDAPI 161DllRegisterServer(void) 162{ 163#if 0 164 RegisterComponent(CLSID_StartMenu, L"Shell Start Menu"); 165 RegisterComponent(CLSID_MenuDeskBar, L"Shell Menu Desk Bar"); 166 RegisterComponent(CLSID_MenuBand, L"Shell Menu Band"); 167 RegisterComponent(CLSID_MenuBandSite, L"Shell Menu Band Site"); 168 RegisterComponent(CLSID_MergedFolder, L"Merged Shell Folder"); 169 RegisterComponent(CLSID_RebarBandSite, L"Shell Rebar Band Site"); 170#endif 171 RegisterComponent(CLSID_QuickLaunchBand, L"Quick Launch"); 172 RegisterComCat(); 173 return S_OK; 174} 175 176STDAPI 177DllUnregisterServer(void) 178{ 179#if 0 180 UnregisterComponent(CLSID_StartMenu); 181 UnregisterComponent(CLSID_MenuDeskBar); 182 UnregisterComponent(CLSID_MenuBand); 183 UnregisterComponent(CLSID_MenuBandSite); 184 UnregisterComponent(CLSID_MergedFolder); 185 UnregisterComponent(CLSID_RebarBandSite); 186#endif 187 UnregisterComponent(CLSID_QuickLaunchBand); 188 UnregisterComCat(); 189 return S_OK; 190} 191 192class CRShellClassFactory : 193 public CComObjectRootEx<CComMultiThreadModelNoCS>, 194 public IClassFactory 195{ 196private: 197 CLSID m_Clsid; 198 199public: 200 CRShellClassFactory() {} 201 virtual ~CRShellClassFactory() {} 202 203 HRESULT Initialize(REFGUID clsid) 204 { 205 m_Clsid = clsid; 206 return S_OK; 207 } 208 209 /* IClassFactory */ 210 virtual HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject) 211 { 212 *ppvObject = NULL; 213 214 if (IsEqualCLSID(m_Clsid, CLSID_StartMenu)) 215 return RSHELL_CStartMenu_CreateInstance(riid, ppvObject); 216 217 if (IsEqualCLSID(m_Clsid, CLSID_MenuDeskBar)) 218 return RSHELL_CMenuDeskBar_CreateInstance(riid, ppvObject); 219 220 if (IsEqualCLSID(m_Clsid, CLSID_MenuBand)) 221 return RSHELL_CMenuBand_CreateInstance(riid, ppvObject); 222 223 if (IsEqualCLSID(m_Clsid, CLSID_MenuBandSite)) 224 return RSHELL_CMenuSite_CreateInstance(riid, ppvObject); 225 226 if (IsEqualCLSID(m_Clsid, CLSID_MergedFolder)) 227 return RSHELL_CMergedFolder_CreateInstance(riid, ppvObject); 228 229 if (IsEqualCLSID(m_Clsid, CLSID_QuickLaunchBand)) 230 return ShellObjectCreator<CQuickLaunchBand>(riid, ppvObject); 231 232 return E_NOINTERFACE; 233 } 234 235 virtual HRESULT WINAPI LockServer(BOOL fLock) 236 { 237 return E_NOTIMPL; 238 } 239 240 BEGIN_COM_MAP(CRShellClassFactory) 241 COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory) 242 END_COM_MAP() 243}; 244 245STDAPI 246DllGetClassObject( 247 REFCLSID rclsid, 248 REFIID riid, 249 LPVOID *ppv) 250{ 251 if (!ppv) 252 return E_INVALIDARG; 253 254 *ppv = NULL; 255 256 return ShellObjectCreatorInit<CRShellClassFactory>(rclsid, riid, ppv); 257} 258 259VOID WINAPI ShowFolderOptionsDialog(UINT Page, BOOL Async) 260{ 261 char buf[MAX_PATH]; 262 wsprintfA(buf, "rundll32.exe shell32.dll,Options_RunDLL %u", Page); 263 WinExec(buf, SW_SHOW); 264}