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
);
35 IEnumMoniker IEnumMoniker_iface
;
45 IPropertyBag IPropertyBag_iface
;
51 static inline RegPropBagImpl
*impl_from_IPropertyBag(IPropertyBag
*iface
)
53 return CONTAINING_RECORD(iface
, RegPropBagImpl
, IPropertyBag_iface
);
56 static HRESULT WINAPI
DEVENUM_IPropertyBag_QueryInterface(
61 RegPropBagImpl
*This
= impl_from_IPropertyBag(iface
);
63 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppvObj
);
65 if (This
== NULL
|| ppvObj
== NULL
) return E_POINTER
;
67 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
68 IsEqualGUID(riid
, &IID_IPropertyBag
))
71 IPropertyBag_AddRef(iface
);
75 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
79 /**********************************************************************
80 * DEVENUM_IPropertyBag_AddRef (also IUnknown)
82 static ULONG WINAPI
DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface
)
84 RegPropBagImpl
*This
= impl_from_IPropertyBag(iface
);
86 TRACE("(%p)->() AddRef from %d\n", iface
, This
->ref
);
88 return InterlockedIncrement(&This
->ref
);
91 /**********************************************************************
92 * DEVENUM_IPropertyBag_Release (also IUnknown)
94 static ULONG WINAPI
DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface
)
96 RegPropBagImpl
*This
= impl_from_IPropertyBag(iface
);
99 TRACE("(%p)->() ReleaseThis->ref from %d\n", iface
, This
->ref
);
101 ref
= InterlockedDecrement(&This
->ref
);
103 RegCloseKey(This
->hkey
);
105 DEVENUM_UnlockModule();
110 static HRESULT WINAPI
DEVENUM_IPropertyBag_Read(
112 LPCOLESTR pszPropName
,
114 IErrorLog
* pErrorLog
)
119 RegPropBagImpl
*This
= impl_from_IPropertyBag(iface
);
123 TRACE("(%p)->(%s, %p, %p)\n", This
, debugstr_w(pszPropName
), pVar
, pErrorLog
);
125 if (!pszPropName
|| !pVar
)
128 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, NULL
, NULL
, &received
);
129 res
= HRESULT_FROM_WIN32(reswin32
);
133 pData
= HeapAlloc(GetProcessHeap(), 0, received
);
135 /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
136 reswin32
= RegQueryValueExW(This
->hkey
, pszPropName
, NULL
, &type
, pData
, &received
);
137 res
= HRESULT_FROM_WIN32(reswin32
);
142 res
= E_INVALIDARG
; /* assume we cannot coerce into right type */
144 TRACE("Read %d bytes (%s)\n", received
, type
== REG_SZ
? debugstr_w(pData
) : "binary data");
152 V_BSTR(pVar
) = CoTaskMemAlloc(received
);
153 memcpy(V_BSTR(pVar
), pData
, received
);
157 V_VT(pVar
) = VT_BSTR
;
160 V_BSTR(pVar
) = SysAllocStringLen(pData
, received
/sizeof(WCHAR
) - 1);
166 TRACE("REG_DWORD: %x\n", *(DWORD
*)pData
);
174 V_I4(pVar
) = *(DWORD
*)pData
;
181 SAFEARRAYBOUND bound
;
182 void * pArrayElements
;
184 bound
.cElements
= received
;
185 TRACE("REG_BINARY: len = %d\n", received
);
189 V_VT(pVar
) = VT_ARRAY
| VT_UI1
;
191 case VT_ARRAY
| VT_UI1
:
192 if (!(V_ARRAY(pVar
) = SafeArrayCreate(VT_UI1
, 1, &bound
)))
199 if (res
== E_INVALIDARG
)
202 res
= SafeArrayAccessData(V_ARRAY(pVar
), &pArrayElements
);
206 CopyMemory(pArrayElements
, pData
, received
);
207 res
= SafeArrayUnaccessData(V_ARRAY(pVar
));
211 if (res
== E_INVALIDARG
)
212 FIXME("Variant type %x not supported for regtype %x\n", V_VT(pVar
), type
);
215 HeapFree(GetProcessHeap(), 0, pData
);
217 TRACE("<- %x\n", res
);
221 static HRESULT WINAPI
DEVENUM_IPropertyBag_Write(
223 LPCOLESTR pszPropName
,
226 RegPropBagImpl
*This
= impl_from_IPropertyBag(iface
);
227 LPVOID lpData
= NULL
;
232 TRACE("(%p)->(%s, %p)\n", This
, debugstr_w(pszPropName
), pVar
);
238 TRACE("writing %s\n", debugstr_w(V_BSTR(pVar
)));
239 lpData
= V_BSTR(pVar
);
241 cbData
= (lstrlenW(V_BSTR(pVar
)) + 1) * sizeof(WCHAR
);
245 TRACE("writing %u\n", V_UI4(pVar
));
246 lpData
= &V_UI4(pVar
);
248 cbData
= sizeof(DWORD
);
250 case VT_ARRAY
| VT_UI1
:
255 res
= SafeArrayGetLBound(V_ARRAY(pVar
), 1, &lLbound
);
256 res
= SafeArrayGetUBound(V_ARRAY(pVar
), 1, &lUbound
);
257 cbData
= (lUbound
- lLbound
+ 1) /* * sizeof(BYTE)*/;
258 TRACE("cbData: %d\n", cbData
);
259 res
= SafeArrayAccessData(V_ARRAY(pVar
), &lpData
);
263 FIXME("Variant type %d not handled\n", V_VT(pVar
));
267 if (RegSetValueExW(This
->hkey
,
269 dwType
, lpData
, cbData
) != ERROR_SUCCESS
)
272 if (V_VT(pVar
) & VT_ARRAY
)
273 res
= SafeArrayUnaccessData(V_ARRAY(pVar
));
278 static const IPropertyBagVtbl IPropertyBag_Vtbl
=
280 DEVENUM_IPropertyBag_QueryInterface
,
281 DEVENUM_IPropertyBag_AddRef
,
282 DEVENUM_IPropertyBag_Release
,
283 DEVENUM_IPropertyBag_Read
,
284 DEVENUM_IPropertyBag_Write
287 static HRESULT
DEVENUM_IPropertyBag_Construct(HANDLE hkey
, IPropertyBag
**ppBag
)
289 RegPropBagImpl
* rpb
= CoTaskMemAlloc(sizeof(RegPropBagImpl
));
291 return E_OUTOFMEMORY
;
292 rpb
->IPropertyBag_iface
.lpVtbl
= &IPropertyBag_Vtbl
;
295 *ppBag
= &rpb
->IPropertyBag_iface
;
296 DEVENUM_LockModule();
301 static inline MediaCatMoniker
*impl_from_IMoniker(IMoniker
*iface
)
303 return CONTAINING_RECORD(iface
, MediaCatMoniker
, IMoniker_iface
);
306 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_QueryInterface(IMoniker
*iface
, REFIID riid
,
309 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid
));
314 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
315 IsEqualGUID(riid
, &IID_IPersist
) ||
316 IsEqualGUID(riid
, &IID_IPersistStream
) ||
317 IsEqualGUID(riid
, &IID_IMoniker
))
320 IMoniker_AddRef(iface
);
324 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
326 return E_NOINTERFACE
;
329 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_AddRef(IMoniker
*iface
)
331 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
332 ULONG ref
= InterlockedIncrement(&This
->ref
);
334 TRACE("(%p) ref=%d\n", This
, ref
);
339 static ULONG WINAPI
DEVENUM_IMediaCatMoniker_Release(IMoniker
*iface
)
341 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
342 ULONG ref
= InterlockedDecrement(&This
->ref
);
344 TRACE("(%p) ref=%d\n", This
, ref
);
347 RegCloseKey(This
->hkey
);
349 DEVENUM_UnlockModule();
354 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetClassID(IMoniker
*iface
, CLSID
*pClassID
)
356 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
358 TRACE("(%p)->(%p)\n", This
, pClassID
);
360 if (pClassID
== NULL
)
363 *pClassID
= CLSID_CDeviceMoniker
;
368 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsDirty(IMoniker
*iface
)
370 FIXME("(%p)->(): stub\n", iface
);
375 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Load(IMoniker
*iface
, IStream
*pStm
)
377 FIXME("(%p)->(%p): stub\n", iface
, pStm
);
382 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Save(IMoniker
*iface
, IStream
*pStm
, BOOL fClearDirty
)
384 FIXME("(%p)->(%p, %s): stub\n", iface
, pStm
, fClearDirty
? "true" : "false");
386 return STG_E_CANTSAVE
;
389 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*pcbSize
)
391 FIXME("(%p)->(%p): stub\n", iface
, pcbSize
);
393 ZeroMemory(pcbSize
, sizeof(*pcbSize
));
398 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToObject(IMoniker
*iface
, IBindCtx
*pbc
,
399 IMoniker
*pmkToLeft
, REFIID riidResult
, void **ppvResult
)
401 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
402 IUnknown
* pObj
= NULL
;
403 IPropertyBag
* pProp
= NULL
;
406 HRESULT res
= E_FAIL
;
408 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riidResult
), ppvResult
);
415 /* first activation of this class */
417 res
=IMoniker_BindToStorage(iface
, NULL
, NULL
, &IID_IPropertyBag
, &pvptr
);
421 V_VT(&var
) = VT_LPWSTR
;
422 res
= IPropertyBag_Read(pProp
, clsid_keyname
, &var
, NULL
);
426 res
= CLSIDFromString(V_BSTR(&var
), &clsID
);
427 CoTaskMemFree(V_BSTR(&var
));
431 res
=CoCreateInstance(&clsID
,NULL
,CLSCTX_ALL
,&IID_IUnknown
,&pvptr
);
438 /* get the requested interface from the loaded class */
443 res2
= IUnknown_QueryInterface(pObj
, &IID_IPersistPropertyBag
, &ppv
);
444 if (SUCCEEDED(res2
)) {
445 res
= IPersistPropertyBag_Load((IPersistPropertyBag
*) ppv
, pProp
, NULL
);
446 IPersistPropertyBag_Release((IPersistPropertyBag
*) ppv
);
450 res
= IUnknown_QueryInterface(pObj
,riidResult
,ppvResult
);
451 IUnknown_Release(pObj
);
456 IPropertyBag_Release(pProp
);
459 TRACE("<- 0x%x\n", res
);
464 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
465 IMoniker
*pmkToLeft
, REFIID riid
, void **ppvObj
)
467 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
469 TRACE("(%p)->(%p, %p, %s, %p)\n", This
, pbc
, pmkToLeft
, debugstr_guid(riid
), ppvObj
);
474 return MK_E_NOSTORAGE
;
478 static DWORD reported
;
481 FIXME("ignoring IBindCtx %p\n", pbc
);
486 if (IsEqualGUID(riid
, &IID_IPropertyBag
))
489 DuplicateHandle(GetCurrentProcess(), This
->hkey
, GetCurrentProcess(), &hkey
, 0, 0, DUPLICATE_SAME_ACCESS
);
490 return DEVENUM_IPropertyBag_Construct(hkey
, (IPropertyBag
**)ppvObj
);
493 return MK_E_NOSTORAGE
;
496 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Reduce(IMoniker
*iface
, IBindCtx
*pbc
,
497 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
499 TRACE("(%p)->(%p, %d, %p, %p)\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
503 *ppmkReduced
= iface
;
505 return MK_S_REDUCED_TO_SELF
;
508 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ComposeWith(IMoniker
*iface
, IMoniker
*pmkRight
,
509 BOOL fOnlyIfNotGeneric
, IMoniker
**ppmkComposite
)
511 FIXME("(%p)->(%p, %s, %p): stub\n", iface
, pmkRight
, fOnlyIfNotGeneric
? "true" : "false", ppmkComposite
);
513 /* FIXME: use CreateGenericComposite? */
514 *ppmkComposite
= NULL
;
519 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Enum(IMoniker
*iface
, BOOL fForward
,
520 IEnumMoniker
**ppenumMoniker
)
522 FIXME("(%p)->(%s, %p): stub\n", iface
, fForward
? "true" : "false", ppenumMoniker
);
524 *ppenumMoniker
= NULL
;
529 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsEqual(IMoniker
*iface
, IMoniker
*pmkOtherMoniker
)
532 LPOLESTR this_name
, other_name
;
536 TRACE("(%p)->(%p)\n", iface
, pmkOtherMoniker
);
538 if (!pmkOtherMoniker
)
541 IMoniker_GetClassID(pmkOtherMoniker
, &clsid
);
542 if (!IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
))
545 res
= CreateBindCtx(0, &bind
);
550 if (SUCCEEDED(IMoniker_GetDisplayName(iface
, bind
, NULL
, &this_name
)) &&
551 SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker
, bind
, NULL
, &other_name
)))
553 int result
= lstrcmpiW(this_name
, other_name
);
554 CoTaskMemFree(this_name
);
555 CoTaskMemFree(other_name
);
559 IBindCtx_Release(bind
);
563 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Hash(IMoniker
*iface
, DWORD
*pdwHash
)
565 TRACE("(%p)->(%p)\n", iface
, pdwHash
);
572 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
573 IMoniker
*pmkToLeft
, IMoniker
*pmkNewlyRunning
)
575 FIXME("(%p)->(%p, %p, %p): stub\n", iface
, pbc
, pmkToLeft
, pmkNewlyRunning
);
580 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
581 IMoniker
*pmkToLeft
, FILETIME
*pFileTime
)
583 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, pFileTime
);
585 pFileTime
->dwLowDateTime
= 0xFFFFFFFF;
586 pFileTime
->dwHighDateTime
= 0x7FFFFFFF;
588 return MK_E_UNAVAILABLE
;
591 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_Inverse(IMoniker
*iface
, IMoniker
**ppmk
)
593 TRACE("(%p)->(%p)\n", iface
, ppmk
);
597 return MK_E_NOINVERSE
;
600 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_CommonPrefixWith(IMoniker
*iface
,
601 IMoniker
*pmkOtherMoniker
, IMoniker
**ppmkPrefix
)
603 TRACE("(%p)->(%p, %p)\n", iface
, pmkOtherMoniker
, ppmkPrefix
);
607 return MK_E_NOPREFIX
;
610 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker
*iface
, IMoniker
*pmkOther
,
611 IMoniker
**ppmkRelPath
)
613 TRACE("(%p)->(%p, %p)\n", iface
, pmkOther
, ppmkRelPath
);
615 *ppmkRelPath
= pmkOther
;
620 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
621 IMoniker
*pmkToLeft
, LPOLESTR
*ppszDisplayName
)
623 MediaCatMoniker
*This
= impl_from_IMoniker(iface
);
624 WCHAR wszBuffer
[MAX_PATH
];
625 static const WCHAR wszFriendlyName
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
626 DWORD received
= sizeof(wszBuffer
);
628 TRACE("(%p)->(%p, %p, %p)\n", iface
, pbc
, pmkToLeft
, ppszDisplayName
);
630 *ppszDisplayName
= NULL
;
632 /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
633 if (RegQueryValueExW(This
->hkey
, wszFriendlyName
, NULL
, NULL
, (LPBYTE
)wszBuffer
, &received
) == ERROR_SUCCESS
)
635 *ppszDisplayName
= CoTaskMemAlloc(received
);
636 strcpyW(*ppszDisplayName
, wszBuffer
);
643 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
644 IMoniker
*pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
*pchEaten
, IMoniker
**ppmkOut
)
646 FIXME("(%p)->(%p, %p, %s, %p, %p)\n", iface
, pbc
, pmkToLeft
, debugstr_w(pszDisplayName
), pchEaten
, ppmkOut
);
654 static HRESULT WINAPI
DEVENUM_IMediaCatMoniker_IsSystemMoniker(IMoniker
*iface
, DWORD
*pdwMksys
)
656 TRACE("(%p)->(%p)\n", iface
, pdwMksys
);
661 static const IMonikerVtbl IMoniker_Vtbl
=
663 DEVENUM_IMediaCatMoniker_QueryInterface
,
664 DEVENUM_IMediaCatMoniker_AddRef
,
665 DEVENUM_IMediaCatMoniker_Release
,
666 DEVENUM_IMediaCatMoniker_GetClassID
,
667 DEVENUM_IMediaCatMoniker_IsDirty
,
668 DEVENUM_IMediaCatMoniker_Load
,
669 DEVENUM_IMediaCatMoniker_Save
,
670 DEVENUM_IMediaCatMoniker_GetSizeMax
,
671 DEVENUM_IMediaCatMoniker_BindToObject
,
672 DEVENUM_IMediaCatMoniker_BindToStorage
,
673 DEVENUM_IMediaCatMoniker_Reduce
,
674 DEVENUM_IMediaCatMoniker_ComposeWith
,
675 DEVENUM_IMediaCatMoniker_Enum
,
676 DEVENUM_IMediaCatMoniker_IsEqual
,
677 DEVENUM_IMediaCatMoniker_Hash
,
678 DEVENUM_IMediaCatMoniker_IsRunning
,
679 DEVENUM_IMediaCatMoniker_GetTimeOfLastChange
,
680 DEVENUM_IMediaCatMoniker_Inverse
,
681 DEVENUM_IMediaCatMoniker_CommonPrefixWith
,
682 DEVENUM_IMediaCatMoniker_RelativePathTo
,
683 DEVENUM_IMediaCatMoniker_GetDisplayName
,
684 DEVENUM_IMediaCatMoniker_ParseDisplayName
,
685 DEVENUM_IMediaCatMoniker_IsSystemMoniker
688 MediaCatMoniker
* DEVENUM_IMediaCatMoniker_Construct(void)
690 MediaCatMoniker
* pMoniker
= NULL
;
691 pMoniker
= CoTaskMemAlloc(sizeof(MediaCatMoniker
));
695 pMoniker
->IMoniker_iface
.lpVtbl
= &IMoniker_Vtbl
;
697 pMoniker
->hkey
= NULL
;
699 DEVENUM_IMediaCatMoniker_AddRef(&pMoniker
->IMoniker_iface
);
701 DEVENUM_LockModule();
706 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
708 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
711 static HRESULT WINAPI
DEVENUM_IEnumMoniker_QueryInterface(IEnumMoniker
*iface
, REFIID riid
,
714 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
719 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
720 IsEqualGUID(riid
, &IID_IEnumMoniker
))
723 IEnumMoniker_AddRef(iface
);
727 FIXME("- no interface IID: %s\n", debugstr_guid(riid
));
729 return E_NOINTERFACE
;
732 static ULONG WINAPI
DEVENUM_IEnumMoniker_AddRef(IEnumMoniker
*iface
)
734 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
735 ULONG ref
= InterlockedIncrement(&This
->ref
);
737 TRACE("(%p) ref=%d\n", This
, ref
);
742 static ULONG WINAPI
DEVENUM_IEnumMoniker_Release(IEnumMoniker
*iface
)
744 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
745 ULONG ref
= InterlockedDecrement(&This
->ref
);
747 TRACE("(%p) ref=%d\n", This
, ref
);
751 if(This
->special_hkey
)
752 RegCloseKey(This
->special_hkey
);
753 RegCloseKey(This
->hkey
);
755 DEVENUM_UnlockModule();
761 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Next(IEnumMoniker
*iface
, ULONG celt
, IMoniker
**rgelt
,
764 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
765 WCHAR buffer
[MAX_PATH
+ 1];
768 MediaCatMoniker
* pMoniker
;
770 TRACE("(%p)->(%d, %p, %p)\n", iface
, celt
, rgelt
, pceltFetched
);
772 while (fetched
< celt
)
774 if(This
->index
+fetched
< This
->subkey_cnt
)
775 res
= RegEnumKeyW(This
->hkey
, This
->index
+fetched
, buffer
, sizeof(buffer
) / sizeof(WCHAR
));
776 else if(This
->special_hkey
)
777 res
= RegEnumKeyW(This
->special_hkey
, This
->index
+fetched
-This
->subkey_cnt
, buffer
, sizeof(buffer
) / sizeof(WCHAR
));
780 if (res
!= ERROR_SUCCESS
)
784 pMoniker
= DEVENUM_IMediaCatMoniker_Construct();
786 return E_OUTOFMEMORY
;
788 if (RegOpenKeyW(This
->index
+fetched
< This
->subkey_cnt
? This
->hkey
: This
->special_hkey
,
789 buffer
, &pMoniker
->hkey
) != ERROR_SUCCESS
)
791 IMoniker_Release(&pMoniker
->IMoniker_iface
);
794 rgelt
[fetched
] = &pMoniker
->IMoniker_iface
;
798 This
->index
+= fetched
;
800 TRACE("-- fetched %d\n", fetched
);
803 *pceltFetched
= fetched
;
811 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Skip(IEnumMoniker
*iface
, ULONG celt
)
813 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
814 DWORD special_subkeys
= 0;
816 TRACE("(%p)->(%d)\n", iface
, celt
);
818 /* Before incrementing, check if there are any more values to run through.
819 Some programs use the Skip() function to get the number of devices */
820 if(This
->special_hkey
)
821 RegQueryInfoKeyW(This
->special_hkey
, NULL
, NULL
, NULL
, &special_subkeys
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
823 if((This
->index
+ celt
) >= This
->subkey_cnt
+ special_subkeys
)
833 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Reset(IEnumMoniker
*iface
)
835 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
837 TRACE("(%p)->()\n", iface
);
844 static HRESULT WINAPI
DEVENUM_IEnumMoniker_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ppenum
)
846 FIXME("(%p)->(%p): stub\n", iface
, ppenum
);
851 /**********************************************************************
854 static const IEnumMonikerVtbl IEnumMoniker_Vtbl
=
856 DEVENUM_IEnumMoniker_QueryInterface
,
857 DEVENUM_IEnumMoniker_AddRef
,
858 DEVENUM_IEnumMoniker_Release
,
859 DEVENUM_IEnumMoniker_Next
,
860 DEVENUM_IEnumMoniker_Skip
,
861 DEVENUM_IEnumMoniker_Reset
,
862 DEVENUM_IEnumMoniker_Clone
865 HRESULT
DEVENUM_IEnumMoniker_Construct(HKEY hkey
, HKEY special_hkey
, IEnumMoniker
** ppEnumMoniker
)
867 EnumMonikerImpl
* pEnumMoniker
= CoTaskMemAlloc(sizeof(EnumMonikerImpl
));
869 return E_OUTOFMEMORY
;
871 pEnumMoniker
->IEnumMoniker_iface
.lpVtbl
= &IEnumMoniker_Vtbl
;
872 pEnumMoniker
->ref
= 1;
873 pEnumMoniker
->index
= 0;
874 pEnumMoniker
->hkey
= hkey
;
875 pEnumMoniker
->special_hkey
= special_hkey
;
877 *ppEnumMoniker
= &pEnumMoniker
->IEnumMoniker_iface
;
879 if(RegQueryInfoKeyW(pEnumMoniker
->hkey
, NULL
, NULL
, NULL
, &pEnumMoniker
->subkey_cnt
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
880 pEnumMoniker
->subkey_cnt
= 0;
883 DEVENUM_LockModule();