2 * IEnumMoniker implementation for DEVENUM.dll
4 * Copyright (C) 2002 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * - Implements IEnumMoniker interface which enumerates through moniker
22 * objects created from HKEY_CLASSES/CLSID/{DEVICE_CLSID}/Instance
25 #include "devenum_private.h"
29 #include "wine/debug.h"
32 /* #define ICOM_THIS_From_IROTData(class, name) class* This = (class*)(((char*)name)-sizeof(void*)) */
34 WINE_DEFAULT_DEBUG_CHANNEL(devenum
);
36 static ULONG WINAPI
DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface
);
37 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Hash(LPMONIKER iface
, DWORD
* pdwHash
);
38 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface
);
39 static ULONG WINAPI
DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface
);
41 static HRESULT WINAPI
DEVENUM_IPropertyBag_QueryInterface(
46 ICOM_THIS(RegPropBagImpl
, iface
);
47 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
49 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
51 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
52 IsEqualGUID(riid
, &IID_IPropertyBag
))
54 *ppvObj
= (LPVOID
)iface
;
55 DEVENUM_IPropertyBag_AddRef(iface
);
59 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
63 /**********************************************************************
64 * DEVENUM_IPropertyBag_AddRef (also IUnknown)
66 static ULONG WINAPI
DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface
)
68 ICOM_THIS(RegPropBagImpl
, iface
);
71 return InterlockedIncrement(&This
->ref
);
74 /**********************************************************************
75 * DEVENUM_IPropertyBag_Release (also IUnknown)
77 static ULONG WINAPI
DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface
)
79 ICOM_THIS(RegPropBagImpl
, iface
);
83 if (InterlockedDecrement(&This
->ref
) == 0) {
84 RegCloseKey(This
->hkey
);
91 static HRESULT WINAPI
DEVENUM_IPropertyBag_Read(
93 LPCOLESTR pszPropName
,
100 ICOM_THIS(RegPropBagImpl
, iface
);
104 TRACE("(%p)->(%s, %p, %p)\n", This
, debugstr_w(pszPropName
), pVar
, pErrorLog
);
106 if (!pszPropName
|| !pVar
)
109 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, NULL
, NULL
, &received
);
110 res
= HRESULT_FROM_WIN32(reswin32
);
114 pData
= HeapAlloc(GetProcessHeap(), 0, received
);
116 /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
117 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, &type
, pData
, &received
);
118 res
= HRESULT_FROM_WIN32(reswin32
);
123 res
= E_INVALIDARG
; /* assume we cannot coerce into right type */
125 TRACE("Read %ld bytes (%s)\n", received
, type
== REG_SZ
? debugstr_w((LPWSTR
)pData
) : "binary data");
133 V_UNION(pVar
, bstrVal
) = CoTaskMemAlloc(received
);
134 memcpy(V_UNION(pVar
, bstrVal
), (LPWSTR
)pData
, received
);
138 V_VT(pVar
) = VT_BSTR
;
141 V_UNION(pVar
, bstrVal
) = SysAllocStringLen((LPWSTR
)pData
, received
/sizeof(WCHAR
) - 1);
147 TRACE("REG_DWORD: %lx\n", *(DWORD
*)pData
);
155 V_UNION(pVar
, ulVal
) = *(DWORD
*)pData
;
162 SAFEARRAYBOUND bound
;
163 void * pArrayElements
;
165 bound
.cElements
= received
;
166 TRACE("REG_BINARY: len = %ld\n", received
);
170 case VT_ARRAY
| VT_UI1
:
171 if (!(V_UNION(pVar
, parray
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
177 if (res
== E_INVALIDARG
)
180 res
= SafeArrayAccessData(V_UNION(pVar
, parray
), &pArrayElements
);
184 CopyMemory(pArrayElements
, pData
, received
);
185 res
= SafeArrayUnaccessData(V_UNION(pVar
, parray
));
189 if (res
== E_INVALIDARG
)
190 FIXME("Variant type %x not supported for regtype %lx\n", V_VT(pVar
), type
);
194 HeapFree(GetProcessHeap(), 0, pData
);
196 TRACE("<- %lx\n", res
);
200 static HRESULT WINAPI
DEVENUM_IPropertyBag_Write(
202 LPCOLESTR pszPropName
,
205 ICOM_THIS(RegPropBagImpl
, iface
);
206 LPVOID lpData
= NULL
;
211 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(pszPropName
), pVar
);
216 TRACE("writing %s\n", debugstr_w(V_UNION(pVar
, bstrVal
)));
217 lpData
= (LPVOID
)V_UNION(pVar
, bstrVal
);
219 cbData
= (lstrlenW(V_UNION(pVar
, bstrVal
)) + 1) * sizeof(WCHAR
);
223 TRACE("writing %lu\n", V_UNION(pVar
, ulVal
));
224 lpData
= (LPVOID
)&V_UNION(pVar
, ulVal
);
226 cbData
= sizeof(DWORD
);
228 case VT_ARRAY
| VT_UI1
:
233 res
= SafeArrayGetLBound(V_UNION(pVar
, parray
), 1, &lLbound
);
234 res
= SafeArrayGetUBound(V_UNION(pVar
, parray
), 1, &lUbound
);
235 cbData
= (lUbound
- lLbound
+ 1) /* * sizeof(BYTE)*/;
236 TRACE("cbData: %ld\n", cbData
);
237 res
= SafeArrayAccessData(V_UNION(pVar
, parray
), &lpData
);
241 FIXME("Variant type %d not handled\n", V_VT(pVar
));
245 if (RegSetValueExW(This
->hkey
,
247 dwType
, lpData
, cbData
) != ERROR_SUCCESS
)
250 if (V_VT(pVar
) & VT_ARRAY
)
251 res
= SafeArrayUnaccessData(V_UNION(pVar
, parray
));
256 static ICOM_VTABLE(IPropertyBag
) IPropertyBag_Vtbl
=
258 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
259 DEVENUM_IPropertyBag_QueryInterface
,
260 DEVENUM_IPropertyBag_AddRef
,
261 DEVENUM_IPropertyBag_Release
,
262 DEVENUM_IPropertyBag_Read
,
263 DEVENUM_IPropertyBag_Write
268 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_QueryInterface(
273 ICOM_THIS(MediaCatMoniker
, iface
);
274 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
276 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
280 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
281 IsEqualGUID(riid
, &IID_IPersist
) ||
282 IsEqualGUID(riid
, &IID_IPersistStream
) ||
283 IsEqualGUID(riid
, &IID_IMoniker
))
285 *ppvObj
= (LPVOID
)iface
;
286 DEVENUM_IMediaCatMoniker_AddRef(iface
);
290 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
291 return E_NOINTERFACE
;
294 /**********************************************************************
295 * DEVENUM_IMediaCatMoniker_AddRef (also IUnknown)
297 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface
)
299 ICOM_THIS(MediaCatMoniker
, iface
);
302 if (This
== NULL
) return E_POINTER
;
307 /**********************************************************************
308 * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
310 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface
)
312 ICOM_THIS(MediaCatMoniker
, iface
);
316 if (This
== NULL
) return E_POINTER
;
320 RegCloseKey(This
->hkey
);
326 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetClassID(
330 ICOM_THIS(MediaCatMoniker
, iface
);
331 FIXME("(%p)->(%p)\n", This
, pClassID
);
333 if (pClassID
== NULL
)
339 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsDirty(LPMONIKER iface
)
346 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Load(LPMONIKER iface
, IStream
* pStm
)
348 FIXME("(%p)\n", pStm
);
353 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Save(LPMONIKER iface
, IStream
* pStm
, BOOL fClearDirty
)
355 FIXME("(%p, %s)\n", pStm
, fClearDirty
? "true" : "false");
357 return STG_E_CANTSAVE
;
360 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetSizeMax(
362 ULARGE_INTEGER
* pcbSize
)
364 FIXME("(%p)\n", pcbSize
);
366 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
371 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToObject(
378 IUnknown
* pObj
= NULL
;
379 IPropertyBag
* pProp
= NULL
;
382 HRESULT res
= E_FAIL
;
384 ICOM_THIS(MediaCatMoniker
, iface
);
388 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riidResult
), ppvResult
);
394 /* first activation of this class */
396 res
=IMoniker_BindToStorage(iface
, NULL
, NULL
, &IID_IPropertyBag
, &pvptr
);
397 pProp
= (IPropertyBag
*)pvptr
;
400 V_VT(&var
) = VT_LPWSTR
;
401 res
= IPropertyBag_Read(pProp
, clsid_keyname
, &var
, NULL
);
405 res
= CLSIDFromString(V_UNION(&var
,bstrVal
), &clsID
);
406 CoTaskMemFree(V_UNION(&var
, bstrVal
));
410 res
=CoCreateInstance(&clsID
,NULL
,CLSCTX_ALL
,&IID_IUnknown
,&pvptr
);
411 pObj
= (IUnknown
*)pvptr
;
417 /* get the requested interface from the loaded class */
418 res
= IUnknown_QueryInterface(pObj
,riidResult
,ppvResult
);
423 IPropertyBag_Release(pProp
);
426 TRACE("<- 0x%lx\n", res
);
431 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToStorage(
438 ICOM_THIS(MediaCatMoniker
, iface
);
439 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvObj
);
443 if (pbc
|| pmkToLeft
)
444 return MK_E_NOSTORAGE
;
446 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
448 RegPropBagImpl
* rpb
= CoTaskMemAlloc(sizeof(RegPropBagImpl
));
450 return E_OUTOFMEMORY
;
451 rpb
->lpVtbl
= &IPropertyBag_Vtbl
;
452 DuplicateHandle(GetCurrentProcess(), This
->hkey
, GetCurrentProcess(), (LPHANDLE
)&(rpb
->hkey
), 0, 0, DUPLICATE_SAME_ACCESS
);
454 *ppvObj
= (LPVOID
)rpb
;
458 return MK_E_NOSTORAGE
;
461 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Reduce(
464 DWORD dwReduceHowFar
,
465 IMoniker
** ppmkToLeft
,
466 IMoniker
** ppmkReduced
)
468 TRACE("(%p, %ld, %p, %p)\n", pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
472 *ppmkReduced
= iface
;
474 return MK_S_REDUCED_TO_SELF
;
477 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ComposeWith(
480 BOOL fOnlyIfNotGeneric
,
481 IMoniker
** ppmkComposite
)
483 FIXME("(%p, %s, %p): stub\n", pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
485 /* FIXME: use CreateGenericComposite? */
486 *ppmkComposite
= NULL
;
491 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Enum(
494 IEnumMoniker
** ppenumMoniker
)
496 FIXME("(%s, %p): stub\n", fForward
? "true" : "false", ppenumMoniker
);
498 *ppenumMoniker
= NULL
;
503 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsEqual(
505 IMoniker
* pmkOtherMoniker
)
507 FIXME("(%p)\n", pmkOtherMoniker
);
512 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Hash(
516 TRACE("(%p)\n", pdwHash
);
523 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsRunning(
527 IMoniker
* pmkNewlyRunning
)
529 FIXME("(%p, %p, %p)\n", pbc
, pmkToLeft
, pmkNewlyRunning
);
534 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(
540 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pFileTime
);
542 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
543 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
545 return MK_E_UNAVAILABLE
;
548 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Inverse(
552 TRACE("(%p)\n", ppmk
);
556 return MK_E_NOINVERSE
;
559 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_CommonPrefixWith(
561 IMoniker
* pmkOtherMoniker
,
562 IMoniker
** ppmkPrefix
)
564 TRACE("(%p, %p)\n", pmkOtherMoniker
, ppmkPrefix
);
568 return MK_E_NOPREFIX
;
571 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_RelativePathTo(
574 IMoniker
** ppmkRelPath
)
576 TRACE("(%p, %p)\n", pmkOther
, ppmkRelPath
);
578 *ppmkRelPath
= pmkOther
;
583 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetDisplayName(
587 LPOLESTR
* ppszDisplayName
)
589 ICOM_THIS(MediaCatMoniker
, iface
);
590 WCHAR wszBuffer
[MAX_PATH
];
591 static const WCHAR wszFriendlyName
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
592 LONG received
= sizeof(wszFriendlyName
);
594 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, ppszDisplayName
);
596 *ppszDisplayName
= NULL
;
598 /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
599 if (RegQueryValueW(This
->hkey
, wszFriendlyName
, wszBuffer
, &received
) == ERROR_SUCCESS
)
601 *ppszDisplayName
= CoTaskMemAlloc(received
);
602 strcpyW(*ppszDisplayName
, wszBuffer
);
609 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ParseDisplayName(
613 LPOLESTR pszDisplayName
,
617 FIXME("(%p, %p, %s, %p, %p)\n", pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
625 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsSystemMoniker(
629 TRACE("(%p)\n", pdwMksys
);
634 static ICOM_VTABLE(IMoniker
) IMoniker_Vtbl
=
636 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
637 DEVENUM_IMediaCatMoniker_QueryInterface
,
638 DEVENUM_IMediaCatMoniker_AddRef
,
639 DEVENUM_IMediaCatMoniker_Release
,
640 DEVENUM_IMediaCatMoniker_GetClassID
,
641 DEVENUM_IMediaCatMoniker_IsDirty
,
642 DEVENUM_IMediaCatMoniker_Load
,
643 DEVENUM_IMediaCatMoniker_Save
,
644 DEVENUM_IMediaCatMoniker_GetSizeMax
,
645 DEVENUM_IMediaCatMoniker_BindToObject
,
646 DEVENUM_IMediaCatMoniker_BindToStorage
,
647 DEVENUM_IMediaCatMoniker_Reduce
,
648 DEVENUM_IMediaCatMoniker_ComposeWith
,
649 DEVENUM_IMediaCatMoniker_Enum
,
650 DEVENUM_IMediaCatMoniker_IsEqual
,
651 DEVENUM_IMediaCatMoniker_Hash
,
652 DEVENUM_IMediaCatMoniker_IsRunning
,
653 DEVENUM_IMediaCatMoniker_GetTimeOfLastChange
,
654 DEVENUM_IMediaCatMoniker_Inverse
,
655 DEVENUM_IMediaCatMoniker_CommonPrefixWith
,
656 DEVENUM_IMediaCatMoniker_RelativePathTo
,
657 DEVENUM_IMediaCatMoniker_GetDisplayName
,
658 DEVENUM_IMediaCatMoniker_ParseDisplayName
,
659 DEVENUM_IMediaCatMoniker_IsSystemMoniker
662 MediaCatMoniker
* DEVENUM_IMediaCatMoniker_Construct()
664 MediaCatMoniker
* pMoniker
= NULL
;
665 pMoniker
= CoTaskMemAlloc(sizeof(MediaCatMoniker
));
669 pMoniker
->lpVtbl
= &IMoniker_Vtbl
;
671 pMoniker
->hkey
= NULL
;
673 DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER
)pMoniker
);
678 /**********************************************************************
679 * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
681 static HRESULT WINAPI
DEVENUM_IEnumMoniker_QueryInterface(
686 ICOM_THIS(EnumMonikerImpl
, iface
);
687 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
689 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
691 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
692 IsEqualGUID(riid
, &IID_IEnumMoniker
))
694 *ppvObj
= (LPVOID
)iface
;
695 DEVENUM_IEnumMoniker_AddRef(iface
);
699 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
700 return E_NOINTERFACE
;
703 /**********************************************************************
704 * DEVENUM_IEnumMoniker_AddRef (also IUnknown)
706 static ULONG WINAPI
DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface
)
708 ICOM_THIS(EnumMonikerImpl
, iface
);
712 if (This
== NULL
) return E_POINTER
;
714 return InterlockedIncrement(&This
->ref
);
717 /**********************************************************************
718 * DEVENUM_IEnumMoniker_Release (also IUnknown)
720 static ULONG WINAPI
DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface
)
722 ICOM_THIS(EnumMonikerImpl
, iface
);
726 if (!InterlockedDecrement(&This
->ref
))
728 RegCloseKey(This
->hkey
);
735 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface
, ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFetched
)
737 WCHAR buffer
[MAX_PATH
+ 1];
740 MediaCatMoniker
* pMoniker
;
741 ICOM_THIS(EnumMonikerImpl
, iface
);
743 TRACE("(%ld, %p, %p)\n", celt
, rgelt
, pceltFetched
);
745 while (fetched
< celt
)
747 res
= RegEnumKeyW(This
->hkey
, This
->index
, buffer
, sizeof(buffer
) / sizeof(WCHAR
));
748 if (res
!= ERROR_SUCCESS
)
752 pMoniker
= DEVENUM_IMediaCatMoniker_Construct();
754 return E_OUTOFMEMORY
;
756 if (RegOpenKeyW(This
->hkey
, buffer
, &pMoniker
->hkey
) != ERROR_SUCCESS
)
758 DEVENUM_IMediaCatMoniker_Release((LPMONIKER
)pMoniker
);
761 rgelt
[fetched
] = (LPMONIKER
)pMoniker
;
765 This
->index
+= fetched
;
767 TRACE("-- fetched %ld\n", fetched
);
770 *pceltFetched
= fetched
;
778 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Skip(LPENUMMONIKER iface
, ULONG celt
)
780 ICOM_THIS(EnumMonikerImpl
, iface
);
782 TRACE("(%ld)\n", celt
);
789 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface
)
791 ICOM_THIS(EnumMonikerImpl
, iface
);
800 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Clone(LPENUMMONIKER iface
, IEnumMoniker
** ppenum
)
802 FIXME("(%p): stub\n", ppenum
);
807 /**********************************************************************
810 ICOM_VTABLE(IEnumMoniker
) IEnumMoniker_Vtbl
=
812 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
813 DEVENUM_IEnumMoniker_QueryInterface
,
814 DEVENUM_IEnumMoniker_AddRef
,
815 DEVENUM_IEnumMoniker_Release
,
816 DEVENUM_IEnumMoniker_Next
,
817 DEVENUM_IEnumMoniker_Skip
,
818 DEVENUM_IEnumMoniker_Reset
,
819 DEVENUM_IEnumMoniker_Clone