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