Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencreatedevenum.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
1.7.6.1
|