[SYSSETUP][NETCFGX][INF] Install the TCPIP protocol driver properly

Get rid of the special RandomProtocolGUID_TCPIP :-)
Works with the Setup CD and Live CD.
This commit is contained in:
Eric Kohl 2019-10-06 22:36:19 +02:00
parent 2d1a6b2db9
commit 80db055135
6 changed files with 561 additions and 100 deletions

View file

@ -503,7 +503,7 @@ CreateNotificationObject(
HRESULT hr;
LONG lRet;
CLSID ClassGUID;
//CLSID InstanceGUID;
CLSID InstanceGUID;
wcscpy(szName,L"SYSTEM\\CurrentControlSet\\Control\\Network\\");
@ -521,7 +521,6 @@ CreateNotificationObject(
wcscat(szName, L"\\");
/* get the Instance GUID */
#if 0
hr = INetCfgComponent_GetInstanceGuid(iface, &InstanceGUID);
if (FAILED(hr))
return hr;
@ -532,10 +531,6 @@ CreateNotificationObject(
wcscat(szName, pStr);
CoTaskMemFree(pStr);
#else
// HACK HACK HACK HACK HACK
wcscat(szName, L"{RandomProtocolGUID_TCPIP}");
#endif
wcscat(szName, L"\\NDI");

View file

@ -6,6 +6,7 @@ list(APPEND SOURCE
dllmain.c
install.c
logfile.c
netinstall.c
proppage.c
security.c
wizard.c
@ -20,5 +21,5 @@ add_library(syssetup MODULE
add_pch(syssetup precomp.h SOURCE)
set_module_type(syssetup win32dll UNICODE)
target_link_libraries(syssetup uuid wine ${PSEH_LIB})
add_importlibs(syssetup advapi32 gdi32 user32 samlib userenv comctl32 setupapi ole32 shell32 shlwapi msvcrt kernel32 ntdll)
add_importlibs(syssetup advapi32 gdi32 user32 samlib userenv comctl32 setupapi rpcrt4 ole32 shell32 shlwapi msvcrt kernel32 ntdll)
add_cd_file(TARGET syssetup DESTINATION reactos/system32 FOR all)

View file

@ -31,6 +31,12 @@ extern ADMIN_INFO AdminInfo;
BOOL RegisterTypeLibraries (HINF hinf, LPCWSTR szSection);
/* netinstall.c */
BOOL
InstallNetworkComponent(
_In_ PWSTR pszComponentId);
/* security.c */
VOID InstallSecurity(VOID);

View file

@ -734,70 +734,6 @@ Exit:
return bResult;
}
/* Install a section of a .inf file
* Returns TRUE if success, FALSE if failure. Error code can
* be retrieved with GetLastError()
*/
static
BOOL
InstallInfSection(
IN HWND hWnd,
IN LPCWSTR InfFile,
IN LPCWSTR InfSection OPTIONAL,
IN LPCWSTR InfService OPTIONAL)
{
WCHAR Buffer[MAX_PATH];
HINF hInf = INVALID_HANDLE_VALUE;
UINT BufferSize;
PVOID Context = NULL;
BOOL ret = FALSE;
/* Get Windows directory */
BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile);
if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize)
{
/* Function failed */
SetLastError(ERROR_GEN_FAILURE);
goto cleanup;
}
/* We have enough space to add some information in the buffer */
if (Buffer[wcslen(Buffer) - 1] != '\\')
wcscat(Buffer, L"\\");
wcscat(Buffer, L"Inf\\");
wcscat(Buffer, InfFile);
/* Install specified section */
hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
goto cleanup;
Context = SetupInitDefaultQueueCallback(hWnd);
if (Context == NULL)
goto cleanup;
ret = TRUE;
if (ret && InfSection)
{
ret = SetupInstallFromInfSectionW(
hWnd, hInf,
InfSection, SPINST_ALL,
NULL, NULL, SP_COPY_NEWER,
SetupDefaultQueueCallbackW, Context,
NULL, NULL);
}
if (ret && InfService)
{
ret = SetupInstallServicesFromInfSectionW(hInf, InfService, 0);
}
cleanup:
if (Context)
SetupTermDefaultQueueCallback(Context);
if (hInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(hInf);
return ret;
}
static
DWORD
InstallLiveCD(VOID)
@ -806,14 +742,14 @@ InstallLiveCD(VOID)
PROCESS_INFORMATION ProcessInformation;
BOOL bRes;
/* Hack: Install TCP/IP protocol driver */
bRes = InstallInfSection(NULL,
L"nettcpip.inf",
L"MS_TCPIP.PrimaryInstall",
L"MS_TCPIP.PrimaryInstall.Services");
if (!CommonInstall())
goto error;
/* Install the TCP/IP protocol driver */
bRes = InstallNetworkComponent(L"MS_TCPIP");
if (!bRes && GetLastError() != ERROR_FILE_NOT_FOUND)
{
DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError());
}
else
{
@ -822,9 +758,6 @@ InstallLiveCD(VOID)
SetupStartService(L"Dhcp", FALSE);
}
if (!CommonInstall())
goto error;
/* Register components */
_SEH2_TRY
{
@ -1327,14 +1260,14 @@ InstallReactOS(VOID)
hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL);
/* Hack: Install TCP/IP protocol driver */
ret = InstallInfSection(NULL,
L"nettcpip.inf",
L"MS_TCPIP.PrimaryInstall",
L"MS_TCPIP.PrimaryInstall.Services");
if (!CommonInstall())
return 0;
/* Install the TCP/IP protocol driver */
ret = InstallNetworkComponent(L"MS_TCPIP");
if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND)
{
DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError());
}
else
{
@ -1343,10 +1276,6 @@ InstallReactOS(VOID)
SetupStartService(L"Dhcp", FALSE);
}
if (!CommonInstall())
return 0;
InstallWizard();
InstallSecurity();

