Revert r66580 and r66579.
[reactos.git] / reactos / base / shell / shell32 / shell32.cpp
1 /*
2 * Shell basics
3 *
4 * Copyright 1998 Marcus Meissner
5 * Copyright 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "precomp.h"
23
24 #include "shell32_version.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(shell);
27
28 /**************************************************************************
29 * Default ClassFactory types
30 */
31 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
32 HRESULT IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInst, IClassFactory **theFactory);
33
34
35 /**************************************************************************
36 * Default ClassFactory Implementation
37 *
38 * SHCreateDefClassObject
39 *
40 * NOTES
41 * Helper function for dlls without their own classfactory.
42 * A generic classfactory is returned.
43 * When the CreateInstance of the cf is called the callback is executed.
44 */
45
46 class IDefClFImpl :
47 public CComObjectRootEx<CComMultiThreadModelNoCS>,
48 public IClassFactory
49 {
50 private:
51 CLSID *rclsid;
52 LPFNCREATEINSTANCE lpfnCI;
53 const IID *riidInst;
54 LONG *pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
55 public:
56 IDefClFImpl();
57 HRESULT Initialize(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInstx);
58
59 // IClassFactory
60 virtual HRESULT WINAPI CreateInstance(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppvObject);
61 virtual HRESULT WINAPI LockServer(BOOL fLock);
62
63 BEGIN_COM_MAP(IDefClFImpl)
64 COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
65 END_COM_MAP()
66 };
67
68 IDefClFImpl::IDefClFImpl()
69 {
70 lpfnCI = NULL;
71 riidInst = NULL;
72 pcRefDll = NULL;
73 rclsid = NULL;
74 }
75
76 HRESULT IDefClFImpl::Initialize(LPFNCREATEINSTANCE lpfnCIx, PLONG pcRefDllx, const IID *riidInstx)
77 {
78 lpfnCI = lpfnCIx;
79 riidInst = riidInstx;
80 pcRefDll = pcRefDllx;
81
82 if (pcRefDll)
83 InterlockedIncrement(pcRefDll);
84
85 TRACE("(%p)%s\n", this, shdebugstr_guid(riidInst));
86 return S_OK;
87 }
88
89 /******************************************************************************
90 * IDefClF_fnCreateInstance
91 */
92 HRESULT WINAPI IDefClFImpl::CreateInstance(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppvObject)
93 {
94 TRACE("%p->(%p,%s,%p)\n", this, pUnkOuter, shdebugstr_guid(&riid), ppvObject);
95
96 *ppvObject = NULL;
97
98 if (riidInst == NULL || IsEqualCLSID(riid, *riidInst) || IsEqualCLSID(riid, IID_IUnknown))
99 {
100 return lpfnCI(pUnkOuter, riid, ppvObject);
101 }
102
103 ERR("unknown IID requested %s\n", shdebugstr_guid(&riid));
104 return E_NOINTERFACE;
105 }
106
107 /******************************************************************************
108 * IDefClF_fnLockServer
109 */
110 HRESULT WINAPI IDefClFImpl::LockServer(BOOL fLock)
111 {
112 TRACE("%p->(0x%x), not implemented\n", this, fLock);
113 return E_NOTIMPL;
114 }
115
116 /**************************************************************************
117 * IDefClF_fnConstructor
118 */
119
120 HRESULT IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInst, IClassFactory **theFactory)
121 {
122 return ShellObjectCreatorInit<IDefClFImpl>(lpfnCI, pcRefDll, riidInst, IID_IClassFactory, theFactory);
123 }
124
125 /******************************************************************************
126 * SHCreateDefClassObject [SHELL32.70]
127 */
128 HRESULT WINAPI SHCreateDefClassObject(
129 REFIID riid,
130 LPVOID* ppv,
131 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
132 LPDWORD pcRefDll, /* [in/out] ref count of the dll */
133 REFIID riidInst) /* [in] optional interface to the instance */
134 {
135 IClassFactory *pcf;
136 HRESULT hResult;
137
138 TRACE("%s %p %p %p %s\n", shdebugstr_guid(&riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(&riidInst));
139
140 if (!IsEqualCLSID(riid, IID_IClassFactory))
141 return E_NOINTERFACE;
142 hResult = IDefClF_fnConstructor(lpfnCI, (PLONG)pcRefDll, &riidInst, &pcf);
143 if (FAILED(hResult))
144 return hResult;
145 *ppv = pcf;
146 return S_OK;
147 }
148
149 class CShell32Module : public CComModule
150 {
151 public:
152 };
153
154
155 BEGIN_OBJECT_MAP(ObjectMap)
156 OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder)
157 OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder)
158 OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder)
159 OBJECT_ENTRY(CLSID_ShellItem, CShellItem)
160 OBJECT_ENTRY(CLSID_ShellLink, CShellLink)
161 OBJECT_ENTRY(CLSID_DragDropHelper, CDropTargetHelper)
162 OBJECT_ENTRY(CLSID_ControlPanel, CControlPanelFolder)
163 OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder)
164 OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder)
165 OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder)
166 OBJECT_ENTRY(CLSID_Printers, CPrinterFolder)
167 OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder)
168 OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin)
169 OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
170 OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
171 OBJECT_ENTRY(CLSID_StartMenu, CStartMenu)
172 OBJECT_ENTRY(CLSID_MenuBandSite, CMenuBandSite)
173 OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
174 OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar)
175 OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
176 END_OBJECT_MAP()
177
178 CShell32Module gModule;
179
180
181 /***********************************************************************
182 * DllGetVersion [SHELL32.@]
183 *
184 * Retrieves version information of the 'SHELL32.DLL'
185 *
186 * PARAMS
187 * pdvi [O] pointer to version information structure.
188 *
189 * RETURNS
190 * Success: S_OK
191 * Failure: E_INVALIDARG
192 *
193 * NOTES
194 * Returns version of a shell32.dll from IE4.01 SP1.
195 */
196
197 STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
198 {
199 /* FIXME: shouldn't these values come from the version resource? */
200 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
201 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
202 {
203 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
204 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
205 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
206 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
207 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
208 {
209 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
210
211 pdvi2->dwFlags = 0;
212 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
213 WINE_FILEVERSION_MINOR,
214 WINE_FILEVERSION_BUILD,
215 WINE_FILEVERSION_PLATFORMID);
216 }
217 TRACE("%u.%u.%u.%u\n",
218 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
219 pdvi->dwBuildNumber, pdvi->dwPlatformID);
220 return S_OK;
221 }
222 else
223 {
224 WARN("wrong DLLVERSIONINFO size from app\n");
225 return E_INVALIDARG;
226 }
227 }
228
229 /*************************************************************************
230 * global variables of the shell32.dll
231 * all are once per process
232 *
233 */
234 HINSTANCE shell32_hInstance;
235
236 void *operator new (size_t, void *buf)
237 {
238 return buf;
239 }
240
241 /*************************************************************************
242 * SHELL32 DllMain
243 *
244 * NOTES
245 * calling oleinitialize here breaks sone apps.
246 */
247 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
248 {
249 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad);
250 if (dwReason == DLL_PROCESS_ATTACH)
251 {
252 /* HACK - the global constructors don't run, so I placement new them here */
253 new (&gModule) CShell32Module;
254 new (&_AtlWinModule) CAtlWinModule;
255 new (&_AtlBaseModule) CAtlBaseModule;
256 new (&_AtlComModule) CAtlComModule;
257
258 shell32_hInstance = hInstance;
259 gModule.Init(ObjectMap, hInstance, NULL);
260
261 DisableThreadLibraryCalls (hInstance);
262
263 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
264 GetModuleFileNameW(hInstance, swShell32Name, MAX_PATH);
265 swShell32Name[MAX_PATH - 1] = '\0';
266
267 /* Initialize comctl32 */
268 INITCOMMONCONTROLSEX InitCtrls;
269 InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
270 InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
271 InitCommonControlsEx(&InitCtrls);
272
273 SIC_Initialize();
274 InitChangeNotifications();
275 InitIconOverlays();
276 }
277 else if (dwReason == DLL_PROCESS_DETACH)
278 {
279 shell32_hInstance = NULL;
280 SIC_Destroy();
281 FreeChangeNotifications();
282 gModule.Term();
283 }
284 return TRUE;
285 }
286
287 /***********************************************************************
288 * DllCanUnloadNow (SHELL32.@)
289 */
290 STDAPI DllCanUnloadNow()
291 {
292 return gModule.DllCanUnloadNow();
293 }
294
295 /*************************************************************************
296 * DllGetClassObject [SHELL32.@]
297 * SHDllGetClassObject [SHELL32.128]
298 */
299 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
300 {
301 HRESULT hResult;
302
303 TRACE("CLSID:%s,IID:%s\n", shdebugstr_guid(&rclsid), shdebugstr_guid(&riid));
304
305 hResult = gModule.DllGetClassObject(rclsid, riid, ppv);
306 TRACE("-- pointer to class factory: %p\n", *ppv);
307 return hResult;
308 }
309
310 /***********************************************************************
311 * DllRegisterServer (SHELL32.@)
312 */
313 STDAPI DllRegisterServer()
314 {
315 HRESULT hr;
316
317 hr = gModule.DllRegisterServer(FALSE);
318 if (FAILED(hr))
319 return hr;
320
321 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL);
322 if (FAILED(hr))
323 return hr;
324
325 hr = SHELL_RegisterShellFolders();
326 if (FAILED(hr))
327 return hr;
328
329 return S_OK;
330 }
331
332 /***********************************************************************
333 * DllUnregisterServer (SHELL32.@)
334 */
335 STDAPI DllUnregisterServer()
336 {
337 HRESULT hr;
338
339 hr = gModule.DllUnregisterServer(FALSE);
340 if (FAILED(hr))
341 return hr;
342
343 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL);
344 if (FAILED(hr))
345 return hr;
346
347 return S_OK;
348 }
349
350 /*************************************************************************
351 * DllInstall [SHELL32.@]
352 *
353 * PARAMETERS
354 *
355 * BOOL bInstall - TRUE for install, FALSE for uninstall
356 * LPCWSTR pszCmdLine - command line (unused by shell32?)
357 */
358
359 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
360 {
361 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
362 return S_OK; /* indicate success */
363 }