version.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

  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. }