verchk.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. ** Command & Conquer Renegade(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:: 2/16/02 10:53p $*
  29. * *
  30. * $Revision:: 6 $*
  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. // Get the version information for this file
  59. //
  60. bool verok = true;
  61. unsigned long dummy_var = 0;
  62. unsigned long version_size = ::GetFileVersionInfoSize (filename, &dummy_var);
  63. if (version_size > 0) {
  64. //
  65. // Get the file version block
  66. //
  67. LPBYTE pblock = new BYTE[version_size];
  68. if (::GetFileVersionInfo (filename, 0L, version_size, pblock)) {
  69. //
  70. // Query the block for the file version information
  71. //
  72. UINT version_len = 0;
  73. VS_FIXEDFILEINFO *pversion_info = NULL;
  74. if (::VerQueryValue (pblock, "\\", (LPVOID *)&pversion_info, &version_len)) {
  75. memcpy(fileInfo, pversion_info, sizeof(VS_FIXEDFILEINFO));
  76. } else {
  77. verok = false;
  78. }
  79. }
  80. delete [] pblock;
  81. pblock = NULL;
  82. }
  83. return verok;
  84. }
  85. bool GetFileCreationTime(char* filename, FILETIME* createTime)
  86. {
  87. if (filename && createTime)
  88. {
  89. createTime->dwLowDateTime = 0;
  90. createTime->dwHighDateTime = 0;
  91. FileClass* file = _TheFileFactory->Get_File(filename);
  92. if (file && file->Open())
  93. {
  94. HANDLE handle = file->Get_File_Handle();
  95. if (handle != INVALID_HANDLE_VALUE)
  96. {
  97. if (GetFileTime(handle, NULL, NULL, createTime))
  98. {
  99. return true;
  100. }
  101. }
  102. }
  103. }
  104. return false;
  105. }
  106. ////////////////////////////////////////////////////////////////////////
  107. //
  108. // Get_Image_File_Header
  109. //
  110. ////////////////////////////////////////////////////////////////////////
  111. bool
  112. Get_Image_File_Header (const char *filename, IMAGE_FILE_HEADER *file_header)
  113. {
  114. bool retval = false;
  115. //
  116. // Attempt to open the file
  117. //
  118. FileClass *file=_TheFileFactory->Get_File(filename);
  119. if (file && file->Open ()) {
  120. //
  121. // Read the dos header (all PE exectuable files begin with this)
  122. //
  123. IMAGE_DOS_HEADER dos_header;
  124. if (file->Read (&dos_header, sizeof (dos_header)) == sizeof (dos_header)) {
  125. //
  126. // Determine the index where the image header resides
  127. //
  128. int file_header_offset = dos_header.e_lfanew + sizeof (DWORD);
  129. file->Seek (file_header_offset, SEEK_SET);
  130. //
  131. // Read the image header from the file
  132. //
  133. int size = sizeof (IMAGE_FILE_HEADER);
  134. if (file->Read (file_header, size) == size) {
  135. retval = true;
  136. }
  137. }
  138. }
  139. _TheFileFactory->Return_File(file);
  140. file=NULL;
  141. return retval;
  142. }
  143. ////////////////////////////////////////////////////////////////////////
  144. //
  145. // Get_Image_File_Header
  146. //
  147. ////////////////////////////////////////////////////////////////////////
  148. bool
  149. Get_Image_File_Header (HINSTANCE app_instance, IMAGE_FILE_HEADER *file_header)
  150. {
  151. bool retval = false;
  152. //
  153. // Read the dos header (all PE exectuable files begin with this)
  154. //
  155. IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)app_instance;
  156. if (dos_header != NULL) {
  157. //
  158. // Determine the offset where the image header resides
  159. //
  160. int image_header_offset = dos_header->e_lfanew + sizeof (DWORD);
  161. //
  162. // Copy the file header into the provided structure
  163. //
  164. ::memcpy ( file_header,
  165. (((char *)dos_header) + image_header_offset),
  166. sizeof (IMAGE_FILE_HEADER));
  167. retval = true;
  168. }
  169. return retval;
  170. }
  171. ////////////////////////////////////////////////////////////////////////
  172. //
  173. // Compare_EXE_Version
  174. //
  175. // Used to compare 2 versions of an executable, the currently executing
  176. // exe and a version saved to disk. These exe's do not need to have
  177. // a version resource.
  178. //
  179. // The return value is the same as strcmp, < 0 if the current process is
  180. // older, 0 if they are the same, and > 0 if the current process is newer.
  181. //
  182. ////////////////////////////////////////////////////////////////////////
  183. int
  184. Compare_EXE_Version (int app_instance, const char *filename)
  185. {
  186. int retval = 0;
  187. //
  188. // Get the image header for both executables
  189. //
  190. IMAGE_FILE_HEADER header1 = { 0 };
  191. IMAGE_FILE_HEADER header2 = { 0 };
  192. if ( ::Get_Image_File_Header ((HINSTANCE)app_instance, &header1) &&
  193. ::Get_Image_File_Header (filename, &header2))
  194. {
  195. retval = int(header1.TimeDateStamp - header2.TimeDateStamp);
  196. }
  197. return retval;
  198. }