[SYSETUP] Implement the CriticalDeviceCoInstaller

The CriticalDeviceCoInstaller adds devices of registered classes to the critical device database.
This commit is contained in:
Eric Kohl 2018-09-30 17:18:28 +02:00
parent c7af85b64b
commit 4aa1bee757

View file

@ -31,7 +31,7 @@ ComputerClassInstaller(
/*
* @unimplemented
* @implemented
*/
DWORD
WINAPI
@ -41,12 +41,208 @@ CriticalDeviceCoInstaller(
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
IN OUT PCOINSTALLER_CONTEXT_DATA Context)
{
switch (InstallFunction)
WCHAR szDeviceId[256];
WCHAR szServiceName[256];
WCHAR szClassGUID[64];
DWORD dwRequiredSize;
HKEY hDriverKey = NULL;
HKEY hDatabaseKey = NULL, hDeviceKey = NULL;
DWORD dwDisposition;
PWSTR Ptr;
DWORD dwError = ERROR_SUCCESS;
DPRINT("CriticalDeviceCoInstaller(%lu %p %p %p)\n",
InstallFunction, DeviceInfoSet, DeviceInfoData, Context);
if (InstallFunction != DIF_INSTALLDEVICE)
return ERROR_SUCCESS;
/* Get the MatchingDeviceId property */
hDriverKey = SetupDiOpenDevRegKey(DeviceInfoSet,
DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ);
if (hDriverKey == INVALID_HANDLE_VALUE)
{
default:
DPRINT1("Install function %u ignored\n", InstallFunction);
return ERROR_SUCCESS;
if (Context->PostProcessing)
{
dwError = GetLastError();
DPRINT1("Failed to open the driver key! (Error %lu)\n", dwError);
goto done;
}
else
{
DPRINT("Failed to open the driver key! Postprocessing required!\n");
return ERROR_DI_POSTPROCESSING_REQUIRED;
}
}
dwRequiredSize = sizeof(szDeviceId);
dwError = RegQueryValueExW(hDriverKey,
L"MatchingDeviceId",
NULL,
NULL,
(PBYTE)szDeviceId,
&dwRequiredSize);
RegCloseKey(hDriverKey);
if (dwError != ERROR_SUCCESS)
{
if (Context->PostProcessing)
{
dwError = GetLastError();
DPRINT1("Failed to read the MatchingDeviceId value! (Error %lu)\n", dwError);
goto done;
}
else
{
DPRINT("Failed to read the MatchingDeviceId value! Postprocessing required!\n");
return ERROR_DI_POSTPROCESSING_REQUIRED;
}
}
DPRINT("MatchingDeviceId: %S\n", szDeviceId);
/* Get the ClassGUID property */
dwRequiredSize = 0;
if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
DeviceInfoData,
SPDRP_CLASSGUID,
NULL,
(PBYTE)szClassGUID,
sizeof(szClassGUID),
&dwRequiredSize))
{
if (Context->PostProcessing)
{
dwError = GetLastError();
DPRINT1("Failed to read the ClassGUID! (Error %lu)\n", dwError);
goto done;
}
else
{
DPRINT("Failed to read the ClassGUID! Postprocessing required!\n");
return ERROR_DI_POSTPROCESSING_REQUIRED;
}
}
DPRINT("ClassGUID %S\n", szClassGUID);
/* Get the Service property (optional) */
dwRequiredSize = 0;
if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
DeviceInfoData,
SPDRP_SERVICE,
NULL,
(PBYTE)szServiceName,
sizeof(szServiceName),
&dwRequiredSize))
{
if (Context->PostProcessing)
{
dwError = GetLastError();
if (dwError != ERROR_FILE_NOT_FOUND)
{
DPRINT1("Failed to read the Service name! (Error %lu)\n", dwError);
goto done;
}
else
{
szServiceName[0] = UNICODE_NULL;
dwError = ERROR_SUCCESS;
}
}
else
{
DPRINT("Failed to read the Service name! Postprocessing required!\n");
return ERROR_DI_POSTPROCESSING_REQUIRED;
}
}
DPRINT("Service %S\n", szServiceName);
/* Replace the first backslash by a number sign */
Ptr = wcschr(szDeviceId, L'\\');
if (Ptr != NULL)
{
*Ptr = L'#';
/* Terminate the device id at the second backslash */
Ptr = wcschr(Ptr, L'\\');
if (Ptr != NULL)
*Ptr = UNICODE_NULL;
}
DPRINT("DeviceId: %S\n", szDeviceId);
/* Open the critical device database key */
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\CriticalDeviceDatabase",
0,
KEY_WRITE,
&hDatabaseKey);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("RegOpenKeyExW failed (Error %lu)\n", dwError);
goto done;
}
/* Create a new key for the device */
dwError = RegCreateKeyExW(hDatabaseKey,
szDeviceId,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hDeviceKey,
&dwDisposition);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("RegCreateKeyExW failed (Error %lu)\n", dwError);
goto done;
}
/* Set the ClassGUID value */
dwError = RegSetValueExW(hDeviceKey,
L"ClassGUID",
0,
REG_SZ,
(PBYTE)szClassGUID,
(wcslen(szClassGUID) + 1) * sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW failed (Error %lu)\n", dwError);
goto done;
}
/* If available, set the Service value */
if (szServiceName[0] != UNICODE_NULL)
{
dwError = RegSetValueExW(hDeviceKey,
L"Service",
0,
REG_SZ,
(PBYTE)szServiceName,
(wcslen(szServiceName) + 1) * sizeof(WCHAR));
if (dwError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW failed (Error %lu)\n", dwError);
goto done;
}
}
done:
if (hDeviceKey != NULL)
RegCloseKey(hDeviceKey);
if (hDatabaseKey != NULL)
RegCloseKey(hDatabaseKey);
DPRINT("CriticalDeviceCoInstaller() done (Error %lu)\n", dwError);
return dwError;
}