ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

createdevenum.c
Go to the documentation of this file.
00001 /*
00002  *  ICreateDevEnum implementation for DEVENUM.dll
00003  *
00004  * Copyright (C) 2002 Robert Shearman
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * NOTES ON THIS FILE:
00021  * - Implements ICreateDevEnum interface which creates an IEnumMoniker
00022  *   implementation
00023  * - Also creates the special registry keys created at run-time
00024  */
00025 
00026 #define NONAMELESSSTRUCT
00027 #define NONAMELESSUNION
00028 
00029 #include "devenum_private.h"
00030 #include "vfw.h"
00031 
00032 #include "wine/debug.h"
00033 #include "wine/unicode.h"
00034 #include "mmddk.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(devenum);
00037 
00038 extern HINSTANCE DEVENUM_hInstance;
00039 
00040 const WCHAR wszInstanceKeyName[] ={'I','n','s','t','a','n','c','e',0};
00041 
00042 static const WCHAR wszRegSeparator[] =   {'\\', 0 };
00043 static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
00044                                    'M','i','c','r','o','s','o','f','t','\\',
00045                                    'A','c','t','i','v','e','M','o','v','i','e','\\',
00046                                    'd','e','v','e','n','u','m','\\',0};
00047 static const WCHAR wszFilterKeyName[] = {'F','i','l','t','e','r',0};
00048 static const WCHAR wszMeritName[] = {'M','e','r','i','t',0};
00049 static const WCHAR wszPins[] = {'P','i','n','s',0};
00050 static const WCHAR wszAllowedMany[] = {'A','l','l','o','w','e','d','M','a','n','y',0};
00051 static const WCHAR wszAllowedZero[] = {'A','l','l','o','w','e','d','Z','e','r','o',0};
00052 static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
00053 static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
00054 static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
00055 
00056 static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
00057 static HRESULT DEVENUM_CreateSpecialCategories(void);
00058 
00059 /**********************************************************************
00060  * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
00061  */
00062 static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(
00063     ICreateDevEnum * iface,
00064     REFIID riid,
00065     LPVOID *ppvObj)
00066 {
00067     TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
00068 
00069     if (ppvObj == NULL) return E_POINTER;
00070 
00071     if (IsEqualGUID(riid, &IID_IUnknown) ||
00072     IsEqualGUID(riid, &IID_ICreateDevEnum))
00073     {
00074         *ppvObj = iface;
00075     DEVENUM_ICreateDevEnum_AddRef(iface);
00076     return S_OK;
00077     }
00078 
00079     FIXME("- no interface IID: %s\n", debugstr_guid(riid));
00080     return E_NOINTERFACE;
00081 }
00082 
00083 /**********************************************************************
00084  * DEVENUM_ICreateDevEnum_AddRef (also IUnknown)
00085  */
00086 static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface)
00087 {
00088     TRACE("\n");
00089 
00090     DEVENUM_LockModule();
00091 
00092     return 2; /* non-heap based object */
00093 }
00094 
00095 /**********************************************************************
00096  * DEVENUM_ICreateDevEnum_Release (also IUnknown)
00097  */
00098 static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface)
00099 {
00100     TRACE("\n");
00101 
00102     DEVENUM_UnlockModule();
00103 
00104     return 1; /* non-heap based object */
00105 }
00106 
00107 HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR *wszRegKeyName, UINT maxLen)
00108 {
00109     if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
00110         IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
00111         IsEqualGUID(clsidDeviceClass, &CLSID_VideoInputDeviceCategory) ||
00112         IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
00113     {
00114         *pBaseKey = HKEY_CURRENT_USER;
00115         strcpyW(wszRegKeyName, wszActiveMovieKey);
00116 
00117         if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + strlenW(wszRegKeyName), maxLen - strlenW(wszRegKeyName)))
00118             return E_OUTOFMEMORY;
00119     }
00120     else
00121     {
00122         *pBaseKey = HKEY_CLASSES_ROOT;
00123         strcpyW(wszRegKeyName, clsid_keyname);
00124         strcatW(wszRegKeyName, wszRegSeparator);
00125 
00126         if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + CLSID_STR_LEN, maxLen - CLSID_STR_LEN))
00127             return E_OUTOFMEMORY;
00128 
00129         strcatW(wszRegKeyName, wszRegSeparator);
00130         strcatW(wszRegKeyName, wszInstanceKeyName);
00131     }
00132 
00133     return S_OK;
00134 }
00135 
00136 static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin)
00137 {
00138     HKEY hkeyTypes = NULL;
00139     DWORD dwMajorTypes, i;
00140     REGPINTYPES *lpMediaType = NULL;
00141     DWORD dwMediaTypeSize = 0;
00142 
00143     if (RegOpenKeyExW(hkeyPinKey, wszTypes, 0, KEY_READ, &hkeyTypes) != ERROR_SUCCESS)
00144         return ;
00145 
00146     if (RegQueryInfoKeyW(hkeyTypes, NULL, NULL, NULL, &dwMajorTypes, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
00147                 != ERROR_SUCCESS)
00148     {
00149         RegCloseKey(hkeyTypes);
00150         return ;
00151     }
00152 
00153     for (i = 0; i < dwMajorTypes; i++)
00154     {
00155         HKEY hkeyMajorType = NULL;
00156         WCHAR wszMajorTypeName[64];
00157         DWORD cName = sizeof(wszMajorTypeName) / sizeof(WCHAR);
00158         DWORD dwMinorTypes, i1;
00159 
00160         if (RegEnumKeyExW(hkeyTypes, i, wszMajorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
00161 
00162         if (RegOpenKeyExW(hkeyTypes, wszMajorTypeName, 0, KEY_READ, &hkeyMajorType) != ERROR_SUCCESS) continue;
00163 
00164         if (RegQueryInfoKeyW(hkeyMajorType, NULL, NULL, NULL, &dwMinorTypes, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
00165                     != ERROR_SUCCESS)
00166         {
00167             RegCloseKey(hkeyMajorType);
00168             continue;
00169         }
00170 
00171         for (i1 = 0; i1 < dwMinorTypes; i1++)
00172         {
00173             WCHAR wszMinorTypeName[64];
00174             DWORD cName = sizeof(wszMinorTypeName) / sizeof(WCHAR);
00175             CLSID *clsMajorType = NULL, *clsMinorType = NULL;
00176             HRESULT hr;
00177 
00178             if (RegEnumKeyExW(hkeyMajorType, i1, wszMinorTypeName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
00179 
00180             clsMinorType = CoTaskMemAlloc(sizeof(CLSID));
00181             if (!clsMinorType) continue;
00182 
00183             clsMajorType = CoTaskMemAlloc(sizeof(CLSID));
00184             if (!clsMajorType) goto error_cleanup_types;
00185 
00186             hr = CLSIDFromString(wszMinorTypeName, clsMinorType);
00187             if (FAILED(hr)) goto error_cleanup_types;
00188 
00189             hr = CLSIDFromString(wszMajorTypeName, clsMajorType);
00190             if (FAILED(hr)) goto error_cleanup_types;
00191 
00192             if (rgPin->nMediaTypes == dwMediaTypeSize)
00193             {
00194                 DWORD dwNewSize = dwMediaTypeSize + (dwMediaTypeSize < 2 ? 1 : dwMediaTypeSize / 2);
00195                 REGPINTYPES *lpNewMediaType;
00196 
00197                 lpNewMediaType = CoTaskMemRealloc(lpMediaType, sizeof(REGPINTYPES) * dwNewSize);
00198                 if (!lpNewMediaType) goto error_cleanup_types;
00199 
00200                 lpMediaType = lpNewMediaType;
00201                 dwMediaTypeSize = dwNewSize;
00202              }
00203 
00204             lpMediaType[rgPin->nMediaTypes].clsMajorType = clsMajorType;
00205             lpMediaType[rgPin->nMediaTypes].clsMinorType = clsMinorType;
00206             rgPin->nMediaTypes++;
00207             continue;
00208 
00209             error_cleanup_types:
00210 
00211             if (clsMajorType) CoTaskMemFree(clsMajorType);
00212             if (clsMinorType) CoTaskMemFree(clsMinorType);
00213         }
00214 
00215         RegCloseKey(hkeyMajorType);
00216     }
00217 
00218     RegCloseKey(hkeyTypes);
00219 
00220     if (lpMediaType && !rgPin->nMediaTypes)
00221     {
00222         CoTaskMemFree(lpMediaType);
00223         lpMediaType = NULL;
00224     }
00225 
00226     rgPin->lpMediaType = lpMediaType;
00227 }
00228 
00229 static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
00230 {
00231     HKEY hkeyPins = NULL;
00232     DWORD dwPinsSubkeys, i;
00233     REGFILTERPINS *rgPins = NULL;
00234 
00235     if (RegOpenKeyExW(hkeyFilterClass, wszPins, 0, KEY_READ, &hkeyPins) != ERROR_SUCCESS)
00236         return ;
00237 
00238     if (RegQueryInfoKeyW(hkeyPins, NULL, NULL, NULL, &dwPinsSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
00239                 != ERROR_SUCCESS)
00240     {
00241         RegCloseKey(hkeyPins);
00242         return ;
00243     }
00244 
00245     if (dwPinsSubkeys)
00246     {
00247         rgPins = CoTaskMemAlloc(sizeof(REGFILTERPINS) * dwPinsSubkeys);
00248         if (!rgPins)
00249         {
00250             RegCloseKey(hkeyPins);
00251             return ;
00252         }
00253     }
00254 
00255     for (i = 0; i < dwPinsSubkeys; i++)
00256     {
00257         HKEY hkeyPinKey = NULL;
00258         WCHAR wszPinName[MAX_PATH];
00259         DWORD cName = sizeof(wszPinName) / sizeof(WCHAR);
00260         DWORD Type, cbData;
00261         REGFILTERPINS *rgPin = &rgPins[rgf2->u.s.cPins];
00262         LONG lRet;
00263 
00264         rgPin->strName = NULL;
00265         rgPin->clsConnectsToFilter = &GUID_NULL;
00266         rgPin->strConnectsToPin = NULL;
00267         rgPin->nMediaTypes = 0;
00268         rgPin->lpMediaType = NULL;
00269 
00270         if (RegEnumKeyExW(hkeyPins, i, wszPinName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
00271 
00272         if (RegOpenKeyExW(hkeyPins, wszPinName, 0, KEY_READ, &hkeyPinKey) != ERROR_SUCCESS) continue;
00273 
00274         rgPin->strName = CoTaskMemAlloc((strlenW(wszPinName) + 1) * sizeof(WCHAR));
00275         if (!rgPin->strName) goto error_cleanup;
00276 
00277         strcpyW(rgPin->strName, wszPinName);
00278 
00279         cbData = sizeof(rgPin->bMany);
00280         lRet = RegQueryValueExW(hkeyPinKey, wszAllowedMany, NULL, &Type, (LPBYTE)&rgPin->bMany, &cbData);
00281         if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
00282             goto error_cleanup;
00283 
00284         cbData = sizeof(rgPin->bZero);
00285         lRet = RegQueryValueExW(hkeyPinKey, wszAllowedZero, NULL, &Type, (LPBYTE)&rgPin->bZero, &cbData);
00286         if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
00287             goto error_cleanup;
00288 
00289         cbData = sizeof(rgPin->bOutput);
00290         lRet = RegQueryValueExW(hkeyPinKey, wszDirection, NULL, &Type, (LPBYTE)&rgPin->bOutput, &cbData);
00291         if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
00292             goto error_cleanup;
00293 
00294         cbData = sizeof(rgPin->bRendered);
00295         lRet = RegQueryValueExW(hkeyPinKey, wszIsRendered, NULL, &Type, (LPBYTE)&rgPin->bRendered, &cbData);
00296         if (lRet != ERROR_SUCCESS || Type != REG_DWORD)
00297             goto error_cleanup;
00298 
00299         DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
00300 
00301         ++rgf2->u.s.cPins;
00302         continue;
00303 
00304         error_cleanup:
00305 
00306         RegCloseKey(hkeyPinKey);
00307         if (rgPin->strName) CoTaskMemFree(rgPin->strName);
00308     }
00309 
00310     RegCloseKey(hkeyPins);
00311 
00312     if (rgPins && !rgf2->u.s.cPins)
00313     {
00314         CoTaskMemFree(rgPins);
00315         rgPins = NULL;
00316     }
00317 
00318     rgf2->u.s.rgPins = rgPins;
00319 }
00320 
00321 static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
00322 {
00323     HKEY hkeyFilter = NULL;
00324     DWORD dwFilterSubkeys, i;
00325     LONG lRet;
00326     IFilterMapper2 *pMapper = NULL;
00327     HRESULT hr;
00328 
00329     hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
00330                            &IID_IFilterMapper2, (void **) &pMapper);
00331     if (SUCCEEDED(hr))
00332     {
00333         lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszFilterKeyName, 0, KEY_READ, &hkeyFilter);
00334         hr = HRESULT_FROM_WIN32(lRet);
00335     }
00336 
00337     if (SUCCEEDED(hr))
00338     {
00339         lRet = RegQueryInfoKeyW(hkeyFilter, NULL, NULL, NULL, &dwFilterSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
00340         hr = HRESULT_FROM_WIN32(lRet);
00341     }
00342 
00343     if (SUCCEEDED(hr))
00344     {
00345         for (i = 0; i < dwFilterSubkeys; i++)
00346         {
00347             WCHAR wszFilterSubkeyName[64];
00348             DWORD cName = sizeof(wszFilterSubkeyName) / sizeof(WCHAR);
00349             HKEY hkeyCategoryBaseKey;
00350             WCHAR wszRegKey[MAX_PATH];
00351             HKEY hkeyInstance = NULL;
00352             HRESULT hr;
00353 
00354             if (RegEnumKeyExW(hkeyFilter, i, wszFilterSubkeyName, &cName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) continue;
00355 
00356             hr = DEVENUM_GetCategoryKey(&CLSID_LegacyAmFilterCategory, &hkeyCategoryBaseKey, wszRegKey, MAX_PATH);
00357             if (FAILED(hr)) continue;
00358 
00359             strcatW(wszRegKey, wszRegSeparator);
00360             strcatW(wszRegKey, wszFilterSubkeyName);
00361 
00362             if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyInstance) == ERROR_SUCCESS)
00363             {
00364                 RegCloseKey(hkeyInstance);
00365             }
00366             else
00367             {
00368                 /* Filter is registered the IFilterMapper(1)-way in HKCR\Filter. Needs to be added to
00369                  * legacy am filter category. */
00370                 HKEY hkeyFilterClass = NULL;
00371                 REGFILTER2 rgf2;
00372                 CLSID clsidFilter;
00373                 WCHAR wszFilterName[MAX_PATH];
00374                 DWORD Type;
00375                 DWORD cbData;
00376                 HRESULT res;
00377                 IMoniker *pMoniker = NULL;
00378 
00379                 TRACE("Registering %s\n", debugstr_w(wszFilterSubkeyName));
00380 
00381                 strcpyW(wszRegKey, clsid_keyname);
00382                 strcatW(wszRegKey, wszRegSeparator);
00383                 strcatW(wszRegKey, wszFilterSubkeyName);
00384 
00385                 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszRegKey, 0, KEY_READ, &hkeyFilterClass) != ERROR_SUCCESS)
00386                     continue;
00387 
00388                 rgf2.dwVersion = 1;
00389                 rgf2.dwMerit = 0;
00390                 rgf2.u.s.cPins = 0;
00391                 rgf2.u.s.rgPins = NULL;
00392 
00393                 cbData = sizeof(wszFilterName);
00394                 if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS ||
00395                     Type != REG_SZ)
00396                     goto cleanup;
00397 
00398                 cbData = sizeof(rgf2.dwMerit);
00399                 if (RegQueryValueExW(hkeyFilterClass, wszMeritName, NULL, &Type, (LPBYTE)&rgf2.dwMerit, &cbData) != ERROR_SUCCESS ||
00400                     Type != REG_DWORD)
00401                     goto cleanup;
00402 
00403                 DEVENUM_ReadPins(hkeyFilterClass, &rgf2);
00404 
00405                 res = CLSIDFromString(wszFilterSubkeyName, &clsidFilter);
00406                 if (FAILED(res)) goto cleanup;
00407 
00408                 IFilterMapper2_RegisterFilter(pMapper, &clsidFilter, wszFilterName, &pMoniker, NULL, NULL, &rgf2);
00409 
00410                 if (pMoniker)
00411                     IMoniker_Release(pMoniker);
00412 
00413                 cleanup:
00414 
00415                 if (hkeyFilterClass) RegCloseKey(hkeyFilterClass);
00416 
00417                 if (rgf2.u.s.rgPins)
00418                 {
00419                     UINT iPin;
00420 
00421                     for (iPin = 0; iPin < rgf2.u.s.cPins; iPin++)
00422                     {
00423                         CoTaskMemFree(rgf2.u.s.rgPins[iPin].strName);
00424 
00425                         if (rgf2.u.s.rgPins[iPin].lpMediaType)
00426                         {
00427                             UINT iType;
00428 
00429                             for (iType = 0; iType < rgf2.u.s.rgPins[iPin].nMediaTypes; iType++)
00430                             {
00431                                 CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMajorType);
00432                                 CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMinorType);
00433                             }
00434 
00435                             CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType);
00436                         }
00437                     }
00438 
00439                     CoTaskMemFree((void*)rgf2.u.s.rgPins);
00440                 }
00441             }
00442         }
00443     }
00444 
00445     if (hkeyFilter) RegCloseKey(hkeyFilter);
00446 
00447     if (pMapper)
00448         IFilterMapper2_Release(pMapper);
00449 
00450     return S_OK;
00451 }
00452 
00453 /**********************************************************************
00454  * DEVENUM_ICreateDevEnum_CreateClassEnumerator
00455  */
00456 static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
00457     ICreateDevEnum * iface,
00458     REFCLSID clsidDeviceClass,
00459     IEnumMoniker **ppEnumMoniker,
00460     DWORD dwFlags)
00461 {
00462     WCHAR wszRegKey[MAX_PATH];
00463     HKEY hkey;
00464     HKEY hbasekey;
00465     HRESULT hr;
00466     CreateDevEnumImpl *This = (CreateDevEnumImpl *)iface;
00467 
00468     TRACE("(%p)->(%s, %p, %x)\n\tDeviceClass:\t%s\n", This, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags, debugstr_guid(clsidDeviceClass));
00469 
00470     if (!ppEnumMoniker)
00471         return E_POINTER;
00472 
00473     *ppEnumMoniker = NULL;
00474 
00475     if (IsEqualGUID(clsidDeviceClass, &CLSID_LegacyAmFilterCategory))
00476     {
00477         DEVENUM_RegisterLegacyAmFilters();
00478     }
00479 
00480     hr = DEVENUM_GetCategoryKey(clsidDeviceClass, &hbasekey, wszRegKey, MAX_PATH);
00481     if (FAILED(hr))
00482         return hr;
00483 
00484     if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
00485         IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
00486         IsEqualGUID(clsidDeviceClass, &CLSID_VideoInputDeviceCategory) ||
00487         IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
00488     {
00489          hr = DEVENUM_CreateSpecialCategories();
00490          if (FAILED(hr))
00491              return hr;
00492          if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
00493          {
00494              ERR("Couldn't open registry key for special device: %s\n",
00495                  debugstr_guid(clsidDeviceClass));
00496              return S_FALSE;
00497          }
00498     }
00499     else if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
00500     {
00501         FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
00502         return S_FALSE;
00503     }
00504 
00505     return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker);
00506 }
00507 
00508 /**********************************************************************
00509  * ICreateDevEnum_Vtbl
00510  */
00511 static const ICreateDevEnumVtbl ICreateDevEnum_Vtbl =
00512 {
00513     DEVENUM_ICreateDevEnum_QueryInterface,
00514     DEVENUM_ICreateDevEnum_AddRef,
00515     DEVENUM_ICreateDevEnum_Release,
00516     DEVENUM_ICreateDevEnum_CreateClassEnumerator,
00517 };
00518 
00519 /**********************************************************************
00520  * static CreateDevEnum instance
00521  */
00522 CreateDevEnumImpl DEVENUM_CreateDevEnum = { &ICreateDevEnum_Vtbl };
00523 
00524 /**********************************************************************
00525  * DEVENUM_CreateAMCategoryKey (INTERNAL)
00526  *
00527  * Creates a registry key for a category at HKEY_CURRENT_USER\Software\
00528  * Microsoft\ActiveMovie\devenum\{clsid}
00529  */
00530 static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
00531 {
00532     WCHAR wszRegKey[MAX_PATH];
00533     HRESULT res = S_OK;
00534     HKEY hkeyDummy = NULL;
00535 
00536     strcpyW(wszRegKey, wszActiveMovieKey);
00537 
00538     if (!StringFromGUID2(clsidCategory, wszRegKey + strlenW(wszRegKey), sizeof(wszRegKey)/sizeof(wszRegKey[0]) - strlenW(wszRegKey)))
00539         res = E_INVALIDARG;
00540 
00541     if (SUCCEEDED(res))
00542     {
00543         LONG lRes = RegCreateKeyW(HKEY_CURRENT_USER, wszRegKey, &hkeyDummy);
00544         res = HRESULT_FROM_WIN32(lRes);
00545     }
00546 
00547     if (hkeyDummy)
00548         RegCloseKey(hkeyDummy);
00549 
00550     if (FAILED(res))
00551         ERR("Failed to create key HKEY_CURRENT_USER\\%s\n", debugstr_w(wszRegKey));
00552 
00553     return res;
00554 }
00555 
00556 static HANDLE DEVENUM_populate_handle;
00557 static const WCHAR DEVENUM_populate_handle_nameW[] =
00558     {'_','_','W','I','N','E','_',
00559      'D','e','v','e','n','u','m','_',
00560      'P','o','p','u','l','a','t','e',0};
00561 
00562 /**********************************************************************
00563  * DEVENUM_CreateSpecialCategories (INTERNAL)
00564  *
00565  * Creates the keys in the registry for the dynamic categories
00566  */
00567 static HRESULT DEVENUM_CreateSpecialCategories(void)
00568 {
00569     HRESULT res;
00570     WCHAR szDSoundNameFormat[MAX_PATH + 1];
00571     WCHAR szDSoundName[MAX_PATH + 1];
00572     DWORD iDefaultDevice = -1;
00573     UINT numDevs;
00574     IFilterMapper2 * pMapper = NULL;
00575     REGFILTER2 rf2;
00576     REGFILTERPINS2 rfp2;
00577     WCHAR path[MAX_PATH];
00578     HKEY basekey;
00579 
00580     if (DEVENUM_populate_handle)
00581         return S_OK;
00582     DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW);
00583     if (GetLastError() == ERROR_ALREADY_EXISTS)
00584     {
00585         /* Webcams can take some time to scan if the driver is badly written and it enables them,
00586          * so have a 10 s timeout here
00587          */
00588         if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT)
00589             WARN("Waiting for object timed out\n");
00590         TRACE("No need to rescan\n");
00591         return S_OK;
00592     }
00593     TRACE("Scanning for devices\n");
00594 
00595     /* Since devices can change between session, for example because you just plugged in a webcam
00596      * or switched from pulseaudio to alsa, delete all old devices first
00597      */
00598     if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey, path, MAX_PATH)))
00599         RegDeleteTreeW(basekey, path);
00600     if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory, &basekey, path, MAX_PATH)))
00601         RegDeleteTreeW(basekey, path);
00602     if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory, &basekey, path, MAX_PATH)))
00603         RegDeleteTreeW(basekey, path);
00604     if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH)))
00605         RegDeleteTreeW(basekey, path);
00606 
00607     rf2.dwVersion = 2;
00608     rf2.dwMerit = MERIT_PREFERRED;
00609     rf2.u.s1.cPins2 = 1;
00610     rf2.u.s1.rgPins2 = &rfp2;
00611     rfp2.cInstances = 1;
00612     rfp2.nMediums = 0;
00613     rfp2.lpMedium = NULL;
00614     rfp2.clsPinCategory = &IID_NULL;
00615 
00616     if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1))
00617     {
00618         ERR("Couldn't get string resource (GetLastError() is %d)\n", GetLastError());
00619         return HRESULT_FROM_WIN32(GetLastError());
00620     }
00621 
00622     res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
00623                            &IID_IFilterMapper2, (void **) &pMapper);
00624     /*
00625      * Fill in info for devices
00626      */
00627     if (SUCCEEDED(res))
00628     {
00629         UINT i;
00630         WAVEOUTCAPSW wocaps;
00631     WAVEINCAPSW wicaps;
00632         MIDIOUTCAPSW mocaps;
00633         REGPINTYPES * pTypes;
00634 
00635     numDevs = waveOutGetNumDevs();
00636 
00637         res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
00638         if (FAILED(res)) /* can't register any devices in this category */
00639             numDevs = 0;
00640 
00641     rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
00642     for (i = 0; i < numDevs; i++)
00643     {
00644         if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
00645             == MMSYSERR_NOERROR)
00646         {
00647                 IMoniker * pMoniker = NULL;
00648 
00649                 rfp2.nMediaTypes = 1;
00650                 pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
00651                 if (!pTypes)
00652                 {
00653                     IFilterMapper2_Release(pMapper);
00654                     return E_OUTOFMEMORY;
00655                 }
00656                 /* FIXME: Native devenum seems to register a lot more types for
00657                  * DSound than we do. Not sure what purpose they serve */
00658                 pTypes[0].clsMajorType = &MEDIATYPE_Audio;
00659                 pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
00660 
00661                 rfp2.lpMediaType = pTypes;
00662 
00663                 res = IFilterMapper2_RegisterFilter(pMapper,
00664                                       &CLSID_AudioRender,
00665                           wocaps.szPname,
00666                           &pMoniker,
00667                           &CLSID_AudioRendererCategory,
00668                           wocaps.szPname,
00669                           &rf2);
00670 
00671                 /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
00672 
00673         if (pMoniker)
00674             IMoniker_Release(pMoniker);
00675 
00676         wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname);
00677             res = IFilterMapper2_RegisterFilter(pMapper,
00678                                       &CLSID_DSoundRender,
00679                           szDSoundName,
00680                           &pMoniker,
00681                           &CLSID_AudioRendererCategory,
00682                           szDSoundName,
00683                           &rf2);
00684 
00685                 /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
00686 
00687         if (pMoniker)
00688             IMoniker_Release(pMoniker);
00689 
00690         if (i == iDefaultDevice)
00691         {
00692             FIXME("Default device\n");
00693         }
00694 
00695                 CoTaskMemFree(pTypes);
00696         }
00697     }
00698 
00699         numDevs = waveInGetNumDevs();
00700 
00701         res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory);
00702         if (FAILED(res)) /* can't register any devices in this category */
00703             numDevs = 0;
00704 
00705     rfp2.dwFlags = REG_PINFLAG_B_OUTPUT;
00706         for (i = 0; i < numDevs; i++)
00707         {
00708             if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW))
00709                 == MMSYSERR_NOERROR)
00710             {
00711                 IMoniker * pMoniker = NULL;
00712 
00713                 rfp2.nMediaTypes = 1;
00714                 pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
00715                 if (!pTypes)
00716                 {
00717                     IFilterMapper2_Release(pMapper);
00718                     return E_OUTOFMEMORY;
00719                 }
00720 
00721                 /* FIXME: Not sure if these are correct */
00722                 pTypes[0].clsMajorType = &MEDIATYPE_Audio;
00723                 pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
00724 
00725                 rfp2.lpMediaType = pTypes;
00726 
00727             res = IFilterMapper2_RegisterFilter(pMapper,
00728                                       &CLSID_AudioRecord,
00729                           wicaps.szPname,
00730                           &pMoniker,
00731                           &CLSID_AudioInputDeviceCategory,
00732                           wicaps.szPname,
00733                           &rf2);
00734 
00735                 /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
00736 
00737         if (pMoniker)
00738             IMoniker_Release(pMoniker);
00739 
00740                 CoTaskMemFree(pTypes);
00741         }
00742     }
00743 
00744     numDevs = midiOutGetNumDevs();
00745 
00746         res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
00747         if (FAILED(res)) /* can't register any devices in this category */
00748             numDevs = 0;
00749 
00750     rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
00751     for (i = 0; i < numDevs; i++)
00752     {
00753         if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
00754             == MMSYSERR_NOERROR)
00755         {
00756                 IMoniker * pMoniker = NULL;
00757 
00758                 rfp2.nMediaTypes = 1;
00759                 pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
00760                 if (!pTypes)
00761                 {
00762                     IFilterMapper2_Release(pMapper);
00763                     return E_OUTOFMEMORY;
00764                 }
00765 
00766                 /* FIXME: Not sure if these are correct */
00767                 pTypes[0].clsMajorType = &MEDIATYPE_Midi;
00768                 pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
00769 
00770                 rfp2.lpMediaType = pTypes;
00771 
00772                 res = IFilterMapper2_RegisterFilter(pMapper,
00773                                       &CLSID_AVIMIDIRender,
00774                           mocaps.szPname,
00775                           &pMoniker,
00776                           &CLSID_MidiRendererCategory,
00777                           mocaps.szPname,
00778                           &rf2);
00779 
00780                 /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
00781         /* Native version sets MidiOutId */
00782 
00783         if (pMoniker)
00784             IMoniker_Release(pMoniker);
00785 
00786         if (i == iDefaultDevice)
00787         {
00788             FIXME("Default device\n");
00789         }
00790 
00791                 CoTaskMemFree(pTypes);
00792         }
00793     }
00794         res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory);
00795         if (SUCCEEDED(res))
00796             for (i = 0; i < 10; i++)
00797             {
00798                 WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10];
00799 
00800                 if (capGetDriverDescriptionW ((WORD) i,
00801                                               szDeviceName, sizeof(szDeviceName)/sizeof(WCHAR),
00802                                               szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR)))
00803                 {
00804                     IMoniker * pMoniker = NULL;
00805                     IPropertyBag * pPropBag = NULL;
00806                     WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 };
00807                     snprintfW(szDevicePath, sizeof(szDevicePath)/sizeof(WCHAR), dprintf, i);
00808                     /* The above code prevents 1 device with a different ID overwriting another */
00809 
00810                     rfp2.nMediaTypes = 1;
00811                     pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
00812                     if (!pTypes) {
00813                         IFilterMapper2_Release(pMapper);
00814                         return E_OUTOFMEMORY;
00815                     }
00816 
00817                     pTypes[0].clsMajorType = &MEDIATYPE_Video;
00818                     pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
00819 
00820                     rfp2.lpMediaType = pTypes;
00821 
00822                     res = IFilterMapper2_RegisterFilter(pMapper,
00823                                                         &CLSID_VfwCapture,
00824                                                         szDeviceName,
00825                                                         &pMoniker,
00826                                                         &CLSID_VideoInputDeviceCategory,
00827                                                         szDevicePath,
00828                                                         &rf2);
00829 
00830                     if (pMoniker) {
00831                        OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 };
00832                        VARIANT var;
00833                        V_VT(&var) = VT_I4;
00834                        V_UNION(&var, ulVal) = i;
00835                        res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag);
00836                        if (SUCCEEDED(res))
00837                           res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var);
00838                        IMoniker_Release(pMoniker);
00839                     }
00840 
00841                     if (i == iDefaultDevice) FIXME("Default device\n");
00842                     CoTaskMemFree(pTypes);
00843                 }
00844             }
00845     }
00846 
00847     if (pMapper)
00848         IFilterMapper2_Release(pMapper);
00849     SetEvent(DEVENUM_populate_handle);
00850     return res;
00851 }

Generated on Sat May 26 2012 04:20:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.