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