[NETCFGX]
[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 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 UNICODE_STRING TcpipServicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip");
294
295 /* Install TCP/IP protocol */
296 ret = InstallInfSection(
297 hWnd,
298 L"nettcpip.inf",
299 L"MS_TCPIP.PrimaryInstall",
300 L"MS_TCPIP.PrimaryInstall.Services");
301 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND)
302 {
303 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
304 return GetLastError();
305 }
306 else if (ret)
307 {
308 /* Start the TCP/IP driver */
309 ret = NtLoadDriver(&TcpipServicePath);
310 if (ret)
311 {
312 /* This isn't really fatal but we want to warn anyway */
313 DPRINT1("NtLoadDriver(TCPIP) failed with NTSTATUS 0x%lx\n", (NTSTATUS)ret);
314 }
315 }
316
317
318 /* You can add here more clients (SMB...) and services (DHCP server...) */
319
320 return ERROR_SUCCESS;
321 }
322
323 static DWORD
324 InstallNetDevice(
325 IN HDEVINFO DeviceInfoSet,
326 IN PSP_DEVINFO_DATA DeviceInfoData,
327 LPCWSTR UuidString,
328 DWORD Characteristics,
329 LPCWSTR BusType)
330 {
331 LPWSTR InstanceId = NULL;
332 LPWSTR DeviceName = NULL;
333 LPWSTR ExportName = NULL;
334 LONG rc;
335 HKEY hKey = NULL;
336 HKEY hNetworkKey = NULL;
337 HKEY hLinkageKey = NULL;
338 HKEY hConnectionKey = NULL;
339 DWORD dwShowIcon, dwLength, dwValue;
340
341 /* Get Instance ID */
342 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, NULL, 0, &dwLength))
343 {
344 DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
345 rc = ERROR_GEN_FAILURE;
346 goto cleanup;
347 }
348 InstanceId = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
349 if (!InstanceId)
350 {
351 DPRINT("HeapAlloc() failed\n");
352 rc = ERROR_NOT_ENOUGH_MEMORY;
353 goto cleanup;
354 }
355 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData, InstanceId, dwLength, NULL))
356 {
357 rc = GetLastError();
358 DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc);
359 goto cleanup;
360 }
361
362 /* Create device name */
363 DeviceName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
364 if (!DeviceName)
365 {
366 DPRINT("HeapAlloc() failed\n");
367 rc = ERROR_NOT_ENOUGH_MEMORY;
368 goto cleanup;
369 }
370 wcscpy(DeviceName, L"\\Device\\");
371 wcscat(DeviceName, UuidString);
372
373 /* Create export name */
374 ExportName = HeapAlloc(GetProcessHeap(), 0, (wcslen(L"\\Device\\Tcpip_") + wcslen(UuidString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
375 if (!ExportName)
376 {
377 DPRINT("HeapAlloc() failed\n");
378 rc = ERROR_NOT_ENOUGH_MEMORY;
379 goto cleanup;
380 }
381 wcscpy(ExportName, L"\\Device\\Tcpip_");
382 wcscat(ExportName, UuidString);
383
384 /* Write Tcpip parameters in new service Key */
385 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services", 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hKey, NULL);
386 if (rc != ERROR_SUCCESS)
387 {
388 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
389 goto cleanup;
390 }
391 rc = RegCreateKeyExW(hKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, 0, NULL, &hNetworkKey, NULL);
392 if (rc != ERROR_SUCCESS)
393 {
394 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
395 goto cleanup;
396 }
397 RegCloseKey(hKey);
398 hKey = NULL;
399 rc = RegCreateKeyExW(hNetworkKey, L"Parameters\\Tcpip", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
400 if (rc != ERROR_SUCCESS)
401 {
402 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
403 goto cleanup;
404 }
405 RegCloseKey(hNetworkKey);
406 hNetworkKey = NULL;
407 rc = RegSetValueExW(hKey, L"DefaultGateway", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
408 if (rc != ERROR_SUCCESS)
409 {
410 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
411 goto cleanup;
412 }
413 rc = RegSetValueExW(hKey, L"IPAddress", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
414 if (rc != ERROR_SUCCESS)
415 {
416 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
417 goto cleanup;
418 }
419 rc = RegSetValueExW(hKey, L"SubnetMask", 0, REG_SZ, (const BYTE*)L"0.0.0.0", (wcslen(L"0.0.0.0") + 1) * sizeof(WCHAR));
420 if (rc != ERROR_SUCCESS)
421 {
422 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
423 goto cleanup;
424 }
425 dwValue = 1;
426 rc = RegSetValueExW(hKey, L"DhcpEnabled", 0, REG_DWORD, (const BYTE*)&dwValue, sizeof(DWORD));
427 if (rc != ERROR_SUCCESS)
428 {
429 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
430 goto cleanup;
431 }
432 RegCloseKey(hKey);
433 hKey = NULL;
434
435 /* Write 'Linkage' key in hardware key */
436 #if _WIN32_WINNT >= 0x502
437 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
438 #else
439 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
440 #endif
441 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
442 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
443 if (hKey == INVALID_HANDLE_VALUE)
444 {
445 hKey = NULL;
446 rc = GetLastError();
447 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
448 goto cleanup;
449 }
450 rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
451 if (rc != ERROR_SUCCESS)
452 {
453 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
454 goto cleanup;
455 }
456 rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
457 if (rc != ERROR_SUCCESS)
458 {
459 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
460 goto cleanup;
461 }
462 if (BusType)
463 rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 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 = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
470 if (rc != ERROR_SUCCESS)
471 {
472 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
473 goto cleanup;
474 }
475 rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
476 if (rc != ERROR_SUCCESS)
477 {
478 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
479 goto cleanup;
480 }
481 rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
482 if (rc != ERROR_SUCCESS)
483 {
484 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
485 goto cleanup;
486 }
487 rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
488 if (rc != ERROR_SUCCESS)
489 {
490 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
491 goto cleanup;
492 }
493 RegCloseKey(hKey);
494 hKey = NULL;
495
496 /* Write connection information in network subkey */
497 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);
498 if (rc != ERROR_SUCCESS)
499 {
500 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
501 goto cleanup;
502 }
503 rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
504 if (rc != ERROR_SUCCESS)
505 {
506 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
507 goto cleanup;
508 }
509 rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
510 RegCloseKey(hKey);
511 hKey = NULL;
512 if (rc != ERROR_SUCCESS)
513 {
514 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
515 goto cleanup;
516 }
517 rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)L"Network connection", (wcslen(L"Network connection") + 1) * sizeof(WCHAR));
518 if (rc != ERROR_SUCCESS)
519 {
520 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
521 goto cleanup;
522 }
523 rc = RegSetValueExW(hConnectionKey, L"PnpInstanceId", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
524 if (rc != ERROR_SUCCESS)
525 {
526 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
527 goto cleanup;
528 }
529 dwShowIcon = 1;
530 rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
531 if (rc != ERROR_SUCCESS)
532 {
533 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
534 goto cleanup;
535 }
536
537 /* Write linkage information in Tcpip service */
538 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);
539 if (rc != ERROR_SUCCESS)
540 {
541 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
542 goto cleanup;
543 }
544 rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
545 if (rc != ERROR_SUCCESS)
546 {
547 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
548 goto cleanup;
549 }
550 rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
551 if (rc != ERROR_SUCCESS)
552 {
553 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
554 goto cleanup;
555 }
556 rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
557 if (rc != ERROR_SUCCESS)
558 {
559 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
560 goto cleanup;
561 }
562
563 /* Install additionnal services */
564 rc = InstallAdditionalServices(NULL);
565 if (rc != ERROR_SUCCESS)
566 {
567 DPRINT("InstallAdditionalServices() failed with error 0x%lx\n", rc);
568 goto cleanup;
569 }
570
571 rc = ERROR_SUCCESS;
572
573 cleanup:
574 HeapFree(GetProcessHeap(), 0, InstanceId);
575 HeapFree(GetProcessHeap(), 0, DeviceName);
576 HeapFree(GetProcessHeap(), 0, ExportName);
577 if (hKey != NULL)
578 RegCloseKey(hKey);
579 if (hNetworkKey != NULL)
580 RegCloseKey(hNetworkKey);
581 if (hLinkageKey != NULL)
582 RegCloseKey(hLinkageKey);
583 if (hConnectionKey != NULL)
584 RegCloseKey(hConnectionKey);
585 return rc;
586 }
587
588 static DWORD
589 InstallNetClient(VOID)
590 {
591 DPRINT1("Installation of network clients is not yet supported\n");
592 return ERROR_GEN_FAILURE;
593 }
594
595 static DWORD
596 InstallNetService(VOID)
597 {
598 DPRINT1("Installation of network services is not yet supported\n");
599 return ERROR_GEN_FAILURE;
600 }
601
602 static DWORD
603 InstallNetTransport(VOID)
604 {
605 DPRINT1("Installation of network protocols is not yet supported\n");
606 return ERROR_GEN_FAILURE;
607 }
608
609 DWORD WINAPI
610 NetClassInstaller(
611 IN DI_FUNCTION InstallFunction,
612 IN HDEVINFO DeviceInfoSet,
613 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
614 {
615 SP_DRVINFO_DATA_W DriverInfoData;
616 SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
617 WCHAR SectionName[LINE_LEN];
618 HINF hInf = INVALID_HANDLE_VALUE;
619 INFCONTEXT InfContext;
620 UINT ErrorLine;
621 INT CharacteristicsInt;
622 DWORD Characteristics;
623 LPWSTR BusType = NULL;
624 RPC_STATUS RpcStatus;
625 UUID Uuid;
626 LPWSTR UuidRpcString = NULL;
627 LPWSTR UuidString = NULL;
628 LONG rc;
629 DWORD dwLength;
630
631 if (InstallFunction != DIF_INSTALLDEVICE)
632 return ERROR_DI_DO_DEFAULT;
633
634 DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
635
636 /* Get driver info details */
637 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
638 if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
639 {
640 rc = GetLastError();
641 DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
642 goto cleanup;
643 }
644 DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
645 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
646 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
647 {
648 rc = GetLastError();
649 DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
650 goto cleanup;
651 }
652 hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
653 if (hInf == INVALID_HANDLE_VALUE)
654 {
655 rc = GetLastError();
656 DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
657 goto cleanup;
658 }
659 if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
660 {
661 rc = GetLastError();
662 DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
663 goto cleanup;
664 }
665
666 /* Get Characteristics and BusType (optional) from .inf file */
667 if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
668 {
669 rc = GetLastError();
670 DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
671 L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
672 goto cleanup;
673 }
674 if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
675 {
676 rc = GetLastError();
677 DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc);
678 goto cleanup;
679 }
680 Characteristics = (DWORD)CharacteristicsInt;
681 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
682 {
683 if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
684 {
685 if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
686 {
687 rc = GetLastError();
688 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
689 goto cleanup;
690 }
691 BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
692 if (!BusType)
693 {
694 DPRINT("HeapAlloc() failed\n");
695 rc = ERROR_NOT_ENOUGH_MEMORY;
696 goto cleanup;
697 }
698 if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
699 {
700 rc = GetLastError();
701 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
702 goto cleanup;
703 }
704 }
705 }
706
707 /* Create a new UUID */
708 RpcStatus = UuidCreate(&Uuid);
709 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
710 {
711 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
712 rc = ERROR_GEN_FAILURE;
713 goto cleanup;
714 }
715 RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
716 if (RpcStatus != RPC_S_OK)
717 {
718 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
719 rc = ERROR_GEN_FAILURE;
720 goto cleanup;
721 }
722
723 /* Add curly braces around Uuid */
724 UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
725 if (!UuidString)
726 {
727 DPRINT("HeapAlloc() failed\n");
728 rc = ERROR_NOT_ENOUGH_MEMORY;
729 goto cleanup;
730 }
731 wcscpy(UuidString, L"{");
732 wcscat(UuidString, UuidRpcString);
733 wcscat(UuidString, L"}");
734
735 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
736 rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
737 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
738 rc = InstallNetClient();
739 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
740 rc = InstallNetService();
741 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
742 rc = InstallNetTransport();
743 else
744 {
745 DPRINT("Invalid class guid\n");
746 rc = ERROR_GEN_FAILURE;
747 }
748
749 cleanup:
750 if (hInf != INVALID_HANDLE_VALUE)
751 SetupCloseInfFile(hInf);
752 if (UuidRpcString != NULL)
753 RpcStringFreeW(&UuidRpcString);
754 HeapFree(GetProcessHeap(), 0, BusType);
755 HeapFree(GetProcessHeap(), 0, UuidString);
756
757 if (rc == ERROR_SUCCESS)
758 rc = ERROR_DI_DO_DEFAULT;
759 DPRINT("Returning 0x%lx\n", rc);
760 return rc;
761 }