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 44 extern "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 55 DWORD WINAPI WinList_Init(void) 56 { 57 /* do something here (perhaps we may want to add our own implementation fo win8) */ 58 return 0; 59 } 60 61 class CRShellModule : public CComModule 62 { 63 public: 64 }; 65 66 CRShellModule gModule; 67 CAtlWinModule gWinModule; 68 69 HINSTANCE shell32_hInstance = NULL; 70 71 static LSTATUS inline _RegSetStringValueW(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpStringData) 72 { 73 DWORD dwStringDataLen = lstrlenW(lpStringData); 74 75 return RegSetValueExW(hKey, lpValueName, 0, REG_SZ, (BYTE *) lpStringData, 2 * (dwStringDataLen + 1)); 76 } 77 78 static HRESULT RegisterComponent(REFGUID clsid, LPCWSTR szDisplayName) 79 { 80 WCHAR szFilename[MAX_PATH]; 81 WCHAR szClsid[MAX_PATH]; 82 WCHAR szRoot[MAX_PATH]; 83 84 if (!StringFromGUID2(clsid, szClsid, _countof(szClsid))) 85 return E_FAIL; 86 87 if (!GetModuleFileNameW(shell32_hInstance, szFilename, _countof(szFilename))) 88 return E_FAIL; 89 90 HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid); 91 if (FAILED(hr)) 92 return hr; 93 94 DWORD dwDisposition; 95 HKEY hkRoot; 96 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, NULL, 0, KEY_WRITE, 0, &hkRoot, &dwDisposition) != 0) 97 return E_FAIL; 98 99 HKEY hkServer; 100 101 _RegSetStringValueW(hkRoot, NULL, szDisplayName); 102 103 if (RegCreateKeyExW(hkRoot, L"InprocServer32", 0, NULL, 0, KEY_SET_VALUE, 0, &hkServer, &dwDisposition) != 0) 104 { 105 RegCloseKey(hkRoot); 106 return E_FAIL; 107 } 108 109 _RegSetStringValueW(hkServer, NULL, szFilename); 110 _RegSetStringValueW(hkServer, L"ThreadingModel", L"Both"); 111 112 RegCloseKey(hkServer); 113 RegCloseKey(hkRoot); 114 return S_OK; 115 } 116 117 static HRESULT UnregisterComponent(REFGUID clsid) 118 { 119 WCHAR szClsid[MAX_PATH]; 120 WCHAR szRoot[MAX_PATH]; 121 HKEY hkRoot; 122 123 if (!StringFromGUID2(clsid, szClsid, _countof(szClsid))) 124 return E_FAIL; 125 126 HRESULT hr = StringCchPrintfW(szRoot, 0x104u, L"CLSID\\%s", szClsid); 127 if (FAILED(hr)) 128 return hr; 129 130 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szRoot, 0, KEY_WRITE, &hkRoot) != 0) 131 return E_FAIL; 132 133 RegDeleteKeyW(hkRoot, L"InprocServer32"); 134 RegCloseKey(hkRoot); 135 136 RegDeleteKeyW(HKEY_CLASSES_ROOT, szRoot); 137 138 return S_OK; 139 } 140 141 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad) 142 { 143 if (dwReason == DLL_PROCESS_ATTACH) 144 { 145 shell32_hInstance = hInstance; 146 147 gModule.Init(NULL, hInstance, NULL); 148 DisableThreadLibraryCalls(hInstance); 149 } 150 else if (dwReason == DLL_PROCESS_DETACH) 151 { 152 shell32_hInstance = NULL; 153 gModule.Term(); 154 } 155 return TRUE; 156 } 157 158 HRESULT 159 WINAPI 160 DllCanUnloadNow(void) 161 { 162 gModule.DllCanUnloadNow(); 163 return S_FALSE; 164 } 165 166 STDAPI 167 DllRegisterServer(void) 168 { 169 #if 0 170 RegisterComponent(CLSID_StartMenu, L"Shell Start Menu"); 171 RegisterComponent(CLSID_MenuDeskBar, L"Shell Menu Desk Bar"); 172 RegisterComponent(CLSID_MenuBand, L"Shell Menu Band"); 173 RegisterComponent(CLSID_MenuBandSite, L"Shell Menu Band Site"); 174 RegisterComponent(CLSID_MergedFolder, L"Merged Shell Folder"); 175 RegisterComponent(CLSID_RebarBandSite, L"Shell Rebar Band Site"); 176 #endif 177 RegisterComponent(CLSID_QuickLaunchBand, L"Quick Launch"); 178 RegisterComCat(); 179 return S_OK; 180 } 181 182 STDAPI 183 DllUnregisterServer(void) 184 { 185 #if 0 186 UnregisterComponent(CLSID_StartMenu); 187 UnregisterComponent(CLSID_MenuDeskBar); 188 UnregisterComponent(CLSID_MenuBand); 189 UnregisterComponent(CLSID_MenuBandSite); 190 UnregisterComponent(CLSID_MergedFolder); 191 UnregisterComponent(CLSID_RebarBandSite); 192 #endif 193 UnregisterComponent(CLSID_QuickLaunchBand); 194 UnregisterComCat(); 195 return S_OK; 196 } 197 198 class CRShellClassFactory : 199 public CComObjectRootEx<CComMultiThreadModelNoCS>, 200 public IClassFactory 201 { 202 private: 203 CLSID m_Clsid; 204 205 public: 206 CRShellClassFactory() {} 207 virtual ~CRShellClassFactory() {} 208 209 HRESULT Initialize(REFGUID clsid) 210 { 211 m_Clsid = clsid; 212 return S_OK; 213 } 214 215 /* IClassFactory */ 216 virtual HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject) 217 { 218 *ppvObject = NULL; 219 220 if (IsEqualCLSID(m_Clsid, CLSID_StartMenu)) 221 return RSHELL_CStartMenu_CreateInstance(riid, ppvObject); 222 223 if (IsEqualCLSID(m_Clsid, CLSID_MenuDeskBar)) 224 return RSHELL_CMenuDeskBar_CreateInstance(riid, ppvObject); 225 226 if (IsEqualCLSID(m_Clsid, CLSID_MenuBand)) 227 return RSHELL_CMenuBand_CreateInstance(riid, ppvObject); 228 229 if (IsEqualCLSID(m_Clsid, CLSID_MenuBandSite)) 230 return RSHELL_CMenuSite_CreateInstance(riid, ppvObject); 231 232 if (IsEqualCLSID(m_Clsid, CLSID_MergedFolder)) 233 return RSHELL_CMergedFolder_CreateInstance(riid, ppvObject); 234 235 if (IsEqualCLSID(m_Clsid, CLSID_QuickLaunchBand)) 236 return ShellObjectCreator<CQuickLaunchBand>(riid, ppvObject); 237 238 return E_NOINTERFACE; 239 } 240 241 virtual HRESULT WINAPI LockServer(BOOL fLock) 242 { 243 return E_NOTIMPL; 244 } 245 246 BEGIN_COM_MAP(CRShellClassFactory) 247 COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory) 248 END_COM_MAP() 249 }; 250 251 STDAPI 252 DllGetClassObject( 253 REFCLSID rclsid, 254 REFIID riid, 255 LPVOID *ppv) 256 { 257 if (!ppv) 258 return E_INVALIDARG; 259 260 *ppv = NULL; 261 262 return ShellObjectCreatorInit<CRShellClassFactory>(rclsid, riid, ppv); 263 } 264 265 VOID WINAPI ShowFolderOptionsDialog(UINT Page, BOOL Async) 266 { 267 char buf[MAX_PATH]; 268 wsprintfA(buf, "rundll32.exe shell32.dll,Options_RunDLL %u", Page); 269 WinExec(buf, SW_SHOW); 270 } 271