xref: /reactos/dll/win32/netcfgx/netcfgx.c (revision 595b846d)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Configuration of network devices
4  * FILE:            dll/win32/netcfgx/netcfgx.c
5  * PURPOSE:         Network devices installer
6  *
7  * PROGRAMMERS:     Herv� Poussineau (hpoussin@reactos.org)
8  */
9 
10 #include "precomp.h"
11 
12 #include <olectl.h>
13 
14 #define NTOS_MODE_USER
15 #include <ndk/iofuncs.h>
16 #include <ndk/rtlfuncs.h>
17 
18 #define NDEBUG
19 #include <debug.h>
20 
21 HINSTANCE netcfgx_hInstance;
22 const GUID CLSID_TcpipConfigNotifyObject      = {0xA907657F, 0x6FDF, 0x11D0, {0x8E, 0xFB, 0x00, 0xC0, 0x4F, 0xD9, 0x12, 0xB2}};
23 
24 static INTERFACE_TABLE InterfaceTable[] =
25 {
26     {
27         &CLSID_CNetCfg,
28         INetCfg_Constructor
29     },
30     {
31         &CLSID_TcpipConfigNotifyObject,
32         TcpipConfigNotify_Constructor
33     },
34     {
35         NULL,
36         NULL
37     }
38 };
39 
40 BOOL
41 WINAPI
42 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
43 {
44     switch (fdwReason)
45     {
46         case DLL_PROCESS_ATTACH:
47             netcfgx_hInstance = hinstDLL;
48             DisableThreadLibraryCalls(netcfgx_hInstance);
49             InitCommonControls();
50             break;
51     default:
52         break;
53     }
54 
55     return TRUE;
56 }
57 
58 HRESULT
59 WINAPI
60 DllCanUnloadNow(void)
61 {
62     return S_FALSE;
63 }
64 
65 STDAPI
66 DllRegisterServer(void)
67 {
68     HKEY hKey, hSubKey;
69     LPOLESTR pStr;
70     WCHAR szName[MAX_PATH] = L"CLSID\\";
71 
72     if (FAILED(StringFromCLSID(&CLSID_CNetCfg, &pStr)))
73         return SELFREG_E_CLASS;
74 
75     wcscpy(&szName[6], pStr);
76     CoTaskMemFree(pStr);
77 
78     if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szName, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
79         return SELFREG_E_CLASS;
80 
81     if (RegCreateKeyExW(hKey, L"InProcServer32", 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
82     {
83         if (!GetModuleFileNameW(netcfgx_hInstance, szName, sizeof(szName)/sizeof(WCHAR)))
84         {
85             RegCloseKey(hSubKey);
86             RegCloseKey(hKey);
87             return SELFREG_E_CLASS;
88         }
89         szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
90         RegSetValueW(hSubKey, NULL, REG_SZ, szName, (wcslen(szName)+1) * sizeof(WCHAR));
91         RegSetValueExW(hSubKey, L"ThreadingModel", 0, REG_SZ, (LPBYTE)L"Both", 10);
92         RegCloseKey(hSubKey);
93     }
94 
95     RegCloseKey(hKey);
96     return S_OK;
97 }
98 
99 STDAPI
100 DllUnregisterServer(void)
101 {
102     //FIXME
103     // implement unregistering services
104     //
105     return S_OK;
106 }
107 
108 STDAPI
109 DllGetClassObject(
110     REFCLSID rclsid,
111     REFIID riid,
112     LPVOID* ppv)
113 {
114     UINT i;
115     HRESULT hres = E_OUTOFMEMORY;
116     IClassFactory * pcf = NULL;
117 
118     if (!ppv)
119         return E_INVALIDARG;
120 
121     *ppv = NULL;
122 
123     for (i = 0; InterfaceTable[i].riid; i++)
124     {
125         if (IsEqualIID(InterfaceTable[i].riid, rclsid))
126         {
127             pcf = IClassFactory_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
128             break;
129         }
130     }
131 
132     if (!pcf)
133     {
134         return CLASS_E_CLASSNOTAVAILABLE;
135     }
136 
137     hres = IClassFactory_QueryInterface(pcf, riid, ppv);
138     IClassFactory_Release(pcf);
139 
140     return hres;
141 }
142 
143 
144 /* Append a REG_SZ to an existing REG_MULTI_SZ string in the registry.
145  * If the value doesn't exist, create it.
146  * Returns ERROR_SUCCESS if success. Otherwise, returns an error code
147  */
148 static
149 LONG
150 AppendStringToMultiSZ(
151     IN HKEY hKey,
152     IN PCWSTR ValueName,
153     IN PCWSTR ValueToAppend)
154 {
155     PWSTR Buffer = NULL;
156     DWORD dwRegType;
157     DWORD dwRequired, dwLength;
158     DWORD dwTmp;
159     LONG rc;
160 
161     rc = RegQueryValueExW(hKey,
162                           ValueName,
163                           NULL,
164                           &dwRegType,
165                           NULL,
166                           &dwRequired);
167     if (rc != ERROR_FILE_NOT_FOUND)
168     {
169         if (rc != ERROR_SUCCESS)
170             goto cleanup;
171         if (dwRegType != REG_MULTI_SZ)
172         {
173             rc = ERROR_GEN_FAILURE;
174             goto cleanup;
175         }
176 
177         dwTmp = dwLength = dwRequired + wcslen(ValueToAppend) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
178         Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
179         if (!Buffer)
180         {
181             rc = ERROR_NOT_ENOUGH_MEMORY;
182             goto cleanup;
183         }
184 
185         rc = RegQueryValueExW(hKey,
186                               ValueName,
187                               NULL,
188                               NULL,
189                               (BYTE*)Buffer,
190                               &dwTmp);
191         if (rc != ERROR_SUCCESS)
192             goto cleanup;
193     }
194     else
195     {
196         dwRequired = sizeof(WCHAR);
197         dwLength = wcslen(ValueToAppend) * sizeof(WCHAR) + 2 * sizeof(UNICODE_NULL);
198         Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
199         if (!Buffer)
200         {
201             rc = ERROR_NOT_ENOUGH_MEMORY;
202             goto cleanup;
203         }
204     }
205 
206     /* Append the value */
207     wcscpy(&Buffer[dwRequired / sizeof(WCHAR) - 1], ValueToAppend);
208     /* Terminate the REG_MULTI_SZ string */
209     Buffer[dwLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
210 
211     rc = RegSetValueExW(hKey,
212                         ValueName,
213                         0,
214                         REG_MULTI_SZ,
215                         (const BYTE*)Buffer,
216                         dwLength);
217 
218 cleanup:
219     HeapFree(GetProcessHeap(), 0, Buffer);
220     return rc;
221 }
222 
223 
224 static
225 DWORD
226 InstallNetDevice(
227     IN HDEVINFO DeviceInfoSet,
228     IN PSP_DEVINFO_DATA DeviceInfoData,
229     LPCWSTR UuidString,
230     DWORD Characteristics,
231     LPCWSTR BusType)
232 {
233     LPWSTR InstanceId = NULL;
234     LPWSTR DeviceName = NULL;
235     LPWSTR ExportName = NULL;
236     LONG rc;
237     HKEY hKey = NULL;
238     HKEY hNetworkKey = NULL;
239     HKEY hLinkageKey = NULL;
240     HKEY hConnectionKey = NULL;
241     DWORD dwShowIcon, dwLength, dwValue;
242     WCHAR szBuffer[300];
243 
244     /* Get Instance ID */
245     if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
246     {
247         DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
248         rc = ERROR_GEN_FAILURE;
249         goto cleanup;
250     }
251 
252     InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
253     if (!InstanceId)
254     {
255         DPRINT("HeapAlloc() failed\n");
256         rc = ERROR_NOT_ENOUGH_MEMORY;
257         goto cleanup;
258     }
259 
260     if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, InstanceId, dwLength, NULL))
261     {
262         rc = GetLastError();
263         DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc);
264         goto cleanup;
265     }
266 
267     /* Create device name */
268     DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
269     if (!DeviceName)
270     {
271         DPRINT("HeapAlloc() failed\n");
272         rc = ERROR_NOT_ENOUGH_MEMORY;
273         goto cleanup;
274     }
275     wcscpy(DeviceName, L"\\Device\\");
276     wcscat(DeviceName, UuidString);
277 
278     /* Create export name */
279     ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
280     if (!ExportName)
281     {
282         DPRINT("HeapAlloc() failed\n");
283         rc = ERROR_NOT_ENOUGH_MEMORY;
284         goto cleanup;
285     }
286     wcscpy(ExportName, L"\\Device\\Tcpip_");
287     wcscat(ExportName, UuidString);
288 
289     /* Write Tcpip parameters in new service Key */
290     rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
291     if (rc != ERROR_SUCCESS)
292     {
293         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
294         goto cleanup;
295     }
296 
297     rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hNetworkKey, NULL);
298     if (rc != ERROR_SUCCESS)
299     {
300         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
301         goto cleanup;
302     }
303     RegCloseKey(hKey);
304     hKey = NULL;
305 
306     rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
307     if (rc != ERROR_SUCCESS)
308     {
309         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
310         goto cleanup;
311     }
312     RegCloseKey(hNetworkKey);
313     hNetworkKey = NULL;
314 
315     rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
316     if (rc != ERROR_SUCCESS)
317     {
318         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
319         goto cleanup;
320     }
321 
322     rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
323     if (rc != ERROR_SUCCESS)
324     {
325         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
326         goto cleanup;
327     }
328 
329     rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
330     if (rc != ERROR_SUCCESS)
331     {
332         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
333         goto cleanup;
334     }
335 
336     dwValue = 1;
337     rc = RegSetValueExW(hKey, L"EnableDHCP", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
338     if (rc != ERROR_SUCCESS)
339     {
340         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
341         goto cleanup;
342     }
343     RegCloseKey(hKey);
344     hKey = NULL;
345 
346     /* Write 'Linkage' key in hardware key */
347 #if _WIN32_WINNT >= 0x502
348     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
349 #else
350     hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
351 #endif
352     if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
353         hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
354     if (hKey == INVALID_HANDLE_VALUE)
355     {
356         hKey = NULL;
357         rc = GetLastError();
358         DPRINT1("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
359         goto cleanup;
360     }
361 
362     rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
363     if (rc != ERROR_SUCCESS)
364     {
365         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
366         goto cleanup;
367     }
368 
369     rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
370     if (rc != ERROR_SUCCESS)
371     {
372         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
373         goto cleanup;
374     }
375 
376     if (BusType)
377     {
378         rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
379         if (rc != ERROR_SUCCESS)
380         {
381             DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
382             goto cleanup;
383         }
384     }
385 
386     rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
387     if (rc != ERROR_SUCCESS)
388     {
389         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
390         goto cleanup;
391     }
392 
393     rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
394     if (rc != ERROR_SUCCESS)
395     {
396         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
397         goto cleanup;
398     }
399 
400     rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
401     if (rc != ERROR_SUCCESS)
402     {
403         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
404         goto cleanup;
405     }
406 
407     rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
408     if (rc != ERROR_SUCCESS)
409     {
410         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
411         goto cleanup;
412     }
413     RegCloseKey(hKey);
414     hKey = NULL;
415 
416     /* Write connection information in network subkey */
417     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);
418     if (rc != ERROR_SUCCESS)
419     {
420         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
421         goto cleanup;
422     }
423 
424     rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
425     if (rc != ERROR_SUCCESS)
426     {
427         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
428         goto cleanup;
429     }
430 
431     rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
432     RegCloseKey(hKey);
433     hKey = NULL;
434     if (rc != ERROR_SUCCESS)
435     {
436         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
437         goto cleanup;
438     }
439 
440     if (!LoadStringW(netcfgx_hInstance, IDS_NET_CONNECT, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
441     {
442         wcscpy(szBuffer, L"Network Connection");
443     }
444 
445     rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
446     if (rc != ERROR_SUCCESS)
447     {
448         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
449         goto cleanup;
450     }
451 
452     rc = RegSetValueExW(hConnectionKey, L"PnpInstanceId", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
453     if (rc != ERROR_SUCCESS)
454     {
455         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
456         goto cleanup;
457     }
458 
459     dwShowIcon = 1;
460     rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
461     if (rc != ERROR_SUCCESS)
462     {
463         DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
464         goto cleanup;
465     }
466 
467     /* Write linkage information in Tcpip service */
468     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);
469     if (rc != ERROR_SUCCESS)
470     {
471         DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
472         goto cleanup;
473     }
474     rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
475     if (rc != ERROR_SUCCESS)
476     {
477         DPRINT1("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
478         goto cleanup;
479     }
480     rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
481     if (rc != ERROR_SUCCESS)
482     {
483         DPRINT1("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
484         goto cleanup;
485     }
486     rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
487     if (rc != ERROR_SUCCESS)
488     {
489         DPRINT1("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
490         goto cleanup;
491     }
492 
493     rc = ERROR_SUCCESS;
494 
495 cleanup:
496     HeapFree(GetProcessHeap(), 0, InstanceId);
497     HeapFree(GetProcessHeap(), 0, DeviceName);
498     HeapFree(GetProcessHeap(), 0, ExportName);
499     if (hKey != NULL)
500         RegCloseKey(hKey);
501     if (hNetworkKey != NULL)
502         RegCloseKey(hNetworkKey);
503     if (hLinkageKey != NULL)
504         RegCloseKey(hLinkageKey);
505     if (hConnectionKey != NULL)
506         RegCloseKey(hConnectionKey);
507     return rc;
508 }
509 
510 static
511 DWORD
512 InstallNetClient(VOID)
513 {
514     DPRINT1("Installation of network clients is not yet supported\n");
515     return ERROR_GEN_FAILURE;
516 }
517 
518 static
519 DWORD
520 InstallNetService(VOID)
521 {
522     DPRINT1("Installation of network services is not yet supported\n");
523     return ERROR_GEN_FAILURE;
524 }
525 
526 static
527 DWORD
528 InstallNetTransport(VOID)
529 {
530     DPRINT1("Installation of network protocols is not yet supported\n");
531     return ERROR_GEN_FAILURE;
532 }
533 
534 DWORD
535 WINAPI
536 NetClassInstaller(
537     IN DI_FUNCTION InstallFunction,
538     IN HDEVINFO DeviceInfoSet,
539     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
540 {
541     SP_DRVINFO_DATA_W DriverInfoData;
542     SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
543     WCHAR SectionName[LINE_LEN];
544     HINF hInf = INVALID_HANDLE_VALUE;
545     INFCONTEXT InfContext;
546     UINT ErrorLine;
547     INT CharacteristicsInt;
548     DWORD Characteristics;
549     LPWSTR BusType = NULL;
550     RPC_STATUS RpcStatus;
551     UUID Uuid;
552     LPWSTR UuidRpcString = NULL;
553     LPWSTR UuidString = NULL;
554     LONG rc;
555     DWORD dwLength;
556 
557     if (InstallFunction != DIF_INSTALLDEVICE)
558         return ERROR_DI_DO_DEFAULT;
559 
560     DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
561 
562     /* Get driver info details */
563     DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
564     if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
565     {
566         rc = GetLastError();
567         DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
568         goto cleanup;
569     }
570 
571     DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
572     if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
573      && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
574     {
575         rc = GetLastError();
576         DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
577         goto cleanup;
578     }
579 
580     hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
581     if (hInf == INVALID_HANDLE_VALUE)
582     {
583         rc = GetLastError();
584         DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
585         goto cleanup;
586     }
587 
588     if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
589     {
590         rc = GetLastError();
591         DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
592         goto cleanup;
593     }
594 
595     /* Get Characteristics and BusType (optional) from .inf file */
596     if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
597     {
598         rc = GetLastError();
599         DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
600             L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
601         goto cleanup;
602     }
603 
604     if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
605     {
606         rc = GetLastError();
607         DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc);
608         goto cleanup;
609     }
610 
611     Characteristics = (DWORD)CharacteristicsInt;
612     if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
613     {
614         if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
615         {
616             if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
617             {
618                 rc = GetLastError();
619                 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
620                 goto cleanup;
621             }
622 
623             BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
624             if (!BusType)
625             {
626                 DPRINT("HeapAlloc() failed\n");
627                 rc = ERROR_NOT_ENOUGH_MEMORY;
628                 goto cleanup;
629             }
630 
631             if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
632             {
633                 rc = GetLastError();
634                 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
635                 goto cleanup;
636             }
637         }
638     }
639 
640     /* Create a new UUID */
641     RpcStatus = UuidCreate(&Uuid);
642     if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
643     {
644         DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
645         rc = ERROR_GEN_FAILURE;
646         goto cleanup;
647     }
648 
649     RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
650     if (RpcStatus != RPC_S_OK)
651     {
652         DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
653         rc = ERROR_GEN_FAILURE;
654         goto cleanup;
655     }
656 
657     /* Add curly braces around Uuid */
658     UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
659     if (!UuidString)
660     {
661         DPRINT("HeapAlloc() failed\n");
662         rc = ERROR_NOT_ENOUGH_MEMORY;
663         goto cleanup;
664     }
665 
666     wcscpy(UuidString, L"{");
667     wcscat(UuidString, UuidRpcString);
668     wcscat(UuidString, L"}");
669 
670     if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
671         rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
672     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
673         rc = InstallNetClient();
674     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
675         rc = InstallNetService();
676     else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
677         rc = InstallNetTransport();
678     else
679     {
680         DPRINT("Invalid class guid\n");
681         rc = ERROR_GEN_FAILURE;
682     }
683 
684 cleanup:
685     if (hInf != INVALID_HANDLE_VALUE)
686         SetupCloseInfFile(hInf);
687     if (UuidRpcString != NULL)
688         RpcStringFreeW(&UuidRpcString);
689     HeapFree(GetProcessHeap(), 0, BusType);
690     HeapFree(GetProcessHeap(), 0, UuidString);
691 
692     if (rc == ERROR_SUCCESS)
693         rc = ERROR_DI_DO_DEFAULT;
694     DPRINT("Returning 0x%lx\n", rc);
695     return rc;
696 }
697