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