[SHELL32] Use the previously implemented Typelib registration from ATL to register...
[reactos.git] / reactos / dll / win32 / 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 /**************************************************************************
150 * CStartMenuDummy
151 */
152 class CStartMenuDummy :
153 public CComCoClass<CStartMenuDummy, &CLSID_StartMenu>,
154 public CComObjectRootEx<CComMultiThreadModelNoCS>
155 {
156 private:
157 CStartMenuDummy();
158 virtual ~CStartMenuDummy();
159
160 public:
161 DECLARE_REGISTRY_RESOURCEID(IDR_STARTMENU)
162
163 class _CreatorClass
164 {
165 public:
166 static STDMETHODIMP CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
167 {
168 if (ppv == NULL)
169 return E_POINTER;
170 *ppv = NULL;
171 if (pv != NULL)
172 return CLASS_E_NOAGGREGATION;
173 return CStartMenu_Constructor(riid, ppv);
174 }
175 };
176 };
177
178 /**************************************************************************
179 * CShell32Module
180 */
181 class CShell32Module : public CComModule
182 {
183 public:
184 void Term()
185 {
186 CComCreatorCentralInstance< ATL::CComObject< CDrivesFolder > >::Term();
187 CComCreatorCentralInstance< ATL::CComObject< CDesktopFolder > >::Term();
188 CComModule::Term();
189 }
190 };
191
192
193 BEGIN_OBJECT_MAP(ObjectMap)
194 OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder)
195 OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder)
196 OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder)
197 OBJECT_ENTRY(CLSID_ShellItem, CShellItem)
198 OBJECT_ENTRY(CLSID_ShellLink, CShellLink)
199 OBJECT_ENTRY(CLSID_Shell, CShell)
200 OBJECT_ENTRY(CLSID_DragDropHelper, CDropTargetHelper)
201 OBJECT_ENTRY(CLSID_ControlPanel, CControlPanelFolder)
202 OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder)
203 OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder)
204 OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder)
205 OBJECT_ENTRY(CLSID_Printers, CPrinterFolder)
206 OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder)
207 OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin)
208 OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
209 OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
210 OBJECT_ENTRY(CLSID_StartMenu, CStartMenuDummy)
211 OBJECT_ENTRY(CLSID_MenuBandSite, CMenuSite)
212 OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
213 OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar)
214 OBJECT_ENTRY(CLSID_MergedFolder, CMergedFolder)
215 OBJECT_ENTRY(CLSID_RebarBandSite, CBandSite)
216 OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
217 OBJECT_ENTRY(CLSID_QueryAssociations, CQueryAssociations)
218 END_OBJECT_MAP()
219
220 CShell32Module gModule;
221
222
223 /***********************************************************************
224 * DllGetVersion [SHELL32.@]
225 *
226 * Retrieves version information of the 'SHELL32.DLL'
227 *
228 * PARAMS
229 * pdvi [O] pointer to version information structure.
230 *
231 * RETURNS
232 * Success: S_OK
233 * Failure: E_INVALIDARG
234 *
235 * NOTES
236 * Returns version of a shell32.dll from IE4.01 SP1.
237 */
238
239 STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
240 {
241 /* FIXME: shouldn't these values come from the version resource? */
242 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
243 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
244 {
245 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
246 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
247 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
248 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
249 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
250 {
251 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
252
253 pdvi2->dwFlags = 0;
254 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
255 WINE_FILEVERSION_MINOR,
256 WINE_FILEVERSION_BUILD,
257 WINE_FILEVERSION_PLATFORMID);
258 }
259 TRACE("%u.%u.%u.%u\n",
260 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
261 pdvi->dwBuildNumber, pdvi->dwPlatformID);
262 return S_OK;
263 }
264 else
265 {
266 WARN("wrong DLLVERSIONINFO size from app\n");
267 return E_INVALIDARG;
268 }
269 }
270
271 /*************************************************************************
272 * global variables of the shell32.dll
273 * all are once per process
274 *
275 */
276 HINSTANCE shell32_hInstance;
277
278 void *operator new (size_t, void *buf)
279 {
280 return buf;
281 }
282
283 /*************************************************************************
284 * SHELL32 DllMain
285 *
286 * NOTES
287 * calling oleinitialize here breaks sone apps.
288 */
289 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
290 {
291 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad);
292 if (dwReason == DLL_PROCESS_ATTACH)
293 {
294 shell32_hInstance = hInstance;
295 gModule.Init(ObjectMap, hInstance, &LIBID_Shell32);
296
297 DisableThreadLibraryCalls (hInstance);
298
299 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
300 GetModuleFileNameW(hInstance, swShell32Name, MAX_PATH);
301 swShell32Name[MAX_PATH - 1] = '\0';
302
303 /* Initialize comctl32 */
304 INITCOMMONCONTROLSEX InitCtrls;
305 InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
306 InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
307 InitCommonControlsEx(&InitCtrls);
308
309 SIC_Initialize();
310 InitChangeNotifications();
311 InitIconOverlays();
312 }
313 else if (dwReason == DLL_PROCESS_DETACH)
314 {
315 shell32_hInstance = NULL;
316 SIC_Destroy();
317 FreeChangeNotifications();
318 gModule.Term();
319 }
320 return TRUE;
321 }
322
323 /***********************************************************************
324 * DllCanUnloadNow (SHELL32.@)
325 */
326 STDAPI DllCanUnloadNow()
327 {
328 return gModule.DllCanUnloadNow();
329 }
330
331 /*************************************************************************
332 * DllGetClassObject [SHELL32.@]
333 * SHDllGetClassObject [SHELL32.128]
334 */
335 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
336 {
337 HRESULT hResult;
338
339 TRACE("CLSID:%s,IID:%s\n", shdebugstr_guid(&rclsid), shdebugstr_guid(&riid));
340
341 hResult = gModule.DllGetClassObject(rclsid, riid, ppv);
342 TRACE("-- pointer to class factory: %p\n", *ppv);
343 return hResult;
344 }
345
346 /***********************************************************************
347 * DllRegisterServer (SHELL32.@)
348 */
349 STDAPI DllRegisterServer()
350 {
351 HRESULT hr;
352
353 hr = gModule.DllRegisterServer(TRUE);
354 if (FAILED(hr))
355 return hr;
356
357 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL);
358 if (FAILED(hr))
359 return hr;
360
361 hr = SHELL_RegisterShellFolders();
362 if (FAILED(hr))
363 return hr;
364
365 return S_OK;
366 }
367
368 /***********************************************************************
369 * DllUnregisterServer (SHELL32.@)
370 */
371 STDAPI DllUnregisterServer()
372 {
373 HRESULT hr;
374
375 hr = gModule.DllUnregisterServer(TRUE);
376 if (FAILED(hr))
377 return hr;
378
379 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL);
380 if (FAILED(hr))
381 return hr;
382
383 return S_OK;
384 }
385
386 /*************************************************************************
387 * DllInstall [SHELL32.@]
388 *
389 * PARAMETERS
390 *
391 * BOOL bInstall - TRUE for install, FALSE for uninstall
392 * LPCWSTR pszCmdLine - command line (unused by shell32?)
393 */
394
395 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
396 {
397 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
398 return S_OK; /* indicate success */
399 }