msado15: Semi-stub _Recordset get/put Filter.
[wine.git] / dlls / shell32 / shellole.c
blob29d973bf1656158694e050939e9669599d9b019b
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 "shell32_main.h"
44 #include "wine/debug.h"
45 #include "shlwapi.h"
46 #include "debughlp.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(shell);
50 extern INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax); /* shlwapi.24 */
51 static HRESULT WINAPI ShellImageDataFactory_Constructor(IUnknown *outer, REFIID riid, void **obj);
53 /**************************************************************************
54 * Default ClassFactory types
56 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
57 static IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst);
59 /* this table contains all CLSIDs of shell32 objects */
60 static const struct {
61 REFIID clsid;
62 LPFNCREATEINSTANCE lpfnCI;
63 } InterfaceTable[] = {
65 {&CLSID_ApplicationAssociationRegistration, ApplicationAssociationRegistration_Constructor},
66 {&CLSID_ApplicationDestinations, ApplicationDestinations_Constructor},
67 {&CLSID_ApplicationDocumentLists, ApplicationDocumentLists_Constructor},
68 {&CLSID_AutoComplete, IAutoComplete_Constructor},
69 {&CLSID_ControlPanel, IControlPanel_Constructor},
70 {&CLSID_DragDropHelper, IDropTargetHelper_Constructor},
71 {&CLSID_FolderShortcut, FolderShortcut_Constructor},
72 {&CLSID_MyComputer, ISF_MyComputer_Constructor},
73 {&CLSID_MyDocuments, MyDocuments_Constructor},
74 {&CLSID_NetworkPlaces, ISF_NetworkPlaces_Constructor},
75 {&CLSID_Printers, Printers_Constructor},
76 {&CLSID_QueryAssociations, QueryAssociations_Constructor},
77 {&CLSID_RecycleBin, RecycleBin_Constructor},
78 {&CLSID_ShellDesktop, ISF_Desktop_Constructor},
79 {&CLSID_ShellFSFolder, IFSFolder_Constructor},
80 {&CLSID_ShellItem, IShellItem_Constructor},
81 {&CLSID_ShellLink, IShellLink_Constructor},
82 {&CLSID_UnixDosFolder, UnixDosFolder_Constructor},
83 {&CLSID_UnixFolder, UnixFolder_Constructor},
84 {&CLSID_ExplorerBrowser,ExplorerBrowser_Constructor},
85 {&CLSID_KnownFolderManager, KnownFolderManager_Constructor},
86 {&CLSID_Shell, IShellDispatch_Constructor},
87 {&CLSID_DestinationList, CustomDestinationList_Constructor},
88 {&CLSID_ShellImageDataFactory, ShellImageDataFactory_Constructor},
89 {&CLSID_FileOperation, IFileOperation_Constructor},
90 {&CLSID_ActiveDesktop, ActiveDesktop_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%08lx\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%08lx) 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("%lu 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%08lx\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 = malloc(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=%lu)\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=%lu)\n", This, refCount + 1);
443 if (!refCount)
445 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
447 TRACE("-- destroying IClassFactory(%p)\n",This);
448 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(HDROP hDrop, UINT lFile, LPSTR lpszFile, UINT lLength)
565 LPWSTR filenameW = NULL;
566 LPSTR filename = NULL;
567 UINT i;
569 TRACE("(%p, %x, %p, %u)\n", hDrop, lFile, lpszFile, lLength);
571 i = DragQueryFileW(hDrop, lFile, NULL, 0);
572 if (!i || lFile == 0xFFFFFFFF) goto end;
573 filenameW = malloc((i + 1) * sizeof(WCHAR));
574 if (!filenameW) goto error;
575 if (!DragQueryFileW(hDrop, lFile, filenameW, i + 1)) goto error;
577 i = WideCharToMultiByte(CP_ACP, 0, filenameW, -1, NULL, 0, NULL, NULL);
578 if (!lpszFile || !lLength)
580 /* minus a trailing null */
581 i--;
582 goto end;
584 filename = malloc(i);
585 if (!filename) goto error;
586 i = WideCharToMultiByte(CP_ACP, 0, filenameW, -1, filename, i, NULL, NULL);
588 lstrcpynA(lpszFile, filename, lLength);
589 i = min(i, lLength) - 1;
590 end:
591 free(filenameW);
592 free(filename);
593 return i;
594 error:
595 i = 0;
596 goto end;
599 /*************************************************************************
600 * DragQueryFileW [SHELL32.@]
602 UINT WINAPI DragQueryFileW(
603 HDROP hDrop,
604 UINT lFile,
605 LPWSTR lpszwFile,
606 UINT lLength)
608 LPWSTR buffer = NULL;
609 LPCWSTR filename;
610 UINT i = 0;
611 const DROPFILES *lpDropFileStruct = GlobalLock(hDrop);
613 TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
615 if(!lpDropFileStruct) goto end;
617 if(lpDropFileStruct->fWide)
619 LPCWSTR p = (LPCWSTR) ((LPCSTR)lpDropFileStruct + lpDropFileStruct->pFiles);
620 while (i++ < lFile)
622 while (*p++); /* skip filename */
623 if (!*p)
625 i = (lFile == 0xFFFFFFFF) ? i : 0;
626 goto end;
629 filename = p;
631 else
633 LPCSTR p = (LPCSTR)lpDropFileStruct + lpDropFileStruct->pFiles;
634 while (i++ < lFile)
636 while (*p++); /* skip filename */
637 if (!*p)
639 i = (lFile == 0xFFFFFFFF) ? i : 0;
640 goto end;
643 i = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
644 buffer = malloc(i * sizeof(WCHAR));
645 if (!buffer)
647 i = 0;
648 goto end;
650 MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, i);
651 filename = buffer;
654 i = lstrlenW(filename);
655 if (!lpszwFile || !lLength) goto end; /* needed buffer size */
656 lstrcpynW(lpszwFile, filename, lLength);
657 i = min(i, lLength - 1);
658 end:
659 GlobalUnlock(hDrop);
660 free(buffer);
661 return i;
664 /*************************************************************************
665 * SHPropStgCreate [SHELL32.685]
667 HRESULT WINAPI SHPropStgCreate(IPropertySetStorage *psstg, REFFMTID fmtid,
668 const CLSID *pclsid, DWORD grfFlags, DWORD grfMode,
669 DWORD dwDisposition, IPropertyStorage **ppstg, UINT *puCodePage)
671 PROPSPEC prop;
672 PROPVARIANT ret;
673 HRESULT hres;
675 TRACE("%p %s %s %lx %lx %lx %p %p\n", psstg, debugstr_guid(fmtid), debugstr_guid(pclsid),
676 grfFlags, grfMode, dwDisposition, ppstg, puCodePage);
678 hres = IPropertySetStorage_Open(psstg, fmtid, grfMode, ppstg);
680 switch(dwDisposition) {
681 case CREATE_ALWAYS:
682 if(SUCCEEDED(hres)) {
683 IPropertyStorage_Release(*ppstg);
684 hres = IPropertySetStorage_Delete(psstg, fmtid);
685 if(FAILED(hres))
686 return hres;
687 hres = E_FAIL;
690 case OPEN_ALWAYS:
691 case CREATE_NEW:
692 if(FAILED(hres))
693 hres = IPropertySetStorage_Create(psstg, fmtid, pclsid,
694 grfFlags, grfMode, ppstg);
696 case OPEN_EXISTING:
697 if(FAILED(hres))
698 return hres;
700 if(puCodePage) {
701 prop.ulKind = PRSPEC_PROPID;
702 prop.u.propid = PID_CODEPAGE;
703 hres = IPropertyStorage_ReadMultiple(*ppstg, 1, &prop, &ret);
704 if(FAILED(hres) || ret.vt!=VT_I2)
705 *puCodePage = 0;
706 else
707 *puCodePage = ret.iVal;
711 return S_OK;
714 /*************************************************************************
715 * SHPropStgReadMultiple [SHELL32.688]
717 HRESULT WINAPI SHPropStgReadMultiple(IPropertyStorage *pps, UINT uCodePage,
718 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar)
720 STATPROPSETSTG stat;
721 HRESULT hres;
723 FIXME("%p %u %lu %p %p\n", pps, uCodePage, cpspec, rgpspec, rgvar);
725 memset(rgvar, 0, cpspec*sizeof(PROPVARIANT));
726 hres = IPropertyStorage_ReadMultiple(pps, cpspec, rgpspec, rgvar);
727 if(FAILED(hres))
728 return hres;
730 if(!uCodePage) {
731 PROPSPEC prop;
732 PROPVARIANT ret;
734 prop.ulKind = PRSPEC_PROPID;
735 prop.u.propid = PID_CODEPAGE;
736 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret);
737 if(FAILED(hres) || ret.vt!=VT_I2)
738 return S_OK;
740 uCodePage = ret.iVal;
743 hres = IPropertyStorage_Stat(pps, &stat);
744 if(FAILED(hres))
745 return S_OK;
747 /* TODO: do something with codepage and stat */
748 return S_OK;
751 /*************************************************************************
752 * SHPropStgWriteMultiple [SHELL32.689]
754 HRESULT WINAPI SHPropStgWriteMultiple(IPropertyStorage *pps, UINT *uCodePage,
755 ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgvar, PROPID propidNameFirst)
757 STATPROPSETSTG stat;
758 UINT codepage;
759 HRESULT hres;
761 FIXME("%p %p %lu %p %p %ld\n", pps, uCodePage, cpspec, rgpspec, rgvar, propidNameFirst);
763 hres = IPropertyStorage_Stat(pps, &stat);
764 if(FAILED(hres))
765 return hres;
767 if(uCodePage && *uCodePage)
768 codepage = *uCodePage;
769 else {
770 PROPSPEC prop;
771 PROPVARIANT ret;
773 prop.ulKind = PRSPEC_PROPID;
774 prop.u.propid = PID_CODEPAGE;
775 hres = IPropertyStorage_ReadMultiple(pps, 1, &prop, &ret);
776 if(FAILED(hres))
777 return hres;
778 if(ret.vt!=VT_I2 || !ret.iVal)
779 return E_FAIL;
781 codepage = ret.iVal;
782 if(uCodePage)
783 *uCodePage = codepage;
786 /* TODO: do something with codepage and stat */
788 hres = IPropertyStorage_WriteMultiple(pps, cpspec, rgpspec, rgvar, propidNameFirst);
789 return hres;
792 /*************************************************************************
793 * SHCreateQueryCancelAutoPlayMoniker [SHELL32.@]
795 HRESULT WINAPI SHCreateQueryCancelAutoPlayMoniker(IMoniker **moniker)
797 TRACE("%p\n", moniker);
799 if (!moniker) return E_INVALIDARG;
800 return CreateClassMoniker(&CLSID_QueryCancelAutoPlay, moniker);
803 static HRESULT gpstatus_to_hresult(GpStatus status)
805 switch (status)
807 case Ok:
808 return S_OK;
809 case InvalidParameter:
810 return E_INVALIDARG;
811 case OutOfMemory:
812 return E_OUTOFMEMORY;
813 case NotImplemented:
814 return E_NOTIMPL;
815 default:
816 return E_FAIL;
820 /* IShellImageData */
821 typedef struct
823 IShellImageData IShellImageData_iface;
824 LONG ref;
826 WCHAR *path;
827 GpImage *image;
828 } ShellImageData;
830 static inline ShellImageData *impl_from_IShellImageData(IShellImageData *iface)
832 return CONTAINING_RECORD(iface, ShellImageData, IShellImageData_iface);
835 static HRESULT WINAPI ShellImageData_QueryInterface(IShellImageData *iface, REFIID riid, void **obj)
837 ShellImageData *This = impl_from_IShellImageData(iface);
839 TRACE("%p, %s, %p\n", This, debugstr_guid(riid), obj);
841 if (IsEqualIID(riid, &IID_IShellImageData) || IsEqualIID(riid, &IID_IUnknown))
843 *obj = &This->IShellImageData_iface;
844 IShellImageData_AddRef(iface);
845 return S_OK;
848 *obj = NULL;
849 return E_NOINTERFACE;
852 static ULONG WINAPI ShellImageData_AddRef(IShellImageData *iface)
854 ShellImageData *This = impl_from_IShellImageData(iface);
855 ULONG ref = InterlockedIncrement(&This->ref);
857 TRACE("%p, %lu\n", This, ref);
859 return ref;
862 static ULONG WINAPI ShellImageData_Release(IShellImageData *iface)
864 ShellImageData *This = impl_from_IShellImageData(iface);
865 ULONG ref = InterlockedDecrement(&This->ref);
867 TRACE("%p, %lu\n", This, ref);
869 if (!ref)
871 GdipDisposeImage(This->image);
872 free(This->path);
873 free(This);
876 return ref;
879 static HRESULT WINAPI ShellImageData_Decode(IShellImageData *iface, DWORD flags, ULONG cx_desired, ULONG cy_desired)
881 ShellImageData *This = impl_from_IShellImageData(iface);
882 GpImage *image;
883 HRESULT hr;
885 TRACE("%p, %#lx, %lu, %lu\n", This, flags, cx_desired, cy_desired);
887 if (This->image)
888 return S_FALSE;
890 if (flags & SHIMGDEC_LOADFULL)
891 FIXME("LOADFULL flag ignored\n");
893 hr = gpstatus_to_hresult(GdipLoadImageFromFile(This->path, &image));
894 if (FAILED(hr))
895 return hr;
897 if (flags & SHIMGDEC_THUMBNAIL)
899 hr = gpstatus_to_hresult(GdipGetImageThumbnail(image, cx_desired, cy_desired, &This->image, NULL, NULL));
900 GdipDisposeImage(image);
902 else
903 This->image = image;
905 return hr;
908 static HRESULT WINAPI ShellImageData_Draw(IShellImageData *iface, HDC hdc, RECT *dest, RECT *src)
910 ShellImageData *This = impl_from_IShellImageData(iface);
911 GpGraphics *graphics;
912 HRESULT hr;
914 TRACE("%p, %p, %s, %s\n", This, hdc, wine_dbgstr_rect(dest), wine_dbgstr_rect(src));
916 if (!This->image)
917 return E_FAIL;
919 if (!dest)
920 return E_INVALIDARG;
922 if (!src)
923 return S_OK;
925 hr = gpstatus_to_hresult(GdipCreateFromHDC(hdc, &graphics));
926 if (FAILED(hr))
927 return hr;
929 hr = gpstatus_to_hresult(GdipDrawImageRectRectI(graphics, This->image, dest->left, dest->top, dest->right - dest->left,
930 dest->bottom - dest->top, src->left, src->top, src->right - src->left, src->bottom - src->top,
931 UnitPixel, NULL, NULL, NULL));
932 GdipDeleteGraphics(graphics);
934 return hr;
937 static HRESULT WINAPI ShellImageData_NextFrame(IShellImageData *iface)
939 ShellImageData *This = impl_from_IShellImageData(iface);
941 FIXME("%p: stub\n", This);
943 return E_NOTIMPL;
946 static HRESULT WINAPI ShellImageData_NextPage(IShellImageData *iface)
948 ShellImageData *This = impl_from_IShellImageData(iface);
950 FIXME("%p: stub\n", This);
952 return E_NOTIMPL;
955 static HRESULT WINAPI ShellImageData_PrevPage(IShellImageData *iface)
957 ShellImageData *This = impl_from_IShellImageData(iface);
959 FIXME("%p: stub\n", This);
961 return E_NOTIMPL;
964 static HRESULT WINAPI ShellImageData_IsTransparent(IShellImageData *iface)
966 ShellImageData *This = impl_from_IShellImageData(iface);
968 FIXME("%p: stub\n", This);
970 return E_NOTIMPL;
973 static HRESULT WINAPI ShellImageData_IsAnimated(IShellImageData *iface)
975 ShellImageData *This = impl_from_IShellImageData(iface);
977 FIXME("%p: stub\n", This);
979 return E_NOTIMPL;
982 static HRESULT WINAPI ShellImageData_IsVector(IShellImageData *iface)
984 ShellImageData *This = impl_from_IShellImageData(iface);
986 FIXME("%p: stub\n", This);
988 return E_NOTIMPL;
991 static HRESULT WINAPI ShellImageData_IsMultipage(IShellImageData *iface)
993 ShellImageData *This = impl_from_IShellImageData(iface);
995 FIXME("%p: stub\n", This);
997 return E_NOTIMPL;
1000 static HRESULT WINAPI ShellImageData_IsEditable(IShellImageData *iface)
1002 ShellImageData *This = impl_from_IShellImageData(iface);
1004 FIXME("%p: stub\n", This);
1006 return E_NOTIMPL;
1009 static HRESULT WINAPI ShellImageData_IsPrintable(IShellImageData *iface)
1011 ShellImageData *This = impl_from_IShellImageData(iface);
1013 FIXME("%p: stub\n", This);
1015 return E_NOTIMPL;
1018 static HRESULT WINAPI ShellImageData_IsDecoded(IShellImageData *iface)
1020 ShellImageData *This = impl_from_IShellImageData(iface);
1022 FIXME("%p: stub\n", This);
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI ShellImageData_GetCurrentPage(IShellImageData *iface, ULONG *page)
1029 ShellImageData *This = impl_from_IShellImageData(iface);
1031 FIXME("%p: stub\n", This);
1033 return E_NOTIMPL;
1036 static HRESULT WINAPI ShellImageData_GetPageCount(IShellImageData *iface, ULONG *count)
1038 ShellImageData *This = impl_from_IShellImageData(iface);
1040 FIXME("%p, %p: stub\n", This, count);
1042 return E_NOTIMPL;
1045 static HRESULT WINAPI ShellImageDate_SelectPage(IShellImageData *iface, ULONG page)
1047 ShellImageData *This = impl_from_IShellImageData(iface);
1049 FIXME("%p, %lu: stub\n", This, page);
1051 return E_NOTIMPL;
1054 static HRESULT WINAPI ShellImageData_GetSize(IShellImageData *iface, SIZE *size)
1056 ShellImageData *This = impl_from_IShellImageData(iface);
1057 REAL cx, cy;
1058 HRESULT hr;
1060 TRACE("%p, %p\n", This, size);
1062 if (!This->image)
1063 return E_FAIL;
1065 hr = gpstatus_to_hresult(GdipGetImageDimension(This->image, &cx, &cy));
1066 if (SUCCEEDED(hr))
1068 size->cx = cx;
1069 size->cy = cy;
1072 return hr;
1075 static HRESULT WINAPI ShellImageData_GetRawDataFormat(IShellImageData *iface, GUID *format)
1077 ShellImageData *This = impl_from_IShellImageData(iface);
1079 FIXME("%p, %p: stub\n", This, format);
1081 return E_NOTIMPL;
1084 static HRESULT WINAPI ShellImageData_GetPixelFormat(IShellImageData *iface, PixelFormat *format)
1086 ShellImageData *This = impl_from_IShellImageData(iface);
1088 FIXME("%p, %p: stub\n", This, format);
1090 return E_NOTIMPL;
1093 static HRESULT WINAPI ShellImageData_GetDelay(IShellImageData *iface, DWORD *delay)
1095 ShellImageData *This = impl_from_IShellImageData(iface);
1097 FIXME("%p, %p: stub\n", This, delay);
1099 return E_NOTIMPL;
1102 static HRESULT WINAPI ShellImageData_GetProperties(IShellImageData *iface, DWORD mode, IPropertySetStorage **props)
1104 ShellImageData *This = impl_from_IShellImageData(iface);
1106 FIXME("%p, %#lx, %p: stub\n", This, mode, props);
1108 return E_NOTIMPL;
1111 static HRESULT WINAPI ShellImageData_Rotate(IShellImageData *iface, DWORD angle)
1113 ShellImageData *This = impl_from_IShellImageData(iface);
1115 FIXME("%p, %lu: stub\n", This, angle);
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI ShellImageData_Scale(IShellImageData *iface, ULONG cx, ULONG cy, InterpolationMode mode)
1122 ShellImageData *This = impl_from_IShellImageData(iface);
1124 FIXME("%p, %lu, %lu, %#x: stub\n", This, cx, cy, mode);
1126 return E_NOTIMPL;
1129 static HRESULT WINAPI ShellImageData_DiscardEdit(IShellImageData *iface)
1131 ShellImageData *This = impl_from_IShellImageData(iface);
1133 FIXME("%p: stub\n", This);
1135 return E_NOTIMPL;
1138 static HRESULT WINAPI ShellImageDate_SetEncoderParams(IShellImageData *iface, IPropertyBag *params)
1140 ShellImageData *This = impl_from_IShellImageData(iface);
1142 FIXME("%p, %p: stub\n", This, params);
1144 return E_NOTIMPL;
1147 static HRESULT WINAPI ShellImageData_DisplayName(IShellImageData *iface, LPWSTR name, UINT count)
1149 ShellImageData *This = impl_from_IShellImageData(iface);
1151 FIXME("%p, %p, %u: stub\n", This, name, count);
1153 return E_NOTIMPL;
1156 static HRESULT WINAPI ShellImageData_GetResolution(IShellImageData *iface, ULONG *res_x, ULONG *res_y)
1158 ShellImageData *This = impl_from_IShellImageData(iface);
1160 FIXME("%p, %p, %p: stub\n", This, res_x, res_y);
1162 return E_NOTIMPL;
1165 static HRESULT WINAPI ShellImageData_GetEncoderParams(IShellImageData *iface, GUID *format, EncoderParameters **params)
1167 ShellImageData *This = impl_from_IShellImageData(iface);
1169 FIXME("%p, %p, %p: stub\n", This, format, params);
1171 return E_NOTIMPL;
1174 static HRESULT WINAPI ShellImageData_RegisterAbort(IShellImageData *iface, IShellImageDataAbort *abort,
1175 IShellImageDataAbort **prev)
1177 ShellImageData *This = impl_from_IShellImageData(iface);
1179 FIXME("%p, %p, %p: stub\n", This, abort, prev);
1181 return E_NOTIMPL;
1184 static HRESULT WINAPI ShellImageData_CloneFrame(IShellImageData *iface, Image **frame)
1186 ShellImageData *This = impl_from_IShellImageData(iface);
1188 FIXME("%p, %p: stub\n", This, frame);
1190 return E_NOTIMPL;
1193 static HRESULT WINAPI ShellImageData_ReplaceFrame(IShellImageData *iface, Image *frame)
1195 ShellImageData *This = impl_from_IShellImageData(iface);
1197 FIXME("%p, %p: stub\n", This, frame);
1199 return E_NOTIMPL;
1202 static const IShellImageDataVtbl ShellImageDataVtbl =
1204 ShellImageData_QueryInterface,
1205 ShellImageData_AddRef,
1206 ShellImageData_Release,
1207 ShellImageData_Decode,
1208 ShellImageData_Draw,
1209 ShellImageData_NextFrame,
1210 ShellImageData_NextPage,
1211 ShellImageData_PrevPage,
1212 ShellImageData_IsTransparent,
1213 ShellImageData_IsAnimated,
1214 ShellImageData_IsVector,
1215 ShellImageData_IsMultipage,
1216 ShellImageData_IsEditable,
1217 ShellImageData_IsPrintable,
1218 ShellImageData_IsDecoded,
1219 ShellImageData_GetCurrentPage,
1220 ShellImageData_GetPageCount,
1221 ShellImageDate_SelectPage,
1222 ShellImageData_GetSize,
1223 ShellImageData_GetRawDataFormat,
1224 ShellImageData_GetPixelFormat,
1225 ShellImageData_GetDelay,
1226 ShellImageData_GetProperties,
1227 ShellImageData_Rotate,
1228 ShellImageData_Scale,
1229 ShellImageData_DiscardEdit,
1230 ShellImageDate_SetEncoderParams,
1231 ShellImageData_DisplayName,
1232 ShellImageData_GetResolution,
1233 ShellImageData_GetEncoderParams,
1234 ShellImageData_RegisterAbort,
1235 ShellImageData_CloneFrame,
1236 ShellImageData_ReplaceFrame,
1239 static HRESULT create_shellimagedata_from_path(const WCHAR *path, IShellImageData **data)
1241 ShellImageData *This;
1243 This = malloc(sizeof(*This));
1245 This->IShellImageData_iface.lpVtbl = &ShellImageDataVtbl;
1246 This->ref = 1;
1248 This->path = wcsdup(path);
1249 This->image = NULL;
1251 *data = &This->IShellImageData_iface;
1252 return S_OK;
1255 /* IShellImageDataFactory */
1256 static HRESULT WINAPI ShellImageDataFactory_QueryInterface(IShellImageDataFactory *iface, REFIID riid, void **obj)
1258 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), obj);
1260 if (IsEqualIID(&IID_IShellImageDataFactory, riid) || IsEqualIID(&IID_IUnknown, riid))
1262 *obj = iface;
1264 else
1266 FIXME("not implemented for %s\n", debugstr_guid(riid));
1267 *obj = NULL;
1268 return E_NOINTERFACE;
1271 IUnknown_AddRef((IUnknown*)*obj);
1272 return S_OK;
1275 static ULONG WINAPI ShellImageDataFactory_AddRef(IShellImageDataFactory *iface)
1277 TRACE("(%p)\n", iface);
1279 return 2;
1282 static ULONG WINAPI ShellImageDataFactory_Release(IShellImageDataFactory *iface)
1284 TRACE("(%p)\n", iface);
1286 return 1;
1289 static HRESULT WINAPI ShellImageDataFactory_CreateIShellImageData(IShellImageDataFactory *iface, IShellImageData **data)
1291 FIXME("%p, %p: stub\n", iface, data);
1293 return E_NOTIMPL;
1296 static HRESULT WINAPI ShellImageDataFactory_CreateImageFromFile(IShellImageDataFactory *iface, const WCHAR *path,
1297 IShellImageData **data)
1299 TRACE("%p, %s, %p\n", iface, debugstr_w(path), data);
1301 return create_shellimagedata_from_path(path, data);
1304 static HRESULT WINAPI ShellImageDataFactory_CreateImageFromStream(IShellImageDataFactory *iface, IStream *stream,
1305 IShellImageData **data)
1307 FIXME("%p, %p, %p: stub\n", iface, stream, data);
1309 return E_NOTIMPL;
1312 static HRESULT WINAPI ShellImageDataFactory_GetDataFormatFromPath(IShellImageDataFactory *iface, const WCHAR *path,
1313 GUID *format)
1315 FIXME("%p, %s, %p: stub\n", iface, debugstr_w(path), format);
1317 return E_NOTIMPL;
1320 static const IShellImageDataFactoryVtbl ShellImageDataFactoryVtbl =
1322 ShellImageDataFactory_QueryInterface,
1323 ShellImageDataFactory_AddRef,
1324 ShellImageDataFactory_Release,
1325 ShellImageDataFactory_CreateIShellImageData,
1326 ShellImageDataFactory_CreateImageFromFile,
1327 ShellImageDataFactory_CreateImageFromStream,
1328 ShellImageDataFactory_GetDataFormatFromPath,
1331 static IShellImageDataFactory ShellImageDataFactory = { &ShellImageDataFactoryVtbl };
1333 HRESULT WINAPI ShellImageDataFactory_Constructor(IUnknown *outer, REFIID riid, void **obj)
1335 TRACE("%p %s %p\n", outer, debugstr_guid(riid), obj);
1337 if (outer)
1338 return CLASS_E_NOAGGREGATION;
1340 return IShellImageDataFactory_QueryInterface(&ShellImageDataFactory, riid, obj);