https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7f248437e88d0d5cd011b7c68e61e15edcecb05d
commit 7f248437e88d0d5cd011b7c68e61e15edcecb05d Author: Eric Kohl <eric.k...@reactos.org> AuthorDate: Sat Mar 1 15:43:34 2025 +0100 Commit: Eric Kohl <eric.k...@reactos.org> CommitDate: Sat Mar 1 15:43:34 2025 +0100 [NETCFGX] Simple implementation of INetCfgClassSetup.Install() Import device installer code from syssetup.dll. This is the first step to move the network component installer code from syssetup.dll to netcfgx.dll and netshell.dll. --- dll/win32/netcfgx/CMakeLists.txt | 1 + dll/win32/netcfgx/netcfgclass_iface.c | 2 + dll/win32/netcfgx/netinstall.c | 627 ++++++++++++++++++++++++++++++++++ dll/win32/netcfgx/precomp.h | 4 + 4 files changed, 634 insertions(+) diff --git a/dll/win32/netcfgx/CMakeLists.txt b/dll/win32/netcfgx/CMakeLists.txt index 3e4dfb3f8b8..5f499a2e0fd 100644 --- a/dll/win32/netcfgx/CMakeLists.txt +++ b/dll/win32/netcfgx/CMakeLists.txt @@ -8,6 +8,7 @@ list(APPEND SOURCE netcfgx.c classfactory.c installer.c + netinstall.c netcfg_iface.c netcfgbindinginterface_iface.c netcfgbindingpath_iface.c diff --git a/dll/win32/netcfgx/netcfgclass_iface.c b/dll/win32/netcfgx/netcfgclass_iface.c index 10eda26cad6..667f36df07c 100644 --- a/dll/win32/netcfgx/netcfgclass_iface.c +++ b/dll/win32/netcfgx/netcfgclass_iface.c @@ -77,6 +77,8 @@ INetCfgClassSetup_fnInstall( if (ppComponent) *ppComponent = NULL; + InstallNetworkComponent(pszwComponentId); + return S_OK; } diff --git a/dll/win32/netcfgx/netinstall.c b/dll/win32/netcfgx/netinstall.c new file mode 100644 index 00000000000..1d167d81d03 --- /dev/null +++ b/dll/win32/netcfgx/netinstall.c @@ -0,0 +1,627 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Network configuration + * FILE: dll/win32/netcfgx/netinstall.c + * PROGRAMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include "precomp.h" +#include <rpc.h> + + +typedef struct _COMPONENT_INFO +{ + PWSTR pszFullInfPath; + PWSTR pszInfPath; + PWSTR pszInfSection; + PWSTR pszComponentId; + PWSTR pszDescription; + PWSTR pszClassGuid; + DWORD dwCharacteristics; +} COMPONENT_INFO, *PCOMPONENT_INFO; + + +/* GLOBALS ******************************************************************/ + + +/* FUNCTIONS ****************************************************************/ + +static +BOOL +InstallInfSections( + _In_ HWND hWnd, + _In_ HKEY hKey, + _In_ LPCWSTR InfFile, + _In_ LPCWSTR InfSection) +{ + WCHAR Buffer[MAX_PATH]; + HINF hInf = INVALID_HANDLE_VALUE; + UINT BufferSize; + PVOID Context = NULL; + BOOL ret = FALSE; + + TRACE("InstallInfSections()\n"); + + if (InfSection == NULL) + return FALSE; + + /* Get Windows directory */ + BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile); + if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize) + { + /* Function failed */ + SetLastError(ERROR_GEN_FAILURE); + goto cleanup; + } + + /* We have enough space to add some information in the buffer */ + if (Buffer[wcslen(Buffer) - 1] != '\\') + wcscat(Buffer, L"\\"); + wcscat(Buffer, L"Inf\\"); + wcscat(Buffer, InfFile); + + /* Install specified section */ + hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL); + if (hInf == INVALID_HANDLE_VALUE) + goto cleanup; + + Context = SetupInitDefaultQueueCallback(hWnd); + if (Context == NULL) + goto cleanup; + + ret = SetupInstallFromInfSectionW( + hWnd, hInf, + InfSection, SPINST_ALL, + hKey, NULL, SP_COPY_NEWER, + SetupDefaultQueueCallbackW, Context, + NULL, NULL); + if (ret == FALSE) + { + ERR("SetupInstallFromInfSectionW(%S) failed (Error %lx)\n", InfSection, GetLastError()); + goto cleanup; + } + + wcscpy(Buffer, InfSection); + wcscat(Buffer, L".Services"); + + ret = SetupInstallServicesFromInfSectionW(hInf, Buffer, 0); + if (ret == FALSE) + { + ERR("SetupInstallServicesFromInfSectionW(%S) failed (Error %lx)\n", Buffer, GetLastError()); + goto cleanup; + } + +cleanup: + if (Context) + SetupTermDefaultQueueCallback(Context); + + if (hInf != INVALID_HANDLE_VALUE) + SetupCloseInfFile(hInf); + + TRACE("InstallInfSections() done %u\n", ret); + + return ret; +} + + +static +BOOL +CreateInstanceKey( + _In_ PCOMPONENT_INFO pComponentInfo, + _Out_ PHKEY pInstanceKey) +{ + WCHAR szKeyBuffer[128]; + LPWSTR UuidString = NULL; + UUID Uuid; + RPC_STATUS RpcStatus; + HKEY hInstanceKey; + DWORD rc; + BOOL ret = FALSE; + + TRACE("CreateInstanceKey()\n"); + + *pInstanceKey = NULL; + + wcscpy(szKeyBuffer, L"SYSTEM\\CurrentControlSet\\Control\\Network\\"); + wcscat(szKeyBuffer, pComponentInfo->pszClassGuid); + wcscat(szKeyBuffer, L"\\{"); + + /* Create a new UUID */ + RpcStatus = UuidCreate(&Uuid); + if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY) + { + ERR("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus); + goto done; + } + + RpcStatus = UuidToStringW(&Uuid, &UuidString); + if (RpcStatus != RPC_S_OK) + { + ERR("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus); + goto done; + } + + wcscat(szKeyBuffer, UuidString); + wcscat(szKeyBuffer, L"}"); + + RpcStringFreeW(&UuidString); + + TRACE("szKeyBuffer %S\n", szKeyBuffer); + + rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, + szKeyBuffer, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_CREATE_SUB_KEY | KEY_SET_VALUE, + NULL, + &hInstanceKey, + NULL); + if (rc != ERROR_SUCCESS) + { + ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc); + goto done; + } + + rc = RegSetValueExW(hInstanceKey, + L"Characteristics", + 0, + REG_DWORD, + (LPBYTE)&pComponentInfo->dwCharacteristics, + sizeof(DWORD)); + if (rc != ERROR_SUCCESS) + { + ERR("RegSetValueExW() failed with error 0x%lx\n", rc); + goto done; + } + + rc = RegSetValueExW(hInstanceKey, + L"ComponentId", + 0, + REG_SZ, + (LPBYTE)pComponentInfo->pszComponentId, + (wcslen(pComponentInfo->pszComponentId) + 1) * sizeof(WCHAR)); + if (rc != ERROR_SUCCESS) + { + ERR("RegSetValueExW() failed with error 0x%lx\n", rc); + goto done; + } + + rc = RegSetValueExW(hInstanceKey, + L"Description", + 0, + REG_SZ, + (LPBYTE)pComponentInfo->pszDescription, + (wcslen(pComponentInfo->pszDescription) + 1) * sizeof(WCHAR)); + if (rc != ERROR_SUCCESS) + { + ERR("RegSetValueExW() failed with error 0x%lx\n", rc); + goto done; + } + + rc = RegSetValueExW(hInstanceKey, + L"InfPath", + 0, + REG_SZ, + (LPBYTE)pComponentInfo->pszInfPath, + (wcslen(pComponentInfo->pszInfPath) + 1) * sizeof(WCHAR)); + if (rc != ERROR_SUCCESS) + { + ERR("RegSetValueExW() failed with error 0x%lx\n", rc); + goto done; + } + + rc = RegSetValueExW(hInstanceKey, + L"InfSection", + 0, + REG_SZ, + (LPBYTE)pComponentInfo->pszInfSection, + (wcslen(pComponentInfo->pszInfSection) + 1) * sizeof(WCHAR)); + if (rc != ERROR_SUCCESS) + { + ERR("RegSetValueExW() failed with error 0x%lx\n", rc); + goto done; + } + + *pInstanceKey = hInstanceKey; + ret = TRUE; + +done: + if (ret == FALSE) + RegCloseKey(hInstanceKey); + + TRACE("CreateInstanceKey() done %u\n", ret); + + return ret; +} + + +static +BOOL +CheckInfFile( + _In_ PWSTR pszFullInfName, + _In_ PCWSTR pszComponentId, + _In_ PCOMPONENT_INFO pComponentInfo) +{ + WCHAR szLineBuffer[MAX_PATH]; + HINF hInf = INVALID_HANDLE_VALUE; + INFCONTEXT MfgContext, DevContext, MiscContext; + DWORD dwLength; + + hInf = SetupOpenInfFileW(pszFullInfName, + NULL, + INF_STYLE_WIN4, + NULL); + if (hInf == INVALID_HANDLE_VALUE) + { + ERR("\n"); + return FALSE; + } + + if (!SetupFindFirstLineW(hInf, + L"Manufacturer", + NULL, + &MfgContext)) + { + ERR("No Manufacurer section found!\n"); + goto done; + } + + for (;;) + { + if (!SetupGetStringFieldW(&MfgContext, + 1, + szLineBuffer, + MAX_PATH, + NULL)) + break; + + TRACE("Manufacturer: %S\n", szLineBuffer); + if (!SetupFindFirstLineW(hInf, + szLineBuffer, + NULL, + &DevContext)) + break; + + for (;;) + { + if (!SetupGetStringFieldW(&DevContext, + 2, + szLineBuffer, + MAX_PATH, + NULL)) + break; + + TRACE("Device: %S\n", szLineBuffer); + if (_wcsicmp(szLineBuffer, pszComponentId) == 0) + { + TRACE("Found it!\n"); + + /* Get the section name*/ + SetupGetStringFieldW(&DevContext, + 1, + NULL, + 0, + &dwLength); + + pComponentInfo->pszInfSection = HeapAlloc(GetProcessHeap(), + 0, + dwLength * sizeof(WCHAR)); + if (pComponentInfo->pszInfSection) + { + SetupGetStringFieldW(&DevContext, + 1, + pComponentInfo->pszInfSection, + dwLength, + &dwLength); + } + + /* Get the description*/ + SetupGetStringFieldW(&DevContext, + 0, + NULL, + 0, + &dwLength); + + pComponentInfo->pszDescription = HeapAlloc(GetProcessHeap(), + 0, + dwLength * sizeof(WCHAR)); + if (pComponentInfo->pszDescription) + { + SetupGetStringFieldW(&DevContext, + 0, + pComponentInfo->pszDescription, + dwLength, + &dwLength); + } + + /* Get the class GUID */ + if (SetupFindFirstLineW(hInf, + L"Version", + L"ClassGuid", + &MiscContext)) + { + SetupGetStringFieldW(&MiscContext, + 1, + NULL, + 0, + &dwLength); + + pComponentInfo->pszClassGuid = HeapAlloc(GetProcessHeap(), + 0, + dwLength * sizeof(WCHAR)); + if (pComponentInfo->pszInfSection) + { + SetupGetStringFieldW(&MiscContext, + 1, + pComponentInfo->pszClassGuid, + dwLength, + &dwLength); + } + } + + /* Get the Characteristics value */ + if (SetupFindFirstLineW(hInf, + pComponentInfo->pszInfSection, + L"Characteristics", + &MiscContext)) + { + SetupGetIntField(&MiscContext, + 1, + (PINT)&pComponentInfo->dwCharacteristics); + } + + SetupCloseInfFile(hInf); + return TRUE; + } + + if (!SetupFindNextLine(&DevContext, &DevContext)) + break; + } + + if (!SetupFindNextLine(&MfgContext, &MfgContext)) + break; + } + +done: + if (hInf != INVALID_HANDLE_VALUE) + SetupCloseInfFile(hInf); + + return FALSE; +} + + +static +BOOL +ScanForInfFile( + _In_ PCWSTR pszComponentId, + _In_ PCOMPONENT_INFO pComponentInfo) +{ + WCHAR szInfPath[MAX_PATH]; + WCHAR szFullInfName[MAX_PATH]; + WCHAR szPathBuffer[MAX_PATH]; + WIN32_FIND_DATAW fdw; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + BOOL bFound = FALSE; + + GetWindowsDirectoryW(szInfPath, MAX_PATH); + wcscat(szInfPath, L"\\inf"); + + wcscpy(szPathBuffer, szInfPath); + wcscat(szPathBuffer, L"\\*.inf"); + + hFindFile = FindFirstFileW(szPathBuffer, &fdw); + if (hFindFile == INVALID_HANDLE_VALUE) + return FALSE; + + for (;;) + { + if (wcscmp(fdw.cFileName, L".") == 0 || + wcscmp(fdw.cFileName, L"..") == 0) + continue; + + TRACE("FileName: %S\n", fdw.cFileName); + + wcscpy(szFullInfName, szInfPath); + wcscat(szFullInfName, L"\\"); + wcscat(szFullInfName, fdw.cFileName); + + TRACE("Full Inf Name: %S\n", szFullInfName); + if (CheckInfFile(szFullInfName, + pszComponentId, + pComponentInfo)) + { + pComponentInfo->pszFullInfPath = HeapAlloc(GetProcessHeap(), + 0, + (wcslen(szFullInfName) + 1) * sizeof(WCHAR)); + if (pComponentInfo->pszFullInfPath) + wcscpy(pComponentInfo->pszFullInfPath, szFullInfName); + + pComponentInfo->pszInfPath = HeapAlloc(GetProcessHeap(), + 0, + (wcslen(fdw.cFileName) + 1) * sizeof(WCHAR)); + if (pComponentInfo->pszInfPath) + wcscpy(pComponentInfo->pszInfPath, fdw.cFileName); + + pComponentInfo->pszComponentId = HeapAlloc(GetProcessHeap(), + 0, + (wcslen(pszComponentId) + 1) * sizeof(WCHAR)); + if (pComponentInfo->pszComponentId) + wcscpy(pComponentInfo->pszComponentId, pszComponentId); + + bFound = TRUE; + break; + } + + if (!FindNextFileW(hFindFile, &fdw)) + break; + } + + if (hFindFile != INVALID_HANDLE_VALUE) + FindClose(hFindFile); + + return bFound; +} + +static +VOID +StartNetworkServices( + _In_ PCOMPONENT_INFO pComponentInfo) +{ + WCHAR szServiceName[64]; + HINF hInf = INVALID_HANDLE_VALUE; + INFCONTEXT Context; + PWSTR pServiceSection = NULL; + + SC_HANDLE hManager = NULL; + SC_HANDLE hService = NULL; + + hManager = OpenSCManagerW(NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + if (hManager == NULL) + { + ERR("\n"); + goto done; + } + + hInf = SetupOpenInfFileW(pComponentInfo->pszFullInfPath, + NULL, + INF_STYLE_WIN4, + NULL); + if (hInf == INVALID_HANDLE_VALUE) + { + ERR("\n"); + goto done; + } + + pServiceSection = HeapAlloc(GetProcessHeap(), 0, + (wcslen(pComponentInfo->pszInfSection) + wcslen(L".Service") + 1) * sizeof(WCHAR)); + if (pServiceSection == NULL) + { + ERR("\n"); + goto done; + } + + wcscpy(pServiceSection, pComponentInfo->pszInfSection); + wcscat(pServiceSection, L".Service"); + + TRACE("ServiceSection: %S\n", pServiceSection); + + if (!SetupFindFirstLineW(hInf, + pServiceSection, + L"AddService", + &Context)) + { + ERR("\n"); + goto done; + } + + for (;;) + { + SetupGetStringFieldW(&Context, + 1, + szServiceName, + 64, + NULL); + + hService = OpenServiceW(hManager, + szServiceName, + SERVICE_START); + if (hService) + { + if (!StartService(hService, 0, NULL)) + { + ERR("StartService() %S failed %lu\n", szServiceName, GetLastError()); + } + + CloseServiceHandle(hService); + } + + if (!SetupFindNextLine(&Context, &Context)) + break; + } + +done: + if (pServiceSection) + HeapFree(GetProcessHeap(), 0, pServiceSection); + + if (hInf != INVALID_HANDLE_VALUE) + SetupCloseInfFile(hInf); + + if (hManager != NULL) + CloseServiceHandle(hManager); +} + + +BOOL +InstallNetworkComponent( + _In_ PCWSTR pszComponentId) +{ + COMPONENT_INFO ComponentInfo; + HKEY hInstanceKey = NULL; + BOOL bResult = FALSE; + + TRACE("InstallNetworkComponent(%S)\n", pszComponentId); + + ZeroMemory(&ComponentInfo, sizeof(COMPONENT_INFO)); + + if (!ScanForInfFile(pszComponentId, &ComponentInfo)) + goto done; + + TRACE("Characteristics: 0x%lx\n", ComponentInfo.dwCharacteristics); + TRACE("ComponentId: %S\n", ComponentInfo.pszComponentId); + TRACE("Description: %S\n", ComponentInfo.pszDescription); + TRACE("InfPath: %S\n", ComponentInfo.pszInfPath); + TRACE("InfSection: %S\n", ComponentInfo.pszInfSection); + TRACE("ClassGuid: %S\n", ComponentInfo.pszClassGuid); + + if (!CreateInstanceKey(&ComponentInfo, + &hInstanceKey)) + { + ERR("CreateInstanceKey() failed (Error %lx)\n", GetLastError()); + goto done; + } + + if (!InstallInfSections(NULL, + hInstanceKey, + ComponentInfo.pszInfPath, + ComponentInfo.pszInfSection)) + { + ERR("InstallInfSections() failed (Error %lx)\n", GetLastError()); + goto done; + } + + bResult = TRUE; + + StartNetworkServices(&ComponentInfo); + +done: + if (hInstanceKey != NULL) + RegCloseKey(hInstanceKey); + + if (ComponentInfo.pszFullInfPath) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszFullInfPath); + + if (ComponentInfo.pszInfPath) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfPath); + + if (ComponentInfo.pszInfSection) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfSection); + + if (ComponentInfo.pszComponentId) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszComponentId); + + if (ComponentInfo.pszDescription) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszDescription); + + if (ComponentInfo.pszClassGuid) + HeapFree(GetProcessHeap(), 0, ComponentInfo.pszClassGuid); + + return bResult; +} + +/* EOF */ diff --git a/dll/win32/netcfgx/precomp.h b/dll/win32/netcfgx/precomp.h index e8551f7c43f..4823576c483 100644 --- a/dll/win32/netcfgx/precomp.h +++ b/dll/win32/netcfgx/precomp.h @@ -14,6 +14,7 @@ #include <windef.h> #include <winbase.h> #include <winreg.h> +#include <winsvc.h> #include <windowsx.h> #include <objbase.h> #include <netcfgx.h> @@ -76,6 +77,9 @@ HRESULT WINAPI IEnumNetCfgBindingPath_Constructor(IUnknown *pUnkOuter, REFIID ri /* netcfgclass_iface.c */ HRESULT WINAPI INetCfgClass_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv, const GUID *pguidClass, INetCfg *pNetCfg); +/* netinstall.c */ +BOOL InstallNetworkComponent(_In_ PCWSTR pszComponentId); + /* tcpipconf_notify.c */ HRESULT WINAPI TcpipConfigNotify_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);