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
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
16 /* Append a REG_SZ to an existing REG_MULTI_SZ string in the registry.
17 * If the value doesn't exist, create it.
18 * Returns ERROR_SUCCESS if success. Othewise, returns an error code
21 AppendStringToMultiSZ(
24 IN PCWSTR ValueToAppend
)
28 DWORD dwRequired
, dwLength
;
32 rc
= RegQueryValueExW(
39 if (rc
!= ERROR_FILE_NOT_FOUND
)
41 if (rc
!= ERROR_SUCCESS
)
43 if (dwRegType
!= REG_MULTI_SZ
)
45 rc
= ERROR_GEN_FAILURE
;
49 dwTmp
= dwLength
= dwRequired
+ wcslen(ValueToAppend
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
50 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
53 rc
= ERROR_NOT_ENOUGH_MEMORY
;
56 rc
= RegQueryValueExW(
63 if (rc
!= ERROR_SUCCESS
)
68 dwRequired
= sizeof(WCHAR
);
69 dwLength
= wcslen(ValueToAppend
) * sizeof(WCHAR
) + 2 * sizeof(UNICODE_NULL
);
70 Buffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
73 rc
= ERROR_NOT_ENOUGH_MEMORY
;
78 /* Append the value */
79 wcscpy(&Buffer
[dwRequired
/ sizeof(WCHAR
) - 1], ValueToAppend
);
80 /* Terminate the REG_MULTI_SZ string */
81 Buffer
[dwLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
92 HeapFree(GetProcessHeap(), 0, Buffer
);
96 /* Install a section of a .inf file
97 * Returns TRUE if success, FALSE if failure. Error code can
98 * be retrieved with GetLastError()
104 IN LPCWSTR InfSection OPTIONAL
,
105 IN LPCWSTR InfService OPTIONAL
)
107 WCHAR Buffer
[MAX_PATH
];
108 HINF hInf
= INVALID_HANDLE_VALUE
;
110 PVOID Context
= NULL
;
113 /* Get Windows directory */
114 BufferSize
= MAX_PATH
- 5 - wcslen(InfFile
);
115 if (GetWindowsDirectoryW(Buffer
, BufferSize
) > BufferSize
)
117 /* Function failed */
118 SetLastError(ERROR_GEN_FAILURE
);
121 /* We have enough space to add some information in the buffer */
122 if (Buffer
[wcslen(Buffer
) - 1] != '\\')
123 wcscat(Buffer
, L
"\\");
124 wcscat(Buffer
, L
"Inf\\");
125 wcscat(Buffer
, InfFile
);
127 /* Install specified section */
128 hInf
= SetupOpenInfFileW(Buffer
, NULL
, INF_STYLE_WIN4
, NULL
);
129 if (hInf
== INVALID_HANDLE_VALUE
)
132 Context
= SetupInitDefaultQueueCallback(hWnd
);
137 if (ret
&& InfSection
)
139 ret
= SetupInstallFromInfSectionW(
141 InfSection
, SPINST_ALL
,
142 NULL
, NULL
, SP_COPY_NEWER
,
143 SetupDefaultQueueCallbackW
, Context
,
146 if (ret
&& InfService
)
148 ret
= SetupInstallServicesFromInfSectionW(
149 hInf
, InfService
, 0);
154 SetupTermDefaultQueueCallback(Context
);
155 if (hInf
!= INVALID_HANDLE_VALUE
)
156 SetupCloseInfFile(hInf
);
160 /* Add default services for network cards */
162 InstallAdditionalServices(
167 /* Install TCP/IP protocol */
168 ret
= InstallInfSection(
171 L
"MS_TCPIP.PrimaryInstall",
172 L
"MS_TCPIP.PrimaryInstall.Services");
173 if (!ret
&& GetLastError() != ERROR_FILE_NOT_FOUND
)
175 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
176 return GetLastError();
179 /* You can add here more clients (SMB...) and services (DHCP server...) */
181 return ERROR_SUCCESS
;
186 IN HDEVINFO DeviceInfoSet
,
187 IN PSP_DEVINFO_DATA DeviceInfoData
,
189 DWORD Characteristics
,
192 LPWSTR InstanceId
= NULL
;
193 LPWSTR DeviceName
= NULL
;
194 LPWSTR ExportName
= NULL
;
197 HKEY hNetworkKey
= NULL
;
198 HKEY hLinkageKey
= NULL
;
199 HKEY hConnectionKey
= NULL
;
200 DWORD dwShowIcon
, dwLength
;
201 SP_DEVINSTALL_PARAMS_W installParams
;
203 /* Get Instance ID */
204 if (SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, NULL
, 0, &dwLength
))
206 DPRINT("SetupDiGetDeviceInstanceIdW() returned TRUE. FALSE expected\n");
207 rc
= ERROR_GEN_FAILURE
;
210 InstanceId
= HeapAlloc(GetProcessHeap(), 0, dwLength
* sizeof(WCHAR
));
213 DPRINT("HeapAlloc() failed\n");
214 rc
= ERROR_NOT_ENOUGH_MEMORY
;
217 if (!SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
, InstanceId
, dwLength
, NULL
))
220 DPRINT("SetupDiGetDeviceInstanceIdW() failed with error 0x%lx\n", rc
);
224 /* Create device name */
225 DeviceName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
228 DPRINT("HeapAlloc() failed\n");
229 rc
= ERROR_NOT_ENOUGH_MEMORY
;
232 wcscpy(DeviceName
, L
"\\Device\\");
233 wcscat(DeviceName
, UuidString
);
235 /* Create export name */
236 ExportName
= HeapAlloc(GetProcessHeap(), 0, (wcslen(L
"\\Device\\Tcpip_") + wcslen(UuidString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
239 DPRINT("HeapAlloc() failed\n");
240 rc
= ERROR_NOT_ENOUGH_MEMORY
;
243 wcscpy(ExportName
, L
"\\Device\\Tcpip_");
244 wcscat(ExportName
, UuidString
);
246 /* Write Tcpip parameters in new service Key */
247 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services", 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hKey
, NULL
);
248 if (rc
!= ERROR_SUCCESS
)
250 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
253 rc
= RegCreateKeyExW(hKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, 0, NULL
, &hNetworkKey
, NULL
);
254 if (rc
!= ERROR_SUCCESS
)
256 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
261 rc
= RegCreateKeyExW(hNetworkKey
, L
"Parameters\\Tcpip", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hKey
, NULL
);
262 if (rc
!= ERROR_SUCCESS
)
264 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
267 RegCloseKey(hNetworkKey
);
269 rc
= RegSetValueExW(hKey
, L
"DefaultGateway", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
270 if (rc
!= ERROR_SUCCESS
)
272 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
275 rc
= RegSetValueExW(hKey
, L
"IPAddress", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
276 if (rc
!= ERROR_SUCCESS
)
278 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
281 rc
= RegSetValueExW(hKey
, L
"SubnetMask", 0, REG_SZ
, (const BYTE
*)L
"0.0.0.0", (wcslen(L
"0.0.0.0") + 1) * sizeof(WCHAR
));
282 if (rc
!= ERROR_SUCCESS
)
284 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
290 /* Write 'Linkage' key in hardware key */
291 #if _WIN32_WINNT >= 0x502
292 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
294 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
296 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
297 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
298 if (hKey
== INVALID_HANDLE_VALUE
)
302 DPRINT("SetupDiCreateDevRegKeyW() failed with error 0x%lx\n", rc
);
305 rc
= RegSetValueExW(hKey
, L
"NetCfgInstanceId", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
306 if (rc
!= ERROR_SUCCESS
)
308 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
311 rc
= RegSetValueExW(hKey
, L
"Characteristics", 0, REG_DWORD
, (const BYTE
*)&Characteristics
, sizeof(DWORD
));
312 if (rc
!= ERROR_SUCCESS
)
314 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
318 rc
= RegSetValueExW(hKey
, L
"BusType", 0, REG_SZ
, (const BYTE
*)BusType
, (wcslen(BusType
) + 1) * sizeof(WCHAR
));
319 if (rc
!= ERROR_SUCCESS
)
321 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
324 rc
= RegCreateKeyExW(hKey
, L
"Linkage", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hLinkageKey
, NULL
);
325 if (rc
!= ERROR_SUCCESS
)
327 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
330 rc
= RegSetValueExW(hLinkageKey
, L
"Export", 0, REG_SZ
, (const BYTE
*)DeviceName
, (wcslen(DeviceName
) + 1) * sizeof(WCHAR
));
331 if (rc
!= ERROR_SUCCESS
)
333 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
336 rc
= RegSetValueExW(hLinkageKey
, L
"RootDevice", 0, REG_SZ
, (const BYTE
*)UuidString
, (wcslen(UuidString
) + 1) * sizeof(WCHAR
));
337 if (rc
!= ERROR_SUCCESS
)
339 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
342 rc
= RegSetValueExW(hLinkageKey
, L
"UpperBind", 0, REG_SZ
, (const BYTE
*)L
"Tcpip", (wcslen(L
"Tcpip") + 1) * sizeof(WCHAR
));
343 if (rc
!= ERROR_SUCCESS
)
345 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
351 /* Write connection information in network subkey */
352 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
);
353 if (rc
!= ERROR_SUCCESS
)
355 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
358 rc
= RegCreateKeyExW(hNetworkKey
, UuidString
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_CREATE_SUB_KEY
, NULL
, &hKey
, NULL
);
359 if (rc
!= ERROR_SUCCESS
)
361 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
364 rc
= RegCreateKeyExW(hKey
, L
"Connection", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_SET_VALUE
, NULL
, &hConnectionKey
, NULL
);
367 if (rc
!= ERROR_SUCCESS
)
369 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
372 rc
= RegSetValueExW(hConnectionKey
, L
"Name", 0, REG_SZ
, (const BYTE
*)L
"Network connection", (wcslen(L
"Network connection") + 1) * sizeof(WCHAR
));
373 if (rc
!= ERROR_SUCCESS
)
375 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
378 rc
= RegSetValueExW(hConnectionKey
, L
"PnpInstanceId", 0, REG_SZ
, (const BYTE
*)InstanceId
, (wcslen(InstanceId
) + 1) * sizeof(WCHAR
));
379 if (rc
!= ERROR_SUCCESS
)
381 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
385 rc
= RegSetValueExW(hConnectionKey
, L
"ShowIcon", 0, REG_DWORD
, (const BYTE
*)&dwShowIcon
, sizeof(dwShowIcon
));
386 if (rc
!= ERROR_SUCCESS
)
388 DPRINT("RegSetValueExW() failed with error 0x%lx\n", rc
);
392 /* Write linkage information in Tcpip service */
393 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
);
394 if (rc
!= ERROR_SUCCESS
)
396 DPRINT("RegCreateKeyExW() failed with error 0x%lx\n", rc
);
399 rc
= AppendStringToMultiSZ(hKey
, L
"Bind", DeviceName
);
400 if (rc
!= ERROR_SUCCESS
)
402 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
405 rc
= AppendStringToMultiSZ(hKey
, L
"Export", ExportName
);
406 if (rc
!= ERROR_SUCCESS
)
408 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
411 rc
= AppendStringToMultiSZ(hKey
, L
"Route", UuidString
);
412 if (rc
!= ERROR_SUCCESS
)
414 DPRINT("AppendStringToMultiSZ() failed with error 0x%lx\n", rc
);
418 /* Install additionnal services */
419 rc
= InstallAdditionalServices(NULL
);
420 if (rc
!= ERROR_SUCCESS
)
422 DPRINT("InstallAdditionalServices() failed with error 0x%lx\n", rc
);
426 /* HACK: hpoussin, Dec 2005. TCP/IP driver is not able to manage devices
427 * which are installed after its startup. So, we have to reboot to take
428 * this new netcard into account.
430 /* Should we reboot? */
431 installParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
432 if (!SetupDiGetDeviceInstallParamsW(
438 DPRINT("SetupDiGetDeviceInstallParams() failed with error 0x%lx\n", rc
);
441 installParams
.Flags
|= DI_NEEDRESTART
;
442 if (!SetupDiSetDeviceInstallParamsW(
448 DPRINT("SetupDiSetDeviceInstallParams() failed with error 0x%lx\n", rc
);
454 HeapFree(GetProcessHeap(), 0, InstanceId
);
455 HeapFree(GetProcessHeap(), 0, DeviceName
);
456 HeapFree(GetProcessHeap(), 0, ExportName
);
459 if (hNetworkKey
!= NULL
)
460 RegCloseKey(hNetworkKey
);
461 if (hLinkageKey
!= NULL
)
462 RegCloseKey(hLinkageKey
);
463 if (hConnectionKey
!= NULL
)
464 RegCloseKey(hConnectionKey
);
469 InstallNetClient(VOID
)
471 DPRINT1("Installation of network clients is not yet supported\n");
472 return ERROR_GEN_FAILURE
;
476 InstallNetService(VOID
)
478 DPRINT1("Installation of network services is not yet supported\n");
479 return ERROR_GEN_FAILURE
;
483 InstallNetTransport(VOID
)
485 DPRINT1("Installation of network protocols is not yet supported\n");
486 return ERROR_GEN_FAILURE
;
491 IN DI_FUNCTION InstallFunction
,
492 IN HDEVINFO DeviceInfoSet
,
493 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
495 SP_DRVINFO_DATA_W DriverInfoData
;
496 SP_DRVINFO_DETAIL_DATA_W DriverInfoDetail
;
497 WCHAR SectionName
[LINE_LEN
];
498 HINF hInf
= INVALID_HANDLE_VALUE
;
499 INFCONTEXT InfContext
;
501 INT CharacteristicsInt
;
502 DWORD Characteristics
;
503 LPWSTR BusType
= NULL
;
504 RPC_STATUS RpcStatus
;
506 LPWSTR UuidRpcString
= NULL
;
507 LPWSTR UuidString
= NULL
;
511 if (InstallFunction
!= DIF_INSTALLDEVICE
)
512 return ERROR_DI_DO_DEFAULT
;
514 DPRINT("%lu %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
516 /* Get driver info details */
517 DriverInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
518 if (!SetupDiGetSelectedDriverW(DeviceInfoSet
, DeviceInfoData
, &DriverInfoData
))
521 DPRINT("SetupDiGetSelectedDriverW() failed with error 0x%lx\n", rc
);
524 DriverInfoDetail
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
525 if (!SetupDiGetDriverInfoDetailW(DeviceInfoSet
, DeviceInfoData
, &DriverInfoData
, &DriverInfoDetail
, sizeof(DriverInfoDetail
), NULL
)
526 && GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
529 DPRINT("SetupDiGetDriverInfoDetailW() failed with error 0x%lx\n", rc
);
532 hInf
= SetupOpenInfFileW(DriverInfoDetail
.InfFileName
, NULL
, INF_STYLE_WIN4
, &ErrorLine
);
533 if (hInf
== INVALID_HANDLE_VALUE
)
536 DPRINT("SetupOpenInfFileW() failed with error 0x%lx\n", rc
);
539 if (!SetupDiGetActualSectionToInstallW(hInf
, DriverInfoDetail
.SectionName
, SectionName
, LINE_LEN
, NULL
, NULL
))
542 DPRINT("SetupDiGetActualSectionToInstallW() failed with error 0x%lx\n", rc
);
546 /* Get Characteristics and BusType (optional) from .inf file */
547 if (!SetupFindFirstLineW(hInf
, SectionName
, L
"Characteristics", &InfContext
))
550 DPRINT("Unable to find key %S in section %S of file %S (error 0x%lx)\n",
551 L
"Characteristics", SectionName
, DriverInfoDetail
.InfFileName
, rc
);
554 if (!SetupGetIntField(&InfContext
, 1, &CharacteristicsInt
))
557 DPRINT("SetupGetIntField() failed with error 0x%lx\n", rc
);
560 Characteristics
= (DWORD
)CharacteristicsInt
;
561 if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NET
))
563 if (SetupFindFirstLineW(hInf
, SectionName
, L
"BusType", &InfContext
))
565 if (!SetupGetStringFieldW(&InfContext
, 1, NULL
, 0, &dwLength
))
568 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc
);
571 BusType
= HeapAlloc(GetProcessHeap(), 0, dwLength
* sizeof(WCHAR
));
574 DPRINT("HeapAlloc() failed\n");
575 rc
= ERROR_NOT_ENOUGH_MEMORY
;
578 if (!SetupGetStringFieldW(&InfContext
, 1, BusType
, dwLength
, NULL
))
581 DPRINT("SetupGetStringFieldW() failed with error 0x%lx\n", rc
);
587 /* Create a new UUID */
588 RpcStatus
= UuidCreate(&Uuid
);
589 if (RpcStatus
!= RPC_S_OK
&& RpcStatus
!= RPC_S_UUID_LOCAL_ONLY
)
591 DPRINT("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus
);
592 rc
= ERROR_GEN_FAILURE
;
595 RpcStatus
= UuidToStringW(&Uuid
, &UuidRpcString
);
596 if (RpcStatus
!= RPC_S_OK
)
598 DPRINT("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus
);
599 rc
= ERROR_GEN_FAILURE
;
603 /* Add curly braces around Uuid */
604 UuidString
= HeapAlloc(GetProcessHeap(), 0, (2 + wcslen(UuidRpcString
)) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
607 DPRINT("HeapAlloc() failed\n");
608 rc
= ERROR_NOT_ENOUGH_MEMORY
;
611 wcscpy(UuidString
, L
"{");
612 wcscat(UuidString
, UuidRpcString
);
613 wcscat(UuidString
, L
"}");
615 if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NET
))
616 rc
= InstallNetDevice(DeviceInfoSet
, DeviceInfoData
, UuidString
, Characteristics
, BusType
);
617 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETCLIENT
))
618 rc
= InstallNetClient();
619 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETSERVICE
))
620 rc
= InstallNetService();
621 else if (IsEqualIID(&DeviceInfoData
->ClassGuid
, &GUID_DEVCLASS_NETTRANS
))
622 rc
= InstallNetTransport();
625 DPRINT("Invalid class guid\n");
626 rc
= ERROR_GEN_FAILURE
;
630 if (hInf
!= INVALID_HANDLE_VALUE
)
631 SetupCloseInfFile(hInf
);
632 if (UuidRpcString
!= NULL
)
633 RpcStringFreeW(&UuidRpcString
);
634 HeapFree(GetProcessHeap(), 0, BusType
);
635 HeapFree(GetProcessHeap(), 0, UuidString
);
637 if (rc
== ERROR_SUCCESS
)
638 rc
= ERROR_DI_DO_DEFAULT
;
639 DPRINT("Returning 0x%lx\n", rc
);