widl: Get rid of PowerPC support.
[wine.git] / dlls / shell32 / shellole.c
blob5b72fecf07e25b29ad38e7da6dc84467548dd2fb
1 /*
2 * handling of SHELL32.DLL OLE-Objects
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
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.
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.
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
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #define COBJMACROS
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "shellapi.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "shlobj.h"
35 #include "shlguid.h"
36 #include "shldisp.h"
37 #include "gdiplus.h"
38 #include "shimgdata.h"
39 #include "winreg.h"
40 #include "winerror.h"
42 #include "undocshell.h"
43 #include "shell32_main.h"
45 #include "wine/debug.h"
46 #include "shlwapi.h"
47 #include "debughlp.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(shell);
51 extern INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax); /* shlwapi.24 */
52 static HRESULT WINAPI ShellImageDataFactory_Constructor(IUnknown *outer, REFIID riid, void **obj);
54 /**************************************************************************
55 * Default ClassFactory types
57 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
58 static IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst);
60 /* this table contains all CLSIDs of shell32 objects */
61 static const struct {
62 REFIID clsid;
63 LPFNCREATEINSTANCE lpfnCI;
64 } InterfaceTable[] = {
66 {&CLSID_ApplicationAssociationRegistration, ApplicationAssociationRegistration_Constructor},
67 {&CLSID_ApplicationDestinations, ApplicationDestinations_Constructor},
68 {&CLSID_ApplicationDocumentLists, ApplicationDocumentLists_Constructor},
69 {&CLSID_AutoComplete, IAutoComplete_Constructor},
70 {&CLSID_ControlPanel, IControlPanel_Constructor},
71 {&CLSID_DragDropHelper, IDropTargetHelper_Constructor},
72 {&CLSID_FolderShortcut, FolderShortcut_Constructor},
73 {&CLSID_MyComputer, ISF_MyComputer_Constructor},
74 {&CLSID_MyDocuments, MyDocuments_Constructor},
75 {&CLSID_NetworkPlaces, ISF_NetworkPlaces_Constructor},
76 {&CLSID_Printers, Printers_Constructor},
77 {&CLSID_QueryAssociations, QueryAssociations_Constructor},
78 {&CLSID_RecycleBin, RecycleBin_Constructor},
79 {&CLSID_ShellDesktop, ISF_Desktop_Constructor},
80 {&CLSID_ShellFSFolder, IFSFolder_Constructor},
81 {&CLSID_ShellItem, IShellItem_Constructor},
82 {&CLSID_ShellLink, IShellLink_Constructor},
83 {&CLSID_UnixDosFolder, UnixDosFolder_Constructor},
84 {&CLSID_UnixFolder, UnixFolder_Constructor},
85 {&CLSID_ExplorerBrowser,ExplorerBrowser_Constructor},
86 {&CLSID_KnownFolderManager, KnownFolderManager_Constructor},
87 {&CLSID_Shell, IShellDispatch_Constructor},
88 {&CLSID_DestinationList, CustomDestinationList_Constructor},
89 {&CLSID_ShellImageDataFactory, ShellImageDataFactory_Constructor},
90 {&CLSID_FileOperation, IFileOperation_Constructor},
91 {NULL, NULL}
94 /*************************************************************************
95 * SHCoCreateInstance [SHELL32.102]
97 * Equivalent to CoCreateInstance. Under Windows 9x this function could sometimes
98 * use the shell32 built-in "mini-COM" without the need to load ole32.dll - see
99 * SHLoadOLE for details.
101 * Under wine if a "LoadWithoutCOM" value is present or the object resides in
102 * shell32.dll the function will load the object manually without the help of ole32
104 * NOTES
105 * exported by ordinal
107 * SEE ALSO
108 * CoCreateInstance, SHLoadOLE
110 HRESULT WINAPI SHCoCreateInstance(
111 LPCWSTR aclsid,
112 const CLSID *clsid,
113 LPUNKNOWN pUnkOuter,
114 REFIID refiid,
115 LPVOID *ppv)
117 DWORD hres;
118 IID iid;
119 const CLSID * myclsid = clsid;
120 WCHAR sKeyName[MAX_PATH];
121 WCHAR sClassID[60];
122 WCHAR sDllPath[MAX_PATH];
123 HKEY hKey = 0;
124 DWORD dwSize;
125 IClassFactory * pcf = NULL;
127 if(!ppv) return E_POINTER;
128 *ppv=NULL;
130 /* if the clsid is a string, convert it */
131 if (!clsid)
133 if (!aclsid) return REGDB_E_CLASSNOTREG;
134 SHCLSIDFromStringW(aclsid, &iid);
135 myclsid = &iid;
138 TRACE("(%p,%s,unk:%p,%s,%p)\n",
139 aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv);
141 if (SUCCEEDED(DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf)))
143 hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
144 IClassFactory_Release(pcf);
145 goto end;
148 /* we look up the dll path in the registry */
149 SHStringFromGUIDW(myclsid, sClassID, ARRAY_SIZE(sClassID));
150 swprintf( sKeyName, ARRAY_SIZE(sKeyName), L"CLSID\\%s\\InprocServer32", sClassID );
152 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey))
153 return E_ACCESSDENIED;
155 /* if a special registry key is set, we load a shell extension without help of OLE32 */
156 if (!SHQueryValueExW(hKey, L"LoadWithoutCOM", 0, 0, 0, 0))
158 /* load an external dll without ole32 */
159 HANDLE hLibrary;
160 typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
161 DllGetClassObjectFunc DllGetClassObject;
163 dwSize = sizeof(sDllPath);
164 SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize );
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;
180 hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
181 IClassFactory_Release(pcf);
182 } else {
184 /* load an external dll in the usual way */
185 hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv);
188 end:
189 if (hKey) RegCloseKey(hKey);
190 if(hres!=S_OK)
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");
197 TRACE("-- instance: %p\n",*ppv);
198 return hres;
201 /*************************************************************************
202 * DllGetClassObject [SHELL32.@]
203 * SHDllGetClassObject [SHELL32.128]
205 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
207 IClassFactory * pcf = NULL;
208 HRESULT hres;
209 int i;
211 TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid));
213 if (!ppv) return E_INVALIDARG;
214 *ppv = NULL;
216 /* search our internal interface table */
217 for(i=0;InterfaceTable[i].clsid;i++) {
218 if(IsEqualIID(InterfaceTable[i].clsid, rclsid)) {
219 TRACE("index[%u]\n", i);
220 pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
221 break;
225 if (!pcf) {
226 FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid));
227 return CLASS_E_CLASSNOTAVAILABLE;
230 hres = IClassFactory_QueryInterface(pcf, iid, ppv);
231 IClassFactory_Release(pcf);
233 TRACE("-- pointer to class factory: %p\n",*ppv);
234 return hres;
237 /*************************************************************************
238 * SHCLSIDFromString [SHELL32.147]
240 * Under Windows 9x this was an ANSI version of CLSIDFromString. It also allowed
241 * to avoid dependency on ole32.dll (see SHLoadOLE for details).
243 * Under Windows NT/2000/XP this is equivalent to CLSIDFromString
245 * NOTES
246 * exported by ordinal
248 * SEE ALSO
249 * CLSIDFromString, SHLoadOLE
251 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id)
253 WCHAR buffer[40];
254 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
255 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, ARRAY_SIZE(buffer) ))
256 return CO_E_CLASSSTRING;
257 return CLSIDFromString( buffer, id );
259 DWORD WINAPI SHCLSIDFromStringW (LPCWSTR clsid, CLSID *id)
261 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
262 return CLSIDFromString(clsid, id);
264 DWORD WINAPI SHCLSIDFromStringAW (LPCVOID clsid, CLSID *id)
266 if (SHELL_OsIsUnicode())
267 return SHCLSIDFromStringW (clsid, id);
268 return SHCLSIDFromStringA (clsid, id);
271 /*************************************************************************
272 * SHGetMalloc [SHELL32.@]
274 * Equivalent to CoGetMalloc(MEMCTX_TASK, ...). Under Windows 9x this function
275 * could use the shell32 built-in "mini-COM" without the need to load ole32.dll -
276 * see SHLoadOLE for details.
278 * PARAMS
279 * lpmal [O] Destination for IMalloc interface.
281 * RETURNS
282 * Success: S_OK. lpmal contains the shells IMalloc interface.
283 * Failure. An HRESULT error code.
285 * SEE ALSO
286 * CoGetMalloc, SHLoadOLE
288 HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal)
290 TRACE("(%p)\n", lpmal);
291 return CoGetMalloc(MEMCTX_TASK, lpmal);
294 /*************************************************************************
295 * SHAlloc [SHELL32.196]
297 * Equivalent to CoTaskMemAlloc. Under Windows 9x this function could use
298 * the shell32 built-in "mini-COM" without the need to load ole32.dll -
299 * see SHLoadOLE for details.
301 * NOTES
302 * exported by ordinal
304 * SEE ALSO
305 * CoTaskMemAlloc, SHLoadOLE
307 LPVOID WINAPI SHAlloc(DWORD len)
309 LPVOID ret;
311 ret = CoTaskMemAlloc(len);
312 TRACE("%u bytes at %p\n",len, ret);
313 return ret;
316 /*************************************************************************
317 * SHFree [SHELL32.195]
319 * Equivalent to CoTaskMemFree. Under Windows 9x this function could use
320 * the shell32 built-in "mini-COM" without the need to load ole32.dll -
321 * see SHLoadOLE for details.
323 * NOTES
324 * exported by ordinal
326 * SEE ALSO
327 * CoTaskMemFree, SHLoadOLE
329 void WINAPI SHFree(LPVOID pv)
331 TRACE("%p\n",pv);
332 CoTaskMemFree(pv);
335 /*************************************************************************
336 * SHGetDesktopFolder [SHELL32.@]
338 HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
340 HRESULT hres;
342 TRACE("(%p)\n", psf);
344 if(!psf) return E_INVALIDARG;
346 *psf = NULL;
347 hres = ISF_Desktop_Constructor(NULL, &IID_IShellFolder, (LPVOID*)psf);
349 TRACE("-- %p->(%p) 0x%08x\n", psf, *psf, hres);
350 return hres;
352 /**************************************************************************
353 * Default ClassFactory Implementation
355 * SHCreateDefClassObject
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.
363 typedef struct
365 IClassFactory IClassFactory_iface;
366 LONG ref;
367 CLSID *rclsid;
368 LPFNCREATEINSTANCE lpfnCI;
369 const IID * riidInst;
370 LONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
371 } IDefClFImpl;
373 static inline IDefClFImpl *impl_from_IClassFactory(IClassFactory *iface)
375 return CONTAINING_RECORD(iface, IDefClFImpl, IClassFactory_iface);
378 static const IClassFactoryVtbl dclfvt;
380 /**************************************************************************
381 * IDefClF_fnConstructor
384 static IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
386 IDefClFImpl* lpclf;
388 lpclf = heap_alloc(sizeof(*lpclf));
389 lpclf->ref = 1;
390 lpclf->IClassFactory_iface.lpVtbl = &dclfvt;
391 lpclf->lpfnCI = lpfnCI;
392 lpclf->pcRefDll = pcRefDll;
394 if (pcRefDll) InterlockedIncrement(pcRefDll);
395 lpclf->riidInst = riidInst;
397 TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst));
398 return &lpclf->IClassFactory_iface;
400 /**************************************************************************
401 * IDefClF_fnQueryInterface
403 static HRESULT WINAPI IDefClF_fnQueryInterface(
404 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
406 IDefClFImpl *This = impl_from_IClassFactory(iface);
408 TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid));
410 *ppvObj = NULL;
412 if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
413 *ppvObj = This;
414 InterlockedIncrement(&This->ref);
415 return S_OK;
418 TRACE("-- E_NOINTERFACE\n");
419 return E_NOINTERFACE;
421 /******************************************************************************
422 * IDefClF_fnAddRef
424 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
426 IDefClFImpl *This = impl_from_IClassFactory(iface);
427 ULONG refCount = InterlockedIncrement(&This->ref);
429 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
431 return refCount;
433 /******************************************************************************
434 * IDefClF_fnRelease
436 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
438 IDefClFImpl *This = impl_from_IClassFactory(iface);
439 ULONG refCount = InterlockedDecrement(&This->ref);
441 TRACE("(%p)->(count=%u)\n", This, refCount + 1);
443 if (!refCount)
445 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
447 TRACE("-- destroying IClassFactory(%p)\n",This);
448 heap_free(This);
451 return refCount;
453 /******************************************************************************
454 * IDefClF_fnCreateInstance
456 static HRESULT WINAPI IDefClF_fnCreateInstance(
457 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
459 IDefClFImpl *This = impl_from_IClassFactory(iface);
461 TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject);
463 *ppvObject = NULL;
465 if ( This->riidInst==NULL ||
466 IsEqualCLSID(riid, This->riidInst) ||
467 IsEqualCLSID(riid, &IID_IUnknown) )
469 return This->lpfnCI(pUnkOuter, riid, ppvObject);
472 ERR("unknown IID requested %s\n",shdebugstr_guid(riid));
473 return E_NOINTERFACE;
475 /******************************************************************************
476 * IDefClF_fnLockServer
478 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
480 IDefClFImpl *This = impl_from_IClassFactory(iface);
481 TRACE("%p->(0x%x), not implemented\n",This, fLock);
482 return E_NOTIMPL;
485 static const IClassFactoryVtbl dclfvt =
487 IDefClF_fnQueryInterface,
488 IDefClF_fnAddRef,
489 IDefClF_fnRelease,
490 IDefClF_fnCreateInstance,
491 IDefClF_fnLockServer
494 /******************************************************************************
495 * SHCreateDefClassObject [SHELL32.70]
497 HRESULT WINAPI SHCreateDefClassObject(
498 REFIID riid,
499 LPVOID* ppv,
500 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
501 LPDWORD pcRefDll, /* [in/out] ref count of the dll */
502 REFIID riidInst) /* [in] optional interface to the instance */
504 IClassFactory * pcf;
506 TRACE("%s %p %p %p %s\n",
507 shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst));
509 if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE;
510 if (! (pcf = IDefClF_fnConstructor(lpfnCI, (PLONG)pcRefDll, riidInst))) return E_OUTOFMEMORY;
511 *ppv = pcf;
512 return S_OK;
515 /*************************************************************************
516 * DragAcceptFiles [SHELL32.@]
518 void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
520 LONG exstyle;
522 if( !IsWindow(hWnd) ) return;
523 exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
524 if (b)
525 exstyle |= WS_EX_ACCEPTFILES;
526 else
527 exstyle &= ~WS_EX_ACCEPTFILES;
528 SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
531 /*************************************************************************
532 * DragFinish [SHELL32.@]
534 void WINAPI DragFinish(HDROP h)
536 TRACE("\n");
537 GlobalFree(h);
540 /*************************************************************************
541 * DragQueryPoint [SHELL32.@]
543 BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
545 DROPFILES *lpDropFileStruct;
546 BOOL bRet;
548 TRACE("\n");
550 lpDropFileStruct = GlobalLock(hDrop);
552 *p = lpDropFileStruct->pt;
553 bRet = !lpDropFileStruct->fNC;
555 GlobalUnlock(hDrop);
556 return bRet;
559 /*************************************************************************
560 * DragQueryFileA [SHELL32.@]
561 * DragQueryFile [SHELL32.@]
563 UINT WINAPI DragQueryFileA(
564 HDROP hDrop,
565 UINT lFile,
566 LPSTR lpszFile,
567 UINT lLength)
569 LPSTR lpDrop;
570 UINT i = 0;
571 DROPFILES *lpDropFileStruct = GlobalLock(hDrop);
573 TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
575 if(!lpDropFileStruct) goto end;
577 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
579 if(lpDropFileStruct->fWide) {
580 LPWSTR lpszFileW = NULL;
582 if(lpszFile && lFile != 0xFFFFFFFF) {
583 lpszFileW = heap_alloc(lLength*sizeof(WCHAR));
584 if(lpszFileW == NULL) {
585 goto end;
588 i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength);
590 if(lpszFileW) {
591 WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL);
592 heap_free(lpszFileW);
594 goto end;
597 while (i++ < lFile)
599 while (*lpDrop++); /* skip filename */
600 if (!*lpDrop)
602 i = (lFile == 0xFFFFFFFF) ? i : 0;
603 goto end;
607 i = strlen(lpDrop);
608 if (!lpszFile ) goto end; /* needed buffer size */
609 lstrcpynA (lpszFile, lpDrop, lLength);
610 end:
611 GlobalUnlock(hDrop);
612 return i;
615 /*************************************************************************
616 * DragQueryFileW [SHELL32.@]
618 UINT WINAPI DragQueryFileW(
619 HDROP hDrop,
620 UINT lFile,
621 LPWSTR lpszwFile,
622 UINT lLength)
624 LPWSTR lpwDrop;
625 UINT i = 0;
626 DROPFILES *lpDropFileStruct = GlobalLock(hDrop);
628 TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
630 if(!lpDropFileStruct) goto end;
632 lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles);
634 if(lpDropFileStruct->fWide == FALSE) {
635 LPSTR lpszFileA = NULL;
637 if(lpszwFile && lFile != 0xFFFFFFFF) {
638 lpszFileA = heap_alloc(lLength);
639 if(lpszFileA == NULL) {
640 goto end;
643 i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength);
645 if(lpszFileA) {
646 MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength);
647 heap_free(lpszFileA);
649 goto end;
652 i = 0;
653 while (i++ < lFile)
655 while (*lpwDrop++); /* skip filename */
656 if (!*lpwDrop)
658 i = (lFile == 0xFFFFFFFF) ? i : 0;
659 goto end;
663 i = lstrlenW(lpwDrop);
664 if ( !lpszwFile) goto end; /* needed buffer size */
665 lstrcpynW (lpszwFile, lpwDrop, lLength);
666 end:
667 GlobalUnlock(hDrop);
668 return i;
671 /*************************************************************************
672 * SHPropStgCreate [SHELL32.685]
674 HRESULT WINAPI SHPropStgCreate(IPropertySetStorage *psstg, REFFMTID fmtid,
675 const CLSID *pclsid, DWORD grfFlags, DWORD grfMode,
676 DWORD dwDisposition, IPropertyStorage **ppstg, UINT *puCodePage)
678 PROPSPEC prop;
679 PROPVARIANT ret;
680 HRESULT hres;
682 TRACE("%p %s %s %x %x %x %p %p\n", psstg, debugstr_guid(fmtid), debugstr_guid(pclsid),
683 grfFlags, grfMode, dwDisposition, ppstg, puCodePage);
685 hres = IPropertySetStorage_Open(psstg, fmtid, grfMode, ppstg);
687 switch(dwDisposition) {
688 case CREATE_ALWAYS:
689 if(SUCCEEDED(hres)) {
690 IPropertyStorage_Release(*ppstg);
691 hres = IPropertySetStorage_Delete(psstg, fmtid);
692 if(FAILED(hres))
693 return hres;
694 hres = E_FAIL;
697 case OPEN_ALWAYS:
698 case CREATE_NEW:
699 if(FAILED(hres))
700 hres = IPropertySetStorage_Create(psstg, fmtid, pclsid,
701 grfFlags, grfMode, ppstg);
703 case OPEN_EXISTING:
704 if(FAILED(hres))
705 return hres;
707 if(puCodePage) {
708 prop.ulKind = PRSPEC_PROPID;
709 prop.u.propid = PID_CODEPAGE;
710 hres = IPropertyStorage_ReadMultiple(*ppstg, 1, &prop, &ret);
711 if(FAILED(hres) || ret.vt!=VT_I2)
712 *puCodePage = 0;
713 else
714 *puCodePage = ret.iVal;
718 return S_OK;
721 /*************************************************************************
722 * SHPropStgReadMultiple [SHELL32.688]
724 HRESULT WINAPI SHPropStgReadMultiple(IPropertyStorage *pps, UINT uCodePage,
725 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar)
727 STATPROPSETSTG stat;
728 HRESULT hres;
730 FIXME("%p %u %u %p %p\n", pps, uCodePage, cpspec, rgpspec, rgvar);
732 memset(rgvar, 0, cpspec*sizeof(PROPVARIANT));
733 hres = IPropertyStorage_ReadMultiple(pps, cpspec, rgpspec, rgvar);
734 if(FAILED(hres))
735 return hres;
737 if(!uCodePage) {
738 PROPSPEC prop;
739 PROPVARIANT ret;
741 prop.ulKind = PRSPEC_PROPID;
742 prop.u.propid = PID_CODEPAGE;
743 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret);
744 if(FAILED(hres) || ret.vt!=VT_I2)
745 return S_OK;
747 uCodePage = ret.iVal;
750 hres = IPropertyStorage_Stat(pps, &stat);
751 if(FAILED(hres))
752 return S_OK;
754 /* TODO: do something with codepage and stat */
755 return S_OK;
758 /*************************************************************************
759 * SHPropStgWriteMultiple [SHELL32.689]
761 HRESULT WINAPI SHPropStgWriteMultiple(IPropertyStorage *pps, UINT *uCodePage,
762 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar, PROPID propidNameFirst)
764 STATPROPSETSTG stat;
765 UINT codepage;
766 HRESULT hres;
768 FIXME("%p %p %u %p %p %d\n", pps, uCodePage, cpspec, rgpspec, rgvar, propidNameFirst);
770 hres = IPropertyStorage_Stat(pps, &stat);
771 if(FAILED(hres))
772 return hres;
774 if(uCodePage && *uCodePage)
775 codepage = *uCodePage;
776 else {
777 PROPSPEC prop;
778 PROPVARIANT ret;
780 prop.ulKind = PRSPEC_PROPID;
781 prop.u.propid = PID_CODEPAGE;
782 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret);
783 if(FAILED(hres))
784 return hres;
785 if(ret.vt!=VT_I2 || !ret.iVal)
786 return E_FAIL;
788 codepage = ret.iVal;
789 if(uCodePage)
790 *uCodePage = codepage;
793 /* TODO: do something with codepage and stat */
795 hres = IPropertyStorage_WriteMultiple(pps, cpspec, rgpspec, rgvar, propidNameFirst);
796 return hres;
799 /*************************************************************************
800 * SHCreateQueryCancelAutoPlayMoniker [SHELL32.@]
802 HRESULT WINAPI SHCreateQueryCancelAutoPlayMoniker(IMoniker **moniker)
804 TRACE("%p\n", moniker);
806 if (!moniker) return E_INVALIDARG;
807 return CreateClassMoniker(&CLSID_QueryCancelAutoPlay, moniker);
810 static HRESULT gpstatus_to_hresult(GpStatus status)
812 switch (status)
814 case Ok:
815 return S_OK;
816 case InvalidParameter:
817 return E_INVALIDARG;
818 case OutOfMemory:
819 return E_OUTOFMEMORY;
820 case NotImplemented:
821 return E_NOTIMPL;
822 default:
823 return E_FAIL;
827 /* IShellImageData */
828 typedef struct
830 IShellImageData IShellImageData_iface;
831 LONG ref;
833 WCHAR *path;
834 GpImage *image;
835 } ShellImageData;
837 static inline ShellImageData *impl_from_IShellImageData(IShellImageData *iface)
839 return CONTAINING_RECORD(iface, ShellImageData, IShellImageData_iface);
842 static HRESULT WINAPI ShellImageData_QueryInterface(IShellImageData *iface, REFIID riid, void **obj)
844 ShellImageData *This = impl_from_IShellImageData(iface);
846 TRACE("%p, %s, %p\n", This, debugstr_guid(riid), obj);
848 if (IsEqualIID(riid, &IID_IShellImageData) || IsEqualIID(riid, &IID_IUnknown))
850 *obj = &This->IShellImageData_iface;
851 IShellImageData_AddRef(iface);
852 return S_OK;
855 *obj = NULL;
856 return E_NOINTERFACE;
859 static ULONG WINAPI ShellImageData_AddRef(IShellImageData *iface)
861 ShellImageData *This = impl_from_IShellImageData(iface);
862 ULONG ref = InterlockedIncrement(&This->ref);
864 TRACE("%p, %u\n", This, ref);
866 return ref;
869 static ULONG WINAPI ShellImageData_Release(IShellImageData *iface)
871 ShellImageData *This = impl_from_IShellImageData(iface);
872 ULONG ref = InterlockedDecrement(&This->ref);
874 TRACE("%p, %u\n", This, ref);
876 if (!ref)
878 GdipDisposeImage(This->image);
879 heap_free(This->path);
880 SHFree(This);
883 return ref;
886 static HRESULT WINAPI ShellImageData_Decode(IShellImageData *iface, DWORD flags, ULONG cx_desired, ULONG cy_desired)
888 ShellImageData *This = impl_from_IShellImageData(iface);
889 GpImage *image;
890 HRESULT hr;
892 TRACE("%p, %#x, %u, %u\n", This, flags, cx_desired, cy_desired);
894 if (This->image)
895 return S_FALSE;
897 if (flags & SHIMGDEC_LOADFULL)
898 FIXME("LOADFULL flag ignored\n");
900 hr = gpstatus_to_hresult(GdipLoadImageFromFile(This->path, &image));
901 if (FAILED(hr))
902 return hr;
904 if (flags & SHIMGDEC_THUMBNAIL)
906 hr = gpstatus_to_hresult(GdipGetImageThumbnail(image, cx_desired, cy_desired, &This->image, NULL, NULL));
907 GdipDisposeImage(image);
909 else
910 This->image = image;
912 return hr;
915 static HRESULT WINAPI ShellImageData_Draw(IShellImageData *iface, HDC hdc, RECT *dest, RECT *src)
917 ShellImageData *This = impl_from_IShellImageData(iface);
918 GpGraphics *graphics;
919 HRESULT hr;
921 TRACE("%p, %p, %s, %s\n", This, hdc, wine_dbgstr_rect(dest), wine_dbgstr_rect(src));
923 if (!This->image)
924 return E_FAIL;
926 if (!dest)
927 return E_INVALIDARG;
929 if (!src)
930 return S_OK;
932 hr = gpstatus_to_hresult(GdipCreateFromHDC(hdc, &graphics));
933 if (FAILED(hr))
934 return hr;
936 hr = gpstatus_to_hresult(GdipDrawImageRectRectI(graphics, This->image, dest->left, dest->top, dest->right - dest->left,
937 dest->bottom - dest->top, src->left, src->top, src->right - src->left, src->bottom - src->top,
938 UnitPixel, NULL, NULL, NULL));
939 GdipDeleteGraphics(graphics);
941 return hr;
944 static HRESULT WINAPI ShellImageData_NextFrame(IShellImageData *iface)
946 ShellImageData *This = impl_from_IShellImageData(iface);
948 FIXME("%p: stub\n", This);
950 return E_NOTIMPL;
953 static HRESULT WINAPI ShellImageData_NextPage(IShellImageData *iface)
955 ShellImageData *This = impl_from_IShellImageData(iface);
957 FIXME("%p: stub\n", This);
959 return E_NOTIMPL;
962 static HRESULT WINAPI ShellImageData_PrevPage(IShellImageData *iface)
964 ShellImageData *This = impl_from_IShellImageData(iface);
966 FIXME("%p: stub\n", This);
968 return E_NOTIMPL;
971 static HRESULT WINAPI ShellImageData_IsTransparent(IShellImageData *iface)
973 ShellImageData *This = impl_from_IShellImageData(iface);
975 FIXME("%p: stub\n", This);
977 return E_NOTIMPL;
980 static HRESULT WINAPI ShellImageData_IsAnimated(IShellImageData *iface)
982 ShellImageData *This = impl_from_IShellImageData(iface);
984 FIXME("%p: stub\n", This);
986 return E_NOTIMPL;
989 static HRESULT WINAPI ShellImageData_IsVector(IShellImageData *iface)
991 ShellImageData *This = impl_from_IShellImageData(iface);
993 FIXME("%p: stub\n", This);
995 return E_NOTIMPL;
998 static HRESULT WINAPI ShellImageData_IsMultipage(IShellImageData *iface)
1000 ShellImageData *This = impl_from_IShellImageData(iface);
1002 FIXME("%p: stub\n", This);
1004 return E_NOTIMPL;
1007 static HRESULT WINAPI ShellImageData_IsEditable(IShellImageData *iface)
1009 ShellImageData *This = impl_from_IShellImageData(iface);
1011 FIXME("%p: stub\n", This);
1013 return E_NOTIMPL;
1016 static HRESULT WINAPI ShellImageData_IsPrintable(IShellImageData *iface)
1018 ShellImageData *This = impl_from_IShellImageData(iface);
1020 FIXME("%p: stub\n", This);
1022 return E_NOTIMPL;
1025 static HRESULT WINAPI ShellImageData_IsDecoded(IShellImageData *iface)
1027 ShellImageData *This = impl_from_IShellImageData(iface);
1029 FIXME("%p: stub\n", This);
1031 return E_NOTIMPL;
1034 static HRESULT WINAPI ShellImageData_GetCurrentPage(IShellImageData *iface, ULONG *page)
1036 ShellImageData *This = impl_from_IShellImageData(iface);
1038 FIXME("%p: stub\n", This);
1040 return E_NOTIMPL;
1043 static HRESULT WINAPI ShellImageData_GetPageCount(IShellImageData *iface, ULONG *count)
1045 ShellImageData *This = impl_from_IShellImageData(iface);
1047 FIXME("%p, %p: stub\n", This, count);
1049 return E_NOTIMPL;
1052 static HRESULT WINAPI ShellImageDate_SelectPage(IShellImageData *iface, ULONG page)
1054 ShellImageData *This = impl_from_IShellImageData(iface);
1056 FIXME("%p, %u: stub\n", This, page);
1058 return E_NOTIMPL;
1061 static HRESULT WINAPI ShellImageData_GetSize(IShellImageData *iface, SIZE *size)
1063 ShellImageData *This = impl_from_IShellImageData(iface);
1064 REAL cx, cy;
1065 HRESULT hr;
1067 TRACE("%p, %p\n", This, size);
1069 if (!This->image)
1070 return E_FAIL;
1072 hr = gpstatus_to_hresult(GdipGetImageDimension(This->image, &cx, &cy));
1073 if (SUCCEEDED(hr))
1075 size->cx = cx;
1076 size->cy = cy;
1079 return hr;
1082 static HRESULT WINAPI ShellImageData_GetRawDataFormat(IShellImageData *iface, GUID *format)
1084 ShellImageData *This = impl_from_IShellImageData(iface);
1086 FIXME("%p, %p: stub\n", This, format);
1088 return E_NOTIMPL;
1091 static HRESULT WINAPI ShellImageData_GetPixelFormat(IShellImageData *iface, PixelFormat *format)
1093 ShellImageData *This = impl_from_IShellImageData(iface);
1095 FIXME("%p, %p: stub\n", This, format);
1097 return E_NOTIMPL;
1100 static HRESULT WINAPI ShellImageData_GetDelay(IShellImageData *iface, DWORD *delay)
1102 ShellImageData *This = impl_from_IShellImageData(iface);
1104 FIXME("%p, %p: stub\n", This, delay);
1106 return E_NOTIMPL;
1109 static HRESULT WINAPI ShellImageData_GetProperties(IShellImageData *iface, DWORD mode, IPropertySetStorage **props)
1111 ShellImageData *This = impl_from_IShellImageData(iface);
1113 FIXME("%p, %#x, %p: stub\n", This, mode, props);
1115 return E_NOTIMPL;
1118 static HRESULT WINAPI ShellImageData_Rotate(IShellImageData *iface, DWORD angle)
1120 ShellImageData *This = impl_from_IShellImageData(iface);
1122 FIXME("%p, %u: stub\n", This, angle);
1124 return E_NOTIMPL;
1127 static HRESULT WINAPI ShellImageData_Scale(IShellImageData *iface, ULONG cx, ULONG cy, InterpolationMode mode)
1129 ShellImageData *This = impl_from_IShellImageData(iface);
1131 FIXME("%p, %u, %u, %#x: stub\n", This, cx, cy, mode);
1133 return E_NOTIMPL;
1136 static HRESULT WINAPI ShellImageData_DiscardEdit(IShellImageData *iface)
1138 ShellImageData *This = impl_from_IShellImageData(iface);
1140 FIXME("%p: stub\n", This);
1142 return E_NOTIMPL;
1145 static HRESULT WINAPI ShellImageDate_SetEncoderParams(IShellImageData *iface, IPropertyBag *params)
1147 ShellImageData *This = impl_from_IShellImageData(iface);
1149 FIXME("%p, %p: stub\n", This, params);
1151 return E_NOTIMPL;
1154 static HRESULT WINAPI ShellImageData_DisplayName(IShellImageData *iface, LPWSTR name, UINT count)
1156 ShellImageData *This = impl_from_IShellImageData(iface);
1158 FIXME("%p, %p, %u: stub\n", This, name, count);
1160 return E_NOTIMPL;
1163 static HRESULT WINAPI ShellImageData_GetResolution(IShellImageData *iface, ULONG *res_x, ULONG *res_y)
1165 ShellImageData *This = impl_from_IShellImageData(iface);
1167 FIXME("%p, %p, %p: stub\n", This, res_x, res_y);
1169 return E_NOTIMPL;
1172 static HRESULT WINAPI ShellImageData_GetEncoderParams(IShellImageData *iface, GUID *format, EncoderParameters **params)
1174 ShellImageData *This = impl_from_IShellImageData(iface);
1176 FIXME("%p, %p, %p: stub\n", This, format, params);
1178 return E_NOTIMPL;
1181 static HRESULT WINAPI ShellImageData_RegisterAbort(IShellImageData *iface, IShellImageDataAbort *abort,
1182 IShellImageDataAbort **prev)
1184 ShellImageData *This = impl_from_IShellImageData(iface);
1186 FIXME("%p, %p, %p: stub\n", This, abort, prev);
1188 return E_NOTIMPL;
1191 static HRESULT WINAPI ShellImageData_CloneFrame(IShellImageData *iface, Image **frame)
1193 ShellImageData *This = impl_from_IShellImageData(iface);
1195 FIXME("%p, %p: stub\n", This, frame);
1197 return E_NOTIMPL;
1200 static HRESULT WINAPI ShellImageData_ReplaceFrame(IShellImageData *iface, Image *frame)
1202 ShellImageData *This = impl_from_IShellImageData(iface);
1204 FIXME("%p, %p: stub\n", This, frame);
1206 return E_NOTIMPL;
1209 static const IShellImageDataVtbl ShellImageDataVtbl =
1211 ShellImageData_QueryInterface,
1212 ShellImageData_AddRef,
1213 ShellImageData_Release,
1214 ShellImageData_Decode,
1215 ShellImageData_Draw,
1216 ShellImageData_NextFrame,
1217 ShellImageData_NextPage,
1218 ShellImageData_PrevPage,
1219 ShellImageData_IsTransparent,
1220 ShellImageData_IsAnimated,
1221 ShellImageData_IsVector,
1222 ShellImageData_IsMultipage,
1223 ShellImageData_IsEditable,
1224 ShellImageData_IsPrintable,
1225 ShellImageData_IsDecoded,
1226 ShellImageData_GetCurrentPage,
1227 ShellImageData_GetPageCount,
1228 ShellImageDate_SelectPage,
1229 ShellImageData_GetSize,
1230 ShellImageData_GetRawDataFormat,
1231 ShellImageData_GetPixelFormat,
1232 ShellImageData_GetDelay,
1233 ShellImageData_GetProperties,
1234 ShellImageData_Rotate,
1235 ShellImageData_Scale,
1236 ShellImageData_DiscardEdit,
1237 ShellImageDate_SetEncoderParams,
1238 ShellImageData_DisplayName,
1239 ShellImageData_GetResolution,
1240 ShellImageData_GetEncoderParams,
1241 ShellImageData_RegisterAbort,
1242 ShellImageData_CloneFrame,
1243 ShellImageData_ReplaceFrame,
1246 static HRESULT create_shellimagedata_from_path(const WCHAR *path, IShellImageData **data)
1248 ShellImageData *This;
1250 This = SHAlloc(sizeof(*This));
1252 This->IShellImageData_iface.lpVtbl = &ShellImageDataVtbl;
1253 This->ref = 1;
1255 This->path = strdupW(path);
1256 This->image = NULL;
1258 *data = &This->IShellImageData_iface;
1259 return S_OK;
1262 /* IShellImageDataFactory */
1263 static HRESULT WINAPI ShellImageDataFactory_QueryInterface(IShellImageDataFactory *iface, REFIID riid, void **obj)
1265 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), obj);
1267 if (IsEqualIID(&IID_IShellImageDataFactory, riid) || IsEqualIID(&IID_IUnknown, riid))
1269 *obj = iface;
1271 else
1273 FIXME("not implemented for %s\n", debugstr_guid(riid));
1274 *obj = NULL;
1275 return E_NOINTERFACE;
1278 IUnknown_AddRef((IUnknown*)*obj);
1279 return S_OK;
1282 static ULONG WINAPI ShellImageDataFactory_AddRef(IShellImageDataFactory *iface)
1284 TRACE("(%p)\n", iface);
1286 return 2;
1289 static ULONG WINAPI ShellImageDataFactory_Release(IShellImageDataFactory *iface)
1291 TRACE("(%p)\n", iface);
1293 return 1;
1296 static HRESULT WINAPI ShellImageDataFactory_CreateIShellImageData(IShellImageDataFactory *iface, IShellImageData **data)
1298 FIXME("%p, %p: stub\n", iface, data);
1300 return E_NOTIMPL;
1303 static HRESULT WINAPI ShellImageDataFactory_CreateImageFromFile(IShellImageDataFactory *iface, const WCHAR *path,
1304 IShellImageData **data)
1306 TRACE("%p, %s, %p\n", iface, debugstr_w(path), data);
1308 return create_shellimagedata_from_path(path, data);
1311 static HRESULT WINAPI ShellImageDataFactory_CreateImageFromStream(IShellImageDataFactory *iface, IStream *stream,
1312 IShellImageData **data)
1314 FIXME("%p, %p, %p: stub\n", iface, stream, data);
1316 return E_NOTIMPL;
1319 static HRESULT WINAPI ShellImageDataFactory_GetDataFormatFromPath(IShellImageDataFactory *iface, const WCHAR *path,
1320 GUID *format)
1322 FIXME("%p, %s, %p: stub\n", iface, debugstr_w(path), format);
1324 return E_NOTIMPL;
1327 static const IShellImageDataFactoryVtbl ShellImageDataFactoryVtbl =
1329 ShellImageDataFactory_QueryInterface,
1330 ShellImageDataFactory_AddRef,
1331 ShellImageDataFactory_Release,
1332 ShellImageDataFactory_CreateIShellImageData,
1333 ShellImageDataFactory_CreateImageFromFile,
1334 ShellImageDataFactory_CreateImageFromStream,
1335 ShellImageDataFactory_GetDataFormatFromPath,
1338 static IShellImageDataFactory ShellImageDataFactory = { &ShellImageDataFactoryVtbl };
1340 HRESULT WINAPI ShellImageDataFactory_Constructor(IUnknown *outer, REFIID riid, void **obj)
1342 TRACE("%p %s %p\n", outer, debugstr_guid(riid), obj);
1344 if (outer)
1345 return CLASS_E_NOAGGREGATION;
1347 return IShellImageDataFactory_QueryInterface(&ShellImageDataFactory, riid, obj);