Bug with NvOptimusEnablement DWORD export in 320.18 and 320.49 drivers.

Hi NVIDIA

Currently we have been exporting the DWORD NvOptimusEnablement = 0x00000001; in order to have the driver use the graphics card over integrated graphics.

Unfortunately in driver version 320.18 (and 320.49) this has now broken some other code we use to retrieve information about all of the video controllers. This was working fine under 320.14.

See the code below. The offending line is HRESULT hr = enumInstance->Next(WBEM_INFINITE, 1, &object, &returnValue); and it crashes inside the nvd3d9wrapx.dll in CheckDXGIModule.

Is there any other (better) way to force the NVIDIA card to be used over integrated graphics without user intervention?

Thanks

Mark


mdf::stlN::vectormdf::sysC_GraphicsCardDetails
mdf::sysN_Host::GraphicsCards()
{
stlN::vectormdf::sysC_GraphicsCardDetails cardDetailsVector;

Tbool comInitialised = true;
HRESULT hres = ::CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) comInitialised = false;

hres = ::CoInitializeSecurity(nullptr,
-1,
nullptr,
nullptr,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr,
EOAC_NONE,
nullptr);

IWbemLocator* loc = nullptr;
hres = ::CoCreateInstance(CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
reinterpret_cast<LPVOID*>(&loc));

if (FAILED(hres))
{
ASSERT_UNREACHABLE();
if (comInitialised) ::CoUninitialize();
return cardDetailsVector;
}

IWbemServices* svc = nullptr;
hres = loc->ConnectServer(L"ROOT\CIMV2",
nullptr,
nullptr,
0,
0,
0,
0,
&svc);

if (FAILED(hres))
{
ASSERT_UNREACHABLE();
loc->Release();
if (comInitialised) ::CoUninitialize();
return cardDetailsVector;
}

hres = ::CoSetProxyBlanket(svc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
nullptr,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr,
EOAC_NONE);

if (FAILED(hres))
{
ASSERT_UNREACHABLE();
svc->Release();
loc->Release();
if (comInitialised) ::CoUninitialize();
return cardDetailsVector;
}

IEnumWbemClassObject* enumInstance = nullptr;
hres = svc->ExecQuery(
bstr_t(“WQL”),
bstr_t(“SELECT * FROM Win32_VideoController”),
WBEM_FLAG_FORWARD_ONLY,
nullptr,
&enumInstance);

if (FAILED(hres))
{
ASSERT_UNREACHABLE();
svc->Release();
loc->Release();
if (comInitialised) ::CoUninitialize();
return cardDetailsVector;
}

IWbemClassObject* object = nullptr;
ULONG returnValue = 0;

while (enumInstance)
{
// ** This line crashes in CheckDXGIModule in nvd3d9wrapx.dll **
HRESULT hr = enumInstance->Next(WBEM_INFINITE, 1, &object, &returnValue);

if (returnValue == 0) break;

Tstring name = "unknown";
Tint32u ram = 0;
Tstring driverVersion = "unknown";

{
  VARIANT variant;
  if (SUCCEEDED(object->Get(L"Caption", 0, &variant, 0, 0)) &&
      V_VT(&variant) == VT_BSTR)
  {
    name = _com_util::ConvertBSTRToString(variant.bstrVal);
    ::VariantClear(&variant);
  }
}

{
  VARIANT variant;
  if (SUCCEEDED(object->Get(L"AdapterRAM", 0, &variant, 0, 0)) &&
      V_VT(&variant) == VT_I4)
  {
    ram = variant.intVal;
    ::VariantClear(&variant);
  }
}

{
  VARIANT variant;
  if (SUCCEEDED(object->Get(L"DriverVersion", 0, &variant, 0, 0)) &&
      V_VT(&variant) == VT_BSTR)
  {
    driverVersion = _com_util::ConvertBSTRToString(variant.bstrVal);
    ::VariantClear(&variant);
  }
}

object->Release();

cardDetailsVector.push_back(
  sysC_GraphicsCardDetails(name, ram, driverVersion));

}

svc->Release();
loc->Release();
enumInstance->Release();
if (comInitialised) ::CoUninitialize();

return cardDetailsVector;
}

Hi:

I’m also interested in know if there is any other way to force the NVIDIA card to be used over integrated graphics without user intervention. And from any programming language, in this case not C nor C++.

Thanks.