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