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.

2212 lines
64 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. attributes.c
  5. Abstract:
  6. This file contains complete implementation of attribute retrieval and
  7. caching.
  8. Author:
  9. vadimb created sometime in 2000
  10. Revision History:
  11. several people contributed (clupu, dmunsil...)
  12. --*/
  13. //
  14. // Obtain tag information
  15. //
  16. #define _WANT_TAG_INFO
  17. #include "sdbp.h"
  18. #include <stddef.h>
  19. #include <time.h>
  20. #if defined(KERNEL_MODE) && defined(ALLOC_DATA_PRAGMA)
  21. #pragma data_seg()
  22. #endif // KERNEL_MODE && ALLOC_DATA_PRAGMA
  23. //
  24. // Attribute tags
  25. // The attributes are checked in the order they are listed below.
  26. //
  27. TAG g_rgAttributeTags[] = {
  28. TAG_SIZE,
  29. TAG_CHECKSUM,
  30. TAG_BIN_FILE_VERSION,
  31. TAG_BIN_PRODUCT_VERSION,
  32. TAG_PRODUCT_VERSION,
  33. TAG_FILE_DESCRIPTION,
  34. TAG_COMPANY_NAME,
  35. TAG_PRODUCT_NAME,
  36. TAG_FILE_VERSION,
  37. TAG_ORIGINAL_FILENAME,
  38. TAG_INTERNAL_NAME,
  39. TAG_LEGAL_COPYRIGHT,
  40. TAG_VERDATEHI,
  41. TAG_VERDATELO,
  42. TAG_VERFILEOS,
  43. TAG_VERFILETYPE,
  44. TAG_MODULE_TYPE,
  45. TAG_PE_CHECKSUM,
  46. TAG_LINKER_VERSION,
  47. #ifndef KERNEL_MODE
  48. TAG_16BIT_DESCRIPTION,
  49. TAG_16BIT_MODULE_NAME,
  50. #endif
  51. TAG_UPTO_BIN_FILE_VERSION,
  52. TAG_UPTO_BIN_PRODUCT_VERSION,
  53. TAG_LINK_DATE,
  54. TAG_UPTO_LINK_DATE,
  55. TAG_VER_LANGUAGE
  56. };
  57. #define ATTRIBUTE_COUNT ARRAYSIZE(g_rgAttributeTags)
  58. static TAG_INFO gaTagInfo[] = {
  59. {TAG_DATABASE ,TEXT("DATABASE")},
  60. {TAG_LIBRARY ,TEXT("LIBRARY")},
  61. {TAG_INEXCLUDE ,TEXT("INEXCLUDE")},
  62. {TAG_SHIM ,TEXT("SHIM")},
  63. {TAG_PATCH ,TEXT("PATCH")},
  64. {TAG_FLAG ,TEXT("FLAG")},
  65. {TAG_APP ,TEXT("APP")},
  66. {TAG_EXE ,TEXT("EXE")},
  67. {TAG_MATCHING_FILE ,TEXT("MATCHING_FILE")},
  68. {TAG_SHIM_REF ,TEXT("SHIM_REF")},
  69. {TAG_PATCH_REF ,TEXT("PATCH_REF")},
  70. {TAG_FLAG_REF ,TEXT("FLAG_REF")},
  71. {TAG_LAYER ,TEXT("LAYER")},
  72. {TAG_FILE ,TEXT("FILE")},
  73. {TAG_APPHELP ,TEXT("APPHELP")},
  74. {TAG_LINK ,TEXT("LINK")},
  75. {TAG_DATA ,TEXT("DATA")},
  76. {TAG_ACTION ,TEXT("ACTION")},
  77. {TAG_MSI_TRANSFORM ,TEXT("MSI TRANSFORM")},
  78. {TAG_MSI_TRANSFORM_REF ,TEXT("MSI TRANSFORM REF")},
  79. {TAG_MSI_PACKAGE ,TEXT("MSI PACKAGE")},
  80. {TAG_MSI_CUSTOM_ACTION ,TEXT("MSI CUSTOM ACTION")},
  81. {TAG_NAME ,TEXT("NAME")},
  82. {TAG_DESCRIPTION ,TEXT("DESCRIPTION")},
  83. {TAG_MODULE ,TEXT("MODULE")},
  84. {TAG_API ,TEXT("API")},
  85. {TAG_VENDOR ,TEXT("VENDOR")},
  86. {TAG_APP_NAME ,TEXT("APP_NAME")},
  87. {TAG_DLLFILE ,TEXT("DLLFILE")},
  88. {TAG_COMMAND_LINE ,TEXT("COMMAND_LINE")},
  89. {TAG_ACTION_TYPE ,TEXT("ACTION_TYPE")},
  90. {TAG_COMPANY_NAME ,TEXT("COMPANY_NAME")},
  91. {TAG_WILDCARD_NAME ,TEXT("WILDCARD_NAME")},
  92. {TAG_PRODUCT_NAME ,TEXT("PRODUCT_NAME")},
  93. {TAG_PRODUCT_VERSION ,TEXT("PRODUCT_VERSION")},
  94. {TAG_FILE_DESCRIPTION ,TEXT("FILE_DESCRIPTION")},
  95. {TAG_FILE_VERSION ,TEXT("FILE_VERSION")},
  96. {TAG_ORIGINAL_FILENAME ,TEXT("ORIGINAL_FILENAME")},
  97. {TAG_INTERNAL_NAME ,TEXT("INTERNAL_NAME")},
  98. {TAG_LEGAL_COPYRIGHT ,TEXT("LEGAL_COPYRIGHT")},
  99. {TAG_16BIT_DESCRIPTION ,TEXT("S16BIT_DESCRIPTION")},
  100. {TAG_APPHELP_DETAILS ,TEXT("PROBLEM_DETAILS")},
  101. {TAG_LINK_URL ,TEXT("LINK_URL")},
  102. {TAG_LINK_TEXT ,TEXT("LINK_TEXT")},
  103. {TAG_APPHELP_TITLE ,TEXT("APPHELP_TITLE")},
  104. {TAG_APPHELP_CONTACT ,TEXT("APPHELP_CONTACT")},
  105. {TAG_SXS_MANIFEST ,TEXT("SXS_MANIFEST")},
  106. {TAG_DATA_STRING ,TEXT("DATA_STRING")},
  107. {TAG_MSI_TRANSFORM_FILE ,TEXT("MSI_TRANSFORM_FILE")},
  108. {TAG_16BIT_MODULE_NAME ,TEXT("S16BIT_MODULE_NAME")},
  109. {TAG_LAYER_DISPLAYNAME ,TEXT("LAYER_DISPLAYNAME")},
  110. {TAG_COMPILER_VERSION ,TEXT("COMPILER_VERSION")},
  111. {TAG_SIZE ,TEXT("SIZE")},
  112. {TAG_OFFSET ,TEXT("OFFSET")},
  113. {TAG_CHECKSUM ,TEXT("CHECKSUM")},
  114. {TAG_SHIM_TAGID ,TEXT("SHIM_TAGID")},
  115. {TAG_PATCH_TAGID ,TEXT("PATCH_TAGID")},
  116. {TAG_LAYER_TAGID ,TEXT("LAYER_TAGID")},
  117. {TAG_FLAG_TAGID ,TEXT("FLAG_TAGID")},
  118. {TAG_MODULE_TYPE ,TEXT("MODULE_TYPE")},
  119. {TAG_VERDATEHI ,TEXT("VERFILEDATEHI")},
  120. {TAG_VERDATELO ,TEXT("VERFILEDATELO")},
  121. {TAG_VERFILEOS ,TEXT("VERFILEOS")},
  122. {TAG_VERFILETYPE ,TEXT("VERFILETYPE")},
  123. {TAG_PE_CHECKSUM ,TEXT("PE_CHECKSUM")},
  124. {TAG_LINKER_VERSION ,TEXT("LINKER_VERSION")},
  125. {TAG_LINK_DATE ,TEXT("LINK_DATE")},
  126. {TAG_UPTO_LINK_DATE ,TEXT("UPTO_LINK_DATE")},
  127. {TAG_OS_SERVICE_PACK ,TEXT("OS_SERVICE_PACK")},
  128. {TAG_VER_LANGUAGE ,TEXT("VER_LANGUAGE")},
  129. {TAG_PREVOSMAJORVER ,TEXT("PREVOSMAJORVERSION")},
  130. {TAG_PREVOSMINORVER ,TEXT("PREVOSMINORVERSION")},
  131. {TAG_PREVOSPLATFORMID ,TEXT("PREVOSPLATFORMID")},
  132. {TAG_PREVOSBUILDNO ,TEXT("PREVOSBUILDNO")},
  133. {TAG_PROBLEMSEVERITY ,TEXT("PROBLEM_SEVERITY")},
  134. {TAG_HTMLHELPID ,TEXT("HTMLHELPID")},
  135. {TAG_INDEX_FLAGS ,TEXT("INDEXFLAGS")},
  136. {TAG_LANGID ,TEXT("APPHELP_LANGID")},
  137. {TAG_ENGINE ,TEXT("ENGINE")},
  138. {TAG_FLAGS ,TEXT("FLAGS") },
  139. {TAG_DATA_VALUETYPE ,TEXT("VALUETYPE")},
  140. {TAG_DATA_DWORD ,TEXT("DATA_DWORD")},
  141. {TAG_MSI_TRANSFORM_TAGID,TEXT("MSI_TRANSFORM_TAGID")},
  142. {TAG_RUNTIME_PLATFORM, TEXT("RUNTIME_PLATFORM")},
  143. {TAG_OS_SKU, TEXT("OS_SKU")},
  144. {TAG_INCLUDE ,TEXT("INCLUDE")},
  145. {TAG_GENERAL ,TEXT("GENERAL")},
  146. {TAG_MATCH_LOGIC_NOT ,TEXT("MATCH_LOGIC_NOT")},
  147. {TAG_APPLY_ALL_SHIMS ,TEXT("APPLY_ALL_SHIMS")},
  148. {TAG_USE_SERVICE_PACK_FILES
  149. ,TEXT("USE_SERVICE_PACK_FILES")},
  150. {TAG_TIME ,TEXT("TIME")},
  151. {TAG_BIN_FILE_VERSION ,TEXT("BIN_FILE_VERSION")},
  152. {TAG_BIN_PRODUCT_VERSION,TEXT("BIN_PRODUCT_VERSION")},
  153. {TAG_MODTIME ,TEXT("MODTIME")},
  154. {TAG_FLAG_MASK_KERNEL ,TEXT("FLAG_MASK_KERNEL")},
  155. {TAG_FLAG_MASK_USER ,TEXT("FLAG_MASK_USER")},
  156. {TAG_FLAG_MASK_SHELL ,TEXT("FLAG_MASK_SHELL")},
  157. {TAG_FLAG_MASK_FUSION ,TEXT("FLAG_MASK_FUSION")},
  158. {TAG_UPTO_BIN_PRODUCT_VERSION, TEXT("UPTO_BIN_PRODUCT_VERSION")},
  159. {TAG_UPTO_BIN_FILE_VERSION, TEXT("UPTO_BIN_FILE_VERSION")},
  160. {TAG_DATA_QWORD ,TEXT("DATA_QWORD")},
  161. {TAG_FLAGS_NTVDM1 ,TEXT("FLAGS_NTVDM1")},
  162. {TAG_FLAGS_NTVDM2 ,TEXT("FLAGS_NTVDM2")},
  163. {TAG_FLAGS_NTVDM3 ,TEXT("FLAGS_NTVDM3")},
  164. {TAG_PATCH_BITS ,TEXT("PATCH_BITS")},
  165. {TAG_FILE_BITS ,TEXT("FILE_BITS")},
  166. {TAG_EXE_ID ,TEXT("EXE_ID(GUID)")},
  167. {TAG_DATA_BITS ,TEXT("DATA_BITS")},
  168. {TAG_MSI_PACKAGE_ID ,TEXT("MSI_PACKAGE_ID(GUID)")},
  169. {TAG_DATABASE_ID ,TEXT("DATABASE_ID(GUID)")},
  170. {TAG_MATCH_MODE ,TEXT("MATCH_MODE")},
  171. //
  172. // Internal types defined in shimdb.h
  173. //
  174. {TAG_STRINGTABLE ,TEXT("STRINGTABLE")},
  175. {TAG_INDEXES ,TEXT("INDEXES")},
  176. {TAG_INDEX ,TEXT("INDEX")},
  177. {TAG_INDEX_TAG ,TEXT("INDEX_TAG")},
  178. {TAG_INDEX_KEY ,TEXT("INDEX_KEY")},
  179. {TAG_INDEX_BITS ,TEXT("INDEX_BITS")},
  180. {TAG_STRINGTABLE_ITEM ,TEXT("STRTAB_ITEM")},
  181. {TAG_TAG ,TEXT("TAG")},
  182. {TAG_TAGID ,TEXT("TAGID")},
  183. {TAG_NULL ,TEXT("")} // always needs to be last item
  184. };
  185. static MOD_TYPE_STRINGS g_rgModTypeStrings[] = {
  186. {MT_UNKNOWN_MODULE, TEXT("NONE")},
  187. {MT_W16_MODULE, TEXT("WIN16")},
  188. {MT_W32_MODULE, TEXT("WIN32")},
  189. {MT_DOS_MODULE, TEXT("DOS")}
  190. };
  191. //
  192. // Version Strings for stringref attributes
  193. //
  194. typedef struct _VER_STRINGS {
  195. TAG tTag;
  196. LPTSTR szName;
  197. } VER_STRINGS;
  198. static VER_STRINGS g_rgVerStrings[] = {
  199. {TAG_PRODUCT_VERSION, TEXT("ProductVersion") },
  200. {TAG_FILE_DESCRIPTION, TEXT("FileDescription") },
  201. {TAG_COMPANY_NAME, TEXT("CompanyName") },
  202. {TAG_PRODUCT_NAME, TEXT("ProductName") },
  203. {TAG_FILE_VERSION, TEXT("FileVersion") },
  204. {TAG_ORIGINAL_FILENAME, TEXT("OriginalFilename") },
  205. {TAG_INTERNAL_NAME, TEXT("InternalName") },
  206. {TAG_LEGAL_COPYRIGHT, TEXT("LegalCopyright") }
  207. };
  208. //
  209. // Binary version tags (DWORDs and QWORDs)
  210. //
  211. //
  212. static TAG g_rgBinVerTags[] = {
  213. TAG_VERDATEHI,
  214. TAG_VERDATELO,
  215. TAG_VERFILEOS,
  216. TAG_VERFILETYPE,
  217. TAG_BIN_PRODUCT_VERSION,
  218. TAG_BIN_FILE_VERSION,
  219. TAG_UPTO_BIN_PRODUCT_VERSION,
  220. TAG_UPTO_BIN_FILE_VERSION
  221. };
  222. //
  223. // Binary header tags (retrieval requires opening a file).
  224. //
  225. static TAG g_rgHeaderTags[] = {
  226. TAG_MODULE_TYPE,
  227. TAG_PE_CHECKSUM,
  228. TAG_LINKER_VERSION,
  229. TAG_CHECKSUM,
  230. TAG_16BIT_DESCRIPTION,
  231. TAG_16BIT_MODULE_NAME,
  232. TAG_LINK_DATE,
  233. TAG_UPTO_LINK_DATE
  234. };
  235. //
  236. // Basic information tags (size).
  237. //
  238. TAG g_rgDirectoryTags[] = {
  239. TAG_SIZE,
  240. 0
  241. };
  242. //
  243. // Invalid tag token
  244. //
  245. static TCHAR s_szInvalidTag[] = _T("InvalidTag");
  246. #if defined(KERNEL_MODE) && defined(ALLOC_PRAGMA)
  247. #pragma alloc_text(PAGE, TagToIndex)
  248. #pragma alloc_text(PAGE, SdbTagToString)
  249. #pragma alloc_text(PAGE, SdbpModuleTypeToString)
  250. #pragma alloc_text(PAGE, SdbpSetAttribute)
  251. #pragma alloc_text(PAGE, SdbpQueryStringVersionInformation)
  252. #pragma alloc_text(PAGE, SdbpQueryBinVersionInformation)
  253. #pragma alloc_text(PAGE, SdbpGetVersionAttributesNT)
  254. #pragma alloc_text(PAGE, SdbpGetHeaderAttributes)
  255. #pragma alloc_text(PAGE, SdbpGetAttribute)
  256. #pragma alloc_text(PAGE, SdbpCheckAttribute)
  257. #pragma alloc_text(PAGE, FindFileInfo)
  258. #pragma alloc_text(PAGE, CreateFileInfo)
  259. #pragma alloc_text(PAGE, SdbFreeFileInfo)
  260. #pragma alloc_text(PAGE, SdbpCleanupAttributeMgr)
  261. #pragma alloc_text(PAGE, SdbpCheckAllAttributes)
  262. #pragma alloc_text(PAGE, SdbpQueryVersionString)
  263. #pragma alloc_text(PAGE, SdbpGetModuleType)
  264. #pragma alloc_text(PAGE, SdbpGetModulePECheckSum)
  265. #pragma alloc_text(PAGE, SdbpGetImageNTHeader)
  266. #pragma alloc_text(PAGE, SdbpGetFileChecksum)
  267. #pragma alloc_text(PAGE, SdbpCheckVersion)
  268. #pragma alloc_text(PAGE, SdbpCheckUptoVersion)
  269. #endif // KERNEL_MODE && ALLOC_PRAGMA
  270. int
  271. TagToIndex(
  272. IN TAG tag // the tag
  273. )
  274. /*++
  275. Return: The index in the attribute info array (g_rgAttributeTags).
  276. Desc: Self explanatory.
  277. --*/
  278. {
  279. int i;
  280. for (i = 0; i < ATTRIBUTE_COUNT; i++) {
  281. if (tag == g_rgAttributeTags[i]) {
  282. return i;
  283. }
  284. }
  285. DBGPRINT((sdlError, "TagToIndex", "Invalid attribute 0x%x.\n", tag));
  286. return -1;
  287. }
  288. LPCTSTR
  289. SdbTagToString(
  290. TAG tag
  291. )
  292. /*++
  293. Return: The pointer to the string name for the specified tag.
  294. Desc: Self explanatory.
  295. --*/
  296. {
  297. int i;
  298. for (i = 0; i < ARRAYSIZE(gaTagInfo); ++i) {
  299. if (gaTagInfo[i].tWhich == tag) {
  300. return gaTagInfo[i].szName;
  301. }
  302. }
  303. return s_szInvalidTag;
  304. }
  305. LPCTSTR
  306. SdbpModuleTypeToString(
  307. DWORD dwModuleType
  308. )
  309. {
  310. int i;
  311. for (i = 0; i < ARRAYSIZE(g_rgModTypeStrings); ++i) {
  312. if (g_rgModTypeStrings[i].dwModuleType == dwModuleType) {
  313. return g_rgModTypeStrings[i].szModuleType;
  314. }
  315. }
  316. //
  317. // The first element is the "UNKNOWN" type -- NONE
  318. //
  319. return g_rgModTypeStrings[0].szModuleType;
  320. }
  321. BOOL
  322. SdbpSetAttribute(
  323. OUT PFILEINFO pFileInfo, // pointer to the FILEINFO structure.
  324. IN TAG AttrID, // Attribute ID (tag, as in TAG_SIZE
  325. IN PVOID pValue // value
  326. )
  327. /*++
  328. Return: TRUE on success, FALSE otherwise.
  329. Desc: This function sets the value for the specified attribute.
  330. If pValue is NULL it means that the specified attribute is not
  331. available for the file.
  332. --*/
  333. {
  334. int nAttrInd;
  335. PATTRINFO pAttrInfo;
  336. nAttrInd = TagToIndex(AttrID);
  337. if (nAttrInd < 0) {
  338. DBGPRINT((sdlError, "SdbpSetAttribute", "Invalid attribute %d.\n", nAttrInd));
  339. return FALSE;
  340. }
  341. pAttrInfo = &pFileInfo->Attributes[nAttrInd];
  342. if (pValue == NULL) {
  343. //
  344. // No value. Mark and exit.
  345. //
  346. pAttrInfo->dwFlags = (pAttrInfo->dwFlags & ~ATTRIBUTE_AVAILABLE) |
  347. ATTRIBUTE_FAILED;
  348. return TRUE;
  349. }
  350. switch (GETTAGTYPE(AttrID)) {
  351. case TAG_TYPE_DWORD:
  352. pAttrInfo->dwAttr = *(DWORD*)pValue;
  353. break;
  354. case TAG_TYPE_QWORD:
  355. pAttrInfo->ullAttr = *(ULONGLONG*)pValue;
  356. break;
  357. case TAG_TYPE_STRINGREF:
  358. pAttrInfo->lpAttr = (LPTSTR)pValue;
  359. break;
  360. }
  361. pAttrInfo->tAttrID = AttrID;
  362. pAttrInfo->dwFlags |= ATTRIBUTE_AVAILABLE;
  363. return TRUE;
  364. }
  365. //
  366. // This is a guard against bad code in version.dll that stomps over the
  367. // buffer size for Unicode apis on 16-bit exes.
  368. //
  369. #define VERSIONINFO_BUFFER_PAD 16
  370. void
  371. SdbpQueryStringVersionInformation(
  372. IN PSDBCONTEXT pContext,
  373. IN PFILEINFO pFileInfo,
  374. OUT LPVOID pVersionInfo
  375. )
  376. /*++
  377. Return: void.
  378. Desc: Sets all the version string info available for the specified file.
  379. --*/
  380. {
  381. int i;
  382. LPTSTR szVerString;
  383. PLANGANDCODEPAGE pLangCodePage = NULL;
  384. UINT cbLangCP = 0;
  385. int nTranslations = 0;
  386. if (!pContext->pfnVerQueryValue(pVersionInfo,
  387. TEXT("\\VarFileInfo\\Translation"),
  388. (LPVOID)&pLangCodePage,
  389. &cbLangCP)) {
  390. DBGPRINT((sdlError,
  391. "SdbpQueryStringVersionInformation",
  392. "VerQueryValue failed for translation\n"));
  393. pLangCodePage = NULL;
  394. }
  395. nTranslations = cbLangCP / sizeof(*pLangCodePage);
  396. for (i = 0; i < ARRAYSIZE(g_rgVerStrings); ++i) {
  397. szVerString = SdbpQueryVersionString(pContext,
  398. pVersionInfo,
  399. pLangCodePage,
  400. nTranslations,
  401. g_rgVerStrings[i].szName);
  402. SdbpSetAttribute(pFileInfo, g_rgVerStrings[i].tTag, szVerString);
  403. }
  404. #ifndef KERNEL_MODE
  405. //
  406. // Set the attribute for Language
  407. //
  408. if (pLangCodePage != NULL && nTranslations == 1) {
  409. DWORD dwLanguage = (DWORD)pLangCodePage->wLanguage;
  410. SdbpSetAttribute(pFileInfo, TAG_VER_LANGUAGE, &dwLanguage);
  411. } else {
  412. SdbpSetAttribute(pFileInfo, TAG_VER_LANGUAGE, NULL);
  413. }
  414. #endif // KERNEL_MODE
  415. }
  416. VOID
  417. SdbpQueryBinVersionInformation(
  418. IN PSDBCONTEXT pContext,
  419. IN PFILEINFO pFileInfo,
  420. OUT VS_FIXEDFILEINFO* pFixedInfo
  421. )
  422. /*++
  423. Return: void.
  424. Desc: Sets all the version string info available for the specified file
  425. from the fixed size resources.
  426. --*/
  427. {
  428. LARGE_INTEGER liVerData;
  429. SdbpSetAttribute(pFileInfo, TAG_VERDATEHI, &pFixedInfo->dwFileDateMS);
  430. SdbpSetAttribute(pFileInfo, TAG_VERDATELO, &pFixedInfo->dwFileDateLS);
  431. SdbpSetAttribute(pFileInfo, TAG_VERFILEOS, &pFixedInfo->dwFileOS);
  432. SdbpSetAttribute(pFileInfo, TAG_VERFILETYPE, &pFixedInfo->dwFileType);
  433. liVerData.LowPart = pFixedInfo->dwProductVersionLS;
  434. liVerData.HighPart = pFixedInfo->dwProductVersionMS;
  435. SdbpSetAttribute(pFileInfo, TAG_BIN_PRODUCT_VERSION, &liVerData.QuadPart);
  436. SdbpSetAttribute(pFileInfo, TAG_UPTO_BIN_PRODUCT_VERSION, &liVerData.QuadPart);
  437. liVerData.LowPart = pFixedInfo->dwFileVersionLS;
  438. liVerData.HighPart = pFixedInfo->dwFileVersionMS;
  439. SdbpSetAttribute(pFileInfo, TAG_BIN_FILE_VERSION, &liVerData.QuadPart);
  440. SdbpSetAttribute(pFileInfo, TAG_UPTO_BIN_FILE_VERSION, &liVerData.QuadPart);
  441. UNREFERENCED_PARAMETER(pContext);
  442. }
  443. #if defined(NT_MODE) || defined(KERNEL_MODE)
  444. BOOL
  445. SdbpGetVersionAttributesNT(
  446. IN PSDBCONTEXT pContext,
  447. OUT PFILEINFO pFileInfo,
  448. IN PIMAGEFILEDATA pImageData
  449. )
  450. /*++
  451. Return: TRUE on success, FALSE otherwise.
  452. Desc: This function retrieves all of the Version-related attributes
  453. Imports apis from version.dll if called for the first time
  454. --*/
  455. {
  456. BOOL bSuccess;
  457. LPVOID pVersionInfo = NULL;
  458. VS_FIXEDFILEINFO* pFixedInfo = NULL;
  459. int i;
  460. //
  461. // First retrieve the version info.
  462. //
  463. bSuccess = SdbpGetFileVersionInformation(pImageData, &pVersionInfo, &pFixedInfo);
  464. if (!bSuccess) {
  465. DBGPRINT((sdlInfo, "SdbpGetVersionAttributesNT", "No version info.\n"));
  466. goto ErrHandle;
  467. }
  468. //
  469. // Version information available.
  470. //
  471. //
  472. // Set the pointer to our internal function.
  473. //
  474. pContext->pfnVerQueryValue = SdbpVerQueryValue;
  475. for (i = 0; i < ARRAYSIZE(g_rgVerStrings); ++i) {
  476. SdbpSetAttribute(pFileInfo, g_rgVerStrings[i].tTag, NULL);
  477. }
  478. SdbpSetAttribute(pFileInfo, TAG_VER_LANGUAGE, NULL);
  479. //
  480. // Query binary stuff
  481. //
  482. SdbpQueryBinVersionInformation(pContext, pFileInfo, pFixedInfo);
  483. pFileInfo->pVersionInfo = pVersionInfo;
  484. return TRUE;
  485. ErrHandle:
  486. //
  487. // Reset all the string info.
  488. //
  489. for (i = 0; i < ARRAYSIZE(g_rgBinVerTags); ++i) {
  490. SdbpSetAttribute(pFileInfo, g_rgBinVerTags[i], NULL);
  491. }
  492. for (i = 0; i < ARRAYSIZE(g_rgVerStrings); ++i) {
  493. SdbpSetAttribute(pFileInfo, g_rgVerStrings[i].tTag, NULL);
  494. }
  495. return FALSE;
  496. }
  497. #endif // NT_MODE || KERNEL_MODE
  498. BOOL
  499. SdbpGetHeaderAttributes(
  500. IN PSDBCONTEXT pContext,
  501. OUT PFILEINFO pFileInfo
  502. )
  503. /*++
  504. Return: TRUE on success, FALSE otherwise.
  505. Desc: This function retrieves the header attributes for the
  506. specified file.
  507. --*/
  508. {
  509. IMAGEFILEDATA ImageData;
  510. ULONG ulPEChecksum = 0;
  511. ULONG ulChecksum = 0;
  512. DWORD dwModuleType = 0;
  513. DWORD dwLinkerVer;
  514. DWORD dwLinkDate;
  515. BOOL bSuccess;
  516. int i;
  517. ImageData.dwFlags = 0;
  518. if (pFileInfo->hFile != INVALID_HANDLE_VALUE) {
  519. ImageData.hFile = pFileInfo->hFile;
  520. ImageData.dwFlags |= IMAGEFILEDATA_HANDLEVALID;
  521. }
  522. if (pFileInfo->pImageBase != NULL) {
  523. ImageData.pBase = pFileInfo->pImageBase;
  524. ImageData.ViewSize = (SIZE_T) pFileInfo->dwImageSize;
  525. ImageData.FileSize = (ULONGLONG)pFileInfo->dwImageSize;
  526. ImageData.dwFlags |= IMAGEFILEDATA_PBASEVALID;
  527. }
  528. //
  529. // SdbpOpenAndMapFile uses DOS_PATH type as an argument
  530. // In kernel mode this parameter is ignored.
  531. //
  532. if (SdbpOpenAndMapFile(pFileInfo->FilePath, &ImageData, DOS_PATH)) {
  533. bSuccess = SdbpGetModuleType(&dwModuleType, &ImageData);
  534. SdbpSetAttribute(pFileInfo, TAG_MODULE_TYPE, bSuccess ? (PVOID)&dwModuleType : NULL);
  535. bSuccess = SdbpGetModulePECheckSum(&ulPEChecksum, &dwLinkerVer, &dwLinkDate, &ImageData);
  536. SdbpSetAttribute(pFileInfo, TAG_PE_CHECKSUM, bSuccess ? (PVOID)&ulPEChecksum : NULL);
  537. SdbpSetAttribute(pFileInfo, TAG_LINKER_VERSION, bSuccess ? (PVOID)&dwLinkerVer : NULL);
  538. SdbpSetAttribute(pFileInfo, TAG_LINK_DATE, bSuccess ? (PVOID)&dwLinkDate : NULL);
  539. SdbpSetAttribute(pFileInfo, TAG_UPTO_LINK_DATE, bSuccess ? (PVOID)&dwLinkDate : NULL);
  540. bSuccess = SdbpGetFileChecksum(&ulChecksum, &ImageData);
  541. SdbpSetAttribute(pFileInfo, TAG_CHECKSUM, bSuccess ? (PVOID)&ulChecksum : NULL);
  542. #ifndef KERNEL_MODE
  543. //
  544. // Now retrieve 16-bit description string, it's max size is 256 bytes.
  545. //
  546. // This attribute is not available in kernel mode.
  547. //
  548. bSuccess = SdbpGet16BitDescription(&pFileInfo->pDescription16, &ImageData);
  549. SdbpSetAttribute(pFileInfo, TAG_16BIT_DESCRIPTION, pFileInfo->pDescription16);
  550. bSuccess = SdbpGet16BitModuleName(&pFileInfo->pModuleName16, &ImageData);
  551. SdbpSetAttribute(pFileInfo, TAG_16BIT_MODULE_NAME, pFileInfo->pModuleName16);
  552. #if defined(NT_MODE)
  553. //
  554. // Hit this case only on current platform
  555. //
  556. if (pFileInfo->hFile != INVALID_HANDLE_VALUE || pFileInfo->pImageBase != NULL) {
  557. SdbpGetVersionAttributesNT(pContext, pFileInfo, &ImageData);
  558. }
  559. #endif // NT_MODE
  560. #else // KERNEL_MODE
  561. //
  562. // When we are running in kernel mode retrieve version-related
  563. // data now as well.
  564. //
  565. SdbpGetVersionAttributesNT(pContext, pFileInfo, &ImageData);
  566. //
  567. // Retrieve file directory attributes.
  568. //
  569. SdbpGetFileDirectoryAttributesNT(pFileInfo, &ImageData);
  570. #endif // KERNEL_MODE
  571. SdbpUnmapAndCloseFile(&ImageData);
  572. return TRUE;
  573. }
  574. for (i = 0; i < ARRAYSIZE(g_rgHeaderTags); ++i) {
  575. SdbpSetAttribute(pFileInfo, g_rgHeaderTags[i], NULL);
  576. }
  577. #ifdef KERNEL_MODE
  578. //
  579. // Reset all the version attributes here as well.
  580. //
  581. for (i = 0; i < ARRAYSIZE(g_rgBinVerTags); ++i) {
  582. SdbpSetAttribute(pFileInfo, g_rgBinVerTags[i], NULL);
  583. }
  584. for (i = 0; i < ARRAYSIZE(g_rgVerStrings); ++i) {
  585. SdbpSetAttribute(pFileInfo, g_rgVerStrings[i].tTag, NULL);
  586. }
  587. #endif // KERNEL_MODE
  588. return FALSE;
  589. UNREFERENCED_PARAMETER(pContext);
  590. }
  591. BOOL
  592. SdbpGetAttribute(
  593. IN PSDBCONTEXT pContext,
  594. OUT PFILEINFO pFileInfo,
  595. IN TAG AttrID
  596. )
  597. /*++
  598. Return: TRUE on success, FALSE otherwise.
  599. Desc: Retrieve an attribute for a given file. We retrieve all the
  600. attributes of the same class.
  601. --*/
  602. {
  603. BOOL bReturn = FALSE;
  604. switch (AttrID) {
  605. //
  606. // The tags below require checking the file and making a directory query.
  607. //
  608. case TAG_SIZE:
  609. #ifndef KERNEL_MODE // in kernel mode we fall through to header attributes
  610. bReturn = SdbpGetFileDirectoryAttributes(pFileInfo);
  611. break;
  612. #endif // KERNEL_MODE
  613. //
  614. // The tags below require retrieving version resources.
  615. //
  616. case TAG_VERDATEHI:
  617. case TAG_VERDATELO:
  618. case TAG_VERFILEOS:
  619. case TAG_VERFILETYPE:
  620. case TAG_UPTO_BIN_PRODUCT_VERSION:
  621. case TAG_UPTO_BIN_FILE_VERSION:
  622. case TAG_BIN_FILE_VERSION:
  623. case TAG_BIN_PRODUCT_VERSION:
  624. case TAG_PRODUCT_VERSION:
  625. case TAG_FILE_DESCRIPTION:
  626. case TAG_COMPANY_NAME:
  627. case TAG_PRODUCT_NAME:
  628. case TAG_FILE_VERSION:
  629. case TAG_ORIGINAL_FILENAME:
  630. case TAG_INTERNAL_NAME:
  631. case TAG_LEGAL_COPYRIGHT:
  632. case TAG_VER_LANGUAGE:
  633. //
  634. // In KERNEL_MODE we fall through and do the attributes using the
  635. // header attributes.
  636. //
  637. #ifndef KERNEL_MODE
  638. //
  639. // Version attributes are retrieved through the header attributes if
  640. // caller provided a handle/image base
  641. //
  642. if (pFileInfo->hFile == INVALID_HANDLE_VALUE && pFileInfo->pImageBase == NULL) {
  643. bReturn = SdbpGetVersionAttributes(pContext, pFileInfo);
  644. break;
  645. }
  646. #endif // KERNEL_MODE
  647. //
  648. // The tags below require opening a file and mapping it into memory.
  649. //
  650. case TAG_CHECKSUM:
  651. case TAG_PE_CHECKSUM:
  652. case TAG_LINKER_VERSION:
  653. case TAG_16BIT_DESCRIPTION:
  654. case TAG_16BIT_MODULE_NAME:
  655. case TAG_MODULE_TYPE:
  656. case TAG_UPTO_LINK_DATE:
  657. case TAG_LINK_DATE:
  658. bReturn = SdbpGetHeaderAttributes(pContext, pFileInfo);
  659. break;
  660. }
  661. return bReturn;
  662. }
  663. BOOL
  664. SdbpCheckAttribute(
  665. IN PSDBCONTEXT pContext, // Database Context pointer
  666. IN PVOID pFileData, // pointer returned from CheckFile
  667. IN TAG AttrID, // Attribute ID
  668. IN PVOID pAttribute // attribute value ptr (see above for description)
  669. )
  670. /*++
  671. Return: TRUE if the value for given attribute matches
  672. the file's attribute, FALSE otherwise.
  673. Desc: Check an attribute against a given value. This function
  674. retrieves attributes as necessary.
  675. --*/
  676. {
  677. int nAttrIndex;
  678. PATTRINFO pAttrInfo;
  679. BOOL bReturn = FALSE;
  680. PFILEINFO pFileInfo = (PFILEINFO)pFileData;
  681. if (pAttribute == NULL) {
  682. DBGPRINT((sdlError, "SdbpCheckAttribute", "Invalid parameter.\n"));
  683. return FALSE;
  684. }
  685. nAttrIndex = TagToIndex(AttrID);
  686. if (nAttrIndex < 0) {
  687. DBGPRINT((sdlError, "SdbpCheckAttribute", "Bad Attribute ID 0x%x\n", AttrID));
  688. return FALSE;
  689. }
  690. //
  691. // Now see if this attribute is any good.
  692. //
  693. pAttrInfo = &pFileInfo->Attributes[nAttrIndex];
  694. if (!(pAttrInfo->dwFlags & ATTRIBUTE_AVAILABLE)) {
  695. //
  696. // See if we have tried already
  697. //
  698. if (pAttrInfo->dwFlags & ATTRIBUTE_FAILED) {
  699. DBGPRINT((sdlInfo,
  700. "SdbpCheckAttribute",
  701. "Already tried to get attr ID 0x%x.\n",
  702. AttrID));
  703. return FALSE;
  704. }
  705. //
  706. // The attribute has not been retrieved yet, do it now then.
  707. //
  708. // Try to obtain this attribute from the file.
  709. //
  710. if (!SdbpGetAttribute(pContext, pFileInfo, AttrID)) {
  711. DBGPRINT((sdlWarning,
  712. "SdbpCheckAttribute",
  713. "Failed to get attribute \"%s\" for \"%s\"\n",
  714. SdbTagToString(AttrID),
  715. pFileInfo->FilePath));
  716. //
  717. // ATTRIBUTE_FAILED is set by the SdbpGetAttribute
  718. //
  719. return FALSE;
  720. }
  721. }
  722. //
  723. // Check again here in case we had to retrieve the attribute.
  724. //
  725. if (!(pAttrInfo->dwFlags & ATTRIBUTE_AVAILABLE)) {
  726. return FALSE;
  727. }
  728. switch (AttrID) {
  729. case TAG_BIN_PRODUCT_VERSION:
  730. case TAG_BIN_FILE_VERSION:
  731. bReturn = SdbpCheckVersion(*(ULONGLONG*)pAttribute, pAttrInfo->ullAttr);
  732. if (!bReturn) {
  733. #ifdef _DEBUG_SPEW
  734. ULONGLONG qwDBFileVer = *(ULONGLONG*)pAttribute;
  735. ULONGLONG qwBinFileVer = pAttrInfo->ullAttr;
  736. DBGPRINT((sdlInfo,
  737. "SdbpCheckAttribute",
  738. "\"%s\" mismatch file: \"%s\". Expected %d.%d.%d.%d, Found %d.%d.%d.%d\n",
  739. SdbTagToString(AttrID),
  740. pFileInfo->FilePath,
  741. (WORD)(qwDBFileVer >> 48),
  742. (WORD)(qwDBFileVer >> 32),
  743. (WORD)(qwDBFileVer >> 16),
  744. (WORD)(qwDBFileVer),
  745. (WORD)(qwBinFileVer >> 48),
  746. (WORD)(qwBinFileVer >> 32),
  747. (WORD)(qwBinFileVer >> 16),
  748. (WORD)(qwBinFileVer)));
  749. #endif
  750. }
  751. break;
  752. case TAG_UPTO_BIN_PRODUCT_VERSION:
  753. case TAG_UPTO_BIN_FILE_VERSION:
  754. bReturn = SdbpCheckUptoVersion(*(ULONGLONG*)pAttribute, pAttrInfo->ullAttr);
  755. if (!bReturn) {
  756. #ifdef _DEBUG_SPEW
  757. ULONGLONG qwDBFileVer = *(ULONGLONG*)pAttribute;
  758. ULONGLONG qwBinFileVer = pAttrInfo->ullAttr;
  759. DBGPRINT((sdlInfo,
  760. "SdbpCheckAttribute",
  761. "\"%s\" mismatch file: \"%s\". Expected %d.%d.%d.%d, Found %d.%d.%d.%d\n",
  762. SdbTagToString(AttrID),
  763. pFileInfo->FilePath,
  764. (WORD)(qwDBFileVer >> 48),
  765. (WORD)(qwDBFileVer >> 32),
  766. (WORD)(qwDBFileVer >> 16),
  767. (WORD)(qwDBFileVer),
  768. (WORD)(qwBinFileVer >> 48),
  769. (WORD)(qwBinFileVer >> 32),
  770. (WORD)(qwBinFileVer >> 16),
  771. (WORD)(qwBinFileVer)));
  772. #endif
  773. }
  774. break;
  775. case TAG_UPTO_LINK_DATE:
  776. bReturn = (*(DWORD*)pAttribute >= pAttrInfo->dwAttr);
  777. if (!bReturn) {
  778. DBGPRINT((sdlInfo,
  779. "SdbpCheckAttribute",
  780. "\"%s\" mismatch file \"%s\". Expected less than 0x%x Found 0x%x\n",
  781. SdbTagToString(AttrID),
  782. pFileInfo->FilePath,
  783. *(DWORD*)pAttribute,
  784. pAttrInfo->dwAttr));
  785. }
  786. break;
  787. default:
  788. switch (GETTAGTYPE(AttrID)) {
  789. case TAG_TYPE_DWORD:
  790. //
  791. // This is likely to be hit first.
  792. //
  793. bReturn = (*(DWORD*)pAttribute == pAttrInfo->dwAttr);
  794. if (!bReturn) {
  795. DBGPRINT((sdlInfo,
  796. "SdbpCheckAttribute",
  797. "\"%s\" mismatch file \"%s\". Expected 0x%x Found 0x%x\n",
  798. SdbTagToString(AttrID),
  799. pFileInfo->FilePath,
  800. *(DWORD*)pAttribute,
  801. pAttrInfo->dwAttr));
  802. }
  803. break;
  804. case TAG_TYPE_STRINGREF:
  805. bReturn = SdbpPatternMatch((LPCTSTR)pAttribute, (LPCTSTR)pAttrInfo->lpAttr);
  806. if (!bReturn) {
  807. DBGPRINT((sdlInfo,
  808. "SdbpCheckAttribute",
  809. "\"%s\" mismatch file \"%s\". Expected \"%s\" Found \"%s\"\n",
  810. SdbTagToString(AttrID),
  811. pFileInfo->FilePath,
  812. pAttribute,
  813. pAttrInfo->lpAttr));
  814. }
  815. break;
  816. case TAG_TYPE_QWORD:
  817. bReturn = (*(ULONGLONG*)pAttribute == pAttrInfo->ullAttr);
  818. if (!bReturn) {
  819. DBGPRINT((sdlInfo,
  820. "SdbpCheckAttribute",
  821. "\"%s\" mismatch file \"%s\". Expected 0x%I64x Found 0x%I64x\n",
  822. SdbTagToString(AttrID),
  823. pFileInfo->FilePath,
  824. *(ULONGLONG*)pAttribute,
  825. pAttrInfo->ullAttr));
  826. }
  827. break;
  828. }
  829. break;
  830. }
  831. return bReturn;
  832. }
  833. PFILEINFO
  834. FindFileInfo(
  835. IN PSDBCONTEXT pContext,
  836. IN LPCTSTR FilePath
  837. )
  838. /*++
  839. Return: A pointer to the cached FILEINFO structure if one is found
  840. or NULL otherwise.
  841. Desc: This function performs a search in the file cache to determine whether
  842. a given file has already been touched.
  843. --*/
  844. {
  845. PFILEINFO pFileInfo = (PFILEINFO)pContext->pFileAttributeCache; // global cache
  846. while (pFileInfo != NULL) {
  847. if (ISEQUALSTRING(pFileInfo->FilePath, FilePath)) {
  848. DBGPRINT((sdlInfo,
  849. "FindFileInfo",
  850. "FILEINFO for \"%s\" found in the cache.\n",
  851. FilePath));
  852. return pFileInfo;
  853. }
  854. pFileInfo = pFileInfo->pNext;
  855. }
  856. return NULL;
  857. }
  858. PFILEINFO
  859. CreateFileInfo(
  860. IN PSDBCONTEXT pContext,
  861. IN LPCTSTR FullPath,
  862. IN DWORD dwLength OPTIONAL, // length (in characters) of FullPath string
  863. IN HANDLE hFile OPTIONAL, // file handle
  864. IN LPVOID pImageBase OPTIONAL,
  865. IN DWORD dwImageSize OPTIONAL,
  866. IN BOOL bNoCache
  867. )
  868. /*++
  869. Return: A pointer to the allocated FILEINFO structure.
  870. Desc: Allocates the FILEINFO structure for the specified file.
  871. --*/
  872. {
  873. PFILEINFO pFileInfo;
  874. SIZE_T sizeBase;
  875. SIZE_T size;
  876. DWORD nPathLen;
  877. nPathLen = dwLength ? dwLength : (DWORD)_tcslen(FullPath);
  878. sizeBase = sizeof(*pFileInfo) + (ATTRIBUTE_COUNT - 1) * sizeof(ATTRINFO);
  879. size = sizeBase + (nPathLen + 1) * sizeof(*FullPath);
  880. pFileInfo = (PFILEINFO)SdbAlloc(size);
  881. if (pFileInfo == NULL) {
  882. DBGPRINT((sdlError,
  883. "CreateFileInfo",
  884. "Failed to allocate %d bytes for FILEINFO structure.\n",
  885. size));
  886. return NULL;
  887. }
  888. RtlZeroMemory(pFileInfo, size);
  889. pFileInfo->FilePath = (LPTSTR)((PBYTE)pFileInfo + sizeBase);
  890. RtlCopyMemory(pFileInfo->FilePath, FullPath, nPathLen * sizeof(*FullPath));
  891. pFileInfo->FilePath[nPathLen] = TEXT('\0');
  892. pFileInfo->hFile = hFile;
  893. pFileInfo->pImageBase = pImageBase;
  894. pFileInfo->dwImageSize = dwImageSize;
  895. //
  896. // Now link it in if we use the cache.
  897. //
  898. if (!bNoCache) {
  899. pFileInfo->pNext = (PFILEINFO)pContext->pFileAttributeCache;
  900. pContext->pFileAttributeCache = (PVOID)pFileInfo;
  901. }
  902. return pFileInfo;
  903. }
  904. void
  905. SdbFreeFileInfo(
  906. IN PVOID pFileData // pointer returned from SdbpGetFileAttributes
  907. )
  908. /*++
  909. Return: void.
  910. Desc: Self explanatory. Use this only after calling GetFileInfo
  911. with bNoCache set to TRUE.
  912. --*/
  913. {
  914. PFILEINFO pFileInfo = (PFILEINFO)pFileData;
  915. if (pFileInfo == NULL) {
  916. DBGPRINT((sdlError, "SdbFreeFileInfo", "Invalid parameter.\n"));
  917. return;
  918. }
  919. if (pFileInfo->pVersionInfo != NULL) {
  920. SdbFree(pFileInfo->pVersionInfo);
  921. }
  922. if (pFileInfo->pDescription16 != NULL) {
  923. SdbFree(pFileInfo->pDescription16);
  924. }
  925. if (pFileInfo->pModuleName16 != NULL) {
  926. SdbFree(pFileInfo->pModuleName16);
  927. }
  928. SdbFree(pFileInfo);
  929. }
  930. void
  931. SdbpCleanupAttributeMgr(
  932. IN PSDBCONTEXT pContext // database context
  933. )
  934. /*++
  935. Return: void.
  936. Desc: This function should be called afer we are done checking a given exe
  937. it performs cleanup tasks, such as:
  938. . unload dynamically linked dll (version.dll)
  939. . cleanup file cache
  940. --*/
  941. {
  942. PFILEINFO pFileInfo = (PFILEINFO)pContext->pFileAttributeCache;
  943. PFILEINFO pNext;
  944. while (pFileInfo != NULL) {
  945. pNext = pFileInfo->pNext;
  946. SdbFreeFileInfo(pFileInfo);
  947. pFileInfo = pNext;
  948. }
  949. //
  950. // Reset the cache pointer.
  951. //
  952. pContext->pFileAttributeCache = NULL;
  953. }
  954. BOOL
  955. SdbpCheckAllAttributes(
  956. IN PSDBCONTEXT pContext, // pointer to the database channel
  957. IN PDB pdb, // pointer to the Shim Database that we're checking against
  958. IN TAGID tiMatch, // TAGID for a given file(exe) to be checked
  959. IN PVOID pFileData // pointer returned from CheckFile
  960. )
  961. /*++
  962. Return: TRUE if all the file's attributes match the ones described in the
  963. database for this file, FALSE otherwise.
  964. Desc: TBD
  965. --*/
  966. {
  967. int i;
  968. TAG tAttrID;
  969. PVOID pAttribute;
  970. TAGID tiTemp;
  971. DWORD dwAttribute;
  972. ULONGLONG ullAttribute;
  973. BOOL bReturn = TRUE; // match by default
  974. assert(tiMatch != TAGID_NULL);
  975. if (pFileData == NULL) {
  976. //
  977. // No file was passed in. This can happen if LOGIC="NOT" is used.
  978. //
  979. return FALSE;
  980. }
  981. for (i = 0; i < ATTRIBUTE_COUNT && bReturn; ++i) {
  982. tAttrID = g_rgAttributeTags[i];
  983. tiTemp = SdbFindFirstTag(pdb, tiMatch, tAttrID);
  984. if (tiTemp != TAGID_NULL) {
  985. pAttribute = NULL;
  986. switch (GETTAGTYPE(tAttrID)) {
  987. case TAG_TYPE_DWORD:
  988. dwAttribute = SdbReadDWORDTag(pdb, tiTemp, 0);
  989. pAttribute = &dwAttribute;
  990. break;
  991. case TAG_TYPE_QWORD:
  992. ullAttribute = SdbReadQWORDTag(pdb, tiTemp, 0);
  993. pAttribute = &ullAttribute;
  994. break;
  995. case TAG_TYPE_STRINGREF:
  996. pAttribute = SdbGetStringTagPtr(pdb, tiTemp);
  997. break;
  998. }
  999. //
  1000. // Now check the attribute.
  1001. //
  1002. bReturn = SdbpCheckAttribute(pContext, pFileData, tAttrID, pAttribute);
  1003. //
  1004. // we bail out if !bReturn via the condition in FOR loop above
  1005. //
  1006. }
  1007. }
  1008. return bReturn;
  1009. }
  1010. //
  1011. // VERSION DATA
  1012. //
  1013. /*--
  1014. Search order is:
  1015. - Language neutral, Unicode (0x000004B0)
  1016. - Language neutral, Windows-multilingual (0x000004e4)
  1017. - US English, Unicode (0x040904B0)
  1018. - US English, Windows-multilingual (0x040904E4)
  1019. If none of those exist, it's not likely we're going to get good
  1020. matching info from what does exist.
  1021. --*/
  1022. LPTSTR
  1023. SdbpQueryVersionString(
  1024. IN PSDBCONTEXT pContext, // the database channel
  1025. IN PVOID pVersionData, // Version data buffer
  1026. IN PLANGANDCODEPAGE pTranslations,
  1027. IN DWORD TranslationCount,
  1028. IN LPCTSTR szString // String to search for; see VerQueryValue in MSDN
  1029. )
  1030. /*++
  1031. Return: The pointer to the string if found, NULL if not.
  1032. Desc: Gets a pointer to a particular string in the StringFileInfo section
  1033. of a version resource.
  1034. Lookup is performed for known english-language resources followed up
  1035. by a lookup in the available translations section (if such was found)
  1036. --*/
  1037. {
  1038. TCHAR szTemp[128];
  1039. LPTSTR szReturn = NULL;
  1040. int i;
  1041. static DWORD adwLangs[] = {0x000004B0, 0x000004E4, 0x040904B0, 0x040904E4};
  1042. assert(pVersionData && szString);
  1043. for (i = 0; i < ARRAYSIZE(adwLangs); ++i) {
  1044. UINT unLen;
  1045. StringCchPrintf(szTemp,
  1046. CHARCOUNT(szTemp),
  1047. _T("\\StringFileInfo\\%08X\\%s"),
  1048. adwLangs[i],
  1049. szString);
  1050. if (pContext->pfnVerQueryValue(pVersionData, szTemp, (PVOID*)&szReturn, &unLen)) {
  1051. return szReturn;
  1052. }
  1053. }
  1054. if (pTranslations != NULL) {
  1055. for (i = 0; i < (int)TranslationCount; ++i, ++pTranslations) {
  1056. UINT unLen;
  1057. StringCchPrintf(szTemp,
  1058. CHARCOUNT(szTemp),
  1059. _T("\\StringFileInfo\\%04X%04X\\%s"),
  1060. (DWORD)pTranslations->wLanguage,
  1061. (DWORD)pTranslations->wCodePage,
  1062. szString);
  1063. if (pContext->pfnVerQueryValue(pVersionData, szTemp, (PVOID*)&szReturn, &unLen)) {
  1064. return szReturn;
  1065. }
  1066. }
  1067. }
  1068. return NULL; // none found
  1069. }
  1070. BOOL
  1071. SdbpGetModuleType(
  1072. OUT LPDWORD lpdwModuleType,
  1073. IN PIMAGEFILEDATA pImageData
  1074. )
  1075. /*++
  1076. Return: TRUE on success, FALSE otherwise.
  1077. Desc: Gets a pointer to a particular string in the StringFileInfo section
  1078. of a version resource.
  1079. --*/
  1080. {
  1081. PIMAGE_DOS_HEADER pDosHeader;
  1082. DWORD dwModuleType = MT_UNKNOWN_MODULE;
  1083. LPBYTE lpSignature;
  1084. DWORD OffsetNew;
  1085. pDosHeader = (PIMAGE_DOS_HEADER)pImageData->pBase;
  1086. if (pDosHeader == NULL || pDosHeader == (PIMAGE_DOS_HEADER)-1) {
  1087. return FALSE;
  1088. }
  1089. //
  1090. // Check size and read signature.
  1091. //
  1092. if (pImageData->ViewSize < sizeof(*pDosHeader) || pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  1093. return FALSE;
  1094. }
  1095. //
  1096. // Assume DOS module.
  1097. //
  1098. dwModuleType = MT_DOS_MODULE;
  1099. OffsetNew = (DWORD)pDosHeader->e_lfanew;
  1100. //
  1101. // New header signature. Check offset.
  1102. //
  1103. if (pImageData->ViewSize < OffsetNew + sizeof(DWORD)) {
  1104. return FALSE;
  1105. }
  1106. lpSignature = ((LPBYTE)pImageData->pBase + OffsetNew);
  1107. if (IMAGE_NT_SIGNATURE == *(LPDWORD)lpSignature) {
  1108. dwModuleType = MT_W32_MODULE;
  1109. } else if (IMAGE_OS2_SIGNATURE == *(PWORD)lpSignature) {
  1110. dwModuleType = MT_W16_MODULE;
  1111. }
  1112. if (lpdwModuleType != NULL) {
  1113. *lpdwModuleType = dwModuleType;
  1114. }
  1115. return TRUE;
  1116. }
  1117. BOOL
  1118. SdbpGetImageNTHeader(
  1119. OUT PIMAGE_NT_HEADERS* ppHeader,
  1120. IN PIMAGEFILEDATA pImageData
  1121. )
  1122. /*++
  1123. Return: TRUE on success, FALSE otherwise.
  1124. Desc: Gets a pointer to the IMAGE_NT_HEADERS.
  1125. --*/
  1126. {
  1127. PIMAGE_DOS_HEADER pDosHeader;
  1128. PIMAGE_NT_HEADERS pNtHeaders = NULL;
  1129. DWORD ModuleType;
  1130. if (!SdbpGetModuleType(&ModuleType, pImageData)) {
  1131. return FALSE;
  1132. }
  1133. if (ModuleType != MT_W32_MODULE) {
  1134. return FALSE;
  1135. }
  1136. //
  1137. // Header is valid.
  1138. //
  1139. pDosHeader = (PIMAGE_DOS_HEADER)pImageData->pBase;
  1140. pNtHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImageData->pBase + pDosHeader->e_lfanew);
  1141. if (pImageData->ViewSize >= pDosHeader->e_lfanew + sizeof(*pNtHeaders)) { // not too short?
  1142. *ppHeader = pNtHeaders;
  1143. return TRUE;
  1144. }
  1145. return FALSE;
  1146. }
  1147. BOOL
  1148. SdbpGetModulePECheckSum(
  1149. OUT PULONG pChecksum,
  1150. OUT LPDWORD pdwLinkerVersion,
  1151. OUT LPDWORD pdwLinkDate,
  1152. IN PIMAGEFILEDATA pImageData
  1153. )
  1154. /*++
  1155. Return: TRUE on success, FALSE otherwise.
  1156. Desc: Gets the checksum from the PE headers.
  1157. --*/
  1158. {
  1159. PIMAGE_NT_HEADERS pNtHeader;
  1160. PIMAGE_DOS_HEADER pDosHeader;
  1161. ULONG ulChecksum = 0;
  1162. if (!SdbpGetImageNTHeader(&pNtHeader, pImageData)) {
  1163. DBGPRINT((sdlError, "SdbpGetModulePECheckSum", "Failed to get Image NT header.\n"));
  1164. return FALSE;
  1165. }
  1166. pDosHeader = (PIMAGE_DOS_HEADER)pImageData->pBase;
  1167. //
  1168. // Fill in the linker version (as it used to calculated in ntuser).
  1169. //
  1170. *pdwLinkerVersion = (pNtHeader->OptionalHeader.MinorImageVersion & 0xFF) +
  1171. ((pNtHeader->OptionalHeader.MajorImageVersion & 0xFF) << 16);
  1172. *pdwLinkDate = pNtHeader->FileHeader.TimeDateStamp;
  1173. switch (pNtHeader->OptionalHeader.Magic) {
  1174. case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  1175. if (pImageData->ViewSize >= pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32)) {
  1176. ulChecksum = ((PIMAGE_NT_HEADERS32)pNtHeader)->OptionalHeader.CheckSum;
  1177. *pChecksum = ulChecksum;
  1178. return TRUE;
  1179. }
  1180. break;
  1181. case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  1182. //
  1183. // Do an additional check.
  1184. //
  1185. if (pImageData->ViewSize >= pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64)) {
  1186. ulChecksum = ((PIMAGE_NT_HEADERS64)pNtHeader)->OptionalHeader.CheckSum;
  1187. *pChecksum = ulChecksum;
  1188. return TRUE;
  1189. }
  1190. break;
  1191. default:
  1192. //
  1193. // Unknown image type ?
  1194. //
  1195. DBGPRINT((sdlError,
  1196. "SdbpGetModulePECheckSum",
  1197. "Bad image type 0x%x\n",
  1198. pNtHeader->OptionalHeader.Magic));
  1199. *pChecksum = 0;
  1200. break;
  1201. }
  1202. return FALSE;
  1203. }
  1204. #define CHECKSUM_SIZE 4096
  1205. #define CHECKSUM_START 512
  1206. BOOL
  1207. SdbpGetFileChecksum(
  1208. OUT PULONG pChecksum,
  1209. IN PIMAGEFILEDATA pImageData
  1210. )
  1211. /*++
  1212. Return: TRUE on success, FALSE otherwise.
  1213. Desc: Calculates a checksum for the file.
  1214. --*/
  1215. {
  1216. ULONG size = CHECKSUM_SIZE;
  1217. ULONG StartAddress = CHECKSUM_START;
  1218. ULONG ulChecksum = 0;
  1219. LPDWORD lpdw;
  1220. int i;
  1221. if ((SIZE_T)pImageData->FileSize < (SIZE_T)size) {
  1222. StartAddress = 0;
  1223. size = (ULONG)pImageData->FileSize; // this is safe (size is rather small)
  1224. } else if ((SIZE_T)(size + StartAddress) > (SIZE_T)pImageData->FileSize) {
  1225. //
  1226. // The cast here is safe (FileSize is small)
  1227. //
  1228. StartAddress = (ULONG)(pImageData->FileSize - size);
  1229. }
  1230. if (size >= sizeof(DWORD)) {
  1231. ULONG ulCarry;
  1232. lpdw = (LPDWORD)((LPBYTE)pImageData->pBase + StartAddress);
  1233. for (i = 0; i < (INT)(size/sizeof(DWORD)); ++i) {
  1234. if (PtrToUlong(lpdw) & 0x3) { // alignment fault fixup
  1235. ulChecksum += *((DWORD UNALIGNED*)lpdw);
  1236. lpdw++;
  1237. } else {
  1238. ulChecksum += *lpdw++;
  1239. }
  1240. ulCarry = ulChecksum & 1;
  1241. ulChecksum >>= 1;
  1242. if (ulCarry) {
  1243. ulChecksum |= 0x80000000;
  1244. }
  1245. }
  1246. }
  1247. *pChecksum = ulChecksum;
  1248. return TRUE;
  1249. }
  1250. BOOL
  1251. SdbpCheckVersion(
  1252. IN ULONGLONG qwDBFileVer,
  1253. IN ULONGLONG qwBinFileVer
  1254. )
  1255. /*++
  1256. Return: TRUE if the versions match, FALSE if they don't.
  1257. Desc: Checks a binary version from the db against the version from
  1258. the file, including allowing for wildcards, which are represented
  1259. in the DB by using FFFF for that word-sized portion of the version.
  1260. --*/
  1261. {
  1262. WORD wDBSegment, wFileSegment;
  1263. int i;
  1264. for (i = 3; i >= 0; --i) {
  1265. //
  1266. // Get the appropriate word out of the QWORD
  1267. //
  1268. wDBSegment = (WORD)(qwDBFileVer >> (16 * i));
  1269. wFileSegment = (WORD)(qwBinFileVer >> (16 * i));
  1270. //
  1271. // The DB segment may be 0xFFFF, in which case it matches on
  1272. // everything.
  1273. //
  1274. if (wDBSegment != wFileSegment && wDBSegment != 0xFFFF) {
  1275. return FALSE;
  1276. }
  1277. }
  1278. return TRUE;
  1279. }
  1280. BOOL
  1281. SdbpCheckUptoVersion(
  1282. IN ULONGLONG qwDBFileVer,
  1283. IN ULONGLONG qwBinFileVer
  1284. )
  1285. /*++
  1286. Return: TRUE if the versions match, FALSE if they don't.
  1287. Desc: Checks a binary version from the db against the version from
  1288. the file, including allowing for wildcards, which are represented
  1289. in the DB by using FFFF for that word-sized portion of the version.
  1290. --*/
  1291. {
  1292. WORD wDBSegment, wFileSegment;
  1293. BOOL bReturn = TRUE;
  1294. int i;
  1295. for (i = 3; i >= 0; --i) {
  1296. //
  1297. // Get the appropriate word out of the QWORD
  1298. //
  1299. wDBSegment = (WORD)(qwDBFileVer >> (16 * i));
  1300. wFileSegment = (WORD)(qwBinFileVer >> (16 * i));
  1301. if (wDBSegment == wFileSegment || wDBSegment == 0xFFFF) {
  1302. continue;
  1303. }
  1304. //
  1305. // At this point we know that the two values don't match
  1306. // the wFileSegment has to be less than wDBSegment to satisfy this
  1307. // test - so set bReturn and exit
  1308. //
  1309. bReturn = (wDBSegment > wFileSegment);
  1310. break;
  1311. }
  1312. return bReturn;
  1313. }
  1314. #ifndef KERNEL_MODE
  1315. BOOL
  1316. SdbFormatAttribute(
  1317. IN PATTRINFO pAttrInfo, // pointer to the attribute information
  1318. OUT LPTSTR pchBuffer, // receives XML corresponding to the given attribute
  1319. IN DWORD dwBufferSize // size in wide characters of the buffer pchBuffer
  1320. )
  1321. /*++
  1322. Return: FALSE if the buffer is too small or attribute not available.
  1323. Desc: TBD.
  1324. --*/
  1325. {
  1326. size_t cchRemaining;
  1327. TCHAR* pszEnd = NULL;
  1328. HRESULT hr;
  1329. #if defined(WIN32A_MODE) || defined(WIN32U_MODE)
  1330. struct tm* ptm;
  1331. time_t tt;
  1332. #else
  1333. LARGE_INTEGER liTime;
  1334. TIME_FIELDS TimeFields;
  1335. #endif
  1336. if (!(pAttrInfo->dwFlags & ATTRIBUTE_AVAILABLE)) {
  1337. return FALSE;
  1338. }
  1339. hr = StringCchPrintfEx(pchBuffer,
  1340. (int)dwBufferSize,
  1341. &pszEnd,
  1342. &cchRemaining,
  1343. 0,
  1344. TEXT("%s="),
  1345. SdbTagToString(pAttrInfo->tAttrID));
  1346. if (FAILED(hr)) {
  1347. DBGPRINT((sdlError,
  1348. "SdbFormatAttribute",
  1349. "Buffer is too small to accomodate \"%s\"\n",
  1350. SdbTagToString(pAttrInfo->tAttrID)));
  1351. return FALSE;
  1352. }
  1353. switch (pAttrInfo->tAttrID) {
  1354. case TAG_BIN_PRODUCT_VERSION:
  1355. case TAG_BIN_FILE_VERSION:
  1356. case TAG_UPTO_BIN_PRODUCT_VERSION:
  1357. case TAG_UPTO_BIN_FILE_VERSION:
  1358. hr = StringCchPrintf(pszEnd,
  1359. cchRemaining,
  1360. TEXT("\"%d.%d.%d.%d\""),
  1361. (WORD)(pAttrInfo->ullAttr >> 48),
  1362. (WORD)(pAttrInfo->ullAttr >> 32),
  1363. (WORD)(pAttrInfo->ullAttr >> 16),
  1364. (WORD)(pAttrInfo->ullAttr));
  1365. break;
  1366. case TAG_MODULE_TYPE:
  1367. hr = StringCchPrintf(pszEnd,
  1368. cchRemaining,
  1369. TEXT("\"%s\""),
  1370. SdbpModuleTypeToString(pAttrInfo->dwAttr));
  1371. break;
  1372. case TAG_VER_LANGUAGE:
  1373. //
  1374. // language is a dword attribute that we shall make a string out of
  1375. //
  1376. {
  1377. TCHAR szLanguageName[MAX_PATH];
  1378. DWORD dwLength;
  1379. szLanguageName[0] = TEXT('\0');
  1380. dwLength = VerLanguageName((LANGID)pAttrInfo->dwAttr,
  1381. szLanguageName,
  1382. CHARCOUNT(szLanguageName));
  1383. if (dwLength) {
  1384. hr = StringCchPrintf(pszEnd,
  1385. cchRemaining,
  1386. TEXT("\"%s [0x%x]\""),
  1387. szLanguageName,
  1388. pAttrInfo->dwAttr);
  1389. } else {
  1390. hr = StringCchPrintf(pszEnd,
  1391. cchRemaining,
  1392. TEXT("\"0x%x\""),
  1393. pAttrInfo->dwAttr);
  1394. }
  1395. }
  1396. break;
  1397. case TAG_LINK_DATE:
  1398. case TAG_UPTO_LINK_DATE:
  1399. #if defined(WIN32A_MODE) || defined(WIN32U_MODE)
  1400. tt = (time_t) pAttrInfo->dwAttr;
  1401. ptm = gmtime(&tt);
  1402. if (ptm) {
  1403. hr = StringCchPrintf(pszEnd,
  1404. cchRemaining,
  1405. TEXT("\"%02d/%02d/%02d %02d:%02d:%02d\""),
  1406. ptm->tm_mon+1,
  1407. ptm->tm_mday,
  1408. ptm->tm_year+1900,
  1409. ptm->tm_hour,
  1410. ptm->tm_min,
  1411. ptm->tm_sec);
  1412. }
  1413. #else
  1414. RtlSecondsSince1970ToTime((ULONG)pAttrInfo->dwAttr, &liTime);
  1415. RtlTimeToTimeFields(&liTime, &TimeFields);
  1416. hr = StringCchPrintf(pszEnd,
  1417. cchRemaining,
  1418. TEXT("\"%02d/%02d/%02d %02d:%02d:%02d\""),
  1419. TimeFields.Month,
  1420. TimeFields.Day,
  1421. TimeFields.Year,
  1422. TimeFields.Hour,
  1423. TimeFields.Minute,
  1424. TimeFields.Second);
  1425. #endif
  1426. break;
  1427. case TAG_SIZE:
  1428. hr = StringCchPrintf(pszEnd,
  1429. cchRemaining,
  1430. TEXT("\"%ld\""),
  1431. pAttrInfo->dwAttr);
  1432. break;
  1433. default:
  1434. switch (GETTAGTYPE(pAttrInfo->tAttrID)) {
  1435. case TAG_TYPE_DWORD:
  1436. hr = StringCchPrintf(pszEnd,
  1437. cchRemaining,
  1438. TEXT("\"0x%lX\""),
  1439. pAttrInfo->dwAttr);
  1440. break;
  1441. case TAG_TYPE_QWORD:
  1442. //
  1443. // This is an unidentified QWORD attribute
  1444. //
  1445. DBGPRINT((sdlError, "SdbFormatAttribute", "Unexpected qword attribute found\n"));
  1446. hr = StringCchPrintf(pszEnd,
  1447. cchRemaining,
  1448. TEXT("\"0x%I64X\""),
  1449. pAttrInfo->ullAttr);
  1450. break;
  1451. case TAG_TYPE_STRINGREF:
  1452. if (cchRemaining < 3) {
  1453. return FALSE; // not enough room even for " ?
  1454. }
  1455. *pszEnd++ = TEXT('\"');
  1456. cchRemaining--;
  1457. if (!SdbpSanitizeXML(pszEnd, (int)cchRemaining, pAttrInfo->lpAttr)) {
  1458. // handle error please
  1459. return FALSE;
  1460. }
  1461. //
  1462. // Once done with this, sanitize further
  1463. //
  1464. if (!SafeNCat(pszEnd, (int)cchRemaining, TEXT("\""), -1)) {
  1465. return FALSE;
  1466. }
  1467. hr = S_OK;
  1468. break;
  1469. }
  1470. }
  1471. return (hr == S_OK); // evaluates to TRUE when we successfully printed the value into the buffer
  1472. }
  1473. BOOL
  1474. SdbpGetVersionAttributes(
  1475. IN PSDBCONTEXT pContext,
  1476. OUT PFILEINFO pFileInfo
  1477. )
  1478. /*++
  1479. Return: TRUE on success, FALSE otherwise.
  1480. Desc: This function retrieves all of the Version-related attributes
  1481. Imports apis from version.dll if called for the first time
  1482. --*/
  1483. {
  1484. DWORD dwNull = 0;
  1485. VS_FIXEDFILEINFO* pFixedInfo = NULL; // fixed info ptr
  1486. UINT FixedInfoSize = 0;
  1487. PVOID pBuffer = NULL; // version data buffer
  1488. DWORD dwBufferSize; // version data buffer size
  1489. int i;
  1490. #ifdef NT_MODE
  1491. //
  1492. // check to see whether we need to run NT routine
  1493. //
  1494. if (pFileInfo->hFile != INVALID_HANDLE_VALUE || pFileInfo->pImageBase != NULL) {
  1495. //
  1496. // not an error -- this case is handled in header attributes
  1497. //
  1498. goto err;
  1499. }
  1500. #endif // NT_MODE
  1501. if (pContext == NULL) {
  1502. //
  1503. // Special case when it's called with null context.
  1504. // In this case we use an internal structure allocated from the stack.
  1505. //
  1506. STACK_ALLOC(pContext, sizeof(SDBCONTEXT));
  1507. if (pContext == NULL) {
  1508. DBGPRINT((sdlError,
  1509. "SdbpGetVersionAttributes",
  1510. "Failed to allocate %d bytes from stack\n",
  1511. sizeof(SDBCONTEXT)));
  1512. goto err;
  1513. }
  1514. RtlZeroMemory(pContext, sizeof(SDBCONTEXT));
  1515. }
  1516. #ifdef WIN32A_MODE
  1517. pContext->pfnGetFileVersionInfoSize = GetFileVersionInfoSizeA;
  1518. pContext->pfnGetFileVersionInfo = GetFileVersionInfoA;
  1519. pContext->pfnVerQueryValue = VerQueryValueA;
  1520. #else
  1521. pContext->pfnGetFileVersionInfoSize = GetFileVersionInfoSizeW;
  1522. pContext->pfnGetFileVersionInfo = GetFileVersionInfoW;
  1523. pContext->pfnVerQueryValue = VerQueryValueW;
  1524. #endif
  1525. dwBufferSize = pContext->pfnGetFileVersionInfoSize(pFileInfo->FilePath, &dwNull);
  1526. if (dwBufferSize == 0) {
  1527. DBGPRINT((sdlInfo, "SdbpGetVersionAttributes", "No version info.\n"));
  1528. //
  1529. // We have failed to obtain version attributes
  1530. //
  1531. goto err;
  1532. }
  1533. pBuffer = SdbAlloc(dwBufferSize + VERSIONINFO_BUFFER_PAD);
  1534. if (pBuffer == NULL) {
  1535. DBGPRINT((sdlError,
  1536. "SdbpGetVersionAttributes",
  1537. "Failed to allocate %d bytes for version info buffer.\n",
  1538. dwBufferSize + VERSIONINFO_BUFFER_PAD));
  1539. goto err;
  1540. }
  1541. if (!pContext->pfnGetFileVersionInfo(pFileInfo->FilePath, 0, dwBufferSize, pBuffer)) {
  1542. DBGPRINT((sdlError,
  1543. "SdbpGetVersionAttributes",
  1544. "Failed to retrieve version info for file \"%s\"",
  1545. pFileInfo->FilePath));
  1546. goto err;
  1547. }
  1548. if (!pContext->pfnVerQueryValue(pBuffer,
  1549. TEXT("\\"),
  1550. (PVOID*)&pFixedInfo,
  1551. &FixedInfoSize)) {
  1552. DBGPRINT((sdlError,
  1553. "SdbpGetVersionAttributes",
  1554. "Failed to query for fixed version info size for \"%s\"\n",
  1555. pFileInfo->FilePath));
  1556. goto err;
  1557. }
  1558. //
  1559. // Retrieve string attributes.
  1560. //
  1561. SdbpQueryStringVersionInformation(pContext, pFileInfo, pBuffer);
  1562. //
  1563. // Now retrieve other attributes.
  1564. //
  1565. if (FixedInfoSize >= sizeof(VS_FIXEDFILEINFO)) {
  1566. SdbpQueryBinVersionInformation(pContext, pFileInfo, pFixedInfo);
  1567. } else {
  1568. //
  1569. // No other version attributes are available. Set the rest of the
  1570. // attributes as being not available.
  1571. //
  1572. for (i = 0; i < ARRAYSIZE(g_rgBinVerTags); ++i) {
  1573. SdbpSetAttribute(pFileInfo, g_rgBinVerTags[i], NULL);
  1574. }
  1575. }
  1576. //
  1577. // Store the pointer to the version info buffer.
  1578. //
  1579. pFileInfo->pVersionInfo = pBuffer;
  1580. return TRUE;
  1581. err:
  1582. //
  1583. // We are here ONLY when we failed to obtain version info
  1584. // through apis -- regardless of the state of other value we might have
  1585. // obtained
  1586. if (pBuffer != NULL) {
  1587. SdbFree(pBuffer);
  1588. }
  1589. for (i = 0; i < ARRAYSIZE(g_rgBinVerTags); ++i) {
  1590. SdbpSetAttribute(pFileInfo, g_rgBinVerTags[i], NULL);
  1591. }
  1592. for (i = 0; i < ARRAYSIZE(g_rgVerStrings); ++i) {
  1593. SdbpSetAttribute(pFileInfo, g_rgVerStrings[i].tTag, NULL);
  1594. }
  1595. return FALSE;
  1596. }
  1597. BOOL
  1598. SdbpGetFileDirectoryAttributes(
  1599. OUT PFILEINFO pFileInfo
  1600. )
  1601. /*++
  1602. Return: TRUE on success, FALSE otherwise.
  1603. Desc: This function retrieves the file directory attributes for the
  1604. specified file.
  1605. --*/
  1606. {
  1607. BOOL bSuccess = FALSE;
  1608. FILEDIRECTORYATTRIBUTES fda;
  1609. int i;
  1610. bSuccess = SdbpQueryFileDirectoryAttributes(pFileInfo->FilePath, &fda);
  1611. if (!bSuccess) {
  1612. DBGPRINT((sdlInfo,
  1613. "SdbpGetFileDirectoryAttributes",
  1614. "No file directory attributes available.\n"));
  1615. goto Done;
  1616. }
  1617. if (fda.dwFlags & FDA_FILESIZE) {
  1618. assert(fda.dwFileSizeHigh == 0);
  1619. SdbpSetAttribute(pFileInfo, TAG_SIZE, &fda.dwFileSizeLow);
  1620. }
  1621. Done:
  1622. if (!bSuccess) {
  1623. for (i = 0; g_rgDirectoryTags[i] != 0; ++i) {
  1624. SdbpSetAttribute(pFileInfo, g_rgDirectoryTags[i], NULL);
  1625. }
  1626. }
  1627. return bSuccess;
  1628. }
  1629. BOOL
  1630. SdbGetFileAttributes(
  1631. IN LPCTSTR lpwszFileName, // the file for which attributes are requested
  1632. OUT PATTRINFO* ppAttrInfo, // receives allocated pointer to the attribute array
  1633. OUT LPDWORD lpdwAttrCount // receives the number of entries in an attributes table
  1634. )
  1635. /*++
  1636. Return: FALSE if the file does not exist or some other severe error had occured.
  1637. Note that each attribute has it's own flag ATTRIBUTE_AVAILABLE that allows
  1638. for checking whether an attribute has been retrieved successfully
  1639. Not all attributes might be present for all files.
  1640. Desc: TBD
  1641. --*/
  1642. {
  1643. PFILEINFO pFileInfo;
  1644. BOOL bReturn;
  1645. //
  1646. // The call below allocates the structure, context is not used
  1647. //
  1648. pFileInfo = SdbGetFileInfo(NULL, lpwszFileName, INVALID_HANDLE_VALUE, NULL, 0, TRUE);
  1649. if (pFileInfo == NULL) {
  1650. DBGPRINT((sdlError, "SdbGetFileAttributes", "Error retrieving FILEINFO structure\n"));
  1651. return FALSE;
  1652. }
  1653. //
  1654. // The three calls below, even when fail do not produce a fatal condition
  1655. // as the exe may not have all the attributes available.
  1656. //
  1657. bReturn = SdbpGetFileDirectoryAttributes(pFileInfo);
  1658. if (!bReturn) {
  1659. DBGPRINT((sdlInfo, "SdbGetFileAttributes", "Error retrieving directory attributes\n"));
  1660. }
  1661. bReturn = SdbpGetVersionAttributes(NULL, pFileInfo);
  1662. if (!bReturn) {
  1663. DBGPRINT((sdlInfo, "SdbGetFileAttributes", "Error retrieving version attributes\n"));
  1664. }
  1665. bReturn = SdbpGetHeaderAttributes(NULL, pFileInfo);
  1666. if (!bReturn) {
  1667. DBGPRINT((sdlInfo, "SdbGetFileAttributes", "Error retrieving header attributes\n"));
  1668. }
  1669. pFileInfo->dwMagic = FILEINFO_MAGIC;
  1670. //
  1671. // Now that we are done, put the return pointer.
  1672. //
  1673. if (lpdwAttrCount != NULL) {
  1674. *lpdwAttrCount = ATTRIBUTE_COUNT;
  1675. }
  1676. if (ppAttrInfo != NULL) {
  1677. //
  1678. // Return the pointer to the attribute info itself.
  1679. // It is the same pointer we expect to get in a complimentary
  1680. // call to SdbFreeFileInfo.
  1681. //
  1682. *ppAttrInfo = &pFileInfo->Attributes[0];
  1683. } else {
  1684. //
  1685. // Pointer is not needed. Release the memory.
  1686. //
  1687. SdbFreeFileInfo(pFileInfo);
  1688. }
  1689. return TRUE;
  1690. }
  1691. BOOL
  1692. SdbFreeFileAttributes(
  1693. IN PATTRINFO pFileAttributes // pointer returned by SdbGetFileAttributes
  1694. )
  1695. /*++
  1696. Return: FALSE if a wrong pointer was passed in (not the one
  1697. from SdbGetFileAttributes).
  1698. Desc: Self explanatory.
  1699. --*/
  1700. {
  1701. PFILEINFO pFileInfo;
  1702. //
  1703. // We are assuming the pointer that was passed in points inside of a
  1704. // larger structure FILEINFO. To verify that we step back a pre-determined number
  1705. // of bytes (calculated below as an offset) and check the "magic" signature.
  1706. //
  1707. pFileInfo = (PFILEINFO)((PBYTE)pFileAttributes - OFFSETOF(FILEINFO, Attributes));
  1708. if (pFileInfo->dwMagic != FILEINFO_MAGIC) {
  1709. DBGPRINT((sdlError, "SdbFreeFileAttributes", "Bad pointer to attributes.\n"));
  1710. return FALSE;
  1711. }
  1712. SdbFreeFileInfo(pFileInfo);
  1713. return TRUE;
  1714. }
  1715. BOOL
  1716. SdbpQuery16BitDescription(
  1717. OUT LPSTR szBuffer, // min length 256 chars !
  1718. IN PIMAGEFILEDATA pImageData
  1719. )
  1720. /*++
  1721. Return: TRUE on success, FALSE otherwise.
  1722. Desc: Gets the 16 bit description for a DOS executable.
  1723. --*/
  1724. {
  1725. PIMAGE_DOS_HEADER pDosHeader;
  1726. PIMAGE_OS2_HEADER pNEHeader;
  1727. PBYTE pSize;
  1728. DWORD ModuleType;
  1729. if (!SdbpGetModuleType(&ModuleType, pImageData)) {
  1730. return FALSE;
  1731. }
  1732. if (ModuleType != MT_W16_MODULE) {
  1733. return FALSE;
  1734. }
  1735. pDosHeader = (PIMAGE_DOS_HEADER)pImageData->pBase;
  1736. pNEHeader = (PIMAGE_OS2_HEADER)((PBYTE)pImageData->pBase + pDosHeader->e_lfanew);
  1737. //
  1738. // Now we know that pNEHeader is valid, just have to make sure that
  1739. // the next offset is valid as well, make a check against file size.
  1740. //
  1741. if (pImageData->ViewSize < pDosHeader->e_lfanew + sizeof(*pNEHeader)) {
  1742. return FALSE;
  1743. }
  1744. if (pImageData->ViewSize < pNEHeader->ne_nrestab + sizeof(*pSize)) {
  1745. return FALSE;
  1746. }
  1747. pSize = (PBYTE)((PBYTE)pImageData->pBase + pNEHeader->ne_nrestab);
  1748. if (*pSize == 0) {
  1749. return FALSE;
  1750. }
  1751. //
  1752. // Now check for the string size.
  1753. //
  1754. if (pImageData->ViewSize < pNEHeader->ne_nrestab + sizeof(*pSize) + *pSize) {
  1755. return FALSE;
  1756. }
  1757. RtlCopyMemory(szBuffer, pSize + 1, *pSize);
  1758. szBuffer[*pSize] = '\0';
  1759. return TRUE;
  1760. }
  1761. BOOL
  1762. SdbpQuery16BitModuleName(
  1763. OUT LPSTR szBuffer,
  1764. IN PIMAGEFILEDATA pImageData
  1765. )
  1766. {
  1767. PIMAGE_DOS_HEADER pDosHeader;
  1768. PIMAGE_OS2_HEADER pNEHeader;
  1769. PBYTE pSize;
  1770. DWORD ModuleType;
  1771. if (!SdbpGetModuleType(&ModuleType, pImageData)) {
  1772. return FALSE;
  1773. }
  1774. if (ModuleType != MT_W16_MODULE) {
  1775. return FALSE;
  1776. }
  1777. pDosHeader = (PIMAGE_DOS_HEADER)pImageData->pBase;
  1778. pNEHeader = (PIMAGE_OS2_HEADER)((PBYTE)pImageData->pBase + pDosHeader->e_lfanew);
  1779. //
  1780. // Now we know that pNEHeader is valid, just have to make sure that
  1781. // the next offset is valid as well, make a check against file size.
  1782. //
  1783. if (pImageData->ViewSize < pDosHeader->e_lfanew + sizeof(*pNEHeader)) {
  1784. return FALSE;
  1785. }
  1786. if (pImageData->ViewSize < pNEHeader->ne_restab + sizeof(*pSize)) {
  1787. return FALSE;
  1788. }
  1789. pSize = (PBYTE)((PBYTE)pImageData->pBase + pDosHeader->e_lfanew + pNEHeader->ne_restab);
  1790. if (*pSize == 0) {
  1791. return FALSE;
  1792. }
  1793. //
  1794. // Now check for the string size.
  1795. //
  1796. if (pImageData->ViewSize <
  1797. pDosHeader->e_lfanew + pNEHeader->ne_restab + sizeof(*pSize) + *pSize) {
  1798. return FALSE;
  1799. }
  1800. RtlCopyMemory(szBuffer, pSize + 1, *pSize);
  1801. szBuffer[*pSize] = '\0';
  1802. return TRUE;
  1803. }
  1804. #endif // KERNEL_MODE