windows-nt/Source/XPSP1/NT/net/snmp/subagent/snmpevnt/evntwin/remote.cpp
2020-09-26 16:20:57 +08:00

372 lines
9.1 KiB
C++

//***********************************************************************
// remote.cpp
//
// This file contains code required to expand environment variables in the
// context of a remote machine. It does this by reading the environment variables
// from the remote machine's registry and caching them here.
//
// This file also contains code required to map local paths read out of the
// remote machine's registry into UNC paths such that c:\foo will be mapped
// to \\machine\c$\foo
//
// Author: Larry A. French
//
// History:
// 19-April-1996 Larry A. French
// Wrote it.
//
// Copyright (C) 1995, 1996 Microsoft Corporation. All rights reserved.
//
//************************************************************************
#include "stdafx.h"
#include "remote.h"
#include "trapreg.h"
#include "regkey.h"
CEnvCache::CEnvCache()
{
}
//*****************************************************************
// CEnvCache::GetEnvironmentVars
//
// Read the system environment variables for the remote machine out
// of its registry.
//
// Parameters:
// LPCTSTR pszMachine
// Pointer to the remote machine's name.
//
// CMapStringToString* pmapVars
// This string to string map is where the environment variables
// for the machine are returned.
//
// Returns:
// SCODE
// S_OK if everything was successful, otherwise E_FAIL.
//
//****************************************************************
SCODE CEnvCache::GetEnvironmentVars(LPCTSTR pszMachine, CMapStringToString* pmapVars)
{
CRegistryKey regkey; // SYSTEM\CurrentControlSet\Services\EventLogs
CRegistryValue regval;
static TCHAR* apszNames1[] = {
_T("SourcePath"),
_T("SystemRoot")
};
if (regkey.Connect(pszMachine) != ERROR_SUCCESS) {
goto CONNECT_FAILURE;
}
// First pick up the values for the SourcePath and SystemRoot environment variables and anything elese in
// apszNames1.
LONG nEntries;
LONG iEntry;
if (regkey.Open(_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), KEY_READ ) == ERROR_SUCCESS) {
nEntries = sizeof(apszNames1) / sizeof(TCHAR*);
for (iEntry=0; iEntry<nEntries; ++iEntry) {
if (regkey.GetValue(apszNames1[iEntry], regval)) {
pmapVars->SetAt(apszNames1[iEntry], (LPCTSTR) regval.m_pData);
}
}
regkey.Close();
}
// Now get the rest of the environment variables.
if (regkey.Open(_T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"), KEY_READ ) == ERROR_SUCCESS) {
CStringArray* pasValues = regkey.EnumValues();
if (pasValues != NULL) {
nEntries = (LONG)pasValues->GetSize();
for (iEntry=0; iEntry< nEntries; ++iEntry) {
CString sValueName = pasValues->GetAt(iEntry);
if (regkey.GetValue(sValueName, regval)) {
pmapVars->SetAt(sValueName, (LPCTSTR) regval.m_pData);
}
}
}
regkey.Close();
}
return S_OK;
CONNECT_FAILURE:
return E_FAIL;
}
SCODE CEnvCache::AddMachine(LPCTSTR pszMachine)
{
CMapStringToString* pmapVars;
if (m_mapMachine.Lookup(pszMachine, (CObject*&) pmapVars)) {
// The machine already has an entry, so don't add another
return E_FAIL;
}
pmapVars = new CMapStringToString;
m_mapMachine.SetAt(pszMachine, pmapVars);
SCODE sc = GetEnvironmentVars(pszMachine, pmapVars);
return sc;
}
//******************************************************************
// CEnvCache::Lookup
//
// Lookup an environment variable on the specified machine.
//
// Parameters:
// LPCTSTR pszMachineName
// Pointer to the machine name string.
//
// LPCTSTR pszName
// Pointer to the name of the environment variable to lookup.
//
// CString& sValue
// This is a reference to the place where the environment varaible's
// value is returned.
//
//
// Returns:
// SCODE
// S_OK if the environment variable was found.
// E_FAIL if the environment varaible was not found.
//
//*******************************************************************
SCODE CEnvCache::Lookup(LPCTSTR pszMachineName, LPCTSTR pszName, CString& sResult)
{
SCODE sc;
CMapStringToString* pmapVars;
// Get a pointer to the machine's cached map of environment variable values.
// If the map hasn't been loaded yet, do so now and try to get its map again.
if (!m_mapMachine.Lookup(pszMachineName, (CObject*&) pmapVars)) {
sc = AddMachine(pszMachineName);
if (FAILED(sc)) {
return sc;
}
if (!m_mapMachine.Lookup(pszMachineName, (CObject*&) pmapVars)) {
ASSERT(FALSE);
}
}
// Look for the variable name in the environment name map
if (pmapVars->Lookup(pszName, sResult)) {
return S_OK;
}
else {
return E_FAIL;
}
}
//****************************************************************
// RemoteExpandEnvStrings
//
// Epand a string that may contain environment variables in the
// context of a remote machine.
//
// Parameters:
// LPCTSTR pszComputerName
// A pointer to the name of the remote machine.
//
// CEnvCache& cache
// The environment variable cache for all machines. Note: the
// cached values for a particular machine are loaded when there
// is a reference to the machine.
//
// CString& sValue
// The string to expand. This string is expanded in-place such
// that on return, the string will contain the expanded values.
//
// Returns:
// SCODE
// S_OK if all strings were expanded
//
//******************************************************************
SCODE RemoteExpandEnvStrings(LPCTSTR pszComputerName, CEnvCache& cache, CString& sValue)
{
SCODE sc = S_OK;
LPCTSTR psz = sValue;
TCHAR ch;
CString sEnvVarName;
CString sEnvVarValue;
CString sResult;
LPCTSTR pszPercent = NULL;
while (ch = *psz++) {
if (ch == _T('%')) {
pszPercent = psz - 1;
sEnvVarName = _T("");
while (ch = *psz) {
++psz;
if (ch == _T('%')) {
SCODE sc;
sc = cache.Lookup(pszComputerName, sEnvVarName, sEnvVarValue);
if (SUCCEEDED(sc)) {
sResult += sEnvVarValue;
pszPercent = NULL;
}
else {
// If any environment variable is not found, then fail.
sc = E_FAIL;
}
break;
}
if (iswspace(ch) || ch==_T(';')) {
break;
}
sEnvVarName += ch;
}
if (pszPercent != NULL) {
// Control comes here if the opening percent was not matched by a closing
// percent.
while(pszPercent < psz) {
sResult += *pszPercent++;
}
}
}
else {
sResult += ch;
}
}
sValue = sResult;
return sc;
}
//************************************************************
// SplitComplexPath
//
// Split a complex path consisting of several semicolon separated
// paths into separate paths and return them in a string array.
//
// Parameters:
// LPCTSTR pszComplexPath
// Pointer to the path that may or may not be composed of
// several semicolon separated paths.
//
// CStringArray& saPath
// The place to return the split paths.
//
// Returns:
// The individual paths are returned via saPath
//
//*************************************************************
void SplitComplexPath(LPCTSTR pszComplexPath, CStringArray& saPath)
{
CString sPath;
while (*pszComplexPath) {
sPath.Empty();
while (isspace(*pszComplexPath)) {
++pszComplexPath;
}
while (*pszComplexPath &&
(*pszComplexPath != _T(';'))) {
sPath += *pszComplexPath++;
}
if (!sPath.IsEmpty()) {
saPath.Add(sPath);
}
if (*pszComplexPath==_T(';')) {
++pszComplexPath;
}
}
}
//**************************************************************************
// MapPathToUNC
//
// Map a path to the UNC equivallent. Note that this method assumes that
// for each path containing a drive letter that the target machine will have
// the path shared out. For example, if the path contains a "c:\foodir" prefix, then
// then you can get to "foodir" bygenerating the "\\machine\c$\foodir" path.
//
// Parameters:
// LPCTSTR pszMachineName
// Pointer to the machine name.
//
// CString& sPath
// Pointer to the path to map. Upon return, this string will contain
// the mapped path.
//
// Returns:
// SCODE
// S_OK if successful
// E_FAIL if something went wrong.
//
//**************************************************************************
SCODE MapPathToUNC(LPCTSTR pszMachineName, CString& sPath)
{
CStringArray saPaths;
SplitComplexPath(sPath, saPaths);
sPath.Empty();
LPCTSTR pszPath = sPath.GetBuffer(sPath.GetLength() + 1);
LONG nPaths = (LONG)saPaths.GetSize();
SCODE sc = S_OK;
for (LONG iPath=0; iPath < nPaths; ++iPath) {
pszPath = saPaths[iPath];
if (isalpha(pszPath[0]) && pszPath[1]==_T(':')) {
CString sResult;
sResult += _T("\\\\");
sResult += pszMachineName;
sResult += _T('\\');
sResult += pszPath[0]; // Drive letter
sResult += _T("$\\");
pszPath += 2;
if (pszPath[0]==_T('\\')) {
++pszPath;
}
sResult += pszPath;
saPaths[iPath] = sResult;
}
else {
sc = E_FAIL;
}
sPath += saPaths[iPath];
if (iPath < nPaths - 1) {
sPath += _T("; ");
}
}
return sc;
}