xref: /reactos/dll/directx/wine/msdmo/dmoreg.c (revision 8c2e9189)
1 /*
2  * Copyright (C) 2003 Michael Günnewig
3  * Copyright (C) 2003 CodeWeavers Inc. (Ulrich Czekalla)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include <stdarg.h>
21 
22 #define COBJMACROS
23 
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "winreg.h"
29 #include "objbase.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
32 #include "initguid.h"
33 #include "dmo.h"
34 
35 WINE_DEFAULT_DEBUG_CHANNEL(msdmo);
36 
37 #define MSDMO_MAJOR_VERSION 6
38 
39 static const WCHAR szDMORootKey[] =
40 {
41     'D','i','r','e','c','t','S','h','o','w','\\',
42     'M','e','d','i','a','O','b','j','e','c','t','s',0
43 };
44 
45 static const WCHAR szDMOInputType[] =
46 {
47     'I','n','p','u','t','T','y','p','e','s',0
48 };
49 
50 static const WCHAR szDMOOutputType[] =
51 {
52     'O','u','t','p','u','t','T','y','p','e','s',0
53 };
54 
55 static const WCHAR szDMOKeyed[] =
56 {
57     'K','e','y','e','d',0
58 };
59 
60 static const WCHAR szDMOCategories[] =
61 {
62     'C','a','t','e','g','o','r','i','e','s',0
63 };
64 
65 static const WCHAR szGUIDFmt[] =
66 {
67     '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0',
68     '2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2',
69     'X','%','0','2','X','%','0','2','X','%','0','2','X',0
70 };
71 
72 static const WCHAR szCat3Fmt[] =
73 {
74     '%','s','\\','%','s','\\','%','s',0
75 };
76 
77 static const WCHAR szCat2Fmt[] =
78 {
79     '%','s','\\','%','s',0
80 };
81 
82 static const WCHAR szToGuidFmt[] =
83 {
84     '{','%','s','}',0
85 };
86 
87 
88 typedef struct
89 {
90     IEnumDMO                    IEnumDMO_iface;
91     LONG			ref;
92     DWORD			index;
93     GUID                        category;
94     DWORD                       dwFlags;
95     DWORD                       cInTypes;
96     DMO_PARTIAL_MEDIATYPE       *pInTypes;
97     DWORD                       cOutTypes;
98     DMO_PARTIAL_MEDIATYPE       *pOutTypes;
99     HKEY                        hkey;
100 } IEnumDMOImpl;
101 
102 static inline IEnumDMOImpl *impl_from_IEnumDMO(IEnumDMO *iface)
103 {
104     return CONTAINING_RECORD(iface, IEnumDMOImpl, IEnumDMO_iface);
105 }
106 
107 static HRESULT read_types(HKEY root, LPCWSTR key, ULONG *supplied, ULONG requested, DMO_PARTIAL_MEDIATYPE* types);
108 
109 static const IEnumDMOVtbl edmovt;
110 
111 static LPWSTR GUIDToString(LPWSTR lpwstr, REFGUID lpcguid)
112 {
113     wsprintfW(lpwstr, szGUIDFmt, lpcguid->Data1, lpcguid->Data2,
114         lpcguid->Data3, lpcguid->Data4[0], lpcguid->Data4[1],
115         lpcguid->Data4[2], lpcguid->Data4[3], lpcguid->Data4[4],
116         lpcguid->Data4[5], lpcguid->Data4[6], lpcguid->Data4[7]);
117 
118     return lpwstr;
119 }
120 
121 static BOOL IsMediaTypeEqual(const DMO_PARTIAL_MEDIATYPE* mt1, const DMO_PARTIAL_MEDIATYPE* mt2)
122 {
123 
124     return (IsEqualCLSID(&mt1->type, &mt2->type) ||
125             IsEqualCLSID(&mt2->type, &GUID_NULL) ||
126             IsEqualCLSID(&mt1->type, &GUID_NULL)) &&
127             (IsEqualCLSID(&mt1->subtype, &mt2->subtype) ||
128             IsEqualCLSID(&mt2->subtype, &GUID_NULL) ||
129             IsEqualCLSID(&mt1->subtype, &GUID_NULL));
130 }
131 
132 static HRESULT write_types(HKEY hkey, LPCWSTR name, const DMO_PARTIAL_MEDIATYPE* types, DWORD count)
133 {
134     LONG ret;
135 
136     if (MSDMO_MAJOR_VERSION > 5)
137     {
138         ret = RegSetValueExW(hkey, name, 0, REG_BINARY, (const BYTE*) types,
139                           count* sizeof(DMO_PARTIAL_MEDIATYPE));
140     }
141     else
142     {
143         HKEY skey1,skey2,skey3;
144         DWORD index = 0;
145         WCHAR szGuidKey[64];
146 
147         ret = RegCreateKeyExW(hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
148                                KEY_WRITE, NULL, &skey1, NULL);
149         if (ret)
150             return HRESULT_FROM_WIN32(ret);
151 
152         while (index < count)
153         {
154             GUIDToString(szGuidKey,&types[index].type);
155             ret = RegCreateKeyExW(skey1, szGuidKey, 0, NULL,
156                         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey2, NULL);
157             GUIDToString(szGuidKey,&types[index].subtype);
158             ret = RegCreateKeyExW(skey2, szGuidKey, 0, NULL,
159                         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &skey3, NULL);
160             RegCloseKey(skey3);
161             RegCloseKey(skey2);
162             index ++;
163         }
164         RegCloseKey(skey1);
165     }
166 
167     return HRESULT_FROM_WIN32(ret);
168 }
169 
170 /***************************************************************
171  * DMORegister (MSDMO.@)
172  *
173  * Register a DirectX Media Object.
174  */
175 HRESULT WINAPI DMORegister(
176    LPCWSTR szName,
177    REFCLSID clsidDMO,
178    REFGUID guidCategory,
179    DWORD dwFlags,
180    DWORD cInTypes,
181    const DMO_PARTIAL_MEDIATYPE *pInTypes,
182    DWORD cOutTypes,
183    const DMO_PARTIAL_MEDIATYPE *pOutTypes
184 )
185 {
186     WCHAR szguid[64];
187     HRESULT hres;
188     HKEY hrkey = 0;
189     HKEY hkey = 0;
190     HKEY hckey = 0;
191     HKEY hclskey = 0;
192     LONG ret;
193 
194     TRACE("%s %s %s\n", debugstr_w(szName), debugstr_guid(clsidDMO), debugstr_guid(guidCategory));
195 
196     if (IsEqualGUID(guidCategory, &GUID_NULL))
197         return E_INVALIDARG;
198 
199     ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, NULL,
200         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hrkey, NULL);
201     if (ret)
202         return HRESULT_FROM_WIN32(ret);
203 
204     /* Create clsidDMO key under MediaObjects */
205     ret = RegCreateKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, NULL,
206         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL);
207     if (ret)
208         goto lend;
209 
210     /* Set default Name value */
211     ret = RegSetValueExW(hkey, NULL, 0, REG_SZ, (const BYTE*) szName,
212         (strlenW(szName) + 1) * sizeof(WCHAR));
213 
214     /* Set InputTypes */
215     hres = write_types(hkey, szDMOInputType, pInTypes, cInTypes);
216 
217     /* Set OutputTypes */
218     hres = write_types(hkey, szDMOOutputType, pOutTypes, cOutTypes);
219 
220     if (dwFlags & DMO_REGISTERF_IS_KEYED)
221     {
222         /* Create Keyed key */
223         ret = RegCreateKeyExW(hkey, szDMOKeyed, 0, NULL,
224             REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL);
225         if (ret)
226             goto lend;
227         RegCloseKey(hckey);
228     }
229 
230     /* Register the category */
231     ret = RegCreateKeyExW(hrkey, szDMOCategories, 0, NULL,
232             REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL);
233     if (ret)
234         goto lend;
235 
236     RegCloseKey(hkey);
237 
238     ret = RegCreateKeyExW(hckey, GUIDToString(szguid, guidCategory), 0, NULL,
239             REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL);
240     if (ret)
241         goto lend;
242     ret = RegCreateKeyExW(hkey, GUIDToString(szguid, clsidDMO), 0, NULL,
243         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hclskey, NULL);
244     if (ret)
245         goto lend;
246 
247 lend:
248     if (hkey)
249         RegCloseKey(hkey);
250     if (hckey)
251         RegCloseKey(hckey);
252     if (hclskey)
253         RegCloseKey(hclskey);
254     if (hrkey)
255         RegCloseKey(hrkey);
256 
257     hres = HRESULT_FROM_WIN32(ret);
258     TRACE(" hresult=0x%08x\n", hres);
259     return hres;
260 }
261 
262 static HRESULT unregister_dmo_from_category(const WCHAR *dmoW, const WCHAR *catW, HKEY categories)
263 {
264     HKEY catkey;
265     LONG ret;
266 
267     ret = RegOpenKeyExW(categories, catW, 0, KEY_WRITE, &catkey);
268     if (!ret)
269     {
270         ret = RegDeleteKeyW(catkey, dmoW);
271         RegCloseKey(catkey);
272     }
273 
274     return !ret ? S_OK : S_FALSE;
275 }
276 
277 /***************************************************************
278  * DMOUnregister (MSDMO.@)
279  *
280  * Unregister a DirectX Media Object.
281  */
282 HRESULT WINAPI DMOUnregister(REFCLSID dmo, REFGUID category)
283 {
284     HKEY rootkey = 0, categorieskey = 0;
285     WCHAR dmoW[64], catW[64];
286     HRESULT hr = S_FALSE;
287     LONG ret;
288 
289     TRACE("%s %s\n", debugstr_guid(dmo), debugstr_guid(category));
290 
291     ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &rootkey);
292     if (ret)
293         return S_FALSE;
294 
295     GUIDToString(dmoW, dmo);
296     RegDeleteKeyW(rootkey, dmoW);
297 
298     /* open 'Categories' */
299     ret = RegOpenKeyExW(rootkey, szDMOCategories, 0, KEY_WRITE|KEY_ENUMERATE_SUB_KEYS, &categorieskey);
300     RegCloseKey(rootkey);
301     if (ret)
302     {
303         hr = HRESULT_FROM_WIN32(ret);
304         goto lend;
305     }
306 
307     /* remove from all categories */
308     if (IsEqualGUID(category, &GUID_NULL))
309     {
310         DWORD index = 0, len = sizeof(catW)/sizeof(WCHAR);
311 
312         while (!RegEnumKeyExW(categorieskey, index++, catW, &len, NULL, NULL, NULL, NULL))
313             hr = unregister_dmo_from_category(dmoW, catW, categorieskey);
314     }
315     else
316     {
317         GUIDToString(catW, category);
318         hr = unregister_dmo_from_category(dmoW, catW, categorieskey);
319     }
320 
321 lend:
322     if (categorieskey)
323         RegCloseKey(categorieskey);
324 
325     return hr;
326 }
327 
328 
329 /***************************************************************
330  * DMOGetName (MSDMO.@)
331  *
332  * Get DMO Name from the registry
333  */
334 HRESULT WINAPI DMOGetName(REFCLSID clsidDMO, WCHAR name[])
335 {
336     static const INT max_name_len = 80*sizeof(WCHAR);
337     DWORD count = max_name_len;
338     WCHAR szguid[64];
339     HKEY hrkey, hkey;
340     LONG ret;
341 
342     TRACE("%s %p\n", debugstr_guid(clsidDMO), name);
343 
344     if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_READ, &hrkey))
345         return E_FAIL;
346 
347     ret = RegOpenKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, KEY_READ, &hkey);
348     RegCloseKey(hrkey);
349     if (ret)
350         return E_FAIL;
351 
352     ret = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE)name, &count);
353     RegCloseKey(hkey);
354 
355     if (!ret && count > 1)
356     {
357         TRACE("name=%s\n", debugstr_w(name));
358         return S_OK;
359     }
360 
361     name[0] = 0;
362     return S_FALSE;
363 }
364 
365 static HRESULT dup_partial_mediatype(const DMO_PARTIAL_MEDIATYPE *types, DWORD count, DMO_PARTIAL_MEDIATYPE **ret)
366 {
367     *ret = NULL;
368 
369     if (count == 0)
370         return S_OK;
371 
372     *ret = HeapAlloc(GetProcessHeap(), 0, count*sizeof(*types));
373     if (!*ret)
374         return E_OUTOFMEMORY;
375 
376     memcpy(*ret, types, count*sizeof(*types));
377     return S_OK;
378 }
379 
380 /**************************************************************************
381  *  IEnumDMO_Constructor
382  */
383 static HRESULT IEnumDMO_Constructor(
384     REFGUID guidCategory,
385     DWORD dwFlags,
386     DWORD cInTypes,
387     const DMO_PARTIAL_MEDIATYPE *pInTypes,
388     DWORD cOutTypes,
389     const DMO_PARTIAL_MEDIATYPE *pOutTypes,
390     IEnumDMO **obj)
391 {
392     IEnumDMOImpl* lpedmo;
393     HRESULT hr;
394     LONG ret;
395 
396     *obj = NULL;
397 
398     lpedmo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumDMOImpl));
399     if (!lpedmo)
400         return E_OUTOFMEMORY;
401 
402     lpedmo->IEnumDMO_iface.lpVtbl = &edmovt;
403     lpedmo->ref = 1;
404     lpedmo->index = -1;
405     lpedmo->category = *guidCategory;
406     lpedmo->dwFlags = dwFlags;
407     lpedmo->cInTypes = cInTypes;
408     lpedmo->cOutTypes = cOutTypes;
409 
410     hr = dup_partial_mediatype(pInTypes, cInTypes, &lpedmo->pInTypes);
411     if (FAILED(hr))
412         goto lerr;
413 
414     hr = dup_partial_mediatype(pOutTypes, cOutTypes, &lpedmo->pOutTypes);
415     if (FAILED(hr))
416         goto lerr;
417 
418     /* If not filtering by category enum from media objects root */
419     if (IsEqualGUID(guidCategory, &GUID_NULL))
420     {
421         if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_READ, &lpedmo->hkey)))
422             hr = HRESULT_FROM_WIN32(ret);
423     }
424     else
425     {
426         WCHAR szguid[64];
427         WCHAR szKey[MAX_PATH];
428 
429         wsprintfW(szKey, szCat3Fmt, szDMORootKey, szDMOCategories, GUIDToString(szguid, guidCategory));
430         if ((ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &lpedmo->hkey)))
431             hr = HRESULT_FROM_WIN32(ret);
432     }
433 
434 lerr:
435 
436     if (FAILED(hr))
437         IEnumDMO_Release(&lpedmo->IEnumDMO_iface);
438     else
439     {
440         TRACE("returning %p\n", lpedmo);
441         *obj = &lpedmo->IEnumDMO_iface;
442     }
443 
444     return hr;
445 }
446 
447 /******************************************************************************
448  * IEnumDMO_fnAddRef
449  */
450 static ULONG WINAPI IEnumDMO_fnAddRef(IEnumDMO * iface)
451 {
452     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
453     ULONG refCount = InterlockedIncrement(&This->ref);
454     TRACE("(%p)->(%d)\n", This, refCount);
455     return refCount;
456 }
457 
458 /**************************************************************************
459  *  EnumDMO_QueryInterface
460  */
461 static HRESULT WINAPI IEnumDMO_fnQueryInterface(IEnumDMO* iface, REFIID riid, void **ppvObj)
462 {
463     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
464 
465     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObj);
466 
467     *ppvObj = NULL;
468 
469     if (IsEqualIID(riid, &IID_IEnumDMO) ||
470         IsEqualIID(riid, &IID_IUnknown))
471     {
472         *ppvObj = iface;
473         IEnumDMO_AddRef(iface);
474     }
475 
476     return *ppvObj ? S_OK : E_NOINTERFACE;
477 }
478 
479 /******************************************************************************
480  * IEnumDMO_fnRelease
481  */
482 static ULONG WINAPI IEnumDMO_fnRelease(IEnumDMO * iface)
483 {
484     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
485     ULONG refCount = InterlockedDecrement(&This->ref);
486 
487     TRACE("(%p)->(%d)\n", This, refCount);
488 
489     if (!refCount)
490     {
491         if (This->hkey)
492             RegCloseKey(This->hkey);
493         HeapFree(GetProcessHeap(), 0, This->pInTypes);
494         HeapFree(GetProcessHeap(), 0, This->pOutTypes);
495         HeapFree(GetProcessHeap(), 0, This);
496     }
497     return refCount;
498 }
499 
500 
501 /******************************************************************************
502  * IEnumDMO_fnNext
503  */
504 static HRESULT WINAPI IEnumDMO_fnNext(
505     IEnumDMO * iface,
506     DWORD cItemsToFetch,
507     CLSID * pCLSID,
508     WCHAR ** Names,
509     DWORD * pcItemsFetched)
510 {
511     HKEY hkey;
512     WCHAR szNextKey[MAX_PATH];
513     WCHAR szGuidKey[64];
514     WCHAR szKey[MAX_PATH];
515     WCHAR szValue[MAX_PATH];
516     DWORD len;
517     UINT count = 0;
518     HRESULT hres = S_OK;
519     LONG ret;
520 
521     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
522 
523     TRACE("(%p)->(%d %p %p %p)\n", This, cItemsToFetch, pCLSID, Names, pcItemsFetched);
524 
525     if (!pCLSID || !Names || !pcItemsFetched)
526         return E_POINTER;
527 
528     while (count < cItemsToFetch)
529     {
530         This->index++;
531 
532         len = MAX_PATH;
533         ret = RegEnumKeyExW(This->hkey, This->index, szNextKey, &len, NULL, NULL, NULL, NULL);
534         if (ret != ERROR_SUCCESS)
535         {
536             hres = HRESULT_FROM_WIN32(ret);
537             break;
538         }
539 
540         TRACE("found %s\n", debugstr_w(szNextKey));
541 
542         if (!(This->dwFlags & DMO_ENUMF_INCLUDE_KEYED))
543         {
544             wsprintfW(szKey, szCat3Fmt, szDMORootKey, szNextKey, szDMOKeyed);
545             ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey);
546             if (ERROR_SUCCESS == ret)
547             {
548                 RegCloseKey(hkey);
549                 /* Skip Keyed entries */
550                 continue;
551             }
552         }
553 
554         wsprintfW(szKey, szCat2Fmt, szDMORootKey, szNextKey);
555         ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey);
556         TRACE("testing %s\n", debugstr_w(szKey));
557 
558         if (This->pInTypes)
559         {
560             UINT i, j;
561             DWORD cInTypes;
562             DMO_PARTIAL_MEDIATYPE* pInTypes;
563 
564             hres = read_types(hkey, szDMOInputType, &cInTypes,
565                     sizeof(szValue)/sizeof(DMO_PARTIAL_MEDIATYPE),
566                     (DMO_PARTIAL_MEDIATYPE*)szValue);
567 
568             if (FAILED(hres))
569             {
570                 RegCloseKey(hkey);
571                 continue;
572             }
573 
574 	    pInTypes = (DMO_PARTIAL_MEDIATYPE*) szValue;
575 
576             TRACE("read %d intypes for %s:\n", cInTypes, debugstr_w(szKey));
577             for (i = 0; i < cInTypes; i++) {
578                 TRACE("intype %d: type %s, subtype %s\n", i, debugstr_guid(&pInTypes[i].type),
579                     debugstr_guid(&pInTypes[i].subtype));
580             }
581 
582             for (i = 0; i < This->cInTypes; i++)
583             {
584                 for (j = 0; j < cInTypes; j++)
585                 {
586                     if (IsMediaTypeEqual(&pInTypes[j], &This->pInTypes[i]))
587 		        break;
588                 }
589 
590 		if (j >= cInTypes)
591                     break;
592             }
593 
594             if (i < This->cInTypes)
595             {
596                 RegCloseKey(hkey);
597                 continue;
598             }
599         }
600 
601         if (This->pOutTypes)
602         {
603             UINT i, j;
604             DWORD cOutTypes;
605             DMO_PARTIAL_MEDIATYPE* pOutTypes;
606 
607             hres = read_types(hkey, szDMOOutputType, &cOutTypes,
608                     sizeof(szValue)/sizeof(DMO_PARTIAL_MEDIATYPE),
609                     (DMO_PARTIAL_MEDIATYPE*)szValue);
610 
611 	    if (FAILED(hres))
612             {
613                 RegCloseKey(hkey);
614                 continue;
615             }
616 
617 	    pOutTypes = (DMO_PARTIAL_MEDIATYPE*) szValue;
618 
619             TRACE("read %d outtypes for %s:\n", cOutTypes, debugstr_w(szKey));
620             for (i = 0; i < cOutTypes; i++) {
621                 TRACE("outtype %d: type %s, subtype %s\n", i, debugstr_guid(&pOutTypes[i].type),
622                     debugstr_guid(&pOutTypes[i].subtype));
623             }
624 
625             for (i = 0; i < This->cOutTypes; i++)
626             {
627                 for (j = 0; j < cOutTypes; j++)
628                 {
629                     if (IsMediaTypeEqual(&pOutTypes[j], &This->pOutTypes[i]))
630 		        break;
631                 }
632 
633 		if (j >= cOutTypes)
634                     break;
635             }
636 
637             if (i < This->cOutTypes)
638             {
639                 RegCloseKey(hkey);
640                 continue;
641             }
642         }
643 
644 	/* Media object wasn't filtered so add it to return list */
645         Names[count] = NULL;
646 	len = MAX_PATH * sizeof(WCHAR);
647         ret = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE)szValue, &len);
648         if (ERROR_SUCCESS == ret)
649 	{
650             Names[count] = CoTaskMemAlloc((strlenW(szValue) + 1) * sizeof(WCHAR));
651 	    if (Names[count])
652                 strcpyW(Names[count], szValue);
653 	}
654         wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
655         CLSIDFromString(szGuidKey, &pCLSID[count]);
656 
657         TRACE("found match %s %s\n", debugstr_w(szValue), debugstr_w(szNextKey));
658         RegCloseKey(hkey);
659 	count++;
660     }
661 
662     *pcItemsFetched = count;
663     if (*pcItemsFetched < cItemsToFetch)
664         hres = S_FALSE;
665 
666     TRACE("<-- %i found\n",count);
667     return hres;
668 }
669 
670 
671 /******************************************************************************
672  * IEnumDMO_fnSkip
673  */
674 static HRESULT WINAPI IEnumDMO_fnSkip(IEnumDMO * iface, DWORD cItemsToSkip)
675 {
676     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
677 
678     TRACE("(%p)->(%d)\n", This, cItemsToSkip);
679     This->index += cItemsToSkip;
680 
681     return S_OK;
682 }
683 
684 
685 /******************************************************************************
686  * IEnumDMO_fnReset
687  */
688 static HRESULT WINAPI IEnumDMO_fnReset(IEnumDMO * iface)
689 {
690     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
691 
692     TRACE("(%p)\n", This);
693     This->index = -1;
694 
695     return S_OK;
696 }
697 
698 
699 /******************************************************************************
700  * IEnumDMO_fnClone
701  */
702 static HRESULT WINAPI IEnumDMO_fnClone(IEnumDMO *iface, IEnumDMO **ppEnum)
703 {
704     IEnumDMOImpl *This = impl_from_IEnumDMO(iface);
705     TRACE("(%p)->(%p)\n", This, ppEnum);
706     return IEnumDMO_Constructor(&This->category, This->dwFlags, This->cInTypes, This->pInTypes,
707         This->cOutTypes, This->pOutTypes, ppEnum);
708 }
709 
710 
711 /***************************************************************
712  * DMOEnum (MSDMO.@)
713  *
714  * Enumerate DirectX Media Objects in the registry.
715  */
716 HRESULT WINAPI DMOEnum(
717     REFGUID category,
718     DWORD flags,
719     DWORD cInTypes,
720     const DMO_PARTIAL_MEDIATYPE *pInTypes,
721     DWORD cOutTypes,
722     const DMO_PARTIAL_MEDIATYPE *pOutTypes,
723     IEnumDMO **ppEnum)
724 {
725     TRACE("%s 0x%08x %d %p %d %p %p\n", debugstr_guid(category), flags, cInTypes, pInTypes,
726         cOutTypes, pOutTypes, ppEnum);
727 
728     if (TRACE_ON(msdmo))
729     {
730         DWORD i;
731         if (cInTypes)
732         {
733             for (i = 0; i < cInTypes; i++)
734                 TRACE("intype %d - type %s, subtype %s\n", i, debugstr_guid(&pInTypes[i].type),
735                     debugstr_guid(&pInTypes[i].subtype));
736         }
737 
738         if (cOutTypes) {
739             for (i = 0; i < cOutTypes; i++)
740                 TRACE("outtype %d - type %s, subtype %s\n", i, debugstr_guid(&pOutTypes[i].type),
741                     debugstr_guid(&pOutTypes[i].subtype));
742         }
743     }
744 
745     return IEnumDMO_Constructor(category, flags, cInTypes,
746         pInTypes, cOutTypes, pOutTypes, ppEnum);
747 }
748 
749 
750 static const IEnumDMOVtbl edmovt =
751 {
752 	IEnumDMO_fnQueryInterface,
753 	IEnumDMO_fnAddRef,
754 	IEnumDMO_fnRelease,
755 	IEnumDMO_fnNext,
756 	IEnumDMO_fnSkip,
757 	IEnumDMO_fnReset,
758 	IEnumDMO_fnClone,
759 };
760 
761 
762 HRESULT read_types(HKEY root, LPCWSTR key, ULONG *supplied, ULONG requested, DMO_PARTIAL_MEDIATYPE* types )
763 {
764     HRESULT ret = S_OK;
765 
766     if (MSDMO_MAJOR_VERSION > 5)
767     {
768         DWORD len;
769         LONG rc;
770 
771         len = requested * sizeof(DMO_PARTIAL_MEDIATYPE);
772         rc = RegQueryValueExW(root, key, NULL, NULL, (LPBYTE) types, &len);
773         ret = HRESULT_FROM_WIN32(rc);
774 
775         *supplied = len / sizeof(DMO_PARTIAL_MEDIATYPE);
776     }
777     else
778     {
779         HKEY hkey;
780         WCHAR szGuidKey[64];
781 
782         *supplied = 0;
783         if (ERROR_SUCCESS == RegOpenKeyExW(root, key, 0, KEY_READ, &hkey))
784         {
785           int index = 0;
786           WCHAR szNextKey[MAX_PATH];
787           DWORD len;
788           LONG rc = ERROR_SUCCESS;
789 
790           while (rc == ERROR_SUCCESS)
791           {
792             len = MAX_PATH;
793             rc = RegEnumKeyExW(hkey, index, szNextKey, &len, NULL, NULL, NULL, NULL);
794             if (rc == ERROR_SUCCESS)
795             {
796               HKEY subk;
797               int sub_index = 0;
798               LONG rcs = ERROR_SUCCESS;
799               WCHAR szSubKey[MAX_PATH];
800 
801               RegOpenKeyExW(hkey, szNextKey, 0, KEY_READ, &subk);
802               while (rcs == ERROR_SUCCESS)
803               {
804                 len = MAX_PATH;
805                 rcs = RegEnumKeyExW(subk, sub_index, szSubKey, &len, NULL, NULL, NULL, NULL);
806                 if (rcs == ERROR_SUCCESS)
807                 {
808                   if (*supplied >= requested)
809                   {
810                     /* Bailing */
811                     ret = S_FALSE;
812                     rc = ERROR_MORE_DATA;
813                     rcs = ERROR_MORE_DATA;
814                     break;
815                   }
816 
817                   wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
818                   CLSIDFromString(szGuidKey, &types[*supplied].type);
819                   wsprintfW(szGuidKey,szToGuidFmt,szSubKey);
820                   CLSIDFromString(szGuidKey, &types[*supplied].subtype);
821                   TRACE("Adding type %s subtype %s at index %i\n",
822                     debugstr_guid(&types[*supplied].type),
823                     debugstr_guid(&types[*supplied].subtype),
824                     *supplied);
825                   (*supplied)++;
826                 }
827                 sub_index++;
828               }
829               index++;
830             }
831           }
832           RegCloseKey(hkey);
833         }
834     }
835     return ret;
836 }
837 
838 /***************************************************************
839  * DMOGetTypes (MSDMO.@)
840  */
841 HRESULT WINAPI DMOGetTypes(REFCLSID clsidDMO,
842                ULONG ulInputTypesRequested,
843                ULONG* pulInputTypesSupplied,
844                DMO_PARTIAL_MEDIATYPE* pInputTypes,
845                ULONG ulOutputTypesRequested,
846                ULONG* pulOutputTypesSupplied,
847                DMO_PARTIAL_MEDIATYPE* pOutputTypes)
848 {
849   HKEY root,hkey;
850   HRESULT ret = S_OK;
851   WCHAR szguid[64];
852 
853   TRACE ("(%s,%u,%p,%p,%u,%p,%p)\n", debugstr_guid(clsidDMO), ulInputTypesRequested,
854         pulInputTypesSupplied, pInputTypes, ulOutputTypesRequested, pulOutputTypesSupplied,
855         pOutputTypes);
856 
857   if (ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0,
858                                      KEY_READ, &root))
859     return E_FAIL;
860 
861   if (ERROR_SUCCESS != RegOpenKeyExW(root,GUIDToString(szguid,clsidDMO) , 0,
862                                      KEY_READ, &hkey))
863   {
864     RegCloseKey(root);
865     return E_FAIL;
866   }
867 
868   if (ulInputTypesRequested > 0)
869   {
870     ret = read_types(hkey, szDMOInputType, pulInputTypesSupplied, ulInputTypesRequested, pInputTypes );
871   }
872   else
873     *pulInputTypesSupplied = 0;
874 
875   if (ulOutputTypesRequested > 0)
876   {
877     HRESULT ret2;
878     ret2 = read_types(hkey, szDMOOutputType, pulOutputTypesSupplied, ulOutputTypesRequested, pOutputTypes );
879 
880     if (ret == S_OK)
881         ret = ret2;
882   }
883   else
884     *pulOutputTypesSupplied = 0;
885 
886   return ret;
887 }
888