Leaked source code of windows server 2003
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.

436 lines
12 KiB

  1. // This file was originally stubexe.cpp (written by a-jsari), and was copied
  2. // to create stubmsd.cpp to generate an identical stub program for winmsd.
  3. //
  4. // Copyright (c) 1998-1999 Microsoft Corporation
  5. #include <afx.h>
  6. #include <afxwin.h>
  7. #include <io.h>
  8. #include <process.h>
  9. #include <errno.h>
  10. #include <iostream.h>
  11. #include "StdAfx.h"
  12. #include "Resource.h"
  13. #include "stubmsd.h"
  14. #ifndef HRESULT
  15. typedef long HRESULT;
  16. #endif
  17. // For Windows 95, the maximum length of a command line is 1024 characters.
  18. // Not sure what it is for NT.
  19. const int MAX_COMMAND_LINE = 1024;
  20. LPCTSTR cszDefaultDirectory = _T("\\Microsoft Shared\\MSInfo\\");
  21. LPCTSTR cszRegistryRoot = _T("Software\\Microsoft\\Shared Tools\\MSInfo");
  22. LPCTSTR cszDirectoryKey = _T("Path");
  23. LPCTSTR cszWindowsRoot = _T("Software\\Microsoft\\Windows\\CurrentVersion");
  24. LPCTSTR cszCommonFilesKey = _T("CommonFilesDir");
  25. CException *g_pException = NULL;
  26. // Microsoft Management Console is the program that hosts MSInfo.
  27. // This is a definition so that we can take its size.
  28. #define cszProgram _T("mmc.exe")
  29. /*
  30. * ThrowErrorException -
  31. *
  32. * History: a-jsari 10/14/97 Initial version.
  33. */
  34. inline void ThrowErrorException()
  35. {
  36. ::g_pException = new CException;
  37. if (::g_pException == NULL) ::AfxThrowMemoryException();
  38. throw ::g_pException;
  39. }
  40. /*
  41. * CSystemExecutable - The class that implements finding and running an
  42. * executable.
  43. *
  44. * History: a-jsari 10/14/97 Initial version.
  45. */
  46. class CSystemExecutable {
  47. public:
  48. CSystemExecutable(LPTSTR szProgram);
  49. ~CSystemExecutable() { DeleteStrings(); }
  50. void Run();
  51. void Find();
  52. void ProcessCommandLine();
  53. // Helper methods.
  54. protected:
  55. void DeleteStrings();
  56. void FindFileOnSystem(CString &szFileName, CString &szDestination);
  57. // Instance variables.
  58. protected:
  59. CString *m_pszPath;
  60. CString *m_pszProgramName;
  61. CString *m_pszCommandLine;
  62. };
  63. /*
  64. * CMSInfoExecutable - MSInfo-specific functions.
  65. *
  66. * History: a-jsari 10/15/97 Initial version
  67. */
  68. class CMSInfoExecutable : public CSystemExecutable {
  69. public:
  70. CMSInfoExecutable(LPTSTR szProgram);
  71. ~CMSInfoExecutable() {}
  72. BOOL ProcessCommandLine();
  73. private:
  74. void DeleteStrings();
  75. void FindMSInfoEXE();
  76. // Instance variables
  77. private:
  78. static const LPCTSTR cszMSInfo32;
  79. };
  80. const LPCTSTR CMSInfoExecutable::cszMSInfo32 = _T("msinfo32.exe");
  81. /*
  82. * CExecutable - Constructor which determines the type of the executable to
  83. * be executed.
  84. *
  85. * History: a-jsari 10/14/97 Initial version.
  86. */
  87. CSystemExecutable::CSystemExecutable(LPTSTR szProgram)
  88. :m_pszProgramName(new CString), m_pszPath(new CString), m_pszCommandLine(new CString)
  89. {
  90. if (!(m_pszProgramName && m_pszPath && m_pszCommandLine)) AfxThrowMemoryException();
  91. *m_pszProgramName = szProgram;
  92. }
  93. /*
  94. * DeleteStrings - Delete all of the strings used by the object. Used to free
  95. * our memory before calling exec.
  96. *
  97. * History: a-jsari 10/15/97 Initial version
  98. */
  99. void CSystemExecutable::DeleteStrings()
  100. {
  101. delete m_pszPath;
  102. m_pszPath = NULL;
  103. delete m_pszProgramName;
  104. m_pszProgramName = NULL;
  105. delete m_pszCommandLine;
  106. m_pszCommandLine = NULL;
  107. }
  108. /*
  109. * FindFileOnSystem - We may eventually put code here to test multiple
  110. * found copies and use the right one. But probably not.
  111. *
  112. * History: a-jsari 10/15/97 Stub version
  113. */
  114. void CSystemExecutable::FindFileOnSystem(CString &szFileName,
  115. CString &szDestination)
  116. {
  117. // Not reached.
  118. CFileFind FileFinder;
  119. BOOL bFindResult;
  120. bFindResult = FileFinder.FindFile(szFileName);
  121. if (!bFindResult) ThrowErrorException();
  122. szDestination = FileFinder.GetFilePath();
  123. #if 0
  124. // Choose among all versions of the file?
  125. while (bFindResult) {
  126. FileFinder.FindNextFile();
  127. }
  128. #endif
  129. }
  130. /*
  131. * Find - Return a pointer to a string containing the full path
  132. * to the MMC executable.
  133. *
  134. * History: a-jsari 10/13/97 Initial version
  135. */
  136. void CSystemExecutable::Find()
  137. {
  138. // We no longer call mmc, we instead call msinfo32.exe so that
  139. // winmsd appears to support all the same command line options
  140. // whatever they may be.
  141. #ifdef BUILD_MMC_COMMAND_LINE
  142. UINT uReturnSize;
  143. TCHAR szSystemDirectory[MAX_PATH + 1];
  144. uReturnSize = GetSystemDirectory(szSystemDirectory, MAX_PATH);
  145. if (uReturnSize == 0) ThrowErrorException();
  146. if (uReturnSize > MAX_PATH) {
  147. // Our buffer isn't big enough. This code will never get called.
  148. AfxThrowResourceException();
  149. }
  150. *m_pszPath += szSystemDirectory;
  151. *m_pszPath += _T("\\") + *m_pszProgramName;
  152. if (_taccess(*m_pszPath, A_READ) < 0) {
  153. // These may eventually want to be distinct exceptions.
  154. if (errno == ENOENT) {
  155. ThrowErrorException();
  156. } else {
  157. ASSERT(errno == EACCES);
  158. ThrowErrorException();
  159. }
  160. }
  161. #endif
  162. }
  163. /*
  164. * Run - Call exec with the parameters we so meticulously collected.
  165. *
  166. * History: a-jsari 10/15/97 Initial version.
  167. */
  168. void CSystemExecutable::Run()
  169. {
  170. #if !defined(UNICODE)
  171. TCHAR szPath[MAX_PATH + 1];
  172. TCHAR szProgramName[MAX_PATH + 1];
  173. TCHAR szCommandLine[MAX_COMMAND_LINE + 1];
  174. _tcsncpy(szPath, (LPCTSTR)*m_pszPath, sizeof(szPath)/sizeof(TCHAR));
  175. _tcsncpy(szProgramName, (LPCTSTR)*m_pszProgramName, sizeof(szProgramName)/sizeof(TCHAR));
  176. _tcsncpy(szCommandLine, (LPCTSTR)*m_pszCommandLine, sizeof(szCommandLine)/sizeof(TCHAR));
  177. DeleteStrings();
  178. ::_execlp(szPath, szProgramName, szCommandLine, 0);
  179. ThrowErrorException();
  180. #else
  181. char szPath[MAX_PATH + 1];
  182. char szProgramName[MAX_PATH + 1];
  183. char szCommandLine[MAX_COMMAND_LINE + 1];
  184. wcstombs(szPath, (LPCTSTR) *m_pszPath, MAX_PATH);
  185. wcstombs(szProgramName, (LPCTSTR) *m_pszProgramName, MAX_PATH);
  186. wcstombs(szCommandLine, (LPCTSTR) *m_pszCommandLine, MAX_COMMAND_LINE);
  187. DeleteStrings();
  188. ::_execlp(szPath, szProgramName, szCommandLine, 0);
  189. ThrowErrorException();
  190. #endif
  191. }
  192. /*
  193. * ProcessCommandLine - Pass all command line parameters to the called
  194. * executable.
  195. *
  196. * History: a-jsari 10/14/97 Initial version
  197. */
  198. void CSystemExecutable::ProcessCommandLine()
  199. {
  200. *m_pszCommandLine = GetCommandLine();
  201. // Skip over the first element in the line, which is the path to
  202. // the current executable. Preserve everything else.
  203. const int FIND_NO_MATCH = -1;
  204. int wIndex;
  205. m_pszCommandLine->TrimLeft();
  206. wIndex = m_pszCommandLine->FindOneOf(_T("\" \t\n"));
  207. if ((*m_pszCommandLine)[wIndex] == '"') {
  208. // This is the primary, if not guaranteed method.
  209. *m_pszCommandLine = m_pszCommandLine->Right(m_pszCommandLine->GetLength() - (wIndex + 1));
  210. wIndex = m_pszCommandLine->Find('"');
  211. *m_pszCommandLine = m_pszCommandLine->Right(m_pszCommandLine->GetLength() - (wIndex + 1));
  212. } else if (wIndex == FIND_NO_MATCH) {
  213. *m_pszCommandLine = _T("");
  214. } else {
  215. *m_pszCommandLine = m_pszCommandLine->Right(m_pszCommandLine->GetLength() - (wIndex + 1));
  216. }
  217. }
  218. /*
  219. * CMSInfoExecutable - Just pass all parameters to the base constructor.
  220. *
  221. * History: a-jsari 10/15/97 Initial version
  222. */
  223. CMSInfoExecutable::CMSInfoExecutable(LPTSTR szProgram)
  224. :CSystemExecutable(szProgram)
  225. {
  226. }
  227. /*
  228. * ProcessCommandLine - Process the command line parameters we can handle; pass on
  229. * the ones we can't, adding the saved console file.
  230. *
  231. * History: a-jsari 10/15/97 Initial version
  232. */
  233. BOOL CMSInfoExecutable::ProcessCommandLine()
  234. {
  235. // If the user specifies the "/?" switch on the winmsd.exe command line,
  236. // we need to inform the user that msinfo32.exe is the preferred way to
  237. // view the information now.
  238. CString strCommandLine = GetCommandLine();
  239. if (strCommandLine.Find(_T("/?")) != -1 && IDNO == ::AfxMessageBox(IDS_MSDNOTE, MB_YESNO))
  240. return FALSE;
  241. // builds m_pszCommandLine
  242. CSystemExecutable::ProcessCommandLine();
  243. FindMSInfoEXE();
  244. return TRUE;
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Locate the msinfo32.exe file. We'll look in the following places:
  248. //
  249. // 1. In the current directory.
  250. // 2. In the directory in the registry under:
  251. // HKLM\Software\Microsoft\Shared Tools\MSInfo\Path
  252. // 3a. In the directory %CommonFilesDir%\Microsoft Shared\MSInfo, where
  253. // %CommonFilesDir% is found in
  254. // HKLM\Software\Microsoft\Windows\CurrentVersion\CommonFilesDir.
  255. // 3b. Use the %CommonFilesDir% value with a subpath loaded from a
  256. // string resource.
  257. // 4. Last ditch is to look in a directory stored as a string resource
  258. // for this file.
  259. //-----------------------------------------------------------------------------
  260. void CMSInfoExecutable::FindMSInfoEXE()
  261. {
  262. m_pszPath->Empty();
  263. // First, check the current directory.
  264. if (::_taccess(_T("msinfo32.exe"), A_READ) == 0)
  265. {
  266. *m_pszPath = _T("msinfo32.exe");
  267. return;
  268. }
  269. // Second, use the path key in the MSInfo registry key.
  270. HKEY hkey;
  271. if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Shared Tools\\MSInfo"), 0, KEY_READ, &hkey))
  272. {
  273. DWORD dwType;
  274. TCHAR szDirectory[MAX_PATH + 1];
  275. DWORD dwKeyLength = MAX_PATH * sizeof(TCHAR);
  276. if (ERROR_SUCCESS == ::RegQueryValueEx(hkey, _T("path"), 0, &dwType, (BYTE *) szDirectory, &dwKeyLength))
  277. if (::_taccess(szDirectory, A_READ) == 0)
  278. {
  279. *m_pszPath = szDirectory;
  280. RegCloseKey(hkey);
  281. return;
  282. }
  283. RegCloseKey(hkey);
  284. }
  285. // Third, look for it in the %CommonFilesDir% directory. Look both in the hardcoded
  286. // subdirectory, and in a subdirectory loaded from a string resource.
  287. if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion"), 0, KEY_READ, &hkey))
  288. {
  289. DWORD dwKeyLength = MAX_PATH * sizeof(TCHAR);
  290. DWORD dwType;
  291. TCHAR szDirectory[MAX_PATH + 1];
  292. if (ERROR_SUCCESS == ::RegQueryValueEx(hkey, _T("CommonFilesDir"), 0, &dwType, (BYTE *) szDirectory, &dwKeyLength))
  293. {
  294. CString strTestPath(szDirectory);
  295. strTestPath += _T("\\Microsoft Shared\\MSInfo\\msinfo32.exe");
  296. if (::_taccess(strTestPath, A_READ) == 0)
  297. {
  298. *m_pszPath = strTestPath;
  299. RegCloseKey(hkey);
  300. return;
  301. }
  302. if (strTestPath.LoadString(IDS_COMMONFILES_SUBPATH))
  303. {
  304. strTestPath = CString(szDirectory) + strTestPath;
  305. if (::_taccess(strTestPath, A_READ) == 0)
  306. {
  307. *m_pszPath = strTestPath;
  308. RegCloseKey(hkey);
  309. return;
  310. }
  311. }
  312. }
  313. RegCloseKey(hkey);
  314. }
  315. // Finally, look for it using the string resource.
  316. CString strTestPath;
  317. if (strTestPath.LoadString(IDS_MSINFO_PATH))
  318. {
  319. TCHAR szExpandedPath[MAX_PATH];
  320. if (::ExpandEnvironmentStrings(strTestPath, szExpandedPath, MAX_PATH))
  321. if (::_taccess(szExpandedPath, A_READ) == 0)
  322. {
  323. *m_pszPath = szExpandedPath;
  324. return;
  325. }
  326. }
  327. CString szNoMSCFile;
  328. szNoMSCFile.LoadString(IDS_NOMSCFILE);
  329. ::AfxMessageBox(szNoMSCFile);
  330. ::ThrowErrorException();
  331. }
  332. /*
  333. * main - The main entry point for the stub executable.
  334. *
  335. * History: a-jsari 10/13/97 Initial version
  336. */
  337. BOOL CMSInfoApp::InitInstance()
  338. {
  339. CString szResText;
  340. CString szResTitle;
  341. // Shouldn't need this.
  342. do {
  343. try {
  344. // FIX: Pre-load the memory resource in case memory problems develop.
  345. CMSInfoExecutable exeMSInfo(cszProgram);
  346. exeMSInfo.Find();
  347. if (exeMSInfo.ProcessCommandLine())
  348. exeMSInfo.Run();
  349. // We never get past this on successful completion.
  350. }
  351. catch (CMemoryException *e_Mem) {
  352. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  353. VERIFY(szResText.LoadString(IDS_MEMORY));
  354. VERIFY(szResTitle.LoadString(IDS_DESCRIPTION));
  355. if (::MessageBox(NULL, szResText, szResTitle, MB_RETRYCANCEL | MB_ICONERROR) == IDCANCEL)
  356. break;
  357. continue;
  358. }
  359. catch (CException *e_Generic) {
  360. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  361. VERIFY(szResText.LoadString(IDS_UNEXPECTED));
  362. ::MessageBox(NULL, szResText, szResTitle, MB_OK | MB_ICONERROR);
  363. delete ::g_pException;
  364. break;
  365. }
  366. catch (...) {
  367. ASSERT(FALSE);
  368. break;
  369. }
  370. break;
  371. } while (TRUE);
  372. return FALSE;
  373. }