xref: /reactos/dll/win32/netcfgx/installer.c (revision f7cab5a1)
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     SP_DEVINSTALL_PARAMS_W DeviceInstallParams;
103     LPWSTR InstanceId = NULL;
104     LPWSTR ComponentId = NULL;
105     LPWSTR DeviceName = NULL;
106     LPWSTR ExportName = NULL;
107     LONG rc;
108     HKEY hKey = NULL;
109     HKEY hNetworkKey = NULL;
110     HKEY hLinkageKey = NULL;
111     HKEY hConnectionKey = NULL;
112     DWORD dwShowIcon, dwLength, dwValue;
113     WCHAR szBuffer[300];
114     PWSTR ptr;
115 
116     DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
117     if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet,
118                                         DeviceInfoData,
119                                         &DeviceInstallParams))
120     {
121         rc = GetLastError();
122         ERR("SetupDiGetDeviceInstallParamsW() failed (Error %lu)\n", rc);
123         goto cleanup;
124     }
125 
126     /* Do not start the adapter in the call to SetupDiInstallDevice */
127     DeviceInstallParams.Flags |= DI_DONOTCALLCONFIGMG;
128 
129     if (!SetupDiSetDeviceInstallParamsW(DeviceInfoSet,
130                                         DeviceInfoData,
131                                         &DeviceInstallParams))
132     {
133         rc = GetLastError();
134         ERR("SetupDiSetDeviceInstallParamsW() failed (Error %lu)\n", rc);
135         goto cleanup;
136     }
137 
138     /* Install the adapter */
139     if (!SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData))
140     {
141         rc = GetLastError();
142         ERR("SetupDiInstallDevice() failed (Error %lu)\n", rc);
143         goto cleanup;
144     }
145 
146     /* Get Instance ID */
147     if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
148     {
149         ERR("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
150         rc = ERROR_GEN_FAILURE;
151         goto cleanup;
152     }
153 
154     InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
155     if (!InstanceId)
156     {
157         ERR("HeapAlloc() failed\n");
158         rc = ERROR_NOT_ENOUGH_MEMORY;
159         goto cleanup;
160     }
161 
162     if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, InstanceId, dwLength, NULL))
163     {
164         rc = GetLastError();
165         ERR("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc);
166         goto cleanup;
167     }
168 
169     ComponentId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
170     if (!ComponentId)
171     {
172         ERR("HeapAlloc() failed\n");
173         rc = ERROR_NOT_ENOUGH_MEMORY;
174         goto cleanup;
175     }
176 
177     wcscpy(ComponentId, InstanceId);
178     ptr = wcsrchr(ComponentId, L'\\');
179     if (ptr != NULL)
180         *ptr = UNICODE_NULL;
181 
182     /* Create device name */
183     DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
184     if (!DeviceName)
185     {
186         ERR("HeapAlloc() failed\n");
187         rc = ERROR_NOT_ENOUGH_MEMORY;
188         goto cleanup;
189     }
190     wcscpy(DeviceName, L"\\Device\\");
191     wcscat(DeviceName, UuidString);
192 
193     /* Create export name */
194     ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
195     if (!ExportName)
196     {
197         ERR("HeapAlloc() failed\n");
198         rc = ERROR_NOT_ENOUGH_MEMORY;
199         goto cleanup;
200     }
201     wcscpy(ExportName, L"\\Device\\Tcpip_");
202     wcscat(ExportName, UuidString);
203 
204     /* Write Tcpip parameters in new service Key */
205     rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
206     if (rc != ERROR_SUCCESS)
207     {
208         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
209         goto cleanup;
210     }
211 
212     rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hNetworkKey, NULL);
213     if (rc != ERROR_SUCCESS)
214     {
215         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
216         goto cleanup;
217     }
218     RegCloseKey(hKey);
219     hKey = NULL;
220 
221     rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
222     if (rc != ERROR_SUCCESS)
223     {
224         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
225         goto cleanup;
226     }
227     RegCloseKey(hNetworkKey);
228     hNetworkKey = NULL;
229 
230     rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
231     if (rc != ERROR_SUCCESS)
232     {
233         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
234         goto cleanup;
235     }
236 
237     rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
238     if (rc != ERROR_SUCCESS)
239     {
240         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
241         goto cleanup;
242     }
243 
244     rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
245     if (rc != ERROR_SUCCESS)
246     {
247         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
248         goto cleanup;
249     }
250 
251     dwValue = 1;
252     rc = RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
253     if (rc != ERROR_SUCCESS)
254     {
255         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
256         goto cleanup;
257     }
258     RegCloseKey(hKey);
259     hKey = NULL;
260 
261     /* Write 'Linkage' key in hardware key */
262 #if _WIN32_WINNT >= 0x502
263     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
264 #else
265     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
266 #endif
267     if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
268         hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
269     if (hKey == INVALID_HANDLE_VALUE)
270     {
271         hKey = NULL;
272         rc = GetLastError();
273         ERR("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
274         goto cleanup;
275     }
276 
277     rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 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(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
285     if (rc != ERROR_SUCCESS)
286     {
287         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
288         goto cleanup;
289     }
290 
291     rc = RegSetValueExW(hKey, L"ComponentId", 0, REG_SZ, (const BYTE*)ComponentId, (wcslen(ComponentId) + 1) * sizeof(WCHAR));
292     if (rc != ERROR_SUCCESS)
293     {
294         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
295         goto cleanup;
296     }
297 
298     if (BusType)
299     {
300         rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
301         if (rc != ERROR_SUCCESS)
302         {
303             ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
304             goto cleanup;
305         }
306     }
307 
308     rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
309     if (rc != ERROR_SUCCESS)
310     {
311         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
312         goto cleanup;
313     }
314 
315     rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
316     if (rc != ERROR_SUCCESS)
317     {
318         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
319         goto cleanup;
320     }
321 
322     rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 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(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
330     if (rc != ERROR_SUCCESS)
331     {
332         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
333         goto cleanup;
334     }
335     RegCloseKey(hKey);
336     hKey = NULL;
337 
338     /* Write connection information in network subkey */
339     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);
340     if (rc != ERROR_SUCCESS)
341     {
342         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
343         goto cleanup;
344     }
345 
346     rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
347     if (rc != ERROR_SUCCESS)
348     {
349         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
350         goto cleanup;
351     }
352 
353     rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
354     RegCloseKey(hKey);
355     hKey = NULL;
356     if (rc != ERROR_SUCCESS)
357     {
358         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
359         goto cleanup;
360     }
361 
362     if (!LoadStringW(netcfgx_hInstance, IDS_NET_CONNECT, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
363     {
364         wcscpy(szBuffer, L"Network Connection");
365     }
366 
367     rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
368     if (rc != ERROR_SUCCESS)
369     {
370         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
371         goto cleanup;
372     }
373 
374     rc = RegSetValueExW(hConnectionKey, L"PnpInstanceID", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
375     if (rc != ERROR_SUCCESS)
376     {
377         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
378         goto cleanup;
379     }
380 
381     dwShowIcon = 1;
382     rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
383     if (rc != ERROR_SUCCESS)
384     {
385         ERR("RegSetValueExW() failed with error 0x%lx\n", rc);
386         goto cleanup;
387     }
388 
389     /* Write linkage information in Tcpip service */
390     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);
391     if (rc != ERROR_SUCCESS)
392     {
393         ERR("RegCreateKeyExW() failed with error 0x%lx\n", rc);
394         goto cleanup;
395     }
396     rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
397     if (rc != ERROR_SUCCESS)
398     {
399         ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
400         goto cleanup;
401     }
402     rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
403     if (rc != ERROR_SUCCESS)
404     {
405         ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
406         goto cleanup;
407     }
408     rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
409     if (rc != ERROR_SUCCESS)
410     {
411         ERR("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
412         goto cleanup;
413     }
414 
415     /* Start the device */
416     if (!SetupDiRestartDevices(DeviceInfoSet, DeviceInfoData))
417     {
418         rc = GetLastError();
419         ERR("SetupDiRestartDevices() failed with error 0x%lx\n", rc);
420         goto cleanup;
421     }
422 
423     rc = ERROR_SUCCESS;
424 
425 cleanup:
426     HeapFree(GetProcessHeap(), 0, InstanceId);
427     HeapFree(GetProcessHeap(), 0, ComponentId);
428     HeapFree(GetProcessHeap(), 0, DeviceName);
429     HeapFree(GetProcessHeap(), 0, ExportName);
430     if (hKey != NULL)
431         RegCloseKey(hKey);
432     if (hNetworkKey != NULL)
433         RegCloseKey(hNetworkKey);
434     if (hLinkageKey != NULL)
435         RegCloseKey(hLinkageKey);
436     if (hConnectionKey != NULL)
437         RegCloseKey(hConnectionKey);
438 
439     return rc;
440 }
441 
442 static
443 DWORD
444 InstallNetClient(VOID)
445 {
446     FIXME("Installation of network clients is not yet supported\n");
447     return ERROR_GEN_FAILURE;
448 }
449 
450 static
451 DWORD
452 InstallNetService(VOID)
453 {
454     FIXME("Installation of network services is not yet supported\n");
455     return ERROR_GEN_FAILURE;
456 }
457 
458 static
459 DWORD
460 InstallNetTransport(VOID)
461 {
462     FIXME("Installation of network protocols is not yet supported\n");
463     return ERROR_GEN_FAILURE;
464 }
465 
466 DWORD
467 WINAPI
468 NetClassInstaller(
469     IN DI_FUNCTION InstallFunction,
470     IN HDEVINFO DeviceInfoSet,
471     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
472 {
473     SP_DRVINFO_DATA_W DriverInfoData;
474     SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
475     WCHAR SectionName[LINE_LEN];
476     HINF hInf = INVALID_HANDLE_VALUE;
477     INFCONTEXT InfContext;
478     UINT ErrorLine;
479     INT CharacteristicsInt;
480     DWORD Characteristics;
481     LPWSTR BusType = NULL;
482     RPC_STATUS RpcStatus;
483     UUID Uuid;
484     LPWSTR UuidRpcString = NULL;
485     LPWSTR UuidString = NULL;
486     LONG rc;
487     DWORD dwLength;
488 
489     if (InstallFunction != DIF_INSTALLDEVICE)
490         return ERROR_DI_DO_DEFAULT;
491 
492     TRACE("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
493 
494     /* Get driver info details */
495     DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
496     if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
497     {
498         rc = GetLastError();
499         ERR("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
500         goto cleanup;
501     }
502 
503     DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
504     if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
505      && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
506     {
507         rc = GetLastError();
508         ERR("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
509         goto cleanup;
510     }
511 
512     hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
513     if (hInf == INVALID_HANDLE_VALUE)
514     {
515         rc = GetLastError();
516         ERR("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
517         goto cleanup;
518     }
519 
520     if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
521     {
522         rc = GetLastError();
523         ERR("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
524         goto cleanup;
525     }
526 
527     /* Get Characteristics and BusType (optional) from .inf file */
528     if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
529     {
530         rc = GetLastError();
531         ERR("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
532             L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
533         goto cleanup;
534     }
535 
536     if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
537     {
538         rc = GetLastError();
539         ERR("SetupGetIntField() failed with error 0x%lx\n", rc);
540         goto cleanup;
541     }
542 
543     Characteristics = (DWORD)CharacteristicsInt;
544     if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
545     {
546         if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
547         {
548             if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
549             {
550                 rc = GetLastError();
551                 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
552                 goto cleanup;
553             }
554 
555             BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
556             if (!BusType)
557             {
558                 ERR("HeapAlloc() failed\n");
559                 rc = ERROR_NOT_ENOUGH_MEMORY;
560                 goto cleanup;
561             }
562 
563             if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
564             {
565                 rc = GetLastError();
566                 ERR("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
567                 goto cleanup;
568             }
569         }
570     }
571 
572     /* Create a new UUID */
573     RpcStatus = UuidCreate(&Uuid);
574     if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
575     {
576         ERR("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
577         rc = ERROR_GEN_FAILURE;
578         goto cleanup;
579     }
580 
581     RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
582     if (RpcStatus != RPC_S_OK)
583     {
584         ERR("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
585         rc = ERROR_GEN_FAILURE;
586         goto cleanup;
587     }
588 
589     /* Add curly braces around Uuid */
590     UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
591     if (!UuidString)
592     {
593         ERR("HeapAlloc() failed\n");
594         rc = ERROR_NOT_ENOUGH_MEMORY;
595         goto cleanup;
596     }
597 
598     wcscpy(UuidString, L"{");
599     wcscat(UuidString, UuidRpcString);
600     wcscat(UuidString, L"}");
601 
602     if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
603         rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
604     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
605         rc = InstallNetClient();
606     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
607         rc = InstallNetService();
608     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
609         rc = InstallNetTransport();
610     else
611     {
612         ERR("Invalid class guid\n");
613         rc = ERROR_GEN_FAILURE;
614     }
615 
616 cleanup:
617     if (hInf != INVALID_HANDLE_VALUE)
618         SetupCloseInfFile(hInf);
619     if (UuidRpcString != NULL)
620         RpcStringFreeW(&UuidRpcString);
621     HeapFree(GetProcessHeap(), 0, BusType);
622     HeapFree(GetProcessHeap(), 0, UuidString);
623 
624     TRACE("Returning 0x%lx\n", rc);
625     return rc;
626 }
627