Merge PR #283 "[USBPORT] Transaction Translator (TT) support bringup"
[reactos.git] / dll / win32 / netcfgx / netcfgx.c
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 }