// Copyright (c) 2019-2020 Intel Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <tchar.h>
#include "mfx_driver_store_loader.h"
#include "mfx_dispatcher_log.h"
#include "mfx_load_dll.h"
namespace MFX
{
inline bool IsIntelDeviceInstanceID(const wchar_t * DeviceID)
{
return wcsstr(DeviceID, L"VEN_8086") || wcsstr(DeviceID, L"ven_8086");
}
inline bool ExctractDeviceID(const wchar_t* descrString, mfxU32& deviceID)
{
const wchar_t *begin = wcsstr(descrString, L"DEV_");
if (!begin)
{
begin = wcsstr(descrString, L"dev_");
if (!begin)
{
DISPATCHER_LOG_WRN(("exctracting device id: failed to find device id substring\n"));
return false;
}
}
begin += wcslen(L"DEV_");
deviceID = wcstoul(begin, NULL, 16);
if (!deviceID)
{
DISPATCHER_LOG_WRN(("exctracting device id: failed to convert device id str to int\n"));
return false;
}
return true;
}
inline bool GetGuidString(const GUID guid, wchar_t * string, size_t size)
{
return swprintf_s(string, size,
L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
DriverStoreLoader::DriverStoreLoader(void)
: m_moduleCfgMgr(NULL)
, m_pCM_Get_Device_ID_List_Size(NULL)
, m_pCM_Get_Device_ID_List(NULL)
, m_pCM_Locate_DevNode(NULL)
, m_pCM_Open_DevNode_Key(NULL)
{
}
DriverStoreLoader::~DriverStoreLoader(void)
{
}
bool DriverStoreLoader::GetDriverStorePath(wchar_t * path, DWORD dwPathSize, mfxU32 deviceID)
{
if (path == NULL || dwPathSize == 0)
{
return false;
}
// Obtain a PnP handle to the Intel graphics adapter
CONFIGRET result = CR_SUCCESS;
ULONG DeviceIDListSize = 0;
MFXVector<WCHAR> DeviceIDList;
wchar_t DisplayGUID[40];
DEVINST DeviceInst;
DISPATCHER_LOG_INFO(("Looking for MediaSDK in DriverStore\n"));
if (!LoadCfgMgr() || !LoadCmFuncs())
{
return false;
}
if (!GetGuidString(GUID_DEVCLASS_DISPLAY, DisplayGUID, sizeof(DisplayGUID) / sizeof(DisplayGUID[0])))
{
DISPATCHER_LOG_WRN(("Couldn't prepare string from GUID\n"));
return false;
}
do
{
result = m_pCM_Get_Device_ID_List_Size(&DeviceIDListSize, DisplayGUID, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
if (result != CR_SUCCESS)
{
break;
}
try
{
DeviceIDList.resize(DeviceIDListSize);
}
catch (...)
{
return false;
}
result = m_pCM_Get_Device_ID_List(DisplayGUID, DeviceIDList.data(), DeviceIDListSize, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
} while (result == CR_BUFFER_SMALL);
if (result != CR_SUCCESS)
{
return false;
}
//Look for MediaSDK record
wchar_t *begin = DeviceIDList.data();
wchar_t *end = begin + DeviceIDList.size();
size_t len = 0;
for (; (begin < end) && (len = wcslen(begin)) > 0; begin += len + 1)
{
if (IsIntelDeviceInstanceID(begin))
{
mfxU32 curDeviceID = 0;
if (!ExctractDeviceID(begin, curDeviceID) || curDeviceID != deviceID)
{
continue;
}
result = m_pCM_Locate_DevNode(&DeviceInst, begin, CM_LOCATE_DEVNODE_NORMAL);
if (result != CR_SUCCESS)
{
continue;
}
HKEY hKey_sw;
result = m_pCM_Open_DevNode_Key(DeviceInst, KEY_READ, 0, RegDisposition_OpenExisting, &hKey_sw, CM_REGISTRY_SOFTWARE);
if (result != CR_SUCCESS)
{
continue;
}
ULONG nError;
DWORD pathSize = dwPathSize;
nError = RegGetValueW(hKey_sw, NULL, L"DriverStorePathForMediaSDK", RRF_RT_REG_SZ, NULL, (LPBYTE)path, &pathSize);
RegCloseKey(hKey_sw);
if (ERROR_SUCCESS == nError)
{
if (path[wcslen(path) - 1] != '/' && path[wcslen(path) - 1] != '\\')
{
wcscat_s(path, dwPathSize / sizeof(path[0]), L"\\");
}
DISPATCHER_LOG_INFO(("DriverStore path is found\n"));
return true;
}
}
}
DISPATCHER_LOG_INFO(("DriverStore path isn't found\n"));
return false;
} // bool DriverStoreLoader::GetDriverStorePath(wchar_t * path, DWORD dwPathSize)
bool DriverStoreLoader::LoadCfgMgr()
{
if (!m_moduleCfgMgr)
{
m_moduleCfgMgr = mfx_dll_load(L"cfgmgr32.dll");
if (!m_moduleCfgMgr)
{
DISPATCHER_LOG_WRN(("cfgmgr32.dll couldn't be loaded\n"));
return false;
}
}
return true;
} // bool DriverStoreLoader::LoadCfgMgr()
bool DriverStoreLoader::LoadCmFuncs()
{
if (!m_pCM_Get_Device_ID_List || !m_pCM_Get_Device_ID_List_Size || !m_pCM_Locate_DevNode || !m_pCM_Open_DevNode_Key)
{
m_pCM_Get_Device_ID_List = (Func_CM_Get_Device_ID_ListW) mfx_dll_get_addr((HMODULE)m_moduleCfgMgr, "CM_Get_Device_ID_ListW");
m_pCM_Get_Device_ID_List_Size = (Func_CM_Get_Device_ID_List_SizeW) mfx_dll_get_addr((HMODULE)m_moduleCfgMgr, "CM_Get_Device_ID_List_SizeW");
m_pCM_Locate_DevNode = (Func_CM_Locate_DevNodeW) mfx_dll_get_addr((HMODULE)m_moduleCfgMgr, "CM_Locate_DevNodeW");
m_pCM_Open_DevNode_Key = (Func_CM_Open_DevNode_Key) mfx_dll_get_addr((HMODULE)m_moduleCfgMgr, "CM_Open_DevNode_Key");
if (!m_pCM_Get_Device_ID_List || !m_pCM_Get_Device_ID_List_Size || !m_pCM_Locate_DevNode || !m_pCM_Open_DevNode_Key)
{
DISPATCHER_LOG_WRN(("One of cfgmgr32.dll function isn't found\n"));
return false;
}
}
return true;
} // bool DriverStoreLoader::LoadCmFuncs()
} // namespace MFX
↑ V832 It's better to use '= default;' syntax instead of empty destructor body.
↑ V801 Decreased performance. It is better to redefine the first function argument as a reference. Consider replacing 'const .. guid' with 'const .. &guid'.
↑ V804 Decreased performance. The 'wcslen' function is called twice in the specified expression to calculate length of the same string.