2e776297177adbaceb02f2c9d20b8615b5694ee6
[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 * Implemented
30 */
31 EXTERN_C LPWSTR
32 WINAPI
33 AddCommasW(DWORD lValue, LPWSTR lpNumber)
34 {
35 WCHAR szValue[MAX_PATH], szSeparator[8 + 1];
36 NUMBERFMTW numFormat;
37
38 GetLocaleInfoW(LOCALE_USER_DEFAULT,
39 LOCALE_STHOUSAND,
40 szSeparator,
41 _countof(szSeparator));
42
43 numFormat.NumDigits = 0;
44 numFormat.LeadingZero = 0;
45 numFormat.Grouping = 0; // FIXME! Use GetLocaleInfoW with LOCALE_SGROUPING and interpret the result.
46 numFormat.lpDecimalSep = szSeparator;
47 numFormat.lpThousandSep = szSeparator;
48 numFormat.NegativeOrder = 0;
49
50 swprintf(szValue, L"%llu", lValue);
51 //_ultow(lValue, szValue, 10);
52
53 if (GetNumberFormatW(LOCALE_USER_DEFAULT,
54 0,
55 szValue,
56 &numFormat,
57 lpNumber,
58 wcslen(lpNumber)) != 0)
59 {
60 return lpNumber;
61 }
62
63 wcscpy(lpNumber, szValue);
64 return lpNumber;
65 }
66
67 /**************************************************************************
68 * Default ClassFactory types
69 */
70 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
71 HRESULT IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInst, IClassFactory **theFactory);
72
73
74 /**************************************************************************
75 * Default ClassFactory Implementation
76 *
77 * SHCreateDefClassObject
78 *
79 * NOTES
80 * Helper function for dlls without their own classfactory.
81 * A generic classfactory is returned.
82 * When the CreateInstance of the cf is called the callback is executed.
83 */
84
85 class IDefClFImpl :
86 public CComObjectRootEx<CComMultiThreadModelNoCS>,
87 public IClassFactory
88 {
89 private:
90 CLSID *rclsid;
91 LPFNCREATEINSTANCE lpfnCI;
92 const IID *riidInst;
93 LONG *pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
94 public:
95 IDefClFImpl();
96 HRESULT Initialize(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInstx);
97
98 // IClassFactory
99 virtual HRESULT WINAPI CreateInstance(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppvObject);
100 virtual HRESULT WINAPI LockServer(BOOL fLock);
101
102 BEGIN_COM_MAP(IDefClFImpl)
103 COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
104 END_COM_MAP()
105 };
106
107 IDefClFImpl::IDefClFImpl()
108 {
109 lpfnCI = NULL;
110 riidInst = NULL;
111 pcRefDll = NULL;
112 rclsid = NULL;
113 }
114
115 HRESULT IDefClFImpl::Initialize(LPFNCREATEINSTANCE lpfnCIx, PLONG pcRefDllx, const IID *riidInstx)
116 {
117 lpfnCI = lpfnCIx;
118 riidInst = riidInstx;
119 pcRefDll = pcRefDllx;
120
121 if (pcRefDll)
122 InterlockedIncrement(pcRefDll);
123
124 TRACE("(%p)%s\n", this, shdebugstr_guid(riidInst));
125 return S_OK;
126 }
127
128 /******************************************************************************
129 * IDefClF_fnCreateInstance
130 */
131 HRESULT WINAPI IDefClFImpl::CreateInstance(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppvObject)
132 {
133 TRACE("%p->(%p,%s,%p)\n", this, pUnkOuter, shdebugstr_guid(&riid), ppvObject);
134
135 *ppvObject = NULL;
136
137 if (riidInst == NULL || IsEqualCLSID(riid, *riidInst) || IsEqualCLSID(riid, IID_IUnknown))
138 {
139 return lpfnCI(pUnkOuter, riid, ppvObject);
140 }
141
142 ERR("unknown IID requested %s\n", shdebugstr_guid(&riid));
143 return E_NOINTERFACE;
144 }
145
146 /******************************************************************************
147 * IDefClF_fnLockServer
148 */
149 HRESULT WINAPI IDefClFImpl::LockServer(BOOL fLock)
150 {
151 TRACE("%p->(0x%x), not implemented\n", this, fLock);
152 return E_NOTIMPL;
153 }
154
155 /**************************************************************************
156 * IDefClF_fnConstructor
157 */
158
159 HRESULT IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, const IID *riidInst, IClassFactory **theFactory)
160 {
161 return ShellObjectCreatorInit<IDefClFImpl>(lpfnCI, pcRefDll, riidInst, IID_IClassFactory, theFactory);
162 }
163
164 /******************************************************************************
165 * SHCreateDefClassObject [SHELL32.70]
166 */
167 HRESULT WINAPI SHCreateDefClassObject(
168 REFIID riid,
169 LPVOID* ppv,
170 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
171 LPDWORD pcRefDll, /* [in/out] ref count of the dll */
172 REFIID riidInst) /* [in] optional interface to the instance */
173 {
174 IClassFactory *pcf;
175 HRESULT hResult;
176
177 TRACE("%s %p %p %p %s\n", shdebugstr_guid(&riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(&riidInst));
178
179 if (!IsEqualCLSID(riid, IID_IClassFactory))
180 return E_NOINTERFACE;
181 hResult = IDefClF_fnConstructor(lpfnCI, (PLONG)pcRefDll, &riidInst, &pcf);
182 if (FAILED(hResult))
183 return hResult;
184 *ppv = pcf;
185 return S_OK;
186 }
187
188 /**************************************************************************
189 * CStartMenuDummy
190 */
191 class CStartMenuDummy :
192 public CComCoClass<CStartMenuDummy, &CLSID_StartMenu>,
193 public CComObjectRootEx<CComMultiThreadModelNoCS>
194 {
195 private:
196 CStartMenuDummy();
197 virtual ~CStartMenuDummy();
198
199 public:
200 DECLARE_REGISTRY_RESOURCEID(IDR_STARTMENU)
201
202 class _CreatorClass
203 {
204 public:
205 static STDMETHODIMP CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
206 {
207 if (ppv == NULL)
208 return E_POINTER;
209 *ppv = NULL;
210 if (pv != NULL)
211 return CLASS_E_NOAGGREGATION;
212 return CStartMenu_Constructor(riid, ppv);
213 }
214 };
215 };
216
217 /**************************************************************************
218 * CShell32Module
219 */
220 class CShell32Module : public CComModule
221 {
222 public:
223 void Term()
224 {
225 CComCreatorCentralInstance< ATL::CComObject< CDrivesFolder > >::Term();
226 CComCreatorCentralInstance< ATL::CComObject< CDesktopFolder > >::Term();
227 CComModule::Term();
228 }
229 };
230
231
232 BEGIN_OBJECT_MAP(ObjectMap)
233 OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder)
234 OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder)
235 OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder)
236 OBJECT_ENTRY(CLSID_ShellItem, CShellItem)
237 OBJECT_ENTRY(CLSID_ShellLink, CShellLink)
238 OBJECT_ENTRY(CLSID_Shell, CShellDispatch)
239 OBJECT_ENTRY(CLSID_DragDropHelper, CDropTargetHelper)
240 OBJECT_ENTRY(CLSID_ControlPanel, CControlPanelFolder)
241 OBJECT_ENTRY(CLSID_MyDocuments, CMyDocsFolder)
242 OBJECT_ENTRY(CLSID_NetworkPlaces, CNetFolder)
243 OBJECT_ENTRY(CLSID_FontsFolderShortcut, CFontsFolder)
244 OBJECT_ENTRY(CLSID_Printers, CPrinterFolder)
245 OBJECT_ENTRY(CLSID_AdminFolderShortcut, CAdminToolsFolder)
246 OBJECT_ENTRY(CLSID_ShellFldSetExt, CFolderOptions)
247 OBJECT_ENTRY(CLSID_RecycleBin, CRecycleBin)
248 OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
249 OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
250 OBJECT_ENTRY(CLSID_StartMenu, CStartMenuDummy)
251 OBJECT_ENTRY(CLSID_MenuBandSite, CMenuSite)
252 OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
253 OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar)
254 OBJECT_ENTRY(CLSID_MergedFolder, CMergedFolder)
255 OBJECT_ENTRY(CLSID_RebarBandSite, CBandSite)
256 OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler)
257 OBJECT_ENTRY(CLSID_QueryAssociations, CQueryAssociations)
258 END_OBJECT_MAP()
259
260 CShell32Module gModule;
261
262
263 /***********************************************************************
264 * DllGetVersion [SHELL32.@]
265 *
266 * Retrieves version information of the 'SHELL32.DLL'
267 *
268 * PARAMS
269 * pdvi [O] pointer to version information structure.
270 *
271 * RETURNS
272 * Success: S_OK
273 * Failure: E_INVALIDARG
274 *
275 * NOTES
276 * Returns version of a shell32.dll from IE4.01 SP1.
277 */
278
279 STDAPI DllGetVersion(DLLVERSIONINFO *pdvi)
280 {
281 /* FIXME: shouldn't these values come from the version resource? */
282 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
283 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
284 {
285 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
286 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
287 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
288 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
289 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
290 {
291 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
292
293 pdvi2->dwFlags = 0;
294 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
295 WINE_FILEVERSION_MINOR,
296 WINE_FILEVERSION_BUILD,
297 WINE_FILEVERSION_PLATFORMID);
298 }
299 TRACE("%u.%u.%u.%u\n",
300 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
301 pdvi->dwBuildNumber, pdvi->dwPlatformID);
302 return S_OK;
303 }
304 else
305 {
306 WARN("wrong DLLVERSIONINFO size from app\n");
307 return E_INVALIDARG;
308 }
309 }
310
311 /*************************************************************************
312 * global variables of the shell32.dll
313 * all are once per process
314 *
315 */
316 HINSTANCE shell32_hInstance;
317
318 void *operator new (size_t, void *buf)
319 {
320 return buf;
321 }
322
323 /*************************************************************************
324 * SHELL32 DllMain
325 *
326 * NOTES
327 * calling oleinitialize here breaks sone apps.
328 */
329 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
330 {
331 TRACE("%p 0x%x %p\n", hInstance, dwReason, fImpLoad);
332 if (dwReason == DLL_PROCESS_ATTACH)
333 {
334 shell32_hInstance = hInstance;
335 gModule.Init(ObjectMap, hInstance, &LIBID_Shell32);
336
337 DisableThreadLibraryCalls (hInstance);
338
339 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
340 GetModuleFileNameW(hInstance, swShell32Name, MAX_PATH);
341 swShell32Name[MAX_PATH - 1] = '\0';
342
343 /* Initialize comctl32 */
344 INITCOMMONCONTROLSEX InitCtrls;
345 InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
346 InitCtrls.dwICC = ICC_WIN95_CLASSES | ICC_DATE_CLASSES | ICC_USEREX_CLASSES;
347 InitCommonControlsEx(&InitCtrls);
348
349 /* Bad idea, initialization in DllMain! */
350 InitChangeNotifications();
351 }
352 else if (dwReason == DLL_PROCESS_DETACH)
353 {
354 shell32_hInstance = NULL;
355 SIC_Destroy();
356 FreeChangeNotifications();
357 gModule.Term();
358 }
359 return TRUE;
360 }
361
362 /***********************************************************************
363 * DllCanUnloadNow (SHELL32.@)
364 */
365 STDAPI DllCanUnloadNow()
366 {
367 return gModule.DllCanUnloadNow();
368 }
369
370 /*************************************************************************
371 * DllGetClassObject [SHELL32.@]
372 * SHDllGetClassObject [SHELL32.128]
373 */
374 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
375 {
376 HRESULT hResult;
377
378 TRACE("CLSID:%s,IID:%s\n", shdebugstr_guid(&rclsid), shdebugstr_guid(&riid));
379
380 hResult = gModule.DllGetClassObject(rclsid, riid, ppv);
381 TRACE("-- pointer to class factory: %p\n", *ppv);
382 return hResult;
383 }
384
385 /***********************************************************************
386 * DllRegisterServer (SHELL32.@)
387 */
388 STDAPI DllRegisterServer()
389 {
390 HRESULT hr;
391
392 hr = gModule.DllRegisterServer(TRUE);
393 if (FAILED(hr))
394 return hr;
395
396 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL);
397 if (FAILED(hr))
398 return hr;
399
400 hr = SHELL_RegisterShellFolders();
401 if (FAILED(hr))
402 return hr;
403
404 return S_OK;
405 }
406
407 /***********************************************************************
408 * DllUnregisterServer (SHELL32.@)
409 */
410 STDAPI DllUnregisterServer()
411 {
412 HRESULT hr;
413
414 hr = gModule.DllUnregisterServer(TRUE);
415 if (FAILED(hr))
416 return hr;
417
418 hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL);
419 if (FAILED(hr))
420 return hr;
421
422 return S_OK;
423 }
424
425 /*************************************************************************
426 * DllInstall [SHELL32.@]
427 *
428 * PARAMETERS
429 *
430 * BOOL bInstall - TRUE for install, FALSE for uninstall
431 * LPCWSTR pszCmdLine - command line (unused by shell32?)
432 */
433
434 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
435 {
436 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
437 return S_OK; /* indicate success */
438 }