reactos/dll/win32/syssetup/netinstall.c

529 lines
16 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: System setup
* FILE: dll/win32/syssetup/netinstall.c
* PROGRAMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "precomp.h"
#include <rpc.h>
#define NDEBUG
#include <debug.h>
typedef struct _COMPONENT_INFO
{
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;
DPRINT("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)
{
DPRINT1("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)
{
DPRINT1("SetupInstallServicesFromInfSectionW(%S) failed (Error %lx)\n", Buffer, GetLastError());
goto cleanup;
}
cleanup:
if (Context)
SetupTermDefaultQueueCallback(Context);
if (hInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(hInf);
DPRINT("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;
DPRINT("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)
{
DPRINT1("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
goto done;
}
RpcStatus = UuidToStringW(&Uuid, &UuidString);
if (RpcStatus != RPC_S_OK)
{
DPRINT1("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
goto done;
}
wcscat(szKeyBuffer, UuidString);
wcscat(szKeyBuffer, L"}");
RpcStringFreeW(&UuidString);
DPRINT("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)
{
DPRINT1("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)
{
DPRINT1("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)
{
DPRINT1("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)
{
DPRINT1("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)
{
DPRINT1("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)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
*pInstanceKey = hInstanceKey;
ret = TRUE;
done:
if (ret == FALSE)
RegCloseKey(hInstanceKey);
DPRINT("CreateInstanceKey() done %u\n", ret);
return ret;
}
static
BOOL
CheckInfFile(
_In_ PWSTR pszFullInfName,
_In_ PWSTR 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)
{
DPRINT1("\n");
return FALSE;
}
if (!SetupFindFirstLineW(hInf,
L"Manufacturer",
NULL,
&MfgContext))
{
DPRINT("No Manufacurer section found!\n");
goto done;
}
for (;;)
{
if (!SetupGetStringFieldW(&MfgContext,
1,
szLineBuffer,
MAX_PATH,
NULL))
break;
DPRINT("Manufacturer: %S\n", szLineBuffer);
if (!SetupFindFirstLineW(hInf,
szLineBuffer,
NULL,
&DevContext))
break;
for (;;)
{
if (!SetupGetStringFieldW(&DevContext,
2,
szLineBuffer,
MAX_PATH,
NULL))
break;
DPRINT("Device: %S\n", szLineBuffer);
if (_wcsicmp(szLineBuffer, pszComponentId) == 0)
{
DPRINT("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_ PWSTR 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;
DPRINT("FileName: %S\n", fdw.cFileName);
wcscpy(szFullInfName, szInfPath);
wcscat(szFullInfName, L"\\");
wcscat(szFullInfName, fdw.cFileName);
DPRINT("Full Inf Name: %S\n", szFullInfName);
if (CheckInfFile(szFullInfName,
pszComponentId,
pComponentInfo))
{
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;
}
BOOL
InstallNetworkComponent(
_In_ PWSTR pszComponentId)
{
COMPONENT_INFO ComponentInfo;
HKEY hInstanceKey = NULL;
BOOL bResult = FALSE;
DPRINT("InstallNetworkComponent(%S)\n", pszComponentId);
ZeroMemory(&ComponentInfo, sizeof(COMPONENT_INFO));
if (!ScanForInfFile(pszComponentId, &ComponentInfo))
goto done;
DPRINT("Characteristics: 0x%lx\n", ComponentInfo.dwCharacteristics);
DPRINT("ComponentId: %S\n", ComponentInfo.pszComponentId);
DPRINT("Description: %S\n", ComponentInfo.pszDescription);
DPRINT("InfPath: %S\n", ComponentInfo.pszInfPath);
DPRINT("InfSection: %S\n", ComponentInfo.pszInfSection);
DPRINT("ClassGuid: %S\n", ComponentInfo.pszClassGuid);
if (!CreateInstanceKey(&ComponentInfo,
&hInstanceKey))
{
DPRINT1("CreateInstanceKey() failed (Error %lx)\n", GetLastError());
goto done;
}
if (!InstallInfSections(NULL,
hInstanceKey,
ComponentInfo.pszInfPath,
ComponentInfo.pszInfSection))
{
DPRINT1("InstallInfSections() failed (Error %lx)\n", GetLastError());
goto done;
}
bResult = TRUE;
done:
if (hInstanceKey != NULL)
RegCloseKey(hInstanceKey);
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 */