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.

1226 lines
25 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 = JoinPathsInPoolExA ((
  554. NULL,
  555. "StringFileInfo",
  556. VrValueEnum->TranslationStr,
  557. VrValueEnum->VersionField,
  558. NULL
  559. ));
  560. if (!text) {
  561. return NULL;
  562. }
  563. __try {
  564. //
  565. // Get the value from the version stamp
  566. //
  567. if (!VerQueryValueA (
  568. VrValueEnum->VersionBuffer,
  569. text,
  570. &string,
  571. &stringLen
  572. )) {
  573. //
  574. // No value is available
  575. //
  576. __leave;
  577. }
  578. //
  579. // Copy value into buffer
  580. //
  581. StringCopyByteCountA (VrValueEnum->StringBuffer, (PCSTR) string, stringLen);
  582. result = (PCSTR)VrValueEnum->StringBuffer;
  583. }
  584. __finally {
  585. FreePathStringA (text);
  586. }
  587. return result;
  588. }
  589. PCWSTR
  590. pVrEnumValueW (
  591. IN OUT PVRVALUE_ENUMW VrValueEnum
  592. )
  593. {
  594. PWSTR text;
  595. UINT stringLen;
  596. PBYTE string;
  597. PCWSTR result = NULL;
  598. //
  599. // Prepare sub block for VerQueryValue API
  600. //
  601. text = JoinPathsInPoolExW ((
  602. NULL,
  603. L"StringFileInfo",
  604. VrValueEnum->TranslationStr,
  605. VrValueEnum->VersionField,
  606. NULL
  607. ));
  608. if (!text) {
  609. return NULL;
  610. }
  611. __try {
  612. //
  613. // Get the value from the version stamp
  614. //
  615. if (!VerQueryValueW (
  616. VrValueEnum->VersionBuffer,
  617. text,
  618. &string,
  619. &stringLen
  620. )) {
  621. //
  622. // No value is available
  623. //
  624. __leave;
  625. }
  626. //
  627. // Copy value into buffer
  628. //
  629. CopyMemory (VrValueEnum->StringBuffer, string, stringLen * sizeof (WCHAR));
  630. VrValueEnum->StringBuffer [stringLen * sizeof (WCHAR)] = 0;
  631. result = (PWSTR) VrValueEnum->StringBuffer;
  632. }
  633. __finally {
  634. FreePathStringW (text);
  635. }
  636. return result;
  637. }
  638. /*++
  639. Routine Description:
  640. VrCheckVersionValueA and VrCheckVersionValueW return TRUE
  641. if the version value name specified has the specified version
  642. value.
  643. Arguments:
  644. VrValueEnum - Specifies the structure being processed
  645. VersionName - Specifies the version value name.
  646. VersionValue - Specifies the version value.
  647. Return value:
  648. TRUE - the query was successful
  649. FALSE - the query failed
  650. --*/
  651. BOOL
  652. VrCheckVersionValueA (
  653. IN PVRVALUE_ENUMA VrValueEnum,
  654. IN PCSTR VersionName,
  655. IN PCSTR VersionValue
  656. )
  657. {
  658. PCSTR CurrentStr;
  659. BOOL result = FALSE;
  660. if ((!VersionName) || (!VersionValue)) {
  661. return FALSE;
  662. }
  663. CurrentStr = VrEnumFirstValueA (VrValueEnum, VersionName);
  664. while (CurrentStr) {
  665. CurrentStr = SkipSpaceA (CurrentStr);
  666. TruncateTrailingSpaceA ((PSTR) CurrentStr);
  667. if (IsPatternMatchA (VersionValue, CurrentStr)) {
  668. result = TRUE;
  669. break;
  670. }
  671. CurrentStr = VrEnumNextValueA (VrValueEnum);
  672. }
  673. return result;
  674. }
  675. BOOL
  676. VrCheckVersionValueW (
  677. IN PVRVALUE_ENUMW VrValueEnum,
  678. IN PCWSTR VersionName,
  679. IN PCWSTR VersionValue
  680. )
  681. {
  682. PCWSTR CurrentStr;
  683. BOOL result = FALSE;
  684. if ((!VersionName) || (!VersionValue)) {
  685. return FALSE;
  686. }
  687. CurrentStr = VrEnumFirstValueW (VrValueEnum, VersionName);
  688. while (CurrentStr) {
  689. CurrentStr = SkipSpaceW (CurrentStr);
  690. TruncateTrailingSpaceW ((PWSTR) CurrentStr);
  691. if (IsPatternMatchW (VersionValue, CurrentStr)) {
  692. result = TRUE;
  693. break;
  694. }
  695. CurrentStr = VrEnumNextValueW (VrValueEnum);
  696. }
  697. return result;
  698. }
  699. ULONGLONG
  700. VrGetBinaryFileVersionA (
  701. IN PVRVALUE_ENUMA VrValueEnum
  702. )
  703. /*++
  704. Routine Description:
  705. VrGetBinaryFileVersion returns the FileVersion field from
  706. the fixed info structure of version information.
  707. Arguments:
  708. VrValueEnum - Specifies the structure being processed
  709. Return Value:
  710. A ULONGLONG FileVersion field
  711. --*/
  712. {
  713. ULONGLONG result = 0;
  714. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  715. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwFileVersionLS;
  716. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwFileVersionMS;
  717. }
  718. return result;
  719. }
  720. ULONGLONG
  721. VrGetBinaryProductVersionA (
  722. IN PVRVALUE_ENUMA VrValueEnum
  723. )
  724. /*++
  725. Routine Description:
  726. VrGetBinaryProductVersion returns the ProductVersion field from
  727. the fixed info structure of version information.
  728. Arguments:
  729. VrValueEnum - Specifies the structure being processed
  730. Return Value:
  731. A ULONGLONG ProductVersion field
  732. --*/
  733. {
  734. ULONGLONG result = 0;
  735. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  736. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwProductVersionLS;
  737. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwProductVersionMS;
  738. }
  739. return result;
  740. }
  741. DWORD
  742. VrGetBinaryFileDateLoA (
  743. IN PVRVALUE_ENUMA VrValueEnum
  744. )
  745. /*++
  746. Routine Description:
  747. VrGetBinaryFileDateLo returns the LS dword from FileDate field from
  748. the fixed info structure of version information.
  749. Arguments:
  750. VrValueEnum - Specifies the structure being processed
  751. Return Value:
  752. A DWORD, LS dword of the FileDate field
  753. --*/
  754. {
  755. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  756. return VrValueEnum->FixedInfo->dwFileDateLS;
  757. }
  758. return 0;
  759. }
  760. DWORD
  761. VrGetBinaryFileDateHiA (
  762. IN PVRVALUE_ENUMA VrValueEnum
  763. )
  764. /*++
  765. Routine Description:
  766. VrGetBinaryFileDateHi returns the MS dword from FileDate field from
  767. the fixed info structure of version information.
  768. Arguments:
  769. VrValueEnum - Specifies the structure being processed
  770. Return Value:
  771. A DWORD, MS dword of the FileDate field
  772. --*/
  773. {
  774. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  775. return VrValueEnum->FixedInfo->dwFileDateMS;
  776. }
  777. return 0;
  778. }
  779. DWORD
  780. VrGetBinaryOsVersionA (
  781. IN PVRVALUE_ENUMA VrValueEnum
  782. )
  783. /*++
  784. Routine Description:
  785. VrGetBinaryOsVersion returns the FileOS field from
  786. the fixed info structure of version information.
  787. Arguments:
  788. VrValueEnum - Specifies the structure being processed
  789. Return Value:
  790. A DWORD FileOS field
  791. --*/
  792. {
  793. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  794. return VrValueEnum->FixedInfo->dwFileOS;
  795. }
  796. return 0;
  797. }
  798. DWORD
  799. VrGetBinaryFileTypeA (
  800. IN PVRVALUE_ENUMA VrValueEnum
  801. )
  802. /*++
  803. Routine Description:
  804. VrGetBinaryFileType returns the FileType field from
  805. the fixed info structure of version information.
  806. Arguments:
  807. VrValueEnum - Specifies the structure being processed
  808. Return Value:
  809. A DWORD FileType field
  810. --*/
  811. {
  812. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  813. return VrValueEnum->FixedInfo->dwFileType;
  814. }
  815. return 0;
  816. }
  817. /*++
  818. Routine Description:
  819. VrCheckFileVersionA and VrCheckFileVersionW look in the file's version
  820. structure trying to see if a specific name has a specific value.
  821. Arguments:
  822. FileName - File to query for version struct.
  823. NameToCheck - Name to query in version structure.
  824. ValueToCheck - Value to query in version structure.
  825. Return value:
  826. TRUE - the query was successful
  827. FALSE - the query failed
  828. --*/
  829. BOOL
  830. VrCheckFileVersionA (
  831. IN PCSTR FileName,
  832. IN PCSTR NameToCheck,
  833. IN PCSTR ValueToCheck
  834. )
  835. {
  836. VRVALUE_ENUMA Version;
  837. PCSTR CurrentStr;
  838. BOOL result = FALSE;
  839. MYASSERT (NameToCheck);
  840. MYASSERT (ValueToCheck);
  841. if (VrCreateEnumStructA (&Version, FileName)) {
  842. __try {
  843. CurrentStr = VrEnumFirstValueA (&Version, NameToCheck);
  844. while (CurrentStr) {
  845. CurrentStr = SkipSpaceA (CurrentStr);
  846. TruncateTrailingSpaceA ((PSTR) CurrentStr);
  847. if (IsPatternMatchA (ValueToCheck, CurrentStr)) {
  848. result = TRUE;
  849. __leave;
  850. }
  851. CurrentStr = VrEnumNextValueA (&Version);
  852. }
  853. }
  854. __finally {
  855. VrDestroyEnumStructA (&Version);
  856. }
  857. }
  858. return result;
  859. }
  860. BOOL
  861. VrCheckFileVersionW (
  862. IN PCWSTR FileName,
  863. IN PCWSTR NameToCheck,
  864. IN PCWSTR ValueToCheck
  865. )
  866. {
  867. VRVALUE_ENUMW Version;
  868. PCWSTR CurrentStr;
  869. BOOL result = FALSE;
  870. MYASSERT (NameToCheck);
  871. MYASSERT (ValueToCheck);
  872. if (VrCreateEnumStructW (&Version, FileName)) {
  873. __try {
  874. CurrentStr = VrEnumFirstValueW (&Version, NameToCheck);
  875. while (CurrentStr) {
  876. CurrentStr = SkipSpaceW (CurrentStr);
  877. TruncateTrailingSpaceW ((PWSTR) CurrentStr);
  878. if (IsPatternMatchW (ValueToCheck, CurrentStr)) {
  879. result = TRUE;
  880. __leave;
  881. }
  882. CurrentStr = VrEnumNextValueW (&Version);
  883. }
  884. }
  885. __finally {
  886. VrDestroyEnumStructW (&Version);
  887. }
  888. }
  889. return result;
  890. }