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