[PRINTING]
[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, CShellDispatch)
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_ShellFldSetExt, CFolderOptions)
208 OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin)
209 OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
210 OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
211 OBJECT_ENTRY(CLSID_StartMenu, CStartMenuDummy)
212 OBJECT_ENTRY(CLSID_MenuBandSite, CMenuSite)
213 OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
214 OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar)
215 OBJECT_ENTRY(CLSID_MergedFolder, CMergedFolder)
216 OBJECT_ENTRY(CLSID_RebarBandSite, CBandSite)
217 OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
218 OBJECT_ENTRY(CLSID_QueryAssociations, CQueryAssociations)
219 END_OBJECT_MAP()
220
221 CShell32Module gModule;
222
223
224 /***********************************************************************
225 * DllGetVersion [SHELL32.@]
226 *
227 * Retrieves version information of the 'SHELL32.DLL'
228 *
229 * PARAMS
230 * pdvi [O] pointer to version information structure.
231 *
232 * RETURNS
233 * Success: S_OK
234 * Failure: E_INVALIDARG
235 *
236 * NOTES
237 * Returns version of a shell32.dll from IE4.01 SP1.
238 */
239
240 STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
241 {
242 /* FIXME: shouldn't these values come from the version resource? */
243 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
244 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
245 {
246 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
247 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
248 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
249 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
250 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
251 {
252 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
253
254 pdvi2->dwFlags = 0;
255 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
256 WINE_FILEVERSION_MINOR,
257 WINE_FILEVERSION_BUILD,
258 WINE_FILEVERSION_PLATFORMID);
259 }
260 TRACE("%u.%u.%u.%u\n",
261 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
262 pdvi->dwBuildNumber, pdvi->dwPlatformID);
263 return S_OK;
264 }
265 else
266 {
267 WARN("wrong DLLVERSIONINFO size from app\n");
268 return E_INVALIDARG;
269 }
270 }
271
272 /*************************************************************************
273 * global variables of the shell32.dll
274 * all are once per process
275 *
276 */
277 HINSTANCE shell32_hInstance;
278
279 void *operator new (size_t, void *buf)
280 {
281 return buf;
282 }
283
284 /*************************************************************************
285 * SHELL32 DllMain
286 *
287 * NOTES
288 * calling oleinitialize here breaks sone apps.
289 */
290 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
291 {
292 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad);
293 if (dwReason == DLL_PROCESS_ATTACH)
294 {
295 shell32_hInstance = hInstance;
296 gModule.Init(ObjectMap, hInstance, &LIBID_Shell32);
297
298 DisableThreadLibraryCalls (hInstance);
299
300 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
301 GetModuleFileNameW(hInstance, swShell32Name, MAX_PATH);
302 swShell32Name[MAX_PATH - 1] = '\0';
303
304 /* Initialize comctl32 */
305 INITCOMMONCONTROLSEX InitCtrls;
306 InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
307 InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
308 InitCommonControlsEx(&InitCtrls);
309
310 SIC_Initialize();
311 InitChangeNotifications();
312 InitIconOverlays();
313 }
314 else if (dwReason == DLL_PROCESS_DETACH)
315 {
316 shell32_hInstance = NULL;
317 SIC_Destroy();
318 FreeChangeNotifications();
319 gModule.Term();
320 }
321 return TRUE;
322 }
323
324 /***********************************************************************
325 * DllCanUnloadNow (SHELL32.@)
326 */
327 STDAPI DllCanUnloadNow()
328 {
329 return gModule.DllCanUnloadNow();
330 }
331
332 /*************************************************************************
333 * DllGetClassObject [SHELL32.@]
334 * SHDllGetClassObject [SHELL32.128]
335 */
336 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
337 {
338 HRESULT hResult;
339
340 TRACE("CLSID:%s,IID:%s\n", shdebugstr_guid(&rclsid), shdebugstr_guid(&riid));
341
342 hResult = gModule.DllGetClassObject(rclsid, riid, ppv);
343 TRACE("-- pointer to class factory: %p\n", *ppv);
344 return hResult;
345 }
346
347 /***********************************************************************
348 * DllRegisterServer (SHELL32.@)
349 */
350 STDAPI DllRegisterServer()
351 {
352 HRESULT hr;
353
354 hr = gModule.DllRegisterServer(TRUE);
355 if (FAILED(hr))
356 return hr;
357
358 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL);
359 if (FAILED(hr))
360 return hr;
361
362 hr = SHELL_RegisterShellFolders();
363 if (FAILED(hr))
364 return hr;
365
366 return S_OK;
367 }
368
369 /***********************************************************************
370 * DllUnregisterServer (SHELL32.@)
371 */
372 STDAPI DllUnregisterServer()
373 {
374 HRESULT hr;
375
376 hr = gModule.DllUnregisterServer(TRUE);
377 if (FAILED(hr))
378 return hr;
379
380 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL);
381 if (FAILED(hr))
382 return hr;
383
384 return S_OK;
385 }
386
387 /*************************************************************************
388 * DllInstall [SHELL32.@]
389 *
390 * PARAMETERS
391 *
392 * BOOL bInstall - TRUE for install, FALSE for uninstall
393 * LPCWSTR pszCmdLine - command line (unused by shell32?)
394 */
395
396 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
397 {
398 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
399 return S_OK; /* indicate success */
400 }