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