]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / SetStamp / SetStamp.c
CommitLineData
3eb9473e 1/*++\r
2\r
3e99020d 3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
4b1e1121 4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 SetStamp.c\r
14\r
15Abstract:\r
16 Set Date/Time Stamp of Portable Executable (PE) format file\r
17\r
18--*/\r
19\r
20#include <stdio.h>\r
21#include <string.h>\r
22#include <time.h>\r
23\r
24#define LINE_MAXLEN 80\r
3e99020d
LG
25#define UTILITY_NAME "SetStamp"\r
26#define UTILITY_VERSION "v1.0"\r
3eb9473e 27void\r
28PrintUsage (\r
29 void\r
30 )\r
31/*++\r
32Routine Description:\r
33 print usage of setstamp command\r
34\r
35Arguments:\r
36 void\r
37\r
38Returns:\r
39 None\r
40--*/\r
41{\r
3e99020d
LG
42 int Index;\r
43 const char *Str[] = {\r
44 UTILITY_NAME" "UTILITY_VERSION" - Intel Set Time Stamp Utility",\r
45 " Copyright (C), 2004 - 2008 Intel Corporation",\r
46 \r
47#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
48 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
49#endif\r
50 "",\r
51 "Usage:",\r
52 " "UTILITY_NAME" PEFILE TIMEFILE",\r
53 "Description:",\r
54 " Set Date/Time Stamp of Portable Executable (PE) format file",\r
55 NULL\r
56 };\r
57 for (Index = 0; Str[Index] != NULL; Index++) {\r
58 fprintf (stdout, "%s\n", Str[Index]);\r
59 }\r
60 \r
3eb9473e 61}\r
62\r
63int\r
64GetDateTime (\r
65 FILE *fp,\r
66 time_t *ltime\r
67 )\r
68/*++\r
69Routine Description:\r
70 Read the date and time from TIME file. If the date/time string is\r
71"NOW NOW", write the current date and time to TIME file and set it to\r
72ltime. Else, set the date and time of TIME file to ltime.\r
73\r
74Arguments:\r
75 fp - The pointer of TIME file\r
76 ltime - Date and time\r
77\r
78Returns:\r
79 = 0 - Success\r
80 = -1 - Failed\r
81--*/\r
82{\r
83 char buffer[LINE_MAXLEN];\r
84 struct tm stime;\r
85 struct tm *now;\r
86\r
87 if (fgets (buffer, LINE_MAXLEN, fp) == NULL) {\r
88 printf ("Error: Cannot read TIME file.\n");\r
89 return -1;\r
90 }\r
91 //\r
92 // compare the value with "NOW NOW", write TIME file if equal\r
93 //\r
94 if (strncmp (buffer, "NOW NOW", 7) == 0) {\r
95 //\r
96 // get system current time and date\r
97 //\r
98 time (ltime);\r
99\r
100 now = localtime (ltime);\r
101 if (now == NULL) {\r
102 printf ("Error: Cannot get local time.\n");\r
103 return -1;\r
104 }\r
105\r
106 if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) {\r
107 printf ("Error: Cannot format time string.\n");\r
108 return -1;\r
109 }\r
110 //\r
111 // write TIME file\r
112 //\r
113 if (fseek (fp, 0, SEEK_SET) != 0) {\r
114 printf ("Error: Cannot move location of TIME file.\n");\r
115 return -1;\r
116 }\r
117\r
118 if (fputs (buffer, fp) == EOF) {\r
119 printf ("Error: Cannot write time string to TIME file.\n");\r
120 return -1;\r
121 }\r
122 //\r
123 // ltime has been set as current time and date, return\r
124 //\r
125 return 0;\r
126 }\r
127 //\r
128 // get the date and time from buffer\r
129 //\r
130 if (6 != sscanf (\r
131 buffer,\r
132 "%d-%d-%d %d:%d:%d",\r
133 &stime.tm_year,\r
134 &stime.tm_mon,\r
135 &stime.tm_mday,\r
136 &stime.tm_hour,\r
137 &stime.tm_min,\r
138 &stime.tm_sec\r
139 )) {\r
140 printf ("Error: Invaild date or time!\n");\r
141 return -1;\r
142 }\r
143 //\r
144 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
145 //\r
146 stime.tm_mon -= 1;\r
147\r
148 //\r
149 // in struct, Year (current year minus 1900)\r
150 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
151 //\r
152 //\r
153 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
154 //\r
155 if (stime.tm_year <= 38) {\r
156 stime.tm_year += 100;\r
157 }\r
158 //\r
159 // convert 1970 -> 70, 2000 -> 100, ...\r
160 //\r
161 else if (stime.tm_year >= 1970) {\r
162 stime.tm_year -= 1900;\r
163 }\r
164 //\r
165 // convert the date and time to time_t format\r
166 //\r
167 *ltime = mktime (&stime);\r
168 if (*ltime == (time_t) - 1) {\r
169 printf ("Error: Invalid date or time!\n");\r
170 return -1;\r
171 }\r
172\r
173 return 0;\r
174}\r
175\r
176int\r
177ReadFromFile (\r
178 FILE *fp,\r
179 long offset,\r
180 void *buffer,\r
181 int size\r
182 )\r
183/*++\r
184Routine Description:\r
185 read data from a specified location of file\r
186\r
187Arguments:\r
188 fp - file pointer\r
189 offset - number of bytes from beginning of file\r
190 buffer - buffer used to store data\r
191 size - size of buffer\r
192\r
193Returns:\r
194 = 0 - Success\r
195 = -1 - Failed\r
196--*/\r
197{\r
198 //\r
199 // set file pointer to the specified location of file\r
200 //\r
201 if (fseek (fp, offset, SEEK_SET) != 0) {\r
202 printf ("Error: Cannot move the current location of the file.\n");\r
203 return -1;\r
204 }\r
205 //\r
206 // read data from the file\r
207 //\r
208 if (fread (buffer, size, 1, fp) != 1) {\r
209 printf ("Error: Cannot read data from the file.\n");\r
210 return -1;\r
211 }\r
212\r
213 return 0;\r
214}\r
215\r
216int\r
217WriteToFile (\r
218 FILE *fp,\r
219 long offset,\r
220 void *buffer,\r
221 int size\r
222 )\r
223/*++\r
224Routine Description:\r
225 write data to a specified location of file\r
226\r
227Arguments:\r
228 fp - file pointer\r
229 offset - number of bytes from beginning of file\r
230 buffer - buffer used to store data\r
231 size - size of buffer\r
232\r
233Returns:\r
234 = 0 - Success\r
235 = -1 - Failed\r
236--*/\r
237{\r
238 //\r
239 // set file pointer to the specified location of file\r
240 //\r
241 if (fseek (fp, offset, SEEK_SET) != 0) {\r
242 printf ("Error: Cannot move the current location of the file.\n");\r
243 return -1;\r
244 }\r
245 //\r
246 // write data to the file\r
247 //\r
248 if (fwrite (buffer, size, 1, fp) != 1) {\r
249 perror ("Error: Cannot write data to the file.\n");\r
250 return -1;\r
251 }\r
252\r
253 return 0;\r
254}\r
255\r
256int\r
257SetStamp (\r
258 FILE *fp,\r
259 time_t ltime\r
260 )\r
261/*++\r
262Routine Description:\r
263 set Date/Time Stamp of the file\r
264\r
265Arguments:\r
266 fp - file pointer\r
267 ltime - time and date\r
268\r
269Returns:\r
270 = 0 - Success\r
271 = -1 - Failed\r
272--*/\r
273{\r
274 unsigned char header[4];\r
275 unsigned long offset;\r
276 unsigned long NumberOfRvaAndSizes;\r
277 unsigned int nvalue;\r
278 unsigned long lvalue;\r
279\r
280 //\r
281 // read the header of file\r
282 //\r
283 if (ReadFromFile (fp, 0, header, 2) != 0) {\r
284 return -1;\r
285 }\r
286 //\r
287 // "MZ" -- the header of image file (PE)\r
288 //\r
289 if (strncmp ((char *) header, "MZ", 2) != 0) {\r
290 printf ("Error: Invalid Image file.\n");\r
291 return -1;\r
292 }\r
293 //\r
294 // At location 0x3C, the stub has the file offset to the\r
295 // PE signature.\r
296 //\r
297 if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {\r
298 return -1;\r
299 }\r
300 //\r
301 // read the header of optional\r
302 //\r
303 if (ReadFromFile (fp, offset, header, 4) != 0) {\r
304 return -1;\r
305 }\r
306 //\r
307 // "PE\0\0" -- the signature of optional header\r
308 //\r
309 if (strncmp ((char *) header, "PE\0\0", 4) != 0) {\r
310 printf ("Error: Invalid PE format file.\n");\r
311 return -1;\r
312 }\r
313 //\r
314 // Add 8 to skip PE signature (4-byte), Machine (2-byte) and\r
315 // NumberOfSection (2-byte)\r
316 //\r
317 offset += 8;\r
318\r
319 if (WriteToFile (fp, offset, &ltime, 4) != 0) {\r
320 return -1;\r
321 }\r
322 //\r
323 // Add 16 to skip COFF file header, and get to optional header.\r
324 //\r
325 offset += 16;\r
326\r
327 //\r
328 // Check the magic field, 0x10B for PE32 and 0x20B for PE32+\r
329 //\r
330 if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {\r
331 return -1;\r
332 }\r
333 //\r
334 // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.\r
335 // Else it is 108.\r
336 //\r
337 switch (nvalue & 0xFFFF) {\r
338 case 0x10B:\r
339 offset += 92;\r
340 break;\r
341\r
342 case 0x20B:\r
343 offset += 108;\r
344 break;\r
345\r
346 default:\r
347 printf ("Error: Sorry! The Magic value is unknown.\n");\r
348 return -1;\r
349 }\r
350 //\r
351 // get the value of NumberOfRvaAndSizes\r
352 //\r
353 if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {\r
354 return -1;\r
355 }\r
356 //\r
357 // Date/time stamp exists in Export Table, Import Table, Resource Table,\r
358 // Debug Table and Delay Import Table. And in Import Table and Delay Import\r
359 // Table, it will be set when bound. So here only set the date/time stamp\r
360 // of Export Table, Resource Table and Debug Table.\r
361 //\r
362 //\r
363 // change date/time stamp of Export Table, the offset of Export Table\r
364 // is 4 + 0 * 8 = 4. And the offset of stamp is 4.\r
365 //\r
366 if (NumberOfRvaAndSizes >= 1) {\r
367 if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) {\r
368 return -1;\r
369 }\r
370\r
371 if (lvalue != 0) {\r
372 if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {\r
373 return -1;\r
374 }\r
375 }\r
376 }\r
377 //\r
378 // change date/time stamp of Resource Table, the offset of Resource Table\r
379 // is 4 + 2 * 8 = 20. And the offset of stamp is 4.\r
380 //\r
381 if (NumberOfRvaAndSizes >= 3) {\r
382 if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) {\r
383 return -1;\r
384 }\r
385\r
386 if (lvalue != 0) {\r
387 if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {\r
388 return -1;\r
389 }\r
390 }\r
391 }\r
392 //\r
393 // change date/time stamp of Debug Table, offset of Debug Table\r
394 // is 4 + 6 * 8 = 52. And the offset of stamp is 4.\r
395 //\r
396 if (NumberOfRvaAndSizes >= 7) {\r
397 if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {\r
398 return -1;\r
399 }\r
400\r
401 if (lvalue != 0) {\r
402 if (WriteToFile (fp, lvalue + 4, &ltime, 4) != 0) {\r
403 return -1;\r
404 }\r
405 }\r
406 //\r
407 // change the date/time stamp of Debug Data\r
408 //\r
409 if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) {\r
410 return -1;\r
411 }\r
412 //\r
413 // get the signature of debug data\r
414 //\r
415 if (ReadFromFile (fp, lvalue, header, 2) != 0) {\r
416 return -1;\r
417 }\r
418 //\r
419 // "NB" - the signature of Debug Data\r
420 // Need Review: (From Spec. is "NB05", From .dll is "NB10")\r
421 //\r
422 if (strncmp ((char *) header, "NB", 2) == 0) {\r
423 if (WriteToFile (fp, lvalue + 8, &ltime, 4) != 0) {\r
424 return -1;\r
425 }\r
426 }\r
427 }\r
428\r
429 return 0;\r
430}\r
431\r
432int\r
433main (\r
434 int argc,\r
435 char *argv[]\r
436 )\r
437{\r
438 FILE *fp;\r
439 time_t ltime;\r
440\r
441 //\r
442 // check the number of parameters\r
443 //\r
444 if (argc != 3) {\r
445 PrintUsage ();\r
446 return -1;\r
447 }\r
448 //\r
449 // open the TIME file, if not exists, return\r
450 //\r
451 fp = fopen (argv[2], "r+");\r
452 if (fp == NULL) {\r
453 return 0;\r
454 }\r
455 //\r
456 // get time and date from file\r
457 //\r
458 if (GetDateTime (fp, &ltime) != 0) {\r
459 fclose (fp);\r
460 return -1;\r
461 }\r
462 //\r
463 // close the TIME file\r
464 //\r
465 fclose (fp);\r
466\r
467 //\r
468 // open the PE file\r
469 //\r
470 fp = fopen (argv[1], "r+b");\r
471 if (fp == NULL) {\r
472 printf ("Error: Cannot open the PE file!\n");\r
473 return -1;\r
474 }\r
475 //\r
476 // set time and date stamp to the PE file\r
477 //\r
478 if (SetStamp (fp, ltime) != 0) {\r
479 fclose (fp);\r
480 return -1;\r
481 }\r
482\r
483 printf ("Set Date/Time Stamp to %s", ctime (&ltime));\r
484\r
485 //\r
486 // close the PE file\r
487 //\r
488 fclose (fp);\r
489\r
490 return 0;\r
491}\r