Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1048 lines
26 KiB

//============================================================================
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: util.cpp
//
// History:
// 03/10/97 Kenn M. Takara Created
//
// Source code for some of the utility functions in util.h
//============================================================================
#include "stdafx.h"
#include "mprsnap.h"
#include "rtrutilp.h"
#include "rtrstr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static const GUID GUID_DevClass_Net = {0x4D36E972,0xE325,0x11CE,{0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18}};
//----------------------------------------------------------------------------
// Function: ConnectRegistry
//
// Connects to the registry on the specified machine
//----------------------------------------------------------------------------
TFSCORE_API(DWORD)
ConnectRegistry(
IN LPCTSTR pszMachine,
OUT HKEY* phkeyMachine
) {
//
// if no machine name was specified, connect to the local machine.
// otherwise, connect to the specified machine
//
DWORD dwErr = NO_ERROR;
if (IsLocalMachine(pszMachine))
{
*phkeyMachine = HKEY_LOCAL_MACHINE;
}
else
{
//
// Make the connection
//
dwErr = ::RegConnectRegistry(
(LPTSTR)pszMachine, HKEY_LOCAL_MACHINE, phkeyMachine
);
}
HrReportExit(HRESULT_FROM_WIN32(dwErr), TEXT("ConnectRegistry"));
return dwErr;
}
//----------------------------------------------------------------------------
// Function: DisconnectRegistry
//
// Disconnects the specified config-handle. The handle is assumed to have been
// acquired by calling 'ConnectRegistry'.
//----------------------------------------------------------------------------
TFSCORE_API(VOID)
DisconnectRegistry(
IN HKEY hkeyMachine
) {
if (hkeyMachine != HKEY_LOCAL_MACHINE)
{
::RegCloseKey(hkeyMachine);
}
}
/*!--------------------------------------------------------------------------
QueryRouterType
-
Author: KennT
---------------------------------------------------------------------------*/
TFSCORE_API(HRESULT) QueryRouterType(HKEY hkeyMachine, DWORD *pdwRouterType,
RouterVersionInfo *pVersion)
{
Assert(pdwRouterType);
Assert(hkeyMachine);
DWORD dwErr = ERROR_SUCCESS;
HKEY hkey = 0;
DWORD dwType;
DWORD dwRouterType;
DWORD dwSize;
RouterVersionInfo versionTemp;
LPCTSTR pszRouterTypeKey = NULL;
BOOL fFirstTry = TRUE;
// If the version structure is not passed in, we have to do it
// ourselves
// ----------------------------------------------------------------
if (pVersion == NULL)
{
dwErr = QueryRouterVersionInfo(hkeyMachine, &versionTemp);
if ( dwErr != ERROR_SUCCESS )
{
goto Error;
}
pVersion = &versionTemp;
}
// Windows NT Bug : 137200
// Need to get the router type from a different place depending
// on the version.
// ----------------------------------------------------------------
// if (pVersion->dwRouterVersion <= 4)
if (pVersion->dwOsBuildNo < RASMAN_PPP_KEY_LAST_VERSION)
pszRouterTypeKey = c_szRegKeyRasProtocols;
else
pszRouterTypeKey = c_szRegKeyRemoteAccessParameters;
// This is where we perform a retry
// ----------------------------------------------------------------
Retry:
// Cool, we have a machine registry entry, now get the
// path down to the routertype key
dwErr = RegOpenKeyEx(hkeyMachine, pszRouterTypeKey, 0, KEY_READ, &hkey);
if (dwErr)
goto Error;
// Ok, at this point we just need to get the RouterType value from
// the key
dwType = REG_DWORD;
dwSize = sizeof(dwRouterType);
dwErr = RegQueryValueEx(hkey, c_szRouterType, NULL,
&dwType,
(LPBYTE) &dwRouterType,
&dwSize);
if (dwErr)
{
// Need to retry (look at the RAS/protocols key), for NT5
if ((pVersion->dwRouterVersion >= 5) && fFirstTry)
{
dwErr = ERROR_SUCCESS;
fFirstTry = FALSE;
if (hkey)
RegCloseKey(hkey);
hkey = 0;
pszRouterTypeKey = c_szRegKeyRasProtocols;
goto Retry;
}
goto Error;
}
// Is this the right type?
if (dwType != REG_DWORD)
{
dwErr = ERROR_BADKEY;
goto Error;
}
// We have the right type, now return that value
*pdwRouterType = dwRouterType;
Error:
if (hkey)
RegCloseKey(hkey);
return HrReportExit(HRESULT_FROM_WIN32(dwErr), TEXT("QueryRouterType"));
}
//----------------------------------------------------------------------------
// Function: LoadLinkageList
//
// Loads a list of strings with the adapters to which 'pszService' is bound;
// the list is built by examining the 'Linkage' and 'Disabled' subkeys
// of the service under HKLM\System\CurrentControlSet\Services.
//----------------------------------------------------------------------------
HRESULT LoadLinkageList(
LPCTSTR pszMachine,
HKEY hkeyMachine,
LPCTSTR pszService,
CStringList* pLinkageList)
{
Assert(hkeyMachine);
DWORD dwErr;
BYTE* pValue = NULL;
HKEY hkeyLinkage = NULL, hkeyDisabled = NULL;
if (!pszService || !lstrlen(pszService) || !pLinkageList) {
return ERROR_INVALID_PARAMETER;
}
do {
TCHAR* psz;
CString skey;
DWORD dwType, dwSize;
BOOL fNt4;
dwErr = IsNT4Machine(hkeyMachine, &fNt4);
if (dwErr != NO_ERROR)
break;
//$NT5 : where is the registry key? same as NT4
skey = c_szSystemCCSServices;
skey += TEXT('\\');
skey += pszService;
skey += TEXT('\\');
skey += c_szLinkage;
//
// Open the service's 'Linkage' key
//
dwErr = RegOpenKeyEx(
hkeyMachine, skey, 0, KEY_READ, &hkeyLinkage
);
if (dwErr != NO_ERROR) {
if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("QueryLinkageList"));
break;
}
//
// Retrieve the size of the 'Bind' value
//
dwErr = RegQueryValueEx(
hkeyLinkage, c_szBind, NULL, &dwType, NULL, &dwSize
);
if (dwErr != NO_ERROR) {
if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szBind, _T("QueryLinkageList"));
break;
}
//
// Allocate space for the 'Bind' value
//
pValue = new BYTE[dwSize + sizeof(TCHAR)];
if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
::ZeroMemory(pValue, dwSize + sizeof(TCHAR));
//
// Read the 'Bind' value
//
dwErr = RegQueryValueEx(
hkeyLinkage, c_szBind, NULL, &dwType, pValue, &dwSize
);
CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szBind, _T("QueryLinkageList"));
if (dwErr != NO_ERROR) { break; }
//
// Convert the 'Bind' multi-string to a list of strings,
// leaving out the string "\Device\" which is the prefix
// for all the bindings.
//
for (psz = (TCHAR*)pValue; *psz; psz += lstrlen(psz) + 1) {
pLinkageList->AddTail(psz + 8);
}
delete [] pValue; pValue = NULL;
//
// Now open the service's 'Disabled' key.
//
dwErr = RegOpenKeyEx(
hkeyLinkage, c_szDisabled, 0, KEY_READ, &hkeyDisabled
);
if (dwErr != NO_ERROR) {
if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
CheckRegOpenError(dwErr, c_szDisabled, _T("QueryLinkageList"));
break;
}
//
// Retrieve the size of the 'Bind' value
//
dwErr = RegQueryValueEx(
hkeyDisabled, c_szBind, NULL, &dwType, NULL, &dwSize
);
if (dwErr != NO_ERROR) {
if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; }
CheckRegQueryValueError(dwErr, c_szDisabled, c_szBind, _T("QueryLinkageList"));
break;
}
//
// Allocate space for the 'Bind' value
//
pValue = new BYTE[dwSize + sizeof(TCHAR)];
if (!pValue) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; }
::ZeroMemory(pValue, dwSize + sizeof(TCHAR));
//
// Read the 'Bind' value
//
dwErr = RegQueryValueEx(
hkeyDisabled, c_szBind, NULL, &dwType, pValue, &dwSize
);
CheckRegQueryValueError(dwErr, c_szDisabled, c_szBind, _T("QueryLinkageList"));
if (dwErr != NO_ERROR) { break; }
//
// Each device in the 'Bind' mulit-string is disabled for the service,
// so we will now remove such devices from the string-list built
// from the 'Linkage' key.
//
for (psz = (TCHAR*)pValue; *psz; psz += lstrlen(psz) + 1) {
POSITION pos = pLinkageList->Find(psz);
if (pos) { pLinkageList->RemoveAt(pos); }
}
} while(FALSE);
if (pValue) { delete [] pValue; }
if (hkeyDisabled) { ::RegCloseKey(hkeyDisabled); }
if (hkeyLinkage) { ::RegCloseKey(hkeyLinkage); }
return dwErr;
}
/*!--------------------------------------------------------------------------
IsNT4Machine
-
Author: KennT, WeiJiang
---------------------------------------------------------------------------*/
TFSCORE_API(DWORD) GetNTVersion(HKEY hkeyMachine, DWORD *pdwMajor, DWORD *pdwMinor, DWORD* pdwCurrentBuildNumber)
{
// Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
// CurrentVersion = REG_SZ "4.0"
CString skey;
DWORD dwErr;
TCHAR szVersion[64];
TCHAR szCurrentBuildNumber[64];
RegKey regkey;
CString strVersion;
CString strMajor;
CString strMinor;
ASSERT(pdwMajor);
ASSERT(pdwMinor);
ASSERT(pdwCurrentBuildNumber);
skey = c_szSoftware;
skey += TEXT('\\');
skey += c_szMicrosoft;
skey += TEXT('\\');
skey += c_szWindowsNT;
skey += TEXT('\\');
skey += c_szCurrentVersion;
dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("GetNTVersion"));
if (dwErr != ERROR_SUCCESS)
return dwErr;
// Ok, now try to get the current version value
dwErr = regkey.QueryValue( c_szCurrentVersion, szVersion,
sizeof(szVersion),
FALSE);
CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentVersion,
_T("GetNTVersion"));
if (dwErr != ERROR_SUCCESS)
goto Err;
// Ok, now try to get the current build number value
dwErr = regkey.QueryValue( c_szCurrentBuildNumber, szCurrentBuildNumber,
sizeof(szCurrentBuildNumber),
FALSE);
CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentBuildNumber,
_T("GetNTVersion"));
if (dwErr != ERROR_SUCCESS)
goto Err;
strVersion = szVersion;
strMajor = strVersion.Left(strVersion.Find(_T('.')));
strMinor = strVersion.Mid(strVersion.Find(_T('.')) + 1);
if(pdwMajor)
*pdwMajor = _ttol(strMajor);
if(pdwMinor)
*pdwMinor = _ttol(strMinor);
if(pdwCurrentBuildNumber)
*pdwCurrentBuildNumber = _ttol(szCurrentBuildNumber);
Err:
return dwErr;
}
/*!--------------------------------------------------------------------------
IsNT4Machine
-
Author: KennT
---------------------------------------------------------------------------*/
TFSCORE_API(DWORD) IsNT4Machine(HKEY hkeyMachine, BOOL *pfNt4)
{
// Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
// CurrentVersion = REG_SZ "4.0"
DWORD dwMajor = 0;
DWORD dwErr = 0;
dwErr = GetNTVersion(hkeyMachine, &dwMajor, NULL, NULL);
if (dwErr == ERROR_SUCCESS)
{
*pfNt4 = (dwMajor == 4);
}
return dwErr;
}
//----------------------------------------------------------------------------
// Function: FindRmSoftwareKey
//
// Finds the key for a router-manager in the Software section of the registry.
//----------------------------------------------------------------------------
HRESULT FindRmSoftwareKey(
HKEY hkeyMachine,
DWORD dwTransportId,
HKEY* phkrm,
LPTSTR* lplpszRm
)
{
Assert(phkrm);
DWORD dwErr;
RegKey regkey;
HRESULT hr = hrOK;
CString stKey;
RegKeyIterator regkeyIter;
HRESULT hrIter;
RegKey regkeyRM;
DWORD dwProtocolId;
BOOL bFound = FALSE;
//
// open the key HKLM\Software\Microsoft\Router\RouterManagers
//
CString skey(c_szSoftware);
skey += TEXT('\\');
skey += c_szMicrosoft;
skey += TEXT('\\');
skey += c_szRouter;
skey += TEXT('\\');
skey += c_szCurrentVersion;
skey += TEXT('\\');
skey += c_szRouterManagers;
dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("QueryRmSoftwareKey"));
CWRg(dwErr);
if (lplpszRm)
*lplpszRm = NULL;
*phkrm = 0;
//
// Enumerate its subkeys looking for one which has a ProtocolId value
// equal to 'dwTransportId';
//
CWRg( regkeyIter.Init(&regkey) );
hrIter = regkeyIter.Next(&stKey);
for (; hrIter == hrOK; hrIter = regkeyIter.Next(&stKey))
{
//
// open the key
//
dwErr = regkeyRM.Open(regkey, stKey, KEY_READ);
CheckRegOpenError(dwErr, stKey, _T("QueryRmSoftwareKey"));
if (dwErr != ERROR_SUCCESS) { continue; }
//
// try to read the ProtocolId value
//
dwErr = regkeyRM.QueryValue(c_szProtocolId, dwProtocolId);
CheckRegQueryValueError(dwErr, stKey, c_szProtocolId, _T("QueryRmSoftwareKey"));
//
// Break if this is the transport we're looking for,
// otherwise close the key and continue
//
if ((dwErr == ERROR_SUCCESS) && (dwProtocolId == dwTransportId))
break;
regkeyRM.Close();
}
if (hrIter == hrOK)
{
//
// The transport was found, so save its key-name and key
//
Assert(((HKEY)regkeyRM) != 0);
if (lplpszRm)
*lplpszRm = StrDup((LPCTSTR) stKey);
bFound = TRUE;
*phkrm = regkeyRM.Detach();
}
Error:
if (FHrSucceeded(hr) && !bFound)
{
hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
}
return hr;
}
#ifdef _DEBUG
void CheckRegOpenErrorEx(DWORD dwError, LPCTSTR pszSubKey,
LPCTSTR pszDesc, LPCTSTR pszFile, int iLineNo)
{
if (dwError)
{
CString st;
st.Format(_T("RegOpenEx failed(%08lx)\nfile: %s\nline: %d\nDesc: %s\nkey: %s"),
dwError, pszFile, iLineNo,
pszDesc, pszSubKey);
if (AfxMessageBox(st, MB_OKCANCEL) == IDCANCEL)
{
DebugBreak();
}
}
}
void CheckRegQueryValueErrorEx(DWORD dwError, LPCTSTR pszSubKey,
LPCTSTR pszValue, LPCTSTR pszDesc,
LPCTSTR pszFile, int iLineNo)
{
if (dwError)
{
CString st;
st.Format(_T("RegQueryValue failed(%08lx)\nfile: %s\nline: %d\ndesc: %s\nkey: %s\nvalue: %s"),
dwError, pszFile, iLineNo, pszDesc, pszSubKey, pszValue);
if (AfxMessageBox(st, MB_OKCANCEL) == IDCANCEL)
{
DebugBreak();
}
}
}
#endif
/*!--------------------------------------------------------------------------
SetupFindInterfaceTitle
-
This function retrieves the title of the given interface.
The argument 'LpszIf' should contain the ID of the interface,
for instance "EPRO1".
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP SetupFindInterfaceTitle(LPCTSTR pszMachine,
LPCTSTR pszInterface,
LPTSTR *ppszTitle)
{
HRESULT hr = hrOK;
CString stMachine;
HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
HKEY hkMachine = NULL;
HKEY hkDevice= NULL;
CString stPnpInstanceId;
RegKey rkNet;
RegKey rkNetcard;
RegKey rkDevice;
RegKey rkConnection;
CString stBuffer, stPath;
CString stConnection;
TCHAR szClassGuid[128];
DWORD dwAction;
DWORD dwErr;
SP_DEVINFO_DATA DevInfo;
stMachine = pszMachine;
if (IsLocalMachine(stMachine))
{
hDevInfo = SetupDiCreateDeviceInfoList(
(LPGUID) &GUID_DevClass_Net,
NULL);
}
else
{
// Append on the "\\\\" if needed
if (StrniCmp((LPCTSTR) stMachine, _T("\\\\"), 2) != 0)
{
stMachine = _T("\\\\");
stMachine += pszMachine;
}
hDevInfo = SetupDiCreateDeviceInfoListEx(
(LPGUID) &GUID_DevClass_Net,
NULL,
(LPCTSTR) stMachine,
0);
}
// Get hkMachine from system
// ----------------------------------------------------------------
CWRg( ConnectRegistry( (LPCTSTR) stMachine, &hkMachine) );
// Get the PnpInstanceID
// ----------------------------------------------------------------
CWRg( rkNet.Open(hkMachine, c_szNetworkCardsNT5Key, KEY_READ) );
CWRg( rkNetcard.Open(rkNet, pszInterface, KEY_READ) );
dwErr = rkNetcard.QueryValue(c_szPnpInstanceID, stPnpInstanceId);
if (dwErr != ERROR_SUCCESS)
{
RegKey rkConnection;
// Need to open another key to get this info.
CWRg( rkConnection.Open(rkNetcard, c_szRegKeyConnection, KEY_READ) );
CWRg( rkConnection.QueryValue(c_szPnpInstanceID, stPnpInstanceId) );
}
// Get hkDevice from SetupDiOpenDevRegKey
// Now get the info for this device
// ----------------------------------------------------------------
::ZeroMemory(&DevInfo, sizeof(DevInfo));
DevInfo.cbSize = sizeof(DevInfo);
if (!SetupDiOpenDeviceInfo(hDevInfo,
(LPCTSTR) stPnpInstanceId,
NULL,
0,
&DevInfo))
{
CWRg( GetLastError() );
}
// Now that we have the info, get the reg key
// ----------------------------------------------------------------
hkDevice = SetupDiOpenDevRegKey(hDevInfo,
&DevInfo,
DICS_FLAG_GLOBAL,
0,
DIREG_DRV,
KEY_READ);
if ((hkDevice == NULL) || (hkDevice == INVALID_HANDLE_VALUE))
{
CWRg( GetLastError() );
}
// Attach so that it will get freed up
// ----------------------------------------------------------------
rkDevice.Attach( hkDevice );
// Read in the netcfg instance
// ----------------------------------------------------------------
CWRg( rkDevice.QueryValue(c_szRegValNetCfgInstanceId, stBuffer) );
// Generate path in registry for lookup
StringFromGUID2(GUID_DevClass_Net,
szClassGuid,
DimensionOf(szClassGuid));
stPath.Format(_T("%s\\%s\\%s\\Connection"),
c_szRegKeyComponentClasses,
szClassGuid,
stBuffer);
// Open the key
CWRg( rkConnection.Open(hkMachine, stPath, KEY_READ) );
// Read in and store the connections name
CWRg( rkConnection.QueryValue(c_szRegValName, stConnection) );
*ppszTitle = StrDup((LPCTSTR) stConnection);
Error:
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);
if (hkMachine)
DisconnectRegistry( hkMachine );
return hr;
}
/*!--------------------------------------------------------------------------
RegFindInterfaceTitle
-
This function retrieves the title of the given interface.
The argument 'LpszIf' should contain the ID of the interface,
for instance "EPRO1".
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP RegFindInterfaceTitle(LPCTSTR pszMachine,
LPCTSTR pszInterface,
LPTSTR *ppszTitle)
{
HRESULT hr = hrOK;
DWORD dwErr;
HKEY hkeyMachine = NULL;
RegKey regkey;
RegKeyIterator regkeyIter;
HRESULT hrIter;
CString stKey;
RegKey regkeyCard;
CString stServiceName;
CString stTitle;
BOOL fNT4;
LPCTSTR pszKey;
CNetcardRegistryHelper ncreghelp;
COM_PROTECT_TRY
{
//
// connect to the registry
//
CWRg( ConnectRegistry(pszMachine, &hkeyMachine) );
CWRg( IsNT4Machine(hkeyMachine, &fNT4) );
//
// open HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards
//
pszKey = fNT4 ? c_szNetworkCardsKey : c_szNetworkCardsNT5Key;
CWRg( regkey.Open(hkeyMachine, pszKey, KEY_READ) );
//
// enumerate the subkeys, and for each key,
// see if it's the one we want
//
CWRg( regkeyIter.Init(&regkey) );
hrIter = regkeyIter.Next(&stKey);
for (; hrIter == hrOK; hrIter = regkeyIter.Next(&stKey))
{
hr = hrOK;
//
// now open the key
//
regkeyCard.Close();
dwErr = regkeyCard.Open(regkey, stKey, KEY_READ);
if (dwErr != ERROR_SUCCESS)
continue;
ncreghelp.Initialize(fNT4, regkeyCard, stKey,
pszMachine);
//
// read the ServiceName
//
//$NT5: the service name is not in the same format as NT4
// this will need to be done differently.
if (fNT4)
{
ncreghelp.ReadServiceName();
if (dwErr != ERROR_SUCCESS)
continue;
stServiceName = ncreghelp.GetServiceName();
}
else
stServiceName = pszKey;
//
// see if it's the one we're looking for
//
if (StriCmp(pszInterface, (LPCTSTR) stServiceName))
{
dwErr = ERROR_INVALID_HANDLE;
continue;
}
//
// this is the one; read the title
//
dwErr = ncreghelp.ReadTitle();
if (dwErr != NO_ERROR)
break;
stTitle = (LPCTSTR) ncreghelp.GetTitle();
*ppszTitle = StrDup((LPCTSTR) stTitle);
}
if (dwErr)
hr = HRESULT_FROM_WIN32(dwErr);
COM_PROTECT_ERROR_LABEL;
}
COM_PROTECT_CATCH;
if (hkeyMachine)
DisconnectRegistry(hkeyMachine);
return hr;
}
/*!--------------------------------------------------------------------------
RegFindRtrMgrTitle
-
This function retrieves the title of the given router-manager.
The argument 'dwTransportId' should contain the ID of the router-manager,
for instance PID_IP.
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP RegFindRtrMgrTitle(LPCTSTR pszMachine,
DWORD dwTransportId,
LPTSTR *ppszTitle)
{
HRESULT hr = hrOK;
HKEY hkey, hkeyMachine = 0;
RegKey regkey;
CString stValue;
COM_PROTECT_TRY
{
//
// connect to the registry
//
CWRg( ConnectRegistry(pszMachine, &hkeyMachine) );
//
// open the key for the router-manager
// under HKLM\Software\Microsoft\Router\RouterManagers
//
CORg( FindRmSoftwareKey(hkeyMachine, dwTransportId, &hkey, NULL) );
regkey.Attach(hkey);
//
// Now find the "Title" value
//
CWRg( regkey.QueryValue( c_szTitle, stValue ) );
// Copy the output data
*ppszTitle = StrDup((LPCTSTR) stValue);
COM_PROTECT_ERROR_LABEL;
}
COM_PROTECT_CATCH;
if (hkeyMachine)
DisconnectRegistry(hkeyMachine);
return hr;
}
/*!--------------------------------------------------------------------------
QueryRouterVersionInfo
-
Author: KennT
---------------------------------------------------------------------------*/
TFSCORE_API(HRESULT) QueryRouterVersionInfo(HKEY hkeyMachine,
RouterVersionInfo *pVerInfo)
{
// Look at the HKLM\Software\Microsoft\Windows NT\CurrentVersion
// CurrentVersion = REG_SZ "4.0"
CString skey;
DWORD dwErr;
TCHAR szData[64];
RegKey regkey;
BOOL fNt4;
DWORD dwMajorVer, dwMinorVer, dwBuildNumber;
DWORD dwConfigured;
DWORD dwSPVer = 0;
DWORD dwOsFlags = 0;
skey = c_szSoftware;
skey += TEXT('\\');
skey += c_szMicrosoft;
skey += TEXT('\\');
skey += c_szWindowsNT;
skey += TEXT('\\');
skey += c_szCurrentVersion;
Assert(hkeyMachine != NULL);
Assert(hkeyMachine != INVALID_HANDLE_VALUE);
dwErr = regkey.Open(hkeyMachine, (LPCTSTR) skey, KEY_READ);
CheckRegOpenError(dwErr, (LPCTSTR) skey, _T("IsNT4Machine"));
if (dwErr != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(dwErr);
// Ok, now try to get the current version value
dwErr = regkey.QueryValue( c_szCurrentVersion, szData,
sizeof(szData),
FALSE);
CheckRegQueryValueError(dwErr, (LPCTSTR) skey, c_szCurrentVersion,
_T("QueryRouterVersionInfo"));
if (dwErr == ERROR_SUCCESS)
{
int nPos;
int nLength;
CString stData;
stData = szData;
nPos = stData.Find(_T('.'));
nLength = stData.GetLength();
// This assumes that
// CurrentVersion : REG_SZ : Major.Minor.XX.XX
// ------------------------------------------------------------
// Pick out the major version from the string
// ------------------------------------------------------------
dwMajorVer = _ttoi(stData.Left(nPos));
// Pick out the minor version
// ------------------------------------------------------------
dwMinorVer = _ttoi(stData.Right(nLength - nPos - 1));
}
// Get the build number
// ----------------------------------------------------------------
dwErr = regkey.QueryValue( c_szCurrentBuildNumber, szData,
sizeof(szData),
FALSE);
if (dwErr == ERROR_SUCCESS)
dwBuildNumber = _ttoi(szData);
// If this is an NT4 machine, look for the Software\Microsoft\Router
// registry key. If that doesn't exist, then this is a
// non-Steelhead router.
// ----------------------------------------------------------------
if ((dwErr == ERROR_SUCCESS) && (dwMajorVer < 5))
{
RegKey regkeyRouter;
dwErr = regkeyRouter.Open(hkeyMachine, c_szRegKeyRouter, KEY_READ);
if (dwErr != ERROR_SUCCESS)
dwOsFlags |= RouterSnapin_RASOnly;
// Ignore the return code
dwErr = ERROR_SUCCESS;
}
// Now get the SP version
// ----------------------------------------------------------------
dwErr = regkey.QueryValue( c_szCSDVersion, szData,
sizeof(szData),
FALSE);
if (dwErr == ERROR_SUCCESS)
dwSPVer = _ttoi(szData);
dwErr = ERROR_SUCCESS; // this could fail, so ignore return code
// Look at the router is configured flag
// ----------------------------------------------------------------
regkey.Close();
if (ERROR_SUCCESS == regkey.Open(hkeyMachine,c_szRemoteAccessKey) )
{
dwErr = regkey.QueryValue( c_szRtrConfigured, dwConfigured);
if (dwErr != ERROR_SUCCESS)
dwConfigured = FALSE;
// Ignore the return code
dwErr = ERROR_SUCCESS;
}
if (dwErr == ERROR_SUCCESS)
{
pVerInfo->dwRouterVersion = dwMajorVer;
pVerInfo->dwOsMajorVersion = dwMajorVer;
pVerInfo->dwOsMinorVersion = dwMinorVer;
pVerInfo->dwOsServicePack = dwSPVer;
pVerInfo->dwOsFlags |= (1 | dwOsFlags);
pVerInfo->dwRouterFlags = dwConfigured ? RouterSnapin_IsConfigured : 0;
// If this is NT4, then the default is the router is configured
if (dwMajorVer <= 4)
pVerInfo->dwRouterFlags |= RouterSnapin_IsConfigured;
pVerInfo->dwOsBuildNo = dwBuildNumber;
}
return HRESULT_FROM_WIN32(dwErr);
}