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