Added the processing for determination of SFGAO_HASSUBFOLDER flag in
[wine/testsucceed.git] / dlls / devenum / mediacatenum.c
blob836bc7fc267ac2315dbb9029a5a3608d18685d21
1 /*
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
20 * NOTES ON THIS FILE:
21 * - Implements IEnumMoniker interface which enumerates through moniker
22 * objects created from HKEY_CLASSES/CLSID/{DEVICE_CLSID}/Instance
25 #include "devenum_private.h"
26 #include "vfwmsgs.h"
27 #include "oleauto.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 ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface);
38 static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface);
40 typedef struct
42 IPropertyBagVtbl *lpVtbl;
43 DWORD ref;
44 HKEY hkey;
45 } RegPropBagImpl;
48 static HRESULT WINAPI DEVENUM_IPropertyBag_QueryInterface(
49 LPPROPERTYBAG iface,
50 REFIID riid,
51 LPVOID *ppvObj)
53 RegPropBagImpl *This = (RegPropBagImpl *)iface;
54 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
56 if (This == NULL || ppvObj == NULL) return E_POINTER;
58 if (IsEqualGUID(riid, &IID_IUnknown) ||
59 IsEqualGUID(riid, &IID_IPropertyBag))
61 *ppvObj = (LPVOID)iface;
62 DEVENUM_IPropertyBag_AddRef(iface);
63 return S_OK;
66 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
67 return E_NOINTERFACE;
70 /**********************************************************************
71 * DEVENUM_IPropertyBag_AddRef (also IUnknown)
73 static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface)
75 RegPropBagImpl *This = (RegPropBagImpl *)iface;
76 TRACE("\n");
78 return InterlockedIncrement(&This->ref);
81 /**********************************************************************
82 * DEVENUM_IPropertyBag_Release (also IUnknown)
84 static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
86 RegPropBagImpl *This = (RegPropBagImpl *)iface;
87 ULONG ref;
89 TRACE("\n");
91 ref = InterlockedDecrement(&This->ref);
92 if (ref == 0) {
93 RegCloseKey(This->hkey);
94 CoTaskMemFree(This);
95 DEVENUM_UnlockModule();
97 return ref;
100 static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
101 LPPROPERTYBAG iface,
102 LPCOLESTR pszPropName,
103 VARIANT* pVar,
104 IErrorLog* pErrorLog)
106 LPVOID pData = NULL;
107 LONG received;
108 DWORD type = 0;
109 RegPropBagImpl *This = (RegPropBagImpl *)iface;
110 HRESULT res = S_OK;
111 LONG reswin32;
113 TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
115 if (!pszPropName || !pVar)
116 return E_POINTER;
118 reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received);
119 res = HRESULT_FROM_WIN32(reswin32);
121 if (SUCCEEDED(res))
123 pData = HeapAlloc(GetProcessHeap(), 0, received);
125 /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
126 reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received);
127 res = HRESULT_FROM_WIN32(reswin32);
130 if (SUCCEEDED(res))
132 res = E_INVALIDARG; /* assume we cannot coerce into right type */
134 TRACE("Read %ld bytes (%s)\n", received, type == REG_SZ ? debugstr_w((LPWSTR)pData) : "binary data");
136 switch (type)
138 case REG_SZ:
139 switch (V_VT(pVar))
141 case VT_LPWSTR:
142 V_UNION(pVar, bstrVal) = CoTaskMemAlloc(received);
143 memcpy(V_UNION(pVar, bstrVal), (LPWSTR)pData, received);
144 res = S_OK;
145 break;
146 case VT_EMPTY:
147 V_VT(pVar) = VT_BSTR;
148 /* fall through */
149 case VT_BSTR:
150 V_UNION(pVar, bstrVal) = SysAllocStringLen((LPWSTR)pData, received/sizeof(WCHAR) - 1);
151 res = S_OK;
152 break;
154 break;
155 case REG_DWORD:
156 TRACE("REG_DWORD: %lx\n", *(DWORD *)pData);
157 switch (V_VT(pVar))
159 case VT_EMPTY:
160 V_VT(pVar) = VT_I4;
161 /* fall through */
162 case VT_I4:
163 case VT_UI4:
164 V_UNION(pVar, ulVal) = *(DWORD *)pData;
165 res = S_OK;
166 break;
168 break;
169 case REG_BINARY:
171 SAFEARRAYBOUND bound;
172 void * pArrayElements;
173 bound.lLbound = 0;
174 bound.cElements = received;
175 TRACE("REG_BINARY: len = %ld\n", received);
176 switch (V_VT(pVar))
178 case VT_EMPTY:
179 case VT_ARRAY | VT_UI1:
180 if (!(V_UNION(pVar, parray) = SafeArrayCreate(VT_UI1, 1, &bound)))
181 res = E_OUTOFMEMORY;
182 res = S_OK;
183 break;
186 if (res == E_INVALIDARG)
187 break;
189 res = SafeArrayAccessData(V_UNION(pVar, parray), &pArrayElements);
190 if (FAILED(res))
191 break;
193 CopyMemory(pArrayElements, pData, received);
194 res = SafeArrayUnaccessData(V_UNION(pVar, parray));
195 break;
198 if (res == E_INVALIDARG)
199 FIXME("Variant type %x not supported for regtype %lx\n", V_VT(pVar), type);
202 HeapFree(GetProcessHeap(), 0, pData);
204 TRACE("<- %lx\n", res);
205 return res;
208 static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
209 LPPROPERTYBAG iface,
210 LPCOLESTR pszPropName,
211 VARIANT* pVar)
213 RegPropBagImpl *This = (RegPropBagImpl *)iface;
214 LPVOID lpData = NULL;
215 DWORD cbData = 0;
216 DWORD dwType = 0;
217 HRESULT res = S_OK;
219 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
221 switch (V_VT(pVar))
223 case VT_BSTR:
224 TRACE("writing %s\n", debugstr_w(V_UNION(pVar, bstrVal)));
225 lpData = (LPVOID)V_UNION(pVar, bstrVal);
226 dwType = REG_SZ;
227 cbData = (lstrlenW(V_UNION(pVar, bstrVal)) + 1) * sizeof(WCHAR);
228 break;
229 case VT_I4:
230 case VT_UI4:
231 TRACE("writing %lu\n", V_UNION(pVar, ulVal));
232 lpData = (LPVOID)&V_UNION(pVar, ulVal);
233 dwType = REG_DWORD;
234 cbData = sizeof(DWORD);
235 break;
236 case VT_ARRAY | VT_UI1:
238 LONG lUbound = 0;
239 LONG lLbound = 0;
240 dwType = REG_BINARY;
241 res = SafeArrayGetLBound(V_UNION(pVar, parray), 1, &lLbound);
242 res = SafeArrayGetUBound(V_UNION(pVar, parray), 1, &lUbound);
243 cbData = (lUbound - lLbound + 1) /* * sizeof(BYTE)*/;
244 TRACE("cbData: %ld\n", cbData);
245 res = SafeArrayAccessData(V_UNION(pVar, parray), &lpData);
246 break;
248 default:
249 FIXME("Variant type %d not handled\n", V_VT(pVar));
250 return E_FAIL;
253 if (RegSetValueExW(This->hkey,
254 pszPropName, 0,
255 dwType, lpData, cbData) != ERROR_SUCCESS)
256 res = E_FAIL;
258 if (V_VT(pVar) & VT_ARRAY)
259 res = SafeArrayUnaccessData(V_UNION(pVar, parray));
261 return res;
264 static IPropertyBagVtbl IPropertyBag_Vtbl =
266 DEVENUM_IPropertyBag_QueryInterface,
267 DEVENUM_IPropertyBag_AddRef,
268 DEVENUM_IPropertyBag_Release,
269 DEVENUM_IPropertyBag_Read,
270 DEVENUM_IPropertyBag_Write
273 static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
275 RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
276 if (!rpb)
277 return E_OUTOFMEMORY;
278 rpb->lpVtbl = &IPropertyBag_Vtbl;
279 rpb->ref = 1;
280 rpb->hkey = hkey;
281 *ppBag = (IPropertyBag*)rpb;
282 DEVENUM_LockModule();
283 return S_OK;
287 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_QueryInterface(
288 LPMONIKER iface,
289 REFIID riid,
290 LPVOID *ppvObj)
292 MediaCatMoniker *This = (MediaCatMoniker *)iface;
293 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
295 if (This == NULL || ppvObj == NULL) return E_POINTER;
297 *ppvObj = NULL;
299 if (IsEqualGUID(riid, &IID_IUnknown) ||
300 IsEqualGUID(riid, &IID_IPersist) ||
301 IsEqualGUID(riid, &IID_IPersistStream) ||
302 IsEqualGUID(riid, &IID_IMoniker))
304 *ppvObj = (LPVOID)iface;
305 DEVENUM_IMediaCatMoniker_AddRef(iface);
306 return S_OK;
309 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
310 return E_NOINTERFACE;
313 /**********************************************************************
314 * DEVENUM_IMediaCatMoniker_AddRef (also IUnknown)
316 static ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface)
318 MediaCatMoniker *This = (MediaCatMoniker *)iface;
319 TRACE("\n");
321 return InterlockedIncrement(&This->ref);
324 /**********************************************************************
325 * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
327 static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface)
329 MediaCatMoniker *This = (MediaCatMoniker *)iface;
330 ULONG ref;
331 TRACE("\n");
333 ref = InterlockedDecrement(&This->ref);
334 if (ref == 0) {
335 RegCloseKey(This->hkey);
336 CoTaskMemFree(This);
337 DEVENUM_UnlockModule();
339 return ref;
342 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetClassID(
343 LPMONIKER iface,
344 CLSID* pClassID)
346 MediaCatMoniker *This = (MediaCatMoniker *)iface;
347 FIXME("(%p)->(%p)\n", This, pClassID);
349 if (pClassID == NULL)
350 return E_POINTER;
352 return E_NOTIMPL;
355 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsDirty(LPMONIKER iface)
357 FIXME("()\n");
359 return S_FALSE;
362 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Load(LPMONIKER iface, IStream* pStm)
364 FIXME("(%p)\n", pStm);
366 return E_NOTIMPL;
369 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Save(LPMONIKER iface, IStream* pStm, BOOL fClearDirty)
371 FIXME("(%p, %s)\n", pStm, fClearDirty ? "true" : "false");
373 return STG_E_CANTSAVE;
376 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetSizeMax(
377 LPMONIKER iface,
378 ULARGE_INTEGER* pcbSize)
380 FIXME("(%p)\n", pcbSize);
382 ZeroMemory(pcbSize, sizeof(*pcbSize));
384 return S_OK;
387 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(
388 LPMONIKER iface,
389 IBindCtx* pbc,
390 IMoniker* pmkToLeft,
391 REFIID riidResult,
392 void** ppvResult)
394 IUnknown * pObj = NULL;
395 IPropertyBag * pProp = NULL;
396 CLSID clsID;
397 VARIANT var;
398 HRESULT res = E_FAIL;
400 MediaCatMoniker *This = (MediaCatMoniker *)iface;
402 VariantClear(&var);
404 TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult);
406 *ppvResult = NULL;
408 if(pmkToLeft==NULL)
410 /* first activation of this class */
411 LPVOID pvptr;
412 res=IMoniker_BindToStorage(iface, NULL, NULL, &IID_IPropertyBag, &pvptr);
413 pProp = (IPropertyBag*)pvptr;
414 if (SUCCEEDED(res))
416 V_VT(&var) = VT_LPWSTR;
417 res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL);
419 if (SUCCEEDED(res))
421 res = CLSIDFromString(V_UNION(&var,bstrVal), &clsID);
422 CoTaskMemFree(V_UNION(&var, bstrVal));
424 if (SUCCEEDED(res))
426 res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IUnknown,&pvptr);
427 pObj = (IUnknown*)pvptr;
431 if (pObj!=NULL)
433 /* get the requested interface from the loaded class */
434 res= IUnknown_QueryInterface(pObj,riidResult,ppvResult);
435 IUnknown_Release(pObj);
438 if (pProp)
440 IPropertyBag_Release(pProp);
443 TRACE("<- 0x%lx\n", res);
445 return res;
448 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(
449 LPMONIKER iface,
450 IBindCtx* pbc,
451 IMoniker* pmkToLeft,
452 REFIID riid,
453 void** ppvObj)
455 MediaCatMoniker *This = (MediaCatMoniker *)iface;
456 TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
458 *ppvObj = NULL;
460 if (pbc || pmkToLeft)
461 return MK_E_NOSTORAGE;
463 if (IsEqualGUID(riid, &IID_IPropertyBag))
465 HANDLE hkey;
466 DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS);
467 return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
470 return MK_E_NOSTORAGE;
473 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Reduce(
474 LPMONIKER iface,
475 IBindCtx* pbc,
476 DWORD dwReduceHowFar,
477 IMoniker** ppmkToLeft,
478 IMoniker** ppmkReduced)
480 TRACE("(%p, %ld, %p, %p)\n", pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
482 if (ppmkToLeft)
483 *ppmkToLeft = NULL;
484 *ppmkReduced = iface;
486 return MK_S_REDUCED_TO_SELF;
489 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ComposeWith(
490 LPMONIKER iface,
491 IMoniker* pmkRight,
492 BOOL fOnlyIfNotGeneric,
493 IMoniker** ppmkComposite)
495 FIXME("(%p, %s, %p): stub\n", pmkRight, fOnlyIfNotGeneric ? "true" : "false", ppmkComposite);
497 /* FIXME: use CreateGenericComposite? */
498 *ppmkComposite = NULL;
500 return E_NOTIMPL;
503 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Enum(
504 LPMONIKER iface,
505 BOOL fForward,
506 IEnumMoniker** ppenumMoniker)
508 FIXME("(%s, %p): stub\n", fForward ? "true" : "false", ppenumMoniker);
510 *ppenumMoniker = NULL;
512 return S_OK;
515 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsEqual(
516 LPMONIKER iface,
517 IMoniker* pmkOtherMoniker)
519 FIXME("(%p)\n", pmkOtherMoniker);
521 return E_NOTIMPL;
524 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Hash(
525 LPMONIKER iface,
526 DWORD* pdwHash)
528 TRACE("(%p)\n", pdwHash);
530 *pdwHash = 0;
532 return S_OK;
535 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsRunning(
536 LPMONIKER iface,
537 IBindCtx* pbc,
538 IMoniker* pmkToLeft,
539 IMoniker* pmkNewlyRunning)
541 FIXME("(%p, %p, %p)\n", pbc, pmkToLeft, pmkNewlyRunning);
543 return S_FALSE;
546 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(
547 LPMONIKER iface,
548 IBindCtx* pbc,
549 IMoniker* pmkToLeft,
550 FILETIME* pFileTime)
552 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pFileTime);
554 pFileTime->dwLowDateTime = 0xFFFFFFFF;
555 pFileTime->dwHighDateTime = 0x7FFFFFFF;
557 return MK_E_UNAVAILABLE;
560 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Inverse(
561 LPMONIKER iface,
562 IMoniker** ppmk)
564 TRACE("(%p)\n", ppmk);
566 *ppmk = NULL;
568 return MK_E_NOINVERSE;
571 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_CommonPrefixWith(
572 LPMONIKER iface,
573 IMoniker* pmkOtherMoniker,
574 IMoniker** ppmkPrefix)
576 TRACE("(%p, %p)\n", pmkOtherMoniker, ppmkPrefix);
578 *ppmkPrefix = NULL;
580 return MK_E_NOPREFIX;
583 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(
584 LPMONIKER iface,
585 IMoniker* pmkOther,
586 IMoniker** ppmkRelPath)
588 TRACE("(%p, %p)\n", pmkOther, ppmkRelPath);
590 *ppmkRelPath = pmkOther;
592 return MK_S_HIM;
595 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(
596 LPMONIKER iface,
597 IBindCtx* pbc,
598 IMoniker* pmkToLeft,
599 LPOLESTR* ppszDisplayName)
601 MediaCatMoniker *This = (MediaCatMoniker *)iface;
602 WCHAR wszBuffer[MAX_PATH];
603 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
604 LONG received = sizeof(wszFriendlyName);
606 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName);
608 *ppszDisplayName = NULL;
610 /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
611 if (RegQueryValueW(This->hkey, wszFriendlyName, wszBuffer, &received) == ERROR_SUCCESS)
613 *ppszDisplayName = CoTaskMemAlloc(received);
614 strcpyW(*ppszDisplayName, wszBuffer);
615 return S_OK;
618 return E_FAIL;
621 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(
622 LPMONIKER iface,
623 IBindCtx* pbc,
624 IMoniker* pmkToLeft,
625 LPOLESTR pszDisplayName,
626 ULONG* pchEaten,
627 IMoniker** ppmkOut)
629 FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
631 *pchEaten = 0;
632 *ppmkOut = NULL;
634 return MK_E_SYNTAX;
637 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsSystemMoniker(
638 LPMONIKER iface,
639 DWORD* pdwMksys)
641 TRACE("(%p)\n", pdwMksys);
643 return S_FALSE;
646 static IMonikerVtbl IMoniker_Vtbl =
648 DEVENUM_IMediaCatMoniker_QueryInterface,
649 DEVENUM_IMediaCatMoniker_AddRef,
650 DEVENUM_IMediaCatMoniker_Release,
651 DEVENUM_IMediaCatMoniker_GetClassID,
652 DEVENUM_IMediaCatMoniker_IsDirty,
653 DEVENUM_IMediaCatMoniker_Load,
654 DEVENUM_IMediaCatMoniker_Save,
655 DEVENUM_IMediaCatMoniker_GetSizeMax,
656 DEVENUM_IMediaCatMoniker_BindToObject,
657 DEVENUM_IMediaCatMoniker_BindToStorage,
658 DEVENUM_IMediaCatMoniker_Reduce,
659 DEVENUM_IMediaCatMoniker_ComposeWith,
660 DEVENUM_IMediaCatMoniker_Enum,
661 DEVENUM_IMediaCatMoniker_IsEqual,
662 DEVENUM_IMediaCatMoniker_Hash,
663 DEVENUM_IMediaCatMoniker_IsRunning,
664 DEVENUM_IMediaCatMoniker_GetTimeOfLastChange,
665 DEVENUM_IMediaCatMoniker_Inverse,
666 DEVENUM_IMediaCatMoniker_CommonPrefixWith,
667 DEVENUM_IMediaCatMoniker_RelativePathTo,
668 DEVENUM_IMediaCatMoniker_GetDisplayName,
669 DEVENUM_IMediaCatMoniker_ParseDisplayName,
670 DEVENUM_IMediaCatMoniker_IsSystemMoniker
673 MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct()
675 MediaCatMoniker * pMoniker = NULL;
676 pMoniker = CoTaskMemAlloc(sizeof(MediaCatMoniker));
677 if (!pMoniker)
678 return NULL;
680 pMoniker->lpVtbl = &IMoniker_Vtbl;
681 pMoniker->ref = 0;
682 pMoniker->hkey = NULL;
684 DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker);
686 DEVENUM_LockModule();
688 return pMoniker;
691 /**********************************************************************
692 * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
694 static HRESULT WINAPI DEVENUM_IEnumMoniker_QueryInterface(
695 LPENUMMONIKER iface,
696 REFIID riid,
697 LPVOID *ppvObj)
699 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
700 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
702 if (This == NULL || ppvObj == NULL) return E_POINTER;
704 if (IsEqualGUID(riid, &IID_IUnknown) ||
705 IsEqualGUID(riid, &IID_IEnumMoniker))
707 *ppvObj = (LPVOID)iface;
708 DEVENUM_IEnumMoniker_AddRef(iface);
709 return S_OK;
712 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
713 return E_NOINTERFACE;
716 /**********************************************************************
717 * DEVENUM_IEnumMoniker_AddRef (also IUnknown)
719 static ULONG WINAPI DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface)
721 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
722 ULONG ref = InterlockedIncrement(&This->ref);
724 TRACE("(%p)->() AddRef from %ld\n", iface, ref - 1);
726 return ref;
729 /**********************************************************************
730 * DEVENUM_IEnumMoniker_Release (also IUnknown)
732 static ULONG WINAPI DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface)
734 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
735 ULONG ref = InterlockedDecrement(&This->ref);
737 TRACE("(%p)->() Release from %ld\n", iface, ref + 1);
739 if (!ref)
741 RegCloseKey(This->hkey);
742 CoTaskMemFree(This);
743 DEVENUM_UnlockModule();
744 return 0;
746 return ref;
749 static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
751 WCHAR buffer[MAX_PATH + 1];
752 LONG res;
753 ULONG fetched = 0;
754 MediaCatMoniker * pMoniker;
755 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
757 TRACE("(%p)->(%ld, %p, %p)\n", iface, celt, rgelt, pceltFetched);
759 while (fetched < celt)
761 res = RegEnumKeyW(This->hkey, This->index, buffer, sizeof(buffer) / sizeof(WCHAR));
762 if (res != ERROR_SUCCESS)
764 break;
766 pMoniker = DEVENUM_IMediaCatMoniker_Construct();
767 if (!pMoniker)
768 return E_OUTOFMEMORY;
770 if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
772 DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker);
773 break;
775 rgelt[fetched] = (LPMONIKER)pMoniker;
776 fetched++;
779 This->index += fetched;
781 TRACE("-- fetched %ld\n", fetched);
783 if (pceltFetched)
784 *pceltFetched = fetched;
786 if (fetched != celt)
787 return S_FALSE;
788 else
789 return S_OK;
792 static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(LPENUMMONIKER iface, ULONG celt)
794 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
796 TRACE("(%p)->(%ld)\n", iface, celt);
798 This->index += celt;
800 return S_OK;
803 static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface)
805 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
807 TRACE("(%p)->()\n", iface);
809 This->index = 0;
811 return S_OK;
814 static HRESULT WINAPI DEVENUM_IEnumMoniker_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
816 FIXME("(%p)->(%p): stub\n", iface, ppenum);
818 return E_NOTIMPL;
821 /**********************************************************************
822 * IEnumMoniker_Vtbl
824 static IEnumMonikerVtbl IEnumMoniker_Vtbl =
826 DEVENUM_IEnumMoniker_QueryInterface,
827 DEVENUM_IEnumMoniker_AddRef,
828 DEVENUM_IEnumMoniker_Release,
829 DEVENUM_IEnumMoniker_Next,
830 DEVENUM_IEnumMoniker_Skip,
831 DEVENUM_IEnumMoniker_Reset,
832 DEVENUM_IEnumMoniker_Clone
835 HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
837 EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
838 if (!pEnumMoniker)
839 return E_OUTOFMEMORY;
841 pEnumMoniker->lpVtbl = &IEnumMoniker_Vtbl;
842 pEnumMoniker->ref = 1;
843 pEnumMoniker->index = 0;
844 pEnumMoniker->hkey = hkey;
846 *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
848 DEVENUM_LockModule();
850 return S_OK;