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