Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

500 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. imgdt.cpp
  5. Abstract:
  6. Tool to manipulate the link date/time
  7. stamp in binaries
  8. NOTE : For I386/IA64 binaries only.
  9. MappedFile abstracts the mapped binary
  10. file in the memory and has methods to
  11. get and set link datetime stamp. While
  12. setting the datetime stamp it also
  13. recomputes and updates the new checksum.
  14. Author:
  15. Vijay Jayaseelan (vijayj) Sep-23-2000
  16. Revision History:
  17. None
  18. --*/
  19. #include <iostream>
  20. #include <string>
  21. #include <exception>
  22. #include <algorithm>
  23. #include <windows.h>
  24. #include <imagehlp.h>
  25. #include <io.h>
  26. //
  27. // Usage format
  28. //
  29. std::wstring Usage(L"Usage: imgdt filename [mm/dd/yyyy] [hh:mm:ss]");
  30. //
  31. // Prototypes
  32. //
  33. BOOL
  34. FileTimeToTimeDateStamp(
  35. LPFILETIME FileTime,
  36. DWORD &DateTime
  37. );
  38. BOOL
  39. TimeDateStampToFileTime(
  40. DWORD DateTime,
  41. LPFILETIME FileTime
  42. );
  43. //
  44. // Helper dump operators
  45. //
  46. std::ostream& operator<<(std::ostream &os, const std::wstring &str) {
  47. FILE *OutStream = (&os == &std::cerr) ? stderr : stdout;
  48. fwprintf(OutStream, str.c_str());
  49. return os;
  50. }
  51. std::ostream& operator<<(std::ostream &os, const SYSTEMTIME &Time) {
  52. os << Time.wMonth << '/' << Time.wDay << '/' << Time.wYear;
  53. os << ", " << Time.wHour << ":" << Time.wMinute << ":" << Time.wSecond;
  54. return os;
  55. }
  56. //
  57. // Exceptions
  58. //
  59. struct ProgramException : public std::exception {
  60. virtual void Dump(std::ostream &os) = 0;
  61. };
  62. //
  63. // Abstracts a Win32 error
  64. //
  65. struct W32Error : public ProgramException {
  66. DWORD ErrorCode;
  67. W32Error(DWORD ErrCode) : ErrorCode(ErrCode){}
  68. void Dump(std::ostream &os) {
  69. WCHAR MsgBuffer[4096];
  70. MsgBuffer[0] = UNICODE_NULL;
  71. DWORD CharCount = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
  72. NULL,
  73. ErrorCode,
  74. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  75. MsgBuffer,
  76. sizeof(MsgBuffer)/sizeof(WCHAR),
  77. NULL);
  78. if (CharCount) {
  79. std::wstring Msg(MsgBuffer);
  80. os << Msg;
  81. } else {
  82. os << std::hex << ErrorCode;
  83. }
  84. }
  85. };
  86. //
  87. // Invalid arguments
  88. //
  89. struct InvalidArguments : public ProgramException {
  90. const char *what() const throw() {
  91. return "Invalid Arguments";
  92. }
  93. void Dump(std::ostream &os) {
  94. os << what() << std::endl;
  95. }
  96. };
  97. //
  98. // Invalid program usage or help
  99. //
  100. struct ProgramUsage : public InvalidArguments {
  101. std::wstring UsageStr;
  102. ProgramUsage(const std::wstring &Usage) : UsageStr(Usage){}
  103. const char *what() const throw() {
  104. return "Program Usage";
  105. }
  106. void Dump(std::ostream &os) {
  107. os << UsageStr << std::endl;
  108. }
  109. };
  110. //
  111. // Invalid file name
  112. //
  113. struct InvalidFileName : InvalidArguments {
  114. std::wstring FileName;
  115. InvalidFileName(const std::wstring &file) : FileName(file){}
  116. const char *what() const throw() {
  117. return "Invalid Filename";
  118. }
  119. virtual void Dump(std::ostream &os) {
  120. os << what() << " : " << FileName << std::endl;
  121. }
  122. };
  123. //
  124. // Argument cracker
  125. //
  126. struct ProgramArguments {
  127. std::wstring ImageName;
  128. bool Set;
  129. SYSTEMTIME TimeToSet;
  130. ProgramArguments(int Argc, wchar_t *Argv[]) {
  131. Set = false;
  132. memset(&TimeToSet, 0, sizeof(SYSTEMTIME));
  133. if (Argc > 1) {
  134. ImageName = Argv[1];
  135. if ((ImageName == L"/?") || (ImageName == L"?") ||
  136. (ImageName == L"-?")) {
  137. throw new ProgramUsage(Usage);
  138. }
  139. if (_waccess(ImageName.c_str(), 0)) {
  140. throw new InvalidFileName(ImageName);
  141. }
  142. if (Argc > 2) {
  143. Set = true;
  144. std::wstring Date = Argv[2];
  145. if (!ParseDateTime(Date, TimeToSet.wMonth,
  146. TimeToSet.wDay, TimeToSet.wYear)) {
  147. throw new InvalidArguments();
  148. }
  149. if (Argc > 3) {
  150. std::wstring Time = Argv[3];
  151. if (!ParseDateTime(Time, TimeToSet.wHour,
  152. TimeToSet.wMinute, TimeToSet.wSecond, L':')) {
  153. throw new InvalidArguments();
  154. }
  155. }
  156. if (!IsValidSystemTime()) {
  157. throw new InvalidArguments();
  158. }
  159. }
  160. } else {
  161. throw new ProgramUsage(Usage);
  162. }
  163. }
  164. bool ParseDateTime(const std::wstring &Input,
  165. WORD &First, WORD &Second, WORD &Third, wchar_t Separator = L'/') {
  166. bool Result = false;
  167. std::wstring::size_type Count = std::count(Input.begin(), Input.end(), Separator);
  168. if (Count == 2) {
  169. std::wstring::size_type FirstSlashPos = Input.find(Separator);
  170. std::wstring::size_type SecondSlashPos = Input.find(Separator, FirstSlashPos + 1);
  171. std::wstring FirstStr = Input.substr(0, FirstSlashPos);
  172. std::wstring SecondStr = Input.substr(FirstSlashPos + 1,
  173. SecondSlashPos - FirstSlashPos - 1);
  174. std::wstring ThirdStr = Input.substr(SecondSlashPos + 1);
  175. wchar_t *Temp = NULL;
  176. long Value = wcstol(FirstStr.c_str(), &Temp, 10);
  177. if (!errno) {
  178. First = (WORD)Value;
  179. Value = wcstol(SecondStr.c_str(), &Temp, 10);
  180. if (!errno) {
  181. Second = (WORD)Value;
  182. Value = wcstol(ThirdStr.c_str(), &Temp, 10);
  183. if (!errno) {
  184. Third = (WORD)Value;
  185. }
  186. }
  187. }
  188. if (!errno) {
  189. Result = true;
  190. }
  191. }
  192. return Result;
  193. }
  194. bool IsValidSystemTime() {
  195. return (TimeToSet.wYear && TimeToSet.wMonth && TimeToSet.wDay &&
  196. (TimeToSet.wMonth < 13) && (TimeToSet.wDay < 32) &&
  197. (TimeToSet.wSecond < 60) && (TimeToSet.wMinute < 60) &&
  198. (TimeToSet.wHour < 24));
  199. }
  200. friend std::ostream operator<<(std::ostream &os, const ProgramArguments &Args) {
  201. os << "Arguments : "
  202. << Args.ImageName << ", "
  203. << "Set = " << Args.Set;
  204. if (Args.Set) {
  205. os << ", " << Args.TimeToSet << std::endl;
  206. }
  207. return os;
  208. }
  209. };
  210. //
  211. // Memory mapped file abstraction
  212. //
  213. class MappedFile {
  214. public:
  215. MappedFile(const std::wstring &ImgName) : ImageName(ImgName){
  216. DWORD ErrorCode = 0;
  217. ImageFileHandle = ImageFileMap = NULL;
  218. ImageFileView = NULL;
  219. ImageHdr = NULL;
  220. ImageFileHandle = CreateFileW(ImageName.c_str(),
  221. GENERIC_WRITE | GENERIC_READ,
  222. 0,
  223. NULL,
  224. OPEN_EXISTING,
  225. FILE_ATTRIBUTE_NORMAL,
  226. NULL);
  227. if (ImageFileHandle != INVALID_HANDLE_VALUE) {
  228. ImageFileMap = CreateFileMapping(ImageFileHandle,
  229. NULL,
  230. PAGE_READWRITE,
  231. 0,
  232. 0,
  233. NULL);
  234. if (ImageFileMap) {
  235. ImageFileView = MapViewOfFile(ImageFileMap,
  236. FILE_MAP_ALL_ACCESS,
  237. 0,
  238. 0,
  239. 0);
  240. if (ImageFileView) {
  241. ImageHdr = ImageNtHeader(ImageFileView);
  242. if (!ImageHdr) {
  243. ErrorCode = GetLastError();
  244. }
  245. } else {
  246. ErrorCode = GetLastError();
  247. }
  248. } else {
  249. ErrorCode = GetLastError();
  250. }
  251. } else {
  252. ErrorCode = GetLastError();
  253. }
  254. if (ErrorCode) {
  255. throw new W32Error(ErrorCode);
  256. }
  257. }
  258. DWORD GetDateTime(SYSTEMTIME &Time) {
  259. FILETIME FileTime;
  260. DWORD DateTime = ImageHdr->FileHeader.TimeDateStamp;
  261. ZeroMemory(&FileTime, sizeof(FILETIME));
  262. if (TimeDateStampToFileTime(DateTime, &FileTime)) {
  263. FileTimeToSystemTime(&FileTime, &Time);
  264. }
  265. return GetLastError();
  266. }
  267. DWORD SetDateTime(SYSTEMTIME &Time) {
  268. FILETIME FileTime;
  269. ZeroMemory(&FileTime, sizeof(FILETIME));
  270. std::cout << Time << std::endl;
  271. if (SystemTimeToFileTime(&Time, &FileTime)) {
  272. DWORD DateTime = 0;
  273. BY_HANDLE_FILE_INFORMATION FileInfo = {0};
  274. if (FileTimeToTimeDateStamp(&FileTime, DateTime) &&
  275. GetFileInformationByHandle(ImageFileHandle, &FileInfo)) {
  276. ImageHdr->FileHeader.TimeDateStamp = DateTime;
  277. DWORD HdrSum = 0;
  278. DWORD ChkSum = 0;
  279. PIMAGE_NT_HEADERS NtHdrs = CheckSumMappedFile(ImageFileView,
  280. FileInfo.nFileSizeLow,
  281. &HdrSum,
  282. &ChkSum);
  283. if (NtHdrs) {
  284. if (ImageHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
  285. PIMAGE_NT_HEADERS64 NtHdrs64 =
  286. (PIMAGE_NT_HEADERS64)NtHdrs;
  287. NtHdrs64->OptionalHeader.CheckSum = ChkSum;
  288. } else {
  289. NtHdrs->OptionalHeader.CheckSum = ChkSum;
  290. }
  291. }
  292. }
  293. }
  294. return GetLastError();
  295. }
  296. ~MappedFile() {
  297. if (ImageFileView)
  298. UnmapViewOfFile(ImageFileView);
  299. if (ImageFileMap)
  300. CloseHandle(ImageFileMap);
  301. if (ImageFileHandle && (ImageFileHandle != INVALID_HANDLE_VALUE))
  302. CloseHandle(ImageFileHandle);
  303. }
  304. protected:
  305. //
  306. // data members
  307. //
  308. HANDLE ImageFileHandle;
  309. HANDLE ImageFileMap;
  310. PVOID ImageFileView;
  311. PIMAGE_NT_HEADERS ImageHdr;
  312. std::wstring ImageName;
  313. };
  314. //
  315. // main() entry point
  316. //
  317. int
  318. __cdecl
  319. wmain(
  320. int Argc,
  321. wchar_t *Argv[]
  322. )
  323. {
  324. int Result = 0;
  325. try {
  326. DWORD Error = 0;
  327. ProgramArguments Args(Argc, Argv);
  328. MappedFile ImgFile(Args.ImageName);
  329. if (Args.Set) {
  330. Error = ImgFile.SetDateTime(Args.TimeToSet);
  331. } else {
  332. Error = ImgFile.GetDateTime(Args.TimeToSet);
  333. if (!Error) {
  334. std::cout << Args.TimeToSet << std::endl;
  335. }
  336. }
  337. if (Error) {
  338. throw new W32Error(Error);
  339. }
  340. }
  341. catch(ProgramUsage *PrgUsg) {
  342. Result = 1;
  343. PrgUsg->Dump(std::cout);
  344. delete PrgUsg;
  345. } catch (InvalidArguments *InvArgs) {
  346. Result = 1;
  347. InvArgs->Dump(std::cout);
  348. delete InvArgs;
  349. std::cout << Usage;
  350. } catch (ProgramException *PrgExp) {
  351. Result = 1;
  352. PrgExp->Dump(std::cout);
  353. delete PrgExp;
  354. } catch (exception *Exp) {
  355. Result = 1;
  356. std::cout << Exp->what() << std::endl;
  357. }
  358. return Result;
  359. }
  360. //
  361. // These functions convert GMT time datetime stamp
  362. // to FILETIME and vice-versa
  363. //
  364. BOOL
  365. FileTimeToTimeDateStamp(
  366. LPFILETIME FileTime,
  367. DWORD &DateTime
  368. )
  369. {
  370. __int64 t1970 = 0x019DB1DED53E8000; // Magic... GMT... Don't ask....
  371. __int64 Time = 0;
  372. memcpy(&Time, FileTime, sizeof(Time));
  373. Time -= t1970;
  374. Time /= 10000000;
  375. DateTime = (DWORD)Time;
  376. return TRUE;
  377. }
  378. BOOL
  379. TimeDateStampToFileTime(
  380. DWORD DateTime,
  381. LPFILETIME FileTime
  382. )
  383. {
  384. __int64 t1970 = 0x019DB1DED53E8000; // Magic... GMT... Don't ask....
  385. __int64 timeStampIn100nsIncr = (__int64)DateTime * 10000000;
  386. __int64 finalValue = t1970 + timeStampIn100nsIncr;
  387. memcpy(FileTime, &finalValue, sizeof( finalValue ) );
  388. return TRUE;
  389. }