/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Configuration of networkd devices
- * FILE: lib/netcfgx/netcfgx.c
+ * PROJECT: ReactOS Configuration of network devices
+ * FILE: dll/win32/netcfgx/netcfgx.c
* PURPOSE: Network devices installer
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
+
+#include "precomp.h"
+#include <initguid.h>
+#include <devguid.h>
#define NDEBUG
#include <debug.h>
-#include "netcfgx.h"
+HINSTANCE netcfgx_hInstance;
+const GUID CLSID_TcpipConfigNotifyObject = {0xA907657F, 0x6FDF, 0x11D0, {0x8E, 0xFB, 0x00, 0xC0, 0x4F, 0xD9, 0x12, 0xB2}};
+
+
+
+
+static INTERFACE_TABLE InterfaceTable[] =
+{
+ {
+ &CLSID_CNetCfg,
+ INetCfg_Constructor
+ },
+ {
+ &CLSID_TcpipConfigNotifyObject,
+ TcpipConfigNotify_Constructor
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+BOOL
+WINAPI
+DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ netcfgx_hInstance = hinstDLL;
+ DisableThreadLibraryCalls(netcfgx_hInstance);
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+HRESULT
+WINAPI
+DllCanUnloadNow(void)
+{
+ return S_FALSE;
+}
+
+STDAPI
+DllRegisterServer(void)
+{
+ HKEY hKey, hSubKey;
+ LPOLESTR pStr;
+ WCHAR szName[MAX_PATH] = L"CLSID\\";
+
+ if (FAILED(StringFromCLSID(&CLSID_CNetCfg, &pStr)))
+ return SELFREG_E_CLASS;
+
+ wcscpy(&szName[6], pStr);
+ CoTaskMemFree(pStr);
+
+ if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szName, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
+ return SELFREG_E_CLASS;
+
+ if (RegCreateKeyExW(hKey, L"InProcServer32", 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
+ {
+ if (!GetModuleFileNameW(netcfgx_hInstance, szName, sizeof(szName)/sizeof(WCHAR)))
+ {
+ RegCloseKey(hSubKey);
+ RegCloseKey(hKey);
+ return SELFREG_E_CLASS;
+ }
+ szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
+ RegSetValueW(hSubKey, NULL, REG_SZ, szName, (wcslen(szName)+1) * sizeof(WCHAR));
+ RegSetValueExW(hSubKey, L"ThreadingModel", 0, REG_SZ, (LPBYTE)L"Both", 10);
+ RegCloseKey(hSubKey);
+ }
+
+ RegCloseKey(hKey);
+ return S_OK;
+}
+
+STDAPI
+DllUnregisterServer(void)
+{
+ //FIXME
+ // implement unregistering services
+ //
+ return S_OK;
+}
+
+STDAPI
+DllGetClassObject(
+ REFCLSID rclsid,
+ REFIID riid,
+ LPVOID* ppv
+)
+{
+ UINT i;
+ HRESULT hres = E_OUTOFMEMORY;
+ IClassFactory * pcf = NULL;
+
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+
+ for (i = 0; InterfaceTable[i].riid; i++)
+ {
+ if (IsEqualIID(InterfaceTable[i].riid, rclsid))
+ {
+ pcf = IClassFactory_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
+ break;
+ }
+ }
+
+ if (!pcf)
+ {
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ hres = IClassFactory_QueryInterface(pcf, riid, ppv);
+ IClassFactory_Release(pcf);
+
+ return hres;
+}
+
/* Append a REG_SZ to an existing REG_MULTI_SZ string in the registry.
* If the value doesn't exist, create it.
InstallInfSection(
IN HWND hWnd,
IN LPCWSTR InfFile,
- IN LPCWSTR InfSection)
+ IN LPCWSTR InfSection OPTIONAL,
+ IN LPCWSTR InfService OPTIONAL)
{
WCHAR Buffer[MAX_PATH];
HINF hInf = INVALID_HANDLE_VALUE;
if (Context == NULL)
goto cleanup;
- ret = SetupInstallFromInfSectionW(
- hWnd, hInf,
- InfSection, SPINST_ALL,
- NULL, NULL, SP_COPY_NEWER,
- SetupDefaultQueueCallbackW, Context,
- NULL, NULL);
+ ret = TRUE;
+ if (ret && InfSection)
+ {
+ ret = SetupInstallFromInfSectionW(
+ hWnd, hInf,
+ InfSection, SPINST_ALL,
+ NULL, NULL, SP_COPY_NEWER,
+ SetupDefaultQueueCallbackW, Context,
+ NULL, NULL);
+ }
+ if (ret && InfService)
+ {
+ ret = SetupInstallServicesFromInfSectionW(
+ hInf, InfService, 0);
+ }
cleanup:
if (Context)
IN HWND hWnd)
{
BOOL ret;
+ UNICODE_STRING TcpipServicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip");
/* Install TCP/IP protocol */
ret = InstallInfSection(
hWnd,
L"nettcpip.inf",
- L"MS_TCPIP.PrimaryInstall");
+ L"MS_TCPIP.PrimaryInstall",
+ L"MS_TCPIP.PrimaryInstall.Services");
if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND)
{
DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
return GetLastError();
}
+ else if (ret)
+ {
+ /* Start the TCP/IP driver */
+ ret = NtLoadDriver(&TcpipServicePath);
+ if (ret)
+ {
+ /* This isn't really fatal but we want to warn anyway */
+ DPRINT1("NtLoadDriver(TCPIP) failed with NTSTATUS 0x%lx\n", (NTSTATUS)ret);
+ }
+ }
+
/* You can add here more clients (SMB...) and services (DHCP server...) */
return ERROR_SUCCESS;
}
-DWORD WINAPI
-NetClassInstaller(
- IN DI_FUNCTION InstallFunction,
+static DWORD
+InstallNetDevice(
IN HDEVINFO DeviceInfoSet,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ LPCWSTR UuidString,
+ DWORD Characteristics,
+ LPCWSTR BusType)
{
- RPC_STATUS RpcStatus;
- UUID Uuid;
LPWSTR InstanceId = NULL;
- LPWSTR UuidRpcString = NULL;
- LPWSTR UuidString = NULL;
LPWSTR DeviceName = NULL;
LPWSTR ExportName = NULL;
LONG rc;
- DWORD dwShowIcon, dwLength;
- HKEY hKey = INVALID_HANDLE_VALUE;
- HKEY hLinkageKey = INVALID_HANDLE_VALUE;
- HKEY hNetworkKey = INVALID_HANDLE_VALUE;
- HKEY hConnectionKey = INVALID_HANDLE_VALUE;
-
- if (InstallFunction != DIF_INSTALLDEVICE)
- return ERROR_DI_DO_DEFAULT;
-
- DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
+ HKEY hKey = NULL;
+ HKEY hNetworkKey = NULL;
+ HKEY hLinkageKey = NULL;
+ HKEY hConnectionKey = NULL;
+ DWORD dwShowIcon, dwLength, dwValue;
/* Get Instance ID */
if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
rc = ERROR_GEN_FAILURE;
goto cleanup;
}
- InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
if (!InstanceId)
{
DPRINT("HeapAlloc() failed\n");
goto cleanup;
}
- /* Create a new UUID */
- RpcStatus = UuidCreate(&Uuid);
- if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
- {
- DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
- rc = ERROR_GEN_FAILURE;
- goto cleanup;
- }
- RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
- if (RpcStatus != RPC_S_OK)
- {
- DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
- rc = ERROR_GEN_FAILURE;
- goto cleanup;
- }
-
- /* Add curly braces around Uuid */
- UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
- if (!UuidString)
- {
- DPRINT("HeapAlloc() failed\n");
- rc = ERROR_NOT_ENOUGH_MEMORY;
- goto cleanup;
- }
- wcscpy(UuidString, L"{");
- wcscat(UuidString, UuidRpcString);
- wcscat(UuidString, L"}");
-
/* Create device name */
DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
if (!DeviceName)
}
wcscpy(DeviceName, L"\\Device\\");
wcscat(DeviceName, UuidString);
-
+
/* Create export name */
ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
if (!ExportName)
goto cleanup;
}
RegCloseKey(hKey);
- hKey = INVALID_HANDLE_VALUE;
+ hKey = NULL;
rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
if (rc != ERROR_SUCCESS)
{
goto cleanup;
}
RegCloseKey(hNetworkKey);
- hNetworkKey = INVALID_HANDLE_VALUE;
+ hNetworkKey = NULL;
rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
goto cleanup;
}
+ dwValue = 1;
+ rc = RegSetValueExW(hKey, L"DhcpEnabled", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
+ if (rc != ERROR_SUCCESS)
+ {
+ DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
RegCloseKey(hKey);
- hKey = INVALID_HANDLE_VALUE;
+ hKey = NULL;
/* Write 'Linkage' key in hardware key */
#if _WIN32_WINNT >= 0x502
hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
if (hKey == INVALID_HANDLE_VALUE)
{
+ hKey = NULL;
rc = GetLastError();
DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
goto cleanup;
DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
goto cleanup;
}
+ rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
+ if (rc != ERROR_SUCCESS)
+ {
+ DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ if (BusType)
+ rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
+ if (rc != ERROR_SUCCESS)
+ {
+ DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
if (rc != ERROR_SUCCESS)
{
goto cleanup;
}
RegCloseKey(hKey);
- hKey = INVALID_HANDLE_VALUE;
+ hKey = NULL;
/* Write connection information in network subkey */
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
}
rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
RegCloseKey(hKey);
- hKey = INVALID_HANDLE_VALUE;
+ hKey = NULL;
if (rc != ERROR_SUCCESS)
{
DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
}
/* Install additionnal services */
- /* FIXME: do it only if it is a network adapter! */
rc = InstallAdditionalServices(NULL);
if (rc != ERROR_SUCCESS)
{
goto cleanup;
}
- /* HACK: hpoussin, Dec 2005. TCP/IP driver is not able to manage devices
- * which are installed after its startup. So, we have to reboot to take
- * this new netcard into account.
- */
- MessageBox(NULL, TEXT("You need to reboot to finish the installation of your network card."), TEXT("Reboot required"), MB_OK | MB_ICONWARNING);
rc = ERROR_SUCCESS;
cleanup:
- if (UuidRpcString != NULL)
- RpcStringFreeW(&UuidRpcString);
HeapFree(GetProcessHeap(), 0, InstanceId);
- HeapFree(GetProcessHeap(), 0, UuidString);
HeapFree(GetProcessHeap(), 0, DeviceName);
HeapFree(GetProcessHeap(), 0, ExportName);
- if (hKey != INVALID_HANDLE_VALUE)
+ if (hKey != NULL)
RegCloseKey(hKey);
- if (hLinkageKey != INVALID_HANDLE_VALUE)
- RegCloseKey(hLinkageKey);
- if (hNetworkKey != INVALID_HANDLE_VALUE)
+ if (hNetworkKey != NULL)
RegCloseKey(hNetworkKey);
- if (hConnectionKey != INVALID_HANDLE_VALUE)
+ if (hLinkageKey != NULL)
+ RegCloseKey(hLinkageKey);
+ if (hConnectionKey != NULL)
RegCloseKey(hConnectionKey);
+ return rc;
+}
+
+static DWORD
+InstallNetClient(VOID)
+{
+ DPRINT1("Installation of network clients is not yet supported\n");
+ return ERROR_GEN_FAILURE;
+}
+
+static DWORD
+InstallNetService(VOID)
+{
+ DPRINT1("Installation of network services is not yet supported\n");
+ return ERROR_GEN_FAILURE;
+}
+
+static DWORD
+InstallNetTransport(VOID)
+{
+ DPRINT1("Installation of network protocols is not yet supported\n");
+ return ERROR_GEN_FAILURE;
+}
+
+DWORD WINAPI
+NetClassInstaller(
+ IN DI_FUNCTION InstallFunction,
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+{
+ SP_DRVINFO_DATA_W DriverInfoData;
+ SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
+ WCHAR SectionName[LINE_LEN];
+ HINF hInf = INVALID_HANDLE_VALUE;
+ INFCONTEXT InfContext;
+ UINT ErrorLine;
+ INT CharacteristicsInt;
+ DWORD Characteristics;
+ LPWSTR BusType = NULL;
+ RPC_STATUS RpcStatus;
+ UUID Uuid;
+ LPWSTR UuidRpcString = NULL;
+ LPWSTR UuidString = NULL;
+ LONG rc;
+ DWORD dwLength;
+
+ if (InstallFunction != DIF_INSTALLDEVICE)
+ return ERROR_DI_DO_DEFAULT;
+
+ DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
+
+ /* Get driver info details */
+ DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
+ if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
+ {
+ rc = GetLastError();
+ DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
+ if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
+ && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ rc = GetLastError();
+ DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
+ if (hInf == INVALID_HANDLE_VALUE)
+ {
+ rc = GetLastError();
+ DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
+ {
+ rc = GetLastError();
+ DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+
+ /* Get Characteristics and BusType (optional) from .inf file */
+ if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
+ {
+ rc = GetLastError();
+ DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
+ L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
+ goto cleanup;
+ }
+ if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
+ {
+ rc = GetLastError();
+ DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ Characteristics = (DWORD)CharacteristicsInt;
+ if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
+ {
+ if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
+ {
+ if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
+ {
+ rc = GetLastError();
+ DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
+ if (!BusType)
+ {
+ DPRINT("HeapAlloc() failed\n");
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+ if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
+ {
+ rc = GetLastError();
+ DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
+ goto cleanup;
+ }
+ }
+ }
+
+ /* Create a new UUID */
+ RpcStatus = UuidCreate(&Uuid);
+ if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
+ {
+ DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
+ }
+ RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
+ if (RpcStatus != RPC_S_OK)
+ {
+ DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
+ rc = ERROR_GEN_FAILURE;
+ goto cleanup;
+ }
+
+ /* Add curly braces around Uuid */
+ UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+ if (!UuidString)
+ {
+ DPRINT("HeapAlloc() failed\n");
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+ wcscpy(UuidString, L"{");
+ wcscat(UuidString, UuidRpcString);
+ wcscat(UuidString, L"}");
+
+ if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
+ rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
+ else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
+ rc = InstallNetClient();
+ else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
+ rc = InstallNetService();
+ else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
+ rc = InstallNetTransport();
+ else
+ {
+ DPRINT("Invalid class guid\n");
+ rc = ERROR_GEN_FAILURE;
+ }
+
+cleanup:
+ if (hInf != INVALID_HANDLE_VALUE)
+ SetupCloseInfFile(hInf);
+ if (UuidRpcString != NULL)
+ RpcStringFreeW(&UuidRpcString);
+ HeapFree(GetProcessHeap(), 0, BusType);
+ HeapFree(GetProcessHeap(), 0, UuidString);
if (rc == ERROR_SUCCESS)
rc = ERROR_DI_DO_DEFAULT;