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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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"
31 WINE_DEFAULT_DEBUG_CHANNEL(devenum
);
33 static ULONG WINAPI
DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface
);
34 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface
);
35 static ULONG WINAPI
DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface
);
39 const IPropertyBagVtbl
*lpVtbl
;
45 static HRESULT WINAPI
DEVENUM_IPropertyBag_QueryInterface(
50 RegPropBagImpl
*This
= (RegPropBagImpl
*)iface
;
51 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
53 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
55 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
56 IsEqualGUID(riid
, &IID_IPropertyBag
))
58 *ppvObj
= (LPVOID
)iface
;
59 DEVENUM_IPropertyBag_AddRef(iface
);
63 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
67 /**********************************************************************
68 * DEVENUM_IPropertyBag_AddRef (also IUnknown)
70 static ULONG WINAPI
DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface
)
72 RegPropBagImpl
*This
= (RegPropBagImpl
*)iface
;
75 return InterlockedIncrement(&This
->ref
);
78 /**********************************************************************
79 * DEVENUM_IPropertyBag_Release (also IUnknown)
81 static ULONG WINAPI
DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface
)
83 RegPropBagImpl
*This
= (RegPropBagImpl
*)iface
;
88 ref
= InterlockedDecrement(&This
->ref
);
90 RegCloseKey(This
->hkey
);
92 DEVENUM_UnlockModule();
97 static HRESULT WINAPI
DEVENUM_IPropertyBag_Read(
99 LPCOLESTR pszPropName
,
101 IErrorLog
* pErrorLog
)
106 RegPropBagImpl
*This
= (RegPropBagImpl
*)iface
;
110 TRACE("(%p)->(%s, %p, %p)\n", This
, debugstr_w(pszPropName
), pVar
, pErrorLog
);
112 if (!pszPropName
|| !pVar
)
115 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, NULL
, NULL
, &received
);
116 res
= HRESULT_FROM_WIN32(reswin32
);
120 pData
= HeapAlloc(GetProcessHeap(), 0, received
);
122 /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
123 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, &type
, (LPBYTE
)pData
, &received
);
124 res
= HRESULT_FROM_WIN32(reswin32
);
129 res
= E_INVALIDARG
; /* assume we cannot coerce into right type */
131 TRACE("Read %d bytes (%s)\n", received
, type
== REG_SZ
? debugstr_w((LPWSTR
)pData
) : "binary data");
139 V_UNION(pVar
, bstrVal
) = CoTaskMemAlloc(received
);
140 memcpy(V_UNION(pVar
, bstrVal
), (LPWSTR
)pData
, received
);
144 V_VT(pVar
) = VT_BSTR
;
147 V_UNION(pVar
, bstrVal
) = SysAllocStringLen((LPWSTR
)pData
, received
/sizeof(WCHAR
) - 1);
153 TRACE("REG_DWORD: %x\n", *(DWORD
*)pData
);
161 V_UNION(pVar
, ulVal
) = *(DWORD
*)pData
;
168 SAFEARRAYBOUND bound
;
169 void * pArrayElements
;
171 bound
.cElements
= received
;
172 TRACE("REG_BINARY: len = %d\n", received
);
176 case VT_ARRAY
| VT_UI1
:
177 if (!(V_UNION(pVar
, parray
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
183 if (res
== E_INVALIDARG
)
186 res
= SafeArrayAccessData(V_UNION(pVar
, parray
), &pArrayElements
);
190 CopyMemory(pArrayElements
, pData
, received
);
191 res
= SafeArrayUnaccessData(V_UNION(pVar
, parray
));
195 if (res
== E_INVALIDARG
)
196 FIXME("Variant type %x not supported for regtype %x\n", V_VT(pVar
), type
);
199 HeapFree(GetProcessHeap(), 0, pData
);
201 TRACE("<- %x\n", res
);
205 static HRESULT WINAPI
DEVENUM_IPropertyBag_Write(
207 LPCOLESTR pszPropName
,
210 RegPropBagImpl
*This
= (RegPropBagImpl
*)iface
;
211 LPVOID lpData
= NULL
;
216 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(pszPropName
), pVar
);
221 TRACE("writing %s\n", debugstr_w(V_UNION(pVar
, bstrVal
)));
222 lpData
= (LPVOID
)V_UNION(pVar
, bstrVal
);
224 cbData
= (lstrlenW(V_UNION(pVar
, bstrVal
)) + 1) * sizeof(WCHAR
);
228 TRACE("writing %u\n", V_UNION(pVar
, ulVal
));
229 lpData
= (LPVOID
)&V_UNION(pVar
, ulVal
);
231 cbData
= sizeof(DWORD
);
233 case VT_ARRAY
| VT_UI1
:
238 res
= SafeArrayGetLBound(V_UNION(pVar
, parray
), 1, &lLbound
);
239 res
= SafeArrayGetUBound(V_UNION(pVar
, parray
), 1, &lUbound
);
240 cbData
= (lUbound
- lLbound
+ 1) /* * sizeof(BYTE)*/;
241 TRACE("cbData: %d\n", cbData
);
242 res
= SafeArrayAccessData(V_UNION(pVar
, parray
), &lpData
);
246 FIXME("Variant type %d not handled\n", V_VT(pVar
));
250 if (RegSetValueExW(This
->hkey
,
252 dwType
, lpData
, cbData
) != ERROR_SUCCESS
)
255 if (V_VT(pVar
) & VT_ARRAY
)
256 res
= SafeArrayUnaccessData(V_UNION(pVar
, parray
));
261 static const IPropertyBagVtbl IPropertyBag_Vtbl
=
263 DEVENUM_IPropertyBag_QueryInterface
,
264 DEVENUM_IPropertyBag_AddRef
,
265 DEVENUM_IPropertyBag_Release
,
266 DEVENUM_IPropertyBag_Read
,
267 DEVENUM_IPropertyBag_Write
270 static HRESULT
DEVENUM_IPropertyBag_Construct(HANDLE hkey
, IPropertyBag
**ppBag
)
272 RegPropBagImpl
* rpb
= CoTaskMemAlloc(sizeof(RegPropBagImpl
));
274 return E_OUTOFMEMORY
;
275 rpb
->lpVtbl
= &IPropertyBag_Vtbl
;
278 *ppBag
= (IPropertyBag
*)rpb
;
279 DEVENUM_LockModule();
284 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_QueryInterface(
289 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
290 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
292 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
296 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
297 IsEqualGUID(riid
, &IID_IPersist
) ||
298 IsEqualGUID(riid
, &IID_IPersistStream
) ||
299 IsEqualGUID(riid
, &IID_IMoniker
))
301 *ppvObj
= (LPVOID
)iface
;
302 DEVENUM_IMediaCatMoniker_AddRef(iface
);
306 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
307 return E_NOINTERFACE
;
310 /**********************************************************************
311 * DEVENUM_IMediaCatMoniker_AddRef (also IUnknown)
313 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface
)
315 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
318 return InterlockedIncrement(&This
->ref
);
321 /**********************************************************************
322 * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
324 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface
)
326 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
330 ref
= InterlockedDecrement(&This
->ref
);
332 RegCloseKey(This
->hkey
);
334 DEVENUM_UnlockModule();
339 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetClassID(
343 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
344 FIXME("(%p)->(%p)\n", This
, pClassID
);
346 if (pClassID
== NULL
)
352 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsDirty(LPMONIKER iface
)
359 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Load(LPMONIKER iface
, IStream
* pStm
)
361 FIXME("(%p)\n", pStm
);
366 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Save(LPMONIKER iface
, IStream
* pStm
, BOOL fClearDirty
)
368 FIXME("(%p, %s)\n", pStm
, fClearDirty
? "true" : "false");
370 return STG_E_CANTSAVE
;
373 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetSizeMax(
375 ULARGE_INTEGER
* pcbSize
)
377 FIXME("(%p)\n", pcbSize
);
379 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
384 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToObject(
391 IUnknown
* pObj
= NULL
;
392 IPropertyBag
* pProp
= NULL
;
395 HRESULT res
= E_FAIL
;
397 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
401 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riidResult
), ppvResult
);
407 /* first activation of this class */
409 res
=IMoniker_BindToStorage(iface
, NULL
, NULL
, &IID_IPropertyBag
, &pvptr
);
410 pProp
= (IPropertyBag
*)pvptr
;
413 V_VT(&var
) = VT_LPWSTR
;
414 res
= IPropertyBag_Read(pProp
, clsid_keyname
, &var
, NULL
);
418 res
= CLSIDFromString(V_UNION(&var
,bstrVal
), &clsID
);
419 CoTaskMemFree(V_UNION(&var
, bstrVal
));
423 res
=CoCreateInstance(&clsID
,NULL
,CLSCTX_ALL
,&IID_IUnknown
,&pvptr
);
424 pObj
= (IUnknown
*)pvptr
;
430 /* get the requested interface from the loaded class */
435 res2
= IUnknown_QueryInterface(pObj
, &IID_IPersistPropertyBag
, &ppv
);
436 if (SUCCEEDED(res2
)) {
437 res
= IPersistPropertyBag_Load((IPersistPropertyBag
*) ppv
, pProp
, NULL
);
438 IPersistPropertyBag_Release((IPersistPropertyBag
*) ppv
);
442 res
= IUnknown_QueryInterface(pObj
,riidResult
,ppvResult
);
443 IUnknown_Release(pObj
);
448 IPropertyBag_Release(pProp
);
451 TRACE("<- 0x%x\n", res
);
456 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToStorage(
463 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
464 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvObj
);
468 if (pbc
|| pmkToLeft
)
469 return MK_E_NOSTORAGE
;
471 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
474 DuplicateHandle(GetCurrentProcess(), This
->hkey
, GetCurrentProcess(), &hkey
, 0, 0, DUPLICATE_SAME_ACCESS
);
475 return DEVENUM_IPropertyBag_Construct(hkey
, (IPropertyBag
**)ppvObj
);
478 return MK_E_NOSTORAGE
;
481 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Reduce(
484 DWORD dwReduceHowFar
,
485 IMoniker
** ppmkToLeft
,
486 IMoniker
** ppmkReduced
)
488 TRACE("(%p, %d, %p, %p)\n", pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
492 *ppmkReduced
= iface
;
494 return MK_S_REDUCED_TO_SELF
;
497 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ComposeWith(
500 BOOL fOnlyIfNotGeneric
,
501 IMoniker
** ppmkComposite
)
503 FIXME("(%p, %s, %p): stub\n", pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
505 /* FIXME: use CreateGenericComposite? */
506 *ppmkComposite
= NULL
;
511 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Enum(
514 IEnumMoniker
** ppenumMoniker
)
516 FIXME("(%s, %p): stub\n", fForward
? "true" : "false", ppenumMoniker
);
518 *ppenumMoniker
= NULL
;
523 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsEqual(
525 IMoniker
* pmkOtherMoniker
)
527 FIXME("(%p)\n", pmkOtherMoniker
);
532 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Hash(
536 TRACE("(%p)\n", pdwHash
);
543 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsRunning(
547 IMoniker
* pmkNewlyRunning
)
549 FIXME("(%p, %p, %p)\n", pbc
, pmkToLeft
, pmkNewlyRunning
);
554 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(
560 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pFileTime
);
562 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
563 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
565 return MK_E_UNAVAILABLE
;
568 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Inverse(
572 TRACE("(%p)\n", ppmk
);
576 return MK_E_NOINVERSE
;
579 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_CommonPrefixWith(
581 IMoniker
* pmkOtherMoniker
,
582 IMoniker
** ppmkPrefix
)
584 TRACE("(%p, %p)\n", pmkOtherMoniker
, ppmkPrefix
);
588 return MK_E_NOPREFIX
;
591 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_RelativePathTo(
594 IMoniker
** ppmkRelPath
)
596 TRACE("(%p, %p)\n", pmkOther
, ppmkRelPath
);
598 *ppmkRelPath
= pmkOther
;
603 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetDisplayName(
607 LPOLESTR
* ppszDisplayName
)
609 MediaCatMoniker
*This
= (MediaCatMoniker
*)iface
;
610 WCHAR wszBuffer
[MAX_PATH
];
611 static const WCHAR wszFriendlyName
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
612 LONG received
= sizeof(wszFriendlyName
);
614 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, ppszDisplayName
);
616 *ppszDisplayName
= NULL
;
618 /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
619 if (RegQueryValueW(This
->hkey
, wszFriendlyName
, wszBuffer
, &received
) == ERROR_SUCCESS
)
621 *ppszDisplayName
= CoTaskMemAlloc(received
);
622 strcpyW(*ppszDisplayName
, wszBuffer
);
629 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ParseDisplayName(
633 LPOLESTR pszDisplayName
,
637 FIXME("(%p, %p, %s, %p, %p)\n", pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
645 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsSystemMoniker(
649 TRACE("(%p)\n", pdwMksys
);
654 static const IMonikerVtbl IMoniker_Vtbl
=
656 DEVENUM_IMediaCatMoniker_QueryInterface
,
657 DEVENUM_IMediaCatMoniker_AddRef
,
658 DEVENUM_IMediaCatMoniker_Release
,
659 DEVENUM_IMediaCatMoniker_GetClassID
,
660 DEVENUM_IMediaCatMoniker_IsDirty
,
661 DEVENUM_IMediaCatMoniker_Load
,
662 DEVENUM_IMediaCatMoniker_Save
,
663 DEVENUM_IMediaCatMoniker_GetSizeMax
,
664 DEVENUM_IMediaCatMoniker_BindToObject
,
665 DEVENUM_IMediaCatMoniker_BindToStorage
,
666 DEVENUM_IMediaCatMoniker_Reduce
,
667 DEVENUM_IMediaCatMoniker_ComposeWith
,
668 DEVENUM_IMediaCatMoniker_Enum
,
669 DEVENUM_IMediaCatMoniker_IsEqual
,
670 DEVENUM_IMediaCatMoniker_Hash
,
671 DEVENUM_IMediaCatMoniker_IsRunning
,
672 DEVENUM_IMediaCatMoniker_GetTimeOfLastChange
,
673 DEVENUM_IMediaCatMoniker_Inverse
,
674 DEVENUM_IMediaCatMoniker_CommonPrefixWith
,
675 DEVENUM_IMediaCatMoniker_RelativePathTo
,
676 DEVENUM_IMediaCatMoniker_GetDisplayName
,
677 DEVENUM_IMediaCatMoniker_ParseDisplayName
,
678 DEVENUM_IMediaCatMoniker_IsSystemMoniker
681 MediaCatMoniker
* DEVENUM_IMediaCatMoniker_Construct(void)
683 MediaCatMoniker
* pMoniker
= NULL
;
684 pMoniker
= CoTaskMemAlloc(sizeof(MediaCatMoniker
));
688 pMoniker
->lpVtbl
= &IMoniker_Vtbl
;
690 pMoniker
->hkey
= NULL
;
692 DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER
)pMoniker
);
694 DEVENUM_LockModule();
699 /**********************************************************************
700 * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
702 static HRESULT WINAPI
DEVENUM_IEnumMoniker_QueryInterface(
707 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
708 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
710 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
712 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
713 IsEqualGUID(riid
, &IID_IEnumMoniker
))
715 *ppvObj
= (LPVOID
)iface
;
716 DEVENUM_IEnumMoniker_AddRef(iface
);
720 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid
));
721 return E_NOINTERFACE
;
724 /**********************************************************************
725 * DEVENUM_IEnumMoniker_AddRef (also IUnknown)
727 static ULONG WINAPI
DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface
)
729 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
730 ULONG ref
= InterlockedIncrement(&This
->ref
);
732 TRACE("(%p)->() AddRef from %d\n", iface
, ref
- 1);
737 /**********************************************************************
738 * DEVENUM_IEnumMoniker_Release (also IUnknown)
740 static ULONG WINAPI
DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface
)
742 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
743 ULONG ref
= InterlockedDecrement(&This
->ref
);
745 TRACE("(%p)->() Release from %d\n", iface
, ref
+ 1);
749 RegCloseKey(This
->hkey
);
751 DEVENUM_UnlockModule();
757 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface
, ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFetched
)
759 WCHAR buffer
[MAX_PATH
+ 1];
762 MediaCatMoniker
* pMoniker
;
763 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
765 TRACE("(%p)->(%d, %p, %p)\n", iface
, celt
, rgelt
, pceltFetched
);
767 while (fetched
< celt
)
769 res
= RegEnumKeyW(This
->hkey
, This
->index
, buffer
, sizeof(buffer
) / sizeof(WCHAR
));
770 if (res
!= ERROR_SUCCESS
)
774 pMoniker
= DEVENUM_IMediaCatMoniker_Construct();
776 return E_OUTOFMEMORY
;
778 if (RegOpenKeyW(This
->hkey
, buffer
, &pMoniker
->hkey
) != ERROR_SUCCESS
)
780 DEVENUM_IMediaCatMoniker_Release((LPMONIKER
)pMoniker
);
783 rgelt
[fetched
] = (LPMONIKER
)pMoniker
;
787 This
->index
+= fetched
;
789 TRACE("-- fetched %d\n", fetched
);
792 *pceltFetched
= fetched
;
800 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Skip(LPENUMMONIKER iface
, ULONG celt
)
802 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
805 TRACE("(%p)->(%d)\n", iface
, celt
);
807 /* Before incrementing, check if there are any more values to run thru.
808 Some programs use the Skip() function to get the amount of devices */
809 if(RegQueryInfoKeyW(This
->hkey
, NULL
, NULL
, NULL
, &subKeys
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
813 if((This
->index
+ celt
) >= subKeys
)
823 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface
)
825 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
827 TRACE("(%p)->()\n", iface
);
834 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Clone(LPENUMMONIKER iface
, IEnumMoniker
** ppenum
)
836 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
841 /**********************************************************************
844 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
846 DEVENUM_IEnumMoniker_QueryInterface
,
847 DEVENUM_IEnumMoniker_AddRef
,
848 DEVENUM_IEnumMoniker_Release
,
849 DEVENUM_IEnumMoniker_Next
,
850 DEVENUM_IEnumMoniker_Skip
,
851 DEVENUM_IEnumMoniker_Reset
,
852 DEVENUM_IEnumMoniker_Clone
855 HRESULT
DEVENUM_IEnumMoniker_Construct(HKEY hkey
, IEnumMoniker
** ppEnumMoniker
)
857 EnumMonikerImpl
* pEnumMoniker
= CoTaskMemAlloc(sizeof(EnumMonikerImpl
));
859 return E_OUTOFMEMORY
;
861 pEnumMoniker
->lpVtbl
= &IEnumMoniker_Vtbl
;
862 pEnumMoniker
->ref
= 1;
863 pEnumMoniker
->index
= 0;
864 pEnumMoniker
->hkey
= hkey
;
866 *ppEnumMoniker
= (IEnumMoniker
*)pEnumMoniker
;
868 DEVENUM_LockModule();