verchk.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : LevelEdit *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/verchk.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 8/15/01 11:29a $*
  29. * *
  30. * $Revision:: 5 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "verchk.h"
  36. #include <windows.h>
  37. #include <winnt.h>
  38. #include "rawfile.h"
  39. #include "ffactory.h"
  40. /******************************************************************************
  41. *
  42. * NAME
  43. * GetVersionInfo
  44. *
  45. * DESCRIPTION
  46. * Retrieve version information from files version resource.
  47. *
  48. * INPUTS
  49. * Filename - Name of file to retrieve version information for.
  50. * FileInfo - Pointer to VS_FIXEDFILEINFO structure to be filled in.
  51. *
  52. * RESULT
  53. * Success - True if successful in obtaining version information.
  54. *
  55. ******************************************************************************/
  56. bool GetVersionInfo(char* filename, VS_FIXEDFILEINFO* fileInfo)
  57. {
  58. if (filename == NULL || fileInfo == NULL)
  59. {
  60. return false;
  61. }
  62. // Get version information from the application
  63. DWORD verHandle;
  64. DWORD verInfoSize = GetFileVersionInfoSize(filename, &verHandle);
  65. if (verInfoSize)
  66. {
  67. // If we were able to get the information, process it:
  68. HANDLE memHandle = GlobalAlloc(GMEM_MOVEABLE, verInfoSize);
  69. if (memHandle)
  70. {
  71. LPVOID buffer = GlobalLock(memHandle);
  72. if (buffer)
  73. {
  74. BOOL success = GetFileVersionInfo(filename, verHandle, verInfoSize, buffer);
  75. if (success)
  76. {
  77. VS_FIXEDFILEINFO* data;
  78. UINT dataSize = 0;
  79. success = VerQueryValue(buffer, "\\", (LPVOID*)&data, &dataSize);
  80. if (success && (dataSize == sizeof(VS_FIXEDFILEINFO)))
  81. {
  82. memcpy(fileInfo, data, sizeof(VS_FIXEDFILEINFO));
  83. return true;
  84. }
  85. }
  86. GlobalUnlock(memHandle);
  87. }
  88. GlobalFree(memHandle);
  89. }
  90. }
  91. return false;
  92. }
  93. bool GetFileCreationTime(char* filename, FILETIME* createTime)
  94. {
  95. if (filename && createTime)
  96. {
  97. createTime->dwLowDateTime = 0;
  98. createTime->dwHighDateTime = 0;
  99. FileClass* file = _TheFileFactory->Get_File(filename);
  100. if (file && file->Open())
  101. {
  102. HANDLE handle = file->Get_File_Handle();
  103. if (handle != INVALID_HANDLE_VALUE)
  104. {
  105. if (GetFileTime(handle, NULL, NULL, createTime))
  106. {
  107. return true;
  108. }
  109. }
  110. }
  111. }
  112. return false;
  113. }
  114. ////////////////////////////////////////////////////////////////////////
  115. //
  116. // Get_Image_File_Header
  117. //
  118. ////////////////////////////////////////////////////////////////////////
  119. bool
  120. Get_Image_File_Header (const char *filename, IMAGE_FILE_HEADER *file_header)
  121. {
  122. bool retval = false;
  123. //
  124. // Attempt to open the file
  125. //
  126. FileClass *file=_TheFileFactory->Get_File(filename);
  127. if (file && file->Open ()) {
  128. //
  129. // Read the dos header (all PE exectuable files begin with this)
  130. //
  131. IMAGE_DOS_HEADER dos_header;
  132. if (file->Read (&dos_header, sizeof (dos_header)) == sizeof (dos_header)) {
  133. //
  134. // Determine the index where the image header resides
  135. //
  136. int file_header_offset = dos_header.e_lfanew + sizeof (DWORD);
  137. file->Seek (file_header_offset, SEEK_SET);
  138. //
  139. // Read the image header from the file
  140. //
  141. int size = sizeof (IMAGE_FILE_HEADER);
  142. if (file->Read (file_header, size) == size) {
  143. retval = true;
  144. }
  145. }
  146. }
  147. _TheFileFactory->Return_File(file);
  148. file=NULL;
  149. return retval;
  150. }
  151. ////////////////////////////////////////////////////////////////////////
  152. //
  153. // Get_Image_File_Header
  154. //
  155. ////////////////////////////////////////////////////////////////////////
  156. bool
  157. Get_Image_File_Header (HINSTANCE app_instance, IMAGE_FILE_HEADER *file_header)
  158. {
  159. bool retval = false;
  160. //
  161. // Read the dos header (all PE exectuable files begin with this)
  162. //
  163. IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)app_instance;
  164. if (dos_header != NULL) {
  165. //
  166. // Determine the offset where the image header resides
  167. //
  168. int image_header_offset = dos_header->e_lfanew + sizeof (DWORD);
  169. //
  170. // Copy the file header into the provided structure
  171. //
  172. ::memcpy ( file_header,
  173. (((char *)dos_header) + image_header_offset),
  174. sizeof (IMAGE_FILE_HEADER));
  175. retval = true;
  176. }
  177. return retval;
  178. }
  179. ////////////////////////////////////////////////////////////////////////
  180. //
  181. // Compare_EXE_Version
  182. //
  183. // Used to compare 2 versions of an executable, the currently executing
  184. // exe and a version saved to disk. These exe's do not need to have
  185. // a version resource.
  186. //
  187. // The return value is the same as strcmp, < 0 if the current process is
  188. // older, 0 if they are the same, and > 0 if the current process is newer.
  189. //
  190. ////////////////////////////////////////////////////////////////////////
  191. int
  192. Compare_EXE_Version (int app_instance, const char *filename)
  193. {
  194. int retval = 0;
  195. //
  196. // Get the image header for both executables
  197. //
  198. IMAGE_FILE_HEADER header1 = { 0 };
  199. IMAGE_FILE_HEADER header2 = { 0 };
  200. if ( ::Get_Image_File_Header ((HINSTANCE)app_instance, &header1) &&
  201. ::Get_Image_File_Header (filename, &header2))
  202. {
  203. retval = int(header1.TimeDateStamp - header2.TimeDateStamp);
  204. }
  205. return retval;
  206. }