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