mirror of
https://github.com/arehnman/yttrium-virtio-gpu.git
synced 2026-10-31 02:05:04 +00:00
netkvmco.h becomes interface file between static lib and the application that uses it. The application should call start and stop procedures of the helper and resolve missing procedures that previously were in netsh.lib Signed-off-by: Yuri Benditovich <[email protected]>
1349 lines
48 KiB
C++
1349 lines
48 KiB
C++
#include "stdafx.h"
|
|
#include "NetKVMnetsh.h"
|
|
#include "RegAccess.h"
|
|
#include "NetKVMAux.h"
|
|
#include "RegParam.h"
|
|
|
|
//This is NetSH Helper GUID {D9C599C4-8DCF-4a6a-93AA-A16FE6D5125C}
|
|
static const GUID NETKVM_HELPER_GUID =
|
|
{ 0xd9c599c4, 0x8dcf, 0x4a6a, { 0x93, 0xaa, 0xa1, 0x6f, 0xe6, 0xd5, 0x12, 0x5c } };
|
|
static const DWORD NETKVM_HELPER_VERSION = 1;
|
|
|
|
static const LPCTSTR NETKVM_HELPER_NAME = TEXT("NetKVM");
|
|
static const LPWSTR NETKVM_HELPER_NAME_W = L"NetKVM";
|
|
|
|
static const LPCTSTR NETKVM_DEVICES_CLASS = TEXT("net");
|
|
|
|
//TODO: put real device numbers here
|
|
static const LPCTSTR NETKVM_DEVICE_VENDOR_ID = TEXT("");
|
|
static const LPCTSTR NETKVM_DEVICE_HARDWARE_ID = TEXT("");
|
|
|
|
static const LPCWSTR NETKVM_IDX_PARAM_NAME = L"idx";
|
|
static const LPCTSTR NETKVM_IDX_PARAM_NAME_T = TEXT("idx");
|
|
static const LPCWSTR NETKVM_PARAM_PARAM_NAME = L"param";
|
|
static const LPCTSTR NETKVM_PARAM_PARAM_NAME_T = TEXT("param");
|
|
static const LPCWSTR NETKVM_VALUE_PARAM_NAME = L"value";
|
|
static const LPCTSTR NETKVM_VALUE_PARAM_NAME_T = TEXT("value");
|
|
|
|
static HINSTANCE g_hinstThisDLL = NULL;
|
|
|
|
class CFileVersion
|
|
{
|
|
public:
|
|
CFileVersion(LPCTSTR Name)
|
|
{
|
|
ULONG size = GetFileVersionInfoSize(Name, NULL);
|
|
if (!size)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Can't get version info size for ") << Name);
|
|
return;
|
|
}
|
|
PVOID data = NULL;
|
|
data = malloc(size);
|
|
if (!data)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Can't alloc file version memory of ") << size);
|
|
return;
|
|
}
|
|
if (!GetFileVersionInfo(Name, NULL, size, data))
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Can't get file version, error ") << GetLastError());
|
|
free(data);
|
|
return;
|
|
}
|
|
VS_FIXEDFILEINFO* info;
|
|
UINT len;
|
|
if (!VerQueryValue(data, L"\\", (PVOID*)&info, &len))
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Can't get fixed file version, error ") << GetLastError());
|
|
free(data);
|
|
return;
|
|
}
|
|
m_Ver[3] = LOWORD(info->dwFileVersionLS);
|
|
m_Ver[2] = HIWORD(info->dwFileVersionLS);
|
|
m_Ver[1] = LOWORD(info->dwFileVersionMS);
|
|
m_Ver[0] = HIWORD(info->dwFileVersionMS);
|
|
m_Valid = true;
|
|
NETCO_DEBUG_PRINT(Name << ": version " << (ULONG)m_Ver[0] <<
|
|
"." << (ULONG)m_Ver[1] << "." << (ULONG)m_Ver[2] << "." << (ULONG)m_Ver[3]);
|
|
}
|
|
const USHORT* GetVersion()
|
|
{
|
|
return m_Valid ? m_Ver : NULL;
|
|
}
|
|
private:
|
|
USHORT m_Ver[4] = {};
|
|
bool m_Valid = false;
|
|
};
|
|
|
|
static bool _NetKVMGetDeviceClassGuids(vector<GUID>& GUIDs)
|
|
{
|
|
GUID *pguidDevClassPtr = NULL;
|
|
DWORD dwNumGuids;
|
|
|
|
if(!SetupDiClassGuidsFromNameEx(NETKVM_DEVICES_CLASS, NULL, 0,
|
|
&dwNumGuids, NULL, NULL))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if(ERROR_INSUFFICIENT_BUFFER == dwErr)
|
|
{
|
|
/* On first attempt we pass NULL and 0 as GUID array and GUID array size respectively;
|
|
according to SetupDiClassGuidsFromNameEx, the function sets RequiredSize output formal parameter (&dwNumGuids)
|
|
to the desired GUID's array size. The static analyzer indicates an error when output parameter from
|
|
failed function is used, so the warning is suppressed */
|
|
#pragma warning(suppress: 6102)
|
|
pguidDevClassPtr = new GUID[dwNumGuids];
|
|
}
|
|
else
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiClassGuidsFromNameEx failed with code ") << dwErr);
|
|
return false;
|
|
}
|
|
|
|
if(!SetupDiClassGuidsFromNameEx(NETKVM_DEVICES_CLASS, pguidDevClassPtr, dwNumGuids,
|
|
&dwNumGuids, NULL, NULL))
|
|
{
|
|
delete [] pguidDevClassPtr;
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiClassGuidsFromNameEx failed with code ") << dwErr);
|
|
return false;
|
|
}
|
|
|
|
GUIDs.insert(GUIDs.end(), &pguidDevClassPtr[0], &pguidDevClassPtr[dwNumGuids]);
|
|
delete[] pguidDevClassPtr;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
tstring _NetKVMQueryDeviceString(HDEVINFO hDeviceSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD dwPropertyID)
|
|
{
|
|
LPTSTR szDeviceString = NULL;
|
|
DWORD dwSize = 0;
|
|
DWORD dwDataType;
|
|
|
|
while(!SetupDiGetDeviceRegistryProperty(hDeviceSet, DeviceInfoData, dwPropertyID,
|
|
&dwDataType, (PBYTE)szDeviceString, dwSize, &dwSize))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if(ERROR_INSUFFICIENT_BUFFER != dwErr)
|
|
{
|
|
delete [] szDeviceString;
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetDeviceRegistryProperty failed with code ") << dwErr);
|
|
return tstring();
|
|
}
|
|
/* According to SetupDiGetDeviceRegistryProperty, the RequiredSize output parameter (&dwSize) is set
|
|
to the required size of PropertyBuffer (szDeviceString) parameter. The static analyzer indicates
|
|
error when the output parameter from failed function, so the warning is suppressed */
|
|
#pragma warning(suppress: 6102)
|
|
szDeviceString = new TCHAR[(dwSize/sizeof(TCHAR))+1];
|
|
}
|
|
if (REG_SZ != dwDataType)
|
|
{
|
|
#pragma warning(suppress: 6102)
|
|
delete[] szDeviceString;
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetDeviceRegistryProperty(string) returned incorrect data type ") << dwDataType);
|
|
return tstring();
|
|
}
|
|
|
|
#pragma warning(suppress: 6102)
|
|
#pragma warning(suppress: 6011)
|
|
szDeviceString[dwSize/sizeof(TCHAR)] = TEXT('\0');
|
|
return tstring(szDeviceString);
|
|
}
|
|
|
|
DWORD _NetKVMQueryDeviceDWORD(HDEVINFO hDeviceSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD dwPropertyID)
|
|
{
|
|
DWORD dwDeviceDword;
|
|
DWORD dwDataType;
|
|
|
|
if(!SetupDiGetDeviceRegistryProperty(hDeviceSet, DeviceInfoData, dwPropertyID,
|
|
&dwDataType, (PBYTE)&dwDeviceDword, sizeof(dwDeviceDword), NULL))
|
|
{
|
|
return 0;
|
|
}
|
|
if (REG_DWORD != dwDataType)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetDeviceRegistryProperty(DWORD) returned incorrect data type ") << REG_DWORD);
|
|
return 0;
|
|
}
|
|
#pragma warning(suppress: 6102)
|
|
return dwDeviceDword;
|
|
}
|
|
|
|
static HKEY _NetKVMOpenDeviceSwRegKey(HDEVINFO hDeviceSet, PSP_DEVINFO_DATA DeviceInfoData)
|
|
{
|
|
HKEY hRes = SetupDiOpenDevRegKey(hDeviceSet, DeviceInfoData, DICS_FLAG_GLOBAL,
|
|
0, DIREG_DRV, KEY_READ);
|
|
|
|
if(INVALID_HANDLE_VALUE == hRes)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_CANNOTOPENKEY);
|
|
tcout << TEXT("Error: ") << GetLastError() << endl;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
typedef struct tag_NetKVMDeviceInfo
|
|
{
|
|
tstring strDeviceID;
|
|
tstring strDeviceDescription;
|
|
tstring strDeviceFriendlyName;
|
|
tstring strLocationInfo;
|
|
tstring strRegPathName;
|
|
DWORD dwDeviceNumber;
|
|
SP_DEVINFO_DATA DevInfoData;
|
|
} _NetKVMDeviceInfo, *_PNetKVMDeviceInfo;
|
|
|
|
bool _NetKVMIsKnownDevice(const tstring &strDeviceID)
|
|
{
|
|
return (tstring::npos != strDeviceID.find(tstring(TEXT("VEN_")) + NETKVM_DEVICE_VENDOR_ID)) &&
|
|
(tstring::npos != strDeviceID.find(tstring(TEXT("DEV_")) + NETKVM_DEVICE_HARDWARE_ID));
|
|
}
|
|
|
|
tstring _NetKVMKeyPathFromDeviceSwHKEY(HKEY hKey)
|
|
{
|
|
tstring strNativePath = wstring2tstring(NetKVMGetKeyPathFromKKEY(hKey));
|
|
tstring strNativePrefix = TEXT("\\REGISTRY\\MACHINE\\");
|
|
if(strNativePath.substr(0, strNativePrefix.length()) == strNativePrefix)
|
|
{
|
|
return strNativePath.substr(strNativePrefix.length());
|
|
}
|
|
else return tstring();
|
|
}
|
|
|
|
|
|
static bool _NetKVMGetKnownDevices(GUID *pguidDevClassPtr, vector<_NetKVMDeviceInfo>& Devices, HDEVINFO *phDeviceInfo)
|
|
{
|
|
*phDeviceInfo = SetupDiGetClassDevsEx(pguidDevClassPtr, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
|
if(INVALID_HANDLE_VALUE == *phDeviceInfo)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
UNREFERENCED_PARAMETER(dwErr);
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetClassDevsEx failed with code ") << dwErr);
|
|
return false;
|
|
}
|
|
|
|
SP_DEVINFO_LIST_DETAIL_DATA DevListInfo;
|
|
DevListInfo.cbSize = sizeof(DevListInfo);
|
|
if(!SetupDiGetDeviceInfoListDetail(*phDeviceInfo, &DevListInfo))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
UNREFERENCED_PARAMETER(dwErr);
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetDeviceInfoListDetail failed with code ") << dwErr);
|
|
SetupDiDestroyDeviceInfoList(*phDeviceInfo);
|
|
return false;
|
|
}
|
|
|
|
SP_DEVINFO_DATA CurrDeviceInfo;
|
|
CurrDeviceInfo.cbSize = sizeof(CurrDeviceInfo);
|
|
for(DWORD dwDevIndex = 0; SetupDiEnumDeviceInfo(*phDeviceInfo, dwDevIndex, &CurrDeviceInfo); dwDevIndex++)
|
|
{
|
|
TCHAR szDeviceId[MAX_DEVICE_ID_LEN];
|
|
CONFIGRET err = CM_Get_Device_ID_Ex(CurrDeviceInfo.DevInst,
|
|
szDeviceId, MAX_DEVICE_ID_LEN,
|
|
0, DevListInfo.RemoteMachineHandle);
|
|
if(CR_SUCCESS == err)
|
|
{
|
|
if(_NetKVMIsKnownDevice(szDeviceId))
|
|
{
|
|
_NetKVMDeviceInfo ResDevInfo;
|
|
ResDevInfo.strDeviceID = szDeviceId;
|
|
ResDevInfo.strDeviceDescription = _NetKVMQueryDeviceString(*phDeviceInfo, &CurrDeviceInfo, SPDRP_DEVICEDESC);
|
|
ResDevInfo.strDeviceFriendlyName = _NetKVMQueryDeviceString(*phDeviceInfo, &CurrDeviceInfo, SPDRP_FRIENDLYNAME);
|
|
if (ResDevInfo.strDeviceFriendlyName.length() == 0)
|
|
{
|
|
ResDevInfo.strDeviceFriendlyName = ResDevInfo.strDeviceDescription;
|
|
}
|
|
ResDevInfo.strLocationInfo = _NetKVMQueryDeviceString(*phDeviceInfo, &CurrDeviceInfo, SPDRP_LOCATION_INFORMATION);
|
|
ResDevInfo.dwDeviceNumber = _NetKVMQueryDeviceDWORD(*phDeviceInfo, &CurrDeviceInfo, SPDRP_UI_NUMBER);
|
|
ResDevInfo.DevInfoData = CurrDeviceInfo;
|
|
HKEY hSoftwareRegKey = _NetKVMOpenDeviceSwRegKey(*phDeviceInfo, &CurrDeviceInfo);
|
|
if(INVALID_HANDLE_VALUE != hSoftwareRegKey)
|
|
{
|
|
ResDevInfo.strRegPathName = _NetKVMKeyPathFromDeviceSwHKEY(hSoftwareRegKey);
|
|
CloseHandle(hSoftwareRegKey);
|
|
if(!ResDevInfo.strRegPathName.empty())
|
|
Devices.push_back(ResDevInfo);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("CM_Get_Device_ID_Ex failed with code ") << err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
DWORD dwErr = GetLastError();
|
|
if(ERROR_NO_MORE_ITEMS != dwErr)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("SetupDiGetDeviceInfoListDetail failed with code ") << dwErr);
|
|
SetupDiDestroyDeviceInfoList(*phDeviceInfo);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static pair< HDEVINFO, vector<_NetKVMDeviceInfo> > _NetKVMGetDevicesOfInterest()
|
|
{
|
|
vector<GUID> GUIDs;
|
|
pair< HDEVINFO, vector<_NetKVMDeviceInfo> > Devices;
|
|
|
|
_NetKVMGetDeviceClassGuids(GUIDs);
|
|
if(GUIDs.empty())
|
|
return Devices;
|
|
|
|
_NetKVMGetKnownDevices(&GUIDs[0], Devices.second, &Devices.first);
|
|
return Devices;
|
|
}
|
|
|
|
void _NetKVMDumpDeviceInfo(DWORD dwIndex, const _NetKVMDeviceInfo &DeviceInfo)
|
|
{
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICEID);
|
|
tcout << TEXT(": ") << DeviceInfo.strDeviceID << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICEIDX);
|
|
tcout << TEXT(": ") << dwIndex << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICEDESC);
|
|
tcout << TEXT(": ") << DeviceInfo.strDeviceDescription << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICEFRNAME);
|
|
tcout << TEXT(": ") << DeviceInfo.strDeviceFriendlyName << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICELOCINFO);
|
|
tcout << TEXT(": ") << DeviceInfo.strLocationInfo << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICENUM);
|
|
tcout << TEXT(": ") << DeviceInfo.dwDeviceNumber << endl;
|
|
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DEVICEREGKEY);
|
|
tcout << TEXT(": ") << DeviceInfo.strRegPathName << endl << endl;
|
|
}
|
|
|
|
HDEVINFO g_hDeviceInfoList = INVALID_HANDLE_VALUE;
|
|
static vector<_NetKVMDeviceInfo> g_DevicesOfInterest;
|
|
|
|
static DWORD _NetKVMRestartDevice(DWORD dwIndex)
|
|
{
|
|
SP_PROPCHANGE_PARAMS Params;
|
|
Params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
|
Params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
|
Params.StateChange = DICS_PROPCHANGE;
|
|
Params.Scope = DICS_FLAG_CONFIGSPECIFIC;
|
|
Params.HwProfile = 0;
|
|
|
|
if(!SetupDiSetClassInstallParams(g_hDeviceInfoList,
|
|
&g_DevicesOfInterest[dwIndex].DevInfoData,
|
|
&Params.ClassInstallHeader,
|
|
sizeof(Params)))
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
if(!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
|
|
g_hDeviceInfoList,
|
|
&g_DevicesOfInterest[dwIndex].DevInfoData))
|
|
{
|
|
return GetLastError();
|
|
}
|
|
|
|
SP_DEVINSTALL_PARAMS DeviceInstallParams;
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
|
|
if(!SetupDiGetDeviceInstallParams(g_hDeviceInfoList,
|
|
&g_DevicesOfInterest[dwIndex].DevInfoData,
|
|
&DeviceInstallParams))
|
|
{
|
|
return ERROR_SUCCESS_REBOOT_REQUIRED;
|
|
}
|
|
|
|
if(DeviceInstallParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))
|
|
{
|
|
return ERROR_SUCCESS_REBOOT_REQUIRED;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
static DWORD __NetKVMwsz2DWORD(PWSTR wszInput)
|
|
{
|
|
wstringstream wstrmConverter;
|
|
wstrmConverter << wszInput;
|
|
DWORD dwIndex;
|
|
wstrmConverter >> dwIndex;
|
|
return dwIndex;
|
|
}
|
|
|
|
static BOOL __NetKVMConvertDeviceIndex(PWSTR wszIndex, PDWORD pdwIndex)
|
|
{
|
|
*pdwIndex = __NetKVMwsz2DWORD(wszIndex);
|
|
if(*pdwIndex >= g_DevicesOfInterest.size())
|
|
{
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_INDEXOUTOFRANGE);
|
|
tcout << endl;
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
typedef pair<tstring, tstring> ParamDescrT;
|
|
typedef list< ParamDescrT > ParamDescrListT;
|
|
|
|
static void _NetKVMFillDeviceParamsList(DWORD dwDeviceIndex, ParamDescrListT& List)
|
|
{
|
|
auto_ptr<neTKVMRegParam> pParam;
|
|
DWORD dwParamIndex = 0;
|
|
neTKVMRegAccess DeviceRegKey(HKEY_LOCAL_MACHINE, g_DevicesOfInterest[dwDeviceIndex].strRegPathName.c_str());
|
|
|
|
while(NULL != (pParam = auto_ptr<neTKVMRegParam>(neTKVMRegParam::GetParam(DeviceRegKey, dwParamIndex++))).get())
|
|
{
|
|
ParamDescrT ParamDescr;
|
|
ParamDescr.first = pParam->GetName();
|
|
ParamDescr.second = pParam->GetDescription();
|
|
List.push_back(ParamDescr);
|
|
}
|
|
}
|
|
|
|
typedef pair<tstring, tstring> ParamValueT;
|
|
typedef list< ParamValueT > ParamValueListT;
|
|
|
|
static void _NetKVMFillDeviceValuesList(DWORD dwDeviceIndex, ParamValueListT& List)
|
|
{
|
|
auto_ptr<neTKVMRegParam> pParam;
|
|
DWORD dwParamIndex = 0;
|
|
neTKVMRegAccess DeviceRegKey(HKEY_LOCAL_MACHINE, g_DevicesOfInterest[dwDeviceIndex].strRegPathName.c_str());
|
|
|
|
while(NULL != (pParam = auto_ptr<neTKVMRegParam>(neTKVMRegParam::GetParam(DeviceRegKey, dwParamIndex++))).get())
|
|
{
|
|
ParamValueT ParamValue;
|
|
ParamValue.first = pParam->GetName();
|
|
ParamValue.second = pParam->GetValue();
|
|
List.push_back(ParamValue);
|
|
}
|
|
}
|
|
|
|
static bool _NetKVMQueryDetailedParamInfo(DWORD dwDeviceIndex,
|
|
const tstring &strParamName,
|
|
neTKVMRegParamType &ParamType,
|
|
neTKVMRegParamExInfoList &ParamInfo)
|
|
{
|
|
neTKVMRegAccess DeviceRegKey(HKEY_LOCAL_MACHINE, g_DevicesOfInterest[dwDeviceIndex].strRegPathName.c_str());
|
|
|
|
auto_ptr<neTKVMRegParam> pParam(neTKVMRegParam::GetParam(DeviceRegKey, strParamName.c_str()));
|
|
|
|
ParamType = neTKVMRegParam::GetType(DeviceRegKey, strParamName.c_str());
|
|
if(NETKVM_RTT_UNKNOWN == ParamType)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(NULL == pParam.get())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pParam->FillExInfo(ParamInfo);
|
|
return true;
|
|
}
|
|
|
|
static bool _NetKVMQueryParamValue(DWORD dwDeviceIndex,
|
|
const tstring &strParamName,
|
|
tstring &strParamValue)
|
|
{
|
|
neTKVMRegAccess DeviceRegKey(HKEY_LOCAL_MACHINE, g_DevicesOfInterest[dwDeviceIndex].strRegPathName.c_str());
|
|
|
|
auto_ptr<neTKVMRegParam> pParam(neTKVMRegParam::GetParam(DeviceRegKey, strParamName.c_str()));
|
|
if(NULL == pParam.get())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
strParamValue = pParam->GetValue();
|
|
return true;
|
|
}
|
|
|
|
static bool _NetKVMSetParamValue(DWORD dwDeviceIndex,
|
|
const tstring &strParamName,
|
|
const tstring &strParamValue)
|
|
{
|
|
neTKVMRegAccess DeviceRegKey(HKEY_LOCAL_MACHINE, g_DevicesOfInterest[dwDeviceIndex].strRegPathName.c_str());
|
|
|
|
auto_ptr<neTKVMRegParam> pParam(neTKVMRegParam::GetParam(DeviceRegKey, strParamName.c_str()));
|
|
if(NULL == pParam.get())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(!pParam->ValidateAndSetValue(strParamValue.c_str()))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return pParam->Save();
|
|
}
|
|
|
|
//
|
|
// Usage: show devices
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Lists all NetKVM devices currently present in the system.
|
|
// Each device is assigned unique index.
|
|
// The index is used to identify the device for all other NetKVM commands.
|
|
//
|
|
DWORD WINAPI _NetKVMShowDevicesCmdHandler(__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* /*ppwcArguments*/,
|
|
__in DWORD /*dwCurrentIndex*/,
|
|
__in DWORD /*dwArgCount*/,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMShowDevicesCmdHandler called"));
|
|
int i = 0;
|
|
for(vector<_NetKVMDeviceInfo>::const_iterator it = g_DevicesOfInterest.begin();
|
|
it != g_DevicesOfInterest.end();
|
|
++it, ++i)
|
|
{
|
|
_NetKVMDumpDeviceInfo(i, *it);
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Usage: show paraminfo [idx=]0-N [param=]name
|
|
//
|
|
// Parameters:
|
|
//
|
|
// IDX - Specifies the device index as it is shown in "show devices" output.
|
|
// PARAM - Specifies name of the parameter.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Shows detailed information about specified parameter of specified device.
|
|
//
|
|
// Examples:
|
|
//
|
|
// show paraminfo idx=0 param=window
|
|
// show paraminfo 2 rx_buffers
|
|
//
|
|
DWORD WINAPI _NetKVMShowParamInfoCmdHandler (__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* ppwcArguments,
|
|
__in DWORD dwCurrentIndex,
|
|
__in DWORD dwArgCount,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMShowParamInfoCmdHandler called"));
|
|
TAG_TYPE TagsList[] =
|
|
{ {NETKVM_IDX_PARAM_NAME, NS_REQ_PRESENT},
|
|
{NETKVM_PARAM_PARAM_NAME, NS_REQ_PRESENT} };
|
|
|
|
auto_ptr<DWORD> pdwTagMatchResults(new DWORD[dwArgCount - dwCurrentIndex]);
|
|
DWORD dwPreprocessResult = PreprocessCommand(NULL, ppwcArguments,
|
|
dwCurrentIndex, dwArgCount,
|
|
TagsList, ARRAY_SIZE(TagsList),
|
|
ARRAY_SIZE(TagsList), ARRAY_SIZE(TagsList),
|
|
pdwTagMatchResults.get());
|
|
|
|
switch (dwPreprocessResult)
|
|
{
|
|
case NO_ERROR:
|
|
{
|
|
DWORD dwIndex;
|
|
if(__NetKVMConvertDeviceIndex(ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[0]], &dwIndex))
|
|
{
|
|
wstring wstrParamName = ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[1]];
|
|
neTKVMRegParamExInfoList ParamInfo;
|
|
neTKVMRegParamType ParamType;
|
|
|
|
if(!_NetKVMQueryDetailedParamInfo(dwIndex, wstring2tstring(wstrParamName),ParamType, ParamInfo))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMTYPE);
|
|
tcout << TEXT(": ");
|
|
switch(ParamType)
|
|
{
|
|
case NETKVM_RTT_ENUM:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMENUM);
|
|
break;
|
|
case NETKVM_RTT_INT:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMINT);
|
|
break;
|
|
case NETKVM_RTT_LONG:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMLONG);
|
|
break;
|
|
case NETKVM_RTT_EDIT:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMTEXT);
|
|
break;
|
|
default:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMUNKNOWN);
|
|
break;
|
|
}
|
|
tcout << endl;
|
|
|
|
for(neTKVMRegParamExInfoList::const_iterator it = ParamInfo.begin();
|
|
it != ParamInfo.end(); ++it)
|
|
{
|
|
switch(it->first)
|
|
{
|
|
case NETKVM_RPIID_ENUM_VALUE:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMENUMVALUE);
|
|
tcout << TEXT(" \"") << it->second << TEXT("\" - ");
|
|
break;
|
|
case NETKVM_RPIID_ENUM_VALUE_DESC:
|
|
tcout << it->second << endl;
|
|
break;
|
|
case NETKVM_RPIID_NUM_MIN:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMNUMMIN);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
case NETKVM_RPIID_NUM_MAX:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMNUMMAX);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
case NETKVM_RPIID_NUM_STEP:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMNUMSTEP);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
case NETKVM_RPIID_EDIT_TEXT_LIMIT:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMTEXTLIMIT);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
case NETKVM_RPIID_EDIT_UPPER_CASE:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMUPPERCASE);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
default:
|
|
tcout << TEXT("\t");
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_PARAMUNKNOWNPROP);
|
|
tcout << TEXT(": ") << it->second << endl;
|
|
break;
|
|
}
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
__fallthrough;
|
|
default:
|
|
NETCO_DEBUG_PRINT(TEXT("PreprocessCommand returned: ") << dwPreprocessResult);
|
|
return dwPreprocessResult;
|
|
}
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Usage: getparam [idx=]0-N [param=]name
|
|
//
|
|
// Parameters:
|
|
//
|
|
// IDX - Specifies the device index as it is shown in "show devices" output.
|
|
// PARAM - Specifies name of the parameter.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Retrieves given parameter value.
|
|
//
|
|
// Examples:
|
|
//
|
|
// getparam idx=0 param=window
|
|
// getparam 2 rx_buffers
|
|
//
|
|
DWORD WINAPI _NetKVMGetParamCmdHandler (__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* ppwcArguments,
|
|
__in DWORD dwCurrentIndex,
|
|
__in DWORD dwArgCount,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMGetParamCmdHandler called"));
|
|
TAG_TYPE TagsList[] =
|
|
{ {NETKVM_IDX_PARAM_NAME, NS_REQ_PRESENT},
|
|
{NETKVM_PARAM_PARAM_NAME, NS_REQ_PRESENT} };
|
|
|
|
auto_ptr<DWORD> pdwTagMatchResults(new DWORD[dwArgCount - dwCurrentIndex]);
|
|
DWORD dwPreprocessResult = PreprocessCommand(NULL, ppwcArguments,
|
|
dwCurrentIndex, dwArgCount,
|
|
TagsList, ARRAY_SIZE(TagsList),
|
|
ARRAY_SIZE(TagsList), ARRAY_SIZE(TagsList),
|
|
pdwTagMatchResults.get());
|
|
|
|
switch (dwPreprocessResult)
|
|
{
|
|
case NO_ERROR:
|
|
{
|
|
DWORD dwIndex;
|
|
if(__NetKVMConvertDeviceIndex(ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[0]], &dwIndex))
|
|
{
|
|
wstring wstrParamName = ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[1]];
|
|
tstring strParamName = wstring2tstring(wstrParamName);
|
|
tstring strParamValue;
|
|
|
|
if(!_NetKVMQueryParamValue(dwIndex, strParamName, strParamValue))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
tcout << strParamName << TEXT(" = ") << strParamValue << endl;
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
__fallthrough;
|
|
default:
|
|
NETCO_DEBUG_PRINT(TEXT("PreprocessCommand returned: ") << dwPreprocessResult);
|
|
return dwPreprocessResult;
|
|
}
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Usage: setparam [idx=]0-N [param=]name [value=]value
|
|
//
|
|
// Parameters:
|
|
//
|
|
// IDX - Specifies the device index as it is shown in "show devices" output.
|
|
// PARAM - Specifies name of the parameter.
|
|
// VALUE - Specifies the value of the parameter.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Set given parameter value.
|
|
//
|
|
// Examples:
|
|
//
|
|
// setparam idx=0 param=window value=10
|
|
// setparam 2 rx_buffers 45
|
|
//
|
|
DWORD WINAPI _NetKVMSetParamCmdHandler (__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* ppwcArguments,
|
|
__in DWORD dwCurrentIndex,
|
|
__in DWORD dwArgCount,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMSetParamCmdHandler called"));
|
|
TAG_TYPE TagsList[] =
|
|
{ {NETKVM_IDX_PARAM_NAME, NS_REQ_PRESENT},
|
|
{NETKVM_PARAM_PARAM_NAME, NS_REQ_PRESENT},
|
|
{NETKVM_VALUE_PARAM_NAME, NS_REQ_PRESENT} };
|
|
|
|
auto_ptr<DWORD> pdwTagMatchResults(new DWORD[dwArgCount - dwCurrentIndex]);
|
|
DWORD dwPreprocessResult = PreprocessCommand(NULL, ppwcArguments,
|
|
dwCurrentIndex, dwArgCount,
|
|
TagsList, ARRAY_SIZE(TagsList),
|
|
ARRAY_SIZE(TagsList), ARRAY_SIZE(TagsList),
|
|
pdwTagMatchResults.get());
|
|
|
|
switch (dwPreprocessResult)
|
|
{
|
|
case NO_ERROR:
|
|
{
|
|
DWORD dwIndex;
|
|
if(__NetKVMConvertDeviceIndex(ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[0]], &dwIndex))
|
|
{
|
|
wstring wstrParamName = ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[1]];
|
|
wstring wstrParamValue = ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[2]];
|
|
|
|
if(!_NetKVMSetParamValue(dwIndex, wstring2tstring(wstrParamName), wstring2tstring(wstrParamValue)))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
__fallthrough;
|
|
default:
|
|
NETCO_DEBUG_PRINT(TEXT("PreprocessCommand returned: ") << dwPreprocessResult);
|
|
return dwPreprocessResult;
|
|
}
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
//
|
|
// Usage: show parameters [idx=]0-N
|
|
//
|
|
// Parameters:
|
|
//
|
|
// IDX - Specifies the device index as it is shown in "show devices" output.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Shows parameters of device specified by index.
|
|
//
|
|
// Examples:
|
|
//
|
|
// show parameters idx=0
|
|
// show parameters 2
|
|
//
|
|
DWORD WINAPI _NetKVMShowParamsCmdHandler(__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* ppwcArguments,
|
|
__in DWORD dwCurrentIndex,
|
|
__in DWORD dwArgCount,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMShowParamsCmdHandler called"));
|
|
TAG_TYPE TagsList[] =
|
|
{ {NETKVM_IDX_PARAM_NAME, NS_REQ_PRESENT} };
|
|
|
|
auto_ptr<DWORD> pdwTagMatchResults(new DWORD[dwArgCount - dwCurrentIndex]);
|
|
DWORD dwPreprocessResult = PreprocessCommand(NULL, ppwcArguments,
|
|
dwCurrentIndex, dwArgCount,
|
|
TagsList, ARRAY_SIZE(TagsList),
|
|
ARRAY_SIZE(TagsList), ARRAY_SIZE(TagsList),
|
|
pdwTagMatchResults.get());
|
|
|
|
switch (dwPreprocessResult)
|
|
{
|
|
case NO_ERROR:
|
|
{
|
|
DWORD dwIndex;
|
|
if(__NetKVMConvertDeviceIndex(ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[0]], &dwIndex))
|
|
{
|
|
ParamDescrListT Params;
|
|
|
|
_NetKVMFillDeviceParamsList(dwIndex, Params);
|
|
for(ParamDescrListT::const_iterator it = Params.begin();
|
|
it != Params.end(); ++it)
|
|
{
|
|
tcout << it->first << endl<< TEXT("\t") << it->second << endl;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
__fallthrough;
|
|
default:
|
|
NETCO_DEBUG_PRINT(TEXT("PreprocessCommand returned: ") << dwPreprocessResult);
|
|
return dwPreprocessResult;
|
|
}
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Usage: restart [idx=]0-N
|
|
//
|
|
// Parameters:
|
|
//
|
|
// IDX - Specifies the device index as it is shown in "show devices" output.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Restarts device specified by index.
|
|
//
|
|
// Examples:
|
|
//
|
|
// restart idx=0
|
|
// restart 2
|
|
//
|
|
DWORD WINAPI _NetKVMRestartDeviceCmdHandler(__in PWCHAR /*pwszMachine*/,
|
|
__in PWCHAR* ppwcArguments,
|
|
__in DWORD dwCurrentIndex,
|
|
__in DWORD dwArgCount,
|
|
__in DWORD /*dwFlags*/,
|
|
__in PVOID /*pvData*/,
|
|
__out BOOL* pbDone)
|
|
{
|
|
*pbDone = FALSE; /* Just to make static analyzer happy */
|
|
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMRestartDeviceCmdHandler called"));
|
|
TAG_TYPE TagsList[] =
|
|
{ {NETKVM_IDX_PARAM_NAME, NS_REQ_PRESENT} };
|
|
|
|
auto_ptr<DWORD> pdwTagMatchResults(new DWORD[dwArgCount - dwCurrentIndex]);
|
|
DWORD dwPreprocessResult = PreprocessCommand(NULL, ppwcArguments,
|
|
dwCurrentIndex, dwArgCount,
|
|
TagsList, ARRAY_SIZE(TagsList),
|
|
ARRAY_SIZE(TagsList), ARRAY_SIZE(TagsList),
|
|
pdwTagMatchResults.get());
|
|
|
|
switch (dwPreprocessResult)
|
|
{
|
|
case NO_ERROR:
|
|
{
|
|
DWORD dwIndex;
|
|
if(__NetKVMConvertDeviceIndex(ppwcArguments[dwCurrentIndex + pdwTagMatchResults.get()[0]], &dwIndex))
|
|
{
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_RESTARTINGDEVICE);
|
|
tcout << TEXT(" ") << dwIndex << TEXT("... ");
|
|
DWORD dwError = _NetKVMRestartDevice(dwIndex);
|
|
switch(dwError)
|
|
{
|
|
case NO_ERROR:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_DONE);
|
|
break;
|
|
case ERROR_SUCCESS_REBOOT_REQUIRED:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_REBOOTREQUIRED);
|
|
break;
|
|
default:
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_FAIL);
|
|
break;
|
|
}
|
|
tcout << endl;
|
|
return dwError;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
__fallthrough;
|
|
default:
|
|
NETCO_DEBUG_PRINT(TEXT("PreprocessCommand returned: ") << dwPreprocessResult);
|
|
return dwPreprocessResult;
|
|
}
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
#define CMD_NETKVM_SHOW_DEVICES L"devices"
|
|
#define HLP_NETKVM_SHOW_DEVICES IDS_SHOWDEVICESSHORT
|
|
#define HLP_NETKVM_SHOW_DEVICES_EX IDS_SHOWDEVICESLONG
|
|
#define CMD_NETKVM_SHOW_PARAMS L"parameters"
|
|
#define HLP_NETKVM_SHOW_PARAMS IDS_SHOWPARAMSSHORT
|
|
#define HLP_NETKVM_SHOW_PARAMS_EX IDS_SHOWPARAMSLONG
|
|
#define CMD_NETKVM_SHOW_PARAMINFO L"paraminfo"
|
|
#define HLP_NETKVM_SHOW_PARAMINFO IDS_SHOWPARAMINFOSHORT
|
|
#define HLP_NETKVM_SHOW_PARAMINFO_EX IDS_SHOWPARAMINFOLONG
|
|
|
|
#define CREATE_CMD_ENTRY(t,f) {CMD_##t, f, HLP_##t, HLP_##t##_EX, CMD_FLAG_PRIVATE, NULL}
|
|
#define CREATE_CMD_ENTRY_EX(t,f,i) {CMD_##t, f, HLP_##t, HLP_##t##_EX, i, NULL}
|
|
#define CREATE_CMD_ENTRY_EX_VER(t,f,i,v) {CMD_##t, f, HLP_##t, HLP_##t##_EX, i, v}
|
|
|
|
#define CREATE_CMD_GROUP_ENTRY(t,s) {CMD_##t, HLP_##t, sizeof(s)/sizeof(CMD_ENTRY), 0, s, NULL }
|
|
#define CREATE_CMD_GROUP_ENTRY_EX(t,s,i) {CMD_##t, HLP_##t, sizeof(s)/sizeof(CMD_ENTRY), i, s, NULL }
|
|
#define CREATE_CMD_GROUP_ENTRY_EX_VER(t,s,i,v) {CMD_##t, HLP_##t, sizeof(s)/sizeof(CMD_ENTRY), i, s, v }
|
|
|
|
#define CMD_FLAG_PRIVATE 0
|
|
#define CMD_FLAG_LOCAL 0
|
|
|
|
CMD_ENTRY g_ShowCmdTable[] =
|
|
{
|
|
CREATE_CMD_ENTRY_EX(NETKVM_SHOW_DEVICES,
|
|
(PFN_HANDLE_CMD) _NetKVMShowDevicesCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL),
|
|
CREATE_CMD_ENTRY_EX(NETKVM_SHOW_PARAMS,
|
|
(PFN_HANDLE_CMD) _NetKVMShowParamsCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL),
|
|
CREATE_CMD_ENTRY_EX(NETKVM_SHOW_PARAMINFO,
|
|
(PFN_HANDLE_CMD) _NetKVMShowParamInfoCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL)
|
|
|
|
};
|
|
|
|
CMD_ENTRY11 g_ShowCmdTable11[] =
|
|
{
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_SHOW_DEVICES,
|
|
(PFN_HANDLE_CMD)_NetKVMShowDevicesCmdHandler,
|
|
/*CMD_FLAG_PRIVATE |*/ CMD_FLAG_LOCAL)},
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_SHOW_PARAMS,
|
|
(PFN_HANDLE_CMD)_NetKVMShowParamsCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL) },
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_SHOW_PARAMINFO,
|
|
(PFN_HANDLE_CMD)_NetKVMShowParamInfoCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL) }
|
|
|
|
};
|
|
|
|
#define CMD_NETKVM_RESTART_DEVICE L"restart"
|
|
#define CMD_NETKVM_RESTART_DEVICE_T TEXT("restart")
|
|
#define HLP_NETKVM_RESTART_DEVICE IDS_RESTARTDEVICE
|
|
#define HLP_NETKVM_RESTART_DEVICE_EX IDS_RESTARTDEVICELONG
|
|
#define CMD_NETKVM_GET_PARAM L"getparam"
|
|
#define HLP_NETKVM_GET_PARAM IDS_GETPARAM
|
|
#define HLP_NETKVM_GET_PARAM_EX IDS_GETPARAMLONG
|
|
#define CMD_NETKVM_SET_PARAM L"setparam"
|
|
#define CMD_NETKVM_SET_PARAM_T TEXT("setparam")
|
|
#define HLP_NETKVM_SET_PARAM IDS_SETPARAM
|
|
#define HLP_NETKVM_SET_PARAM_EX IDS_SETPARAMLONG
|
|
|
|
CMD_ENTRY g_TopLevelCommands[] =
|
|
{
|
|
CREATE_CMD_ENTRY_EX(NETKVM_RESTART_DEVICE,
|
|
(PFN_HANDLE_CMD) _NetKVMRestartDeviceCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL),
|
|
CREATE_CMD_ENTRY_EX(NETKVM_GET_PARAM,
|
|
(PFN_HANDLE_CMD) _NetKVMGetParamCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL),
|
|
CREATE_CMD_ENTRY_EX(NETKVM_SET_PARAM,
|
|
(PFN_HANDLE_CMD) _NetKVMSetParamCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL)
|
|
};
|
|
|
|
CMD_ENTRY11 g_TopLevelCommands11[] =
|
|
{
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_RESTART_DEVICE,
|
|
(PFN_HANDLE_CMD)_NetKVMRestartDeviceCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL) },
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_GET_PARAM,
|
|
(PFN_HANDLE_CMD)_NetKVMGetParamCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL) },
|
|
{ CREATE_CMD_ENTRY_EX(NETKVM_SET_PARAM,
|
|
(PFN_HANDLE_CMD)_NetKVMSetParamCmdHandler,
|
|
CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL) }
|
|
};
|
|
|
|
|
|
#define HLP_GROUP_SHOW IDS_SHOWCMDHELP
|
|
#define CMD_GROUP_SHOW L"show"
|
|
|
|
static CMD_GROUP_ENTRY g_TopLevelGroups[] =
|
|
{
|
|
CREATE_CMD_GROUP_ENTRY_EX(GROUP_SHOW, g_ShowCmdTable, CMD_FLAG_PRIVATE | CMD_FLAG_LOCAL)
|
|
};
|
|
|
|
static CMD_GROUP_ENTRY g_TopLevelGroups11[] =
|
|
{
|
|
CREATE_CMD_GROUP_ENTRY_EX(GROUP_SHOW, g_ShowCmdTable, /*CMD_FLAG_PRIVATE | */CMD_FLAG_LOCAL)
|
|
};
|
|
|
|
DWORD WINAPI _NetKVMDumpCdmHandler(__in PWCHAR pwszRouter,
|
|
__in WCHAR ** /* ppwcArguments */,
|
|
__in DWORD /* dwArgCount */,
|
|
__in PVOID /* pvData */)
|
|
{
|
|
try
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("_NetKVMDumpCdmHandler called"));
|
|
|
|
if(NULL != pwszRouter)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOCALONLY);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
tcout << endl<< TEXT("pushd ") << NETKVM_HELPER_NAME << endl << endl;
|
|
|
|
for(DWORD i = 0; i < g_DevicesOfInterest.size(); i++)
|
|
{
|
|
ParamValueListT ValuesList;
|
|
_NetKVMFillDeviceValuesList(i, ValuesList);
|
|
|
|
for(ParamValueListT::const_iterator it = ValuesList.begin();
|
|
it != ValuesList.end(); ++it)
|
|
{
|
|
tcout << CMD_NETKVM_SET_PARAM_T << TEXT(" ")
|
|
<< NETKVM_IDX_PARAM_NAME_T << TEXT("=") << i << TEXT(" ")
|
|
<< NETKVM_PARAM_PARAM_NAME_T << TEXT("=") << it->first << TEXT(" ")
|
|
<< NETKVM_VALUE_PARAM_NAME_T << TEXT("=") << it->second << endl;
|
|
}
|
|
|
|
tcout << CMD_NETKVM_RESTART_DEVICE_T << TEXT(" ")
|
|
<< NETKVM_IDX_PARAM_NAME_T << TEXT("=") << i << TEXT(" ")
|
|
<< endl << endl;
|
|
}
|
|
|
|
tcout << TEXT("popd") << endl;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
}
|
|
|
|
DWORD WINAPI NetKVMNetshStartHelper(__in const GUID *pguidParent,
|
|
__in DWORD dwVersion)
|
|
{
|
|
try
|
|
{
|
|
UNREFERENCED_PARAMETER(pguidParent);
|
|
UNREFERENCED_PARAMETER(dwVersion);
|
|
|
|
NETCO_DEBUG_PRINT(TEXT("NetKVMNetshStartHelper called"));
|
|
|
|
pair< HDEVINFO, vector<_NetKVMDeviceInfo> > Devices = _NetKVMGetDevicesOfInterest();
|
|
g_hDeviceInfoList = Devices.first;
|
|
g_DevicesOfInterest = Devices.second;
|
|
|
|
if(g_DevicesOfInterest.empty())
|
|
{
|
|
PrintMessageFromModule(g_hinstThisDLL, IDS_NODEVICESFOUND);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
NS_CONTEXT_ATTRIBUTES attr;
|
|
ZeroMemory(&attr, sizeof(attr));
|
|
attr.dwVersion = NETKVM_HELPER_VERSION;
|
|
attr.dwReserved = 0;
|
|
attr.pwszContext = NETKVM_HELPER_NAME_W;
|
|
attr.guidHelper = NETKVM_HELPER_GUID;
|
|
attr.dwFlags = CMD_FLAG_LOCAL;
|
|
attr.ulPriority = 0;
|
|
attr.ulNumTopCmds = ARRAYSIZE(g_TopLevelCommands);
|
|
attr.pTopCmds = (CMD_ENTRY (*)[])g_TopLevelCommands;
|
|
if (Is11_22H2) attr.pTopCmds = (CMD_ENTRY(*)[])g_TopLevelCommands11;
|
|
attr.ulNumGroups = ARRAYSIZE(g_TopLevelGroups);
|
|
attr.pCmdGroups = (CMD_GROUP_ENTRY (*)[])g_TopLevelGroups;
|
|
if (Is11_22H2) g_TopLevelGroups->pCmdGroup = (PCMD_ENTRY)&g_ShowCmdTable11[0];
|
|
attr.pfnCommitFn = NULL;
|
|
attr.pfnDumpFn = (PNS_CONTEXT_DUMP_FN) _NetKVMDumpCdmHandler;
|
|
attr.pfnConnectFn = NULL;
|
|
attr.pReserved = NULL;
|
|
RegisterContext(&attr);
|
|
|
|
NETCO_DEBUG_PRINT(TEXT("RegisterContext returned"));
|
|
}
|
|
catch(const exception& ex)
|
|
{
|
|
PrintError(g_hinstThisDLL, IDS_LOGICEXCEPTION);
|
|
tcout << TEXT(": ") << string2tstring(string(ex.what())) << endl;
|
|
return ERROR_EXCEPTION_IN_SERVICE;
|
|
}
|
|
catch(...)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Unknown exception"));
|
|
return ERROR_UNKNOWN_EXCEPTION;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD WINAPI NetKVMNetshStopHelper(__in DWORD dwReserved)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwReserved);
|
|
|
|
NETCO_DEBUG_PRINT(TEXT("NetKVMNetshStopHelper called"));
|
|
|
|
return SetupDiDestroyDeviceInfoList(g_hDeviceInfoList) ? NO_ERROR
|
|
: GetLastError();
|
|
}
|
|
|
|
DWORD NETCO_API InitHelperDll(__in DWORD dwNetshVersion,
|
|
PVOID pReserved)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwNetshVersion);
|
|
UNREFERENCED_PARAMETER(pReserved);
|
|
|
|
NETCO_DEBUG_PRINT(TEXT("InitHelperDll called. dwNetshVersion: ") << hex << dwNetshVersion);
|
|
|
|
NS_HELPER_ATTRIBUTES attr;
|
|
|
|
ZeroMemory(&attr, sizeof(attr));
|
|
attr.guidHelper = NETKVM_HELPER_GUID;
|
|
attr.dwVersion = NETKVM_HELPER_VERSION;
|
|
attr.pfnStart = _NetKVMNetshStartHelper;
|
|
attr.pfnStop = _NetKVMNetshStopHelper;
|
|
RegisterHelper( NULL, &attr );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
static DWORD _GetThisDLLPathName(LPTSTR szPathName, DWORD *pdwLength)
|
|
{
|
|
DWORD dwPathLength = GetModuleFileName(g_hinstThisDLL, szPathName, *pdwLength);
|
|
DWORD dwErr = GetLastError();
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("GetModuleFileName failed. Error code: ") << dwErr);
|
|
return dwErr;
|
|
}
|
|
else if(dwPathLength == *pdwLength)
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("Buffer provided to GetModuleFileName is too small"));
|
|
return ERROR_BUFFER_OVERFLOW;
|
|
}
|
|
else
|
|
{
|
|
NETCO_DEBUG_PRINT(TEXT("DLL pathname: ") << szPathName);
|
|
*pdwLength = dwPathLength;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
static const LPCTSTR NETSH_HELPERS_LIST_PATH = TEXT("SOFTWARE\\Microsoft\\NetSh");
|
|
static const HKEY NETSH_HELPERS_LIST_HIVE = HKEY_LOCAL_MACHINE;
|
|
|
|
DWORD NETCO_API RegisterNetKVMNetShHelper(void)
|
|
{
|
|
try
|
|
{
|
|
TCHAR szDllPathName[MAX_PATH];
|
|
DWORD dwPathNameLength = TBUF_SIZEOF(szDllPathName);
|
|
|
|
DWORD dwErr = _GetThisDLLPathName(szDllPathName, &dwPathNameLength);
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
tstringstream strmError;
|
|
strmError << TEXT("_GetThisDLLPathName failed with code ") << dwErr;
|
|
OutputDebugString(strmError.str().c_str());
|
|
return dwErr;
|
|
}
|
|
|
|
neTKVMRegAccess regAccess(NETSH_HELPERS_LIST_HIVE, NETSH_HELPERS_LIST_PATH);
|
|
if(!regAccess.WriteString(NETKVM_HELPER_NAME, szDllPathName))
|
|
{
|
|
dwErr = GetLastError();
|
|
tstringstream strmError;
|
|
strmError << TEXT("Registry operation failed with code ") << dwErr;
|
|
OutputDebugString(strmError.str().c_str());
|
|
return dwErr;
|
|
}
|
|
return ERROR_SUCCESS;
|
|
}
|
|
catch (const exception& ex)
|
|
{
|
|
OutputDebugStringA(ex.what());
|
|
return ERROR_INSTALL_FAILURE;
|
|
}
|
|
}
|
|
DWORD NETCO_API UnregisterNetKVMNetShHelper(void)
|
|
{
|
|
try
|
|
{
|
|
neTKVMRegAccess regAccess(NETSH_HELPERS_LIST_HIVE, NETSH_HELPERS_LIST_PATH);
|
|
regAccess.DeleteValue(NETKVM_HELPER_NAME);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
catch (const exception& ex)
|
|
{
|
|
OutputDebugStringA(ex.what());
|
|
return ERROR_INSTALL_FAILURE;
|
|
}
|
|
}
|
|
|
|
BOOL NETCO_API __stdcall DllMain(__in HINSTANCE hinstDLL,
|
|
__in DWORD fdwReason,
|
|
__in LPVOID lpvReserved)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpvReserved);
|
|
|
|
NETCO_DEBUG_PRINT(TEXT("DllMain(") << fdwReason << TEXT(") called"));
|
|
|
|
//Obtain DLL path name and store it for future use
|
|
if(DLL_PROCESS_ATTACH == fdwReason)
|
|
{
|
|
g_hinstThisDLL = hinstDLL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|