2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of networkd devices
4 * FILE: lib/netcfgx/netcfgx.c
5 * PURPOSE: Network devices installer
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
15 /* Append a REG_SZ to an existing REG_MULTI_SZ string in the registry.
16 * If the value doesn't exist, create it.
17 * Returns ERROR_SUCCESS if success. Othewise, returns an error code
20 AppendStringToMultiSZ(
23 IN PCWSTR ValueToAppend
)
27 DWORD dwRequired
, dwLength
;
31 rc
= RegQueryValueExW(
38 if (rc
!= ERROR_FILE_NOT_FOUND
)
40 if (rc
!= ERROR_SUCCESS
)
42 if (dwRegType
!= REG_MULTI_SZ
)
44 rc
= ERROR_GEN_FAILURE
;
48 dwTmp
= dwLength
= dwRequired
+ wcslen(ValueToAppend
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
49 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
52 rc
= ERROR_NOT_ENOUGH_MEMORY
;
55 rc
= RegQueryValueExW(
62 if (rc
!= ERROR_SUCCESS
)
67 dwRequired
= sizeof(WCHAR
);
68 dwLength
= wcslen(ValueToAppend
) * sizeof(WCHAR
) + 2 * sizeof(UNICODE_NULL
);
69 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
72 rc
= ERROR_NOT_ENOUGH_MEMORY
;
77 /* Append the value */
78 wcscpy(&Buffer
[dwRequired
/ sizeof(WCHAR
) - 1], ValueToAppend
);
79 /* Terminate the REG_MULTI_SZ string */
80 Buffer
[dwLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
91 HeapFree(GetProcessHeap(), 0, Buffer
);
95 /* Install a section of a .inf file
96 * Returns TRUE if success, FALSE if failure. Error code can
97 * be retrieved with GetLastError()
103 IN LPCWSTR InfSection
)
105 WCHAR Buffer
[MAX_PATH
];
106 HINF hInf
= INVALID_HANDLE_VALUE
;
108 PVOID Context
= NULL
;
111 /* Get Windows directory */
112 BufferSize
= MAX_PATH
- 5 - wcslen(InfFile
);
113 if (GetWindowsDirectoryW(Buffer
, BufferSize
) > BufferSize
)
115 /* Function failed */
116 SetLastError(ERROR_GEN_FAILURE
);
119 /* We have enough space to add some information in the buffer */
120 if (Buffer
[wcslen(Buffer
) - 1] != '\\')
121 wcscat(Buffer
, L
"\\");
122 wcscat(Buffer
, L
"Inf\\");
123 wcscat(Buffer
, InfFile
);
125 /* Install specified section */
126 hInf
= SetupOpenInfFileW(Buffer
, NULL
, INF_STYLE_WIN4
, NULL
);
127 if (hInf
== INVALID_HANDLE_VALUE
)
130 Context
= SetupInitDefaultQueueCallback(hWnd
);
134 ret
= SetupInstallFromInfSectionW(
136 InfSection
, SPINST_ALL
,
137 NULL
, NULL
, SP_COPY_NEWER
,
138 SetupDefaultQueueCallbackW
, Context
,
143 SetupTermDefaultQueueCallback(Context
);
144 if (hInf
!= INVALID_HANDLE_VALUE
)
145 SetupCloseInfFile(hInf
);
149 /* Add default services for network cards */
151 InstallAdditionalServices(
156 /* Install TCP/IP protocol */
157 ret
= InstallInfSection(
160 L
"MS_TCPIP.PrimaryInstall");
161 if (!ret
&& GetLastError() != ERROR_FILE_NOT_FOUND
)
163 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
164 return GetLastError();
167 /* You can add here more clients (SMB...) and services (DHCP server...) */
169 return ERROR_SUCCESS
;
174 IN DI_FUNCTION InstallFunction
,
175 IN HDEVINFO DeviceInfoSet
,
176 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
178 RPC_STATUS RpcStatus
;
180 LPWSTR InstanceId
= NULL
;
181 LPWSTR UuidRpcString
= NULL
;
182 LPWSTR UuidString
= NULL
;
183 LPWSTR DeviceName
= NULL
;
184 LPWSTR ExportName
= NULL
;
186 DWORD dwShowIcon
, dwLength
;
187 HKEY hKey
= INVALID_HANDLE_VALUE
;
188 HKEY hLinkageKey
= INVALID_HANDLE_VALUE
;
189 HKEY hNetworkKey
= INVALID_HANDLE_VALUE
;
190 HKEY hConnectionKey
= INVALID_HANDLE_VALUE
;
192 if (InstallFunction
!= DIF_INSTALLDEVICE
)
193 return ERROR_DI_DO_DEFAULT
;
195 DPRINT("%lu %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
197 /* Get Instance ID */
198 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, NULL
, 0, &dwLength
))
200 DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
201 rc
= ERROR_GEN_FAILURE
;
204 InstanceId
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
207 DPRINT("HeapAlloc() failed\n");
208 rc
= ERROR_NOT_ENOUGH_MEMORY
;
211 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, InstanceId
, dwLength
, NULL
))
214 DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc
);
218 /* Create a new UUID */
219 RpcStatus
= UuidCreate(&Uuid
);
220 if (RpcStatus
!= RPC_S_OK
&& RpcStatus
!= RPC_S_UUID_LOCAL_ONLY
)
222 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus
);
223 rc
= ERROR_GEN_FAILURE
;
226 RpcStatus
= UuidToStringW(&Uuid
, &UuidRpcString
);
227 if (RpcStatus
!= RPC_S_OK
)
229 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus
);
230 rc
= ERROR_GEN_FAILURE
;
234 /* Add curly braces around Uuid */
235 UuidString
= HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
238 DPRINT("HeapAlloc() failed\n");
239 rc
= ERROR_NOT_ENOUGH_MEMORY
;
242 wcscpy(UuidString
, L
"{");
243 wcscat(UuidString
, UuidRpcString
);
244 wcscat(UuidString
, L
"}");
246 /* Create device name */
247 DeviceName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
250 DPRINT("HeapAlloc() failed\n");
251 rc
= ERROR_NOT_ENOUGH_MEMORY
;
254 wcscpy(DeviceName
, L
"\\Device\\");
255 wcscat(DeviceName
, UuidString
);
257 /* Create export name */
258 ExportName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\Tcpip_") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
261 DPRINT("HeapAlloc() failed\n");
262 rc
= ERROR_NOT_ENOUGH_MEMORY
;
265 wcscpy(ExportName
, L
"\\Device\\Tcpip_");
266 wcscat(ExportName
, UuidString
);
268 /* Write Tcpip parameters in new service Key */
269 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services", 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hKey
, NULL
);
270 if (rc
!= ERROR_SUCCESS
)
272 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
275 rc
= RegCreateKeyExW(hKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hNetworkKey
, NULL
);
276 if (rc
!= ERROR_SUCCESS
)
278 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
282 hKey
= INVALID_HANDLE_VALUE
;
283 rc
= RegCreateKeyExW(hNetworkKey
, L
"Parameters\\Tcpip", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hKey
, NULL
);
284 if (rc
!= ERROR_SUCCESS
)
286 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
289 RegCloseKey(hNetworkKey
);
290 hNetworkKey
= INVALID_HANDLE_VALUE
;
291 rc
= RegSetValueExW(hKey
, L
"DefaultGateway", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
292 if (rc
!= ERROR_SUCCESS
)
294 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
297 rc
= RegSetValueExW(hKey
, L
"IPAddress", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
298 if (rc
!= ERROR_SUCCESS
)
300 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
303 rc
= RegSetValueExW(hKey
, L
"SubnetMask", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
304 if (rc
!= ERROR_SUCCESS
)
306 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
310 hKey
= INVALID_HANDLE_VALUE
;
312 /* Write 'Linkage' key in hardware key */
313 #if _WIN32_WINNT >= 0x502
314 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
316 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
318 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
319 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
320 if (hKey
== INVALID_HANDLE_VALUE
)
323 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc
);
326 rc
= RegSetValueExW(hKey
, L
"NetCfgInstanceId", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
327 if (rc
!= ERROR_SUCCESS
)
329 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
332 rc
= RegCreateKeyExW(hKey
, L
"Linkage", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hLinkageKey
, NULL
);
333 if (rc
!= ERROR_SUCCESS
)
335 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
338 rc
= RegSetValueExW(hLinkageKey
, L
"Export", 0, REG_SZ
, (const BYTE
*)DeviceName
, (wcslen(DeviceName
) + 1) * sizeof(WCHAR
));
339 if (rc
!= ERROR_SUCCESS
)
341 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
344 rc
= RegSetValueExW(hLinkageKey
, L
"RootDevice", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
345 if (rc
!= ERROR_SUCCESS
)
347 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
350 rc
= RegSetValueExW(hLinkageKey
, L
"UpperBind", 0, REG_SZ
, (const BYTE
*)L
"Tcpip", (wcslen(L
"Tcpip") + 1) * sizeof(WCHAR
));
351 if (rc
!= ERROR_SUCCESS
)
353 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
357 hKey
= INVALID_HANDLE_VALUE
;
359 /* Write connection information in network subkey */
360 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
);
361 if (rc
!= ERROR_SUCCESS
)
363 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
366 rc
= RegCreateKeyExW(hNetworkKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hKey
, NULL
);
367 if (rc
!= ERROR_SUCCESS
)
369 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
372 rc
= RegCreateKeyExW(hKey
, L
"Connection", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hConnectionKey
, NULL
);
374 hKey
= INVALID_HANDLE_VALUE
;
375 if (rc
!= ERROR_SUCCESS
)
377 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
380 rc
= RegSetValueExW(hConnectionKey
, L
"Name", 0, REG_SZ
, (const BYTE
*)L
"Network connection", (wcslen(L
"Network connection") + 1) * sizeof(WCHAR
));
381 if (rc
!= ERROR_SUCCESS
)
383 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
386 rc
= RegSetValueExW(hConnectionKey
, L
"PnpInstanceId", 0, REG_SZ
, (const BYTE
*)InstanceId
, (wcslen(InstanceId
) + 1) * sizeof(WCHAR
));
387 if (rc
!= ERROR_SUCCESS
)
389 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
393 rc
= RegSetValueExW(hConnectionKey
, L
"ShowIcon", 0, REG_DWORD
, (const BYTE
*)&dwShowIcon
, sizeof(dwShowIcon
));
394 if (rc
!= ERROR_SUCCESS
)
396 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
400 /* Write linkage information in Tcpip service */
401 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, NULL
, &hKey
, NULL
);
402 if (rc
!= ERROR_SUCCESS
)
404 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
407 rc
= AppendStringToMultiSZ(hKey
, L
"Bind", DeviceName
);
408 if (rc
!= ERROR_SUCCESS
)
410 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
413 rc
= AppendStringToMultiSZ(hKey
, L
"Export", ExportName
);
414 if (rc
!= ERROR_SUCCESS
)
416 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
419 rc
= AppendStringToMultiSZ(hKey
, L
"Route", UuidString
);
420 if (rc
!= ERROR_SUCCESS
)
422 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
426 /* Install additionnal services */
427 /* FIXME: do it only if it is a network adapter! */
428 rc
= InstallAdditionalServices(NULL
);
429 if (rc
!= ERROR_SUCCESS
)
431 DPRINT("InstallAdditionalServices() failed with error 0x%lx\n", rc
);
435 /* HACK: hpoussin, Dec 2005. TCP/IP driver is not able to manage devices
436 * which are installed after its startup. So, we have to reboot to take
437 * this new netcard into account.
439 MessageBox(NULL
, TEXT("You need to reboot to finish the installation of your network card."), TEXT("Reboot required"), MB_OK
| MB_ICONWARNING
);
443 if (UuidRpcString
!= NULL
)
444 RpcStringFreeW(&UuidRpcString
);
445 HeapFree(GetProcessHeap(), 0, InstanceId
);
446 HeapFree(GetProcessHeap(), 0, UuidString
);
447 HeapFree(GetProcessHeap(), 0, DeviceName
);
448 HeapFree(GetProcessHeap(), 0, ExportName
);
449 if (hKey
!= INVALID_HANDLE_VALUE
)
451 if (hLinkageKey
!= INVALID_HANDLE_VALUE
)
452 RegCloseKey(hLinkageKey
);
453 if (hNetworkKey
!= INVALID_HANDLE_VALUE
)
454 RegCloseKey(hNetworkKey
);
455 if (hConnectionKey
!= INVALID_HANDLE_VALUE
)
456 RegCloseKey(hConnectionKey
);
458 if (rc
== ERROR_SUCCESS
)
459 rc
= ERROR_DI_DO_DEFAULT
;
460 DPRINT("Returning 0x%lx\n", rc
);