[SHELL32]
[reactos.git] / 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 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_AutoComplete, CAutoComplete)
164 OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder)
165 OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder)
166 OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder)
167 OBJECT_ENTRY(CLSID_Printers, CPrinterFolder)
168 OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder)
169 OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin)
170 OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
171 OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
172 OBJECT_ENTRY(CLSID_StartMenu, CStartMenu)
173 OBJECT_ENTRY(CLSID_MenuBandSite, CMenuBandSite)
174 OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
175 OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar)
176 OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
177 END_OBJECT_MAP()
178
179 CShell32Module gModule;
180
181
182 /***********************************************************************
183 * DllGetVersion [SHELL32.@]
184 *
185 * Retrieves version information of the 'SHELL32.DLL'
186 *
187 * PARAMS
188 * pdvi [O] pointer to version information structure.
189 *
190 * RETURNS
191 * Success: S_OK
192 * Failure: E_INVALIDARG
193 *
194 * NOTES
195 * Returns version of a shell32.dll from IE4.01 SP1.
196 */
197
198 STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
199 {
200 /* FIXME: shouldn't these values come from the version resource? */
201 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
202 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
203 {
204 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
205 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
206 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
207 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
208 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
209 {
210 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
211
212 pdvi2->dwFlags = 0;
213 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
214 WINE_FILEVERSION_MINOR,
215 WINE_FILEVERSION_BUILD,
216 WINE_FILEVERSION_PLATFORMID);
217 }
218 TRACE("%u.%u.%u.%u\n",
219 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
220 pdvi->dwBuildNumber, pdvi->dwPlatformID);
221 return S_OK;
222 }
223 else
224 {
225 WARN("wrong DLLVERSIONINFO size from app\n");
226 return E_INVALIDARG;
227 }
228 }
229
230 /*************************************************************************
231 * global variables of the shell32.dll
232 * all are once per process
233 *
234 */
235 HINSTANCE shell32_hInstance;
236 HIMAGELIST ShellSmallIconList = 0;
237 HIMAGELIST ShellBigIconList = 0;
238
239 void *operator new (size_t, void *buf)
240 {
241 return buf;
242 }
243
244 /*************************************************************************
245 * SHELL32 DllMain
246 *
247 * NOTES
248 * calling oleinitialize here breaks sone apps.
249 */
250 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
251 {
252 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad);
253 if (dwReason == DLL_PROCESS_ATTACH)
254 {
255 /* HACK - the global constructors don't run, so I placement new them here */
256 new (&gModule) CShell32Module;
257 new (&_AtlWinModule) CAtlWinModule;
258 new (&_AtlBaseModule) CAtlBaseModule;
259 new (&_AtlComModule) CAtlComModule;
260
261 shell32_hInstance = hInstance;
262 gModule.Init(ObjectMap, hInstance, NULL);
263
264 DisableThreadLibraryCalls (hInstance);
265
266 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
267 GetModuleFileNameW(hInstance, swShell32Name, MAX_PATH);
268 swShell32Name[MAX_PATH - 1] = '\0';
269
270 /* Initialize comctl32 */
271 INITCOMMONCONTROLSEX InitCtrls;
272 InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
273 InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
274 InitCommonControlsEx(&InitCtrls);
275
276 SIC_Initialize();
277 InitChangeNotifications();
278 InitIconOverlays();
279 }
280 else if (dwReason == DLL_PROCESS_DETACH)
281 {
282 shell32_hInstance = NULL;
283 SIC_Destroy();
284 FreeChangeNotifications();
285 gModule.Term();
286 }
287 return TRUE;
288 }
289
290 /***********************************************************************
291 * DllCanUnloadNow (SHELL32.@)
292 */
293 STDAPI DllCanUnloadNow()
294 {
295 return gModule.DllCanUnloadNow();
296 }
297
298 /*************************************************************************
299 * DllGetClassObject [SHELL32.@]
300 * SHDllGetClassObject [SHELL32.128]
301 */
302 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
303 {
304 HRESULT hResult;
305
306 TRACE("CLSID:%s,IID:%s\n", shdebugstr_guid(&rclsid), shdebugstr_guid(&riid));
307
308 hResult = gModule.DllGetClassObject(rclsid, riid, ppv);
309 TRACE("-- pointer to class factory: %p\n", *ppv);
310 return hResult;
311 }
312
313 /***********************************************************************
314 * DllRegisterServer (SHELL32.@)
315 */
316 STDAPI DllRegisterServer()
317 {
318 HRESULT hr;
319
320 hr = gModule.DllRegisterServer(FALSE);
321 if (FAILED(hr))
322 return hr;
323
324 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL);
325 if (FAILED(hr))
326 return hr;
327
328 hr = SHELL_RegisterShellFolders();
329 if (FAILED(hr))
330 return hr;
331
332 return S_OK;
333 }
334
335 /***********************************************************************
336 * DllUnregisterServer (SHELL32.@)
337 */
338 STDAPI DllUnregisterServer()
339 {
340 HRESULT hr;
341
342 hr = gModule.DllUnregisterServer(FALSE);
343 if (FAILED(hr))
344 return hr;
345
346 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL);
347 if (FAILED(hr))
348 return hr;
349
350 return S_OK;
351 }
352
353 /*************************************************************************
354 * DllInstall [SHELL32.@]
355 *
356 * PARAMETERS
357 *
358 * BOOL bInstall - TRUE for install, FALSE for uninstall
359 * LPCWSTR pszCmdLine - command line (unused by shell32?)
360 */
361
362 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
363 {
364 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
365 return S_OK; /* indicate success */
366 }