void RegistryQuery::FillDriverDetails()

in library/src/RegistryQuery.cpp [149:198]


void RegistryQuery::FillDriverDetails(Device& device)
{
	// Log the device ID to provide context for any subsequent log messages and errors
	LOG(L"Querying device driver registry details for device {}", device.ID);
	
	// Attempt to open the DirectX adapter for the device
	auto adapterDetails = ObjectHelpers::GetZeroedStruct<D3DKMT_OPENADAPTERFROMLUID>();
	adapterDetails.AdapterLuid = LuidFromInt64(device.DeviceAdapter.InstanceLuid);
	auto error = CheckNtStatus(D3DKMTOpenAdapterFromLuid(&adapterDetails));
	if (error)
	{
		throw error.Wrap(
			L"D3DKMTOpenAdapterFromLuid failed to open adapter with LUID " +
			std::to_wstring(device.DeviceAdapter.InstanceLuid)
		);
	}
	
	// Ensure we automatically close the adapter handle when we finish
	unique_adapter_handle adapter(adapterDetails.hAdapter);
	
	// Retrieve the path to the driver store directory for the adapter
	QueryD3DRegistryInfo queryDriverStore;
	queryDriverStore.SetFilesystemQuery(D3DDDI_QUERYREGISTRY_DRIVERSTOREPATH);
	queryDriverStore.PerformQuery(adapter);
	device.DriverStorePath = wstring(queryDriverStore.RegistryInfo->OutputString);
	
	// If the driver store path begins with the "\SystemRoot" prefix then expand it
	wstring prefix = L"\\SystemRoot";
	wstring systemRoot = wstring(wil::GetEnvironmentVariableW(L"SystemRoot").get());
	if (device.DriverStorePath.find(prefix, 0) == 0) {
		device.DriverStorePath = device.DriverStorePath.replace(0, prefix.size(), systemRoot);
	}
	
	// Determine whether we're running on the host or inside a container
	// (e.g. when using a client tool to verify that a device has been mounted correctly)
	if (device.DriverStorePath.find(L"HostDriverStore", 0) != wstring::npos)
	{
		// We have no way of enumerating the CopyToVmWhenNewer subkey inside a container, so stop processing here
		LOG(L"Running inside a container, skipping runtime file enumeration");
		return;
	}
	
	// Retrieve the list of additional runtime files that need to be copied to the System32 directory
	RegistryQuery::ProcessRuntimeFiles(device, L"CopyToVmOverwrite", false);
	RegistryQuery::ProcessRuntimeFiles(device, L"CopyToVmWhenNewer", false);
	
	// Retrieve the list of additional runtime files that need to be copied to the SysWOW64 directory
	RegistryQuery::ProcessRuntimeFiles(device, L"CopyToVmOverwriteWow64", true);
	RegistryQuery::ProcessRuntimeFiles(device, L"CopyToVmWhenNewerWow64", true);
}