mfx_library_iterator.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /* ****************************************************************************** *\
  2. Copyright (C) 2012-2018 Intel Corporation. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. - Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. - Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. - Neither the name of Intel Corporation nor the names of its contributors
  11. may be used to endorse or promote products derived from this software
  12. without specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR
  14. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  15. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  16. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. File Name: mfx_library_iterator.cpp
  24. \* ****************************************************************************** */
  25. #if defined(_WIN32) || defined(_WIN64)
  26. #include "mfx_library_iterator.h"
  27. #include "mfx_dispatcher.h"
  28. #include "mfx_dispatcher_log.h"
  29. #include "mfx_dxva2_device.h"
  30. #include "mfx_load_dll.h"
  31. #include <tchar.h>
  32. #include <windows.h>
  33. #include <vector>
  34. namespace MFX
  35. {
  36. enum
  37. {
  38. MFX_MAX_MERIT = 0x7fffffff
  39. };
  40. //
  41. // declare registry keys
  42. //
  43. const
  44. wchar_t rootDispPath[] = L"Software\\Intel\\MediaSDK\\Dispatch";
  45. const
  46. wchar_t vendorIDKeyName[] = L"VendorID";
  47. const
  48. wchar_t deviceIDKeyName[] = L"DeviceID";
  49. const
  50. wchar_t meritKeyName[] = L"Merit";
  51. const
  52. wchar_t pathKeyName[] = L"Path";
  53. const
  54. wchar_t apiVersionName[] = L"APIVersion";
  55. mfxStatus SelectImplementationType(const mfxU32 adapterNum, mfxIMPL *pImplInterface, mfxU32 *pVendorID, mfxU32 *pDeviceID)
  56. {
  57. if (NULL == pImplInterface)
  58. {
  59. return MFX_ERR_NULL_PTR;
  60. }
  61. mfxIMPL impl_via = *pImplInterface;
  62. DXVA2Device dxvaDevice;
  63. if (MFX_IMPL_VIA_D3D9 == impl_via)
  64. {
  65. // try to create the Direct3D 9 device and find right adapter
  66. if (!dxvaDevice.InitD3D9(adapterNum))
  67. {
  68. DISPATCHER_LOG_INFO((("dxvaDevice.InitD3D9(%d) Failed "), adapterNum ));
  69. return MFX_ERR_UNSUPPORTED;
  70. }
  71. }
  72. else if (MFX_IMPL_VIA_D3D11 == impl_via)
  73. {
  74. // try to open DXGI 1.1 device to get hardware ID
  75. if (!dxvaDevice.InitDXGI1(adapterNum))
  76. {
  77. DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum ));
  78. return MFX_ERR_UNSUPPORTED;
  79. }
  80. }
  81. else if (MFX_IMPL_VIA_ANY == impl_via)
  82. {
  83. // try the Direct3D 9 device
  84. if (dxvaDevice.InitD3D9(adapterNum))
  85. {
  86. *pImplInterface = MFX_IMPL_VIA_D3D9; // store value for GetImplementationType() call
  87. }
  88. // else try to open DXGI 1.1 device to get hardware ID
  89. else if (dxvaDevice.InitDXGI1(adapterNum))
  90. {
  91. *pImplInterface = MFX_IMPL_VIA_D3D11; // store value for GetImplementationType() call
  92. }
  93. else
  94. {
  95. DISPATCHER_LOG_INFO((("Unsupported adapter %d "), adapterNum ));
  96. return MFX_ERR_UNSUPPORTED;
  97. }
  98. }
  99. else
  100. {
  101. DISPATCHER_LOG_ERROR((("Unknown implementation type %d "), *pImplInterface ));
  102. return MFX_ERR_UNSUPPORTED;
  103. }
  104. // obtain card's parameters
  105. if (pVendorID && pDeviceID)
  106. {
  107. *pVendorID = dxvaDevice.GetVendorID();
  108. *pDeviceID = dxvaDevice.GetDeviceID();
  109. }
  110. return MFX_ERR_NONE;
  111. }
  112. MFXLibraryIterator::MFXLibraryIterator(void)
  113. {
  114. m_implType = MFX_LIB_PSEUDO;
  115. m_implInterface = MFX_IMPL_UNSUPPORTED;
  116. m_vendorID = 0;
  117. m_deviceID = 0;
  118. m_lastLibIndex = 0;
  119. m_lastLibMerit = MFX_MAX_MERIT;
  120. m_bIsSubKeyValid = 0;
  121. m_StorageID = 0;
  122. m_SubKeyName[0] = 0;
  123. } // MFXLibraryIterator::MFXLibraryIterator(void)
  124. MFXLibraryIterator::~MFXLibraryIterator(void)
  125. {
  126. Release();
  127. } // MFXLibraryIterator::~MFXLibraryIterator(void)
  128. void MFXLibraryIterator::Release(void)
  129. {
  130. m_implType = MFX_LIB_PSEUDO;
  131. m_implInterface = MFX_IMPL_UNSUPPORTED;
  132. m_vendorID = 0;
  133. m_deviceID = 0;
  134. m_lastLibIndex = 0;
  135. m_lastLibMerit = MFX_MAX_MERIT;
  136. m_SubKeyName[0] = 0;
  137. } // void MFXLibraryIterator::Release(void)
  138. DECLSPEC_NOINLINE HMODULE GetThisDllModuleHandle()
  139. {
  140. HMODULE hDll = HMODULE(-1);
  141. GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
  142. GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
  143. reinterpret_cast<LPCWSTR>(&GetThisDllModuleHandle), &hDll);
  144. return hDll;
  145. }
  146. // msdk_disp_char* sImplPath must be allocated with size not less then msdk_disp_path_len
  147. bool GetImplPath(int storageID, msdk_disp_char* sImplPath)
  148. {
  149. HMODULE hModule = NULL;
  150. sImplPath[0] = L'\0';
  151. switch (storageID) {
  152. case MFX_APP_FOLDER:
  153. hModule = 0;
  154. break;
  155. #if defined(MEDIASDK_UWP_LOADER) || defined(MEDIASDK_UWP_PROCTABLE)
  156. case MFX_PATH_MSDK_FOLDER:
  157. hModule = GetThisDllModuleHandle();
  158. break;
  159. #endif
  160. }
  161. if(hModule == HMODULE(-1)) {
  162. return false;
  163. }
  164. DWORD nSize = 0;
  165. DWORD allocSize = msdk_disp_path_len;
  166. nSize = GetModuleFileNameW(hModule, &sImplPath[0], allocSize);
  167. if (nSize == 0 || nSize == allocSize) {
  168. // nSize == 0 meanse that system can't get this info for hModule
  169. // nSize == allocSize buffer is too small
  170. return false;
  171. }
  172. // for any case because WinXP implementation of GetModuleFileName does not add \0 to the end of string
  173. sImplPath[nSize] = L'\0';
  174. msdk_disp_char * dirSeparator = wcsrchr(sImplPath, L'\\');
  175. if (dirSeparator != NULL && dirSeparator < (sImplPath + msdk_disp_path_len))
  176. {
  177. *++dirSeparator = 0;
  178. }
  179. return true;
  180. }
  181. mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID)
  182. {
  183. // check error(s)
  184. if ((MFX_LIB_SOFTWARE != implType) &&
  185. (MFX_LIB_HARDWARE != implType))
  186. {
  187. return MFX_ERR_UNSUPPORTED;
  188. }
  189. // release the object before initialization
  190. Release();
  191. m_StorageID = storageID;
  192. m_lastLibIndex = 0;
  193. #if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
  194. if (storageID == MFX_CURRENT_USER_KEY || storageID == MFX_LOCAL_MACHINE_KEY)
  195. {
  196. return InitRegistry(implType, implInterface, adapterNum, storageID);
  197. }
  198. #endif
  199. msdk_disp_char sCurrentModulePath[msdk_disp_path_len];
  200. if(!GetImplPath(storageID, sCurrentModulePath)) {
  201. return MFX_ERR_UNSUPPORTED;
  202. }
  203. return InitFolder(implType, implInterface, adapterNum, sCurrentModulePath);
  204. } // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID)
  205. mfxStatus MFXLibraryIterator::InitRegistry(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID)
  206. {
  207. #if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
  208. HKEY rootHKey;
  209. bool bRes;
  210. // open required registry key
  211. rootHKey = (MFX_LOCAL_MACHINE_KEY == storageID) ? (HKEY_LOCAL_MACHINE) : (HKEY_CURRENT_USER);
  212. bRes = m_baseRegKey.Open(rootHKey, rootDispPath, KEY_READ);
  213. if (false == bRes)
  214. {
  215. DISPATCHER_LOG_WRN((("Can't open %s\\%S : RegOpenKeyExA()==0x%x\n"),
  216. (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
  217. rootDispPath, GetLastError()))
  218. return MFX_ERR_UNKNOWN;
  219. }
  220. // set the required library's implementation type
  221. m_implType = implType;
  222. m_implInterface = implInterface != 0
  223. ? implInterface
  224. : MFX_IMPL_VIA_ANY;
  225. //deviceID and vendorID are not actual for SW library loading
  226. if (m_implType != MFX_LIB_SOFTWARE)
  227. {
  228. mfxStatus mfxRes = MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID);
  229. if (MFX_ERR_NONE != mfxRes)
  230. {
  231. return mfxRes;
  232. }
  233. }
  234. DISPATCHER_LOG_INFO((("Inspecting %s\\%S\n"),
  235. (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
  236. rootDispPath))
  237. return MFX_ERR_NONE;
  238. #else
  239. (void) storageID;
  240. (void) adapterNum;
  241. (void) implInterface;
  242. (void) implType;
  243. return MFX_ERR_UNSUPPORTED;
  244. #endif // #if !defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE)
  245. } // mfxStatus MFXLibraryIterator::InitRegistry(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID)
  246. mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, const msdk_disp_char * path)
  247. {
  248. const int maxPathLen = sizeof(m_path)/sizeof(m_path[0]);
  249. m_path[0] = 0;
  250. msdk_disp_char_cpy_s(m_path, maxPathLen, path);
  251. size_t pathLen = wcslen(m_path);
  252. #if !defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE)
  253. // we looking for runtime in application folder, it should be named libmfxsw64 or libmfxsw32
  254. mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, MFX_LIB_SOFTWARE);
  255. #else
  256. mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, implType);
  257. #endif
  258. // set the required library's implementation type
  259. m_implType = implType;
  260. m_implInterface = implInterface != 0
  261. ? implInterface
  262. : MFX_IMPL_VIA_ANY;
  263. //deviceID and vendorID are not actual for SW library loading
  264. if (m_implType != MFX_LIB_SOFTWARE)
  265. {
  266. mfxStatus mfxRes = MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID);
  267. if (MFX_ERR_NONE != mfxRes)
  268. {
  269. return mfxRes;
  270. }
  271. }
  272. return MFX_ERR_NONE;
  273. } // mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, const msdk_disp_char * path)
  274. mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath
  275. , size_t pathSize
  276. , eMfxImplType *pImplType, mfxVersion minVersion)
  277. {
  278. UNREFERENCED_PARAMETER(minVersion);
  279. if (m_StorageID == MFX_APP_FOLDER)
  280. {
  281. if (m_lastLibIndex != 0)
  282. return MFX_ERR_NOT_FOUND;
  283. if (m_vendorID != INTEL_VENDOR_ID)
  284. return MFX_ERR_UNKNOWN;
  285. m_lastLibIndex = 1;
  286. msdk_disp_char_cpy_s(pPath, pathSize, m_path);
  287. *pImplType = MFX_LIB_SOFTWARE;
  288. return MFX_ERR_NONE;
  289. }
  290. #if defined(MEDIASDK_UWP_LOADER) || defined(MEDIASDK_UWP_PROCTABLE)
  291. if (m_StorageID == MFX_PATH_MSDK_FOLDER) {
  292. if (m_lastLibIndex != 0)
  293. return MFX_ERR_NOT_FOUND;
  294. if (m_vendorID != INTEL_VENDOR_ID)
  295. return MFX_ERR_UNKNOWN;
  296. m_lastLibIndex = 1;
  297. msdk_disp_char_cpy_s(pPath, pathSize, m_path);
  298. // do not change impl type
  299. //*pImplType = MFX_LIB_HARDWARE;
  300. return MFX_ERR_NONE;
  301. }
  302. #endif
  303. #if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
  304. wchar_t libPath[MFX_MAX_DLL_PATH] = L"";
  305. DWORD libIndex = 0;
  306. DWORD libMerit = 0;
  307. DWORD index;
  308. bool enumRes;
  309. // main query cycle
  310. index = 0;
  311. m_bIsSubKeyValid = false;
  312. do
  313. {
  314. WinRegKey subKey;
  315. wchar_t subKeyName[MFX_MAX_REGISTRY_KEY_NAME] = { 0 };
  316. DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
  317. // query next value name
  318. enumRes = m_baseRegKey.EnumKey(index, subKeyName, &subKeyNameSize);
  319. if (!enumRes)
  320. {
  321. DISPATCHER_LOG_WRN((("no more subkeys : RegEnumKeyExA()==0x%x\n"), GetLastError()))
  322. }
  323. else
  324. {
  325. DISPATCHER_LOG_INFO((("found subkey: %S\n"), subKeyName))
  326. bool bRes;
  327. // open the sub key
  328. bRes = subKey.Open(m_baseRegKey, subKeyName, KEY_READ);
  329. if (!bRes)
  330. {
  331. DISPATCHER_LOG_WRN((("error opening key %S :RegOpenKeyExA()==0x%x\n"), subKeyName, GetLastError()));
  332. }
  333. else
  334. {
  335. DISPATCHER_LOG_INFO((("opened key: %S\n"), subKeyName));
  336. mfxU32 vendorID = 0, deviceID = 0, merit = 0;
  337. DWORD size;
  338. // query vendor and device IDs
  339. size = sizeof(vendorID);
  340. bRes = subKey.Query(vendorIDKeyName, REG_DWORD, (LPBYTE) &vendorID, &size);
  341. DISPATCHER_LOG_OPERATION({
  342. if (bRes)
  343. {
  344. DISPATCHER_LOG_INFO((("loaded %S : 0x%x\n"), vendorIDKeyName, vendorID));
  345. }
  346. else
  347. {
  348. DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"), vendorIDKeyName, GetLastError()));
  349. }
  350. })
  351. if (bRes)
  352. {
  353. size = sizeof(deviceID);
  354. bRes = subKey.Query(deviceIDKeyName, REG_DWORD, (LPBYTE) &deviceID, &size);
  355. DISPATCHER_LOG_OPERATION({
  356. if (bRes)
  357. {
  358. DISPATCHER_LOG_INFO((("loaded %S : 0x%x\n"), deviceIDKeyName, deviceID));
  359. }
  360. else
  361. {
  362. DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"), deviceIDKeyName, GetLastError()));
  363. }
  364. })
  365. }
  366. // query merit value
  367. if (bRes)
  368. {
  369. size = sizeof(merit);
  370. bRes = subKey.Query(meritKeyName, REG_DWORD, (LPBYTE) &merit, &size);
  371. DISPATCHER_LOG_OPERATION({
  372. if (bRes)
  373. {
  374. DISPATCHER_LOG_INFO((("loaded %S : %d\n"), meritKeyName, merit));
  375. }
  376. else
  377. {
  378. DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"), meritKeyName, GetLastError()));
  379. }
  380. })
  381. }
  382. // if the library fits required parameters,
  383. // query the library's path
  384. if (bRes)
  385. {
  386. // compare device's and library's IDs
  387. if (MFX_LIB_HARDWARE == m_implType)
  388. {
  389. if (m_vendorID != vendorID)
  390. {
  391. bRes = false;
  392. DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"), vendorIDKeyName, m_vendorID, vendorID));
  393. }
  394. if (bRes && m_deviceID != deviceID)
  395. {
  396. bRes = false;
  397. DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"), deviceIDKeyName, m_deviceID, deviceID));
  398. }
  399. }
  400. DISPATCHER_LOG_OPERATION({
  401. if (bRes)
  402. {
  403. if (!(((m_lastLibMerit > merit) || ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
  404. (libMerit < merit)))
  405. {
  406. DISPATCHER_LOG_WRN((("merit conflict: lastMerit = 0x%x, requiredMerit = 0x%x, libraryMerit = 0x%x, lastindex = %d, index = %d\n")
  407. , m_lastLibMerit, merit, libMerit, m_lastLibIndex, index));
  408. }
  409. }})
  410. if ((bRes) &&
  411. ((m_lastLibMerit > merit) || ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
  412. (libMerit < merit))
  413. {
  414. wchar_t tmpPath[MFX_MAX_DLL_PATH];
  415. DWORD tmpPathSize = sizeof(tmpPath);
  416. bRes = subKey.Query(pathKeyName, REG_SZ, (LPBYTE) tmpPath, &tmpPathSize);
  417. if (!bRes)
  418. {
  419. DISPATCHER_LOG_WRN((("error querying %S : RegQueryValueExA()==0x%x\n"), pathKeyName, GetLastError()));
  420. }
  421. else
  422. {
  423. DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, tmpPath));
  424. msdk_disp_char_cpy_s(libPath, sizeof(libPath) / sizeof(libPath[0]), tmpPath);
  425. msdk_disp_char_cpy_s(m_SubKeyName, sizeof(m_SubKeyName) / sizeof(m_SubKeyName[0]), subKeyName);
  426. libMerit = merit;
  427. libIndex = index;
  428. // set the library's type
  429. if ((0 == vendorID) || (0 == deviceID))
  430. {
  431. *pImplType = MFX_LIB_SOFTWARE;
  432. DISPATCHER_LOG_INFO((("Library type is MFX_LIB_SOFTWARE\n")));
  433. }
  434. else
  435. {
  436. *pImplType = MFX_LIB_HARDWARE;
  437. DISPATCHER_LOG_INFO((("Library type is MFX_LIB_HARDWARE\n")));
  438. }
  439. }
  440. }
  441. }
  442. }
  443. }
  444. // advance key index
  445. index += 1;
  446. } while (enumRes);
  447. // if the library's path was successfully read,
  448. // the merit variable holds valid value
  449. if (0 == libMerit)
  450. {
  451. return MFX_ERR_NOT_FOUND;
  452. }
  453. msdk_disp_char_cpy_s(pPath, pathSize, libPath);
  454. m_lastLibIndex = libIndex;
  455. m_lastLibMerit = libMerit;
  456. m_bIsSubKeyValid = true;
  457. #endif
  458. return MFX_ERR_NONE;
  459. } // mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion)
  460. mfxIMPL MFXLibraryIterator::GetImplementationType()
  461. {
  462. return m_implInterface;
  463. } // mfxIMPL MFXLibraryIterator::GetImplementationType()
  464. bool MFXLibraryIterator::GetSubKeyName(msdk_disp_char *subKeyName, size_t length) const
  465. {
  466. msdk_disp_char_cpy_s(subKeyName, length, m_SubKeyName);
  467. return m_bIsSubKeyValid;
  468. }
  469. } // namespace MFX
  470. #endif // #if defined(_WIN32) || defined(_WIN64)