[NETSH] Add the pfnOsVersionCheck function to the internal data structures and retrieve the WMI version information

This commit is contained in:
Eric Kohl
2026-06-30 23:14:18 +02:00
parent e21afa5b21
commit e848ce1c52
5 changed files with 347 additions and 34 deletions
@@ -8,6 +8,7 @@ list(APPEND SOURCE
helper.c
interpreter.c
netsh.c
wmi.c
precomp.h
${CMAKE_CURRENT_BINARY_DIR}/netsh_stubs.c)
@@ -21,5 +22,5 @@ set_target_properties(netsh
set_module_type(netsh win32cui UNICODE)
target_link_libraries(netsh conutils)
add_importlibs(netsh iphlpapi advapi32 msvcrt kernel32 ntdll)
add_importlibs(netsh ole32 oleaut32 iphlpapi advapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET netsh DESTINATION reactos/system32 FOR all)
+43 -33
View File
@@ -104,7 +104,8 @@ AddContextCommand(
PFN_HANDLE_CMD pfnCmdHandler,
DWORD dwShortCmdHelpToken,
DWORD dwCmdHlpToken,
DWORD dwFlags)
DWORD dwFlags,
PNS_OSVERSIONCHECK pfnOsVersionCheck)
{
PCOMMAND_ENTRY pEntry;
@@ -131,6 +132,7 @@ AddContextCommand(
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
pEntry->dwCmdHlpToken = dwCmdHlpToken;
pEntry->dwFlags = dwFlags;
pEntry->pfnOsVersionCheck = pfnOsVersionCheck;
if (pContext->pCommandListHead == NULL && pContext->pCommandListTail == NULL)
{
@@ -153,7 +155,8 @@ AddCommandGroup(
PCONTEXT_ENTRY pContext,
LPCWSTR pwszCmdGroupToken,
DWORD dwShortCmdHelpToken,
DWORD dwFlags)
DWORD dwFlags,
PNS_OSVERSIONCHECK pfnOsVersionCheck)
{
PCOMMAND_GROUP pEntry;
@@ -176,6 +179,7 @@ AddCommandGroup(
wcscpy((LPWSTR)pEntry->pwszCmdGroupToken, pwszCmdGroupToken);
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
pEntry->dwFlags = dwFlags;
pEntry->pfnOsVersionCheck = pfnOsVersionCheck;
if (pContext->pGroupListHead == NULL && pContext->pGroupListTail == NULL)
{
@@ -200,7 +204,8 @@ AddGroupCommand(
PFN_HANDLE_CMD pfnCmdHandler,
DWORD dwShortCmdHelpToken,
DWORD dwCmdHlpToken,
DWORD dwFlags)
DWORD dwFlags,
PNS_OSVERSIONCHECK pfnOsVersionCheck)
{
PCOMMAND_ENTRY pEntry;
@@ -227,6 +232,7 @@ AddGroupCommand(
pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken;
pEntry->dwCmdHlpToken = dwCmdHlpToken;
pEntry->dwFlags = dwFlags;
pEntry->pfnOsVersionCheck = pfnOsVersionCheck;
if (pGroup->pCommandListHead == NULL && pGroup->pCommandListTail == NULL)
{
@@ -813,48 +819,48 @@ CreateRootContext(VOID)
pRootContext->hModule = g_hModule;
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0);
AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"abort", AbortCommand, IDS_HLP_ABORT, IDS_HLP_ABORT_EX, 0);
AddContextCommand(pRootContext, L"alias", AliasCommand, IDS_HLP_ALIAS, IDS_HLP_ALIAS_EX, 0);
AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"commit", CommitCommand, IDS_HLP_COMMIT, IDS_HLP_COMMIT_EX, 0);
AddContextCommand(pRootContext, L"dump", DumpCommand, IDS_HLP_DUMP, IDS_HLP_DUMP_EX, 0);
AddContextCommand(pRootContext, L"exec", ExecCommand, IDS_HLP_EXEC, IDS_HLP_EXEC_EX, 0);
AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"help", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0);
AddContextCommand(pRootContext, L"offline", OfflineCommand, IDS_HLP_OFFLINE, IDS_HLP_OFFLINE_EX, 0);
AddContextCommand(pRootContext, L"online", OnlineCommand, IDS_HLP_ONLINE, IDS_HLP_ONLINE_EX, 0);
AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0);
AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0);
AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0);
AddContextCommand(pRootContext, L"unalias", UnaliasCommand, IDS_HLP_UNALIAS, IDS_HLP_UNALIAS_EX, 0);
AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0, NULL);
AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0, NULL);
AddContextCommand(pRootContext, L"abort", AbortCommand, IDS_HLP_ABORT, IDS_HLP_ABORT_EX, 0, NULL);
AddContextCommand(pRootContext, L"alias", AliasCommand, IDS_HLP_ALIAS, IDS_HLP_ALIAS_EX, 0, NULL);
AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0, NULL);
AddContextCommand(pRootContext, L"commit", CommitCommand, IDS_HLP_COMMIT, IDS_HLP_COMMIT_EX, 0, NULL);
AddContextCommand(pRootContext, L"dump", DumpCommand, IDS_HLP_DUMP, IDS_HLP_DUMP_EX, 0, NULL);
AddContextCommand(pRootContext, L"exec", ExecCommand, IDS_HLP_EXEC, IDS_HLP_EXEC_EX, 0, NULL);
AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0, NULL);
AddContextCommand(pRootContext, L"help", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0, NULL);
AddContextCommand(pRootContext, L"offline", OfflineCommand, IDS_HLP_OFFLINE, IDS_HLP_OFFLINE_EX, 0, NULL);
AddContextCommand(pRootContext, L"online", OnlineCommand, IDS_HLP_ONLINE, IDS_HLP_ONLINE_EX, 0, NULL);
AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0, NULL);
AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0, NULL);
AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0, NULL);
AddContextCommand(pRootContext, L"unalias", UnaliasCommand, IDS_HLP_UNALIAS, IDS_HLP_UNALIAS_EX, 0, NULL);
pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0);
pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0, NULL);
if (pGroup)
{
AddGroupCommand(pGroup, L"helper", AddHelperCommand, IDS_HLP_ADD_HELPER, IDS_HLP_ADD_HELPER_EX, 0);
AddGroupCommand(pGroup, L"helper", AddHelperCommand, IDS_HLP_ADD_HELPER, IDS_HLP_ADD_HELPER_EX, 0, NULL);
}
pGroup = AddCommandGroup(pRootContext, L"delete", IDS_HLP_GROUP_DELETE, 0);
pGroup = AddCommandGroup(pRootContext, L"delete", IDS_HLP_GROUP_DELETE, 0, NULL);
if (pGroup)
{
AddGroupCommand(pGroup, L"helper", DeleteHelperCommand, IDS_HLP_DEL_HELPER, IDS_HLP_DEL_HELPER_EX, 0);
AddGroupCommand(pGroup, L"helper", DeleteHelperCommand, IDS_HLP_DEL_HELPER, IDS_HLP_DEL_HELPER_EX, 0, NULL);
}
pGroup = AddCommandGroup(pRootContext, L"set", IDS_HLP_GROUP_SET, 0);
pGroup = AddCommandGroup(pRootContext, L"set", IDS_HLP_GROUP_SET, 0, NULL);
if (pGroup)
{
AddGroupCommand(pGroup, L"machine", SetMachineCommand, IDS_HLP_SET_MACHINE, IDS_HLP_SET_MACHINE_EX, 0);
AddGroupCommand(pGroup, L"mode", SetModeCommand, IDS_HLP_SET_MODE, IDS_HLP_SET_MODE_EX, 0);
AddGroupCommand(pGroup, L"machine", SetMachineCommand, IDS_HLP_SET_MACHINE, IDS_HLP_SET_MACHINE_EX, 0, NULL);
AddGroupCommand(pGroup, L"mode", SetModeCommand, IDS_HLP_SET_MODE, IDS_HLP_SET_MODE_EX, 0, NULL);
}
pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0);
pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0, NULL);
if (pGroup)
{
AddGroupCommand(pGroup, L"alias", ShowAliasCommand, IDS_HLP_SHOW_ALIAS, IDS_HLP_SHOW_ALIAS_EX, 0);
AddGroupCommand(pGroup, L"helper", ShowHelperCommand, IDS_HLP_SHOW_HELPER, IDS_HLP_SHOW_HELPER_EX, 0);
AddGroupCommand(pGroup, L"mode", ShowModeCommand, IDS_HLP_SHOW_MODE, IDS_HLP_SHOW_MODE_EX, 0);
AddGroupCommand(pGroup, L"alias", ShowAliasCommand, IDS_HLP_SHOW_ALIAS, IDS_HLP_SHOW_ALIAS_EX, 0, NULL);
AddGroupCommand(pGroup, L"helper", ShowHelperCommand, IDS_HLP_SHOW_HELPER, IDS_HLP_SHOW_HELPER_EX, 0, NULL);
AddGroupCommand(pGroup, L"mode", ShowModeCommand, IDS_HLP_SHOW_MODE, IDS_HLP_SHOW_MODE_EX, 0, NULL);
}
pCurrentContext = pRootContext;
@@ -952,6 +958,7 @@ RegisterContext(
pContext->pfnCommitFn = pChildContext->pfnCommitFn;
pContext->pfnDumpFn = pChildContext->pfnDumpFn;
pContext->pfnConnectFn = pChildContext->pfnConnectFn;
pContext->pfnOsVersionCheck = pChildContext->pfnOsVersionCheck;
pContext->ulPriority = (pChildContext->dwFlags & CMD_FLAG_PRIORITY) ?
pChildContext->ulPriority : DEFAULT_CONTEXT_PRIORITY;
@@ -967,7 +974,8 @@ RegisterContext(
pChildContext->pTopCmds[i].pfnCmdHandler,
pChildContext->pTopCmds[i].dwShortCmdHelpToken,
pChildContext->pTopCmds[i].dwCmdHlpToken,
pChildContext->pTopCmds[i].dwFlags);
pChildContext->pTopCmds[i].dwFlags,
pChildContext->pTopCmds[i].pOsVersionCheck);
}
/* Add command groups */
@@ -976,7 +984,8 @@ RegisterContext(
pGroup = AddCommandGroup(pContext,
pChildContext->pCmdGroups[i].pwszCmdGroupToken,
pChildContext->pCmdGroups[i].dwShortCmdHelpToken,
pChildContext->pCmdGroups[i].dwFlags);
pChildContext->pCmdGroups[i].dwFlags,
pChildContext->pCmdGroups[i].pOsVersionCheck);
if (pGroup != NULL)
{
for (j = 0; j < pChildContext->pCmdGroups[i].ulCmdGroupSize; j++)
@@ -986,7 +995,8 @@ RegisterContext(
pChildContext->pCmdGroups[i].pCmdGroup[j].pfnCmdHandler,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwShortCmdHelpToken,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwCmdHlpToken,
pChildContext->pCmdGroups[i].pCmdGroup[j].dwFlags);
pChildContext->pCmdGroups[i].pCmdGroup[j].dwFlags,
pChildContext->pCmdGroups[i].pCmdGroup[j].pOsVersionCheck);
}
}
}
+2
View File
@@ -101,6 +101,8 @@ wmain(
DPRINT("wmain(%S)\n", GetCommandLineW());
GetWmiVersionInfo();
g_hModule = GetModuleHandle(NULL);
/* Initialize the Console Standard Streams */
+17
View File
@@ -80,6 +80,7 @@ typedef struct _COMMAND_ENTRY
DWORD dwShortCmdHelpToken;
DWORD dwCmdHlpToken;
DWORD dwFlags;
PNS_OSVERSIONCHECK pfnOsVersionCheck;
} COMMAND_ENTRY, *PCOMMAND_ENTRY;
typedef struct _COMMAND_GROUP
@@ -90,6 +91,7 @@ typedef struct _COMMAND_GROUP
PWSTR pwszCmdGroupToken;
DWORD dwShortCmdHelpToken;
DWORD dwFlags;
PNS_OSVERSIONCHECK pfnOsVersionCheck;
PCOMMAND_ENTRY pCommandListHead;
PCOMMAND_ENTRY pCommandListTail;
@@ -110,6 +112,7 @@ typedef struct _CONTEXT_ENTRY
PNS_CONTEXT_COMMIT_FN pfnCommitFn;
PNS_CONTEXT_DUMP_FN pfnDumpFn;
PNS_CONTEXT_CONNECT_FN pfnConnectFn;
PNS_OSVERSIONCHECK pfnOsVersionCheck;
PCOMMAND_ENTRY pCommandListHead;
PCOMMAND_ENTRY pCommandListTail;
@@ -132,6 +135,15 @@ extern PHELPER_ENTRY pHelperListHead;
extern HMODULE g_hModule;
extern PWSTR pszMachine;
extern UINT VersionInfoArchitecture;
extern UINT VersionInfoOsProductSuite;
extern UINT VersionInfoOsType;
extern UINT VersionInfoVersion;
extern WCHAR VersionInfoBuildNumber[MAX_PATH];
extern WCHAR VersionInfoServicePackMajorVersion[MAX_PATH];
extern WCHAR VersionInfoServicePackMinorVersion[MAX_PATH];
/* PROTOTYPES *****************************************************************/
/* alias.c */
@@ -273,3 +285,8 @@ LPWSTR
MergeStrings(
_In_ LPWSTR pszStringArray[],
_In_ UINT nCount);
/* wmi.c */
HRESULT
GetWmiVersionInfo(VOID);
+283
View File
@@ -0,0 +1,283 @@
/*
* PROJECT: ReactOS NetSh
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Network Shell WMI info functions
* COPYRIGHT: Copyright 2026 Eric Kohl <[email protected]>
*/
/* INCLUDES *******************************************************************/
#define COBJMACROS
#include "precomp.h"
#include <strsafe.h>
#include <initguid.h>
#include <objbase.h>
#include <wbemcli.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
UINT VersionInfoArchitecture;
UINT VersionInfoOsProductSuite;
UINT VersionInfoOsType;
UINT VersionInfoVersion;
WCHAR VersionInfoBuildNumber[MAX_PATH];
WCHAR VersionInfoServicePackMajorVersion[MAX_PATH];
WCHAR VersionInfoServicePackMinorVersion[MAX_PATH];
/* FUNCTIONS ******************************************************************/
static
HRESULT
QueryOperatingSystemInfo(
_In_ IWbemServices *Services)
{
IEnumWbemClassObject *Result = NULL;
IWbemClassObject *Object = NULL;
BSTR Wql = NULL;
BSTR Query = NULL;
BSTR Name;
CIMTYPE Type;
ULONG Count;
VARIANT Value;
HRESULT hr;
Wql = SysAllocString(L"WQL");
if (Wql == NULL)
return E_OUTOFMEMORY;
Query = SysAllocString(L"SELECT * FROM Win32_OperatingSystem");
if (Query == NULL)
{
hr = E_OUTOFMEMORY;
goto done;
}
hr = IWbemServices_ExecQuery(Services, Wql, Query, 0, NULL, &Result);
if (hr != S_OK)
{
DPRINT1("IWbemServices_ExecQuery failed %08x\n", hr);
goto done;
}
hr = IEnumWbemClassObject_Next(Result, 10000, 1, &Object, &Count);
if (hr != S_OK)
{
DPRINT1("IEnumWbemClassObject_Next failed %08x\n", hr);
goto done;
}
hr = IWbemClassObject_BeginEnumeration(Object, 0);
if (hr != S_OK)
{
DPRINT1("IWbemClassObject_BeginEnumeration returned %08x\n", hr);
goto done;
}
while (IWbemClassObject_Next(Object, 0, &Name, &Value, &Type, NULL) == S_OK)
{
DPRINT1("Name: %S\n", Name);
if (_wcsicmp(Name, L"BuildNumber") == 0)
{
DPRINT1("BuildNumber %S\n", V_BSTR(&Value));
StringCbCopyW(VersionInfoBuildNumber, sizeof(VersionInfoBuildNumber), V_BSTR(&Value));
}
else if (_wcsicmp(Name, L"OSProductSuite") == 0)
{
DPRINT1("OSProductSuite 0x%x\n", V_UINT(&Value));
VersionInfoOsProductSuite = V_UINT(&Value);
}
else if (_wcsicmp(Name, L"OSType") == 0)
{
DPRINT1("OSType %u\n", V_UINT(&Value));
VersionInfoOsType = V_UINT(&Value);
}
else if (_wcsicmp(Name, L"ServicePackMajorVersion") == 0)
{
DPRINT1("ServicePackMajorVersion %S\n", V_BSTR(&Value));
StringCbCopyW(VersionInfoServicePackMajorVersion, sizeof(VersionInfoServicePackMajorVersion), V_BSTR(&Value));
}
else if (_wcsicmp(Name, L"ServicePackMinorVersion") == 0)
{
DPRINT1("ServicePackMinorVersion %S\n", V_BSTR(&Value));
StringCbCopyW(VersionInfoServicePackMinorVersion, sizeof(VersionInfoServicePackMinorVersion), V_BSTR(&Value));
}
else if (_wcsicmp(Name, L"Version") == 0)
{
DPRINT1("Version %S\n", V_BSTR(&Value));
VersionInfoVersion = V_UINT(&Value);
}
SysFreeString(Name);
VariantClear(&Value);
}
hr = IWbemClassObject_EndEnumeration(Object);
if (hr != S_OK)
{
DPRINT1("got %08x\n", hr);
goto done;
}
done:
if (Object)
IWbemClassObject_Release(Object);
if (Result)
IEnumWbemClassObject_Release(Result);
if (Query)
SysFreeString(Query);
if (Wql)
SysFreeString(Wql);
return hr;
}
static
HRESULT
QueryProcessorInfo(
_In_ IWbemServices *Services)
{
IEnumWbemClassObject *Result = NULL;
IWbemClassObject *Object = NULL;
BSTR Wql = NULL;
BSTR Query = NULL;
BSTR Name;
CIMTYPE Type;
ULONG Count;
VARIANT Value;
HRESULT hr;
Wql = SysAllocString(L"WQL");
if (Wql == NULL)
return E_OUTOFMEMORY;
Query = SysAllocString(L"SELECT * FROM Win32_Processor");
if (Query == NULL)
{
hr = E_OUTOFMEMORY;
goto done;
}
hr = IWbemServices_ExecQuery(Services, Wql, Query, 0, NULL, &Result);
if (hr != S_OK)
{
DPRINT1("IWbemServices_ExecQuery failed %08x\n", hr);
goto done;
}
hr = IEnumWbemClassObject_Next(Result, 10000, 1, &Object, &Count);
if (hr != S_OK)
{
DPRINT1("IEnumWbemClassObject_Next failed %08x\n", hr);
goto done;
}
hr = IWbemClassObject_BeginEnumeration(Object, 0);
if (hr != S_OK)
{
DPRINT1("IWbemClassObject_BeginEnumeration returned %08x\n", hr);
goto done;
}
while (IWbemClassObject_Next(Object, 0, &Name, &Value, &Type, NULL) == S_OK)
{
DPRINT1("Name: %S\n", Name);
if (_wcsicmp(Name, L"Architecture") == 0)
{
DPRINT1("Architecture %u\n", V_UINT(&Value));
}
SysFreeString(Name);
VariantClear(&Value);
}
hr = IWbemClassObject_EndEnumeration(Object);
if (hr != S_OK)
{
DPRINT1("got %08x\n", hr);
goto done;
}
done:
if (Object)
IWbemClassObject_Release(Object);
if (Result)
IEnumWbemClassObject_Release(Result);
if (Query)
SysFreeString(Query);
if (Wql)
SysFreeString(Wql);
return hr;
}
HRESULT
GetWmiVersionInfo(VOID)
{
BSTR Path = NULL;
IWbemLocator *Locator = NULL;
IWbemServices *Services = NULL;
HRESULT hr;
CoInitialize(NULL);
CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
hr = CoCreateInstance(&CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
&IID_IWbemLocator, (void **)&Locator);
if (hr != S_OK)
{
DPRINT1("Can't create instance of WbemLocator\n");
return hr;
}
Path = SysAllocString(L"ROOT\\CIMV2");
if (Path == NULL)
{
hr = E_OUTOFMEMORY;
goto done;
}
hr = IWbemLocator_ConnectServer(Locator, Path, NULL, NULL, NULL, 0, NULL, NULL, &Services);
if (hr != S_OK)
{
DPRINT1("Failed to get IWbemServices interface %08x\n", hr);
goto done;
}
hr = CoSetProxyBlanket((IUnknown *)Services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (hr != S_OK)
{
DPRINT1("Failed to set proxy blanket %08x\n", hr);
goto done;
}
hr = QueryOperatingSystemInfo(Services);
hr = QueryProcessorInfo(Services);
done:
if (Path)
SysFreeString(Path);
if (Services)
IWbemServices_Release(Services);
if (Locator)
IWbemLocator_Release(Locator);
CoUninitialize();
return hr;
}