From: Eric Kohl Date: Sun, 30 Sep 2018 15:18:28 +0000 (+0200) Subject: [SYSETUP] Implement the CriticalDeviceCoInstaller X-Git-Tag: 0.4.12-dev~694 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=4aa1bee7572664224a7f368dff0d56dfea922b1f [SYSETUP] Implement the CriticalDeviceCoInstaller The CriticalDeviceCoInstaller adds devices of registered classes to the critical device database. --- diff --git a/dll/win32/syssetup/classinst.c b/dll/win32/syssetup/classinst.c index 6eb949e568c..d7ea97e1d0a 100644 --- a/dll/win32/syssetup/classinst.c +++ b/dll/win32/syssetup/classinst.c @@ -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; }