2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/win32/netcfgx/installer.c
5 * PURPOSE: Network devices installer
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
13 /* Append a REG_SZ to an existing REG_MULTI_SZ string in the registry.
14 * If the value doesn't exist, create it.
15 * Returns ERROR_SUCCESS if success. Otherwise, returns an error code
19 AppendStringToMultiSZ(
22 IN PCWSTR ValueToAppend
)
26 DWORD dwRequired
, dwLength
;
30 rc
= RegQueryValueExW(hKey
,
36 if (rc
!= ERROR_FILE_NOT_FOUND
)
38 if (rc
!= ERROR_SUCCESS
)
40 if (dwRegType
!= REG_MULTI_SZ
)
42 rc
= ERROR_GEN_FAILURE
;
46 dwTmp
= dwLength
= dwRequired
+ wcslen(ValueToAppend
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
47 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
50 rc
= ERROR_NOT_ENOUGH_MEMORY
;
54 rc
= RegQueryValueExW(hKey
,
60 if (rc
!= ERROR_SUCCESS
)
65 dwRequired
= sizeof(WCHAR
);
66 dwLength
= wcslen(ValueToAppend
) * sizeof(WCHAR
) + 2 * sizeof(UNICODE_NULL
);
67 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
70 rc
= ERROR_NOT_ENOUGH_MEMORY
;
75 /* Append the value */
76 wcscpy(&Buffer
[dwRequired
/ sizeof(WCHAR
) - 1], ValueToAppend
);
77 /* Terminate the REG_MULTI_SZ string */
78 Buffer
[dwLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
80 rc
= RegSetValueExW(hKey
,
88 HeapFree(GetProcessHeap(), 0, Buffer
);
96 IN HDEVINFO DeviceInfoSet
,
97 IN PSP_DEVINFO_DATA DeviceInfoData
,
99 DWORD Characteristics
,
102 LPWSTR InstanceId
= NULL
;
103 LPWSTR ComponentId
= NULL
;
104 LPWSTR DeviceName
= NULL
;
105 LPWSTR ExportName
= NULL
;
108 HKEY hNetworkKey
= NULL
;
109 HKEY hLinkageKey
= NULL
;
110 HKEY hConnectionKey
= NULL
;
111 DWORD dwShowIcon
, dwLength
, dwValue
;
115 /* Install the adapter */
116 if (!SetupDiInstallDevice(DeviceInfoSet
, DeviceInfoData
))
119 ERR("SetupDiInstallDevice() failed (Error %lu)\n", rc
);
123 /* Get Instance ID */
124 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, NULL
, 0, &dwLength
))
126 ERR("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
127 rc
= ERROR_GEN_FAILURE
;
131 InstanceId
= HeapAlloc(GetProcessHeap(), 0, dwLength
* sizeof(WCHAR
));
134 ERR("HeapAlloc() failed\n");
135 rc
= ERROR_NOT_ENOUGH_MEMORY
;
139 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, InstanceId
, dwLength
, NULL
))
142 ERR("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc
);
146 ComponentId
= HeapAlloc(GetProcessHeap(), 0, dwLength
* sizeof(WCHAR
));
149 ERR("HeapAlloc() failed\n");
150 rc
= ERROR_NOT_ENOUGH_MEMORY
;
154 wcscpy(ComponentId
, InstanceId
);
155 ptr
= wcsrchr(ComponentId
, L
'\\');
159 /* Create device name */
160 DeviceName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
163 ERR("HeapAlloc() failed\n");
164 rc
= ERROR_NOT_ENOUGH_MEMORY
;
167 wcscpy(DeviceName
, L
"\\Device\\");
168 wcscat(DeviceName
, UuidString
);
170 /* Create export name */
171 ExportName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\Tcpip_") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
174 ERR("HeapAlloc() failed\n");
175 rc
= ERROR_NOT_ENOUGH_MEMORY
;
178 wcscpy(ExportName
, L
"\\Device\\Tcpip_");
179 wcscat(ExportName
, UuidString
);
181 /* Write Tcpip parameters in new service Key */
182 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hKey
, NULL
);
183 if (rc
!= ERROR_SUCCESS
)
185 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
189 rc
= RegCreateKeyExW(hKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hNetworkKey
, NULL
);
190 if (rc
!= ERROR_SUCCESS
)
192 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
198 rc
= RegCreateKeyExW(hNetworkKey
, L
"Parameters\\Tcpip", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hKey
, NULL
);
199 if (rc
!= ERROR_SUCCESS
)
201 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
204 RegCloseKey(hNetworkKey
);
207 rc
= RegSetValueExW(hKey
, L
"DefaultGateway", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
208 if (rc
!= ERROR_SUCCESS
)
210 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
214 rc
= RegSetValueExW(hKey
, L
"IPAddress", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
215 if (rc
!= ERROR_SUCCESS
)
217 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
221 rc
= RegSetValueExW(hKey
, L
"SubnetMask", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
222 if (rc
!= ERROR_SUCCESS
)
224 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
229 rc
= RegSetValueExW(hKey
, L
"EnableDHCP", 0, REG_DWORD
, (const BYTE
*)&dwValue
, sizeof(DWORD
));
230 if (rc
!= ERROR_SUCCESS
)
232 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
238 /* Write 'Linkage' key in hardware key */
239 #if _WIN32_WINNT >= 0x502
240 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
242 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
244 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
245 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
246 if (hKey
== INVALID_HANDLE_VALUE
)
250 ERR("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc
);
254 rc
= RegSetValueExW(hKey
, L
"NetCfgInstanceId", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
255 if (rc
!= ERROR_SUCCESS
)
257 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
261 rc
= RegSetValueExW(hKey
, L
"Characteristics", 0, REG_DWORD
, (const BYTE
*)&Characteristics
, sizeof(DWORD
));
262 if (rc
!= ERROR_SUCCESS
)
264 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
268 rc
= RegSetValueExW(hKey
, L
"ComponentId", 0, REG_SZ
, (const BYTE
*)ComponentId
, (wcslen(ComponentId
) + 1) * sizeof(WCHAR
));
269 if (rc
!= ERROR_SUCCESS
)
271 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
277 rc
= RegSetValueExW(hKey
, L
"BusType", 0, REG_SZ
, (const BYTE
*)BusType
, (wcslen(BusType
) + 1) * sizeof(WCHAR
));
278 if (rc
!= ERROR_SUCCESS
)
280 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
285 rc
= RegCreateKeyExW(hKey
, L
"Linkage", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hLinkageKey
, NULL
);
286 if (rc
!= ERROR_SUCCESS
)
288 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
292 rc
= RegSetValueExW(hLinkageKey
, L
"Export", 0, REG_SZ
, (const BYTE
*)DeviceName
, (wcslen(DeviceName
) + 1) * sizeof(WCHAR
));
293 if (rc
!= ERROR_SUCCESS
)
295 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
299 rc
= RegSetValueExW(hLinkageKey
, L
"RootDevice", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
300 if (rc
!= ERROR_SUCCESS
)
302 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
306 rc
= RegSetValueExW(hLinkageKey
, L
"UpperBind", 0, REG_SZ
, (const BYTE
*)L
"Tcpip", (wcslen(L
"Tcpip") + 1) * sizeof(WCHAR
));
307 if (rc
!= ERROR_SUCCESS
)
309 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
315 /* Write connection information in network subkey */
316 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hNetworkKey
, NULL
);
317 if (rc
!= ERROR_SUCCESS
)
319 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
323 rc
= RegCreateKeyExW(hNetworkKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hKey
, NULL
);
324 if (rc
!= ERROR_SUCCESS
)
326 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
330 rc
= RegCreateKeyExW(hKey
, L
"Connection", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hConnectionKey
, NULL
);
333 if (rc
!= ERROR_SUCCESS
)
335 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
339 if (!LoadStringW(netcfgx_hInstance
, IDS_NET_CONNECT
, szBuffer
, sizeof(szBuffer
)/sizeof(WCHAR
)))
341 wcscpy(szBuffer
, L
"Network Connection");
344 rc
= RegSetValueExW(hConnectionKey
, L
"Name", 0, REG_SZ
, (const BYTE
*)szBuffer
, (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
345 if (rc
!= ERROR_SUCCESS
)
347 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
351 rc
= RegSetValueExW(hConnectionKey
, L
"PnpInstanceID", 0, REG_SZ
, (const BYTE
*)InstanceId
, (wcslen(InstanceId
) + 1) * sizeof(WCHAR
));
352 if (rc
!= ERROR_SUCCESS
)
354 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
359 rc
= RegSetValueExW(hConnectionKey
, L
"ShowIcon", 0, REG_DWORD
, (const BYTE
*)&dwShowIcon
, sizeof(dwShowIcon
));
360 if (rc
!= ERROR_SUCCESS
)
362 ERR("RegSetValueExW() failed with error 0x%lx\n", rc
);
366 /* Write linkage information in Tcpip service */
367 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
);
368 if (rc
!= ERROR_SUCCESS
)
370 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
373 rc
= AppendStringToMultiSZ(hKey
, L
"Bind", DeviceName
);
374 if (rc
!= ERROR_SUCCESS
)
376 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
379 rc
= AppendStringToMultiSZ(hKey
, L
"Export", ExportName
);
380 if (rc
!= ERROR_SUCCESS
)
382 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
385 rc
= AppendStringToMultiSZ(hKey
, L
"Route", UuidString
);
386 if (rc
!= ERROR_SUCCESS
)
388 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
395 HeapFree(GetProcessHeap(), 0, InstanceId
);
396 HeapFree(GetProcessHeap(), 0, ComponentId
);
397 HeapFree(GetProcessHeap(), 0, DeviceName
);
398 HeapFree(GetProcessHeap(), 0, ExportName
);
401 if (hNetworkKey
!= NULL
)
402 RegCloseKey(hNetworkKey
);
403 if (hLinkageKey
!= NULL
)
404 RegCloseKey(hLinkageKey
);
405 if (hConnectionKey
!= NULL
)
406 RegCloseKey(hConnectionKey
);
413 InstallNetClient(VOID
)
415 FIXME("Installation of network clients is not yet supported\n");
416 return ERROR_GEN_FAILURE
;
421 InstallNetService(VOID
)
423 FIXME("Installation of network services is not yet supported\n");
424 return ERROR_GEN_FAILURE
;
429 InstallNetTransport(VOID
)
431 FIXME("Installation of network protocols is not yet supported\n");
432 return ERROR_GEN_FAILURE
;
438 IN DI_FUNCTION InstallFunction
,
439 IN HDEVINFO DeviceInfoSet
,
440 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
442 SP_DRVINFO_DATA_W DriverInfoData
;
443 SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail
;
444 WCHAR SectionName
[LINE_LEN
];
445 HINF hInf
= INVALID_HANDLE_VALUE
;
446 INFCONTEXT InfContext
;
448 INT CharacteristicsInt
;
449 DWORD Characteristics
;
450 LPWSTR BusType
= NULL
;
451 RPC_STATUS RpcStatus
;
453 LPWSTR UuidRpcString
= NULL
;
454 LPWSTR UuidString
= NULL
;
458 if (InstallFunction
!= DIF_INSTALLDEVICE
)
459 return ERROR_DI_DO_DEFAULT
;
461 TRACE("%lu %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
463 /* Get driver info details */
464 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
465 if (!SetupDiGetSelectedDriverW(DeviceInfoSet
, DeviceInfoData
, &DriverInfoData
))
468 ERR("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc
);
472 DriverInfoDetail
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
473 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet
, DeviceInfoData
, &DriverInfoData
, &DriverInfoDetail
, sizeof(DriverInfoDetail
), NULL
)
474 && GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
477 ERR("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc
);
481 hInf
= SetupOpenInfFileW(DriverInfoDetail
.InfFileName
, NULL
, INF_STYLE_WIN4
, &ErrorLine
);
482 if (hInf
== INVALID_HANDLE_VALUE
)
485 ERR("SetupOpenInfFileW() failed with error 0x%lx\n", rc
);
489 if (!SetupDiGetActualSectionToInstallW(hInf
, DriverInfoDetail
.SectionName
, SectionName
, LINE_LEN
, NULL
, NULL
))
492 ERR("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc
);
496 /* Get Characteristics and BusType (optional) from .inf file */
497 if (!SetupFindFirstLineW(hInf
, SectionName
, L
"Characteristics", &InfContext
))
500 ERR("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
501 L
"Characteristics", SectionName
, DriverInfoDetail
.InfFileName
, rc
);
505 if (!SetupGetIntField(&InfContext
, 1, &CharacteristicsInt
))
508 ERR("SetupGetIntField() failed with error 0x%lx\n", rc
);
512 Characteristics
= (DWORD
)CharacteristicsInt
;
513 if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NET
))
515 if (SetupFindFirstLineW(hInf
, SectionName
, L
"BusType", &InfContext
))
517 if (!SetupGetStringFieldW(&InfContext
, 1, NULL
, 0, &dwLength
))
520 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc
);
524 BusType
= HeapAlloc(GetProcessHeap(), 0, dwLength
* sizeof(WCHAR
));
527 ERR("HeapAlloc() failed\n");
528 rc
= ERROR_NOT_ENOUGH_MEMORY
;
532 if (!SetupGetStringFieldW(&InfContext
, 1, BusType
, dwLength
, NULL
))
535 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc
);
541 /* Create a new UUID */
542 RpcStatus
= UuidCreate(&Uuid
);
543 if (RpcStatus
!= RPC_S_OK
&& RpcStatus
!= RPC_S_UUID_LOCAL_ONLY
)
545 ERR("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus
);
546 rc
= ERROR_GEN_FAILURE
;
550 RpcStatus
= UuidToStringW(&Uuid
, &UuidRpcString
);
551 if (RpcStatus
!= RPC_S_OK
)
553 ERR("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus
);
554 rc
= ERROR_GEN_FAILURE
;
558 /* Add curly braces around Uuid */
559 UuidString
= HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
562 ERR("HeapAlloc() failed\n");
563 rc
= ERROR_NOT_ENOUGH_MEMORY
;
567 wcscpy(UuidString
, L
"{");
568 wcscat(UuidString
, UuidRpcString
);
569 wcscat(UuidString
, L
"}");
571 if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NET
))
572 rc
= InstallNetDevice(DeviceInfoSet
, DeviceInfoData
, UuidString
, Characteristics
, BusType
);
573 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETCLIENT
))
574 rc
= InstallNetClient();
575 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETSERVICE
))
576 rc
= InstallNetService();
577 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETTRANS
))
578 rc
= InstallNetTransport();
581 ERR("Invalid class guid\n");
582 rc
= ERROR_GEN_FAILURE
;
586 if (hInf
!= INVALID_HANDLE_VALUE
)
587 SetupCloseInfFile(hInf
);
588 if (UuidRpcString
!= NULL
)
589 RpcStringFreeW(&UuidRpcString
);
590 HeapFree(GetProcessHeap(), 0, BusType
);
591 HeapFree(GetProcessHeap(), 0, UuidString
);
593 TRACE("Returning 0x%lx\n", rc
);