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
);
97 IN DI_FUNCTION InstallFunction
,
98 IN HDEVINFO DeviceInfoSet
,
99 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
101 RPC_STATUS RpcStatus
;
103 LPWSTR InstanceId
= NULL
;
104 LPWSTR UuidRpcString
= NULL
;
105 LPWSTR UuidString
= NULL
;
106 LPWSTR DeviceName
= NULL
;
107 LPWSTR ExportName
= NULL
;
109 DWORD dwShowIcon
, dwLength
;
110 HKEY hKey
= INVALID_HANDLE_VALUE
;
111 HKEY hLinkageKey
= INVALID_HANDLE_VALUE
;
112 HKEY hNetworkKey
= INVALID_HANDLE_VALUE
;
113 HKEY hConnectionKey
= INVALID_HANDLE_VALUE
;
115 if (InstallFunction
!= DIF_INSTALLDEVICE
)
116 return ERROR_DI_DO_DEFAULT
;
118 DPRINT("%lu %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
120 /* Get Instance ID */
121 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, NULL
, 0, &dwLength
))
123 DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
124 rc
= ERROR_GEN_FAILURE
;
127 InstanceId
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
130 DPRINT("HeapAlloc() failed\n");
131 rc
= ERROR_NOT_ENOUGH_MEMORY
;
134 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, InstanceId
, dwLength
, NULL
))
137 DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc
);
141 /* Create a new UUID */
142 RpcStatus
= UuidCreate(&Uuid
);
143 if (RpcStatus
!= RPC_S_OK
&& RpcStatus
!= RPC_S_UUID_LOCAL_ONLY
)
145 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus
);
146 rc
= ERROR_GEN_FAILURE
;
149 RpcStatus
= UuidToStringW(&Uuid
, &UuidRpcString
);
150 if (RpcStatus
!= RPC_S_OK
)
152 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus
);
153 rc
= ERROR_GEN_FAILURE
;
157 /* Add curly braces around Uuid */
158 UuidString
= HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
161 DPRINT("HeapAlloc() failed\n");
162 rc
= ERROR_NOT_ENOUGH_MEMORY
;
165 wcscpy(UuidString
, L
"{");
166 wcscat(UuidString
, UuidRpcString
);
167 wcscat(UuidString
, L
"}");
169 /* Create device name */
170 DeviceName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
173 DPRINT("HeapAlloc() failed\n");
174 rc
= ERROR_NOT_ENOUGH_MEMORY
;
177 wcscpy(DeviceName
, L
"\\Device\\");
178 wcscat(DeviceName
, UuidString
);
180 /* Create export name */
181 ExportName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\Tcpip_") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
184 DPRINT("HeapAlloc() failed\n");
185 rc
= ERROR_NOT_ENOUGH_MEMORY
;
188 wcscpy(ExportName
, L
"\\Device\\Tcpip_");
189 wcscat(ExportName
, UuidString
);
191 /* Write Tcpip parameters in new service Key */
192 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services", 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hKey
, NULL
);
193 if (rc
!= ERROR_SUCCESS
)
195 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
198 rc
= RegCreateKeyExW(hKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hNetworkKey
, NULL
);
199 if (rc
!= ERROR_SUCCESS
)
201 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
205 hKey
= INVALID_HANDLE_VALUE
;
206 rc
= RegCreateKeyExW(hNetworkKey
, L
"Parameters\\Tcpip", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hKey
, NULL
);
207 if (rc
!= ERROR_SUCCESS
)
209 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
212 RegCloseKey(hNetworkKey
);
213 hNetworkKey
= INVALID_HANDLE_VALUE
;
214 rc
= RegSetValueExW(hKey
, L
"DefaultGateway", 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 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
220 rc
= RegSetValueExW(hKey
, L
"IPAddress", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
221 if (rc
!= ERROR_SUCCESS
)
223 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
226 rc
= RegSetValueExW(hKey
, L
"SubnetMask", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
227 if (rc
!= ERROR_SUCCESS
)
229 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
233 hKey
= INVALID_HANDLE_VALUE
;
235 /* Write 'Linkage' key in hardware key */
236 #if _WIN32_WINNT >= 0x502
237 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
239 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
241 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
242 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
243 if (hKey
== INVALID_HANDLE_VALUE
)
246 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc
);
249 rc
= RegSetValueExW(hKey
, L
"NetCfgInstanceId", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
250 if (rc
!= ERROR_SUCCESS
)
252 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
255 rc
= RegCreateKeyExW(hKey
, L
"Linkage", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hLinkageKey
, NULL
);
256 if (rc
!= ERROR_SUCCESS
)
258 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
261 rc
= RegSetValueExW(hLinkageKey
, L
"Export", 0, REG_SZ
, (const BYTE
*)DeviceName
, (wcslen(DeviceName
) + 1) * sizeof(WCHAR
));
262 if (rc
!= ERROR_SUCCESS
)
264 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
267 rc
= RegSetValueExW(hLinkageKey
, L
"RootDevice", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
268 if (rc
!= ERROR_SUCCESS
)
270 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
273 rc
= RegSetValueExW(hLinkageKey
, L
"UpperBind", 0, REG_SZ
, (const BYTE
*)L
"Tcpip", (wcslen(L
"Tcpip") + 1) * sizeof(WCHAR
));
274 if (rc
!= ERROR_SUCCESS
)
276 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
280 hKey
= INVALID_HANDLE_VALUE
;
282 /* Write connection information in network subkey */
283 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
);
284 if (rc
!= ERROR_SUCCESS
)
286 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
289 rc
= RegCreateKeyExW(hNetworkKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hKey
, NULL
);
290 if (rc
!= ERROR_SUCCESS
)
292 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
295 rc
= RegCreateKeyExW(hKey
, L
"Connection", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hConnectionKey
, NULL
);
297 hKey
= INVALID_HANDLE_VALUE
;
298 if (rc
!= ERROR_SUCCESS
)
300 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
303 rc
= RegSetValueExW(hConnectionKey
, L
"Name", 0, REG_SZ
, (const BYTE
*)L
"Network connection", (wcslen(L
"Network connection") + 1) * sizeof(WCHAR
));
304 if (rc
!= ERROR_SUCCESS
)
306 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
309 rc
= RegSetValueExW(hConnectionKey
, L
"PnpInstanceId", 0, REG_SZ
, (const BYTE
*)InstanceId
, (wcslen(InstanceId
) + 1) * sizeof(WCHAR
));
310 if (rc
!= ERROR_SUCCESS
)
312 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
316 rc
= RegSetValueExW(hConnectionKey
, L
"ShowIcon", 0, REG_DWORD
, (const BYTE
*)&dwShowIcon
, sizeof(dwShowIcon
));
317 if (rc
!= ERROR_SUCCESS
)
319 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
323 /* Write linkage information in Tcpip service */
324 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
);
325 if (rc
!= ERROR_SUCCESS
)
327 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
330 rc
= AppendStringToMultiSZ(hKey
, L
"Bind", DeviceName
);
331 if (rc
!= ERROR_SUCCESS
)
333 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
336 rc
= AppendStringToMultiSZ(hKey
, L
"Export", ExportName
);
337 if (rc
!= ERROR_SUCCESS
)
339 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
342 rc
= AppendStringToMultiSZ(hKey
, L
"Route", UuidString
);
343 if (rc
!= ERROR_SUCCESS
)
345 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
352 if (UuidRpcString
!= NULL
)
353 RpcStringFreeW(&UuidRpcString
);
354 HeapFree(GetProcessHeap(), 0, InstanceId
);
355 HeapFree(GetProcessHeap(), 0, UuidString
);
356 HeapFree(GetProcessHeap(), 0, DeviceName
);
357 HeapFree(GetProcessHeap(), 0, ExportName
);
358 if (hKey
!= INVALID_HANDLE_VALUE
)
360 if (hLinkageKey
!= INVALID_HANDLE_VALUE
)
361 RegCloseKey(hLinkageKey
);
362 if (hNetworkKey
!= INVALID_HANDLE_VALUE
)
363 RegCloseKey(hNetworkKey
);
364 if (hConnectionKey
!= INVALID_HANDLE_VALUE
)
365 RegCloseKey(hConnectionKey
);
367 if (rc
== ERROR_SUCCESS
)
368 rc
= ERROR_DI_DO_DEFAULT
;
369 DPRINT("Returning 0x%lx\n", rc
);