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.

371 lines
9.1 KiB

  1. //***********************************************************************
  2. // remote.cpp
  3. //
  4. // This file contains code required to expand environment variables in the
  5. // context of a remote machine. It does this by reading the environment variables
  6. // from the remote machine's registry and caching them here.
  7. //
  8. // This file also contains code required to map local paths read out of the
  9. // remote machine's registry into UNC paths such that c:\foo will be mapped
  10. // to \\machine\c$\foo
  11. //
  12. // Author: Larry A. French
  13. //
  14. // History:
  15. // 19-April-1996 Larry A. French
  16. // Wrote it.
  17. //
  18. // Copyright (C) 1995, 1996 Microsoft Corporation. All rights reserved.
  19. //
  20. //************************************************************************
  21. #include "stdafx.h"
  22. #include "remote.h"
  23. #include "trapreg.h"
  24. #include "regkey.h"
  25. CEnvCache::CEnvCache()
  26. {
  27. }
  28. //*****************************************************************
  29. // CEnvCache::GetEnvironmentVars
  30. //
  31. // Read the system environment variables for the remote machine out
  32. // of its registry.
  33. //
  34. // Parameters:
  35. // LPCTSTR pszMachine
  36. // Pointer to the remote machine's name.
  37. //
  38. // CMapStringToString* pmapVars
  39. // This string to string map is where the environment variables
  40. // for the machine are returned.
  41. //
  42. // Returns:
  43. // SCODE
  44. // S_OK if everything was successful, otherwise E_FAIL.
  45. //
  46. //****************************************************************
  47. SCODE CEnvCache::GetEnvironmentVars(LPCTSTR pszMachine, CMapStringToString* pmapVars)
  48. {
  49. CRegistryKey regkey; // SYSTEM\CurrentControlSet\Services\EventLogs
  50. CRegistryValue regval;
  51. static TCHAR* apszNames1[] = {
  52. _T("SourcePath"),
  53. _T("SystemRoot")
  54. };
  55. if (regkey.Connect(pszMachine) != ERROR_SUCCESS) {
  56. goto CONNECT_FAILURE;
  57. }
  58. // First pick up the values for the SourcePath and SystemRoot environment variables and anything elese in
  59. // apszNames1.
  60. LONG nEntries;
  61. LONG iEntry;
  62. if (regkey.Open(_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), KEY_READ ) == ERROR_SUCCESS) {
  63. nEntries = sizeof(apszNames1) / sizeof(TCHAR*);
  64. for (iEntry=0; iEntry<nEntries; ++iEntry) {
  65. if (regkey.GetValue(apszNames1[iEntry], regval)) {
  66. pmapVars->SetAt(apszNames1[iEntry], (LPCTSTR) regval.m_pData);
  67. }
  68. }
  69. regkey.Close();
  70. }
  71. // Now get the rest of the environment variables.
  72. if (regkey.Open(_T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"), KEY_READ ) == ERROR_SUCCESS) {
  73. CStringArray* pasValues = regkey.EnumValues();
  74. if (pasValues != NULL) {
  75. nEntries = (LONG)pasValues->GetSize();
  76. for (iEntry=0; iEntry< nEntries; ++iEntry) {
  77. CString sValueName = pasValues->GetAt(iEntry);
  78. if (regkey.GetValue(sValueName, regval)) {
  79. pmapVars->SetAt(sValueName, (LPCTSTR) regval.m_pData);
  80. }
  81. }
  82. }
  83. regkey.Close();
  84. }
  85. return S_OK;
  86. CONNECT_FAILURE:
  87. return E_FAIL;
  88. }
  89. SCODE CEnvCache::AddMachine(LPCTSTR pszMachine)
  90. {
  91. CMapStringToString* pmapVars;
  92. if (m_mapMachine.Lookup(pszMachine, (CObject*&) pmapVars)) {
  93. // The machine already has an entry, so don't add another
  94. return E_FAIL;
  95. }
  96. pmapVars = new CMapStringToString;
  97. m_mapMachine.SetAt(pszMachine, pmapVars);
  98. SCODE sc = GetEnvironmentVars(pszMachine, pmapVars);
  99. return sc;
  100. }
  101. //******************************************************************
  102. // CEnvCache::Lookup
  103. //
  104. // Lookup an environment variable on the specified machine.
  105. //
  106. // Parameters:
  107. // LPCTSTR pszMachineName
  108. // Pointer to the machine name string.
  109. //
  110. // LPCTSTR pszName
  111. // Pointer to the name of the environment variable to lookup.
  112. //
  113. // CString& sValue
  114. // This is a reference to the place where the environment varaible's
  115. // value is returned.
  116. //
  117. //
  118. // Returns:
  119. // SCODE
  120. // S_OK if the environment variable was found.
  121. // E_FAIL if the environment varaible was not found.
  122. //
  123. //*******************************************************************
  124. SCODE CEnvCache::Lookup(LPCTSTR pszMachineName, LPCTSTR pszName, CString& sResult)
  125. {
  126. SCODE sc;
  127. CMapStringToString* pmapVars;
  128. // Get a pointer to the machine's cached map of environment variable values.
  129. // If the map hasn't been loaded yet, do so now and try to get its map again.
  130. if (!m_mapMachine.Lookup(pszMachineName, (CObject*&) pmapVars)) {
  131. sc = AddMachine(pszMachineName);
  132. if (FAILED(sc)) {
  133. return sc;
  134. }
  135. if (!m_mapMachine.Lookup(pszMachineName, (CObject*&) pmapVars)) {
  136. ASSERT(FALSE);
  137. }
  138. }
  139. // Look for the variable name in the environment name map
  140. if (pmapVars->Lookup(pszName, sResult)) {
  141. return S_OK;
  142. }
  143. else {
  144. return E_FAIL;
  145. }
  146. }
  147. //****************************************************************
  148. // RemoteExpandEnvStrings
  149. //
  150. // Epand a string that may contain environment variables in the
  151. // context of a remote machine.
  152. //
  153. // Parameters:
  154. // LPCTSTR pszComputerName
  155. // A pointer to the name of the remote machine.
  156. //
  157. // CEnvCache& cache
  158. // The environment variable cache for all machines. Note: the
  159. // cached values for a particular machine are loaded when there
  160. // is a reference to the machine.
  161. //
  162. // CString& sValue
  163. // The string to expand. This string is expanded in-place such
  164. // that on return, the string will contain the expanded values.
  165. //
  166. // Returns:
  167. // SCODE
  168. // S_OK if all strings were expanded
  169. //
  170. //******************************************************************
  171. SCODE RemoteExpandEnvStrings(LPCTSTR pszComputerName, CEnvCache& cache, CString& sValue)
  172. {
  173. SCODE sc = S_OK;
  174. LPCTSTR psz = sValue;
  175. TCHAR ch;
  176. CString sEnvVarName;
  177. CString sEnvVarValue;
  178. CString sResult;
  179. LPCTSTR pszPercent = NULL;
  180. while (ch = *psz++) {
  181. if (ch == _T('%')) {
  182. pszPercent = psz - 1;
  183. sEnvVarName = _T("");
  184. while (ch = *psz) {
  185. ++psz;
  186. if (ch == _T('%')) {
  187. SCODE sc;
  188. sc = cache.Lookup(pszComputerName, sEnvVarName, sEnvVarValue);
  189. if (SUCCEEDED(sc)) {
  190. sResult += sEnvVarValue;
  191. pszPercent = NULL;
  192. }
  193. else {
  194. // If any environment variable is not found, then fail.
  195. sc = E_FAIL;
  196. }
  197. break;
  198. }
  199. if (iswspace(ch) || ch==_T(';')) {
  200. break;
  201. }
  202. sEnvVarName += ch;
  203. }
  204. if (pszPercent != NULL) {
  205. // Control comes here if the opening percent was not matched by a closing
  206. // percent.
  207. while(pszPercent < psz) {
  208. sResult += *pszPercent++;
  209. }
  210. }
  211. }
  212. else {
  213. sResult += ch;
  214. }
  215. }
  216. sValue = sResult;
  217. return sc;
  218. }
  219. //************************************************************
  220. // SplitComplexPath
  221. //
  222. // Split a complex path consisting of several semicolon separated
  223. // paths into separate paths and return them in a string array.
  224. //
  225. // Parameters:
  226. // LPCTSTR pszComplexPath
  227. // Pointer to the path that may or may not be composed of
  228. // several semicolon separated paths.
  229. //
  230. // CStringArray& saPath
  231. // The place to return the split paths.
  232. //
  233. // Returns:
  234. // The individual paths are returned via saPath
  235. //
  236. //*************************************************************
  237. void SplitComplexPath(LPCTSTR pszComplexPath, CStringArray& saPath)
  238. {
  239. CString sPath;
  240. while (*pszComplexPath) {
  241. sPath.Empty();
  242. while (isspace(*pszComplexPath)) {
  243. ++pszComplexPath;
  244. }
  245. while (*pszComplexPath &&
  246. (*pszComplexPath != _T(';'))) {
  247. sPath += *pszComplexPath++;
  248. }
  249. if (!sPath.IsEmpty()) {
  250. saPath.Add(sPath);
  251. }
  252. if (*pszComplexPath==_T(';')) {
  253. ++pszComplexPath;
  254. }
  255. }
  256. }
  257. //**************************************************************************
  258. // MapPathToUNC
  259. //
  260. // Map a path to the UNC equivallent. Note that this method assumes that
  261. // for each path containing a drive letter that the target machine will have
  262. // the path shared out. For example, if the path contains a "c:\foodir" prefix, then
  263. // then you can get to "foodir" bygenerating the "\\machine\c$\foodir" path.
  264. //
  265. // Parameters:
  266. // LPCTSTR pszMachineName
  267. // Pointer to the machine name.
  268. //
  269. // CString& sPath
  270. // Pointer to the path to map. Upon return, this string will contain
  271. // the mapped path.
  272. //
  273. // Returns:
  274. // SCODE
  275. // S_OK if successful
  276. // E_FAIL if something went wrong.
  277. //
  278. //**************************************************************************
  279. SCODE MapPathToUNC(LPCTSTR pszMachineName, CString& sPath)
  280. {
  281. CStringArray saPaths;
  282. SplitComplexPath(sPath, saPaths);
  283. sPath.Empty();
  284. LPCTSTR pszPath = sPath.GetBuffer(sPath.GetLength() + 1);
  285. LONG nPaths = (LONG)saPaths.GetSize();
  286. SCODE sc = S_OK;
  287. for (LONG iPath=0; iPath < nPaths; ++iPath) {
  288. pszPath = saPaths[iPath];
  289. if (isalpha(pszPath[0]) && pszPath[1]==_T(':')) {
  290. CString sResult;
  291. sResult += _T("\\\\");
  292. sResult += pszMachineName;
  293. sResult += _T('\\');
  294. sResult += pszPath[0]; // Drive letter
  295. sResult += _T("$\\");
  296. pszPath += 2;
  297. if (pszPath[0]==_T('\\')) {
  298. ++pszPath;
  299. }
  300. sResult += pszPath;
  301. saPaths[iPath] = sResult;
  302. }
  303. else {
  304. sc = E_FAIL;
  305. }
  306. sPath += saPaths[iPath];
  307. if (iPath < nPaths - 1) {
  308. sPath += _T("; ");
  309. }
  310. }
  311. return sc;
  312. }