Reactos
at master 856 lines 24 kB view raw
1/* 2 * handling of SHELL32.DLL OLE-Objects 3 * 4 * Copyright 1997 Marcus Meissner 5 * Copyright 1998 Juergen Schmied <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 <wine/config.h> 23 24#include <stdarg.h> 25#include <stdlib.h> 26#include <string.h> 27 28#define WIN32_NO_STATUS 29#define _INC_WINDOWS 30#define COBJMACROS 31#define NONAMELESSUNION 32 33#include <windef.h> 34#include <winbase.h> 35#include <shellapi.h> 36#include <shlobj.h> 37#include <shlwapi.h> 38#include <debughlp.h> 39 40#include <wine/debug.h> 41#include <wine/unicode.h> 42 43#include "shell32_main.h" 44 45WINE_DEFAULT_DEBUG_CHANNEL(shell); 46 47extern INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax); /* shlwapi.24 */ 48 49/************************************************************************** 50 * Default ClassFactory types 51 */ 52typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject); 53 54#ifndef __REACTOS__ 55 56static IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst); 57 58/* this table contains all CLSIDs of shell32 objects */ 59static const struct { 60 REFIID clsid; 61 LPFNCREATEINSTANCE lpfnCI; 62} InterfaceTable[] = { 63 64 {&CLSID_ApplicationAssociationRegistration, ApplicationAssociationRegistration_Constructor}, 65 {&CLSID_AutoComplete, IAutoComplete_Constructor}, 66 {&CLSID_ControlPanel, IControlPanel_Constructor}, 67 {&CLSID_DragDropHelper, IDropTargetHelper_Constructor}, 68 {&CLSID_FolderShortcut, FolderShortcut_Constructor}, 69 {&CLSID_MyComputer, ISF_MyComputer_Constructor}, 70 {&CLSID_MyDocuments, MyDocuments_Constructor}, 71 {&CLSID_NetworkPlaces, ISF_NetworkPlaces_Constructor}, 72 {&CLSID_Printers, Printers_Constructor}, 73 {&CLSID_QueryAssociations, QueryAssociations_Constructor}, 74 {&CLSID_RecycleBin, RecycleBin_Constructor}, 75 {&CLSID_ShellDesktop, ISF_Desktop_Constructor}, 76 {&CLSID_ShellFSFolder, IFSFolder_Constructor}, 77 {&CLSID_ShellItem, IShellItem_Constructor}, 78 {&CLSID_ShellLink, IShellLink_Constructor}, 79 {&CLSID_UnixDosFolder, UnixDosFolder_Constructor}, 80 {&CLSID_UnixFolder, UnixFolder_Constructor}, 81 {&CLSID_ExplorerBrowser,ExplorerBrowser_Constructor}, 82 {&CLSID_KnownFolderManager, KnownFolderManager_Constructor}, 83 {&CLSID_Shell, IShellDispatch_Constructor}, 84 {NULL, NULL} 85}; 86 87#endif /* !__REACTOS__ */ 88 89HRESULT WINAPI SH32_CoCreateInstance( 90 LPCWSTR aclsid, 91 const CLSID *clsid, 92 LPUNKNOWN pUnkOuter, 93 DWORD dwClsCtx, 94 REFIID refiid, 95 LPVOID *ppv) 96{ 97 DWORD hres; 98 CLSID iid; 99 const CLSID * myclsid = clsid; 100 WCHAR sKeyName[MAX_PATH]; 101 WCHAR sClassID[60]; 102 WCHAR sDllPath[MAX_PATH]; 103 HKEY hKey = 0; 104 DWORD dwSize; 105 IClassFactory * pcf = NULL; 106 107 if(!ppv) return E_POINTER; 108 *ppv=NULL; 109 110 /* if the clsid is a string, convert it */ 111 if (!clsid) 112 { 113 if (!aclsid) return REGDB_E_CLASSNOTREG; 114 SHCLSIDFromStringW(aclsid, &iid); 115 myclsid = &iid; 116 } 117 118 TRACE("(%p,%s,unk:%p,%s,%p)\n", 119 aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv); 120 121 if (SUCCEEDED(DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) 122 { 123 hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv); 124 IClassFactory_Release(pcf); 125 goto end; 126 } 127 128 /* we look up the dll path in the registry */ 129 SHStringFromGUIDW(myclsid, sClassID, ARRAY_SIZE(sClassID)); 130 swprintf(sKeyName, L"CLSID\\%s\\InprocServer32", sClassID); 131 132 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey)) 133 return E_ACCESSDENIED; 134 135 /* if a special registry key is set, we load a shell extension without help of OLE32 */ 136 if ((dwClsCtx & CLSCTX_INPROC_SERVER) && !SHQueryValueExW(hKey, L"LoadWithoutCOM", 0, 0, 0, 0)) 137 { 138 /* load an external dll without ole32 */ 139 HANDLE hLibrary; 140 typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv); 141 DllGetClassObjectFunc DllGetClassObject; 142 143 dwSize = sizeof(sDllPath); 144 SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize ); 145 146 if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) { 147 ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath)); 148 hres = E_ACCESSDENIED; 149 goto end; 150 } else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"))) { 151 ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(sDllPath)); 152 FreeLibrary( hLibrary ); 153 hres = E_ACCESSDENIED; 154 goto end; 155 } else if (FAILED(hres = DllGetClassObject(myclsid, &IID_IClassFactory, (LPVOID*)&pcf))) { 156 TRACE("GetClassObject failed 0x%08x\n", hres); 157 goto end; 158 } 159 160 hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv); 161 IClassFactory_Release(pcf); 162 } else { 163 164 /* load an external dll in the usual way */ 165 hres = CoCreateInstance(myclsid, pUnkOuter, dwClsCtx, refiid, ppv); 166 } 167 168end: 169 if (hKey) RegCloseKey(hKey); 170 if(hres!=S_OK) 171 { 172 ERR("failed (0x%08x) to create CLSID:%s IID:%s\n", 173 hres, shdebugstr_guid(myclsid), shdebugstr_guid(refiid)); 174 ERR("class not found in registry\n"); 175 } 176 177 TRACE("-- instance: %p\n",*ppv); 178 return hres; 179} 180 181/************************************************************************* 182 * SHCoCreateInstance [SHELL32.102] 183 * 184 * Equivalent to CoCreateInstance. Under Windows 9x this function could sometimes 185 * use the shell32 built-in "mini-COM" without the need to load ole32.dll - see 186 * SHLoadOLE for details. 187 * 188 * Under wine if a "LoadWithoutCOM" value is present or the object resides in 189 * shell32.dll the function will load the object manually without the help of ole32 190 * 191 * NOTES 192 * exported by ordinal 193 * 194 * SEE ALSO 195 * CoCreateInstance, SHLoadOLE 196 */ 197HRESULT WINAPI SHCoCreateInstance( 198 LPCWSTR aclsid, 199 const CLSID *clsid, 200 LPUNKNOWN pUnkOuter, 201 REFIID riid, 202 LPVOID *ppv) 203{ 204 return SH32_CoCreateInstance(aclsid, clsid, pUnkOuter, CLSCTX_INPROC_SERVER, riid, ppv); 205} 206 207HRESULT WINAPI SH32_ExtCoCreateInstance( 208 _In_opt_ LPCWSTR aclsid, 209 _In_opt_ const CLSID *clsid, 210 _In_opt_ LPUNKNOWN pUnkOuter, 211 _In_ DWORD dwClsCtx, 212 _In_ REFIID riid, 213 _Out_ LPVOID *ppv) 214{ 215 // TODO: Verify that this CLSID is allowed (..\CurrentVersion\Shell Extensions\Approved) if REST_ENFORCESHELLEXTSECURITY is active 216 return SH32_CoCreateInstance(aclsid, clsid, pUnkOuter, dwClsCtx, riid, ppv); 217} 218 219/************************************************************************* 220 * SHCoCreateInstance [SHELL32.866] 221 */ 222HRESULT WINAPI SHExtCoCreateInstance( 223 _In_opt_ LPCWSTR aclsid, 224 _In_opt_ const CLSID *clsid, 225 _In_opt_ LPUNKNOWN pUnkOuter, 226 _In_ REFIID riid, 227 _Out_ LPVOID *ppv) 228{ 229 return SH32_ExtCoCreateInstance(aclsid, clsid, pUnkOuter, CLSCTX_INPROC_SERVER, riid, ppv); 230} 231 232#if 0 233/************************************************************************* 234 * SHExtCoCreateInstanceCheckCategory [SHELL32.887] 235 */ 236// TODO: ICatInformation::IsClassOfCategories? 237// return SH32_ExtCoCreateInstance() 238#endif 239 240#ifndef __REACTOS__ 241/************************************************************************* 242 * DllGetClassObject [SHELL32.@] 243 * SHDllGetClassObject [SHELL32.128] 244 */ 245HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) 246{ 247 IClassFactory * pcf = NULL; 248 HRESULT hres; 249 int i; 250 251 TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid)); 252 253 if (!ppv) return E_INVALIDARG; 254 *ppv = NULL; 255 256 /* search our internal interface table */ 257 for(i=0;InterfaceTable[i].clsid;i++) { 258 if(IsEqualIID(InterfaceTable[i].clsid, rclsid)) { 259 TRACE("index[%u]\n", i); 260 pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL); 261 break; 262 } 263 } 264 265 if (!pcf) { 266 FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid)); 267 return CLASS_E_CLASSNOTAVAILABLE; 268 } 269 270 hres = IClassFactory_QueryInterface(pcf, iid, ppv); 271 IClassFactory_Release(pcf); 272 273 TRACE("-- pointer to class factory: %p\n",*ppv); 274 return hres; 275} 276#endif 277 278/************************************************************************* 279 * SHCLSIDFromString [SHELL32.147] 280 * 281 * Under Windows 9x this was an ANSI version of CLSIDFromString. It also allowed 282 * to avoid dependency on ole32.dll (see SHLoadOLE for details). 283 * 284 * Under Windows NT/2000/XP this is equivalent to CLSIDFromString 285 * 286 * NOTES 287 * exported by ordinal 288 * 289 * SEE ALSO 290 * CLSIDFromString, SHLoadOLE 291 */ 292DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id) 293{ 294 WCHAR buffer[40]; 295 TRACE("(%p(%s) %p)\n", clsid, clsid, id); 296 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) )) 297 return CO_E_CLASSSTRING; 298 return CLSIDFromString( buffer, id ); 299} 300DWORD WINAPI SHCLSIDFromStringW (LPCWSTR clsid, CLSID *id) 301{ 302 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id); 303 return CLSIDFromString(clsid, id); 304} 305DWORD WINAPI SHCLSIDFromStringAW (LPCVOID clsid, CLSID *id) 306{ 307 if (SHELL_OsIsUnicode()) 308 return SHCLSIDFromStringW (clsid, id); 309 return SHCLSIDFromStringA (clsid, id); 310} 311 312/************************************************************************* 313 * SHGetMalloc [SHELL32.@] 314 * 315 * Equivalent to CoGetMalloc(MEMCTX_TASK, ...). Under Windows 9x this function 316 * could use the shell32 built-in "mini-COM" without the need to load ole32.dll - 317 * see SHLoadOLE for details. 318 * 319 * PARAMS 320 * lpmal [O] Destination for IMalloc interface. 321 * 322 * RETURNS 323 * Success: S_OK. lpmal contains the shells IMalloc interface. 324 * Failure. An HRESULT error code. 325 * 326 * SEE ALSO 327 * CoGetMalloc, SHLoadOLE 328 */ 329HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal) 330{ 331 TRACE("(%p)\n", lpmal); 332 return CoGetMalloc(MEMCTX_TASK, lpmal); 333} 334 335/************************************************************************* 336 * SHAlloc [SHELL32.196] 337 * 338 * Equivalent to CoTaskMemAlloc. Under Windows 9x this function could use 339 * the shell32 built-in "mini-COM" without the need to load ole32.dll - 340 * see SHLoadOLE for details. 341 * 342 * NOTES 343 * exported by ordinal 344 * 345 * SEE ALSO 346 * CoTaskMemAlloc, SHLoadOLE 347 */ 348LPVOID WINAPI SHAlloc(SIZE_T len) 349{ 350 LPVOID ret; 351 352 ret = CoTaskMemAlloc(len); 353 TRACE("%u bytes at %p\n",len, ret); 354 return ret; 355} 356 357/************************************************************************* 358 * SHFree [SHELL32.195] 359 * 360 * Equivalent to CoTaskMemFree. Under Windows 9x this function could use 361 * the shell32 built-in "mini-COM" without the need to load ole32.dll - 362 * see SHLoadOLE for details. 363 * 364 * NOTES 365 * exported by ordinal 366 * 367 * SEE ALSO 368 * CoTaskMemFree, SHLoadOLE 369 */ 370void WINAPI SHFree(LPVOID pv) 371{ 372 TRACE("%p\n",pv); 373 CoTaskMemFree(pv); 374} 375 376#ifndef __REACTOS__ 377/************************************************************************* 378 * SHGetDesktopFolder [SHELL32.@] 379 */ 380HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf) 381{ 382 HRESULT hres; 383 384 TRACE("(%p)\n", psf); 385 386 if(!psf) return E_INVALIDARG; 387 388 *psf = NULL; 389 hres = ISF_Desktop_Constructor(NULL, &IID_IShellFolder, (LPVOID*)psf); 390 391 TRACE("-- %p->(%p) 0x%08x\n", psf, *psf, hres); 392 return hres; 393} 394#endif 395 396/************************************************************************** 397 * Default ClassFactory Implementation 398 * 399 * SHCreateDefClassObject 400 * 401 * NOTES 402 * Helper function for dlls without their own classfactory. 403 * A generic classfactory is returned. 404 * When the CreateInstance of the cf is called the callback is executed. 405 */ 406 407#ifndef __REACTOS__ 408 409typedef struct 410{ 411 IClassFactory IClassFactory_iface; 412 LONG ref; 413 CLSID *rclsid; 414 LPFNCREATEINSTANCE lpfnCI; 415 const IID * riidInst; 416 LONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */ 417} IDefClFImpl; 418 419static inline IDefClFImpl *impl_from_IClassFactory(IClassFactory *iface) 420{ 421 return CONTAINING_RECORD(iface, IDefClFImpl, IClassFactory_iface); 422} 423 424static const IClassFactoryVtbl dclfvt; 425 426/************************************************************************** 427 * IDefClF_fnConstructor 428 */ 429 430static IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst) 431{ 432 IDefClFImpl* lpclf; 433 434 lpclf = HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl)); 435 lpclf->ref = 1; 436 lpclf->IClassFactory_iface.lpVtbl = &dclfvt; 437 lpclf->lpfnCI = lpfnCI; 438 lpclf->pcRefDll = pcRefDll; 439 440 if (pcRefDll) InterlockedIncrement(pcRefDll); 441 lpclf->riidInst = riidInst; 442 443 TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst)); 444 return (LPCLASSFACTORY)lpclf; 445} 446/************************************************************************** 447 * IDefClF_fnQueryInterface 448 */ 449static HRESULT WINAPI IDefClF_fnQueryInterface( 450 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj) 451{ 452 IDefClFImpl *This = impl_from_IClassFactory(iface); 453 454 TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid)); 455 456 *ppvObj = NULL; 457 458 if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { 459 *ppvObj = This; 460 InterlockedIncrement(&This->ref); 461 return S_OK; 462 } 463 464 TRACE("-- E_NOINTERFACE\n"); 465 return E_NOINTERFACE; 466} 467/****************************************************************************** 468 * IDefClF_fnAddRef 469 */ 470static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface) 471{ 472 IDefClFImpl *This = impl_from_IClassFactory(iface); 473 ULONG refCount = InterlockedIncrement(&This->ref); 474 475 TRACE("(%p)->(count=%u)\n", This, refCount - 1); 476 477 return refCount; 478} 479/****************************************************************************** 480 * IDefClF_fnRelease 481 */ 482static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface) 483{ 484 IDefClFImpl *This = impl_from_IClassFactory(iface); 485 ULONG refCount = InterlockedDecrement(&This->ref); 486 487 TRACE("(%p)->(count=%u)\n", This, refCount + 1); 488 489 if (!refCount) 490 { 491 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll); 492 493 TRACE("-- destroying IClassFactory(%p)\n",This); 494 HeapFree(GetProcessHeap(),0,This); 495 return 0; 496 } 497 return refCount; 498} 499/****************************************************************************** 500 * IDefClF_fnCreateInstance 501 */ 502static HRESULT WINAPI IDefClF_fnCreateInstance( 503 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject) 504{ 505 IDefClFImpl *This = impl_from_IClassFactory(iface); 506 507 TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject); 508 509 *ppvObject = NULL; 510 511 if ( This->riidInst==NULL || 512 IsEqualCLSID(riid, This->riidInst) || 513 IsEqualCLSID(riid, &IID_IUnknown) ) 514 { 515 return This->lpfnCI(pUnkOuter, riid, ppvObject); 516 } 517 518 ERR("unknown IID requested %s\n",shdebugstr_guid(riid)); 519 return E_NOINTERFACE; 520} 521/****************************************************************************** 522 * IDefClF_fnLockServer 523 */ 524static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock) 525{ 526 IDefClFImpl *This = impl_from_IClassFactory(iface); 527 TRACE("%p->(0x%x), not implemented\n",This, fLock); 528 return E_NOTIMPL; 529} 530 531static const IClassFactoryVtbl dclfvt = 532{ 533 IDefClF_fnQueryInterface, 534 IDefClF_fnAddRef, 535 IDefClF_fnRelease, 536 IDefClF_fnCreateInstance, 537 IDefClF_fnLockServer 538}; 539 540/****************************************************************************** 541 * SHCreateDefClassObject [SHELL32.70] 542 */ 543HRESULT WINAPI SHCreateDefClassObject( 544 REFIID riid, 545 LPVOID* ppv, 546 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */ 547 LPDWORD pcRefDll, /* [in/out] ref count of the dll */ 548 REFIID riidInst) /* [in] optional interface to the instance */ 549{ 550 IClassFactory * pcf; 551 552 TRACE("%s %p %p %p %s\n", 553 shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst)); 554 555 if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE; 556 if (! (pcf = IDefClF_fnConstructor(lpfnCI, (PLONG)pcRefDll, riidInst))) return E_OUTOFMEMORY; 557 *ppv = pcf; 558 return S_OK; 559} 560 561#endif /* !__REACTOS__ */ 562 563/************************************************************************* 564 * DragAcceptFiles [SHELL32.@] 565 */ 566void WINAPI DragAcceptFiles(HWND hWnd, BOOL b) 567{ 568 LONG exstyle; 569 570 if( !IsWindow(hWnd) ) return; 571 exstyle = GetWindowLongPtrA(hWnd,GWL_EXSTYLE); 572 if (b) 573 exstyle |= WS_EX_ACCEPTFILES; 574 else 575 exstyle &= ~WS_EX_ACCEPTFILES; 576 SetWindowLongPtrA(hWnd,GWL_EXSTYLE,exstyle); 577} 578 579/************************************************************************* 580 * DragFinish [SHELL32.@] 581 */ 582void WINAPI DragFinish(HDROP h) 583{ 584 TRACE("\n"); 585 GlobalFree(h); 586} 587 588/************************************************************************* 589 * DragQueryPoint [SHELL32.@] 590 */ 591BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p) 592{ 593 DROPFILES *lpDropFileStruct; 594 BOOL bRet; 595 596 TRACE("\n"); 597 598 lpDropFileStruct = GlobalLock(hDrop); 599 600 *p = lpDropFileStruct->pt; 601 bRet = lpDropFileStruct->fNC; 602 603 GlobalUnlock(hDrop); 604 return bRet; 605} 606 607/************************************************************************* 608 * DragQueryFileA [SHELL32.@] 609 * DragQueryFile [SHELL32.@] 610 */ 611UINT WINAPI DragQueryFileA( 612 HDROP hDrop, 613 UINT lFile, 614 LPSTR lpszFile, 615 UINT lLength) 616{ 617 LPSTR lpDrop; 618 UINT i = 0; 619 DROPFILES *lpDropFileStruct = GlobalLock(hDrop); 620 621 TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength); 622 623 if(!lpDropFileStruct) goto end; 624 625 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles; 626 627 if(lpDropFileStruct->fWide) { 628 LPWSTR lpszFileW = NULL; 629 630 if(lpszFile && lFile != 0xFFFFFFFF) { 631 lpszFileW = HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR)); 632 if(lpszFileW == NULL) { 633 goto end; 634 } 635 } 636 i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength); 637 638 if(lpszFileW) { 639 WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL); 640 HeapFree(GetProcessHeap(), 0, lpszFileW); 641 } 642 goto end; 643 } 644 645 while (i++ < lFile) 646 { 647 while (*lpDrop++); /* skip filename */ 648 if (!*lpDrop) 649 { 650 i = (lFile == 0xFFFFFFFF) ? i : 0; 651 goto end; 652 } 653 } 654 655 i = strlen(lpDrop); 656 if (!lpszFile ) goto end; /* needed buffer size */ 657 lstrcpynA (lpszFile, lpDrop, lLength); 658end: 659 GlobalUnlock(hDrop); 660 return i; 661} 662 663/************************************************************************* 664 * DragQueryFileW [SHELL32.@] 665 */ 666UINT WINAPI DragQueryFileW( 667 HDROP hDrop, 668 UINT lFile, 669 LPWSTR lpszwFile, 670 UINT lLength) 671{ 672 LPWSTR lpwDrop; 673 UINT i = 0; 674 DROPFILES *lpDropFileStruct = GlobalLock(hDrop); 675 676 TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength); 677 678 if(!lpDropFileStruct) goto end; 679 680 lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles); 681 682 if(lpDropFileStruct->fWide == FALSE) { 683 LPSTR lpszFileA = NULL; 684 685 if(lpszwFile && lFile != 0xFFFFFFFF) { 686 lpszFileA = HeapAlloc(GetProcessHeap(), 0, lLength); 687 if(lpszFileA == NULL) { 688 goto end; 689 } 690 } 691 i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength); 692 693 if(lpszFileA) { 694 MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength); 695 HeapFree(GetProcessHeap(), 0, lpszFileA); 696 } 697 goto end; 698 } 699 700 i = 0; 701 while (i++ < lFile) 702 { 703 while (*lpwDrop++); /* skip filename */ 704 if (!*lpwDrop) 705 { 706 i = (lFile == 0xFFFFFFFF) ? i : 0; 707 goto end; 708 } 709 } 710 711 i = strlenW(lpwDrop); 712 if ( !lpszwFile) goto end; /* needed buffer size */ 713 lstrcpynW (lpszwFile, lpwDrop, lLength); 714end: 715 GlobalUnlock(hDrop); 716 return i; 717} 718 719/************************************************************************* 720 * SHPropStgCreate [SHELL32.685] 721 */ 722HRESULT WINAPI SHPropStgCreate(IPropertySetStorage *psstg, REFFMTID fmtid, 723 const CLSID *pclsid, DWORD grfFlags, DWORD grfMode, 724 DWORD dwDisposition, IPropertyStorage **ppstg, UINT *puCodePage) 725{ 726 PROPSPEC prop; 727 PROPVARIANT ret; 728 HRESULT hres; 729 730 TRACE("%p %s %s %x %x %x %p %p\n", psstg, debugstr_guid(fmtid), debugstr_guid(pclsid), 731 grfFlags, grfMode, dwDisposition, ppstg, puCodePage); 732 733 hres = IPropertySetStorage_Open(psstg, fmtid, grfMode, ppstg); 734 735 switch(dwDisposition) { 736 case CREATE_ALWAYS: 737 if(SUCCEEDED(hres)) { 738 IPropertyStorage_Release(*ppstg); 739 hres = IPropertySetStorage_Delete(psstg, fmtid); 740 if(FAILED(hres)) 741 return hres; 742 hres = E_FAIL; 743 } 744 745 case OPEN_ALWAYS: 746 case CREATE_NEW: 747 if(FAILED(hres)) 748 hres = IPropertySetStorage_Create(psstg, fmtid, pclsid, 749 grfFlags, grfMode, ppstg); 750 751 case OPEN_EXISTING: 752 if(FAILED(hres)) 753 return hres; 754 755 if(puCodePage) { 756 prop.ulKind = PRSPEC_PROPID; 757 prop.u.propid = PID_CODEPAGE; 758 hres = IPropertyStorage_ReadMultiple(*ppstg, 1, &prop, &ret); 759 if(FAILED(hres) || ret.vt!=VT_I2) 760 *puCodePage = 0; 761 else 762 *puCodePage = ret.u.iVal; 763 } 764 } 765 766 return S_OK; 767} 768 769/************************************************************************* 770 * SHPropStgReadMultiple [SHELL32.688] 771 */ 772HRESULT WINAPI SHPropStgReadMultiple(IPropertyStorage *pps, UINT uCodePage, 773 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar) 774{ 775 STATPROPSETSTG stat; 776 HRESULT hres; 777 778 FIXME("%p %u %u %p %p\n", pps, uCodePage, cpspec, rgpspec, rgvar); 779 780 memset(rgvar, 0, cpspec*sizeof(PROPVARIANT)); 781 hres = IPropertyStorage_ReadMultiple(pps, cpspec, rgpspec, rgvar); 782 if(FAILED(hres)) 783 return hres; 784 785 if(!uCodePage) { 786 PROPSPEC prop; 787 PROPVARIANT ret; 788 789 prop.ulKind = PRSPEC_PROPID; 790 prop.u.propid = PID_CODEPAGE; 791 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret); 792 if(FAILED(hres) || ret.vt!=VT_I2) 793 return S_OK; 794 795 uCodePage = ret.u.iVal; 796 } 797 798 hres = IPropertyStorage_Stat(pps, &stat); 799 if(FAILED(hres)) 800 return S_OK; 801 802 /* TODO: do something with codepage and stat */ 803 return S_OK; 804} 805 806/************************************************************************* 807 * SHPropStgWriteMultiple [SHELL32.689] 808 */ 809HRESULT WINAPI SHPropStgWriteMultiple(IPropertyStorage *pps, UINT *uCodePage, 810 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar, PROPID propidNameFirst) 811{ 812 STATPROPSETSTG stat; 813 UINT codepage; 814 HRESULT hres; 815 816 FIXME("%p %p %u %p %p %d\n", pps, uCodePage, cpspec, rgpspec, rgvar, propidNameFirst); 817 818 hres = IPropertyStorage_Stat(pps, &stat); 819 if(FAILED(hres)) 820 return hres; 821 822 if(uCodePage && *uCodePage) 823 codepage = *uCodePage; 824 else { 825 PROPSPEC prop; 826 PROPVARIANT ret; 827 828 prop.ulKind = PRSPEC_PROPID; 829 prop.u.propid = PID_CODEPAGE; 830 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret); 831 if(FAILED(hres)) 832 return hres; 833 if(ret.vt!=VT_I2 || !ret.u.iVal) 834 return E_FAIL; 835 836 codepage = ret.u.iVal; 837 if(uCodePage) 838 *uCodePage = codepage; 839 } 840 841 /* TODO: do something with codepage and stat */ 842 843 hres = IPropertyStorage_WriteMultiple(pps, cpspec, rgpspec, rgvar, propidNameFirst); 844 return hres; 845} 846 847/************************************************************************* 848 * SHCreateQueryCancelAutoPlayMoniker [SHELL32.@] 849 */ 850HRESULT WINAPI SHCreateQueryCancelAutoPlayMoniker(IMoniker **moniker) 851{ 852 TRACE("%p\n", moniker); 853 854 if (!moniker) return E_INVALIDARG; 855 return CreateClassMoniker(&CLSID_QueryCancelAutoPlay, moniker); 856}