1607bb247bbb47cc9e2c446d849633309b5712b8
[reactos.git] / dll / win32 / netcfgx / installer.c
1 /*
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
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "precomp.h"
11
12
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
16 */
17 static
18 LONG
19 AppendStringToMultiSZ(
20 IN HKEY hKey,
21 IN PCWSTR ValueName,
22 IN PCWSTR ValueToAppend)
23 {
24 PWSTR Buffer = NULL;
25 DWORD dwRegType;
26 DWORD dwRequired, dwLength;
27 DWORD dwTmp;
28 LONG rc;
29
30 rc = RegQueryValueExW(hKey,
31 ValueName,
32 NULL,
33 &dwRegType,
34 NULL,
35 &dwRequired);
36 if (rc != ERROR_FILE_NOT_FOUND)
37 {
38 if (rc != ERROR_SUCCESS)
39 goto cleanup;
40 if (dwRegType != REG_MULTI_SZ)
41 {
42 rc = ERROR_GEN_FAILURE;
43 goto cleanup;
44 }
45
46 dwTmp = dwLength = dwRequired + wcslen(ValueToAppend) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
47 Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
48 if (!Buffer)
49 {
50 rc = ERROR_NOT_ENOUGH_MEMORY;
51 goto cleanup;
52 }
53
54 rc = RegQueryValueExW(hKey,
55 ValueName,
56 NULL,
57 NULL,
58 (BYTE*)Buffer,
59 &dwTmp);
60 if (rc != ERROR_SUCCESS)
61 goto cleanup;
62 }
63 else
64 {
65 dwRequired = sizeof(WCHAR);
66 dwLength = wcslen(ValueToAppend) * sizeof(WCHAR) + 2 * sizeof(UNICODE_NULL);
67 Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
68 if (!Buffer)
69 {
70 rc = ERROR_NOT_ENOUGH_MEMORY;
71 goto cleanup;
72 }
73 }
74
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;
79
80 rc = RegSetValueExW(hKey,
81 ValueName,
82 0,
83 REG_MULTI_SZ,
84 (const BYTE*)Buffer,
85 dwLength);
86
87 cleanup:
88 HeapFree(GetProcessHeap(), 0, Buffer);
89 return rc;
90 }
91
92
93 static
94 DWORD
95 InstallNetDevice(
96 IN HDEVINFO DeviceInfoSet,
97 IN PSP_DEVINFO_DATA DeviceInfoData,
98 LPCWSTR UuidString,
99 DWORD Characteristics,
100 LPCWSTR BusType)
101 {
102 LPWSTR InstanceId = NULL;
103 LPWSTR DeviceName = NULL;
104 LPWSTR ExportName = NULL;
105 LONG rc;
106 HKEY hKey = NULL;
107 HKEY hNetworkKey = NULL;
108 HKEY hLinkageKey = NULL;
109 HKEY hConnectionKey = NULL;
110 DWORD dwShowIcon, dwLength, dwValue;
111 WCHAR szBuffer[300];
112
113 /* Install the adapter */
114 if (!SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData))
115 {
116 rc = GetLastError();
117 ERR("SetupDiInstallDevice() failed (Error %lu)\n", rc);
118 goto cleanup;
119 }
120
121 /* Get Instance ID */
122 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
123 {
124 ERR("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
125 rc = ERROR_GEN_FAILURE;
126 goto cleanup;
127 }
128
129 InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
130 if (!InstanceId)
131 {
132 ERR("HeapAlloc() failed\n");
133 rc = ERROR_NOT_ENOUGH_MEMORY;
134 goto cleanup;
135 }
136
137 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, InstanceId, dwLength, NULL))
138 {
139 rc = GetLastError();
140 ERR("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc);
141 goto cleanup;
142 }
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 ERR("HeapAlloc() failed\n");
149 rc = ERROR_NOT_ENOUGH_MEMORY;
150 goto cleanup;
151 }
152 wcscpy(DeviceName, L"\\Device\\");
153 wcscat(DeviceName, UuidString);
154
155 /* Create export name */
156 ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
157 if (!ExportName)
158 {
159 ERR("HeapAlloc() failed\n");
160 rc = ERROR_NOT_ENOUGH_MEMORY;
161 goto cleanup;
162 }
163 wcscpy(ExportName, L"\\Device\\Tcpip_");
164 wcscat(ExportName, UuidString);
165
166 /* Write Tcpip parameters in new service Key */
167 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
168 if (rc != ERROR_SUCCESS)
169 {
170 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
171 goto cleanup;
172 }
173
174 rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hNetworkKey, NULL);
175 if (rc != ERROR_SUCCESS)
176 {
177 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
178 goto cleanup;
179 }
180 RegCloseKey(hKey);
181 hKey = NULL;
182
183 rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
184 if (rc != ERROR_SUCCESS)
185 {
186 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
187 goto cleanup;
188 }
189 RegCloseKey(hNetworkKey);
190 hNetworkKey = NULL;
191
192 rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
193 if (rc != ERROR_SUCCESS)
194 {
195 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
196 goto cleanup;
197 }
198
199 rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
200 if (rc != ERROR_SUCCESS)
201 {
202 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
203 goto cleanup;
204 }
205
206 rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
207 if (rc != ERROR_SUCCESS)
208 {
209 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
210 goto cleanup;
211 }
212
213 dwValue = 1;
214 rc = RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
215 if (rc != ERROR_SUCCESS)
216 {
217 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
218 goto cleanup;
219 }
220 RegCloseKey(hKey);
221 hKey = NULL;
222
223 /* Write 'Linkage' key in hardware key */
224 #if _WIN32_WINNT >= 0x502
225 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
226 #else
227 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
228 #endif
229 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
230 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
231 if (hKey == INVALID_HANDLE_VALUE)
232 {
233 hKey = NULL;
234 rc = GetLastError();
235 ERR("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
236 goto cleanup;
237 }
238
239 rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
240 if (rc != ERROR_SUCCESS)
241 {
242 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
243 goto cleanup;
244 }
245
246 rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
247 if (rc != ERROR_SUCCESS)
248 {
249 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
250 goto cleanup;
251 }
252
253 if (BusType)
254 {
255 rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
256 if (rc != ERROR_SUCCESS)
257 {
258 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
259 goto cleanup;
260 }
261 }
262
263 rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
264 if (rc != ERROR_SUCCESS)
265 {
266 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
267 goto cleanup;
268 }
269
270 rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
271 if (rc != ERROR_SUCCESS)
272 {
273 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
274 goto cleanup;
275 }
276
277 rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
278 if (rc != ERROR_SUCCESS)
279 {
280 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
281 goto cleanup;
282 }
283
284 rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
285 if (rc != ERROR_SUCCESS)
286 {
287 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
288 goto cleanup;
289 }
290 RegCloseKey(hKey);
291 hKey = NULL;
292
293 /* Write connection information in network subkey */
294 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);
295 if (rc != ERROR_SUCCESS)
296 {
297 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
298 goto cleanup;
299 }
300
301 rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
302 if (rc != ERROR_SUCCESS)
303 {
304 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
305 goto cleanup;
306 }
307
308 rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
309 RegCloseKey(hKey);
310 hKey = NULL;
311 if (rc != ERROR_SUCCESS)
312 {
313 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
314 goto cleanup;
315 }
316
317 if (!LoadStringW(netcfgx_hInstance, IDS_NET_CONNECT, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
318 {
319 wcscpy(szBuffer, L"Network Connection");
320 }
321
322 rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
323 if (rc != ERROR_SUCCESS)
324 {
325 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
326 goto cleanup;
327 }
328
329 rc = RegSetValueExW(hConnectionKey, L"PnpInstanceId", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
330 if (rc != ERROR_SUCCESS)
331 {
332 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
333 goto cleanup;
334 }
335
336 dwShowIcon = 1;
337 rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
338 if (rc != ERROR_SUCCESS)
339 {
340 ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
341 goto cleanup;
342 }
343
344 /* Write linkage information in Tcpip service */
345 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);
346 if (rc != ERROR_SUCCESS)
347 {
348 ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
349 goto cleanup;
350 }
351 rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
352 if (rc != ERROR_SUCCESS)
353 {
354 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
355 goto cleanup;
356 }
357 rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
358 if (rc != ERROR_SUCCESS)
359 {
360 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
361 goto cleanup;
362 }
363 rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
364 if (rc != ERROR_SUCCESS)
365 {
366 ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
367 goto cleanup;
368 }
369
370 rc = ERROR_SUCCESS;
371
372 cleanup:
373 HeapFree(GetProcessHeap(), 0, InstanceId);
374 HeapFree(GetProcessHeap(), 0, DeviceName);
375 HeapFree(GetProcessHeap(), 0, ExportName);
376 if (hKey != NULL)
377 RegCloseKey(hKey);
378 if (hNetworkKey != NULL)
379 RegCloseKey(hNetworkKey);
380 if (hLinkageKey != NULL)
381 RegCloseKey(hLinkageKey);
382 if (hConnectionKey != NULL)
383 RegCloseKey(hConnectionKey);
384
385 return rc;
386 }
387
388 static
389 DWORD
390 InstallNetClient(VOID)
391 {
392 FIXME("Installation of network clients is not yet supported\n");
393 return ERROR_GEN_FAILURE;
394 }
395
396 static
397 DWORD
398 InstallNetService(VOID)
399 {
400 FIXME("Installation of network services is not yet supported\n");
401 return ERROR_GEN_FAILURE;
402 }
403
404 static
405 DWORD
406 InstallNetTransport(VOID)
407 {
408 FIXME("Installation of network protocols is not yet supported\n");
409 return ERROR_GEN_FAILURE;
410 }
411
412 DWORD
413 WINAPI
414 NetClassInstaller(
415 IN DI_FUNCTION InstallFunction,
416 IN HDEVINFO DeviceInfoSet,
417 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
418 {
419 SP_DRVINFO_DATA_W DriverInfoData;
420 SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
421 WCHAR SectionName[LINE_LEN];
422 HINF hInf = INVALID_HANDLE_VALUE;
423 INFCONTEXT InfContext;
424 UINT ErrorLine;
425 INT CharacteristicsInt;
426 DWORD Characteristics;
427 LPWSTR BusType = NULL;
428 RPC_STATUS RpcStatus;
429 UUID Uuid;
430 LPWSTR UuidRpcString = NULL;
431 LPWSTR UuidString = NULL;
432 LONG rc;
433 DWORD dwLength;
434
435 if (InstallFunction != DIF_INSTALLDEVICE)
436 return ERROR_DI_DO_DEFAULT;
437
438 TRACE("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
439
440 /* Get driver info details */
441 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
442 if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
443 {
444 rc = GetLastError();
445 ERR("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
446 goto cleanup;
447 }
448
449 DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
450 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
451 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
452 {
453 rc = GetLastError();
454 ERR("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
455 goto cleanup;
456 }
457
458 hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
459 if (hInf == INVALID_HANDLE_VALUE)
460 {
461 rc = GetLastError();
462 ERR("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
463 goto cleanup;
464 }
465
466 if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
467 {
468 rc = GetLastError();
469 ERR("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
470 goto cleanup;
471 }
472
473 /* Get Characteristics and BusType (optional) from .inf file */
474 if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
475 {
476 rc = GetLastError();
477 ERR("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
478 L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
479 goto cleanup;
480 }
481
482 if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
483 {
484 rc = GetLastError();
485 ERR("SetupGetIntField() failed with error 0x%lx\n", rc);
486 goto cleanup;
487 }
488
489 Characteristics = (DWORD)CharacteristicsInt;
490 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
491 {
492 if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
493 {
494 if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
495 {
496 rc = GetLastError();
497 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
498 goto cleanup;
499 }
500
501 BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
502 if (!BusType)
503 {
504 ERR("HeapAlloc() failed\n");
505 rc = ERROR_NOT_ENOUGH_MEMORY;
506 goto cleanup;
507 }
508
509 if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
510 {
511 rc = GetLastError();
512 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
513 goto cleanup;
514 }
515 }
516 }
517
518 /* Create a new UUID */
519 RpcStatus = UuidCreate(&Uuid);
520 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
521 {
522 ERR("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
523 rc = ERROR_GEN_FAILURE;
524 goto cleanup;
525 }
526
527 RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
528 if (RpcStatus != RPC_S_OK)
529 {
530 ERR("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
531 rc = ERROR_GEN_FAILURE;
532 goto cleanup;
533 }
534
535 /* Add curly braces around Uuid */
536 UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
537 if (!UuidString)
538 {
539 ERR("HeapAlloc() failed\n");
540 rc = ERROR_NOT_ENOUGH_MEMORY;
541 goto cleanup;
542 }
543
544 wcscpy(UuidString, L"{");
545 wcscat(UuidString, UuidRpcString);
546 wcscat(UuidString, L"}");
547
548 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
549 rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
550 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
551 rc = InstallNetClient();
552 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
553 rc = InstallNetService();
554 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
555 rc = InstallNetTransport();
556 else
557 {
558 ERR("Invalid class guid\n");
559 rc = ERROR_GEN_FAILURE;
560 }
561
562 cleanup:
563 if (hInf != INVALID_HANDLE_VALUE)
564 SetupCloseInfFile(hInf);
565 if (UuidRpcString != NULL)
566 RpcStringFreeW(&UuidRpcString);
567 HeapFree(GetProcessHeap(), 0, BusType);
568 HeapFree(GetProcessHeap(), 0, UuidString);
569
570 TRACE("Returning 0x%lx\n", rc);
571 return rc;
572 }