1 /*############################################################################
2   # Copyright (C) 2012-2020 Intel Corporation
3   #
4   # SPDX-License-Identifier: MIT
5   ############################################################################*/
6 
7 #include "windows/mfx_library_iterator.h"
8 
9 #include "windows/mfx_dispatcher.h"
10 #include "windows/mfx_dispatcher_log.h"
11 
12 #include "windows/mfx_dxva2_device.h"
13 #include "windows/mfx_load_dll.h"
14 
15 #include <tchar.h>
16 #include <windows.h>
17 
18 #include <vector>
19 
20 namespace MFX {
21 
22 enum { MFX_MAX_MERIT = 0x7fffffff };
23 
24 //
25 // declare registry keys
26 //
27 
28 const wchar_t rootDispPath[]    = L"Software\\Intel\\MediaSDK\\Dispatch";
29 const wchar_t vendorIDKeyName[] = L"VendorID";
30 const wchar_t deviceIDKeyName[] = L"DeviceID";
31 const wchar_t meritKeyName[]    = L"Merit";
32 const wchar_t pathKeyName[]     = L"Path";
33 const wchar_t apiVersionName[]  = L"APIVersion";
34 
SelectImplementationType(const mfxU32 adapterNum,mfxIMPL * pImplInterface,mfxU32 * pVendorID,mfxU32 * pDeviceID,mfxU64 * pLUID)35 mfxStatus SelectImplementationType(const mfxU32 adapterNum,
36                                    mfxIMPL *pImplInterface,
37                                    mfxU32 *pVendorID,
38                                    mfxU32 *pDeviceID,
39                                    mfxU64 *pLUID) {
40     if (NULL == pImplInterface) {
41         return MFX_ERR_NULL_PTR;
42     }
43     mfxIMPL impl_via = *pImplInterface;
44 
45     DXVA2Device dxvaDevice;
46     if (MFX_IMPL_VIA_D3D9 == impl_via) {
47         // try to create the Direct3D 9 device and find right adapter
48         if (!dxvaDevice.InitD3D9(adapterNum)) {
49             DISPATCHER_LOG_INFO((("dxvaDevice.InitD3D9(%d) Failed "), adapterNum));
50             return MFX_ERR_UNSUPPORTED;
51         }
52     }
53     else if (MFX_IMPL_VIA_D3D11 == impl_via) {
54         // try to open DXGI 1.1 device to get hardware ID
55         if (!dxvaDevice.InitDXGI1(adapterNum)) {
56             DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum));
57             return MFX_ERR_UNSUPPORTED;
58         }
59     }
60     else if (MFX_IMPL_VIA_ANY == impl_via) {
61         // try the Direct3D 9 device
62         if (dxvaDevice.InitD3D9(adapterNum)) {
63             *pImplInterface = MFX_IMPL_VIA_D3D9; // store value for GetImplementationType() call
64         }
65         // else try to open DXGI 1.1 device to get hardware ID
66         else if (dxvaDevice.InitDXGI1(adapterNum)) {
67             *pImplInterface = MFX_IMPL_VIA_D3D11; // store value for GetImplementationType() call
68         }
69         else {
70             DISPATCHER_LOG_INFO((("Unsupported adapter %d "), adapterNum));
71             return MFX_ERR_UNSUPPORTED;
72         }
73     }
74     else {
75         DISPATCHER_LOG_ERROR((("Unknown implementation type %d "), *pImplInterface));
76         return MFX_ERR_UNSUPPORTED;
77     }
78 
79     // obtain card's parameters
80     if (pVendorID && pDeviceID) {
81         *pVendorID = dxvaDevice.GetVendorID();
82         *pDeviceID = dxvaDevice.GetDeviceID();
83     }
84 
85     if (pLUID) {
86         *pLUID = dxvaDevice.GetLUID();
87     }
88 
89     return MFX_ERR_NONE;
90 }
91 
SelectImplementationType(const mfxU32 adapterNum,mfxIMPL * pImplInterface,mfxU32 * pVendorID,mfxU32 * pDeviceID)92 mfxStatus SelectImplementationType(const mfxU32 adapterNum,
93                                    mfxIMPL *pImplInterface,
94                                    mfxU32 *pVendorID,
95                                    mfxU32 *pDeviceID) {
96     // do not return LUID
97     return SelectImplementationType(adapterNum, pImplInterface, pVendorID, pDeviceID, nullptr);
98 }
99 
MFXLibraryIterator(void)100 MFXLibraryIterator::MFXLibraryIterator(void)
101 #if !defined(MEDIASDK_UWP_DISPATCHER)
102         : m_baseRegKey()
103 #endif
104 {
105     m_implType      = MFX_LIB_PSEUDO;
106     m_implInterface = MFX_IMPL_UNSUPPORTED;
107 
108     m_vendorID = 0;
109     m_deviceID = 0;
110 
111     m_lastLibIndex = 0;
112     m_lastLibMerit = MFX_MAX_MERIT;
113 
114     m_bIsSubKeyValid = 0;
115     m_StorageID      = 0;
116 
117     m_SubKeyName[0]     = 0;
118     m_driverStoreDir[0] = 0;
119 } // MFXLibraryIterator::MFXLibraryIterator(void)
120 
~MFXLibraryIterator(void)121 MFXLibraryIterator::~MFXLibraryIterator(void) {
122     Release();
123 
124 } // MFXLibraryIterator::~MFXLibraryIterator(void)
125 
Release(void)126 void MFXLibraryIterator::Release(void) {
127     m_implType      = MFX_LIB_PSEUDO;
128     m_implInterface = MFX_IMPL_UNSUPPORTED;
129 
130     m_vendorID = 0;
131     m_deviceID = 0;
132 
133     m_lastLibIndex  = 0;
134     m_lastLibMerit  = MFX_MAX_MERIT;
135     m_SubKeyName[0] = 0;
136 
137 } // void MFXLibraryIterator::Release(void)
138 
GetThisDllModuleHandle()139 DECLSPEC_NOINLINE HMODULE GetThisDllModuleHandle() {
140     HMODULE hDll = NULL;
141 
142     GetModuleHandleExW(
143         GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
144         reinterpret_cast<LPCWSTR>(&GetThisDllModuleHandle),
145         &hDll);
146     return hDll;
147 }
148 
149 // wchar_t* sImplPath must be allocated with size not less then msdk_disp_path_len
GetImplPath(int storageID,wchar_t * sImplPath)150 bool GetImplPath(int storageID, wchar_t *sImplPath) {
151     HMODULE hModule = NULL;
152 
153     sImplPath[0] = L'\0';
154 
155     switch (storageID) {
156         case MFX_APP_FOLDER:
157             hModule = 0;
158             break;
159         case MFX_PATH_MSDK_FOLDER:
160             hModule           = GetThisDllModuleHandle();
161             HMODULE exeModule = GetModuleHandleW(NULL);
162             //It should works only if Dispatcher is linked with Dynamic Linked Library
163             if (!hModule || !exeModule || hModule == exeModule)
164                 return false;
165             break;
166     }
167 
168     DWORD nSize     = 0;
169     DWORD allocSize = msdk_disp_path_len;
170 
171     nSize = GetModuleFileNameW(hModule, &sImplPath[0], allocSize);
172 
173     if (nSize == 0 || nSize == allocSize) {
174         // nSize == 0 meanse that system can't get this info for hModule
175         // nSize == allocSize buffer is too small
176         return false;
177     }
178 
179     // for any case because WinXP implementation of GetModuleFileName does not add \0 to the end of string
180     sImplPath[nSize] = L'\0';
181 
182     wchar_t *dirSeparator = wcsrchr(sImplPath, L'\\');
183     if (dirSeparator != NULL && dirSeparator < (sImplPath + msdk_disp_path_len)) {
184         *++dirSeparator = 0;
185     }
186     return true;
187 }
188 
Init(eMfxImplType implType,mfxIMPL implInterface,const mfxU32 adapterNum,int storageID)189 mfxStatus MFXLibraryIterator::Init(eMfxImplType implType,
190                                    mfxIMPL implInterface,
191                                    const mfxU32 adapterNum,
192                                    int storageID) {
193     // check error(s)
194     if ((MFX_LIB_SOFTWARE != implType) && (MFX_LIB_HARDWARE != implType)) {
195         return MFX_ERR_UNSUPPORTED;
196     }
197 
198     // release the object before initialization
199     Release();
200     m_StorageID     = storageID;
201     m_lastLibIndex  = 0;
202     m_implType      = implType;
203     m_implInterface = implInterface != 0 ? implInterface : MFX_IMPL_VIA_ANY;
204 
205     // for HW impl check impl interface, check adapter, obtain deviceID and vendorID
206     if (m_implType != MFX_LIB_SOFTWARE) {
207         mfxStatus mfxRes =
208             MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID);
209         if (MFX_ERR_NONE != mfxRes) {
210             return mfxRes;
211         }
212     }
213 
214 #if !defined(MEDIASDK_UWP_DISPATCHER)
215     if (storageID == MFX_CURRENT_USER_KEY || storageID == MFX_LOCAL_MACHINE_KEY ||
216         storageID == MFX_CURRENT_USER_KEY_ONEVPL || storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
217         return InitRegistry(storageID);
218     }
219 
220     #if defined(MFX_TRACER_WA_FOR_DS)
221     if (storageID == MFX_TRACER) {
222         return InitRegistryTracer();
223     }
224     #endif
225 
226 #endif
227     if (storageID == MFX_DRIVER_STORE) {
228         m_driverStoreDir[0] = 0;
229         if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
230                                                     sizeof(m_driverStoreDir),
231                                                     m_deviceID,
232                                                     L"DriverStorePathForMediaSDK")) {
233             return MFX_ERR_UNSUPPORTED;
234         }
235     }
236     else if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
237         // get path to runtime directory only (without library name)
238         m_driverStoreDir[0] = 0;
239         if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
240                                                     sizeof(m_driverStoreDir),
241                                                     m_deviceID,
242                                                     L"DriverStorePathForVPL")) {
243             return MFX_ERR_UNSUPPORTED;
244         }
245     }
246     else if (!GetImplPath(storageID, m_driverStoreDir)) {
247         return MFX_ERR_UNSUPPORTED;
248     }
249 
250     // only need the path for oneVPL loader
251     if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_CURRENT_USER_KEY_ONEVPL ||
252         storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
253         return MFX_ERR_NONE;
254     }
255 
256     return InitFolder(implType, m_driverStoreDir, storageID);
257 
258 } // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID)
259 
InitRegistry(int storageID)260 mfxStatus MFXLibraryIterator::InitRegistry(int storageID) {
261 #if !defined(MEDIASDK_UWP_DISPATCHER)
262     HKEY rootHKey;
263     bool bRes;
264 
265     // open required registry key
266     switch (storageID) {
267         case MFX_LOCAL_MACHINE_KEY:
268         case MFX_LOCAL_MACHINE_KEY_ONEVPL:
269             rootHKey = HKEY_LOCAL_MACHINE;
270             break;
271         default:
272             rootHKey = HKEY_CURRENT_USER;
273             break;
274     }
275 
276     bRes = m_baseRegKey.Open(rootHKey, rootDispPath, KEY_READ);
277     if (false == bRes) {
278         DISPATCHER_LOG_WRN(
279             (("Can't open %s\\%S : RegOpenKeyExA()==0x%x\n"),
280              (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
281              rootDispPath,
282              GetLastError()))
283         return MFX_ERR_UNKNOWN;
284     }
285 
286     DISPATCHER_LOG_INFO(
287         (("Inspecting %s\\%S\n"),
288          (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
289          rootDispPath))
290 
291     return MFX_ERR_NONE;
292 #else
293     (void)storageID;
294     return MFX_ERR_UNSUPPORTED;
295 #endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
296 
297 } // mfxStatus MFXLibraryIterator::InitRegistry(int storageID)
298 
299 #if defined(MFX_TRACER_WA_FOR_DS)
InitRegistryTracer()300 mfxStatus MFXLibraryIterator::InitRegistryTracer() {
301     #if !defined(MEDIASDK_UWP_DISPATCHER)
302 
303     const wchar_t tracerRegKeyPath[] = L"Software\\Intel\\MediaSDK\\Dispatch\\tracer";
304 
305     if (!m_baseRegKey.Open(HKEY_LOCAL_MACHINE, tracerRegKeyPath, KEY_READ) &&
306         !m_baseRegKey.Open(HKEY_CURRENT_USER, tracerRegKeyPath, KEY_READ)) {
307         DISPATCHER_LOG_WRN(("can't find tracer registry key\n"))
308         return MFX_ERR_UNKNOWN;
309     }
310 
311     DISPATCHER_LOG_INFO(("found tracer registry key\n"))
312     return MFX_ERR_NONE;
313 
314     #else
315     return MFX_ERR_UNSUPPORTED;
316     #endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
317 
318 } // mfxStatus MFXLibraryIterator::InitRegistryTracer()
319 #endif
320 
InitFolder(eMfxImplType implType,const wchar_t * path,const int storageID)321 mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType,
322                                          const wchar_t *path,
323                                          const int storageID) {
324     const int maxPathLen = sizeof(m_path) / sizeof(m_path[0]);
325     m_path[0]            = 0;
326     wcscpy_s(m_path, maxPathLen, path);
327     size_t pathLen = wcslen(m_path);
328 
329     if (storageID == MFX_APP_FOLDER) {
330         // we looking for runtime in application folder, it should be named libmfxsw64 or libmfxsw32
331         mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, MFX_LIB_SOFTWARE);
332     }
333     else if (storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
334         mfx_get_default_onevpl_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen);
335     }
336     else {
337         mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, implType);
338     }
339 
340     return MFX_ERR_NONE;
341 } // mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, const wchar_t * path, const int storageID)
342 
SelectDLLVersion(wchar_t * pPath,size_t pathSize,eMfxImplType * pImplType,mfxVersion minVersion)343 mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath,
344                                                size_t pathSize,
345                                                eMfxImplType *pImplType,
346                                                mfxVersion minVersion) {
347     UNREFERENCED_PARAMETER(minVersion);
348 
349     if (m_StorageID == MFX_APP_FOLDER) {
350         if (m_lastLibIndex != 0)
351             return MFX_ERR_NOT_FOUND;
352         if (m_vendorID != INTEL_VENDOR_ID)
353             return MFX_ERR_UNKNOWN;
354 
355         m_lastLibIndex = 1;
356         wcscpy_s(pPath, pathSize, m_path);
357         *pImplType = MFX_LIB_SOFTWARE;
358         return MFX_ERR_NONE;
359     }
360 
361     if (m_StorageID == MFX_PATH_MSDK_FOLDER || m_StorageID == MFX_DRIVER_STORE ||
362         m_StorageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
363         if (m_lastLibIndex != 0)
364             return MFX_ERR_NOT_FOUND;
365         if (m_vendorID != INTEL_VENDOR_ID)
366             return MFX_ERR_UNKNOWN;
367 
368         m_lastLibIndex = 1;
369         wcscpy_s(pPath, pathSize, m_path);
370         // do not change impl type
371         return MFX_ERR_NONE;
372     }
373 
374 #if !defined(MEDIASDK_UWP_DISPATCHER)
375 
376     #if defined(MFX_TRACER_WA_FOR_DS)
377     if (m_StorageID == MFX_TRACER) {
378         if (m_lastLibIndex != 0)
379             return MFX_ERR_NOT_FOUND;
380         if (m_vendorID != INTEL_VENDOR_ID)
381             return MFX_ERR_UNKNOWN;
382 
383         m_lastLibIndex = 1;
384 
385         if (m_baseRegKey.Query(pathKeyName, REG_SZ, (LPBYTE)pPath, (DWORD *)&pathSize)) {
386             DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, pPath));
387         }
388         else {
389             DISPATCHER_LOG_WRN(
390                 (("error querying %S : RegQueryValueExA()==0x%x\n"), pathKeyName, GetLastError()));
391         }
392         return MFX_ERR_NONE;
393     }
394     #endif
395 
396     wchar_t libPath[MFX_MAX_DLL_PATH] = L"";
397     DWORD libIndex                    = 0;
398     DWORD libMerit                    = 0;
399     DWORD index;
400     bool enumRes;
401 
402     // main query cycle
403     index            = 0;
404     m_bIsSubKeyValid = false;
405     do {
406         WinRegKey subKey;
407         wchar_t subKeyName[MFX_MAX_REGISTRY_KEY_NAME] = { 0 };
408         DWORD subKeyNameSize                          = sizeof(subKeyName) / sizeof(subKeyName[0]);
409 
410         // query next value name
411         enumRes = m_baseRegKey.EnumKey(index, subKeyName, &subKeyNameSize);
412         if (!enumRes) {
413             DISPATCHER_LOG_WRN((("no more subkeys : RegEnumKeyExA()==0x%x\n"), GetLastError()))
414         }
415         else {
416             DISPATCHER_LOG_INFO((("found subkey: %S\n"), subKeyName))
417 
418             bool bRes;
419 
420             // open the sub key
421             bRes = subKey.Open(m_baseRegKey, subKeyName, KEY_READ);
422             if (!bRes) {
423                 DISPATCHER_LOG_WRN((("error opening key %S :RegOpenKeyExA()==0x%x\n"),
424                                     subKeyName,
425                                     GetLastError()));
426             }
427             else {
428                 DISPATCHER_LOG_INFO((("opened key: %S\n"), subKeyName));
429 
430                 mfxU32 vendorID = 0, deviceID = 0, merit = 0;
431                 DWORD size;
432 
433                 // query vendor and device IDs
434                 size = sizeof(vendorID);
435                 bRes = subKey.Query(vendorIDKeyName, REG_DWORD, (LPBYTE)&vendorID, &size);
436                 DISPATCHER_LOG_OPERATION({
437                     if (bRes) {
438                         DISPATCHER_LOG_INFO((("loaded %S : 0x%x\n"), vendorIDKeyName, vendorID));
439                     }
440                     else {
441                         DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
442                                             vendorIDKeyName,
443                                             GetLastError()));
444                     }
445                 })
446 
447                 if (bRes) {
448                     size = sizeof(deviceID);
449                     bRes = subKey.Query(deviceIDKeyName, REG_DWORD, (LPBYTE)&deviceID, &size);
450                     DISPATCHER_LOG_OPERATION({
451                         if (bRes) {
452                             DISPATCHER_LOG_INFO(
453                                 (("loaded %S : 0x%x\n"), deviceIDKeyName, deviceID));
454                         }
455                         else {
456                             DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
457                                                 deviceIDKeyName,
458                                                 GetLastError()));
459                         }
460                     })
461                 }
462                 // query merit value
463                 if (bRes) {
464                     size = sizeof(merit);
465                     bRes = subKey.Query(meritKeyName, REG_DWORD, (LPBYTE)&merit, &size);
466                     DISPATCHER_LOG_OPERATION({
467                         if (bRes) {
468                             DISPATCHER_LOG_INFO((("loaded %S : %d\n"), meritKeyName, merit));
469                         }
470                         else {
471                             DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
472                                                 meritKeyName,
473                                                 GetLastError()));
474                         }
475                     })
476                 }
477 
478                 // if the library fits required parameters,
479                 // query the library's path
480                 if (bRes) {
481                     // compare device's and library's IDs
482                     if (MFX_LIB_HARDWARE == m_implType) {
483                         if (m_vendorID != vendorID) {
484                             bRes = false;
485                             DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
486                                                 vendorIDKeyName,
487                                                 m_vendorID,
488                                                 vendorID));
489                         }
490                         if (bRes && m_deviceID != deviceID) {
491                             bRes = false;
492                             DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
493                                                 deviceIDKeyName,
494                                                 m_deviceID,
495                                                 deviceID));
496                         }
497                     }
498 
499                     DISPATCHER_LOG_OPERATION({
500                         if (bRes) {
501                             if (!(((m_lastLibMerit > merit) ||
502                                    ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
503                                   (libMerit < merit))) {
504                                 DISPATCHER_LOG_WRN((
505                                     ("merit conflict: lastMerit = 0x%x, requiredMerit = 0x%x, libraryMerit = 0x%x, lastindex = %d, index = %d\n"),
506                                     m_lastLibMerit,
507                                     merit,
508                                     libMerit,
509                                     m_lastLibIndex,
510                                     index));
511                             }
512                         }
513                     })
514 
515                     if ((bRes) &&
516                         ((m_lastLibMerit > merit) ||
517                          ((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
518                         (libMerit < merit)) {
519                         wchar_t tmpPath[MFX_MAX_DLL_PATH];
520                         DWORD tmpPathSize = sizeof(tmpPath);
521 
522                         bRes = subKey.Query(pathKeyName, REG_SZ, (LPBYTE)tmpPath, &tmpPathSize);
523                         if (!bRes) {
524                             DISPATCHER_LOG_WRN((("error querying %S : RegQueryValueExA()==0x%x\n"),
525                                                 pathKeyName,
526                                                 GetLastError()));
527                         }
528                         else {
529                             DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, tmpPath));
530 
531                             wcscpy_s(libPath, sizeof(libPath) / sizeof(libPath[0]), tmpPath);
532                             wcscpy_s(m_SubKeyName,
533                                      sizeof(m_SubKeyName) / sizeof(m_SubKeyName[0]),
534                                      subKeyName);
535 
536                             libMerit = merit;
537                             libIndex = index;
538 
539                             // set the library's type
540                             if ((0 == vendorID) || (0 == deviceID)) {
541                                 *pImplType = MFX_LIB_SOFTWARE;
542                                 DISPATCHER_LOG_INFO((("Library type is MFX_LIB_SOFTWARE\n")));
543                             }
544                             else {
545                                 *pImplType = MFX_LIB_HARDWARE;
546                                 DISPATCHER_LOG_INFO((("Library type is MFX_LIB_HARDWARE\n")));
547                             }
548                         }
549                     }
550                 }
551             }
552         }
553 
554         // advance key index
555         index += 1;
556 
557     } while (enumRes);
558 
559     // if the library's path was successfully read,
560     // the merit variable holds valid value
561     if (0 == libMerit) {
562         return MFX_ERR_NOT_FOUND;
563     }
564 
565     wcscpy_s(pPath, pathSize, libPath);
566 
567     m_lastLibIndex   = libIndex;
568     m_lastLibMerit   = libMerit;
569     m_bIsSubKeyValid = true;
570 
571 #endif
572 
573     return MFX_ERR_NONE;
574 
575 } // mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion)
576 
GetImplementationType()577 mfxIMPL MFXLibraryIterator::GetImplementationType() {
578     return m_implInterface;
579 } // mfxIMPL MFXLibraryIterator::GetImplementationType()
580 
GetSubKeyName(wchar_t * subKeyName,size_t length) const581 bool MFXLibraryIterator::GetSubKeyName(wchar_t *subKeyName, size_t length) const {
582     wcscpy_s(subKeyName, length, m_SubKeyName);
583     return m_bIsSubKeyValid;
584 }
585 
586 // lightweight implementation that takes deviceID as an argument, avoiding need to init the adapter
GetDriverStoreDir(std::wstring & driverStoreDir,size_t length,mfxU32 deviceID,int storageID)587 mfxStatus MFXLibraryIterator::GetDriverStoreDir(std::wstring &driverStoreDir,
588                                                 size_t length,
589                                                 mfxU32 deviceID,
590                                                 int storageID) {
591     wchar_t wcDir[MFX_MAX_DLL_PATH];
592     wcDir[0] = 0;
593 
594     DriverStoreLoader dsLoader;
595 
596     if (storageID == MFX_DRIVER_STORE_ONEVPL) {
597         // pass size of wcDir in bytes (see implementation of GetDriverStorePath)
598         if (!dsLoader.GetDriverStorePath(wcDir, sizeof(wcDir), deviceID, L"DriverStorePathForVPL"))
599             return MFX_ERR_UNSUPPORTED;
600     }
601     else if (storageID == MFX_DRIVER_STORE) {
602         if (!dsLoader.GetDriverStorePath(wcDir,
603                                          sizeof(wcDir),
604                                          deviceID,
605                                          L"DriverStorePathForMediaSDK"))
606             return MFX_ERR_UNSUPPORTED;
607     }
608 
609     if (wcslen(wcDir) == 0)
610         return MFX_ERR_UNSUPPORTED;
611 
612     // return path to driverStorDir
613     driverStoreDir = wcDir;
614 
615     return MFX_ERR_NONE;
616 }
617 
GetRegkeyDir(std::wstring & regDir,size_t length,int storageID)618 mfxStatus MFXLibraryIterator::GetRegkeyDir(std::wstring &regDir, size_t length, int storageID) {
619     mfxStatus sts = MFX_ERR_UNSUPPORTED;
620     MFX::MFXLibraryIterator libIterator;
621     wchar_t wRegDir[MFX_MAX_DLL_PATH];
622 
623     regDir.clear();
624     sts = libIterator.Init(MFX_LIB_HARDWARE, MFX_IMPL_VIA_D3D11, 0, storageID);
625     if (sts)
626         return MFX_ERR_UNSUPPORTED;
627 
628     eMfxImplType implType = MFX_LIB_HARDWARE;
629     mfxVersion ver        = { 0, 1 };
630     sts =
631         libIterator.SelectDLLVersion(wRegDir, sizeof(wRegDir) / sizeof(wRegDir[0]), &implType, ver);
632     if (sts)
633         return MFX_ERR_UNSUPPORTED;
634 
635     // remove DLL name - only need the path
636     std::wstring s = wRegDir;
637     size_t f       = s.find_last_of('\\');
638     if (f == std::string::npos)
639         return MFX_ERR_UNSUPPORTED;
640 
641     regDir = s.substr(0, f);
642 
643     return MFX_ERR_NONE;
644 }
645 
646 } // namespace MFX
647