svn path=/trunk/; revision=21197
[reactos.git] / reactos / dll / directx / devenum / mediacatenum.c
1 /*
2 * IEnumMoniker implementation for DEVENUM.dll
3 *
4 * Copyright (C) 2002 Robert Shearman
5 *
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.
10 *
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.
15 *
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
19 *
20 * NOTES ON THIS FILE:
21 * - Implements IEnumMoniker interface which enumerates through moniker
22 * objects created from HKEY_CLASSES/CLSID/{DEVICE_CLSID}/Instance
23 */
24
25 #include "devenum_private.h"
26 #include "vfwmsgs.h"
27 #include "oleauto.h"
28
29 #include "wine/debug.h"
30
31
32 /* #define ICOM_THIS_From_IROTData(class, name) class* This = (class*)(((char*)name)-sizeof(void*)) */
33
34 WINE_DEFAULT_DEBUG_CHANNEL(devenum);
35
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);
39
40 typedef struct
41 {
42 IPropertyBagVtbl *lpVtbl;
43 DWORD ref;
44 HKEY hkey;
45 } RegPropBagImpl;
46
47
48 static HRESULT WINAPI DEVENUM_IPropertyBag_QueryInterface(
49 LPPROPERTYBAG iface,
50 REFIID riid,
51 LPVOID *ppvObj)
52 {
53 RegPropBagImpl *This = (RegPropBagImpl *)iface;
54 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
55
56 if (This == NULL || ppvObj == NULL) return E_POINTER;
57
58 if (IsEqualGUID(riid, &IID_IUnknown) ||
59 IsEqualGUID(riid, &IID_IPropertyBag))
60 {
61 *ppvObj = (LPVOID)iface;
62 DEVENUM_IPropertyBag_AddRef(iface);
63 return S_OK;
64 }
65
66 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
67 return E_NOINTERFACE;
68 }
69
70 /**********************************************************************
71 * DEVENUM_IPropertyBag_AddRef (also IUnknown)
72 */
73 static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface)
74 {
75 RegPropBagImpl *This = (RegPropBagImpl *)iface;
76 TRACE("\n");
77
78 return InterlockedIncrement(&This->ref);
79 }
80
81 /**********************************************************************
82 * DEVENUM_IPropertyBag_Release (also IUnknown)
83 */
84 static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
85 {
86 RegPropBagImpl *This = (RegPropBagImpl *)iface;
87
88 TRACE("\n");
89
90 if (InterlockedDecrement(&This->ref) == 0) {
91 RegCloseKey(This->hkey);
92 CoTaskMemFree(This);
93 DEVENUM_UnlockModule();
94 return 0;
95 }
96 return This->ref;
97 }
98
99 static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
100 LPPROPERTYBAG iface,
101 LPCOLESTR pszPropName,
102 VARIANT* pVar,
103 IErrorLog* pErrorLog)
104 {
105 LPVOID pData = NULL;
106 LONG received;
107 DWORD type = 0;
108 RegPropBagImpl *This = (RegPropBagImpl *)iface;
109 HRESULT res = S_OK;
110 LONG reswin32;
111
112 TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
113
114 if (!pszPropName || !pVar)
115 return E_POINTER;
116
117 reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received);
118 res = HRESULT_FROM_WIN32(reswin32);
119
120 if (SUCCEEDED(res))
121 {
122 pData = HeapAlloc(GetProcessHeap(), 0, received);
123
124 /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
125 reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received);
126 res = HRESULT_FROM_WIN32(reswin32);
127 }
128
129 if (SUCCEEDED(res))
130 {
131 res = E_INVALIDARG; /* assume we cannot coerce into right type */
132
133 TRACE("Read %ld bytes (%s)\n", received, type == REG_SZ ? debugstr_w((LPWSTR)pData) : "binary data");
134
135 switch (type)
136 {
137 case REG_SZ:
138 switch (V_VT(pVar))
139 {
140 case VT_LPWSTR:
141 V_UNION(pVar, bstrVal) = CoTaskMemAlloc(received);
142 memcpy(V_UNION(pVar, bstrVal), (LPWSTR)pData, received);
143 res = S_OK;
144 break;
145 case VT_EMPTY:
146 V_VT(pVar) = VT_BSTR;
147 /* fall through */
148 case VT_BSTR:
149 V_UNION(pVar, bstrVal) = SysAllocStringLen((LPWSTR)pData, received/sizeof(WCHAR) - 1);
150 res = S_OK;
151 break;
152 }
153 break;
154 case REG_DWORD:
155 TRACE("REG_DWORD: %lx\n", *(DWORD *)pData);
156 switch (V_VT(pVar))
157 {
158 case VT_EMPTY:
159 V_VT(pVar) = VT_I4;
160 /* fall through */
161 case VT_I4:
162 case VT_UI4:
163 V_UNION(pVar, ulVal) = *(DWORD *)pData;
164 res = S_OK;
165 break;
166 }
167 break;
168 case REG_BINARY:
169 {
170 SAFEARRAYBOUND bound;
171 void * pArrayElements;
172 bound.lLbound = 0;
173 bound.cElements = received;
174 TRACE("REG_BINARY: len = %ld\n", received);
175 switch (V_VT(pVar))
176 {
177 case VT_EMPTY:
178 case VT_ARRAY | VT_UI1:
179 if (!(V_UNION(pVar, parray) = SafeArrayCreate(VT_UI1, 1, &bound)))
180 res = E_OUTOFMEMORY;
181 res = S_OK;
182 break;
183 }
184
185 if (res == E_INVALIDARG)
186 break;
187
188 res = SafeArrayAccessData(V_UNION(pVar, parray), &pArrayElements);
189 if (FAILED(res))
190 break;
191
192 CopyMemory(pArrayElements, pData, received);
193 res = SafeArrayUnaccessData(V_UNION(pVar, parray));
194 break;
195 }
196 }
197 if (res == E_INVALIDARG)
198 FIXME("Variant type %x not supported for regtype %lx\n", V_VT(pVar), type);
199 }
200
201 if (pData)
202 HeapFree(GetProcessHeap(), 0, pData);
203
204 TRACE("<- %lx\n", res);
205 return res;
206 }
207
208 static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
209 LPPROPERTYBAG iface,
210 LPCOLESTR pszPropName,
211 VARIANT* pVar)
212 {
213 RegPropBagImpl *This = (RegPropBagImpl *)iface;
214 LPVOID lpData = NULL;
215 DWORD cbData = 0;
216 DWORD dwType = 0;
217 HRESULT res = S_OK;
218
219 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
220
221 switch (V_VT(pVar))
222 {
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:
237 {
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;
247 }
248 default:
249 FIXME("Variant type %d not handled\n", V_VT(pVar));
250 return E_FAIL;
251 }
252
253 if (RegSetValueExW(This->hkey,
254 pszPropName, 0,
255 dwType, lpData, cbData) != ERROR_SUCCESS)
256 res = E_FAIL;
257
258 if (V_VT(pVar) & VT_ARRAY)
259 res = SafeArrayUnaccessData(V_UNION(pVar, parray));
260
261 return res;
262 }
263
264 static IPropertyBagVtbl IPropertyBag_Vtbl =
265 {
266 DEVENUM_IPropertyBag_QueryInterface,
267 DEVENUM_IPropertyBag_AddRef,
268 DEVENUM_IPropertyBag_Release,
269 DEVENUM_IPropertyBag_Read,
270 DEVENUM_IPropertyBag_Write
271 };
272
273 static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
274 {
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;
284 }
285
286
287 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_QueryInterface(
288 LPMONIKER iface,
289 REFIID riid,
290 LPVOID *ppvObj)
291 {
292 MediaCatMoniker *This = (MediaCatMoniker *)iface;
293 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
294
295 if (This == NULL || ppvObj == NULL) return E_POINTER;
296
297 *ppvObj = NULL;
298
299 if (IsEqualGUID(riid, &IID_IUnknown) ||
300 IsEqualGUID(riid, &IID_IPersist) ||
301 IsEqualGUID(riid, &IID_IPersistStream) ||
302 IsEqualGUID(riid, &IID_IMoniker))
303 {
304 *ppvObj = (LPVOID)iface;
305 DEVENUM_IMediaCatMoniker_AddRef(iface);
306 return S_OK;
307 }
308
309 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
310 return E_NOINTERFACE;
311 }
312
313 /**********************************************************************
314 * DEVENUM_IMediaCatMoniker_AddRef (also IUnknown)
315 */
316 static ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface)
317 {
318 MediaCatMoniker *This = (MediaCatMoniker *)iface;
319 TRACE("\n");
320
321 return InterlockedIncrement(&This->ref);
322 }
323
324 /**********************************************************************
325 * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
326 */
327 static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface)
328 {
329 MediaCatMoniker *This = (MediaCatMoniker *)iface;
330 ULONG ref;
331 TRACE("\n");
332
333 ref = InterlockedDecrement(&This->ref);
334 if (ref == 0) {
335 RegCloseKey(This->hkey);
336 CoTaskMemFree(This);
337 DEVENUM_UnlockModule();
338 }
339 return ref;
340 }
341
342 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetClassID(
343 LPMONIKER iface,
344 CLSID* pClassID)
345 {
346 MediaCatMoniker *This = (MediaCatMoniker *)iface;
347 FIXME("(%p)->(%p)\n", This, pClassID);
348
349 if (pClassID == NULL)
350 return E_POINTER;
351
352 return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsDirty(LPMONIKER iface)
356 {
357 FIXME("()\n");
358
359 return S_FALSE;
360 }
361
362 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Load(LPMONIKER iface, IStream* pStm)
363 {
364 FIXME("(%p)\n", pStm);
365
366 return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Save(LPMONIKER iface, IStream* pStm, BOOL fClearDirty)
370 {
371 FIXME("(%p, %s)\n", pStm, fClearDirty ? "true" : "false");
372
373 return STG_E_CANTSAVE;
374 }
375
376 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetSizeMax(
377 LPMONIKER iface,
378 ULARGE_INTEGER* pcbSize)
379 {
380 FIXME("(%p)\n", pcbSize);
381
382 ZeroMemory(pcbSize, sizeof(*pcbSize));
383
384 return S_OK;
385 }
386
387 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(
388 LPMONIKER iface,
389 IBindCtx* pbc,
390 IMoniker* pmkToLeft,
391 REFIID riidResult,
392 void** ppvResult)
393 {
394 IUnknown * pObj = NULL;
395 IPropertyBag * pProp = NULL;
396 CLSID clsID;
397 VARIANT var;
398 HRESULT res = E_FAIL;
399
400 MediaCatMoniker *This = (MediaCatMoniker *)iface;
401
402 VariantClear(&var);
403
404 TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult);
405
406 *ppvResult = NULL;
407
408 if(pmkToLeft==NULL)
409 {
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))
415 {
416 V_VT(&var) = VT_LPWSTR;
417 res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL);
418 }
419 if (SUCCEEDED(res))
420 {
421 res = CLSIDFromString(V_UNION(&var,bstrVal), &clsID);
422 CoTaskMemFree(V_UNION(&var, bstrVal));
423 }
424 if (SUCCEEDED(res))
425 {
426 res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IUnknown,&pvptr);
427 pObj = (IUnknown*)pvptr;
428 }
429 }
430
431 if (pObj!=NULL)
432 {
433 /* get the requested interface from the loaded class */
434 res= IUnknown_QueryInterface(pObj,riidResult,ppvResult);
435 }
436
437 if (pProp)
438 {
439 IPropertyBag_Release(pProp);
440 }
441
442 TRACE("<- 0x%lx\n", res);
443
444 return res;
445 }
446
447 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(
448 LPMONIKER iface,
449 IBindCtx* pbc,
450 IMoniker* pmkToLeft,
451 REFIID riid,
452 void** ppvObj)
453 {
454 MediaCatMoniker *This = (MediaCatMoniker *)iface;
455 TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
456
457 *ppvObj = NULL;
458
459 if (pbc || pmkToLeft)
460 return MK_E_NOSTORAGE;
461
462 if (IsEqualGUID(riid, &IID_IPropertyBag))
463 {
464 HANDLE hkey;
465 DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS);
466 return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
467 }
468
469 return MK_E_NOSTORAGE;
470 }
471
472 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Reduce(
473 LPMONIKER iface,
474 IBindCtx* pbc,
475 DWORD dwReduceHowFar,
476 IMoniker** ppmkToLeft,
477 IMoniker** ppmkReduced)
478 {
479 TRACE("(%p, %ld, %p, %p)\n", pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
480
481 if (ppmkToLeft)
482 *ppmkToLeft = NULL;
483 *ppmkReduced = iface;
484
485 return MK_S_REDUCED_TO_SELF;
486 }
487
488 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ComposeWith(
489 LPMONIKER iface,
490 IMoniker* pmkRight,
491 BOOL fOnlyIfNotGeneric,
492 IMoniker** ppmkComposite)
493 {
494 FIXME("(%p, %s, %p): stub\n", pmkRight, fOnlyIfNotGeneric ? "true" : "false", ppmkComposite);
495
496 /* FIXME: use CreateGenericComposite? */
497 *ppmkComposite = NULL;
498
499 return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Enum(
503 LPMONIKER iface,
504 BOOL fForward,
505 IEnumMoniker** ppenumMoniker)
506 {
507 FIXME("(%s, %p): stub\n", fForward ? "true" : "false", ppenumMoniker);
508
509 *ppenumMoniker = NULL;
510
511 return S_OK;
512 }
513
514 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsEqual(
515 LPMONIKER iface,
516 IMoniker* pmkOtherMoniker)
517 {
518 FIXME("(%p)\n", pmkOtherMoniker);
519
520 return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Hash(
524 LPMONIKER iface,
525 DWORD* pdwHash)
526 {
527 TRACE("(%p)\n", pdwHash);
528
529 *pdwHash = 0;
530
531 return S_OK;
532 }
533
534 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsRunning(
535 LPMONIKER iface,
536 IBindCtx* pbc,
537 IMoniker* pmkToLeft,
538 IMoniker* pmkNewlyRunning)
539 {
540 FIXME("(%p, %p, %p)\n", pbc, pmkToLeft, pmkNewlyRunning);
541
542 return S_FALSE;
543 }
544
545 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(
546 LPMONIKER iface,
547 IBindCtx* pbc,
548 IMoniker* pmkToLeft,
549 FILETIME* pFileTime)
550 {
551 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pFileTime);
552
553 pFileTime->dwLowDateTime = 0xFFFFFFFF;
554 pFileTime->dwHighDateTime = 0x7FFFFFFF;
555
556 return MK_E_UNAVAILABLE;
557 }
558
559 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Inverse(
560 LPMONIKER iface,
561 IMoniker** ppmk)
562 {
563 TRACE("(%p)\n", ppmk);
564
565 *ppmk = NULL;
566
567 return MK_E_NOINVERSE;
568 }
569
570 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_CommonPrefixWith(
571 LPMONIKER iface,
572 IMoniker* pmkOtherMoniker,
573 IMoniker** ppmkPrefix)
574 {
575 TRACE("(%p, %p)\n", pmkOtherMoniker, ppmkPrefix);
576
577 *ppmkPrefix = NULL;
578
579 return MK_E_NOPREFIX;
580 }
581
582 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(
583 LPMONIKER iface,
584 IMoniker* pmkOther,
585 IMoniker** ppmkRelPath)
586 {
587 TRACE("(%p, %p)\n", pmkOther, ppmkRelPath);
588
589 *ppmkRelPath = pmkOther;
590
591 return MK_S_HIM;
592 }
593
594 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(
595 LPMONIKER iface,
596 IBindCtx* pbc,
597 IMoniker* pmkToLeft,
598 LPOLESTR* ppszDisplayName)
599 {
600 MediaCatMoniker *This = (MediaCatMoniker *)iface;
601 WCHAR wszBuffer[MAX_PATH];
602 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
603 LONG received = sizeof(wszFriendlyName);
604
605 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName);
606
607 *ppszDisplayName = NULL;
608
609 /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
610 if (RegQueryValueW(This->hkey, wszFriendlyName, wszBuffer, &received) == ERROR_SUCCESS)
611 {
612 *ppszDisplayName = CoTaskMemAlloc(received);
613 strcpyW(*ppszDisplayName, wszBuffer);
614 return S_OK;
615 }
616
617 return E_FAIL;
618 }
619
620 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(
621 LPMONIKER iface,
622 IBindCtx* pbc,
623 IMoniker* pmkToLeft,
624 LPOLESTR pszDisplayName,
625 ULONG* pchEaten,
626 IMoniker** ppmkOut)
627 {
628 FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
629
630 *pchEaten = 0;
631 *ppmkOut = NULL;
632
633 return MK_E_SYNTAX;
634 }
635
636 static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsSystemMoniker(
637 LPMONIKER iface,
638 DWORD* pdwMksys)
639 {
640 TRACE("(%p)\n", pdwMksys);
641
642 return S_FALSE;
643 }
644
645 static IMonikerVtbl IMoniker_Vtbl =
646 {
647 DEVENUM_IMediaCatMoniker_QueryInterface,
648 DEVENUM_IMediaCatMoniker_AddRef,
649 DEVENUM_IMediaCatMoniker_Release,
650 DEVENUM_IMediaCatMoniker_GetClassID,
651 DEVENUM_IMediaCatMoniker_IsDirty,
652 DEVENUM_IMediaCatMoniker_Load,
653 DEVENUM_IMediaCatMoniker_Save,
654 DEVENUM_IMediaCatMoniker_GetSizeMax,
655 DEVENUM_IMediaCatMoniker_BindToObject,
656 DEVENUM_IMediaCatMoniker_BindToStorage,
657 DEVENUM_IMediaCatMoniker_Reduce,
658 DEVENUM_IMediaCatMoniker_ComposeWith,
659 DEVENUM_IMediaCatMoniker_Enum,
660 DEVENUM_IMediaCatMoniker_IsEqual,
661 DEVENUM_IMediaCatMoniker_Hash,
662 DEVENUM_IMediaCatMoniker_IsRunning,
663 DEVENUM_IMediaCatMoniker_GetTimeOfLastChange,
664 DEVENUM_IMediaCatMoniker_Inverse,
665 DEVENUM_IMediaCatMoniker_CommonPrefixWith,
666 DEVENUM_IMediaCatMoniker_RelativePathTo,
667 DEVENUM_IMediaCatMoniker_GetDisplayName,
668 DEVENUM_IMediaCatMoniker_ParseDisplayName,
669 DEVENUM_IMediaCatMoniker_IsSystemMoniker
670 };
671
672 MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct()
673 {
674 MediaCatMoniker * pMoniker = NULL;
675 pMoniker = CoTaskMemAlloc(sizeof(MediaCatMoniker));
676 if (!pMoniker)
677 return NULL;
678
679 pMoniker->lpVtbl = &IMoniker_Vtbl;
680 pMoniker->ref = 0;
681 pMoniker->hkey = NULL;
682
683 DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker);
684
685 DEVENUM_LockModule();
686
687 return pMoniker;
688 }
689
690 /**********************************************************************
691 * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
692 */
693 static HRESULT WINAPI DEVENUM_IEnumMoniker_QueryInterface(
694 LPENUMMONIKER iface,
695 REFIID riid,
696 LPVOID *ppvObj)
697 {
698 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
699 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
700
701 if (This == NULL || ppvObj == NULL) return E_POINTER;
702
703 if (IsEqualGUID(riid, &IID_IUnknown) ||
704 IsEqualGUID(riid, &IID_IEnumMoniker))
705 {
706 *ppvObj = (LPVOID)iface;
707 DEVENUM_IEnumMoniker_AddRef(iface);
708 return S_OK;
709 }
710
711 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
712 return E_NOINTERFACE;
713 }
714
715 /**********************************************************************
716 * DEVENUM_IEnumMoniker_AddRef (also IUnknown)
717 */
718 static ULONG WINAPI DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface)
719 {
720 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
721
722 TRACE("\n");
723
724 return InterlockedIncrement(&This->ref);
725 }
726
727 /**********************************************************************
728 * DEVENUM_IEnumMoniker_Release (also IUnknown)
729 */
730 static ULONG WINAPI DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface)
731 {
732 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
733
734 TRACE("\n");
735
736 if (!InterlockedDecrement(&This->ref))
737 {
738 RegCloseKey(This->hkey);
739 CoTaskMemFree(This);
740 DEVENUM_UnlockModule();
741 return 0;
742 }
743 return This->ref;
744 }
745
746 static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
747 {
748 WCHAR buffer[MAX_PATH + 1];
749 LONG res;
750 ULONG fetched = 0;
751 MediaCatMoniker * pMoniker;
752 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
753
754 TRACE("(%ld, %p, %p)\n", celt, rgelt, pceltFetched);
755
756 while (fetched < celt)
757 {
758 res = RegEnumKeyW(This->hkey, This->index, buffer, sizeof(buffer) / sizeof(WCHAR));
759 if (res != ERROR_SUCCESS)
760 {
761 break;
762 }
763 pMoniker = DEVENUM_IMediaCatMoniker_Construct();
764 if (!pMoniker)
765 return E_OUTOFMEMORY;
766
767 if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
768 {
769 DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker);
770 break;
771 }
772 rgelt[fetched] = (LPMONIKER)pMoniker;
773 fetched++;
774 }
775
776 This->index += fetched;
777
778 TRACE("-- fetched %ld\n", fetched);
779
780 if (pceltFetched)
781 *pceltFetched = fetched;
782
783 if (fetched != celt)
784 return S_FALSE;
785 else
786 return S_OK;
787 }
788
789 static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(LPENUMMONIKER iface, ULONG celt)
790 {
791 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
792
793 TRACE("(%ld)\n", celt);
794
795 This->index += celt;
796
797 return S_OK;
798 }
799
800 static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface)
801 {
802 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
803
804 TRACE("()\n");
805
806 This->index = 0;
807
808 return S_OK;
809 }
810
811 static HRESULT WINAPI DEVENUM_IEnumMoniker_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
812 {
813 FIXME("(%p): stub\n", ppenum);
814
815 return E_NOTIMPL;
816 }
817
818 /**********************************************************************
819 * IEnumMoniker_Vtbl
820 */
821 static IEnumMonikerVtbl IEnumMoniker_Vtbl =
822 {
823 DEVENUM_IEnumMoniker_QueryInterface,
824 DEVENUM_IEnumMoniker_AddRef,
825 DEVENUM_IEnumMoniker_Release,
826 DEVENUM_IEnumMoniker_Next,
827 DEVENUM_IEnumMoniker_Skip,
828 DEVENUM_IEnumMoniker_Reset,
829 DEVENUM_IEnumMoniker_Clone
830 };
831
832 HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
833 {
834 EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
835 if (!pEnumMoniker)
836 return E_OUTOFMEMORY;
837
838 pEnumMoniker->lpVtbl = &IEnumMoniker_Vtbl;
839 pEnumMoniker->ref = 1;
840 pEnumMoniker->index = 0;
841 pEnumMoniker->hkey = hkey;
842
843 *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
844
845 DEVENUM_LockModule();
846
847 return S_OK;
848 }