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.

1236 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. version.c
  5. Abstract:
  6. Implements a set of enumeration routines to access version
  7. information from a Win32 binary.
  8. Author:
  9. Jim Schmidt (jimschm) 03-Dec-1997
  10. Revision History:
  11. calinn 03-Sep-1999 Moved over from Win9xUpg project.
  12. --*/
  13. //
  14. // Includes
  15. //
  16. #include "pch.h"
  17. //
  18. // Debug constants
  19. //
  20. #define DBG_VERSION "VerAPI"
  21. //
  22. // Strings
  23. //
  24. // None
  25. //
  26. // Constants
  27. //
  28. // None
  29. //
  30. // Macros
  31. //
  32. // None
  33. //
  34. // Types
  35. //
  36. // None
  37. //
  38. // Globals
  39. //
  40. PCSTR g_DefaultTranslationsA[] = {
  41. "04090000",
  42. "040904E4",
  43. "040904B0",
  44. NULL
  45. };
  46. PCWSTR g_DefaultTranslationsW[] = {
  47. L"04090000",
  48. L"040904E4",
  49. L"040904B0",
  50. NULL
  51. };
  52. //
  53. // Macro expansion list
  54. //
  55. // None
  56. //
  57. // Private function prototypes
  58. //
  59. PCSTR
  60. pVrEnumValueA (
  61. IN OUT PVRVALUE_ENUMA VrValueEnum
  62. );
  63. PCWSTR
  64. pVrEnumValueW (
  65. IN OUT PVRVALUE_ENUMW VrValueEnum
  66. );
  67. PCSTR
  68. pVrEnumNextTranslationA (
  69. IN OUT PVRVALUE_ENUMA VrValueEnum
  70. );
  71. PCWSTR
  72. pVrEnumNextTranslationW (
  73. IN OUT PVRVALUE_ENUMW VrValueEnum
  74. );
  75. //
  76. // Macro expansion definition
  77. //
  78. // None
  79. //
  80. // Code
  81. //
  82. /*++
  83. Routine Description:
  84. VrCreateEnumStructA and VrCreateEnumStructW are called to load a version
  85. structure from a file and to obtain the fixed version stamp info that is
  86. language-independent.
  87. The caller must call VrDestroyEnumStruct after the VrValueEnum is no
  88. longer needed.
  89. Arguments:
  90. VrValueEnum - Receives the version stamp info to be used by other
  91. functions in this module
  92. FileSpec - Specifies the file to obtain version information from
  93. Return Value:
  94. TRUE if the routine was able to get version info, or FALSE if an
  95. error occurred.
  96. --*/
  97. BOOL
  98. VrCreateEnumStructA (
  99. OUT PVRVALUE_ENUMA VrValueEnum,
  100. IN PCSTR FileSpec
  101. )
  102. {
  103. //
  104. // Initialize the structure
  105. //
  106. ZeroMemory (VrValueEnum, sizeof (VRVALUE_ENUMA));
  107. VrValueEnum->FileSpec = FileSpec;
  108. //
  109. // Allocate enough memory for the version stamp
  110. //
  111. VrValueEnum->Size = GetFileVersionInfoSizeA (
  112. (PSTR) FileSpec,
  113. &VrValueEnum->Handle
  114. );
  115. if (!VrValueEnum->Size) {
  116. DEBUGMSG ((DBG_VERSION, "File %s does not have version information", FileSpec));
  117. return FALSE;
  118. }
  119. //
  120. // fix for version info bug:
  121. // allocate both buffers at once; this way the first buffer will not point to invalid
  122. // memory when a reallocation occurs because of the second grow
  123. //
  124. VrValueEnum->VersionBuffer = GbGrow (&VrValueEnum->GrowBuf, VrValueEnum->Size * 2);
  125. if (!VrValueEnum->VersionBuffer) {
  126. return FALSE;
  127. }
  128. VrValueEnum->StringBuffer = VrValueEnum->GrowBuf.Buf + VrValueEnum->Size;
  129. //
  130. // Now get the version info from the file
  131. //
  132. if (!GetFileVersionInfoA (
  133. (PSTR) FileSpec,
  134. VrValueEnum->Handle,
  135. VrValueEnum->Size,
  136. VrValueEnum->VersionBuffer
  137. )) {
  138. VrDestroyEnumStructA (VrValueEnum);
  139. return FALSE;
  140. }
  141. //
  142. // Extract the fixed info
  143. //
  144. VerQueryValueA (
  145. VrValueEnum->VersionBuffer,
  146. "\\",
  147. &VrValueEnum->FixedInfo,
  148. &VrValueEnum->FixedInfoSize
  149. );
  150. return TRUE;
  151. }
  152. BOOL
  153. VrCreateEnumStructW (
  154. OUT PVRVALUE_ENUMW VrValueEnum,
  155. IN PCWSTR FileSpec
  156. )
  157. {
  158. ZeroMemory (VrValueEnum, sizeof (VRVALUE_ENUMW));
  159. VrValueEnum->FileSpec = FileSpec;
  160. //
  161. // Allocate enough memory for the version stamp
  162. //
  163. VrValueEnum->Size = GetFileVersionInfoSizeW (
  164. (PWSTR) FileSpec,
  165. &VrValueEnum->Handle
  166. );
  167. if (!VrValueEnum->Size) {
  168. DEBUGMSG ((DBG_VERSION, "File %S does not have version info", FileSpec));
  169. return FALSE;
  170. }
  171. //
  172. // fix for version info bug:
  173. // allocate both buffers at once; this way the first buffer will not point to invalid
  174. // memory when a reallocation occurs because of the second grow
  175. //
  176. VrValueEnum->VersionBuffer = GbGrow (&VrValueEnum->GrowBuf, VrValueEnum->Size * 2);
  177. if (!VrValueEnum->VersionBuffer) {
  178. return FALSE;
  179. }
  180. VrValueEnum->StringBuffer = VrValueEnum->GrowBuf.Buf + VrValueEnum->Size;
  181. //
  182. // Now get the version info from the file
  183. //
  184. if (!GetFileVersionInfoW (
  185. (PWSTR) FileSpec,
  186. VrValueEnum->Handle,
  187. VrValueEnum->Size,
  188. VrValueEnum->VersionBuffer
  189. )) {
  190. VrDestroyEnumStructW (VrValueEnum);
  191. return FALSE;
  192. }
  193. //
  194. // Extract the fixed info
  195. //
  196. VerQueryValueW (
  197. VrValueEnum->VersionBuffer,
  198. L"\\",
  199. &VrValueEnum->FixedInfo,
  200. &VrValueEnum->FixedInfoSize
  201. );
  202. return TRUE;
  203. }
  204. /*++
  205. Routine Description:
  206. VrDestroyEnumStructA and VrDestroyEnumStructW cleans up all memory
  207. allocated by the routines in this module.
  208. Arguments:
  209. VrValueEnum - Specifies the structure to clean up
  210. Return Value:
  211. none
  212. --*/
  213. VOID
  214. VrDestroyEnumStructA (
  215. IN PVRVALUE_ENUMA VrValueEnum
  216. )
  217. {
  218. //
  219. // Clean up all allocations made by any routine using
  220. // the VrValueEnum
  221. //
  222. if (VrValueEnum->GrowBuf.Buf) {
  223. GbFree (&VrValueEnum->GrowBuf);
  224. }
  225. ZeroMemory (VrValueEnum, sizeof (VRVALUE_ENUMA));
  226. }
  227. VOID
  228. VrDestroyEnumStructW (
  229. IN PVRVALUE_ENUMW VrValueEnum
  230. )
  231. {
  232. //
  233. // Clean up all allocations made by any routine using
  234. // the VrValueEnum
  235. //
  236. if (VrValueEnum->GrowBuf.Buf) {
  237. GbFree (&VrValueEnum->GrowBuf);
  238. }
  239. ZeroMemory (VrValueEnum, sizeof (VRVALUE_ENUMW));
  240. }
  241. /*++
  242. Routine Description:
  243. pVrEnumFirstTranslationA and pVrEnumFirstTranslationW return the translation
  244. string needed to access the string table of a version stamp.
  245. Arguments:
  246. VrValueEnum - Specifies the structure that has been initialized
  247. by VrCreateEnumStruct.
  248. Return Value:
  249. A pointer to a string specifying the first translation, or
  250. NULL if no translations exist.
  251. --*/
  252. PCSTR
  253. pVrEnumFirstTranslationA (
  254. IN OUT PVRVALUE_ENUMA VrValueEnum
  255. )
  256. {
  257. UINT arraySize;
  258. //
  259. // Query version block for array of code pages/languages
  260. //
  261. if (!VerQueryValueA (
  262. VrValueEnum->VersionBuffer,
  263. "\\VarFileInfo\\Translation",
  264. &VrValueEnum->Translations,
  265. &arraySize
  266. )) {
  267. //
  268. // No translations are available
  269. //
  270. arraySize = 0;
  271. }
  272. //
  273. // Return a pointer to the first translation
  274. //
  275. VrValueEnum->CurrentDefaultTranslation = 0;
  276. VrValueEnum->MaxTranslations = arraySize / sizeof (TRANSLATION);
  277. VrValueEnum->CurrentTranslation = 0;
  278. DEBUGMSG_IF ((
  279. VrValueEnum->MaxTranslations == 0,
  280. DBG_VERSION,
  281. "File %s has no translations",
  282. VrValueEnum->FileSpec
  283. ));
  284. return pVrEnumNextTranslationA (VrValueEnum);
  285. }
  286. PCWSTR
  287. pVrEnumFirstTranslationW (
  288. IN OUT PVRVALUE_ENUMW VrValueEnum
  289. )
  290. {
  291. UINT arraySize;
  292. //
  293. // Query version block for array of code pages/languages
  294. //
  295. if (!VerQueryValueW (
  296. VrValueEnum->VersionBuffer,
  297. L"\\VarFileInfo\\Translation",
  298. &VrValueEnum->Translations,
  299. &arraySize
  300. )) {
  301. //
  302. // No translations are available
  303. //
  304. arraySize = 0;
  305. }
  306. //
  307. // Return a pointer to the first translation
  308. //
  309. VrValueEnum->CurrentDefaultTranslation = 0;
  310. VrValueEnum->MaxTranslations = arraySize / sizeof (TRANSLATION);
  311. VrValueEnum->CurrentTranslation = 0;
  312. DEBUGMSG_IF ((
  313. VrValueEnum->MaxTranslations == 0,
  314. DBG_VERSION,
  315. "File %S has no translations",
  316. VrValueEnum->FileSpec
  317. ));
  318. return pVrEnumNextTranslationW (VrValueEnum);
  319. }
  320. /*++
  321. Routine Description:
  322. pIsDefaultTranslationA and pIsDefaultTranslationW return TRUE
  323. if the specified translation string is enumerated by default.
  324. These routines stops multiple enumeration of the same
  325. translation string.
  326. Arguments:
  327. TranslationStr - Specifies the translation string to test
  328. Return Value:
  329. TRUE if the translation string is the same as a default translation
  330. string, or FALSE if it is not.
  331. --*/
  332. BOOL
  333. pIsDefaultTranslationA (
  334. IN PCSTR TranslationStr
  335. )
  336. {
  337. INT i;
  338. for (i = 0 ; g_DefaultTranslationsA[i] ; i++) {
  339. if (StringIMatchA (TranslationStr, g_DefaultTranslationsA[i])) {
  340. return TRUE;
  341. }
  342. }
  343. return FALSE;
  344. }
  345. BOOL
  346. pIsDefaultTranslationW (
  347. IN PCWSTR TranslationStr
  348. )
  349. {
  350. INT i;
  351. for (i = 0 ; g_DefaultTranslationsW[i] ; i++) {
  352. if (StringIMatchW (TranslationStr, g_DefaultTranslationsW[i])) {
  353. return TRUE;
  354. }
  355. }
  356. return FALSE;
  357. }
  358. /*++
  359. Routine Description:
  360. pVrEnumNextTranslationA and pVrEnumNextTranslationW continue
  361. the enumeration of translation strings, needed to access the
  362. string table in a version stamp.
  363. Arguments:
  364. VrValueEnum - Specifies the same structure passed to
  365. pVrEnumFirstTranslation.
  366. Return Value:
  367. A pointer to a string specifying the next translation, or
  368. NULL if no additional translations exist.
  369. --*/
  370. PCSTR
  371. pVrEnumNextTranslationA (
  372. IN OUT PVRVALUE_ENUMA VrValueEnum
  373. )
  374. {
  375. PTRANSLATION translation;
  376. if (g_DefaultTranslationsA[VrValueEnum->CurrentDefaultTranslation]) {
  377. //
  378. // Return default translations first
  379. //
  380. StringCopyA (
  381. VrValueEnum->TranslationStr,
  382. g_DefaultTranslationsA[VrValueEnum->CurrentDefaultTranslation]
  383. );
  384. VrValueEnum->CurrentDefaultTranslation++;
  385. } else {
  386. do {
  387. //
  388. // Return NULL if all translations have been enumerated
  389. //
  390. if (VrValueEnum->CurrentTranslation == VrValueEnum->MaxTranslations) {
  391. return NULL;
  392. }
  393. //
  394. // Otherwise build translation string and return pointer to it
  395. //
  396. translation = &VrValueEnum->Translations[VrValueEnum->CurrentTranslation];
  397. wsprintfA (
  398. VrValueEnum->TranslationStr,
  399. "%04x%04x",
  400. translation->CodePage,
  401. translation->Language
  402. );
  403. VrValueEnum->CurrentTranslation++;
  404. } while (pIsDefaultTranslationA (VrValueEnum->TranslationStr));
  405. }
  406. return VrValueEnum->TranslationStr;
  407. }
  408. PCWSTR
  409. pVrEnumNextTranslationW (
  410. IN OUT PVRVALUE_ENUMW VrValueEnum
  411. )
  412. {
  413. PTRANSLATION translation;
  414. if (g_DefaultTranslationsW[VrValueEnum->CurrentDefaultTranslation]) {
  415. StringCopyW (
  416. VrValueEnum->TranslationStr,
  417. g_DefaultTranslationsW[VrValueEnum->CurrentDefaultTranslation]
  418. );
  419. VrValueEnum->CurrentDefaultTranslation++;
  420. } else {
  421. do {
  422. //
  423. // Return NULL if all translations have been enumerated
  424. //
  425. if (VrValueEnum->CurrentTranslation == VrValueEnum->MaxTranslations) {
  426. return NULL;
  427. }
  428. //
  429. // Otherwise build translation string and return pointer to it
  430. //
  431. translation = &VrValueEnum->Translations[VrValueEnum->CurrentTranslation];
  432. wsprintfW (
  433. VrValueEnum->TranslationStr,
  434. L"%04x%04x",
  435. translation->CodePage,
  436. translation->Language
  437. );
  438. VrValueEnum->CurrentTranslation++;
  439. } while (pIsDefaultTranslationW (VrValueEnum->TranslationStr));
  440. }
  441. return VrValueEnum->TranslationStr;
  442. }
  443. /*++
  444. Routine Description:
  445. VrEnumFirstValueA and VrEnumFirstValueW return the first value
  446. stored in a version stamp for a specific field. If the field
  447. does not exist, the functions returns NULL.
  448. An enumeration of VrEnumFirstValue/VrEnumNextValue
  449. is used to list all localized strings for a field.
  450. Arguments:
  451. VrValueEnum - Specifies the structure that was initialized by
  452. VrCreateEnumStruct.
  453. VersionField - Specifies the name of the version field to enumerate
  454. Return Value:
  455. A pointer to the first value of the field, or NULL if the field does
  456. not exist.
  457. --*/
  458. PCSTR
  459. VrEnumFirstValueA (
  460. IN OUT PVRVALUE_ENUMA VrValueEnum,
  461. IN PCSTR VersionField
  462. )
  463. {
  464. PCSTR result = NULL;
  465. if (!pVrEnumFirstTranslationA (VrValueEnum)) {
  466. return NULL;
  467. }
  468. VrValueEnum->VersionField = VersionField;
  469. result = pVrEnumValueA (VrValueEnum);
  470. if (!result) {
  471. result = VrEnumNextValueA (VrValueEnum);
  472. }
  473. return result;
  474. }
  475. PCWSTR
  476. VrEnumFirstValueW (
  477. IN OUT PVRVALUE_ENUMW VrValueEnum,
  478. IN PCWSTR VersionField
  479. )
  480. {
  481. PCWSTR result = NULL;
  482. if (!pVrEnumFirstTranslationW (VrValueEnum)) {
  483. return NULL;
  484. }
  485. VrValueEnum->VersionField = VersionField;
  486. result = pVrEnumValueW (VrValueEnum);
  487. if (!result) {
  488. result = VrEnumNextValueW (VrValueEnum);
  489. }
  490. return result;
  491. }
  492. /*++
  493. Routine Description:
  494. VrEnumNextValueA and VrEnumNextValueW return the next value
  495. stored in a version stamp for a specific field.
  496. Arguments:
  497. VrValueEnum - Specifies the same structure passed to VrEnumFirstValue
  498. Return Value:
  499. A pointer to the next value of the field, or NULL if another field
  500. does not exist.
  501. --*/
  502. PCSTR
  503. VrEnumNextValueA (
  504. IN OUT PVRVALUE_ENUMA VrValueEnum
  505. )
  506. {
  507. PCSTR result = NULL;
  508. do {
  509. if (!pVrEnumNextTranslationA (VrValueEnum)) {
  510. break;
  511. }
  512. result = pVrEnumValueA (VrValueEnum);
  513. } while (!result);
  514. return result;
  515. }
  516. PCWSTR
  517. VrEnumNextValueW (
  518. IN OUT PVRVALUE_ENUMW VrValueEnum
  519. )
  520. {
  521. PCWSTR result = NULL;
  522. do {
  523. if (!pVrEnumNextTranslationW (VrValueEnum)) {
  524. break;
  525. }
  526. result = pVrEnumValueW (VrValueEnum);
  527. } while (!result);
  528. return result;
  529. }
  530. /*++
  531. Routine Description:
  532. pVrEnumValueA and pVrEnumValueW are routines that obtain
  533. the value of a version field. They are used for both
  534. VrEnumFirstValue and VrEnumNextValue.
  535. Arguments:
  536. VrValueEnum - Specifies the structure being processed
  537. Return Value:
  538. A pointer to the version value for the current translation, or
  539. NULL if the value does not exist for the current translation.
  540. --*/
  541. PCSTR
  542. pVrEnumValueA (
  543. IN OUT PVRVALUE_ENUMA VrValueEnum
  544. )
  545. {
  546. PSTR text;
  547. UINT stringLen;
  548. PBYTE string;
  549. PCSTR result = NULL;
  550. //
  551. // Prepare sub block for VerQueryValue API
  552. //
  553. text = AllocTextA (
  554. SizeOfStringA (VrValueEnum->TranslationStr) +
  555. SizeOfStringA (VrValueEnum->VersionField) +
  556. 16
  557. );
  558. if (!text) {
  559. return NULL;
  560. }
  561. wsprintfA (
  562. text,
  563. "\\StringFileInfo\\%s\\%s",
  564. VrValueEnum->TranslationStr,
  565. VrValueEnum->VersionField
  566. );
  567. __try {
  568. //
  569. // Get the value from the version stamp
  570. //
  571. if (!VerQueryValueA (
  572. VrValueEnum->VersionBuffer,
  573. text,
  574. &string,
  575. &stringLen
  576. )) {
  577. //
  578. // No value is available
  579. //
  580. __leave;
  581. }
  582. //
  583. // Copy value into buffer
  584. //
  585. StringCopyByteCountA (VrValueEnum->StringBuffer, (PCSTR) string, stringLen);
  586. result = (PCSTR)VrValueEnum->StringBuffer;
  587. }
  588. __finally {
  589. FreeTextA (text);
  590. }
  591. return result;
  592. }
  593. PCWSTR
  594. pVrEnumValueW (
  595. IN OUT PVRVALUE_ENUMW VrValueEnum
  596. )
  597. {
  598. PWSTR text;
  599. UINT stringLen;
  600. PBYTE string;
  601. PCWSTR result = NULL;
  602. //
  603. // Prepare sub block for VerQueryValue API
  604. //
  605. text = AllocTextW (
  606. 18 +
  607. CharCountW (VrValueEnum->TranslationStr) +
  608. CharCountW (VrValueEnum->VersionField)
  609. );
  610. if (!text) {
  611. return NULL;
  612. }
  613. wsprintfW (
  614. text,
  615. L"\\StringFileInfo\\%s\\%s",
  616. VrValueEnum->TranslationStr,
  617. VrValueEnum->VersionField
  618. );
  619. __try {
  620. //
  621. // Get the value from the version stamp
  622. //
  623. if (!VerQueryValueW (
  624. VrValueEnum->VersionBuffer,
  625. text,
  626. &string,
  627. &stringLen
  628. )) {
  629. //
  630. // No value is available
  631. //
  632. __leave;
  633. }
  634. //
  635. // Copy value into buffer
  636. //
  637. CopyMemory (VrValueEnum->StringBuffer, string, stringLen * sizeof (WCHAR));
  638. VrValueEnum->StringBuffer [stringLen * sizeof (WCHAR)] = 0;
  639. result = (PWSTR) VrValueEnum->StringBuffer;
  640. }
  641. __finally {
  642. FreeTextW (text);
  643. }
  644. return result;
  645. }
  646. /*++
  647. Routine Description:
  648. VrCheckVersionValueA and VrCheckVersionValueW return TRUE
  649. if the version value name specified has the specified version
  650. value.
  651. Arguments:
  652. VrValueEnum - Specifies the structure being processed
  653. VersionName - Specifies the version value name.
  654. VersionValue - Specifies the version value.
  655. Return value:
  656. TRUE - the query was successful
  657. FALSE - the query failed
  658. --*/
  659. BOOL
  660. VrCheckVersionValueA (
  661. IN PVRVALUE_ENUMA VrValueEnum,
  662. IN PCSTR VersionName,
  663. IN PCSTR VersionValue
  664. )
  665. {
  666. PCSTR CurrentStr;
  667. BOOL result = FALSE;
  668. if ((!VersionName) || (!VersionValue)) {
  669. return FALSE;
  670. }
  671. CurrentStr = VrEnumFirstValueA (VrValueEnum, VersionName);
  672. while (CurrentStr) {
  673. CurrentStr = SkipSpaceA (CurrentStr);
  674. TruncateTrailingSpaceA ((PSTR) CurrentStr);
  675. if (IsPatternMatchA (VersionValue, CurrentStr)) {
  676. result = TRUE;
  677. break;
  678. }
  679. CurrentStr = VrEnumNextValueA (VrValueEnum);
  680. }
  681. return result;
  682. }
  683. BOOL
  684. VrCheckVersionValueW (
  685. IN PVRVALUE_ENUMW VrValueEnum,
  686. IN PCWSTR VersionName,
  687. IN PCWSTR VersionValue
  688. )
  689. {
  690. PCWSTR CurrentStr;
  691. BOOL result = FALSE;
  692. if ((!VersionName) || (!VersionValue)) {
  693. return FALSE;
  694. }
  695. CurrentStr = VrEnumFirstValueW (VrValueEnum, VersionName);
  696. while (CurrentStr) {
  697. CurrentStr = SkipSpaceW (CurrentStr);
  698. TruncateTrailingSpaceW ((PWSTR) CurrentStr);
  699. if (IsPatternMatchW (VersionValue, CurrentStr)) {
  700. result = TRUE;
  701. break;
  702. }
  703. CurrentStr = VrEnumNextValueW (VrValueEnum);
  704. }
  705. return result;
  706. }
  707. ULONGLONG
  708. VrGetBinaryFileVersionA (
  709. IN PVRVALUE_ENUMA VrValueEnum
  710. )
  711. /*++
  712. Routine Description:
  713. VrGetBinaryFileVersion returns the FileVersion field from
  714. the fixed info structure of version information.
  715. Arguments:
  716. VrValueEnum - Specifies the structure being processed
  717. Return Value:
  718. A ULONGLONG FileVersion field
  719. --*/
  720. {
  721. ULONGLONG result = 0;
  722. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  723. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwFileVersionLS;
  724. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwFileVersionMS;
  725. }
  726. return result;
  727. }
  728. ULONGLONG
  729. VrGetBinaryProductVersionA (
  730. IN PVRVALUE_ENUMA VrValueEnum
  731. )
  732. /*++
  733. Routine Description:
  734. VrGetBinaryProductVersion returns the ProductVersion field from
  735. the fixed info structure of version information.
  736. Arguments:
  737. VrValueEnum - Specifies the structure being processed
  738. Return Value:
  739. A ULONGLONG ProductVersion field
  740. --*/
  741. {
  742. ULONGLONG result = 0;
  743. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  744. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwProductVersionLS;
  745. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwProductVersionMS;
  746. }
  747. return result;
  748. }
  749. DWORD
  750. VrGetBinaryFileDateLoA (
  751. IN PVRVALUE_ENUMA VrValueEnum
  752. )
  753. /*++
  754. Routine Description:
  755. VrGetBinaryFileDateLo returns the LS dword from FileDate field from
  756. the fixed info structure of version information.
  757. Arguments:
  758. VrValueEnum - Specifies the structure being processed
  759. Return Value:
  760. A DWORD, LS dword of the FileDate field
  761. --*/
  762. {
  763. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  764. return VrValueEnum->FixedInfo->dwFileDateLS;
  765. }
  766. return 0;
  767. }
  768. DWORD
  769. VrGetBinaryFileDateHiA (
  770. IN PVRVALUE_ENUMA VrValueEnum
  771. )
  772. /*++
  773. Routine Description:
  774. VrGetBinaryFileDateHi returns the MS dword from FileDate field from
  775. the fixed info structure of version information.
  776. Arguments:
  777. VrValueEnum - Specifies the structure being processed
  778. Return Value:
  779. A DWORD, MS dword of the FileDate field
  780. --*/
  781. {
  782. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  783. return VrValueEnum->FixedInfo->dwFileDateMS;
  784. }
  785. return 0;
  786. }
  787. DWORD
  788. VrGetBinaryOsVersionA (
  789. IN PVRVALUE_ENUMA VrValueEnum
  790. )
  791. /*++
  792. Routine Description:
  793. VrGetBinaryOsVersion returns the FileOS field from
  794. the fixed info structure of version information.
  795. Arguments:
  796. VrValueEnum - Specifies the structure being processed
  797. Return Value:
  798. A DWORD FileOS field
  799. --*/
  800. {
  801. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  802. return VrValueEnum->FixedInfo->dwFileOS;
  803. }
  804. return 0;
  805. }
  806. DWORD
  807. VrGetBinaryFileTypeA (
  808. IN PVRVALUE_ENUMA VrValueEnum
  809. )
  810. /*++
  811. Routine Description:
  812. VrGetBinaryFileType returns the FileType field from
  813. the fixed info structure of version information.
  814. Arguments:
  815. VrValueEnum - Specifies the structure being processed
  816. Return Value:
  817. A DWORD FileType field
  818. --*/
  819. {
  820. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  821. return VrValueEnum->FixedInfo->dwFileType;
  822. }
  823. return 0;
  824. }
  825. /*++
  826. Routine Description:
  827. VrCheckFileVersionA and VrCheckFileVersionW look in the file's version
  828. structure trying to see if a specific name has a specific value.
  829. Arguments:
  830. FileName - File to query for version struct.
  831. NameToCheck - Name to query in version structure.
  832. ValueToCheck - Value to query in version structure.
  833. Return value:
  834. TRUE - the query was successful
  835. FALSE - the query failed
  836. --*/
  837. BOOL
  838. VrCheckFileVersionA (
  839. IN PCSTR FileName,
  840. IN PCSTR NameToCheck,
  841. IN PCSTR ValueToCheck
  842. )
  843. {
  844. VRVALUE_ENUMA Version;
  845. PCSTR CurrentStr;
  846. BOOL result = FALSE;
  847. MYASSERT (NameToCheck);
  848. MYASSERT (ValueToCheck);
  849. if (VrCreateEnumStructA (&Version, FileName)) {
  850. __try {
  851. CurrentStr = VrEnumFirstValueA (&Version, NameToCheck);
  852. while (CurrentStr) {
  853. CurrentStr = SkipSpaceA (CurrentStr);
  854. TruncateTrailingSpaceA ((PSTR) CurrentStr);
  855. if (IsPatternMatchA (ValueToCheck, CurrentStr)) {
  856. result = TRUE;
  857. __leave;
  858. }
  859. CurrentStr = VrEnumNextValueA (&Version);
  860. }
  861. }
  862. __finally {
  863. VrDestroyEnumStructA (&Version);
  864. }
  865. }
  866. return result;
  867. }
  868. BOOL
  869. VrCheckFileVersionW (
  870. IN PCWSTR FileName,
  871. IN PCWSTR NameToCheck,
  872. IN PCWSTR ValueToCheck
  873. )
  874. {
  875. VRVALUE_ENUMW Version;
  876. PCWSTR CurrentStr;
  877. BOOL result = FALSE;
  878. MYASSERT (NameToCheck);
  879. MYASSERT (ValueToCheck);
  880. if (VrCreateEnumStructW (&Version, FileName)) {
  881. __try {
  882. CurrentStr = VrEnumFirstValueW (&Version, NameToCheck);
  883. while (CurrentStr) {
  884. CurrentStr = SkipSpaceW (CurrentStr);
  885. TruncateTrailingSpaceW ((PWSTR) CurrentStr);
  886. if (IsPatternMatchW (ValueToCheck, CurrentStr)) {
  887. result = TRUE;
  888. __leave;
  889. }
  890. CurrentStr = VrEnumNextValueW (&Version);
  891. }
  892. }
  893. __finally {
  894. VrDestroyEnumStructW (&Version);
  895. }
  896. }
  897. return result;
  898. }