mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-27 10:50:43 +00:00 
			
		
		
		
	 c6359f6825
			
		
	
	
		c6359f6825
		
	
	
	
	
		
			
			git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2211 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			528 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			528 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2004 - 2007, Intel Corporation                                                         
 | |
| All rights reserved. This program and the accompanying materials                          
 | |
| are licensed and made available under the terms and conditions of the BSD License         
 | |
| which accompanies this distribution.  The full text of the license may be found at        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| Module Name:
 | |
|   SetStamp.c
 | |
| 
 | |
| Abstract:
 | |
|   Set Date/Time Stamp of Portable Executable (PE) format file
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <time.h>
 | |
| 
 | |
| #define LINE_MAXLEN 80
 | |
| 
 | |
| //
 | |
| // Utility Name
 | |
| //
 | |
| #define UTILITY_NAME  "SetStamp"
 | |
| 
 | |
| //
 | |
| // Utility version information
 | |
| //
 | |
| #define UTILITY_MAJOR_VERSION 0
 | |
| #define UTILITY_MINOR_VERSION 1
 | |
| 
 | |
| void
 | |
| Version (
 | |
|   void
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Displays the standard utility information to SDTOUT
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   printf ("%s v%d.%d -Utility to set Date/Time Stamp for Portable Executable (PE) format file.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
 | |
|   printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
 | |
| }
 | |
| 
 | |
| void
 | |
| Usage (
 | |
|   void
 | |
|   )
 | |
| /*++
 | |
| Routine Description:
 | |
|   print usage of setstamp command
 | |
| 
 | |
| Arguments:
 | |
|   void
 | |
| 
 | |
| Returns:
 | |
|   None
 | |
| --*/
 | |
| {
 | |
|   Version();
 | |
|   
 | |
|   //
 | |
|   // print usage of command
 | |
|   //
 | |
|   printf ("\nUsage: SetStamp <PE-File> <TIME-File>\n");
 | |
| }
 | |
| 
 | |
| int
 | |
| GetDateTime (
 | |
|   FILE      *fp,
 | |
|   time_t    *ltime
 | |
|   )
 | |
| /*++
 | |
| Routine Description:
 | |
|   Read the date and time from TIME file. If the date/time string is
 | |
| "NOW NOW", write the current date and time to TIME file and set it to
 | |
| ltime. Else, set the date and time of TIME file to ltime.
 | |
| 
 | |
| Arguments:
 | |
|   fp              - The pointer of TIME file
 | |
|   ltime           - Date and time
 | |
| 
 | |
| Returns:
 | |
|   =  0            - Success
 | |
|   = -1            - Failed
 | |
| --*/
 | |
| {
 | |
|   char      buffer[LINE_MAXLEN];
 | |
|   struct tm stime;
 | |
|   struct tm *now;
 | |
| 
 | |
|   if (fgets (buffer, LINE_MAXLEN, fp) == NULL) {
 | |
|     printf ("Error: Cannot read TIME file.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // compare the value with "NOW NOW", write TIME file if equal
 | |
|   //
 | |
|   if (strncmp (buffer, "NOW NOW", 7) == 0) {
 | |
|     //
 | |
|     // get system current time and date
 | |
|     //
 | |
|     time (ltime);
 | |
| 
 | |
|     now = localtime (ltime);
 | |
|     if (now == NULL) {
 | |
|       printf ("Error: Cannot get local time.\n");
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) {
 | |
|       printf ("Error: Cannot format time string.\n");
 | |
|       return -1;
 | |
|     }
 | |
|     //
 | |
|     // write TIME file
 | |
|     //
 | |
|     if (fseek (fp, 0, SEEK_SET) != 0) {
 | |
|       printf ("Error: Cannot move location of TIME file.\n");
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     if (fputs (buffer, fp) == EOF) {
 | |
|       printf ("Error: Cannot write time string to TIME file.\n");
 | |
|       return -1;
 | |
|     }
 | |
|     //
 | |
|     // ltime has been set as current time and date, return
 | |
|     //
 | |
|     return 0;
 | |
|   }
 | |
|   //
 | |
|   // get the date and time from buffer
 | |
|   //
 | |
|   if (6 != sscanf (
 | |
|             buffer,
 | |
|             "%d-%d-%d %d:%d:%d",
 | |
|             &stime.tm_year,
 | |
|             &stime.tm_mon,
 | |
|             &stime.tm_mday,
 | |
|             &stime.tm_hour,
 | |
|             &stime.tm_min,
 | |
|             &stime.tm_sec
 | |
|             )) {
 | |
|     printf ("Error: Invaild date or time!\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
 | |
|   //
 | |
|   stime.tm_mon -= 1;
 | |
| 
 | |
|   //
 | |
|   // in struct, Year (current year minus 1900)
 | |
|   // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
 | |
|   //
 | |
|   //
 | |
|   // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
 | |
|   //
 | |
|   if (stime.tm_year <= 38) {
 | |
|     stime.tm_year += 100;
 | |
|   }
 | |
|   //
 | |
|   // convert 1970 -> 70, 2000 -> 100, ...
 | |
|   //
 | |
|   else if (stime.tm_year >= 1970) {
 | |
|     stime.tm_year -= 1900;
 | |
|   }
 | |
|   //
 | |
|   // convert the date and time to time_t format
 | |
|   //
 | |
|   *ltime = mktime (&stime);
 | |
|   if (*ltime == (time_t) - 1) {
 | |
|     printf ("Error: Invalid date or time!\n");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| ReadFromFile (
 | |
|   FILE      *fp,
 | |
|   long      offset,
 | |
|   void      *buffer,
 | |
|   int       size
 | |
|   )
 | |
| /*++
 | |
| Routine Description:
 | |
|   read data from a specified location of file
 | |
| 
 | |
| Arguments:
 | |
|   fp              - file pointer
 | |
|   offset          - number of bytes from beginning of file
 | |
|   buffer          - buffer used to store data
 | |
|   size            - size of buffer
 | |
| 
 | |
| Returns:
 | |
|   =  0            - Success
 | |
|   = -1            - Failed
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // set file pointer to the specified location of file
 | |
|   //
 | |
|   if (fseek (fp, offset, SEEK_SET) != 0) {
 | |
|     printf ("Error: Cannot move the current location of the file.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // read data from the file
 | |
|   //
 | |
|   if (fread (buffer, size, 1, fp) != 1) {
 | |
|     printf ("Error: Cannot read data from the file.\n");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| WriteToFile (
 | |
|   FILE      *fp,
 | |
|   long      offset,
 | |
|   void      *buffer,
 | |
|   int       size
 | |
|   )
 | |
| /*++
 | |
| Routine Description:
 | |
|   write data to a specified location of file
 | |
| 
 | |
| Arguments:
 | |
|   fp              - file pointer
 | |
|   offset          - number of bytes from beginning of file
 | |
|   buffer          - buffer used to store data
 | |
|   size            - size of buffer
 | |
| 
 | |
| Returns:
 | |
|   =  0            - Success
 | |
|   = -1            - Failed
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // set file pointer to the specified location of file
 | |
|   //
 | |
|   if (fseek (fp, offset, SEEK_SET) != 0) {
 | |
|     printf ("Error: Cannot move the current location of the file.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // write data to the file
 | |
|   //
 | |
|   if (fwrite (buffer, size, 1, fp) != 1) {
 | |
|     perror ("Error: Cannot write data to the file.\n");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| SetStamp (
 | |
|   FILE      *fp,
 | |
|   time_t    ltime
 | |
|   )
 | |
| /*++
 | |
| Routine Description:
 | |
|   set Date/Time Stamp of the file
 | |
| 
 | |
| Arguments:
 | |
|   fp              - file pointer
 | |
|   ltime           - time and date
 | |
| 
 | |
| Returns:
 | |
|   =  0            - Success
 | |
|   = -1            - Failed
 | |
| --*/
 | |
| {
 | |
|   unsigned char header[4];
 | |
|   unsigned long offset;
 | |
|   unsigned long NumberOfRvaAndSizes;
 | |
|   unsigned int  nvalue;
 | |
|   unsigned long lvalue;
 | |
| 
 | |
|   //
 | |
|   // read the header of file
 | |
|   //
 | |
|   if (ReadFromFile (fp, 0, header, 2) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // "MZ" -- the header of image file (PE)
 | |
|   //
 | |
|   if (strncmp ((char *) header, "MZ", 2) != 0) {
 | |
|     printf ("Error: Invalid Image file.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // At location 0x3C, the stub has the file offset to the
 | |
|   // PE signature.
 | |
|   //
 | |
|   if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // read the header of optional
 | |
|   //
 | |
|   if (ReadFromFile (fp, offset, header, 4) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // "PE\0\0" -- the signature of optional header
 | |
|   //
 | |
|   if (strncmp ((char *) header, "PE\0\0", 4) != 0) {
 | |
|     printf ("Error: Invalid PE format file.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // Add 8 to skip PE signature (4-byte), Machine (2-byte) and
 | |
|   // NumberOfSection (2-byte)
 | |
|   //
 | |
|   offset += 8;
 | |
| 
 | |
|   if (WriteToFile (fp, offset, <ime, 4) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // Add 16 to skip COFF file header, and get to optional header.
 | |
|   //
 | |
|   offset += 16;
 | |
| 
 | |
|   //
 | |
|   // Check the magic field, 0x10B for PE32 and 0x20B for PE32+
 | |
|   //
 | |
|   if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.
 | |
|   // Else it is 108.
 | |
|   //
 | |
|   switch (nvalue & 0xFFFF) {
 | |
|   case 0x10B:
 | |
|     offset += 92;
 | |
|     break;
 | |
| 
 | |
|   case 0x20B:
 | |
|     offset += 108;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     printf ("Error: Sorry! The Magic value is unknown.\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // get the value of NumberOfRvaAndSizes
 | |
|   //
 | |
|   if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // Date/time stamp exists in Export Table, Import Table, Resource Table,
 | |
|   // Debug Table and Delay Import Table. And in Import Table and Delay Import
 | |
|   // Table, it will be set when bound. So here only set the date/time stamp
 | |
|   // of Export Table, Resource Table and Debug Table.
 | |
|   //
 | |
|   //
 | |
|   // change date/time stamp of Export Table, the offset of Export Table
 | |
|   // is 4 + 0 * 8 = 4. And the offset of stamp is 4.
 | |
|   //
 | |
|   if (NumberOfRvaAndSizes >= 1) {
 | |
|     if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) {
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     if (lvalue != 0) {
 | |
|       if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) {
 | |
|         return -1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // change date/time stamp of Resource Table, the offset of Resource Table
 | |
|   // is 4 + 2 * 8 = 20. And the offset of stamp is 4.
 | |
|   //
 | |
|   if (NumberOfRvaAndSizes >= 3) {
 | |
|     if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) {
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     if (lvalue != 0) {
 | |
|       if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) {
 | |
|         return -1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // change date/time stamp of Debug Table, offset of Debug Table
 | |
|   // is 4 + 6 * 8 = 52. And the offset of stamp is 4.
 | |
|   //
 | |
|   if (NumberOfRvaAndSizes >= 7) {
 | |
|     if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     if (lvalue != 0) {
 | |
|       if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) {
 | |
|         return -1;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // change the date/time stamp of Debug Data
 | |
|     //
 | |
|     if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) {
 | |
|       return -1;
 | |
|     }
 | |
|     //
 | |
|     // get the signature of debug data
 | |
|     //
 | |
|     if (ReadFromFile (fp, lvalue, header, 2) != 0) {
 | |
|       return -1;
 | |
|     }
 | |
|     //
 | |
|     // "NB" - the signature of Debug Data
 | |
|     // Need Review: (From Spec. is "NB05", From .dll is "NB10")
 | |
|     //
 | |
|     if (strncmp ((char *) header, "NB", 2) == 0) {
 | |
|       if (WriteToFile (fp, lvalue + 8, <ime, 4) != 0) {
 | |
|         return -1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| int
 | |
| main (
 | |
|   int       argc,
 | |
|   char      *argv[]
 | |
|   )
 | |
| {
 | |
|   FILE    *fp;
 | |
|   time_t  ltime;
 | |
| 
 | |
|   if (argc == 1) {
 | |
|     Usage();
 | |
|     return -1;
 | |
|   }
 | |
|     
 | |
|   if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
 | |
|       (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
 | |
|     Usage();
 | |
|     return -1;
 | |
|   }
 | |
|   
 | |
|   if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
 | |
|     Version();
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // check the number of parameters
 | |
|   //
 | |
|   if (argc != 3) {
 | |
|     Usage ();
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // open the TIME file, if not exists, return
 | |
|   //
 | |
|   fp = fopen (argv[2], "r+");
 | |
|   if (fp == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
|   //
 | |
|   // get time and date from file
 | |
|   //
 | |
|   if (GetDateTime (fp, <ime) != 0) {
 | |
|     fclose (fp);
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // close the TIME file
 | |
|   //
 | |
|   fclose (fp);
 | |
| 
 | |
|   //
 | |
|   // open the PE file
 | |
|   //
 | |
|   fp = fopen (argv[1], "r+b");
 | |
|   if (fp == NULL) {
 | |
|     printf ("Error: Cannot open the PE file!\n");
 | |
|     return -1;
 | |
|   }
 | |
|   //
 | |
|   // set time and date stamp to the PE file
 | |
|   //
 | |
|   if (SetStamp (fp, ltime) != 0) {
 | |
|     fclose (fp);
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   printf ("Set Date/Time Stamp to %s", ctime (<ime));
 | |
| 
 | |
|   //
 | |
|   // close the PE file
 | |
|   //
 | |
|   fclose (fp);
 | |
| 
 | |
|   return 0;
 | |
| }
 |