Fix the HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\Export value. The GUID...
[reactos.git] / reactos / lib / netcfgx / netcfgx.c
1 /*
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
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 //#define NDEBUG
11 #include <debug.h>
12
13 #include "netcfgx.h"
14
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
18 */
19 static LONG
20 AppendStringToMultiSZ(
21 IN HKEY hKey,
22 IN PCWSTR ValueName,
23 IN PCWSTR ValueToAppend)
24
25 {
26 PWSTR Buffer = NULL;
27 DWORD dwRegType;
28 DWORD dwRequired, dwLength;
29 DWORD dwTmp;
30 LONG rc;
31
32 rc = RegQueryValueExW(
33 hKey,
34 ValueName,
35 NULL,
36 &dwRegType,
37 NULL,
38 &dwRequired);
39 if (rc != ERROR_FILE_NOT_FOUND)
40 {
41 if (rc != ERROR_SUCCESS)
42 goto cleanup;
43 if (dwRegType != REG_MULTI_SZ)
44 {
45 rc = ERROR_GEN_FAILURE;
46 goto cleanup;
47 }
48
49 dwTmp = dwLength = dwRequired + wcslen(ValueToAppend) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
50 Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
51 if (!Buffer)
52 {
53 rc = ERROR_NOT_ENOUGH_MEMORY;
54 goto cleanup;
55 }
56 rc = RegQueryValueExW(
57 hKey,
58 ValueName,
59 NULL,
60 NULL,
61 (BYTE*)Buffer,
62 &dwTmp);
63 if (rc != ERROR_SUCCESS)
64 goto cleanup;
65 }
66 else
67 {
68 dwRequired = sizeof(WCHAR);
69 dwLength = wcslen(ValueToAppend) * sizeof(WCHAR) + 2 * sizeof(UNICODE_NULL);
70 Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
71 if (!Buffer)
72 {
73 rc = ERROR_NOT_ENOUGH_MEMORY;
74 goto cleanup;
75 }
76 }
77
78 /* Append the value */
79 wcscpy(&Buffer[dwRequired / sizeof(WCHAR) - 1], ValueToAppend);
80 /* Terminate the REG_MULTI_SZ string */
81 Buffer[dwLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
82
83 rc = RegSetValueExW(
84 hKey,
85 ValueName,
86 0,
87 REG_MULTI_SZ,
88 (const BYTE*)Buffer,
89 dwLength);
90
91 cleanup:
92 HeapFree(GetProcessHeap(), 0, Buffer);
93 return rc;
94 }
95
96 DWORD WINAPI
97 NetClassInstaller(
98 IN DI_FUNCTION InstallFunction,
99 IN HDEVINFO DeviceInfoSet,
100 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
101 {
102 RPC_STATUS RpcStatus;
103 UUID Uuid;
104 LPWSTR UuidRpcString = NULL;
105 LPWSTR UuidString = NULL;
106 LPWSTR DeviceName = NULL;
107 LPWSTR ExportName = NULL;
108 LONG rc;
109 HKEY hKey = INVALID_HANDLE_VALUE;
110 HKEY hLinkageKey = INVALID_HANDLE_VALUE;
111 HKEY hNetworkKey = INVALID_HANDLE_VALUE;
112 HKEY hConnectionKey = INVALID_HANDLE_VALUE;
113
114 if (InstallFunction != DIF_INSTALLDEVICE)
115 return ERROR_DI_DO_DEFAULT;
116
117 /* Create a new UUID */
118 RpcStatus = UuidCreate(&Uuid);
119 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
120 {
121 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
122 rc = ERROR_GEN_FAILURE;
123 goto cleanup;
124 }
125 RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
126 if (RpcStatus != RPC_S_OK)
127 {
128 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
129 rc = ERROR_GEN_FAILURE;
130 goto cleanup;
131 }
132
133 /* Add curly braces around Uuid */
134 UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
135 if (!UuidString)
136 {
137 DPRINT("HeapAlloc() failed\n");
138 rc = ERROR_NOT_ENOUGH_MEMORY;
139 goto cleanup;
140 }
141 wcscpy(UuidString, L"{");
142 wcscat(UuidString, UuidRpcString);
143 wcscat(UuidString, L"}");
144
145 /* Create device name */
146 DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
147 if (!DeviceName)
148 {
149 DPRINT("HeapAlloc() failed\n");
150 rc = ERROR_NOT_ENOUGH_MEMORY;
151 goto cleanup;
152 }
153 wcscpy(DeviceName, L"\\Device\\");
154 wcscat(DeviceName, UuidString);
155
156 /* Create export name */
157 ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
158 if (!ExportName)
159 {
160 DPRINT("HeapAlloc() failed\n");
161 rc = ERROR_NOT_ENOUGH_MEMORY;
162 goto cleanup;
163 }
164 wcscpy(ExportName, L"\\Device\\Tcpip_");
165 wcscat(ExportName, UuidString);
166
167 /* Write Tcpip parameters in new service Key */
168 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hKey, NULL);
169 if (rc != ERROR_SUCCESS)
170 {
171 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
172 goto cleanup;
173 }
174 rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
175 if (rc != ERROR_SUCCESS)
176 {
177 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
178 goto cleanup;
179 }
180 RegCloseKey(hKey);
181 hKey = INVALID_HANDLE_VALUE;
182 rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
183 if (rc != ERROR_SUCCESS)
184 {
185 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
186 goto cleanup;
187 }
188 RegCloseKey(hNetworkKey);
189 hNetworkKey = INVALID_HANDLE_VALUE;
190 rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
191 if (rc != ERROR_SUCCESS)
192 {
193 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
194 goto cleanup;
195 }
196 rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
197 if (rc != ERROR_SUCCESS)
198 {
199 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
200 goto cleanup;
201 }
202 rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
203 if (rc != ERROR_SUCCESS)
204 {
205 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
206 goto cleanup;
207 }
208 RegCloseKey(hKey);
209 hKey = INVALID_HANDLE_VALUE;
210
211 /* Write 'Linkage' key in hardware key */
212 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
213 if (hKey == INVALID_HANDLE_VALUE)
214 {
215 rc = GetLastError();
216 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
217 goto cleanup;
218 }
219 rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
220 if (rc != ERROR_SUCCESS)
221 {
222 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
223 goto cleanup;
224 }
225 rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
226 if (rc != ERROR_SUCCESS)
227 {
228 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
229 goto cleanup;
230 }
231 rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
232 if (rc != ERROR_SUCCESS)
233 {
234 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
235 goto cleanup;
236 }
237 rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
238 if (rc != ERROR_SUCCESS)
239 {
240 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
241 goto cleanup;
242 }
243 rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
244 if (rc != ERROR_SUCCESS)
245 {
246 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
247 goto cleanup;
248 }
249 RegCloseKey(hKey);
250 hKey = INVALID_HANDLE_VALUE;
251
252 /* Write connection information in network subkey */
253 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);
254 if (rc != ERROR_SUCCESS)
255 {
256 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
257 goto cleanup;
258 }
259 rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
260 if (rc != ERROR_SUCCESS)
261 {
262 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
263 goto cleanup;
264 }
265 rc = RegSetValueExW(hKey, L"Name", 0, REG_SZ, (const BYTE*)L"Network connection", (wcslen(L"Network connection") + 1) * sizeof(WCHAR));
266 if (rc != ERROR_SUCCESS)
267 {
268 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
269 goto cleanup;
270 }
271 RegCloseKey(hKey);
272 hKey = INVALID_HANDLE_VALUE;
273
274 /* Write linkage information in Tcpip service */
275 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);
276 if (rc != ERROR_SUCCESS)
277 {
278 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
279 goto cleanup;
280 }
281 rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
282 if (rc != ERROR_SUCCESS)
283 goto cleanup;
284 rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
285 if (rc != ERROR_SUCCESS)
286 goto cleanup;
287 rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
288 if (rc != ERROR_SUCCESS)
289 goto cleanup;
290
291 rc = ERROR_SUCCESS;
292
293 cleanup:
294 if (UuidRpcString != NULL)
295 RpcStringFreeW(&UuidRpcString);
296 HeapFree(GetProcessHeap(), 0, UuidString);
297 HeapFree(GetProcessHeap(), 0, DeviceName);
298 HeapFree(GetProcessHeap(), 0, ExportName);
299 if (hKey != INVALID_HANDLE_VALUE)
300 RegCloseKey(hKey);
301 if (hLinkageKey != INVALID_HANDLE_VALUE)
302 RegCloseKey(hLinkageKey);
303 if (hNetworkKey != INVALID_HANDLE_VALUE)
304 RegCloseKey(hNetworkKey);
305 if (hConnectionKey != INVALID_HANDLE_VALUE)
306 RegCloseKey(hConnectionKey);
307
308 return rc == ERROR_SUCCESS ? ERROR_DI_DO_DEFAULT : rc;
309 }