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