[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;
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 RegCloseKey(hKey);
426 hKey = NULL;
427
428 /* Write 'Linkage' key in hardware key */
429 #if _WIN32_WINNT >= 0x502
430 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
431 #else
432 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
433 #endif
434 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
435 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
436 if (hKey == INVALID_HANDLE_VALUE)
437 {
438 hKey = NULL;
439 rc = GetLastError();
440 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc);
441 goto cleanup;
442 }
443 rc = RegSetValueExW(hKey, L"NetCfgInstanceId", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
444 if (rc != ERROR_SUCCESS)
445 {
446 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
447 goto cleanup;
448 }
449 rc = RegSetValueExW(hKey, L"Characteristics", 0, REG_DWORD, (const BYTE*)&Characteristics, sizeof(DWORD));
450 if (rc != ERROR_SUCCESS)
451 {
452 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
453 goto cleanup;
454 }
455 if (BusType)
456 rc = RegSetValueExW(hKey, L"BusType", 0, REG_SZ, (const BYTE*)BusType, (wcslen(BusType) + 1) * sizeof(WCHAR));
457 if (rc != ERROR_SUCCESS)
458 {
459 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
460 goto cleanup;
461 }
462 rc = RegCreateKeyExW(hKey, L"Linkage", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hLinkageKey, NULL);
463 if (rc != ERROR_SUCCESS)
464 {
465 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
466 goto cleanup;
467 }
468 rc = RegSetValueExW(hLinkageKey, L"Export", 0, REG_SZ, (const BYTE*)DeviceName, (wcslen(DeviceName) + 1) * sizeof(WCHAR));
469 if (rc != ERROR_SUCCESS)
470 {
471 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
472 goto cleanup;
473 }
474 rc = RegSetValueExW(hLinkageKey, L"RootDevice", 0, REG_SZ, (const BYTE*)UuidString, (wcslen(UuidString) + 1) * sizeof(WCHAR));
475 if (rc != ERROR_SUCCESS)
476 {
477 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
478 goto cleanup;
479 }
480 rc = RegSetValueExW(hLinkageKey, L"UpperBind", 0, REG_SZ, (const BYTE*)L"Tcpip", (wcslen(L"Tcpip") + 1) * sizeof(WCHAR));
481 if (rc != ERROR_SUCCESS)
482 {
483 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
484 goto cleanup;
485 }
486 RegCloseKey(hKey);
487 hKey = NULL;
488
489 /* Write connection information in network subkey */
490 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);
491 if (rc != ERROR_SUCCESS)
492 {
493 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
494 goto cleanup;
495 }
496 rc = RegCreateKeyExW(hNetworkKey, UuidString, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
497 if (rc != ERROR_SUCCESS)
498 {
499 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
500 goto cleanup;
501 }
502 rc = RegCreateKeyExW(hKey, L"Connection", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hConnectionKey, NULL);
503 RegCloseKey(hKey);
504 hKey = NULL;
505 if (rc != ERROR_SUCCESS)
506 {
507 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
508 goto cleanup;
509 }
510 rc = RegSetValueExW(hConnectionKey, L"Name", 0, REG_SZ, (const BYTE*)L"Network connection", (wcslen(L"Network connection") + 1) * sizeof(WCHAR));
511 if (rc != ERROR_SUCCESS)
512 {
513 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
514 goto cleanup;
515 }
516 rc = RegSetValueExW(hConnectionKey, L"PnpInstanceId", 0, REG_SZ, (const BYTE*)InstanceId, (wcslen(InstanceId) + 1) * sizeof(WCHAR));
517 if (rc != ERROR_SUCCESS)
518 {
519 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
520 goto cleanup;
521 }
522 dwShowIcon = 1;
523 rc = RegSetValueExW(hConnectionKey, L"ShowIcon", 0, REG_DWORD, (const BYTE*)&dwShowIcon, sizeof(dwShowIcon));
524 if (rc != ERROR_SUCCESS)
525 {
526 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc);
527 goto cleanup;
528 }
529
530 /* Write linkage information in Tcpip service */
531 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);
532 if (rc != ERROR_SUCCESS)
533 {
534 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc);
535 goto cleanup;
536 }
537 rc = AppendStringToMultiSZ(hKey, L"Bind", DeviceName);
538 if (rc != ERROR_SUCCESS)
539 {
540 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
541 goto cleanup;
542 }
543 rc = AppendStringToMultiSZ(hKey, L"Export", ExportName);
544 if (rc != ERROR_SUCCESS)
545 {
546 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
547 goto cleanup;
548 }
549 rc = AppendStringToMultiSZ(hKey, L"Route", UuidString);
550 if (rc != ERROR_SUCCESS)
551 {
552 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc);
553 goto cleanup;
554 }
555
556 /* Install additionnal services */
557 rc = InstallAdditionalServices(NULL);
558 if (rc != ERROR_SUCCESS)
559 {
560 DPRINT("InstallAdditionalServices() failed with error 0x%lx\n", rc);
561 goto cleanup;
562 }
563
564 rc = ERROR_SUCCESS;
565
566 cleanup:
567 HeapFree(GetProcessHeap(), 0, InstanceId);
568 HeapFree(GetProcessHeap(), 0, DeviceName);
569 HeapFree(GetProcessHeap(), 0, ExportName);
570 if (hKey != NULL)
571 RegCloseKey(hKey);
572 if (hNetworkKey != NULL)
573 RegCloseKey(hNetworkKey);
574 if (hLinkageKey != NULL)
575 RegCloseKey(hLinkageKey);
576 if (hConnectionKey != NULL)
577 RegCloseKey(hConnectionKey);
578 return rc;
579 }
580
581 static DWORD
582 InstallNetClient(VOID)
583 {
584 DPRINT1("Installation of network clients is not yet supported\n");
585 return ERROR_GEN_FAILURE;
586 }
587
588 static DWORD
589 InstallNetService(VOID)
590 {
591 DPRINT1("Installation of network services is not yet supported\n");
592 return ERROR_GEN_FAILURE;
593 }
594
595 static DWORD
596 InstallNetTransport(VOID)
597 {
598 DPRINT1("Installation of network protocols is not yet supported\n");
599 return ERROR_GEN_FAILURE;
600 }
601
602 DWORD WINAPI
603 NetClassInstaller(
604 IN DI_FUNCTION InstallFunction,
605 IN HDEVINFO DeviceInfoSet,
606 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
607 {
608 SP_DRVINFO_DATA_W DriverInfoData;
609 SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail;
610 WCHAR SectionName[LINE_LEN];
611 HINF hInf = INVALID_HANDLE_VALUE;
612 INFCONTEXT InfContext;
613 UINT ErrorLine;
614 INT CharacteristicsInt;
615 DWORD Characteristics;
616 LPWSTR BusType = NULL;
617 RPC_STATUS RpcStatus;
618 UUID Uuid;
619 LPWSTR UuidRpcString = NULL;
620 LPWSTR UuidString = NULL;
621 LONG rc;
622 DWORD dwLength;
623
624 if (InstallFunction != DIF_INSTALLDEVICE)
625 return ERROR_DI_DO_DEFAULT;
626
627 DPRINT("%lu %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
628
629 /* Get driver info details */
630 DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W);
631 if (!SetupDiGetSelectedDriverW(DeviceInfoSet, DeviceInfoData, &DriverInfoData))
632 {
633 rc = GetLastError();
634 DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc);
635 goto cleanup;
636 }
637 DriverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
638 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet, DeviceInfoData, &DriverInfoData, &DriverInfoDetail, sizeof(DriverInfoDetail), NULL)
639 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
640 {
641 rc = GetLastError();
642 DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc);
643 goto cleanup;
644 }
645 hInf = SetupOpenInfFileW(DriverInfoDetail.InfFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
646 if (hInf == INVALID_HANDLE_VALUE)
647 {
648 rc = GetLastError();
649 DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc);
650 goto cleanup;
651 }
652 if (!SetupDiGetActualSectionToInstallW(hInf, DriverInfoDetail.SectionName, SectionName, LINE_LEN, NULL, NULL))
653 {
654 rc = GetLastError();
655 DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc);
656 goto cleanup;
657 }
658
659 /* Get Characteristics and BusType (optional) from .inf file */
660 if (!SetupFindFirstLineW(hInf, SectionName, L"Characteristics", &InfContext))
661 {
662 rc = GetLastError();
663 DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
664 L"Characteristics", SectionName, DriverInfoDetail.InfFileName, rc);
665 goto cleanup;
666 }
667 if (!SetupGetIntField(&InfContext, 1, &CharacteristicsInt))
668 {
669 rc = GetLastError();
670 DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc);
671 goto cleanup;
672 }
673 Characteristics = (DWORD)CharacteristicsInt;
674 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
675 {
676 if (SetupFindFirstLineW(hInf, SectionName, L"BusType", &InfContext))
677 {
678 if (!SetupGetStringFieldW(&InfContext, 1, NULL, 0, &dwLength))
679 {
680 rc = GetLastError();
681 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
682 goto cleanup;
683 }
684 BusType = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR));
685 if (!BusType)
686 {
687 DPRINT("HeapAlloc() failed\n");
688 rc = ERROR_NOT_ENOUGH_MEMORY;
689 goto cleanup;
690 }
691 if (!SetupGetStringFieldW(&InfContext, 1, BusType, dwLength, NULL))
692 {
693 rc = GetLastError();
694 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc);
695 goto cleanup;
696 }
697 }
698 }
699
700 /* Create a new UUID */
701 RpcStatus = UuidCreate(&Uuid);
702 if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
703 {
704 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
705 rc = ERROR_GEN_FAILURE;
706 goto cleanup;
707 }
708 RpcStatus = UuidToStringW(&Uuid, &UuidRpcString);
709 if (RpcStatus != RPC_S_OK)
710 {
711 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
712 rc = ERROR_GEN_FAILURE;
713 goto cleanup;
714 }
715
716 /* Add curly braces around Uuid */
717 UuidString = HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString)) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
718 if (!UuidString)
719 {
720 DPRINT("HeapAlloc() failed\n");
721 rc = ERROR_NOT_ENOUGH_MEMORY;
722 goto cleanup;
723 }
724 wcscpy(UuidString, L"{");
725 wcscat(UuidString, UuidRpcString);
726 wcscat(UuidString, L"}");
727
728 if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NET))
729 rc = InstallNetDevice(DeviceInfoSet, DeviceInfoData, UuidString, Characteristics, BusType);
730 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETCLIENT))
731 rc = InstallNetClient();
732 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETSERVICE))
733 rc = InstallNetService();
734 else if (IsEqualIID(&DeviceInfoData->ClassGuid, &GUID_DEVCLASS_NETTRANS))
735 rc = InstallNetTransport();
736 else
737 {
738 DPRINT("Invalid class guid\n");
739 rc = ERROR_GEN_FAILURE;
740 }
741
742 cleanup:
743 if (hInf != INVALID_HANDLE_VALUE)
744 SetupCloseInfFile(hInf);
745 if (UuidRpcString != NULL)
746 RpcStringFreeW(&UuidRpcString);
747 HeapFree(GetProcessHeap(), 0, BusType);
748 HeapFree(GetProcessHeap(), 0, UuidString);
749
750 if (rc == ERROR_SUCCESS)
751 rc = ERROR_DI_DO_DEFAULT;
752 DPRINT("Returning 0x%lx\n", rc);
753 return rc;
754 }