Leaked source code of windows server 2003
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.

818 lines
24 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include "filever.h"
  6. // command line flags
  7. UINT fFlags = 0;
  8. VOID
  9. usage(CHAR *szProgName)
  10. {
  11. puts ("Prints file version information.\n");
  12. printf("%s [/S] [/V] [/E] [/X] [/B] [/A] [/D] [[drive:][path][filename]]\n", szProgName);
  13. puts ("\n"
  14. "/S\tDisplays files in specified directory and all subdirectories.\n"
  15. "/V\tList verbose version information if available.\n"
  16. "/E\tList executables only.\n"
  17. "/X\tDisplays short names generated for non-8dot3 file names.\n"
  18. "/B\tUses bare format (no dir listing).\n"
  19. "/A\tDon't display file attributes.\n"
  20. "/D\tDon't display file date and time."
  21. #ifdef DEBUG
  22. "\n/z\tPrint debug messages."
  23. #endif
  24. );
  25. }
  26. int __cdecl
  27. main(INT argc, CHAR **argv)
  28. {
  29. INT i;
  30. LPTSTR szT;
  31. UINT cDirs = 0;
  32. if (argc < 2)
  33. {
  34. usage(argv[0]);
  35. exit(0);
  36. }
  37. // Loop through and process all the args
  38. for(i = 1; i < argc; ++i)
  39. {
  40. if(argv[i][0] != '/' && argv[i][0] != '-')
  41. {
  42. cDirs++;
  43. continue;
  44. }
  45. for(szT = &argv[i][1]; *szT; ++szT)
  46. {
  47. switch(*szT)
  48. {
  49. #ifdef DEBUG
  50. case 'z':
  51. fFlags |= FSTR_DEBUG;
  52. break;
  53. #endif
  54. case 'l':
  55. case 'L':
  56. // provided for compatability (list format is default now)
  57. break;
  58. case 'd':
  59. case 'D':
  60. fFlags |= FSTR_NODATETIME;
  61. break;
  62. case 'a':
  63. case 'A':
  64. fFlags |= FSTR_NOATTRS;
  65. break;
  66. case 'b':
  67. case 'B':
  68. fFlags |= FSTR_BAREFORMAT;
  69. break;
  70. case 'x':
  71. case 'X':
  72. fFlags |= FSTR_SHORTNAME;
  73. break;
  74. case 'S':
  75. case 's':
  76. fFlags |= (FSTR_RECURSE | FSTR_PRINTDIR);
  77. break;
  78. case 'V':
  79. case 'v':
  80. fFlags |= FSTR_VERBOSE;
  81. break;
  82. case 'e':
  83. case 'E':
  84. fFlags |= FSTR_EXESONLY;
  85. break;
  86. case '?':
  87. case 'h':
  88. case 'H':
  89. usage(argv[0]);
  90. exit(0);
  91. default:
  92. printf("Invalid flag specified: (-%c)\n", *szT);
  93. usage(argv[0]);
  94. exit(-1);
  95. }
  96. }
  97. }
  98. #ifdef DEBUG
  99. if(fFlags & FSTR_DEBUG)
  100. printf("DBG> Command line dir count: %d\n", cDirs);
  101. #endif
  102. // If they didn't specify a dir, default to current one
  103. if(!cDirs)
  104. {
  105. argc = 2;
  106. argv[1] = ".";
  107. }
  108. else if(cDirs > 1)
  109. {
  110. // turn on dir printing if we have more than one dir
  111. fFlags |= FSTR_PRINTDIR;
  112. }
  113. // if we have bareformat on, turn dir printing off
  114. if(fFlags & FSTR_BAREFORMAT)
  115. fFlags &= ~FSTR_PRINTDIR;
  116. for(i = 1; i < argc; ++i)
  117. {
  118. DWORD dwAttr;
  119. LPTSTR szDir = NULL;
  120. LPTSTR szPat = NULL;
  121. TCHAR szFullPath[MAX_PATH + 1];
  122. TCHAR szPattern[MAX_PATH + 1];
  123. // skip flags
  124. if(argv[i][0] == '/' || argv[i][0] == '-')
  125. continue;
  126. // Grab de dir
  127. szDir = argv[i];
  128. // get the full path to our dir
  129. if(GetFullPathName(szDir, MAX_PATH, szFullPath, &szT)) {
  130. szDir = szFullPath;
  131. } else {
  132. lstrcpy(szFullPath, szDir);
  133. szDir = szFullPath;
  134. }
  135. dwAttr = GetFileAttributes(szDir);
  136. #ifdef NEVER
  137. // If it's not a directory or -1, assume a single file and flip on verbose
  138. if(!(fFlags & FSTR_RECURSE) && !FA_DIR(dwAttr))
  139. fFlags |= FSTR_VERBOSE;
  140. #endif
  141. // If GetFileAttributes failed or it isn't a directory, grab the pattern
  142. if((dwAttr == (DWORD)-1) || !FA_DIR(dwAttr))
  143. {
  144. for(szT = szDir; *szT; szT++)
  145. {
  146. if(*szT == '\\')
  147. szPat = szT;
  148. }
  149. if(szPat)
  150. *szPat++ = 0;
  151. }
  152. // make sure we have a pattern
  153. if(!szPat || !*szPat)
  154. szPat = "*.*";
  155. lstrcpy(szPattern, szPat);
  156. FListFiles(szDir, szPattern);
  157. }
  158. return 0;
  159. }
  160. BOOL
  161. FListFiles(LPTSTR szDir, LPTSTR szPat)
  162. {
  163. HANDLE hf;
  164. WIN32_FIND_DATA fd;
  165. UINT cchDir;
  166. TCHAR szFileName[MAX_PATH + 1];
  167. BOOL fPrintedDir = !(fFlags & FSTR_PRINTDIR);
  168. #ifdef DEBUG
  169. if(fFlags & FSTR_DEBUG)
  170. printf("DBG> FListFiles('%s', '%s')\n", szDir, szPat);
  171. #endif
  172. // Get short name if that's what they want
  173. if(fFlags & FSTR_SHORTNAME)
  174. GetShortPathName(szDir, szDir, MAX_PATH);
  175. // Get dir length and add trailing '\' if not there
  176. cchDir = lstrlen(szDir);
  177. if(szDir[cchDir - 1] != '\\')
  178. {
  179. szDir[cchDir++] = '\\';
  180. szDir[cchDir] = 0;
  181. }
  182. // Concat pattern to dir
  183. CharLower(szDir);
  184. lstrcpy(szFileName, szDir);
  185. lstrcpy(&szFileName[cchDir], szPat);
  186. // list all the files
  187. hf = FindFirstFile(szFileName, &fd);
  188. if(hf != INVALID_HANDLE_VALUE)
  189. {
  190. do
  191. {
  192. DWORD lBinaryType;
  193. BOOL fIsDir = FA_DIR(fd.dwFileAttributes);
  194. if(fIsDir && (fd.cFileName[0] == '.'))
  195. {
  196. // skip . and ..
  197. if(!fd.cFileName[1] ||
  198. ((fd.cFileName[1] == '.') && !fd.cFileName[2]))
  199. continue;
  200. }
  201. CharLower(fd.cFileName);
  202. lstrcpy(&szFileName[cchDir], fd.cFileName);
  203. // get type of file
  204. lBinaryType = MyGetBinaryType(szFileName);
  205. if(!(fFlags & FSTR_EXESONLY) || (lBinaryType != SCS_UNKOWN))
  206. {
  207. // Print out our dir name
  208. if(!fPrintedDir)
  209. {
  210. printf("\t%s%s\n", szDir, szPat);
  211. fPrintedDir = TRUE;
  212. }
  213. // file attributes
  214. if(!(fFlags & FSTR_NOATTRS))
  215. PrintFileAttributes(fd.dwFileAttributes);
  216. // file type
  217. PrintFileType(lBinaryType);
  218. // version
  219. PrintFileVersion(szFileName);
  220. // size & date
  221. if(!(fFlags & FSTR_NODATETIME))
  222. PrintFileSizeAndDate(&fd);
  223. // print file name
  224. printf(fIsDir ? " [%s%s]\n" : " %s%s\n",
  225. fFlags & FSTR_BAREFORMAT ? szDir : "",
  226. ((fFlags & FSTR_SHORTNAME) && fd.cAlternateFileName[0]) ?
  227. fd.cAlternateFileName : fd.cFileName);
  228. // print verbose info if this isn't a dir
  229. // Win95 also craps out on dos files so ignore those too
  230. if((fFlags & FSTR_VERBOSE) &&
  231. (lBinaryType != SCS_UNKOWN) &&
  232. (lBinaryType != SCS_DOS_BINARY))
  233. GetVersionStuff(szFileName, NULL, NULL);
  234. }
  235. } while(FindNextFile(hf, &fd));
  236. FindClose(hf);
  237. }
  238. // dive into all the subdirs
  239. if(fFlags & FSTR_RECURSE)
  240. {
  241. // Concat pattern to dir
  242. lstrcpy(&szFileName[cchDir], "*.*");
  243. hf = FindFirstFile(szFileName, &fd);
  244. if(hf != INVALID_HANDLE_VALUE)
  245. {
  246. do
  247. {
  248. if(FA_DIR(fd.dwFileAttributes))
  249. {
  250. if(fd.cFileName[0] == '.')
  251. {
  252. if(!fd.cFileName[1] ||
  253. ((fd.cFileName[1] == '.') && !fd.cFileName[2]))
  254. continue;
  255. }
  256. // create new dir name and dive in
  257. lstrcpy(&szFileName[cchDir], fd.cFileName);
  258. FListFiles(szFileName, szPat);
  259. }
  260. } while(FindNextFile(hf, &fd));
  261. FindClose(hf);
  262. }
  263. }
  264. return TRUE;
  265. }
  266. #define PrintFlagsMap(_structname, _flags) \
  267. for(iType = 0; iType < sizeof(_structname)/sizeof(TypeTag); iType++) \
  268. { \
  269. if((_flags) & _structname[iType].dwTypeMask) \
  270. printf(" %s", _structname[iType].szFullStr); \
  271. }
  272. #define PrintFlagsVal(_structname, _flags) \
  273. for(iType = 0; iType < sizeof(_structname)/sizeof(TypeTag); iType++) \
  274. { \
  275. if((_flags) == _structname[iType].dwTypeMask) \
  276. { \
  277. printf(" %s", _structname[iType].szFullStr); \
  278. break; \
  279. } \
  280. }
  281. VOID
  282. PrintFixedFileInfo(VS_FIXEDFILEINFO *pvs)
  283. {
  284. UINT iType;
  285. printf("\tVS_FIXEDFILEINFO:\n");
  286. printf("\tSignature:\t%08.8lx\n", pvs->dwSignature);
  287. printf("\tStruc Ver:\t%08.8lx\n", pvs->dwStrucVersion);
  288. printf("\tFileVer:\t%08.8lx:%08.8lx (%d.%d:%d.%d)\n",
  289. pvs->dwFileVersionMS, pvs->dwFileVersionLS,
  290. HIWORD(pvs->dwFileVersionMS), LOWORD(pvs->dwFileVersionMS),
  291. HIWORD(pvs->dwFileVersionLS), LOWORD(pvs->dwFileVersionLS));
  292. printf("\tProdVer:\t%08.8lx:%08.8lx (%d.%d:%d.%d)\n",
  293. pvs->dwProductVersionMS, pvs->dwProductVersionLS,
  294. HIWORD(pvs->dwProductVersionMS), LOWORD(pvs->dwProductVersionMS),
  295. HIWORD(pvs->dwProductVersionLS), LOWORD(pvs->dwProductVersionLS));
  296. printf("\tFlagMask:\t%08.8lx\n", pvs->dwFileFlagsMask);
  297. printf("\tFlags:\t\t%08.8lx", pvs->dwFileFlags);
  298. PrintFlagsMap(ttFileFlags, pvs->dwFileFlags);
  299. printf("\n\tOS:\t\t%08.8lx", pvs->dwFileOS);
  300. PrintFlagsVal(ttFileOsHi, pvs->dwFileOS & 0xffff000);
  301. PrintFlagsVal(ttFileOsLo, LOWORD(pvs->dwFileOS));
  302. printf("\n\tFileType:\t%08.8lx", pvs->dwFileType);
  303. PrintFlagsVal(ttFType, pvs->dwFileType);
  304. printf("\n\tSubType:\t%08.8lx", pvs->dwFileSubtype);
  305. if(pvs->dwFileType == VFT_FONT)
  306. {
  307. PrintFlagsVal(ttFTypeFont, pvs->dwFileSubtype);
  308. }
  309. else if(pvs->dwFileType == VFT_DRV)
  310. {
  311. PrintFlagsVal(ttFTypeDrv, pvs->dwFileSubtype);
  312. }
  313. printf("\n\tFileDate:\t%08.8lx:%08.8lx\n", pvs->dwFileDateMS, pvs->dwFileDateLS);
  314. }
  315. typedef struct tagVERHEAD {
  316. WORD wTotLen;
  317. WORD wValLen;
  318. WORD wType; /* always 0 */
  319. WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
  320. VS_FIXEDFILEINFO vsf;
  321. } VERHEAD ;
  322. /*
  323. * [alanau]
  324. *
  325. * MyGetFileVersionInfo: Maps a file directly without using LoadLibrary. This ensures
  326. * that the right version of the file is examined without regard to where the loaded image
  327. * is. Since this is a local function, it allocates the memory which is freed by the caller.
  328. * This makes it slightly more efficient than a GetFileVersionInfoSize/GetFileVersionInfo pair.
  329. */
  330. BOOL
  331. MyGetFileVersionInfo(LPTSTR lpszFilename, LPVOID *lpVersionInfo)
  332. {
  333. VS_FIXEDFILEINFO *pvsFFI = NULL;
  334. UINT uiBytes = 0;
  335. HINSTANCE hinst;
  336. HRSRC hVerRes;
  337. HANDLE FileHandle = NULL;
  338. HANDLE MappingHandle = NULL;
  339. LPVOID DllBase = NULL;
  340. VERHEAD *pVerHead;
  341. BOOL bResult = FALSE;
  342. DWORD dwHandle;
  343. DWORD dwLength;
  344. if (!lpVersionInfo)
  345. return FALSE;
  346. *lpVersionInfo = NULL;
  347. FileHandle = CreateFile( lpszFilename,
  348. GENERIC_READ,
  349. FILE_SHARE_READ,
  350. NULL,
  351. OPEN_EXISTING,
  352. 0,
  353. NULL
  354. );
  355. if (FileHandle == INVALID_HANDLE_VALUE)
  356. goto Cleanup;
  357. MappingHandle = CreateFileMapping( FileHandle,
  358. NULL,
  359. PAGE_READONLY,
  360. 0,
  361. 0,
  362. NULL
  363. );
  364. if (MappingHandle == NULL)
  365. goto Cleanup;
  366. DllBase = MapViewOfFileEx( MappingHandle,
  367. FILE_MAP_READ,
  368. 0,
  369. 0,
  370. 0,
  371. NULL
  372. );
  373. if (DllBase == NULL)
  374. goto Cleanup;
  375. hinst = (HMODULE)((ULONG_PTR)DllBase | 0x00000001);
  376. __try {
  377. hVerRes = FindResource(hinst, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO);
  378. if (hVerRes == NULL)
  379. {
  380. // Probably a 16-bit file. Fall back to system APIs.
  381. if(!(dwLength = GetFileVersionInfoSize(lpszFilename, &dwHandle)))
  382. {
  383. if(!GetLastError())
  384. SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
  385. __leave;
  386. }
  387. if(!(*lpVersionInfo = GlobalAllocPtr(GHND, dwLength)))
  388. __leave;
  389. if(!GetFileVersionInfo(lpszFilename, 0, dwLength, *lpVersionInfo))
  390. __leave;
  391. bResult = TRUE;
  392. __leave;
  393. }
  394. pVerHead = (VERHEAD*)LoadResource(hinst, hVerRes);
  395. if (pVerHead == NULL)
  396. __leave;
  397. *lpVersionInfo = GlobalAllocPtr(GHND, pVerHead->wTotLen + pVerHead->wTotLen/2);
  398. if (*lpVersionInfo == NULL)
  399. __leave;
  400. memcpy(*lpVersionInfo, (PVOID)pVerHead, pVerHead->wTotLen);
  401. bResult = TRUE;
  402. } __except (EXCEPTION_EXECUTE_HANDLER) {
  403. }
  404. Cleanup:
  405. if (FileHandle)
  406. CloseHandle(FileHandle);
  407. if (MappingHandle)
  408. CloseHandle(MappingHandle);
  409. if (DllBase)
  410. UnmapViewOfFile(DllBase);
  411. if (*lpVersionInfo && bResult == FALSE)
  412. GlobalFreePtr(*lpVersionInfo);
  413. return bResult;
  414. }
  415. DWORD
  416. GetVersionStuff(LPTSTR szFileName, DWORD *pdwLangRet, VS_FIXEDFILEINFO *pvsRet)
  417. {
  418. LPVOID lpInfo;
  419. TCHAR key[80];
  420. DWORD dwLength;
  421. LPVOID lpvData = NULL;
  422. DWORD *pdwTranslation;
  423. UINT i, iType, cch, uLen;
  424. VS_FIXEDFILEINFO *pvs;
  425. DWORD dwDefLang = 0x409;
  426. if(!MyGetFileVersionInfo(szFileName, &lpvData))
  427. goto err;
  428. if(!VerQueryValue(lpvData, "\\VarFileInfo\\Translation", &pdwTranslation, &uLen))
  429. {
  430. if(!pdwLangRet)
  431. printf("\t- No \\VarFileInfo\\Translation, assuming %08lx\n", dwDefLang);
  432. pdwTranslation = &dwDefLang;
  433. uLen = sizeof(DWORD);
  434. }
  435. if(pdwLangRet)
  436. {
  437. *pdwLangRet = *pdwTranslation;
  438. goto fixedfileinfo;
  439. }
  440. while(uLen)
  441. {
  442. // Language
  443. printf("\tLanguage\t0x%04x", LOWORD(*pdwTranslation));
  444. if(VerLanguageName(LOWORD(*pdwTranslation), key, sizeof(key) / sizeof(TCHAR)))
  445. printf(" (%s)", key);
  446. printf("\n");
  447. // CharSet
  448. printf("\tCharSet\t\t0x%04x", HIWORD(*pdwTranslation));
  449. for(iType = 0; iType < sizeof(ltCharSet)/sizeof(CharSetTag); iType++)
  450. {
  451. if(HIWORD(*pdwTranslation) == ltCharSet[iType].wCharSetId)
  452. printf(" %s", ltCharSet[iType].szDesc);
  453. }
  454. printf("\n");
  455. tryagain:
  456. wsprintf(key, "\\StringFileInfo\\%04x%04x\\",
  457. LOWORD(*pdwTranslation), HIWORD(*pdwTranslation));
  458. lstrcat(key, "OleSelfRegister");
  459. printf("\t%s\t%s\n", "OleSelfRegister",
  460. VerQueryValue(lpvData, key, &lpInfo, &cch) ? "Enabled" : "Disabled");
  461. for(i = 0; i < (sizeof(VersionKeys) / sizeof(VersionKeys[0])); i++)
  462. {
  463. wsprintf(key, "\\StringFileInfo\\%04x%04x\\",
  464. LOWORD(*pdwTranslation), HIWORD(*pdwTranslation));
  465. lstrcat(key, VersionKeys[i]);
  466. if(VerQueryValue(lpvData, key, &lpInfo, &cch))
  467. {
  468. lstrcpy(key, VersionKeys[i]);
  469. key[15] = 0;
  470. printf("\t%s\t%s\n", key, lpInfo);
  471. }
  472. }
  473. // if the Lang is neutral, go try again with the default lang
  474. // (this seems to work with msspell32.dll)
  475. if(LOWORD(*pdwTranslation) == 0)
  476. {
  477. pdwTranslation = &dwDefLang;
  478. goto tryagain;
  479. }
  480. uLen -= sizeof(DWORD);
  481. pdwTranslation++;
  482. printf("\n");
  483. }
  484. fixedfileinfo:
  485. if(!VerQueryValue(lpvData, "\\", (LPVOID *)&pvs, &uLen))
  486. goto err;
  487. if(pvsRet)
  488. *pvsRet = *pvs;
  489. else
  490. PrintFixedFileInfo(pvs);
  491. err:
  492. dwLength = GetLastError();
  493. if(dwLength &&
  494. (dwLength != ERROR_RESOURCE_DATA_NOT_FOUND) &&
  495. (dwLength != ERROR_RESOURCE_TYPE_NOT_FOUND) &&
  496. !pvsRet)
  497. {
  498. PrintErrorMessage(dwLength, NULL);
  499. }
  500. if(lpvData)
  501. GlobalFreePtr(lpvData);
  502. return dwLength;
  503. }
  504. DWORD
  505. MyGetBinaryType(LPTSTR szFileName)
  506. {
  507. HANDLE hFile;
  508. DWORD cbRead;
  509. IMAGE_DOS_HEADER img_dos_hdr;
  510. PIMAGE_OS2_HEADER pimg_os2_hdr;
  511. IMAGE_NT_HEADERS img_nt_hdrs;
  512. DWORD lFileType = SCS_UNKOWN;
  513. if((hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  514. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE)
  515. goto err;
  516. if(!ReadFile(hFile, &img_dos_hdr, sizeof(img_dos_hdr), &cbRead, NULL))
  517. goto err;
  518. if(img_dos_hdr.e_magic != IMAGE_DOS_SIGNATURE)
  519. goto err;
  520. lFileType = SCS_DOS_BINARY;
  521. if(SetFilePointer(hFile, img_dos_hdr.e_lfanew, 0, FILE_BEGIN) == -1)
  522. goto err;
  523. if(!ReadFile(hFile, &img_nt_hdrs, sizeof(img_nt_hdrs), &cbRead, NULL))
  524. goto err;
  525. if((img_nt_hdrs.Signature & 0xffff) == IMAGE_OS2_SIGNATURE)
  526. {
  527. pimg_os2_hdr = (PIMAGE_OS2_HEADER)&img_nt_hdrs;
  528. switch(pimg_os2_hdr->ne_exetyp)
  529. {
  530. case NE_OS2:
  531. lFileType = SCS_OS216_BINARY;
  532. break;
  533. case NE_DEV386:
  534. case NE_WINDOWS:
  535. lFileType = SCS_WOW_BINARY;
  536. break;
  537. case NE_DOS4:
  538. case NE_UNKNOWN:
  539. default:
  540. // lFileType = SCS_DOS_BINARY;
  541. break;
  542. }
  543. }
  544. else if(img_nt_hdrs.Signature == IMAGE_NT_SIGNATURE)
  545. {
  546. switch(img_nt_hdrs.OptionalHeader.Subsystem)
  547. {
  548. case IMAGE_SUBSYSTEM_OS2_CUI:
  549. lFileType = SCS_OS216_BINARY;
  550. break;
  551. case IMAGE_SUBSYSTEM_POSIX_CUI:
  552. lFileType = SCS_POSIX_BINARY;
  553. break;
  554. case IMAGE_SUBSYSTEM_NATIVE:
  555. case IMAGE_SUBSYSTEM_WINDOWS_GUI:
  556. case IMAGE_SUBSYSTEM_WINDOWS_CUI:
  557. default:
  558. switch(img_nt_hdrs.FileHeader.Machine)
  559. {
  560. case IMAGE_FILE_MACHINE_I386:
  561. lFileType = SCS_32BIT_BINARY_INTEL;
  562. break;
  563. case IMAGE_FILE_MACHINE_R3000:
  564. case IMAGE_FILE_MACHINE_R4000:
  565. lFileType = SCS_32BIT_BINARY_MIPS;
  566. break;
  567. case IMAGE_FILE_MACHINE_ALPHA:
  568. lFileType = SCS_32BIT_BINARY_ALPHA;
  569. break;
  570. case IMAGE_FILE_MACHINE_ALPHA64:
  571. lFileType = SCS_32BIT_BINARY_AXP64;
  572. break;
  573. case IMAGE_FILE_MACHINE_IA64:
  574. lFileType = SCS_32BIT_BINARY_IA64;
  575. break;
  576. case IMAGE_FILE_MACHINE_POWERPC:
  577. lFileType = SCS_32BIT_BINARY_PPC;
  578. break;
  579. case IMAGE_FILE_MACHINE_AMD64:
  580. lFileType = SCS_32BIT_BINARY_AMD64;
  581. break;
  582. default:
  583. case IMAGE_FILE_MACHINE_UNKNOWN:
  584. lFileType = SCS_32BIT_BINARY;
  585. break;
  586. }
  587. break;
  588. }
  589. }
  590. err:
  591. if(hFile != INVALID_HANDLE_VALUE)
  592. CloseHandle(hFile);
  593. return lFileType;
  594. }
  595. VOID __cdecl
  596. PrintErrorMessage(DWORD dwError, LPTSTR szFmt, ...)
  597. {
  598. LPTSTR szT;
  599. va_list arglist;
  600. LPTSTR szErrMessage = NULL;
  601. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  602. NULL, dwError, 0/*LANG_USER_DEFAULT*/, (LPTSTR)&szErrMessage, 0, NULL);
  603. if(szFmt && szErrMessage)
  604. {
  605. for(szT = szErrMessage; *szT; szT++)
  606. {
  607. if(*szT == '\r' || *szT == '\n')
  608. *szT = 0;
  609. }
  610. }
  611. printf("Error 0x%08lx. %s", dwError, szErrMessage ? szErrMessage : "");
  612. if(szFmt)
  613. {
  614. va_start(arglist, szFmt);
  615. vprintf(szFmt, arglist);
  616. va_end(arglist);
  617. }
  618. if(szErrMessage)
  619. LocalFree((HLOCAL)szErrMessage);
  620. }
  621. VOID
  622. PrintFileType(DWORD lBinaryType)
  623. {
  624. LPCTSTR szFmtFileType = " - ";
  625. if(lBinaryType < (sizeof(szType) / sizeof(szType[0])))
  626. szFmtFileType = szType[lBinaryType];
  627. printf("%s", szFmtFileType);
  628. }
  629. VOID
  630. PrintFileAttributes(DWORD dwAttr)
  631. {
  632. DWORD dwT;
  633. static const FileAttr attrs[] =
  634. {{FILE_ATTRIBUTE_DIRECTORY, 'd'},
  635. {FILE_ATTRIBUTE_READONLY, 'r'},
  636. {FILE_ATTRIBUTE_ARCHIVE, 'a'},
  637. {FILE_ATTRIBUTE_HIDDEN, 'h'},
  638. {FILE_ATTRIBUTE_SYSTEM, 's'} };
  639. TCHAR szAttr[(sizeof(attrs) / sizeof(attrs[0])) + 1];
  640. for(dwT = 0; dwT < (sizeof(attrs) / sizeof(attrs[0])); dwT++)
  641. szAttr[dwT] = (dwAttr & attrs[dwT].dwAttr) ? attrs[dwT].ch : '-';
  642. szAttr[dwT] = 0;
  643. printf("%s ", szAttr);
  644. }
  645. VOID
  646. PrintFileSizeAndDate(WIN32_FIND_DATA *pfd)
  647. {
  648. FILETIME ft;
  649. SYSTEMTIME st = {0};
  650. TCHAR szSize[15];
  651. szSize[0] = 0;
  652. if(FileTimeToLocalFileTime(&pfd->ftLastWriteTime, &ft) &&
  653. FileTimeToSystemTime(&ft, &st))
  654. {
  655. TCHAR szVal[15];
  656. NUMBERFMT numfmt = {0, 0, 3, "", ",", 0};
  657. wsprintf(szVal, "%ld", pfd->nFileSizeLow); //$ SPEED
  658. GetNumberFormat(GetUserDefaultLCID(), 0, szVal, &numfmt, szSize, 15);
  659. }
  660. printf(" %10s %02d-%02d-%02d", szSize, st.wMonth, st.wDay, st.wYear);
  661. }
  662. VOID
  663. PrintFileVersion(LPTSTR szFileName)
  664. {
  665. VS_FIXEDFILEINFO vs = {0};
  666. INT iType;
  667. DWORD dwLang;
  668. TCHAR szBuffer[100];
  669. dwLang = (DWORD)-1;
  670. vs.dwFileVersionMS = (DWORD)-1;
  671. vs.dwFileVersionLS = (DWORD)-1;
  672. GetVersionStuff(szFileName, &dwLang, &vs);
  673. dwLang = LOWORD(dwLang);
  674. szBuffer[0] = 0;
  675. for(iType = 0; iType < sizeof(ttFType) / sizeof(TypeTag); iType++)
  676. {
  677. if(vs.dwFileType == ttFType[iType].dwTypeMask)
  678. {
  679. printf("%3.3s ", ttFType[iType].szTypeStr);
  680. break;
  681. }
  682. }
  683. if(iType == (sizeof(ttFType) / sizeof(TypeTag)))
  684. printf(" - ");
  685. for(iType = 0; iType < sizeof(ltLang) / sizeof(LangTag); iType++)
  686. {
  687. if(dwLang == ltLang[iType].wLangId)
  688. {
  689. printf("%3.3s ", ltLang[iType].szKey);
  690. break;
  691. }
  692. }
  693. if(iType == (sizeof(ltLang) / sizeof(LangTag)))
  694. printf(" - ");
  695. if(vs.dwFileVersionMS != (DWORD)-1)
  696. {
  697. wsprintf(szBuffer, "%u.%u.%u.%u %s",
  698. HIWORD(vs.dwFileVersionMS),
  699. LOWORD(vs.dwFileVersionMS),
  700. HIWORD(vs.dwFileVersionLS),
  701. LOWORD(vs.dwFileVersionLS),
  702. vs.dwFileFlags & VS_FF_DEBUG ? "dbg" : "shp");
  703. }
  704. else
  705. {
  706. lstrcpy(szBuffer, "- -");
  707. }
  708. printf(" %18.18s", szBuffer);
  709. }