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.

1070 lines
20 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 = RealAllocTextExA (NULL, 0);
  554. text = AllocTextA (
  555. SizeOfStringA (VrValueEnum->TranslationStr) +
  556. SizeOfStringA (VrValueEnum->VersionField) +
  557. 16
  558. );
  559. if (!text) {
  560. return NULL;
  561. }
  562. wsprintfA (
  563. text,
  564. "\\StringFileInfo\\%s\\%s",
  565. VrValueEnum->TranslationStr,
  566. VrValueEnum->VersionField
  567. );
  568. __try {
  569. //
  570. // Get the value from the version stamp
  571. //
  572. if (!VerQueryValueA (
  573. VrValueEnum->VersionBuffer,
  574. text,
  575. &string,
  576. &stringLen
  577. )) {
  578. //
  579. // No value is available
  580. //
  581. __leave;
  582. }
  583. //
  584. // Copy value into buffer
  585. //
  586. StringCopyByteCountA (VrValueEnum->StringBuffer, (PCSTR) string, stringLen);
  587. result = (PCSTR)VrValueEnum->StringBuffer;
  588. }
  589. __finally {
  590. FreeTextA (text);
  591. }
  592. return result;
  593. }
  594. PCWSTR
  595. pVrEnumValueW (
  596. IN OUT PVRVALUE_ENUMW VrValueEnum
  597. )
  598. {
  599. PWSTR text;
  600. UINT stringLen;
  601. PBYTE string;
  602. PCWSTR result = NULL;
  603. //
  604. // Prepare sub block for VerQueryValue API
  605. //
  606. text = AllocTextW (
  607. 18 +
  608. CharCountW (VrValueEnum->TranslationStr) +
  609. CharCountW (VrValueEnum->VersionField)
  610. );
  611. if (!text) {
  612. return NULL;
  613. }
  614. wsprintfW (
  615. text,
  616. L"\\StringFileInfo\\%s\\%s",
  617. VrValueEnum->TranslationStr,
  618. VrValueEnum->VersionField
  619. );
  620. __try {
  621. //
  622. // Get the value from the version stamp
  623. //
  624. if (!VerQueryValueW (
  625. VrValueEnum->VersionBuffer,
  626. text,
  627. &string,
  628. &stringLen
  629. )) {
  630. //
  631. // No value is available
  632. //
  633. __leave;
  634. }
  635. //
  636. // Copy value into buffer
  637. //
  638. CopyMemory (VrValueEnum->StringBuffer, string, stringLen * sizeof (WCHAR));
  639. VrValueEnum->StringBuffer [stringLen * sizeof (WCHAR)] = 0;
  640. result = (PWSTR) VrValueEnum->StringBuffer;
  641. }
  642. __finally {
  643. FreeTextW (text);
  644. }
  645. return result;
  646. }
  647. ULONGLONG
  648. VrGetBinaryFileVersionA (
  649. IN PVRVALUE_ENUMA VrValueEnum
  650. )
  651. /*++
  652. Routine Description:
  653. VrGetBinaryFileVersion returns the FileVersion field from
  654. the fixed info structure of version information.
  655. Arguments:
  656. VrValueEnum - Specifies the structure being processed
  657. Return Value:
  658. A ULONGLONG FileVersion field
  659. --*/
  660. {
  661. ULONGLONG result = 0;
  662. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  663. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwFileVersionLS;
  664. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwFileVersionMS;
  665. }
  666. return result;
  667. }
  668. ULONGLONG
  669. VrGetBinaryProductVersionA (
  670. IN PVRVALUE_ENUMA VrValueEnum
  671. )
  672. /*++
  673. Routine Description:
  674. VrGetBinaryProductVersion returns the ProductVersion field from
  675. the fixed info structure of version information.
  676. Arguments:
  677. VrValueEnum - Specifies the structure being processed
  678. Return Value:
  679. A ULONGLONG ProductVersion field
  680. --*/
  681. {
  682. ULONGLONG result = 0;
  683. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  684. *((PDWORD) (&result)) = VrValueEnum->FixedInfo->dwProductVersionLS;
  685. *(((PDWORD) (&result)) + 1) = VrValueEnum->FixedInfo->dwProductVersionMS;
  686. }
  687. return result;
  688. }
  689. DWORD
  690. VrGetBinaryFileDateLoA (
  691. IN PVRVALUE_ENUMA VrValueEnum
  692. )
  693. /*++
  694. Routine Description:
  695. VrGetBinaryFileDateLo returns the LS dword from FileDate field from
  696. the fixed info structure of version information.
  697. Arguments:
  698. VrValueEnum - Specifies the structure being processed
  699. Return Value:
  700. A DWORD, LS dword of the FileDate field
  701. --*/
  702. {
  703. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  704. return VrValueEnum->FixedInfo->dwFileDateLS;
  705. }
  706. return 0;
  707. }
  708. DWORD
  709. VrGetBinaryFileDateHiA (
  710. IN PVRVALUE_ENUMA VrValueEnum
  711. )
  712. /*++
  713. Routine Description:
  714. VrGetBinaryFileDateHi returns the MS dword from FileDate field from
  715. the fixed info structure of version information.
  716. Arguments:
  717. VrValueEnum - Specifies the structure being processed
  718. Return Value:
  719. A DWORD, MS dword of the FileDate field
  720. --*/
  721. {
  722. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  723. return VrValueEnum->FixedInfo->dwFileDateMS;
  724. }
  725. return 0;
  726. }
  727. DWORD
  728. VrGetBinaryOsVersionA (
  729. IN PVRVALUE_ENUMA VrValueEnum
  730. )
  731. /*++
  732. Routine Description:
  733. VrGetBinaryOsVersion returns the FileOS field from
  734. the fixed info structure of version information.
  735. Arguments:
  736. VrValueEnum - Specifies the structure being processed
  737. Return Value:
  738. A DWORD FileOS field
  739. --*/
  740. {
  741. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  742. return VrValueEnum->FixedInfo->dwFileOS;
  743. }
  744. return 0;
  745. }
  746. DWORD
  747. VrGetBinaryFileType (
  748. IN PVRVALUE_ENUMA VrValueEnum
  749. )
  750. /*++
  751. Routine Description:
  752. VrGetBinaryFileType returns the FileType field from
  753. the fixed info structure of version information.
  754. Arguments:
  755. VrValueEnum - Specifies the structure being processed
  756. Return Value:
  757. A DWORD FileType field
  758. --*/
  759. {
  760. if (VrValueEnum->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) {
  761. return VrValueEnum->FixedInfo->dwFileType;
  762. }
  763. return 0;
  764. }