xref: /reactos/base/shell/rshell/misc.cpp (revision 6f86c05c)
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