ea40e5788d5cec564fdea950633e55b7b169cc85
[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 LONG rc;
108 HKEY hKey = INVALID_HANDLE_VALUE;
109 HKEY hLinkageKey = INVALID_HANDLE_VALUE;
110 HKEY hNetworkKey = INVALID_HANDLE_VALUE;
111 HKEY hConnectionKey = INVALID_HANDLE_VALUE;
112
113 if (InstallFunction != DIF_INSTALLDEVICE)
114 return ERROR_DI_DO_DEFAULT;
115
116 /* Create a new UUID */
117 RpcStatus = UuidCreate(&Uuid);
118 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
119 {
120 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
121 rc = ERROR_GEN_FAILURE;
122 goto cleanup;
123 }
124 RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
125 if (RpcStatus != RPC_S_OK)
126 {
127 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
128 rc = ERROR_GEN_FAILURE;
129 goto cleanup;
130 }
131
132 /* Add curly braces around Uuid */
133 UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
134 if (!UuidString)
135 {
136 DPRINT("HeapAlloc() failed\n");
137 rc = ERROR_NOT_ENOUGH_MEMORY;
138 goto cleanup;
139 }
140 wcscpy(UuidString, L"{");
141 wcscat(UuidString, UuidRpcString);
142 wcscat(UuidString, L"}");
143
144 /* Create device name */
145 DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
146 if (!DeviceName)
147 {
148 DPRINT("HeapAlloc() failed\n");
149 rc = ERROR_NOT_ENOUGH_MEMORY;
150 goto cleanup;
151 }
152 wcscpy(DeviceName, L"\\Device\\");
153 wcscat(DeviceName, UuidString);
154
155 /* Write Tcpip parameters in new service Key */
156 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hKey, NULL);
157 if (rc != ERROR_SUCCESS)
158 {
159 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
160 goto cleanup;
161 }
162 rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
163 if (rc != ERROR_SUCCESS)
164 {
165 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
166 goto cleanup;
167 }
168 RegCloseKey(hKey);
169 hKey = INVALID_HANDLE_VALUE;
170 rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
171 if (rc != ERROR_SUCCESS)
172 {
173 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
174 goto cleanup;
175 }
176 RegCloseKey(hNetworkKey);
177 hNetworkKey = INVALID_HANDLE_VALUE;
178 rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
179 if (rc != ERROR_SUCCESS)
180 {
181 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
182 goto cleanup;
183 }
184 rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
185 if (rc != ERROR_SUCCESS)
186 {
187 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
188 goto cleanup;
189 }
190 rc = RegSetValueExW(hKey, L"SubnetMask", 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 RegCloseKey(hKey);
197 hKey = INVALID_HANDLE_VALUE;
198
199 /* Write 'Linkage' key in hardware key */
200 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
201 if (hKey == INVALID_HANDLE_VALUE)
202 {
203 rc = GetLastError();
204 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
205 goto cleanup;
206 }
207 rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
208 if (rc != ERROR_SUCCESS)
209 {
210 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
211 goto cleanup;
212 }
213 rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
214 if (rc != ERROR_SUCCESS)
215 {
216 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
217 goto cleanup;
218 }
219 rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 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 = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
226 if (rc != ERROR_SUCCESS)
227 {
228 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
229 goto cleanup;
230 }
231 rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
232 if (rc != ERROR_SUCCESS)
233 {
234 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
235 goto cleanup;
236 }
237 RegCloseKey(hKey);
238 hKey = INVALID_HANDLE_VALUE;
239
240 /* Write connection information in network subkey */
241 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);
242 if (rc != ERROR_SUCCESS)
243 {
244 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
245 goto cleanup;
246 }
247 rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
248 if (rc != ERROR_SUCCESS)
249 {
250 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
251 goto cleanup;
252 }
253 rc = RegSetValueExW(hKey, L"Name", 0, REG_SZ, (const BYTE*)L"Network connection", (wcslen(L"Network connection") + 1) * sizeof(WCHAR));
254 if (rc != ERROR_SUCCESS)
255 {
256 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
257 goto cleanup;
258 }
259 RegCloseKey(hKey);
260 hKey = INVALID_HANDLE_VALUE;
261
262 /* Write linkage information in Tcpip service */
263 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);
264 if (rc != ERROR_SUCCESS)
265 {
266 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
267 goto cleanup;
268 }
269 rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
270 if (rc != ERROR_SUCCESS)
271 goto cleanup;
272 rc = AppendStringToMultiSZ(hKey, L"Export", DeviceName);
273 if (rc != ERROR_SUCCESS)
274 goto cleanup;
275 rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
276 if (rc != ERROR_SUCCESS)
277 goto cleanup;
278
279 rc = ERROR_DI_DO_DEFAULT;
280
281 cleanup:
282 if (UuidRpcString != NULL)
283 RpcStringFreeW(&UuidRpcString);
284 if (UuidString != NULL)
285 HeapFree(GetProcessHeap(), 0, UuidString);
286 if (DeviceName != NULL)
287 HeapFree(GetProcessHeap(), 0, DeviceName);
288 if (hKey != INVALID_HANDLE_VALUE)
289 RegCloseKey(hKey);
290 if (hLinkageKey != INVALID_HANDLE_VALUE)
291 RegCloseKey(hLinkageKey);
292 if (hNetworkKey != INVALID_HANDLE_VALUE)
293 RegCloseKey(hNetworkKey);
294 if (hConnectionKey != INVALID_HANDLE_VALUE)
295 RegCloseKey(hConnectionKey);
296
297 return rc == ERROR_SUCCESS ? ERROR_DI_DO_DEFAULT : rc;
298 }