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.

435 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. version.c
  5. Abstract:
  6. Implements calls to version APIs.
  7. Author:
  8. Calin Negreanu (calinn) 20-Jan-1999
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "utils.h"
  13. #include "version.h"
  14. static PCTSTR g_DefaultTranslations[] = {
  15. TEXT("04090000"),
  16. TEXT("040904E4"),
  17. TEXT("040904B0"),
  18. NULL
  19. };
  20. BOOL
  21. ShCreateVersionStruct (
  22. OUT PVERSION_STRUCT VersionStruct,
  23. IN PCTSTR FileSpec
  24. )
  25. /*++
  26. Routine Description:
  27. ShCreateVersionStruct is called to load a version structure from a file
  28. and to obtain the fixed version stamp info that is language-independent.
  29. The caller must call ShDestroyVersionStruct after the VersionStruct is no
  30. longer needed.
  31. Arguments:
  32. VersionStruct - Receives the version stamp info to be used by other
  33. functions in this module
  34. FileSpec - Specifies the file to obtain version info from
  35. Return Value:
  36. TRUE if the routine was able to get version info, or FALSE if an
  37. error occurred.
  38. --*/
  39. {
  40. ZeroMemory (VersionStruct, sizeof (VERSION_STRUCT));
  41. VersionStruct->FileSpec = FileSpec;
  42. //
  43. // Allocate enough memory for the version stamp
  44. //
  45. VersionStruct->Size = GetFileVersionInfoSize (
  46. (PTSTR) FileSpec,
  47. &VersionStruct->Handle
  48. );
  49. if (!VersionStruct->Size) {
  50. return FALSE;
  51. }
  52. VersionStruct->VersionBuffer = HeapAlloc (GetProcessHeap (), 0, VersionStruct->Size);
  53. if (!VersionStruct->VersionBuffer) {
  54. return FALSE;
  55. }
  56. VersionStruct->StringBuffer = HeapAlloc (GetProcessHeap (), 0, VersionStruct->Size);
  57. if (!VersionStruct->StringBuffer) {
  58. return FALSE;
  59. }
  60. //
  61. // Now get the version info from the file
  62. //
  63. if (!GetFileVersionInfo (
  64. (PTSTR) FileSpec,
  65. VersionStruct->Handle,
  66. VersionStruct->Size,
  67. VersionStruct->VersionBuffer
  68. )) {
  69. ShDestroyVersionStruct (VersionStruct);
  70. return FALSE;
  71. }
  72. //
  73. // Extract the fixed info
  74. //
  75. VerQueryValue (
  76. VersionStruct->VersionBuffer,
  77. TEXT("\\"),
  78. &VersionStruct->FixedInfo,
  79. &VersionStruct->FixedInfoSize
  80. );
  81. return TRUE;
  82. }
  83. VOID
  84. ShDestroyVersionStruct (
  85. IN PVERSION_STRUCT VersionStruct
  86. )
  87. /*++
  88. Routine Description:
  89. ShDestroyVersionStruct cleans up all memory allocated by the routines
  90. in this module.
  91. Arguments:
  92. VersionStruct - Specifies the structure to clean up
  93. Return Value:
  94. none
  95. --*/
  96. {
  97. if (VersionStruct->VersionBuffer) {
  98. HeapFree (GetProcessHeap (), 0, VersionStruct->VersionBuffer);
  99. }
  100. if (VersionStruct->StringBuffer) {
  101. HeapFree (GetProcessHeap (), 0, VersionStruct->StringBuffer);
  102. }
  103. ZeroMemory (VersionStruct, sizeof (VERSION_STRUCT));
  104. }
  105. ULONGLONG
  106. ShVerGetFileVer (
  107. IN PVERSION_STRUCT VersionStruct
  108. )
  109. {
  110. ULONGLONG result = 0;
  111. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  112. *((PDWORD) (&result)) = VersionStruct->FixedInfo->dwFileVersionLS;
  113. *(((PDWORD) (&result)) + 1) = VersionStruct->FixedInfo->dwFileVersionMS;
  114. }
  115. return result;
  116. }
  117. ULONGLONG
  118. ShVerGetProductVer (
  119. IN PVERSION_STRUCT VersionStruct
  120. )
  121. {
  122. ULONGLONG result = 0;
  123. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  124. *((PDWORD) (&result)) = VersionStruct->FixedInfo->dwProductVersionLS;
  125. *(((PDWORD) (&result)) + 1) = VersionStruct->FixedInfo->dwProductVersionMS;
  126. }
  127. return result;
  128. }
  129. DWORD
  130. ShVerGetFileDateLo (
  131. IN PVERSION_STRUCT VersionStruct
  132. )
  133. {
  134. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  135. return VersionStruct->FixedInfo->dwFileDateLS;
  136. }
  137. return 0;
  138. }
  139. DWORD
  140. ShVerGetFileDateHi (
  141. IN PVERSION_STRUCT VersionStruct
  142. )
  143. {
  144. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  145. return VersionStruct->FixedInfo->dwFileDateMS;
  146. }
  147. return 0;
  148. }
  149. DWORD
  150. ShVerGetFileVerOs (
  151. IN PVERSION_STRUCT VersionStruct
  152. )
  153. {
  154. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  155. return VersionStruct->FixedInfo->dwFileOS;
  156. }
  157. return 0;
  158. }
  159. DWORD
  160. ShVerGetFileVerType (
  161. IN PVERSION_STRUCT VersionStruct
  162. )
  163. {
  164. if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  165. return VersionStruct->FixedInfo->dwFileType;
  166. }
  167. return 0;
  168. }
  169. PCTSTR
  170. pShEnumVersionValueCommon (
  171. IN OUT PVERSION_STRUCT VersionStruct
  172. );
  173. PCTSTR
  174. pShEnumNextVersionTranslation (
  175. IN OUT PVERSION_STRUCT VersionStruct
  176. );
  177. PCTSTR
  178. pShEnumFirstVersionTranslation (
  179. IN OUT PVERSION_STRUCT VersionStruct
  180. )
  181. {
  182. UINT ArraySize;
  183. if (!VerQueryValue (
  184. VersionStruct->VersionBuffer,
  185. TEXT("\\VarFileInfo\\Translation"),
  186. &VersionStruct->Translations,
  187. &ArraySize
  188. )) {
  189. //
  190. // No translations are available
  191. //
  192. ArraySize = 0;
  193. }
  194. //
  195. // Return a pointer to the first translation
  196. //
  197. VersionStruct->CurrentDefaultTranslation = 0;
  198. VersionStruct->MaxTranslations = ArraySize / sizeof (TRANSLATION);
  199. VersionStruct->CurrentTranslation = 0;
  200. return pShEnumNextVersionTranslation (VersionStruct);
  201. }
  202. BOOL
  203. pShIsDefaultTranslation (
  204. IN PCTSTR TranslationStr
  205. )
  206. {
  207. INT i;
  208. for (i = 0 ; g_DefaultTranslations[i] ; i++) {
  209. if (lstrcmpi (TranslationStr, g_DefaultTranslations[i]) == 0) {
  210. return TRUE;
  211. }
  212. }
  213. return FALSE;
  214. }
  215. PCTSTR
  216. pShEnumNextVersionTranslation (
  217. IN OUT PVERSION_STRUCT VersionStruct
  218. )
  219. {
  220. PTRANSLATION Translation;
  221. if (g_DefaultTranslations[VersionStruct->CurrentDefaultTranslation]) {
  222. lstrcpy (VersionStruct->TranslationStr, g_DefaultTranslations[VersionStruct->CurrentDefaultTranslation]);
  223. VersionStruct->CurrentDefaultTranslation++;
  224. } else {
  225. do {
  226. if (VersionStruct->CurrentTranslation == VersionStruct->MaxTranslations) {
  227. return NULL;
  228. }
  229. Translation = &VersionStruct->Translations[VersionStruct->CurrentTranslation];
  230. wsprintf (
  231. VersionStruct->TranslationStr,
  232. TEXT("%04x%04x"),
  233. Translation->CodePage,
  234. Translation->Language
  235. );
  236. VersionStruct->CurrentTranslation++;
  237. } while (pShIsDefaultTranslation (VersionStruct->TranslationStr));
  238. }
  239. return VersionStruct->TranslationStr;
  240. }
  241. PCTSTR
  242. pShEnumNextVersionValue (
  243. IN OUT PVERSION_STRUCT VersionStruct
  244. )
  245. {
  246. PCTSTR rc = NULL;
  247. do {
  248. if (!pShEnumNextVersionTranslation (VersionStruct)) {
  249. break;
  250. }
  251. rc = pShEnumVersionValueCommon (VersionStruct);
  252. } while (!rc);
  253. return rc;
  254. }
  255. PCTSTR
  256. pShEnumFirstVersionValue (
  257. IN OUT PVERSION_STRUCT VersionStruct,
  258. IN PCTSTR VersionField
  259. )
  260. {
  261. PCTSTR rc;
  262. if (!pShEnumFirstVersionTranslation (VersionStruct)) {
  263. return NULL;
  264. }
  265. VersionStruct->VersionField = VersionField;
  266. rc = pShEnumVersionValueCommon (VersionStruct);
  267. if (!rc) {
  268. rc = pShEnumNextVersionValue (VersionStruct);
  269. }
  270. return rc;
  271. }
  272. PCTSTR
  273. pShEnumVersionValueCommon (
  274. IN OUT PVERSION_STRUCT VersionStruct
  275. )
  276. {
  277. PTSTR Text;
  278. UINT StringLen;
  279. PBYTE String;
  280. PCTSTR Result = NULL;
  281. //
  282. // Prepare sub block for VerQueryValue API
  283. //
  284. Text = HeapAlloc (GetProcessHeap (), 0, (18 + lstrlen (VersionStruct->TranslationStr) + lstrlen (VersionStruct->VersionField)) * sizeof (TCHAR));
  285. if (!Text) {
  286. return NULL;
  287. }
  288. wsprintf (
  289. Text,
  290. TEXT("\\StringFileInfo\\%s\\%s"),
  291. VersionStruct->TranslationStr,
  292. VersionStruct->VersionField
  293. );
  294. __try {
  295. //
  296. // Get the value from the version stamp
  297. //
  298. if (!VerQueryValue (
  299. VersionStruct->VersionBuffer,
  300. Text,
  301. &String,
  302. &StringLen
  303. )) {
  304. //
  305. // No value is available
  306. //
  307. return NULL;
  308. }
  309. CopyMemory (VersionStruct->StringBuffer, String, StringLen * sizeof (TCHAR));
  310. VersionStruct->StringBuffer [StringLen * sizeof (TCHAR)] = 0;
  311. Result = (PTSTR) VersionStruct->StringBuffer;
  312. }
  313. __finally {
  314. HeapFree (GetProcessHeap (), 0, Text);
  315. }
  316. return Result;
  317. }
  318. BOOL
  319. ShGlobalVersionCheck (
  320. IN PVERSION_STRUCT VersionData,
  321. IN PCTSTR NameToCheck,
  322. IN PCTSTR ValueToCheck
  323. )
  324. {
  325. PCTSTR CurrentStr;
  326. BOOL result = FALSE;
  327. CurrentStr = pShEnumFirstVersionValue (VersionData, NameToCheck);
  328. while (CurrentStr) {
  329. if (ShIsPatternMatch (ValueToCheck, CurrentStr)) {
  330. result = TRUE;
  331. break;
  332. }
  333. CurrentStr = pShEnumNextVersionValue (VersionData);
  334. }
  335. return result;
  336. }