|
|
//============================================================================
// 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(®key) );
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(®key) );
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); }
|