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
WinList_Init(void)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
_RegSetStringValueW(HKEY hKey,LPCWSTR lpValueName,LPCWSTR lpStringData)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
RegisterComponent(REFGUID clsid,LPCWSTR szDisplayName)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
UnregisterComponent(REFGUID clsid)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
DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID fImpLoad)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
DllCanUnloadNow(void)160 DllCanUnloadNow(void)
161 {
162 gModule.DllCanUnloadNow();
163 return S_FALSE;
164 }
165
166 STDAPI
DllRegisterServer(void)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
DllUnregisterServer(void)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:
CRShellClassFactory()206 CRShellClassFactory() {}
~CRShellClassFactory()207 virtual ~CRShellClassFactory() {}
208
Initialize(REFGUID clsid)209 HRESULT Initialize(REFGUID clsid)
210 {
211 m_Clsid = clsid;
212 return S_OK;
213 }
214
215 /* IClassFactory */
CreateInstance(LPUNKNOWN pUnkOuter,REFIID riid,LPVOID * ppvObject)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
LockServer(BOOL fLock)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
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)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
ShowFolderOptionsDialog(UINT Page,BOOL Async)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