wintrust: Add a helper function to initialize chain creation parameters.
[wine] / dlls / msdmo / dmoreg.c
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 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "winerror.h"
26 #include "winreg.h"
27 #include "objbase.h"
28 #include "wine/unicode.h"
29 #include "wine/debug.h"
30 #include "initguid.h"
31 #include "dmo.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(msdmo);
34
35
36 static const WCHAR szDMORootKey[] = 
37 {
38     'D','i','r','e','c','t','S','h','o','w','\\',
39     'M','e','d','i','a','O','b','j','e','c','t','s',0
40 }; 
41
42 static const WCHAR szDMOInputType[] =
43 {
44     'I','n','p','u','t','T','y','p','e','s',0
45 };
46
47 static const WCHAR szDMOOutputType[] =
48 {
49     'O','u','t','p','u','t','T','y','p','e','s',0
50 };
51
52 static const WCHAR szDMOKeyed[] =
53 {
54     'K','e','y','e','d',0
55 };
56
57 static const WCHAR szDMOCategories[] =
58 {
59     'C','a','t','e','g','o','r','i','e','s',0
60 };
61
62 static const WCHAR szGUIDFmt[] =
63 {
64     '%','0','8','X','-','%','0','4','X','-','%','0','4','X','-','%','0',
65     '2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2',
66     'X','%','0','2','X','%','0','2','X','%','0','2','X',0
67 };
68
69 static const WCHAR szCat3Fmt[] =
70 {
71     '%','s','\\','%','s','\\','%','s',0
72 };
73
74 static const WCHAR szCat2Fmt[] =
75 {
76     '%','s','\\','%','s',0
77 };
78
79 static const WCHAR szToGuidFmt[] =
80 {
81     '{','%','s','}',0
82 };
83
84
85 typedef struct
86 {
87     const IEnumDMOVtbl         *lpVtbl;
88     LONG                        ref;
89     DWORD                       index;
90     const GUID*                 guidCategory;
91     DWORD                       dwFlags;
92     DWORD                       cInTypes;
93     DMO_PARTIAL_MEDIATYPE       *pInTypes;
94     DWORD                       cOutTypes;
95     DMO_PARTIAL_MEDIATYPE       *pOutTypes;
96     HKEY                        hkey;
97 } IEnumDMOImpl;
98
99 static const IEnumDMOVtbl edmovt;
100
101 static LPWSTR GUIDToString(LPWSTR lpwstr, REFGUID lpcguid)
102 {
103     wsprintfW(lpwstr, szGUIDFmt, lpcguid->Data1, lpcguid->Data2,
104         lpcguid->Data3, lpcguid->Data4[0], lpcguid->Data4[1],
105         lpcguid->Data4[2], lpcguid->Data4[3], lpcguid->Data4[4],
106         lpcguid->Data4[5], lpcguid->Data4[6], lpcguid->Data4[7]);
107
108     return lpwstr;
109 }
110
111 static BOOL IsMediaTypeEqual(const DMO_PARTIAL_MEDIATYPE* mt1, const DMO_PARTIAL_MEDIATYPE* mt2)
112 {
113
114     return (IsEqualCLSID(&mt1->type, &mt2->type) ||
115             IsEqualCLSID(&mt2->type, &GUID_NULL) ||
116             IsEqualCLSID(&mt1->type, &GUID_NULL)) &&
117             (IsEqualCLSID(&mt1->subtype, &mt2->subtype) ||
118             IsEqualCLSID(&mt2->subtype, &GUID_NULL) ||
119             IsEqualCLSID(&mt1->subtype, &GUID_NULL));
120 }
121
122 /***************************************************************
123  * DMORegister
124  *
125  * Register a DirectX Media Object.
126  */
127 HRESULT WINAPI DMORegister(
128    LPCWSTR szName,
129    REFCLSID clsidDMO,
130    REFGUID guidCategory,
131    DWORD dwFlags,
132    DWORD cInTypes,
133    const DMO_PARTIAL_MEDIATYPE *pInTypes,
134    DWORD cOutTypes,
135    const DMO_PARTIAL_MEDIATYPE *pOutTypes
136 )
137 {
138     WCHAR szguid[64];
139     HRESULT hres;
140     HKEY hrkey = 0;
141     HKEY hkey = 0;
142     HKEY hckey = 0;
143     HKEY hclskey = 0;
144
145     TRACE("%s\n", debugstr_w(szName));
146
147     hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &hrkey);
148     if (ERROR_SUCCESS != hres)
149         goto lend;
150
151     /* Create clsidDMO key under MediaObjects */ 
152     hres = RegCreateKeyExW(hrkey, GUIDToString(szguid, clsidDMO), 0, NULL,
153         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL);
154     if (ERROR_SUCCESS != hres)
155         goto lend;
156
157     /* Set default Name value */
158     hres = RegSetValueExW(hkey, NULL, 0, REG_SZ, (const BYTE*) szName, 
159         (strlenW(szName) + 1)) * sizeof(WCHAR);
160     /* Set InputTypes */
161     hres = RegSetValueExW(hkey, szDMOInputType, 0, REG_BINARY, 
162         (const BYTE*) pInTypes, cInTypes * sizeof(DMO_PARTIAL_MEDIATYPE));
163     /* Set OutputTypes */
164     hres = RegSetValueExW(hkey, szDMOOutputType, 0, REG_BINARY, 
165         (const BYTE*) pOutTypes, cOutTypes * sizeof(DMO_PARTIAL_MEDIATYPE));
166
167     if (dwFlags & DMO_REGISTERF_IS_KEYED)
168     {
169         /* Create Keyed key */ 
170         hres = RegCreateKeyExW(hkey, szDMOKeyed, 0, NULL,
171             REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hckey, NULL);
172         if (ERROR_SUCCESS != hres)
173             goto lend;
174         RegCloseKey(hckey);
175     }
176
177     /* Register the category */
178     hres = RegOpenKeyExW(hrkey, szDMOCategories, 0, KEY_WRITE, &hckey);
179     if (ERROR_SUCCESS != hres)
180         goto lend;
181
182     RegCloseKey(hkey);
183
184     hres = RegOpenKeyExW(hckey, GUIDToString(szguid, guidCategory), 0, KEY_WRITE, &hkey);
185     if (ERROR_SUCCESS != hres)
186         goto lend;
187     hres = RegCreateKeyExW(hkey, GUIDToString(szguid, clsidDMO), 0, NULL,
188         REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hclskey, NULL);
189     if (ERROR_SUCCESS != hres)
190         goto lend;
191
192 lend:
193     if (hkey)
194         RegCloseKey(hkey);
195     if (hckey)
196         RegCloseKey(hckey);
197     if (hclskey)
198         RegCloseKey(hclskey);
199     if (hrkey)
200         RegCloseKey(hrkey);
201
202     TRACE(" hresult=0x%08x\n", hres);
203     return hres;
204 }
205
206
207 /***************************************************************
208  * DMOUnregister
209  *
210  * Unregister a DirectX Media Object.
211  */
212 HRESULT WINAPI DMOUnregister(REFCLSID clsidDMO, REFGUID guidCategory)
213 {
214     HRESULT hres;
215     WCHAR szguid[64];
216     HKEY hrkey = 0;
217     HKEY hckey = 0;
218
219     GUIDToString(szguid, clsidDMO);
220
221     TRACE("%s %p\n", debugstr_w(szguid), guidCategory);
222
223     hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0, KEY_WRITE, &hrkey);
224     if (ERROR_SUCCESS != hres)
225         goto lend;
226
227     hres = RegDeleteKeyW(hrkey, szguid);
228     if (ERROR_SUCCESS != hres)
229         goto lend;
230
231     hres = RegOpenKeyExW(hrkey, szDMOCategories, 0, KEY_WRITE, &hckey);
232     if (ERROR_SUCCESS != hres)
233         goto lend;
234
235     hres = RegDeleteKeyW(hckey, szguid);
236     if (ERROR_SUCCESS != hres)
237         goto lend;
238
239 lend:
240     if (hckey)
241         RegCloseKey(hckey);
242     if (hrkey)
243         RegCloseKey(hrkey);
244
245     return hres;
246 }
247
248
249 /***************************************************************
250  * DMOGetName
251  *
252  * Get DMP Name from the registry
253  */
254 HRESULT WINAPI DMOGetName(REFCLSID clsidDMO, WCHAR* szName)
255 {
256     WCHAR szguid[64];
257     HRESULT hres;
258     HKEY hrkey = 0;
259     HKEY hkey = 0;
260     DWORD count;
261
262     TRACE("%s\n", debugstr_guid(clsidDMO));
263
264     hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 
265         0, KEY_READ, &hrkey);
266     if (ERROR_SUCCESS != hres)
267         goto lend;
268
269     hres = RegOpenKeyExW(hrkey, GUIDToString(szguid, clsidDMO),
270         0, KEY_READ, &hkey);
271     if (ERROR_SUCCESS != hres)
272         goto lend;
273
274     count = 80 * sizeof(WCHAR); /* 80 by API definition */
275     hres = RegQueryValueExW(hkey, NULL, NULL, NULL, 
276         (LPBYTE) szName, &count); 
277
278     TRACE(" szName=%s\n", debugstr_w(szName));
279 lend:
280     if (hkey)
281         RegCloseKey(hrkey);
282     if (hkey)
283         RegCloseKey(hkey);
284
285     return hres;
286 }
287
288
289 /**************************************************************************
290 *   IEnumDMO_Destructor
291 */
292 static BOOL IEnumDMO_Destructor(IEnumDMO* iface)
293 {
294     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
295
296     TRACE("%p\n", This);
297
298     if (This->hkey)
299         RegCloseKey(This->hkey);
300
301     HeapFree(GetProcessHeap(), 0, This->pInTypes);
302     HeapFree(GetProcessHeap(), 0, This->pOutTypes);
303
304     return TRUE;
305 }
306
307
308 /**************************************************************************
309  *  IEnumDMO_Constructor
310  */
311 static IEnumDMO * IEnumDMO_Constructor(
312     REFGUID guidCategory,
313     DWORD dwFlags,
314     DWORD cInTypes,
315     const DMO_PARTIAL_MEDIATYPE *pInTypes,
316     DWORD cOutTypes,
317     const DMO_PARTIAL_MEDIATYPE *pOutTypes)
318 {
319     UINT size;
320     IEnumDMOImpl* lpedmo;
321     BOOL ret = FALSE;
322
323     lpedmo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumDMOImpl));
324
325     if (lpedmo)
326     {
327         lpedmo->ref = 1;
328         lpedmo->lpVtbl = &edmovt;
329         lpedmo->index = -1;
330         lpedmo->guidCategory = guidCategory;
331         lpedmo->dwFlags = dwFlags;
332
333         size = cInTypes * sizeof(DMO_PARTIAL_MEDIATYPE);
334         lpedmo->pInTypes = HeapAlloc(GetProcessHeap(), 0, size);
335         if (!lpedmo->pInTypes)
336             goto lerr;
337         memcpy(lpedmo->pInTypes, pInTypes, size);
338         lpedmo->cInTypes = cInTypes;
339
340         size = cOutTypes * sizeof(DMO_PARTIAL_MEDIATYPE);
341         lpedmo->pOutTypes = HeapAlloc(GetProcessHeap(), 0, size);
342         if (!lpedmo->pOutTypes)
343             goto lerr;
344         memcpy(lpedmo->pOutTypes, pOutTypes, size);
345         lpedmo->cOutTypes = cOutTypes;
346
347         /* If not filtering by category enum from media objects root */
348         if (IsEqualGUID(guidCategory, &GUID_NULL))
349         {
350             if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 
351                 0, KEY_READ, &lpedmo->hkey))
352                 ret = TRUE;
353         }
354         else
355         {
356             WCHAR szguid[64];
357             WCHAR szKey[MAX_PATH];
358
359             wsprintfW(szKey, szCat3Fmt, szDMORootKey, szDMOCategories, 
360                 GUIDToString(szguid, guidCategory));
361             if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 
362                 0, KEY_READ, &lpedmo->hkey))
363                 ret = TRUE;
364         }
365
366 lerr:
367         if(!ret)
368         {
369             IEnumDMO_Destructor((IEnumDMO*)lpedmo);
370             HeapFree(GetProcessHeap(),0,lpedmo);
371             lpedmo = NULL;
372         }
373     }
374
375     TRACE("returning %p\n", lpedmo);
376
377     return (IEnumDMO*)lpedmo;
378 }
379
380
381 /******************************************************************************
382  * IEnumDMO_fnAddRef
383  */
384 static ULONG WINAPI IEnumDMO_fnAddRef(IEnumDMO * iface)
385 {
386     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
387     return InterlockedIncrement(&This->ref);
388 }
389
390
391 /**************************************************************************
392  *  EnumDMO_QueryInterface
393  */
394 static HRESULT WINAPI IEnumDMO_fnQueryInterface(
395     IEnumDMO* iface,
396     REFIID riid,
397     LPVOID *ppvObj)
398 {
399     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
400
401     *ppvObj = NULL;
402
403     if(IsEqualIID(riid, &IID_IUnknown))
404         *ppvObj = This;
405     else if(IsEqualIID(riid, &IID_IEnumDMO))
406         *ppvObj = (IEnumDMO*)This;
407
408     if(*ppvObj)
409     {
410         IEnumDMO_fnAddRef((IEnumDMO*)*ppvObj);
411         return S_OK;
412     }
413
414     return E_NOINTERFACE;
415 }
416
417
418 /******************************************************************************
419  * IEnumDMO_fnRelease
420  */
421 static ULONG WINAPI IEnumDMO_fnRelease(IEnumDMO * iface)
422 {
423     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
424     ULONG refCount = InterlockedDecrement(&This->ref);
425
426     if (!refCount)
427     {
428         IEnumDMO_Destructor((IEnumDMO*)This);
429         HeapFree(GetProcessHeap(),0,This);
430     }
431     return refCount;
432 }
433
434
435 /******************************************************************************
436  * IEnumDMO_fnNext
437  */
438 static HRESULT WINAPI IEnumDMO_fnNext(
439     IEnumDMO * iface, 
440     DWORD cItemsToFetch,
441     CLSID * pCLSID,
442     WCHAR ** Names,
443     DWORD * pcItemsFetched)
444 {
445     FILETIME ft;
446     HKEY hkey;
447     WCHAR szNextKey[MAX_PATH];
448     WCHAR szGuidKey[64];
449     WCHAR szKey[MAX_PATH];
450     WCHAR szValue[MAX_PATH];
451     DWORD len;
452     UINT count = 0;
453     HRESULT hres = S_OK;
454
455     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
456
457     TRACE("--> (%p) %d %p %p %p\n", iface, cItemsToFetch, pCLSID, Names, pcItemsFetched);
458
459     if (!pCLSID || !Names || !pcItemsFetched)
460         return E_POINTER;
461
462     while (count < cItemsToFetch)
463     {
464         This->index++;
465
466         hres = RegEnumKeyExW(This->hkey, This->index, szNextKey, &len, NULL, NULL, NULL, &ft);
467         if (hres != ERROR_SUCCESS)
468             break;
469
470         TRACE("found %s\n", debugstr_w(szNextKey));
471
472         if (This->dwFlags & DMO_REGISTERF_IS_KEYED)
473         {
474             wsprintfW(szKey, szCat3Fmt, szDMORootKey, szNextKey, szDMOKeyed);
475             hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey);
476             if (ERROR_SUCCESS != hres)
477                 continue;
478             RegCloseKey(hkey);
479         }
480
481         wsprintfW(szKey, szCat2Fmt, szDMORootKey, szNextKey);
482         hres = RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkey);
483
484         if (This->pInTypes)
485         {
486             UINT i, j;
487             DWORD cInTypes;
488             DMO_PARTIAL_MEDIATYPE* pInTypes;
489
490             len = MAX_PATH * sizeof(WCHAR);
491             hres = RegQueryValueExW(hkey, szDMOInputType, NULL, NULL, (LPBYTE) szValue, &len);
492             if (ERROR_SUCCESS != hres)
493             {
494                 RegCloseKey(hkey);
495                 continue;
496             }
497
498             cInTypes = len / sizeof(DMO_PARTIAL_MEDIATYPE);
499             pInTypes = (DMO_PARTIAL_MEDIATYPE*) szValue;
500
501             for (i = 0; i < This->cInTypes; i++)
502             {
503                 for (j = 0; j < cInTypes; j++) 
504                 {
505                     if (IsMediaTypeEqual(&pInTypes[j], &This->pInTypes[i]))
506                         break;
507                 }
508
509                 if (j >= cInTypes)
510                     break;
511             }
512
513             if (i < This->cInTypes)
514             {
515                 RegCloseKey(hkey);
516                 continue;
517             }
518         }
519
520         if (This->pOutTypes)
521         {
522             UINT i, j;
523             DWORD cOutTypes;
524             DMO_PARTIAL_MEDIATYPE* pOutTypes;
525
526             len = MAX_PATH * sizeof(WCHAR);
527             hres = RegQueryValueExW(hkey, szDMOOutputType, NULL, NULL, (LPBYTE) szValue, &len);
528             if (ERROR_SUCCESS != hres)
529             {
530                 RegCloseKey(hkey);
531                 continue;
532             }
533
534             cOutTypes = len / sizeof(DMO_PARTIAL_MEDIATYPE);
535             pOutTypes = (DMO_PARTIAL_MEDIATYPE*) szValue;
536
537             for (i = 0; i < This->cOutTypes; i++)
538             {
539                 for (j = 0; j < cOutTypes; j++) 
540                 {
541                     if (IsMediaTypeEqual(&pOutTypes[j], &This->pOutTypes[i]))
542                         break;
543                 }
544
545                 if (j >= cOutTypes)
546                     break;
547             }
548
549             if (i < This->cOutTypes)
550             {
551                 RegCloseKey(hkey);
552                 continue;
553             }
554         }
555
556         /* Media object wasn't filtered so add it to return list */
557         Names[count] = NULL;
558         len = MAX_PATH * sizeof(WCHAR);
559         hres = RegQueryValueExW(hkey, NULL, NULL, NULL, (LPBYTE) szValue, &len); 
560         if (ERROR_SUCCESS == hres)
561         {
562             Names[count] = HeapAlloc(GetProcessHeap(), 0, strlenW(szValue) + 1);
563             if (Names[count])
564                 strcmpW(Names[count], szValue);
565         }
566         wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
567         CLSIDFromString(szGuidKey, &pCLSID[count]);
568
569         TRACE("found match %s %s\n", debugstr_w(szValue), debugstr_w(szNextKey));
570         RegCloseKey(hkey);
571         count++;
572     }
573
574     *pcItemsFetched = count;
575     if (*pcItemsFetched < cItemsToFetch)
576         hres = S_FALSE;
577
578     TRACE("<-- %i found\n",count);
579     return hres;
580 }
581  
582
583 /******************************************************************************
584  * IEnumDMO_fnSkip
585  */
586 static HRESULT WINAPI IEnumDMO_fnSkip(IEnumDMO * iface, DWORD cItemsToSkip)
587 {
588     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
589
590     This->index += cItemsToSkip;
591
592     return S_OK;
593 }
594
595
596 /******************************************************************************
597  * IEnumDMO_fnReset
598  */
599 static HRESULT WINAPI IEnumDMO_fnReset(IEnumDMO * iface)
600 {
601     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
602
603     This->index = -1;
604
605     return S_OK;
606 }
607  
608
609 /******************************************************************************
610  * IEnumDMO_fnClone
611  */
612 static HRESULT WINAPI IEnumDMO_fnClone(IEnumDMO * iface, IEnumDMO **ppEnum)
613 {
614     IEnumDMOImpl *This = (IEnumDMOImpl *)iface;
615
616     FIXME("(%p)->() to (%p)->() E_NOTIMPL\n", This, ppEnum);
617
618   return E_NOTIMPL;
619 }
620
621
622 /***************************************************************
623  * DMOEnum
624  *
625  * Enumerate DirectX Media Objects in the registry.
626  */
627 HRESULT WINAPI DMOEnum(
628     REFGUID guidCategory,
629     DWORD dwFlags,
630     DWORD cInTypes,
631     const DMO_PARTIAL_MEDIATYPE *pInTypes,
632     DWORD cOutTypes,
633     const DMO_PARTIAL_MEDIATYPE *pOutTypes,
634     IEnumDMO **ppEnum)
635 {
636     HRESULT hres = E_FAIL;
637
638     TRACE("guidCategory=%p dwFlags=0x%08x cInTypes=%d cOutTypes=%d\n",
639         guidCategory, dwFlags, cInTypes, cOutTypes);
640
641     *ppEnum = IEnumDMO_Constructor(guidCategory, dwFlags, cInTypes,
642         pInTypes, cOutTypes, pOutTypes);
643     if (*ppEnum)
644         hres = S_OK;
645
646     return hres;
647 }
648
649
650 static const IEnumDMOVtbl edmovt =
651 {
652         IEnumDMO_fnQueryInterface,
653         IEnumDMO_fnAddRef,
654         IEnumDMO_fnRelease,
655         IEnumDMO_fnNext,
656         IEnumDMO_fnSkip,
657         IEnumDMO_fnReset,
658         IEnumDMO_fnClone,
659 };
660
661
662 HRESULT build_types(HKEY root, LPCWSTR key, ULONG *supplied, ULONG requested, DMO_PARTIAL_MEDIATYPE* types )
663 {
664     HRESULT ret = S_OK;
665     HKEY hkey;
666     WCHAR szGuidKey[64];
667
668     *supplied = 0;
669     if (ERROR_SUCCESS == RegOpenKeyExW(root, key, 0, KEY_READ, &hkey))
670     {
671       int index = 0;
672       WCHAR szNextKey[MAX_PATH];
673       DWORD len;
674       LONG rc = ERROR_SUCCESS;
675
676       len = MAX_PATH;
677       while (rc == ERROR_SUCCESS)
678       {
679         len = MAX_PATH;
680         rc = RegEnumKeyExW(hkey, index, szNextKey, &len, NULL, NULL, NULL, NULL);
681         if (rc == ERROR_SUCCESS)
682         {
683           HKEY subk;
684           int sub_index = 0;
685           LONG rcs = ERROR_SUCCESS;
686           WCHAR szSubKey[MAX_PATH];
687
688           RegOpenKeyExW(hkey, szNextKey, 0, KEY_READ, &subk);
689           while (rcs == ERROR_SUCCESS)
690           {
691             len = MAX_PATH;
692             rcs = RegEnumKeyExW(subk, sub_index, szSubKey, &len, NULL, NULL, NULL, NULL);
693             if (rcs == ERROR_SUCCESS)
694             {
695               if (*supplied >= requested)
696               {
697                 /* Bailing */
698                 ret = S_FALSE;
699                 rc = ERROR_MORE_DATA;
700                 rcs = ERROR_MORE_DATA;
701                 break;
702               }
703
704               wsprintfW(szGuidKey,szToGuidFmt,szNextKey);
705               CLSIDFromString(szGuidKey, &types[*supplied].type);
706               wsprintfW(szGuidKey,szToGuidFmt,szSubKey);
707               CLSIDFromString(szGuidKey, &types[*supplied].subtype);
708               TRACE("Adding type %s subtype %s at index %i\n",
709                 debugstr_guid(&types[*supplied].type),
710                 debugstr_guid(&types[*supplied].subtype),
711                 *supplied);
712               (*supplied)++;
713             }
714             sub_index++;
715           }
716           index++;
717         }
718       }
719       RegCloseKey(hkey);
720     }
721     return ret;
722 }
723
724
725 HRESULT WINAPI DMOGetTypes(REFCLSID clsidDMO,
726                ULONG ulInputTypesRequested,
727                ULONG* pulInputTypesSupplied,
728                DMO_PARTIAL_MEDIATYPE* pInputTypes,
729                ULONG ulOutputTypesRequested,
730                ULONG* pulOutputTypesSupplied,
731                DMO_PARTIAL_MEDIATYPE* pOutputTypes)
732 {
733   HKEY root,hkey;
734   HRESULT ret = S_OK;
735   WCHAR szguid[64];
736
737   TRACE ("(%s,%u,%p,%p,%u,%p,%p),stub!\n", debugstr_guid(clsidDMO),
738         ulInputTypesRequested, pulInputTypesSupplied, pInputTypes,
739         ulOutputTypesRequested, pulOutputTypesSupplied, pOutputTypes);
740
741   if (ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, szDMORootKey, 0,
742                                      KEY_READ, &root))
743     return E_FAIL;
744
745   if (ERROR_SUCCESS != RegOpenKeyExW(root,GUIDToString(szguid,clsidDMO) , 0,
746                                      KEY_READ, &hkey))
747   {
748     RegCloseKey(root);
749     return E_FAIL;
750   }
751
752   if (ulInputTypesRequested > 0)
753   {
754     ret = build_types(hkey, szDMOInputType, pulInputTypesSupplied, ulInputTypesRequested, pInputTypes );
755   }
756   else
757     *pulInputTypesSupplied = 0;
758
759   if (ulOutputTypesRequested > 0)
760   {
761     HRESULT ret2;
762     ret2 = build_types(hkey, szDMOOutputType, pulOutputTypesSupplied, ulOutputTypesRequested, pOutputTypes );
763
764     if (ret == S_OK)
765         ret = ret2;
766   }
767   else
768     *pulOutputTypesSupplied = 0;
769
770   return ret;
771 }