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.

376 lines
10 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // VerInfo.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CVersionInfo class.
  10. //
  11. // Author:
  12. // David Potter (davidp) October 11, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "VerInfo.h"
  21. #include "ExcOper.h"
  22. #include "TraceTag.h"
  23. #include "resource.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. /////////////////////////////////////////////////////////////////////////////
  30. // Global Variables
  31. /////////////////////////////////////////////////////////////////////////////
  32. #ifdef _DEBUG
  33. CTraceTag g_tagVersionInfo(_T("Misc"), _T("CVersionInfo"), 0);
  34. #endif
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CVersionInfo
  37. /////////////////////////////////////////////////////////////////////////////
  38. /////////////////////////////////////////////////////////////////////////////
  39. //++
  40. //
  41. // CVersionInfo::CVersionInfo
  42. //
  43. // Routine Description:
  44. // Default constructor.
  45. //
  46. // Arguments:
  47. // None.
  48. //
  49. // Return Value:
  50. // None.
  51. //
  52. //--
  53. /////////////////////////////////////////////////////////////////////////////
  54. CVersionInfo::CVersionInfo(void)
  55. {
  56. m_pbVerInfo = NULL;
  57. } //*** CVersionInfo::CVersionInfo()
  58. /////////////////////////////////////////////////////////////////////////////
  59. //++
  60. //
  61. // CVersionInfo::~CVersionInfo
  62. //
  63. // Routine Description:
  64. // Destructor.
  65. //
  66. // Arguments:
  67. // None.
  68. //
  69. // Return Value:
  70. // None.
  71. //
  72. //--
  73. /////////////////////////////////////////////////////////////////////////////
  74. CVersionInfo::~CVersionInfo(void)
  75. {
  76. delete [] m_pbVerInfo;
  77. } //*** CVersionInfo::~CVersionInfo()
  78. /////////////////////////////////////////////////////////////////////////////
  79. //++
  80. //
  81. // CVersionInfo::Init
  82. //
  83. // Routine Description:
  84. // Initialize the class instance.
  85. //
  86. // Arguments:
  87. // None.
  88. //
  89. // Return Value:
  90. // None.
  91. //
  92. // Exceptions Thrown:
  93. // CNTException Errors from GetModuleFileName(),
  94. // GetFileVersionInfoSize(), and
  95. // GetFileVersionInfo().
  96. // Any exceptions thrown by new[]().
  97. //--
  98. /////////////////////////////////////////////////////////////////////////////
  99. void CVersionInfo::Init(void)
  100. {
  101. TCHAR szExeName[MAX_PATH];
  102. DWORD dwVerHandle;
  103. DWORD cbVerInfo;
  104. ASSERT(m_pbVerInfo == NULL);
  105. // Get the name of the file from which to read version information.
  106. if (!::GetModuleFileName(
  107. AfxGetInstanceHandle(),
  108. szExeName,
  109. sizeof(szExeName) / sizeof(TCHAR)
  110. ))
  111. ThrowStaticException(::GetLastError());
  112. // Trace(...)
  113. try
  114. {
  115. // Get the size of the version information
  116. cbVerInfo = ::GetFileVersionInfoSize(szExeName, &dwVerHandle);
  117. if (cbVerInfo == 0)
  118. ThrowStaticException(::GetLastError());
  119. // Allocate the version info buffer.
  120. m_pbVerInfo = new BYTE[cbVerInfo];
  121. if ( m_pbVerInfo == NULL )
  122. {
  123. AfxThrowMemoryException();
  124. } // if: error allocating the version info buffer
  125. // Read the version info from the file.
  126. if (!::GetFileVersionInfo(szExeName, dwVerHandle, cbVerInfo, PbVerInfo()))
  127. ThrowStaticException(::GetLastError());
  128. } // try
  129. catch (CException *)
  130. {
  131. delete [] m_pbVerInfo;
  132. m_pbVerInfo = NULL;
  133. throw;
  134. } // catch: CException
  135. } //*** CVersionInfo::Init()
  136. /////////////////////////////////////////////////////////////////////////////
  137. //++
  138. //
  139. // CVersionInfo::PszQueryValue
  140. //
  141. // Routine Description:
  142. // Read a string value from the version resource.
  143. //
  144. // Arguments:
  145. // pszValueName [IN] Name of value to get.
  146. //
  147. // Return Value:
  148. // Pointer to value string buffer.
  149. // The string pointed to belongs to CVersionInfo and
  150. // is valid until the object is destructed.
  151. //
  152. // Exceptions Thrown:
  153. // CNTException Errors from VerQueryValue().
  154. // Any exceptions thrown by CString::Format().
  155. //--
  156. /////////////////////////////////////////////////////////////////////////////
  157. LPCTSTR CVersionInfo::PszQueryValue(IN LPCTSTR pszValueName)
  158. {
  159. CString strValueName;
  160. LPDWORD pdwTranslation;
  161. LPTSTR pszReturn;
  162. UINT cbReturn;
  163. UINT cchReturn;
  164. ASSERT(pszValueName != NULL);
  165. ASSERT(PbVerInfo() != NULL);
  166. // Get the LangID and CharSetID.
  167. strValueName = _T("\\VarFileInfo\\Translation");
  168. if (!::VerQueryValue(
  169. PbVerInfo(),
  170. (LPTSTR) (LPCTSTR) strValueName,
  171. (LPVOID *) &pdwTranslation,
  172. &cbReturn
  173. )
  174. || (cbReturn == 0))
  175. {
  176. pszReturn = NULL;
  177. } // if: error getting LangID and CharSetID
  178. else
  179. {
  180. // Construct the name of the value to read.
  181. strValueName.Format(
  182. _T("\\StringFileInfo\\%04X%04X\\%s"),
  183. LOWORD(*pdwTranslation), // LangID
  184. HIWORD(*pdwTranslation), // CharSetID
  185. pszValueName
  186. );
  187. Trace(g_tagVersionInfo, _T("Querying '%s'"), strValueName);
  188. // Read the value.
  189. if (!::VerQueryValue(
  190. PbVerInfo(),
  191. (LPTSTR) (LPCTSTR) strValueName,
  192. (LPVOID *) &pszReturn,
  193. &cchReturn
  194. )
  195. || (cchReturn == 0))
  196. pszReturn = NULL;
  197. } // else:
  198. #ifdef _DEBUG
  199. if (pszReturn != NULL)
  200. Trace(g_tagVersionInfo, _T("PszQueryValue(%s) = '%s'"), pszValueName, pszReturn);
  201. else
  202. Trace(g_tagVersionInfo, _T("PszQueryValue(%s) = Not Available"), pszValueName);
  203. #endif
  204. return pszReturn;
  205. } //*** CVersionInfo::PszQueryValue()
  206. /////////////////////////////////////////////////////////////////////////////
  207. //++
  208. //
  209. // CVersionInfo::BQueryValue
  210. //
  211. // Routine Description:
  212. // Read a value from the version resource.
  213. //
  214. // Arguments:
  215. // pszValueName [IN] Name of value to get.
  216. // rdwValue [OUT] DWORD in which to return the value.
  217. //
  218. // Return Value:
  219. // TRUE = success, FALSE = failure
  220. //
  221. // Exceptions Thrown:
  222. // None.
  223. //--
  224. /////////////////////////////////////////////////////////////////////////////
  225. BOOL CVersionInfo::BQueryValue(
  226. IN LPCTSTR pszValueName,
  227. OUT DWORD & rdwValue
  228. )
  229. {
  230. BOOL bSuccess;
  231. UINT cbReturn;
  232. DWORD * pdwValue;
  233. ASSERT(pszValueName != NULL);
  234. ASSERT(PbVerInfo() != NULL);
  235. // Read the value.
  236. if (!::VerQueryValue(
  237. PbVerInfo(),
  238. (LPTSTR) pszValueName,
  239. (LPVOID *) &pdwValue,
  240. &cbReturn
  241. )
  242. || (cbReturn == 0))
  243. bSuccess = FALSE;
  244. else
  245. {
  246. rdwValue = *pdwValue;
  247. bSuccess = TRUE;
  248. } // else: value read successfully
  249. #ifdef _DEBUG
  250. if (bSuccess)
  251. Trace(g_tagVersionInfo, _T("BQueryValue(%s) = '%lx'"), pszValueName, rdwValue);
  252. else
  253. Trace(g_tagVersionInfo, _T("BQueryValue(%s) = Not Available"), pszValueName);
  254. #endif
  255. return bSuccess;
  256. } //*** CVersionInfo::BQueryValue()
  257. /////////////////////////////////////////////////////////////////////////////
  258. //++
  259. //
  260. // CVersionInfo::PffiQueryValue
  261. //
  262. // Routine Description:
  263. // Read the VS_FIXEDFILEINFO information from the version resource.
  264. //
  265. // Arguments:
  266. // None.
  267. //
  268. // Return Value:
  269. // pffi Pointer to a VS_FIXEDFILEINFO structure. The buffer
  270. // pointerd to belongs to CVersionInfo and is valid
  271. // until the object is destructed.
  272. //
  273. // Exceptions Thrown:
  274. // CNTException Errors from VerQueryValue().
  275. // Any exceptions thrown by CString::Format().
  276. //--
  277. /////////////////////////////////////////////////////////////////////////////
  278. const VS_FIXEDFILEINFO * CVersionInfo::PffiQueryValue(void)
  279. {
  280. VS_FIXEDFILEINFO * pffi;
  281. UINT cbReturn;
  282. ASSERT(PbVerInfo() != NULL);
  283. // Read the FixedFileInfo.
  284. if (!::VerQueryValue(PbVerInfo(), _T("\\"), (LPVOID *) &pffi, &cbReturn)
  285. || (cbReturn == 0))
  286. pffi = NULL;
  287. #ifdef _DEBUG
  288. if (pffi != NULL)
  289. Trace(g_tagVersionInfo, _T("PffiQueryValue() version = %d.%d.%d.%d"),
  290. HIWORD(pffi->dwFileVersionMS),
  291. LOWORD(pffi->dwFileVersionMS),
  292. HIWORD(pffi->dwFileVersionLS),
  293. LOWORD(pffi->dwFileVersionLS));
  294. else
  295. Trace(g_tagVersionInfo, _T("PffiQueryValue() = Not Available"));
  296. #endif
  297. return pffi;
  298. } //*** CVersionInfo::PffiQueryValue()
  299. /////////////////////////////////////////////////////////////////////////////
  300. //++
  301. //
  302. // CVersionInfo::QueryFileVersionDisplayString
  303. //
  304. // Routine Description:
  305. // Read the file version as a display string from the version resource.
  306. //
  307. // Arguments:
  308. // rstrValue [OUT] String in which to return the version display string.
  309. //
  310. // Return Value:
  311. // None.
  312. //
  313. // Exceptions Thrown:
  314. // CNTException ERROR_RESOURCE_TYPE_NOT_FOUND.
  315. // Any exceptions thrown by CString::Format().
  316. //--
  317. /////////////////////////////////////////////////////////////////////////////
  318. void CVersionInfo::QueryFileVersionDisplayString(OUT CString & rstrValue)
  319. {
  320. const VS_FIXEDFILEINFO * pffi;
  321. // Get the file version information.
  322. pffi = PffiQueryValue();
  323. if (pffi == NULL)
  324. ThrowStaticException((SC) ERROR_RESOURCE_TYPE_NOT_FOUND);
  325. // Format the display string.
  326. rstrValue.Format(
  327. IDS_VERSION_NUMBER_FORMAT,
  328. HIWORD(pffi->dwFileVersionMS),
  329. LOWORD(pffi->dwFileVersionMS),
  330. HIWORD(pffi->dwFileVersionLS),
  331. LOWORD(pffi->dwFileVersionLS)
  332. );
  333. Trace(g_tagVersionInfo, _T("QueryFileVersionDisplayString() = %s"), rstrValue);
  334. } //*** CVersionInfo::QueryFileVersionDisplayString()