View file

@ -0,0 +1,528 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: System setup
* FILE: dll/win32/syssetup/netinstall.c
* PROGRAMER: Eric Kohl
*/
/* INCLUDES *****************************************************************/
#include "precomp.h"
#include <rpc.h>
#define NDEBUG
#include <debug.h>
typedef struct _COMPONENT_INFO
{
PWSTR pszInfPath;
PWSTR pszInfSection;
PWSTR pszComponentId;
PWSTR pszDescription;
PWSTR pszClassGuid;
DWORD dwCharacteristics;
} COMPONENT_INFO, *PCOMPONENT_INFO;
/* GLOBALS ******************************************************************/
/* FUNCTIONS ****************************************************************/
static
BOOL
InstallInfSections(
_In_ HWND hWnd,
_In_ HKEY hKey,
_In_ LPCWSTR InfFile,
_In_ LPCWSTR InfSection)
{
WCHAR Buffer[MAX_PATH];
HINF hInf = INVALID_HANDLE_VALUE;
UINT BufferSize;
PVOID Context = NULL;
BOOL ret = FALSE;
DPRINT("InstallInfSections()\n");
if (InfSection == NULL)
return FALSE;
/* Get Windows directory */
BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile);
if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize)
{
/* Function failed */
SetLastError(ERROR_GEN_FAILURE);
goto cleanup;
}
/* We have enough space to add some information in the buffer */
if (Buffer[wcslen(Buffer) - 1] != '\\')
wcscat(Buffer, L"\\");
wcscat(Buffer, L"Inf\\");
wcscat(Buffer, InfFile);
/* Install specified section */
hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
goto cleanup;
Context = SetupInitDefaultQueueCallback(hWnd);
if (Context == NULL)
goto cleanup;
ret = SetupInstallFromInfSectionW(
hWnd, hInf,
InfSection, SPINST_ALL,
hKey, NULL, SP_COPY_NEWER,
SetupDefaultQueueCallbackW, Context,
NULL, NULL);
if (ret == FALSE)
{
DPRINT1("SetupInstallFromInfSectionW(%S) failed (Error %lx)\n", InfSection, GetLastError());
goto cleanup;
}
wcscpy(Buffer, InfSection);
wcscat(Buffer, L".Services");
ret = SetupInstallServicesFromInfSectionW(hInf, Buffer, 0);
if (ret == FALSE)
{
DPRINT1("SetupInstallServicesFromInfSectionW(%S) failed (Error %lx)\n", Buffer, GetLastError());
goto cleanup;
}
cleanup:
if (Context)
SetupTermDefaultQueueCallback(Context);
if (hInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(hInf);
DPRINT("InstallInfSections() done %u\n", ret);
return ret;
}
static
BOOL
CreateInstanceKey(
_In_ PCOMPONENT_INFO pComponentInfo,
_Out_ PHKEY pInstanceKey)
{
WCHAR szKeyBuffer[128];
LPWSTR UuidString = NULL;
UUID Uuid;
RPC_STATUS RpcStatus;
HKEY hInstanceKey;
DWORD rc;
BOOL ret = FALSE;
DPRINT("CreateInstanceKey()\n");
*pInstanceKey = NULL;
wcscpy(szKeyBuffer, L"SYSTEM\\CurrentControlSet\\Control\\Network\\");
wcscat(szKeyBuffer, pComponentInfo->pszClassGuid);
wcscat(szKeyBuffer, L"\\{");
/* Create a new UUID */
RpcStatus = UuidCreate(&Uuid);
if (RpcStatus != RPC_S_OK && RpcStatus != RPC_S_UUID_LOCAL_ONLY)
{
DPRINT1("UuidCreate() failed with RPC status 0x%lx\n", RpcStatus);
goto done;
}
RpcStatus = UuidToStringW(&Uuid, &UuidString);
if (RpcStatus != RPC_S_OK)
{
DPRINT1("UuidToStringW() failed with RPC status 0x%lx\n", RpcStatus);
goto done;
}
wcscat(szKeyBuffer, UuidString);
wcscat(szKeyBuffer, L"}");
RpcStringFreeW(&UuidString);
DPRINT("szKeyBuffer %S\n", szKeyBuffer);
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
szKeyBuffer,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
NULL,
&hInstanceKey,
NULL);
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegCreateKeyExW() failed with error 0x%lx\n", rc);
goto done;
}
rc = RegSetValueExW(hInstanceKey,
L"Characteristics",
0,
REG_DWORD,
(LPBYTE)&pComponentInfo->dwCharacteristics,
sizeof(DWORD));
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
rc = RegSetValueExW(hInstanceKey,
L"ComponentId",
0,
REG_SZ,
(LPBYTE)pComponentInfo->pszComponentId,
(wcslen(pComponentInfo->pszComponentId) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
rc = RegSetValueExW(hInstanceKey,
L"Description",
0,
REG_SZ,
(LPBYTE)pComponentInfo->pszDescription,
(wcslen(pComponentInfo->pszDescription) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
rc = RegSetValueExW(hInstanceKey,
L"InfPath",
0,
REG_SZ,
(LPBYTE)pComponentInfo->pszInfPath,
(wcslen(pComponentInfo->pszInfPath) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
rc = RegSetValueExW(hInstanceKey,
L"InfSection",
0,
REG_SZ,
(LPBYTE)pComponentInfo->pszInfSection,
(wcslen(pComponentInfo->pszInfSection) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
DPRINT1("RegSetValueExW() failed with error 0x%lx\n", rc);
goto done;
}
*pInstanceKey = hInstanceKey;
ret = TRUE;
done:
if (ret == FALSE)
RegCloseKey(hInstanceKey);
DPRINT("CreateInstanceKey() done %u\n", ret);
return ret;
}
static
BOOL
CheckInfFile(
_In_ PWSTR pszFullInfName,
_In_ PWSTR pszComponentId,
_In_ PCOMPONENT_INFO pComponentInfo)
{
WCHAR szLineBuffer[MAX_PATH];
HINF hInf = INVALID_HANDLE_VALUE;
INFCONTEXT MfgContext, DevContext, MiscContext;
DWORD dwLength;
hInf = SetupOpenInfFileW(pszFullInfName,
NULL,
INF_STYLE_WIN4,
NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
DPRINT1("\n");
return FALSE;
}
if (!SetupFindFirstLineW(hInf,
L"Manufacturer",
NULL,
&MfgContext))
{
DPRINT("No Manufacurer section found!\n");
goto done;
}
for (;;)
{
if (!SetupGetStringFieldW(&MfgContext,
1,
szLineBuffer,
MAX_PATH,
NULL))
break;
DPRINT("Manufacturer: %S\n", szLineBuffer);
if (!SetupFindFirstLineW(hInf,
szLineBuffer,
NULL,
&DevContext))
break;
for (;;)
{
if (!SetupGetStringFieldW(&DevContext,
2,
szLineBuffer,
MAX_PATH,
NULL))
break;
DPRINT("Device: %S\n", szLineBuffer);
if (_wcsicmp(szLineBuffer, pszComponentId) == 0)
{
DPRINT("Found it!\n");
/* Get the section name*/
SetupGetStringFieldW(&DevContext,
1,
NULL,
0,
&dwLength);
pComponentInfo->pszInfSection = HeapAlloc(GetProcessHeap(),
0,
dwLength * sizeof(WCHAR));
if (pComponentInfo->pszInfSection)
{
SetupGetStringFieldW(&DevContext,
1,
pComponentInfo->pszInfSection,
dwLength,
&dwLength);
}
/* Get the description*/
SetupGetStringFieldW(&DevContext,
0,
NULL,
0,
&dwLength);
pComponentInfo->pszDescription = HeapAlloc(GetProcessHeap(),
0,
dwLength * sizeof(WCHAR));
if (pComponentInfo->pszDescription)
{
SetupGetStringFieldW(&DevContext,
0,
pComponentInfo->pszDescription,
dwLength,
&dwLength);
}
/* Get the class GUID */
if (SetupFindFirstLineW(hInf,
L"Version",
L"ClassGuid",
&MiscContext))
{
SetupGetStringFieldW(&MiscContext,
1,
NULL,
0,
&dwLength);
pComponentInfo->pszClassGuid = HeapAlloc(GetProcessHeap(),
0,
dwLength * sizeof(WCHAR));
if (pComponentInfo->pszInfSection)
{
SetupGetStringFieldW(&MiscContext,
1,
pComponentInfo->pszClassGuid,
dwLength,
&dwLength);
}
}
/* Get the Characteristics value */
if (SetupFindFirstLineW(hInf,
pComponentInfo->pszInfSection,
L"Characteristics",
&MiscContext))
{
SetupGetIntField(&MiscContext,
1,
(PINT)&pComponentInfo->dwCharacteristics);
}
SetupCloseInfFile(hInf);
return TRUE;
}
if (!SetupFindNextLine(&DevContext, &DevContext))
break;
}
if (!SetupFindNextLine(&MfgContext, &MfgContext))
break;
}
done:
if (hInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(hInf);
return FALSE;
}
static
BOOL
ScanForInfFile(
_In_ PWSTR pszComponentId,
_In_ PCOMPONENT_INFO pComponentInfo)
{
WCHAR szInfPath[MAX_PATH];
WCHAR szFullInfName[MAX_PATH];
WCHAR szPathBuffer[MAX_PATH];
WIN32_FIND_DATAW fdw;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
BOOL bFound = FALSE;
GetWindowsDirectoryW(szInfPath, MAX_PATH);
wcscat(szInfPath, L"\\inf");
wcscpy(szPathBuffer, szInfPath);
wcscat(szPathBuffer, L"\\*.inf");
hFindFile = FindFirstFileW(szPathBuffer, &fdw);
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
for (;;)
{
if (wcscmp(fdw.cFileName, L".") == 0 ||
wcscmp(fdw.cFileName, L"..") == 0)
continue;
DPRINT("FileName: %S\n", fdw.cFileName);
wcscpy(szFullInfName, szInfPath);
wcscat(szFullInfName, L"\\");
wcscat(szFullInfName, fdw.cFileName);
DPRINT("Full Inf Name: %S\n", szFullInfName);
if (CheckInfFile(szFullInfName,
pszComponentId,
pComponentInfo))
{
pComponentInfo->pszInfPath = HeapAlloc(GetProcessHeap(),
0,
(wcslen(fdw.cFileName) + 1) * sizeof(WCHAR));
if (pComponentInfo->pszInfPath)
wcscpy(pComponentInfo->pszInfPath, fdw.cFileName);
pComponentInfo->pszComponentId = HeapAlloc(GetProcessHeap(),
0,
(wcslen(pszComponentId) + 1) * sizeof(WCHAR));
if (pComponentInfo->pszComponentId)
wcscpy(pComponentInfo->pszComponentId, pszComponentId);
bFound = TRUE;
break;
}
if (!FindNextFileW(hFindFile, &fdw))
break;
}
if (hFindFile != INVALID_HANDLE_VALUE)
FindClose(hFindFile);
return bFound;
}
BOOL
InstallNetworkComponent(
_In_ PWSTR pszComponentId)
{
COMPONENT_INFO ComponentInfo;
HKEY hInstanceKey = NULL;
BOOL bResult = FALSE;
DPRINT("InstallNetworkComponent(%S)\n", pszComponentId);
ZeroMemory(&ComponentInfo, sizeof(COMPONENT_INFO));
if (!ScanForInfFile(pszComponentId, &ComponentInfo))
goto done;
DPRINT("Characteristics: 0x%lx\n", ComponentInfo.dwCharacteristics);
DPRINT("ComponentId: %S\n", ComponentInfo.pszComponentId);
DPRINT("Description: %S\n", ComponentInfo.pszDescription);
DPRINT("InfPath: %S\n", ComponentInfo.pszInfPath);
DPRINT("InfSection: %S\n", ComponentInfo.pszInfSection);
DPRINT("ClassGuid: %S\n", ComponentInfo.pszClassGuid);
if (!CreateInstanceKey(&ComponentInfo,
&hInstanceKey))
{
DPRINT1("CreateInstanceKey() failed (Error %lx)\n", GetLastError());
goto done;
}
if (!InstallInfSections(NULL,
hInstanceKey,
ComponentInfo.pszInfPath,
ComponentInfo.pszInfSection))
{
DPRINT1("InstallInfSections() failed (Error %lx)\n", GetLastError());
goto done;
}
bResult = TRUE;
done:
if (hInstanceKey != NULL)
RegCloseKey(hInstanceKey);
if (ComponentInfo.pszInfPath)
HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfPath);
if (ComponentInfo.pszInfSection)
HeapFree(GetProcessHeap(), 0, ComponentInfo.pszInfSection);
if (ComponentInfo.pszComponentId)
HeapFree(GetProcessHeap(), 0, ComponentInfo.pszComponentId);
if (ComponentInfo.pszDescription)
HeapFree(GetProcessHeap(), 0, ComponentInfo.pszDescription);
if (ComponentInfo.pszClassGuid)
HeapFree(GetProcessHeap(), 0, ComponentInfo.pszClassGuid);
return bResult;
}
/* EOF */

View file

@ -11,22 +11,23 @@ ClassGUID = {4D36E975-E325-11CE-BFC1-08002BE10318}
Provider = %ReactOS%
DriverVer = 04/12/2006,1.00
[Manufacturer]
%ReactOS% = ReactOS
[ReactOS]
%MS_TCPIP.DisplayName% = MS_TCPIP.PrimaryInstall, MS_TCPIP
;----------------------------- TCP/IPv4 DRIVER ----------------------------
[MS_TCPIP.PrimaryInstall]
Characteristics = 0xA0
AddReg = TCPIP_AddReg_Global.NT
[TCPIP_AddReg_Global.NT]
; The following entries should be generated from .inf files during installation
; TCPIPv4 Protocol
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}","Characteristics",0x00010001,0x00000080
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}","ComponentId",0x00000000,"ms_tcpip"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}","Description",0x00000000,"Internet Protocol Version 4 (TCP/IPv4)"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}","InfPath",0x00000000,"BUGBUG_Create from Inffile.inf"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}","InfSection",0x00000000,"BUGBUG_Create from Inffile.inf"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}\Ndi","ClsId",0x00000000,"{A907657F-6FDF-11D0-8EFB-00C04FD912B2}"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}\Ndi","HelpText",0x00000000,"Transmission Control Protocol/Internet Protocol"
HKLM,"SYSTEM\CurrentControlSet\Control\Network\{4D36E975-E325-11CE-BFC1-08002BE10318}\{RandomProtocolGUID_TCPIP}\Ndi","Service",0x00000000,"Tcpip"
HKR,"Ndi","ClsId",0x00000000,"{A907657F-6FDF-11D0-8EFB-00C04FD912B2}"
HKR,"Ndi","HelpText",0x00000000,"Transmission Control Protocol/Internet Protocol"
HKR,"Ndi","Service",0x00000000,"Tcpip"
HKR,"Ndi","CoServices",0x00010000,"Tcpip","Dhcp"
; TCP/IPv4 driver
; NOTE: These settings should be added by the network setup
@ -278,6 +279,7 @@ HKR,"Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dhcpcsvc.dll"
[Strings]
ReactOS = "ReactOS Team"
MS_TCPIP.DisplayName = "Internet Protocol Version 4 (TCP/IPv4)"
[Strings.0a]
ReactOS = "Equipo de ReactOS"