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.

2341 lines
68 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. sdbapi.c
  5. Abstract:
  6. BUGBUG: This module implements ...
  7. Author:
  8. dmunsil created sometime in 1999
  9. Revision History:
  10. several people contributed (vadimb, clupu, ...)
  11. --*/
  12. #include "sdbp.h"
  13. #include "initguid.h"
  14. DEFINE_GUID(GUID_SYSMAIN_SDB, 0x11111111, 0x1111, 0x1111, 0x11, 0x11, 0x11, 0x11, \
  15. 0x11, 0x11, 0x11, 0x11);
  16. DEFINE_GUID(GUID_APPHELP_SDB, 0x22222222, 0x2222, 0x2222, 0x22, 0x22, 0x22, 0x22, \
  17. 0x22, 0x22, 0x22, 0x22);
  18. DEFINE_GUID(GUID_SYSTEST_SDB, 0x33333333, 0x3333, 0x3333, 0x33, 0x33, 0x33, 0x33, \
  19. 0x33, 0x33, 0x33, 0x33);
  20. DEFINE_GUID(GUID_DRVMAIN_SDB, 0xF9AB2228, 0x3312, 0x4A73, 0xB6, 0xF9, 0x93, 0x6D, \
  21. 0x70, 0xE1, 0x12, 0xEF);
  22. DEFINE_GUID(GUID_MSIMAIN_SDB, 0xD8FF6D16, 0x6A3A, 0x468A, 0x8B, 0x44, 0x01, 0x71, \
  23. 0x4D, 0xDC, 0x49, 0xEA);
  24. DEFINE_GUID(GUID_APPHELP_SP_SDB, 0x44444444, 0x4444, 0x4444, 0x44, 0x44, 0x44, 0x44, \
  25. 0x44, 0x44, 0x44, 0x44);
  26. #ifdef _DEBUG_SPEW
  27. //
  28. // Shim Debug output support
  29. //
  30. int g_iShimDebugLevel = SHIM_DEBUG_UNINITIALIZED;
  31. DBGLEVELINFO g_rgDbgLevelInfo[DEBUG_LEVELS] = {
  32. { "Err", sdlError },
  33. { "Warn", sdlWarning },
  34. { "Fail", sdlFail },
  35. { "Info", sdlInfo }
  36. };
  37. PCH g_szDbgLevelUser = "User";
  38. #endif // _DEBUG_SPEW
  39. BOOL
  40. SdbpInitializeSearchDBContext(
  41. PSEARCHDBCONTEXT pContext
  42. );
  43. #if defined(KERNEL_MODE) && defined(ALLOC_PRAGMA)
  44. #pragma alloc_text(PAGE, ShimExceptionHandler)
  45. #pragma alloc_text(PAGE, SdbpCreateSearchDBContext)
  46. #pragma alloc_text(PAGE, SdbpInitializeSearchDBContext)
  47. #pragma alloc_text(PAGE, SdbpReleaseSearchDBContext)
  48. #pragma alloc_text(PAGE, SdbpCheckForMatch)
  49. #pragma alloc_text(PAGE, SdbpSearchDB)
  50. #pragma alloc_text(PAGE, SdbpCreateSearchDBContext)
  51. #pragma alloc_text(PAGE, SdbGetDatabaseMatch)
  52. #pragma alloc_text(PAGE, SdbQueryData)
  53. #pragma alloc_text(PAGE, SdbQueryDataEx)
  54. #pragma alloc_text(PAGE, SdbReadEntryInformation)
  55. #pragma alloc_text(PAGE, PrepareFormatForUnicode)
  56. #pragma alloc_text(PAGE, ShimDbgPrint)
  57. #endif
  58. #if DBG
  59. const BOOL g_bDBG = TRUE;
  60. #else
  61. const BOOL g_bDBG = FALSE;
  62. #endif
  63. //
  64. // Exception handler
  65. //
  66. ULONG
  67. ShimExceptionHandler(
  68. PEXCEPTION_POINTERS pexi,
  69. char* szFile,
  70. DWORD dwLine
  71. )
  72. {
  73. #ifndef KERNEL_MODE // in kmode exceptions won't work anyway
  74. DBGPRINT((sdlError,
  75. "ShimExceptionHandler",
  76. "Shim Exception %#x in module \"%hs\", line %d, at address %#p. flags:%#x. !exr %#p !cxr %#p",
  77. pexi->ExceptionRecord->ExceptionCode,
  78. szFile,
  79. dwLine,
  80. CONTEXT_TO_PROGRAM_COUNTER(pexi->ContextRecord),
  81. pexi->ExceptionRecord->ExceptionFlags,
  82. pexi->ExceptionRecord,
  83. pexi->ContextRecord));
  84. //
  85. // Special-case stack overflow exception which is likely to occur due to
  86. // low memory conditions during stress. The process is dead anyway so we
  87. // will not handle this exception.
  88. //
  89. if (pexi->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
  90. return EXCEPTION_CONTINUE_SEARCH;
  91. }
  92. #if DBG
  93. SDB_BREAK_POINT();
  94. #endif // DBG
  95. #endif // KERNEL_MODE
  96. return EXCEPTION_EXECUTE_HANDLER;
  97. }
  98. BOOL
  99. SdbpResolveAndSplitPath(
  100. IN DWORD dwFlags, // context flags (SEARCHDBF_NO_LFN in particular)
  101. IN LPCTSTR szFullPath, // a full UNC or DOS path & filename, "c:\foo\myfile.ext"
  102. OUT LPTSTR szDir, // the drive and dir portion of the filename "c:\foo\"
  103. OUT LPTSTR szName, // the filename portion "myfile"
  104. OUT LPTSTR szExt // the extension portion ".ext"
  105. )
  106. /*++
  107. Return: TRUE on success, FALSE otherwise.
  108. Desc: This function takes a full path and splits it into pieces ala splitpath,
  109. but also converts short file names to long names.
  110. NOTE: The caller is responsible for allocating enough space
  111. for the passed-in strings to take any portion of the path.
  112. For safety, allocate at least MAX_PATH WCHARS for each piece.
  113. --*/
  114. {
  115. TCHAR* szCursor;
  116. TCHAR szLongFileName[MAX_PATH + 1];
  117. BOOL bFound;
  118. DWORD i;
  119. assert(szFullPath && szDir && szName && szExt);
  120. //
  121. // Parse the directory.
  122. //
  123. szDir[0] = _T('\0');
  124. szCursor = _tcsrchr(szFullPath, _T('\\')); // last backslash please
  125. if (szCursor == NULL) {
  126. szCursor = (LPTSTR)szFullPath;
  127. } else {
  128. _tcsncpy(szDir, szFullPath, szCursor - szFullPath + 1);
  129. szDir[szCursor - szFullPath + 1] = _T('\0');
  130. }
  131. #ifndef KERNEL_MODE
  132. //
  133. // Make sure we're using the long filename
  134. //
  135. if (dwFlags & SEARCHDBF_NO_LFN) {
  136. assert(_tcslen(szCursor) < CHARCOUNT(szLongFileName));
  137. _tcscpy(szLongFileName, szCursor);
  138. } else {
  139. if (!SdbpGetLongFileName(szFullPath, szLongFileName)) {
  140. return FALSE;
  141. }
  142. }
  143. #else // KERNEL_MODE
  144. //
  145. // When we are in kernel mode, our file name is always considered to be "long".
  146. // At this point szCursor points to the last '\\' or to the beginning of the name.
  147. //
  148. if (*szCursor == _T('\\')) {
  149. ++szCursor;
  150. }
  151. //
  152. // Make sure that we have enough room for the name.
  153. //
  154. assert(wcslen(szCursor) < CHARCOUNT(szLongFileName));
  155. wcscpy(szLongFileName, szCursor);
  156. #endif // KERNEL_MODE
  157. //
  158. // Parse name & extension
  159. //
  160. szExt[0] = _T('\0');
  161. szName[0] = _T('\0');
  162. //
  163. // Within the long file name find the last dot
  164. //
  165. szCursor = _tcsrchr(szLongFileName, _T('.'));
  166. if (szCursor != NULL) {
  167. _tcsncpy(szName, szLongFileName, szCursor - szLongFileName);
  168. szName [szCursor-szLongFileName] = _T('\0');
  169. _tcscpy(szExt, szCursor);
  170. } else {
  171. _tcscpy(szName, szLongFileName);
  172. }
  173. return TRUE;
  174. }
  175. BOOL
  176. SdbpCreateSearchDBContext(
  177. PSEARCHDBCONTEXT pContext,
  178. LPCTSTR szPath,
  179. LPCTSTR szModuleName,
  180. LPCTSTR pEnvironment
  181. )
  182. /*++
  183. Return: TRUE - search db context was successfully created
  184. Desc: This function creates context for searching the database, in particular, the
  185. context is initalized with the path of probable local database location,
  186. executable path is broken down into containing directory and the filename part.
  187. --*/
  188. {
  189. DWORD dwPathLen;
  190. BOOL bReturn = FALSE;
  191. TCHAR* szDirectory = NULL;
  192. TCHAR* szExt = NULL;
  193. TCHAR* szFullName = NULL;
  194. TCHAR* szFileName = NULL;
  195. TCHAR* szModule = NULL;
  196. assert(NULL != szPath);
  197. assert(NULL != pContext);
  198. dwPathLen = _tcslen(szPath);
  199. //
  200. // Allocate enough to guarantee our strings will not overflow
  201. //
  202. szDirectory = SdbAlloc((dwPathLen + 1) * sizeof(TCHAR));
  203. szFullName = SdbAlloc((_MAX_PATH + 1) * sizeof(TCHAR));
  204. if (szModuleName) {
  205. szModule = SdbAlloc((_tcslen(szModuleName) + 1) * sizeof(TCHAR));
  206. if (!szModule) {
  207. DBGPRINT((sdlError,
  208. "SdbpCreateSearchDBContext",
  209. "Unable to allocate memory for szModule.\n"));
  210. goto out;
  211. }
  212. _tcscpy(szModule, szModuleName);
  213. }
  214. STACK_ALLOC(szExt, (_MAX_PATH + 1) * sizeof(TCHAR));
  215. STACK_ALLOC(szFileName, (_MAX_PATH + 1) * sizeof(TCHAR));
  216. if (!szDirectory || !szExt || !szFullName || !szFileName || !pContext) {
  217. DBGPRINT((sdlError,
  218. "SdbpCreateSearchDBContext",
  219. "Unable to allocate memory for strings.\n"));
  220. goto out;
  221. }
  222. if (!SdbpResolveAndSplitPath(pContext->dwFlags, szPath, szDirectory, szFileName, szExt)) {
  223. DBGPRINT((sdlError,
  224. "SdbpCreateSearchDBContext",
  225. "Unable to parse executable path for \"%s\".\n",
  226. szPath));
  227. goto out;
  228. }
  229. _tcscpy(szFullName, szFileName);
  230. _tcscat(szFullName, szExt);
  231. pContext->pEnvironment = pEnvironment;
  232. pContext->szDir = szDirectory;
  233. pContext->szName = szFullName; // fullname (filename + ext)
  234. pContext->szModuleName = szModule;
  235. //
  236. // We do not retain szExt (don't need it)
  237. //
  238. // Calculate this later -- implied by RtlZeroMemory statement above
  239. //
  240. pContext->pSearchParts = NULL;
  241. pContext->szProcessHistory = NULL;
  242. bReturn = TRUE;
  243. out:
  244. if (szExt != NULL) {
  245. STACK_FREE(szExt);
  246. }
  247. if (szFileName != NULL) {
  248. STACK_FREE(szFileName);
  249. }
  250. if (!bReturn) {
  251. if (szDirectory != NULL) {
  252. SdbFree(szDirectory);
  253. }
  254. if (szFullName != NULL) {
  255. SdbFree(szFullName);
  256. }
  257. if (szModule != NULL) {
  258. SdbFree(szModule);
  259. }
  260. }
  261. return bReturn;
  262. }
  263. BOOL
  264. SdbpInitializeSearchDBContext(
  265. PSEARCHDBCONTEXT pContext
  266. )
  267. /*++
  268. Return: TRUE - the context was successfully initialized with the process history
  269. which was broken down into the separate search paths
  270. Desc: This function prepares search context for use, obtaining and parsing process
  271. history into separate paths. The array of these search paths is used then
  272. by the caller to inquire about matching files that might be present in one
  273. of the these places.
  274. In Kernel mode use SEARCHDBF_NO_PROCESS_HISTORY flag within context
  275. it will include only the current exe path into the process history
  276. --*/
  277. {
  278. BOOL bSuccess = TRUE;
  279. LPTSTR pszProcessHistory = NULL;
  280. if (pContext->pSearchParts != NULL) {
  281. return TRUE;
  282. }
  283. if (pContext->dwFlags & SEARCHDBF_NO_PROCESS_HISTORY) {
  284. pszProcessHistory = pContext->szProcessHistory;
  285. if (pszProcessHistory == NULL) {
  286. DWORD DirLen = _tcslen(pContext->szDir);
  287. DWORD NameLen = _tcslen(pContext->szName);
  288. //
  289. // We create a temporary process history
  290. //
  291. pContext->szProcessHistory = SdbAlloc((DirLen + NameLen + 1) * sizeof(TCHAR));
  292. if (pContext->szProcessHistory == NULL) {
  293. DBGPRINT((sdlError,
  294. "SdbpInitializeSearchDBContext",
  295. "Failed to allocate buffer %d bytes\n",
  296. (DirLen + NameLen + 1) * sizeof(TCHAR)));
  297. return FALSE;
  298. }
  299. pszProcessHistory = pContext->szProcessHistory;
  300. RtlMoveMemory(pszProcessHistory, pContext->szDir, DirLen * sizeof(TCHAR));
  301. RtlMoveMemory(pszProcessHistory + DirLen, pContext->szName, NameLen * sizeof(TCHAR));
  302. *(pszProcessHistory + DirLen + NameLen) = TEXT('\0');
  303. }
  304. //
  305. // When we are here -- we either have a process history or we just
  306. // created it consisting of a single search item
  307. //
  308. } else {
  309. #ifndef KERNEL_MODE
  310. if (pContext->szProcessHistory == NULL) {
  311. pContext->szProcessHistory = GetProcessHistory(pContext->pEnvironment,
  312. pContext->szDir,
  313. pContext->szName);
  314. if (pContext->szProcessHistory == NULL) {
  315. DBGPRINT((sdlError,
  316. "SdbpInitializeSearchDBContext",
  317. "Failed to retrieve process history\n"));
  318. return FALSE;
  319. }
  320. }
  321. pszProcessHistory = pContext->szProcessHistory;
  322. #else
  323. //
  324. // This is the case with KERNEL_MODE. YOU HAVE TO SET SEARCHDBF_NO_PROCESS_HISTORY
  325. //
  326. assert(FALSE);
  327. pszProcessHistory = NULL;
  328. #endif
  329. }
  330. //
  331. // At this point pszProcessHistory is NOT NULL
  332. //
  333. assert(pszProcessHistory != NULL);
  334. DBGPRINT((sdlInfo,
  335. "SdbpInitializeSearchDBContext",
  336. "Using Process History: \"%s\"\n",
  337. pszProcessHistory));
  338. bSuccess = SdbpCreateSearchPathPartsFromPath(pszProcessHistory, &pContext->pSearchParts);
  339. if (bSuccess) {
  340. pContext->dwFlags |= SEARCHDBF_INITIALIZED;
  341. }
  342. return bSuccess;
  343. }
  344. void
  345. SdbpReleaseSearchDBContext(
  346. PSEARCHDBCONTEXT pContext
  347. )
  348. /*++
  349. Return: void
  350. Desc: Resets search DB context, frees memory allocated for each of the
  351. temporary buffers.
  352. --*/
  353. {
  354. if (pContext == NULL) {
  355. return;
  356. }
  357. if (pContext->szProcessHistory != NULL) {
  358. SdbFree(pContext->szProcessHistory);
  359. pContext->szProcessHistory = NULL;
  360. }
  361. if (pContext->pSearchParts != NULL) {
  362. SdbFree(pContext->pSearchParts);
  363. pContext->pSearchParts = NULL;
  364. }
  365. if (pContext->szDir != NULL) {
  366. SdbFree(pContext->szDir);
  367. pContext->szDir = NULL;
  368. }
  369. if (pContext->szName != NULL) {
  370. SdbFree(pContext->szName);
  371. pContext->szName = NULL;
  372. }
  373. if (pContext->szModuleName != NULL) {
  374. SdbFree(pContext->szModuleName);
  375. pContext->szModuleName = NULL;
  376. }
  377. }
  378. BOOL
  379. SdbpIsExeEntryEnabled(
  380. IN PDB pdb,
  381. IN TAGID tiExe,
  382. OUT GUID* pGUID,
  383. OUT DWORD* pdwFlags
  384. )
  385. {
  386. TAGID tiExeID;
  387. DWORD i;
  388. BOOL fSuccess = FALSE;
  389. //
  390. // Get the EXE's GUID
  391. //
  392. tiExeID = SdbFindFirstTag(pdb, tiExe, TAG_EXE_ID);
  393. if (tiExeID == TAGID_NULL) {
  394. DBGPRINT((sdlError,
  395. "SdbpIsExeEntryEnabled",
  396. "Failed to read TAG_EXE_ID for tiExe 0x%x !\n",
  397. tiExe));
  398. goto error;
  399. }
  400. if (!SdbReadBinaryTag(pdb, tiExeID, (PBYTE)pGUID, sizeof(GUID))) {
  401. DBGPRINT((sdlError,
  402. "SdbpIsExeEntryEnabled",
  403. "Failed to read the GUID for tiExe 0x%x !\n",
  404. tiExe));
  405. goto error;
  406. }
  407. if (!SdbGetEntryFlags(pGUID, pdwFlags)) {
  408. DBGPRINT((sdlWarning,
  409. "SdbpIsExeEntryEnabled",
  410. "No flags for tiExe 0x%lx\n",
  411. tiExe));
  412. *pdwFlags = 0;
  413. } else {
  414. DBGPRINT((sdlInfo,
  415. "SdbpIsExeEntryEnabled",
  416. "Retrieved flags for this app 0x%x.\n",
  417. *pdwFlags));
  418. }
  419. if (!(*pdwFlags & SHIMREG_DISABLE_SHIM)) {
  420. fSuccess = TRUE;
  421. }
  422. error:
  423. return fSuccess;
  424. }
  425. #define EXTRA_BUF_SPACE (16 * sizeof(TCHAR))
  426. //
  427. // Matching an entry:
  428. //
  429. // 1. We check whether each file exists by calling SdbGetFileInfo
  430. // 2. Each file's info is stored in FILEINFOCHAINITEM (allocated on the stack) - such as pointer
  431. // to the actual FILEINFO structure (stored in file attribute cache) and tiMatch denoting
  432. // the entry in the database for a given MATCHING_FILE
  433. // 3. After we have verified that all the matching files do exist -- we proceed to walk the
  434. // chain of FILEINFOCHAINITEM structures and call SdbCheckAllAttributes to check on all the
  435. // other attributes of the file
  436. // 4. Cleanup: File attribute cache is destroyed when the database is closed via call to
  437. // SdbCleanupAttributeMgr
  438. // 5. No cleanup is needed for FILEINFOCHAINITEM structures (they are allocated on the stack and
  439. // just "go away")
  440. //
  441. //
  442. typedef struct tagFILEINFOCHAINITEM {
  443. PVOID pFileInfo; // pointer to the actual FILEINFO
  444. // structure (from attribute cache)
  445. TAGID tiMatch; // matching entry in the database
  446. struct tagFILEINFOCHAINITEM* pNextItem; // pointer to the next matching file
  447. } FILEINFOCHAINITEM, *PFILEINFOCHAINITEM;
  448. BOOL
  449. SdbpCheckForMatch(
  450. IN HSDB hSDB, // context ptr
  451. IN PDB pdb, // pdb to get match criteria from
  452. IN TAGID tiExe, // TAGID of exe record to get match criteria from
  453. IN PSEARCHDBCONTEXT pContext, // search db context (includes name/path)
  454. OUT PMATCHMODE pMatchMode, // the match mode of this EXE
  455. OUT GUID* pGUID,
  456. OUT DWORD* pdwFlags
  457. )
  458. /*++
  459. Return: TRUE if match is good, FALSE if this EXE doesn't match.
  460. Desc: Given an EXE tag and a name and dir, checks the DB for MATCHING_FILE
  461. tags, and checks all the matching info available for each the
  462. files listed. If all the files check out, returns TRUE. If any of
  463. the files don't exist, or don't match on one of the given
  464. criteria, returns FALSE.
  465. --*/
  466. {
  467. BOOL bReturn = FALSE;
  468. BOOL bMatchLogicNot = FALSE;
  469. BOOL bAllAttributesMatch = FALSE;
  470. TAGID tiMatch;
  471. TCHAR* szTemp = NULL;
  472. LONG nFullPathBufSize = 0;
  473. LONG nFullPathReqBufSize = 0;
  474. LPTSTR szFullPath = NULL;
  475. LONG i;
  476. LONG NameLen = _tcslen(pContext->szName);
  477. LONG MatchFileLen;
  478. PSEARCHPATHPARTS pSearchPath;
  479. PSEARCHPATHPART pSearchPathPart;
  480. NTSTATUS Status;
  481. PFILEINFOCHAINITEM pFileInfoItem = NULL;
  482. PFILEINFOCHAINITEM pFileInfoItemList = NULL; // holds the list of matching files
  483. // which were found
  484. PFILEINFOCHAINITEM pFileInfoItemNext; // holds the next item in the list
  485. PVOID pFileInfo = NULL; // points to the current file's
  486. // information structure
  487. BOOL bDisableAttributeCache = FALSE; // will be set according to search
  488. TAGID tiName, tiTemp, tiMatchLogicNot;
  489. TCHAR* szMatchFile = NULL;
  490. HANDLE hFileHandle; // handle for the file we're checking, optimization
  491. LPVOID pImageBase; // pointer to the image
  492. DWORD dwImageSize = 0;
  493. WORD wDefaultMatchMode;
  494. //
  495. // Check context's flags
  496. //
  497. if (pContext->dwFlags & SEARCHDBF_NO_ATTRIBUTE_CACHE) {
  498. bDisableAttributeCache = TRUE;
  499. }
  500. //
  501. // Loop through matching criteria.
  502. //
  503. tiMatch = SdbFindFirstTag(pdb, tiExe, TAG_MATCHING_FILE);
  504. while (tiMatch != TAGID_NULL) {
  505. tiMatchLogicNot = SdbFindFirstTag(pdb, tiMatch, TAG_MATCH_LOGIC_NOT);
  506. bMatchLogicNot = (tiMatchLogicNot != TAGID_NULL);
  507. tiName = SdbFindFirstTag(pdb, tiMatch, TAG_NAME);
  508. if (!tiName) {
  509. goto out;
  510. }
  511. szTemp = SdbGetStringTagPtr(pdb, tiName);
  512. if (szTemp == NULL) {
  513. DBGPRINT((sdlError,
  514. "SdbpCheckForMatch",
  515. "Failed to get the string from the database.\n"));
  516. goto out;
  517. }
  518. if (szTemp[0] == TEXT('*')) {
  519. //
  520. // This is a signal that we should use the exe name.
  521. //
  522. szMatchFile = pContext->szName;
  523. MatchFileLen = NameLen;
  524. hFileHandle = pContext->hMainFile;
  525. pImageBase = pContext->pImageBase;
  526. dwImageSize = pContext->dwImageSize;
  527. } else {
  528. szMatchFile = szTemp;
  529. MatchFileLen = _tcslen(szMatchFile);
  530. hFileHandle = INVALID_HANDLE_VALUE;
  531. pImageBase = NULL;
  532. }
  533. //
  534. // When searching for files, we look in all process' exe directories,
  535. // starting with the current process and working backwards through the process
  536. // tree.
  537. //
  538. //
  539. // See that the context is good...
  540. //
  541. if (!(pContext->dwFlags & SEARCHDBF_INITIALIZED)) {
  542. if (!SdbpInitializeSearchDBContext(pContext)) {
  543. DBGPRINT((sdlError,
  544. "SdbpCheckForMatch",
  545. "Failed to initialize SEARCHDBCONTEXT.\n"));
  546. goto out;
  547. }
  548. }
  549. pSearchPath = pContext->pSearchParts;
  550. assert(pSearchPath != NULL);
  551. for (i = 0; i < (LONG)pSearchPath->PartCount && NULL == pFileInfo; ++i) {
  552. pSearchPathPart = &pSearchPath->Parts[i];
  553. //
  554. // There are two ways to specify a matching file: A relative path
  555. // from the EXE, or an absolute path. To specify an absolute path,
  556. // an environment variable (like "%systemroot%") must be used
  557. // as the base of the path. Therefore, we check for the first character
  558. // of the matching file to be % and if so, we assume that it is an
  559. // absolute path.
  560. //
  561. #ifndef KERNEL_MODE
  562. if (szMatchFile[0] == TEXT('%')) {
  563. //
  564. // Absolute path. Contains environment variables, get expanded size.
  565. //
  566. nFullPathReqBufSize = SdbExpandEnvironmentStrings(szMatchFile, NULL, 0);
  567. } else
  568. #endif // KERNEL_MODE
  569. {
  570. //
  571. // Relative path. Determine size of full path.
  572. //
  573. nFullPathReqBufSize = (pSearchPathPart->PartLength + MatchFileLen + 1) * sizeof(TCHAR);
  574. }
  575. if (nFullPathBufSize < nFullPathReqBufSize) {
  576. //
  577. // Need to realloc the buffer.
  578. //
  579. if (szFullPath == NULL) {
  580. nFullPathBufSize = _MAX_PATH * sizeof(TCHAR);
  581. if (nFullPathReqBufSize >= nFullPathBufSize) {
  582. nFullPathBufSize = nFullPathReqBufSize + EXTRA_BUF_SPACE;
  583. }
  584. } else {
  585. STACK_FREE(szFullPath);
  586. nFullPathBufSize = nFullPathReqBufSize + EXTRA_BUF_SPACE;
  587. }
  588. STACK_ALLOC(szFullPath, nFullPathBufSize);
  589. }
  590. if (szFullPath == NULL) {
  591. DBGPRINT((sdlError,
  592. "SdbpCheckForMatch",
  593. "Failed to allocate %d bytes for FullPath.\n",
  594. nFullPathBufSize));
  595. goto out;
  596. }
  597. #ifndef KERNEL_MODE
  598. if (szMatchFile[0] == TEXT('%')) {
  599. //
  600. // Absolute Path. Path contains environment variables, expand it.
  601. //
  602. if (!SdbExpandEnvironmentStrings(szMatchFile, szFullPath, nFullPathBufSize)) {
  603. DBGPRINT((sdlError,
  604. "SdbpCheckForMatch",
  605. "SdbExpandEnvironmentStrings failed to expand strings for %s.\n",
  606. szMatchFile));
  607. goto out;
  608. }
  609. } else
  610. #endif // KERNEL_MODE
  611. {
  612. //
  613. // Relative path. Concatenate EXE directory with specified relative path.
  614. //
  615. RtlMoveMemory(szFullPath,
  616. pSearchPathPart->pszPart,
  617. pSearchPathPart->PartLength * sizeof(TCHAR));
  618. RtlMoveMemory(szFullPath + pSearchPathPart->PartLength,
  619. szMatchFile,
  620. (MatchFileLen + 1) * sizeof(TCHAR));
  621. }
  622. pFileInfo = SdbGetFileInfo(hSDB,
  623. szFullPath,
  624. hFileHandle,
  625. pImageBase,
  626. dwImageSize, // this will be set ONLY if pImageBase != NULL
  627. bDisableAttributeCache);
  628. //
  629. // This is not a bug, attributes are cleaned up when the database
  630. // context is released.
  631. //
  632. }
  633. if (pFileInfo == NULL && !bMatchLogicNot) {
  634. DBGPRINT((sdlInfo,
  635. "SdbpCheckForMatch",
  636. "Matching file \"%s\" not found.\n",
  637. szMatchFile));
  638. goto out;
  639. }
  640. //
  641. // Create and store a new FILEINFOITEM on the stack
  642. //
  643. STACK_ALLOC(pFileInfoItem, sizeof(*pFileInfoItem));
  644. if (pFileInfoItem == NULL) {
  645. DBGPRINT((sdlError,
  646. "SdbpCheckForMatch",
  647. "Failed to allocate %d bytes for FILEINFOITEM\n",
  648. sizeof(*pFileInfoItem)));
  649. goto out;
  650. }
  651. pFileInfoItem->pFileInfo = pFileInfo;
  652. pFileInfoItem->tiMatch = tiMatch;
  653. pFileInfoItem->pNextItem = pFileInfoItemList;
  654. pFileInfoItemList = pFileInfoItem;
  655. //
  656. // We have the matching file.
  657. // Remember where it is for the second pass when we check all the file attributes.
  658. //
  659. tiMatch = SdbFindNextTag(pdb, tiExe, tiMatch);
  660. //
  661. // Reset the file matching. we don't touch this file again for now, it's info
  662. // is safely linked in pFileInfoItemList
  663. //
  664. pFileInfo = NULL;
  665. }
  666. //
  667. // We are still here. That means all the matching files have been found.
  668. // Check all the other attributes using fileinfoitemlist information.
  669. //
  670. pFileInfoItem = pFileInfoItemList;
  671. while (pFileInfoItem != NULL) {
  672. tiMatchLogicNot = SdbFindFirstTag(pdb, pFileInfoItem->tiMatch, TAG_MATCH_LOGIC_NOT);
  673. bMatchLogicNot = (tiMatchLogicNot != TAGID_NULL);
  674. if (pFileInfoItem->pFileInfo != NULL) {
  675. bAllAttributesMatch = SdbpCheckAllAttributes(hSDB,
  676. pdb,
  677. pFileInfoItem->tiMatch,
  678. pFileInfoItem->pFileInfo);
  679. } else {
  680. bAllAttributesMatch = FALSE;
  681. }
  682. if (bAllAttributesMatch && bMatchLogicNot) {
  683. DBGPRINT((sdlInfo,
  684. "SdbpCheckForMatch",
  685. "All attributes match, but LOGIC=\"NOT\" was used which negates the match.\n"));
  686. goto out;
  687. }
  688. if (!bAllAttributesMatch && !bMatchLogicNot) {
  689. //
  690. // Debug output happened inside SdbpCheckAllAttributes, no
  691. // need for further spew here.
  692. //
  693. goto out;
  694. }
  695. //
  696. // Advance to the next item.
  697. //
  698. pFileInfoItem = pFileInfoItem->pNextItem;
  699. }
  700. //
  701. // It's a match! get the match mode
  702. //
  703. if (pMatchMode) {
  704. //
  705. // Important: depending on a particular database, we may use a different mode if
  706. // there is match mode tag
  707. //
  708. // For Custom DB: default is the all-additive mode
  709. // For Main DB: default is normal mode
  710. //
  711. #ifndef KERNEL_MODE
  712. wDefaultMatchMode = SdbpIsMainPDB(hSDB, pdb) ? MATCHMODE_DEFAULT_MAIN :
  713. MATCHMODE_DEFAULT_CUSTOM;
  714. #else // KERNEL_MODE
  715. wDefaultMatchMode = MATCHMODE_DEFAULT_MAIN;
  716. #endif // KERNEL_MODE
  717. tiTemp = SdbFindFirstTag(pdb, tiExe, TAG_MATCH_MODE);
  718. if (tiTemp) {
  719. pMatchMode->dwMatchMode = SdbReadWORDTag(pdb, tiTemp, wDefaultMatchMode);
  720. } else {
  721. pMatchMode->dwMatchMode = wDefaultMatchMode;
  722. }
  723. }
  724. bReturn = TRUE;
  725. out:
  726. pFileInfoItem = pFileInfoItemList;
  727. while (pFileInfoItem != NULL) {
  728. pFileInfoItemNext = pFileInfoItem->pNextItem;
  729. if (pFileInfoItem->pFileInfo != NULL && bDisableAttributeCache) {
  730. SdbFreeFileInfo(pFileInfoItem->pFileInfo);
  731. }
  732. STACK_FREE(pFileInfoItem);
  733. pFileInfoItem = pFileInfoItemNext;
  734. }
  735. if (szFullPath != NULL) {
  736. STACK_FREE(szFullPath);
  737. }
  738. if (bReturn) {
  739. //
  740. // One last matching criteria: verify the entry is not disabled.
  741. //
  742. bReturn = SdbpIsExeEntryEnabled(pdb, tiExe, pGUID, pdwFlags);
  743. }
  744. return bReturn;
  745. }
  746. typedef enum _ADDITIVE_MODE {
  747. AM_NORMAL,
  748. AM_ADDITIVE_ONLY,
  749. AM_NO_ADDITIVE
  750. } ADDITIVE_MODE, *PADDITIVE_MODE;
  751. LPCTSTR
  752. SdbpFormatMatchModeType(
  753. DWORD dwMatchMode
  754. )
  755. {
  756. LPCTSTR pszMatchMode;
  757. switch (dwMatchMode) {
  758. case MATCH_ADDITIVE:
  759. pszMatchMode = _T("Additive");
  760. break;
  761. case MATCH_EXCLUSIVE:
  762. pszMatchMode = _T("Exclusive");
  763. break;
  764. case MATCH_NORMAL:
  765. pszMatchMode = _T("Normal");
  766. break;
  767. default:
  768. pszMatchMode = _T("Unknown");
  769. break;
  770. }
  771. return pszMatchMode;
  772. }
  773. LPCTSTR
  774. SdbpFormatMatchMode(
  775. PMATCHMODE pMatchMode
  776. )
  777. {
  778. static TCHAR szMatchMode[MAX_PATH];
  779. LPTSTR pszMatchMode = szMatchMode;
  780. int nChars = CHARCOUNT(szMatchMode);
  781. int nLen;
  782. nLen = _sntprintf(pszMatchMode,
  783. nChars,
  784. _T("0x%.2x%.2x [Mode: %s"),
  785. pMatchMode->Flags,
  786. pMatchMode->Type,
  787. SdbpFormatMatchModeType(pMatchMode->Type));
  788. if (nLen < 0) {
  789. goto eh;
  790. }
  791. nChars -= nLen;
  792. pszMatchMode += nLen;
  793. eh:
  794. //
  795. // Just in case, truncate
  796. //
  797. if (nLen < 0) {
  798. szMatchMode[CHARCOUNT(szMatchMode) - 1] = _T('\0');
  799. }
  800. return szMatchMode;
  801. }
  802. /*++
  803. SdbpCheckExe
  804. Checks a particular instance of an application in an SDB against for a match
  805. Information on the file is passed through pContext parameter
  806. result is returned in ptiExes
  807. --*/
  808. BOOL
  809. SdbpCheckExe(
  810. IN HSDB hSDB, //
  811. IN PDB pdb, //
  812. IN TAGID tiExe, // tag for an exe in the database
  813. IN OUT PDWORD pdwNumExes, // returns (and passes in) the number of accumulated exe matches
  814. IN OUT PSEARCHDBCONTEXT pContext, // information about the file which we match against
  815. IN ADDITIVE_MODE eMode, // target Match mode, we filter entries based on this parameter
  816. IN BOOL bDebug, // debug flag
  817. OUT PMATCHMODE pMatchMode, // returns match mode used if success
  818. OUT TAGID* ptiExes, // returns another entry in array of matched exes
  819. OUT GUID* pGUID, // matched exe id
  820. OUT DWORD* pdwFlags // matched exe flags
  821. )
  822. {
  823. BOOL bSuccess = FALSE;
  824. TAGID tiAppName = TAGID_NULL;
  825. LPTSTR szAppName = NULL;
  826. LPCTSTR pszMatchMode = NULL;
  827. TAGID tiRuntimePlatform;
  828. DWORD dwRuntimePlatform;
  829. TAGID tiOSSKU;
  830. DWORD dwOSSKU;
  831. TAGID tiSP;
  832. DWORD dwSPMask;
  833. MATCHMODE MatchMode;
  834. //
  835. // For debug purposes we'd like to know the name of the app, which
  836. // is more useful when the exe name is, say, AUTORUN.EXE or SETUP.EXE
  837. //
  838. tiAppName = SdbFindFirstTag(pdb, tiExe, TAG_APP_NAME);
  839. if (tiAppName != TAGID_NULL) {
  840. szAppName = SdbGetStringTagPtr(pdb, tiAppName);
  841. }
  842. DBGPRINT((sdlInfo, "SdbpCheckExe", "---------\n"));
  843. DBGPRINT((sdlInfo,
  844. "SdbpCheckExe",
  845. "Index entry found for App: \"%s\" Exe: \"%s\"\n",
  846. szAppName,
  847. pContext->szName));
  848. #ifndef KERNEL_MODE
  849. //
  850. // Check whether this exe is good for this platform first.
  851. //
  852. tiRuntimePlatform = SdbFindFirstTag(pdb, tiExe, TAG_RUNTIME_PLATFORM);
  853. if (tiRuntimePlatform) {
  854. dwRuntimePlatform = SdbReadDWORDTag(pdb, tiRuntimePlatform, RUNTIME_PLATFORM_ANY);
  855. //
  856. // Check for the platform match
  857. //
  858. if (!SdbpCheckRuntimePlatform(hSDB, szAppName, dwRuntimePlatform)) {
  859. //
  860. // Not the right platform. Debug spew would have occured in SdbpCheckRuntimePlatform
  861. //
  862. goto out;
  863. }
  864. }
  865. tiOSSKU = SdbFindFirstTag(pdb, tiExe, TAG_OS_SKU);
  866. if (tiOSSKU) {
  867. dwOSSKU = SdbReadDWORDTag(pdb, tiOSSKU, OS_SKU_ALL);
  868. if (dwOSSKU != OS_SKU_ALL) {
  869. PSDBCONTEXT pDBContext = (PSDBCONTEXT)hSDB;
  870. //
  871. // Check for the OS SKU match
  872. //
  873. if (!(dwOSSKU & pDBContext->dwOSSKU)) {
  874. DBGPRINT((sdlInfo,
  875. "SdbpCheckExe",
  876. "OS SKU Mismatch for \"%s\" Database(0x%lx) vs 0x%lx\n",
  877. (szAppName ? szAppName : TEXT("Unknown")),
  878. dwOSSKU,
  879. pDBContext->dwOSSKU));
  880. goto out;
  881. }
  882. }
  883. }
  884. tiSP = SdbFindFirstTag(pdb, tiExe, TAG_OS_SERVICE_PACK);
  885. if (tiSP) {
  886. dwSPMask = SdbReadDWORDTag(pdb, tiSP, 0xFFFFFFFF);
  887. if (dwSPMask != 0xFFFFFFFF) {
  888. PSDBCONTEXT pDBContext = (PSDBCONTEXT)hSDB;
  889. //
  890. // Check for the OS SKU match
  891. //
  892. if (!(dwSPMask & pDBContext->dwSPMask)) {
  893. DBGPRINT((sdlInfo,
  894. "SdbpCheckExe",
  895. "OS SP Mismatch for \"%s\" Database(0x%lx) vs 0x%lx\n",
  896. (szAppName ? szAppName : TEXT("Unknown")),
  897. dwSPMask,
  898. pDBContext->dwSPMask));
  899. goto out;
  900. }
  901. }
  902. }
  903. #endif // KERNEL_MODE
  904. if (!SdbpCheckForMatch(hSDB, pdb, tiExe, pContext, &MatchMode, pGUID, pdwFlags)) {
  905. goto out;
  906. }
  907. if (eMode == AM_ADDITIVE_ONLY && MatchMode.Type != MATCH_ADDITIVE) {
  908. goto out;
  909. }
  910. if (eMode == AM_NO_ADDITIVE && MatchMode.Type == MATCH_ADDITIVE) {
  911. goto out;
  912. }
  913. pszMatchMode = SdbpFormatMatchMode(&MatchMode);
  914. //
  915. // If we're in debug mode, don't actually put the ones we find on the
  916. // list, just put up an error.
  917. //
  918. if (bDebug) {
  919. //
  920. // We are in debug mode, do not add the match
  921. //
  922. DBGPRINT((sdlError,
  923. "SdbpCheckExe",
  924. "-----------------------------------------------------\n"));
  925. DBGPRINT((sdlError|sdlLogPipe,
  926. "SdbpCheckExe",
  927. "!!!! Multiple matches! App: '%s', Exe: '%s', Mode: %s\n",
  928. hSDB, // so that the pipe would use hPipe if needed
  929. szAppName,
  930. pContext->szName,
  931. pszMatchMode));
  932. DBGPRINT((sdlError,
  933. "SdbpCheckExe",
  934. "-----------------------------------------------------\n"));
  935. } else {
  936. DBGPRINT((sdlWarning|sdlLogPipe,
  937. "SdbpCheckExe",
  938. "++++ Successful match for App: '%s', Exe: '%s', Mode: %s\n",
  939. hSDB,
  940. szAppName,
  941. pContext->szName,
  942. pszMatchMode));
  943. //
  944. // If this is an exclusive match, kill anything we've found up to now
  945. //
  946. if (MatchMode.Type == MATCH_EXCLUSIVE) {
  947. RtlZeroMemory(ptiExes, sizeof(TAGID) * SDB_MAX_EXES);
  948. *pdwNumExes = 0;
  949. }
  950. //
  951. // Save this match on the list
  952. //
  953. ptiExes[*pdwNumExes] = tiExe;
  954. (*pdwNumExes)++;
  955. bSuccess = TRUE;
  956. }
  957. out:
  958. //
  959. // In case of success, return match mode information
  960. //
  961. if (bSuccess && pMatchMode != NULL) {
  962. pMatchMode->dwMatchMode = MatchMode.dwMatchMode;
  963. }
  964. return bSuccess;
  965. }
  966. DWORD
  967. SdbpSearchDB(
  968. IN HSDB hSDB,
  969. IN PDB pdb, // pdb to search in
  970. IN TAG tiSearchTag, // OPTIONAL - target tag (TAG_EXE or TAG_APPHELP_EXE)
  971. IN PSEARCHDBCONTEXT pContext,
  972. OUT TAGID* ptiExes, // caller needs to provide array of size SDB_MAX_EXES
  973. OUT GUID* pLastExeGUID,
  974. OUT DWORD* pLastExeFlags,
  975. OUT PMATCHMODE pMatchMode // reason why we stopped scanning
  976. )
  977. /*++
  978. Return: TAGID of found EXE record, TAGID_NULL if not found.
  979. Desc: This function searches a given shimDB for any EXEs with the given filename.
  980. If it finds one, it checks all the MATCHING_FILE records by
  981. calling SdbpCheckForMatch.
  982. If any EXEs are found, the number of EXEs found is returned in ptiExes.
  983. If not, it returns 0.
  984. when we get the matching mode out of the particular exe -- it is checked
  985. to see whether we need to continue and then this matching mode is returned
  986. It will never return more than SDB_MAX_EXES EXE entries.
  987. Debug Output is controlled by three factors
  988. -- a global one (controlled via the ifdef DBG), TRUE on checked builds
  989. -- a pipe handle in hSDB which is activated when we init the context
  990. -- a local variable that is set when we are in one of the conditions above
  991. when the variable bDebug is set -- we do not actually store the matches
  992. --*/
  993. {
  994. TAGID tiDatabase, tiExe;
  995. FIND_INFO FindInfo;
  996. TAGID tiAppName = TAGID_NULL;
  997. TCHAR* szAppName = _T("(unknown)");
  998. BOOL bUsingIndex = FALSE;
  999. DWORD dwNumExes = 0;
  1000. DWORD dwMatchMode = MATCH_NORMAL;
  1001. DWORD i;
  1002. DWORD dwAdditiveMode = MATCH_NORMAL;
  1003. BOOL bDebug = FALSE;
  1004. BOOL bMultiple = FALSE;
  1005. BOOL bSuccess = FALSE;
  1006. MATCHMODE MatchMode; // internal match mode
  1007. MATCHMODE MatchModeExe;
  1008. #ifndef KERNEL_MODE
  1009. if (pMatchMode) {
  1010. MatchMode.dwMatchMode = pMatchMode->dwMatchMode;
  1011. } else {
  1012. MatchMode.dwMatchMode = SdbpIsMainPDB(hSDB, pdb) ? MATCHMODE_DEFAULT_MAIN :
  1013. MATCHMODE_DEFAULT_CUSTOM;
  1014. }
  1015. #else // KERNEL_MODE
  1016. MatchMode.dwMatchMode = MATCHMODE_DEFAULT_MAIN;
  1017. #endif
  1018. if (!tiSearchTag) {
  1019. tiSearchTag = TAG_EXE;
  1020. }
  1021. //
  1022. // ADDITIVE MATCHES -- wildcards
  1023. //
  1024. if (tiSearchTag == TAG_EXE && SdbIsIndexAvailable(pdb, TAG_EXE, TAG_WILDCARD_NAME)) {
  1025. tiExe = SdbpFindFirstIndexedWildCardTag(pdb,
  1026. TAG_EXE,
  1027. TAG_WILDCARD_NAME,
  1028. pContext->szName,
  1029. &FindInfo);
  1030. while (tiExe != TAGID_NULL) {
  1031. bSuccess = SdbpCheckExe(hSDB,
  1032. pdb,
  1033. tiExe,
  1034. &dwNumExes,
  1035. pContext,
  1036. AM_ADDITIVE_ONLY, // match mode we request for this db
  1037. bDebug,
  1038. &MatchModeExe, // this is the matched tag from the db
  1039. ptiExes,
  1040. pLastExeGUID,
  1041. pLastExeFlags);
  1042. if (bSuccess) {
  1043. if (bDebug) {
  1044. bMultiple = TRUE; // if bDebug is set -- we already seen a match
  1045. } else {
  1046. //
  1047. // We got a match, update the state and make decision on whether to continue
  1048. //
  1049. MatchMode = MatchModeExe;
  1050. if (MatchModeExe.Type != MATCH_ADDITIVE) {
  1051. bDebug = (g_bDBG || SDBCONTEXT_IS_INSTRUMENTED(hSDB));
  1052. if (!bDebug) {
  1053. goto out;
  1054. }
  1055. }
  1056. }
  1057. }
  1058. tiExe = SdbpFindNextIndexedWildCardTag(pdb, &FindInfo);
  1059. }
  1060. }
  1061. //
  1062. // Normal EXEs
  1063. //
  1064. bUsingIndex = SdbIsIndexAvailable(pdb, tiSearchTag, TAG_NAME);
  1065. if (bUsingIndex) {
  1066. //
  1067. // Look in the index.
  1068. //
  1069. tiExe = SdbFindFirstStringIndexedTag(pdb,
  1070. tiSearchTag,
  1071. TAG_NAME,
  1072. pContext->szName,
  1073. &FindInfo);
  1074. if (tiExe == TAGID_NULL) {
  1075. DBGPRINT((sdlInfo,
  1076. "SdbpSearchDB",
  1077. "SdbFindFirstStringIndexedTag failed to locate exe: \"%s\".\n",
  1078. pContext->szName));
  1079. }
  1080. } else {
  1081. //
  1082. // Searching without an index...
  1083. //
  1084. DBGPRINT((sdlInfo, "SdbpSearchDB", "Searching database with no index.\n"));
  1085. //
  1086. // First get the DATABASE
  1087. //
  1088. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  1089. if (tiDatabase != TAGID_NULL) {
  1090. DBGPRINT((sdlError, "SdbpSearchDB", "No DATABASE tag found.\n"));
  1091. goto out;
  1092. }
  1093. //
  1094. // Then get the first EXE.
  1095. //
  1096. tiExe = SdbFindFirstNamedTag(pdb, tiDatabase, tiSearchTag, TAG_NAME, pContext->szName);
  1097. }
  1098. while (tiExe != TAGID_NULL) {
  1099. bSuccess = SdbpCheckExe(hSDB,
  1100. pdb,
  1101. tiExe,
  1102. &dwNumExes,
  1103. pContext,
  1104. AM_NORMAL,
  1105. bDebug,
  1106. &MatchModeExe,
  1107. ptiExes,
  1108. pLastExeGUID,
  1109. pLastExeFlags);
  1110. if (bSuccess) {
  1111. if (bDebug) {
  1112. bMultiple = TRUE; // if bDebug is set -- we already seen a match
  1113. } else {
  1114. //
  1115. // We got a match, update the state and make decision on whether to continue
  1116. // if we're not additive, we may go into debug mode
  1117. //
  1118. MatchMode = MatchModeExe;
  1119. if (MatchModeExe.Type != MATCH_ADDITIVE) {
  1120. bDebug = (g_bDBG || SDBCONTEXT_IS_INSTRUMENTED(hSDB));
  1121. if (!bDebug) {
  1122. goto out;
  1123. }
  1124. }
  1125. }
  1126. }
  1127. if (bUsingIndex) {
  1128. tiExe = SdbFindNextStringIndexedTag(pdb, &FindInfo);
  1129. } else {
  1130. tiExe = SdbpFindNextNamedTag(pdb, tiDatabase, tiExe, TAG_NAME, pContext->szName);
  1131. }
  1132. }
  1133. #ifndef KERNEL_MODE
  1134. //
  1135. // Now we search by module name, if one is available
  1136. // this case falls into 16-bit flags category
  1137. //
  1138. if (tiSearchTag == TAG_EXE && pContext->szModuleName) {
  1139. bUsingIndex = SdbIsIndexAvailable(pdb, tiSearchTag, TAG_16BIT_MODULE_NAME);
  1140. if (bUsingIndex) {
  1141. //
  1142. // Look in the index.
  1143. //
  1144. tiExe = SdbFindFirstStringIndexedTag(pdb,
  1145. tiSearchTag,
  1146. TAG_16BIT_MODULE_NAME,
  1147. pContext->szModuleName,
  1148. &FindInfo);
  1149. if (tiExe == TAGID_NULL) {
  1150. DBGPRINT((sdlInfo,
  1151. "SdbpSearchDB",
  1152. "SdbFindFirstStringIndexedTag failed to locate exe (MODNAME): \"%s\".\n",
  1153. pContext->szModuleName));
  1154. }
  1155. } else {
  1156. //
  1157. // Searching without an index...
  1158. //
  1159. DBGPRINT((sdlInfo, "SdbpSearchDB", "Searching database with no index.\n"));
  1160. //
  1161. // First get the DATABASE
  1162. //
  1163. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  1164. if (tiDatabase != TAGID_NULL) {
  1165. DBGPRINT((sdlError, "SdbpSearchDB", "No DATABASE tag found.\n"));
  1166. goto out;
  1167. }
  1168. //
  1169. // Then get the first EXE.
  1170. //
  1171. tiExe = SdbFindFirstNamedTag(pdb,
  1172. tiDatabase,
  1173. tiSearchTag,
  1174. TAG_16BIT_MODULE_NAME,
  1175. pContext->szModuleName);
  1176. }
  1177. while (tiExe != TAGID_NULL) {
  1178. bSuccess = SdbpCheckExe(hSDB,
  1179. pdb,
  1180. tiExe,
  1181. &dwNumExes,
  1182. pContext,
  1183. AM_NORMAL,
  1184. bDebug,
  1185. &MatchModeExe,
  1186. ptiExes,
  1187. pLastExeGUID,
  1188. pLastExeFlags);
  1189. if (bSuccess) {
  1190. if (bDebug) {
  1191. bMultiple = TRUE; // if bDebug is set -- we already seen a match
  1192. } else {
  1193. //
  1194. // We got a match, update the state and make decision on whether to continue
  1195. //
  1196. MatchMode = MatchModeExe;
  1197. if (MatchModeExe.Type != MATCH_ADDITIVE) {
  1198. bDebug = (g_bDBG || SDBCONTEXT_IS_INSTRUMENTED(hSDB));
  1199. if (!bDebug) {
  1200. goto out;
  1201. }
  1202. }
  1203. }
  1204. }
  1205. if (bUsingIndex) {
  1206. tiExe = SdbFindNextStringIndexedTag(pdb, &FindInfo);
  1207. } else {
  1208. tiExe = SdbpFindNextNamedTag(pdb,
  1209. tiDatabase,
  1210. tiExe,
  1211. TAG_16BIT_MODULE_NAME,
  1212. pContext->szModuleName);
  1213. }
  1214. }
  1215. }
  1216. #endif // KERNEL_MODE
  1217. //
  1218. // Now check for wild-card non-additive exes.
  1219. //
  1220. if (tiSearchTag == TAG_EXE && SdbIsIndexAvailable(pdb, TAG_EXE, TAG_WILDCARD_NAME)) {
  1221. tiExe = SdbpFindFirstIndexedWildCardTag(pdb,
  1222. TAG_EXE,
  1223. TAG_WILDCARD_NAME,
  1224. pContext->szName,
  1225. &FindInfo);
  1226. while (tiExe != TAGID_NULL) {
  1227. bSuccess = SdbpCheckExe(hSDB,
  1228. pdb,
  1229. tiExe,
  1230. &dwNumExes,
  1231. pContext,
  1232. AM_NO_ADDITIVE,
  1233. bDebug,
  1234. &MatchModeExe,
  1235. ptiExes,
  1236. pLastExeGUID,
  1237. pLastExeFlags);
  1238. if (bSuccess) {
  1239. if (bDebug) {
  1240. bMultiple = TRUE; // if bDebug is set -- we already seen a match
  1241. } else {
  1242. //
  1243. // we got a match, update the state and make decision on whether to continue
  1244. //
  1245. MatchMode = MatchModeExe;
  1246. if (MatchModeExe.Type != MATCH_ADDITIVE) {
  1247. bDebug = (g_bDBG || SDBCONTEXT_IS_INSTRUMENTED(hSDB));
  1248. if (!bDebug) {
  1249. goto out;
  1250. }
  1251. }
  1252. }
  1253. }
  1254. tiExe = SdbpFindNextIndexedWildCardTag(pdb, &FindInfo);
  1255. }
  1256. }
  1257. out:
  1258. //
  1259. // Now report the final resolution of the match.
  1260. //
  1261. for (i = 0; i < dwNumExes; ++i) {
  1262. tiAppName = SdbFindFirstTag(pdb, ptiExes[i], TAG_APP_NAME);
  1263. if (tiAppName != TAGID_NULL) {
  1264. szAppName = SdbGetStringTagPtr(pdb, tiAppName);
  1265. } else {
  1266. szAppName = _T("(Unknown)");
  1267. }
  1268. DBGPRINT((sdlWarning,
  1269. "SdbpSearchDB",
  1270. "--------------------------------------------------------\n"));
  1271. DBGPRINT((sdlWarning|sdlLogPipe,
  1272. "SdbpSearchDB",
  1273. "+ Final match is App: \"%s\", exe: \"%s\".\n",
  1274. hSDB,
  1275. szAppName,
  1276. pContext->szName));
  1277. DBGPRINT((sdlWarning,
  1278. "SdbpSearchDB",
  1279. "--------------------------------------------------------\n"));
  1280. }
  1281. if (bMultiple) {
  1282. DBGPRINT((sdlError,
  1283. "SdbpSearchDB",
  1284. "--------------------------------------------------------\n"));
  1285. DBGPRINT((sdlError|sdlLogPipe,
  1286. "SdbpSearchDB",
  1287. "!!!!!!! Multiple non-additive matches. !!!!!\n",
  1288. hSDB));
  1289. DBGPRINT((sdlError,
  1290. "SdbpSearchDB",
  1291. "--------------------------------------------------------\n"));
  1292. }
  1293. if (pMatchMode != NULL) {
  1294. pMatchMode->dwMatchMode = MatchMode.dwMatchMode;
  1295. }
  1296. return dwNumExes;
  1297. }
  1298. TAGREF
  1299. SdbGetDatabaseMatch(
  1300. IN HSDB hSDB,
  1301. IN LPCTSTR szPath,
  1302. IN HANDLE FileHandle OPTIONAL,
  1303. IN LPVOID pImageBase OPTIONAL,
  1304. IN DWORD dwImageSize OPTIONAL
  1305. )
  1306. /*++
  1307. Return: BUGBUG: ?
  1308. Desc: BUGBUG: ?
  1309. --*/
  1310. {
  1311. SEARCHDBCONTEXT Context;
  1312. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  1313. TAGID tiExe = TAGID_NULL;
  1314. TAGID atiExes[SDB_MAX_EXES];
  1315. TAGREF trExe = TAGREF_NULL;
  1316. DWORD dwNumExes = 0;
  1317. GUID guid;
  1318. DWORD dwFlags = 0;
  1319. assert(pSdbContext->pdbMain && szPath);
  1320. RtlZeroMemory(&Context, sizeof(Context)); // do this so that we don't trip later
  1321. RtlZeroMemory(atiExes, sizeof(atiExes));
  1322. Context.dwFlags |= (SEARCHDBF_NO_PROCESS_HISTORY | SEARCHDBF_NO_ATTRIBUTE_CACHE);
  1323. if (FileHandle != INVALID_HANDLE_VALUE || pImageBase != NULL) {
  1324. Context.dwFlags |= SEARCHDBF_NO_LFN;
  1325. }
  1326. Context.hMainFile = FileHandle; // used to optimize attribute retrieval
  1327. Context.pImageBase = pImageBase; // this will be used and not a file handle
  1328. Context.dwImageSize = dwImageSize; // size of the image
  1329. DBGPRINT((sdlInfo, "SdbGetDatabaseMatch", "Looking for \"%s\"\n", szPath));
  1330. //
  1331. // Create search db context, no process history needed.
  1332. //
  1333. if (!SdbpCreateSearchDBContext(&Context, szPath, NULL, NULL)) {
  1334. DBGPRINT((sdlError,
  1335. "SdbGetDatabaseMatch",
  1336. "Failed to create search DB context.\n"));
  1337. goto out;
  1338. }
  1339. //
  1340. // We will be searching the main db
  1341. //
  1342. dwNumExes = SdbpSearchDB(pSdbContext,
  1343. pSdbContext->pdbMain,
  1344. TAG_EXE,
  1345. &Context,
  1346. atiExes,
  1347. &guid,
  1348. &dwFlags,
  1349. NULL);
  1350. //
  1351. // Convert to TAGREF
  1352. //
  1353. if (dwNumExes) {
  1354. //
  1355. // Always use the last exe in the list, as it will be the most specific
  1356. //
  1357. tiExe = atiExes[dwNumExes - 1];
  1358. if (!SdbTagIDToTagRef(hSDB, pSdbContext->pdbMain, tiExe, &trExe)) {
  1359. DBGPRINT((sdlError,
  1360. "SdbGetDatabaseMatch",
  1361. "Failed to convert tagid to tagref\n"));
  1362. goto out;
  1363. }
  1364. }
  1365. out:
  1366. SdbpReleaseSearchDBContext(&Context);
  1367. return trExe;
  1368. }
  1369. DWORD
  1370. SdbQueryData(
  1371. IN HSDB hSDB, // database handle
  1372. IN TAGREF trExe, // tagref of the matching exe
  1373. IN LPCTSTR lpszDataName, // if this is null, will try to return all the policy names
  1374. OUT LPDWORD lpdwDataType, // pointer to data type (REG_SZ, REG_BINARY, etc)
  1375. OUT LPVOID lpBuffer, // buffer to fill with information
  1376. IN OUT LPDWORD lpdwBufferSize // pointer to buffer size
  1377. )
  1378. {
  1379. return SdbQueryDataEx(hSDB, trExe, lpszDataName, lpdwDataType, lpBuffer, lpdwBufferSize, NULL);
  1380. }
  1381. DWORD
  1382. SdbQueryDataExTagID(
  1383. IN PDB pdb, // database handle
  1384. IN TAGID tiExe, // tagref of the matching exe
  1385. IN LPCTSTR lpszDataName, // if this is null, will try to return all the policy names
  1386. OUT LPDWORD lpdwDataType, // pointer to data type (REG_SZ, REG_BINARY, etc)
  1387. OUT LPVOID lpBuffer, // buffer to fill with information
  1388. IN OUT LPDWORD lpdwBufferSize, // pointer to buffer size
  1389. OUT TAGID* ptiData // optional pointer to the retrieved data tag
  1390. )
  1391. /*++
  1392. Return: Error code or ERROR_SUCCESS if successful
  1393. Desc: See complete description with sample code
  1394. in doc subdirectory
  1395. --*/
  1396. {
  1397. TAGID tiData;
  1398. BOOL bSuccess;
  1399. TAGID tiParent;
  1400. TAGID tiName;
  1401. TAGID tiValue;
  1402. TAGID tiValueType;
  1403. DWORD cbSize;
  1404. DWORD dwValueType;
  1405. LPCTSTR pszName;
  1406. LPTSTR pszNameBuffer = NULL;
  1407. LPTSTR pSlash;
  1408. LPTSTR pchBuffer;
  1409. DWORD dwData;
  1410. TAG tData;
  1411. ULONGLONG ullData;
  1412. LPVOID lpValue;
  1413. DWORD Status = ERROR_NOT_SUPPORTED; // have it initialized
  1414. if (lpszDataName == NULL) {
  1415. if (lpdwBufferSize == NULL) {
  1416. Status = ERROR_INVALID_PARAMETER;
  1417. goto ErrHandle;
  1418. }
  1419. cbSize = 0;
  1420. tiData = SdbFindFirstTag(pdb, tiExe, TAG_DATA);
  1421. if (!tiData) {
  1422. //
  1423. // Bad entry.
  1424. //
  1425. DBGPRINT((sdlError,
  1426. "SdbQueryDataExTagID",
  1427. "The entry 0x%x does not appear to have data\n",
  1428. tiExe));
  1429. Status = ERROR_INTERNAL_DB_CORRUPTION;
  1430. goto ErrHandle;
  1431. }
  1432. while (tiData) {
  1433. //
  1434. // Pass one: Calculate the size needed.
  1435. //
  1436. tiName = SdbFindFirstTag(pdb, tiData, TAG_NAME);
  1437. if (!tiName) {
  1438. DBGPRINT((sdlError,
  1439. "SdbQueryDataExTagID",
  1440. "The entry 0x%x does not contain a name tag\n",
  1441. tiData));
  1442. Status = ERROR_INTERNAL_DB_CORRUPTION;
  1443. goto ErrHandle;
  1444. }
  1445. pszName = SdbGetStringTagPtr(pdb, tiName);
  1446. if (!pszName) {
  1447. DBGPRINT((sdlError,
  1448. "SdbQueryDataExTagID",
  1449. "The entry 0x%x contains NULL name\n",
  1450. tiName));
  1451. Status = ERROR_INTERNAL_DB_CORRUPTION;
  1452. goto ErrHandle;
  1453. }
  1454. cbSize += (_tcslen(pszName) + 1) * sizeof(*pszName);
  1455. tiData = SdbFindNextTag(pdb, tiExe, tiData);
  1456. }
  1457. cbSize += sizeof(*pszName); // for the final 0
  1458. //
  1459. // We are done, compare the size.
  1460. //
  1461. if (lpBuffer == NULL || *lpdwBufferSize < cbSize) {
  1462. *lpdwBufferSize = cbSize;
  1463. Status = ERROR_INSUFFICIENT_BUFFER;
  1464. goto ErrHandle;
  1465. }
  1466. //
  1467. // lpBuffer != NULL here and there is enough room
  1468. //
  1469. pchBuffer = (LPTSTR)lpBuffer;
  1470. tiData = SdbFindFirstTag(pdb, tiExe, TAG_DATA);
  1471. while (tiData) {
  1472. tiName = SdbFindFirstTag(pdb, tiData, TAG_NAME);
  1473. if (tiName) {
  1474. pszName = SdbGetStringTagPtr(pdb, tiName);
  1475. if (pszName) {
  1476. _tcscpy(pchBuffer, pszName);
  1477. pchBuffer += _tcslen(pchBuffer) + 1;
  1478. }
  1479. }
  1480. tiData = SdbFindNextTag(pdb, tiExe, tiData);
  1481. }
  1482. //
  1483. // The buffer has been filled, terminate.
  1484. //
  1485. *pchBuffer++ = TEXT('\0');
  1486. //
  1487. // Save the size written to the buffer
  1488. //
  1489. *lpdwBufferSize = (DWORD)((ULONG_PTR)pchBuffer - (ULONG_PTR)lpBuffer);
  1490. //
  1491. // Save data type
  1492. //
  1493. if (lpdwDataType != NULL) {
  1494. *lpdwDataType = REG_MULTI_SZ;
  1495. }
  1496. return ERROR_SUCCESS;
  1497. }
  1498. //
  1499. // In this case we allow the query to proceed if
  1500. // the buffer is null and lpdwBufferSize is not null or lpBufferSize is not null
  1501. //
  1502. if (lpBuffer == NULL && lpdwBufferSize == NULL) {
  1503. DBGPRINT((sdlError,
  1504. "SdbQueryDataExTagID",
  1505. "One of lpBuffer or lpdwBufferSize should not be null\n"));
  1506. Status = ERROR_INVALID_PARAMETER;
  1507. goto ErrHandle;
  1508. }
  1509. //
  1510. // Expect the name to be in format "name1\name2..."
  1511. //
  1512. STACK_ALLOC(pszNameBuffer, (_tcslen(lpszDataName) + 1) * sizeof(*pszNameBuffer));
  1513. if (pszNameBuffer == NULL) {
  1514. DBGPRINT((sdlError,
  1515. "SdbQueryDataExTagID",
  1516. "Cannot allocate temporary buffer for parsing the name \"%s\"\n",
  1517. lpszDataName));
  1518. Status = ERROR_NOT_ENOUGH_MEMORY;
  1519. goto ErrHandle;
  1520. }
  1521. tiParent = tiExe;
  1522. tiData = TAGID_NULL;
  1523. do {
  1524. pSlash = _tcschr(lpszDataName, TEXT('\\'));
  1525. if (pSlash == NULL) {
  1526. _tcscpy(pszNameBuffer, lpszDataName);
  1527. lpszDataName = NULL;
  1528. } else {
  1529. _tcsncpy(pszNameBuffer, lpszDataName, pSlash - lpszDataName);
  1530. pszNameBuffer[pSlash - lpszDataName] = TEXT('\0');
  1531. lpszDataName = pSlash + 1; // go to the next char
  1532. }
  1533. tiData = SdbFindFirstNamedTag(pdb, tiParent, TAG_DATA, TAG_NAME, pszNameBuffer);
  1534. tiParent = tiData;
  1535. } while (lpszDataName != NULL && *lpszDataName != TEXT('\0') && tiData != TAGID_NULL);
  1536. if (!tiData) {
  1537. DBGPRINT((sdlError,
  1538. "SdbQueryDataExTagID",
  1539. "The entry \"%s\" not found\n",
  1540. pszNameBuffer));
  1541. Status = ERROR_NOT_FOUND;
  1542. goto ErrHandle;
  1543. }
  1544. //
  1545. // Looks like we found the entry, query value type
  1546. //
  1547. dwValueType = REG_NONE;
  1548. tiValueType = SdbFindFirstTag(pdb, tiData, TAG_DATA_VALUETYPE);
  1549. if (!tiValueType) {
  1550. DBGPRINT((sdlWarning,
  1551. "SdbQueryDataExTagID",
  1552. "The entry 0x%x does not have valuetype information\n",
  1553. tiData));
  1554. } else {
  1555. dwValueType = SdbReadDWORDTag(pdb, tiValueType, REG_NONE);
  1556. }
  1557. cbSize = 0;
  1558. lpValue = NULL;
  1559. if (dwValueType != REG_NONE) {
  1560. //
  1561. // Find data tag
  1562. //
  1563. cbSize = 0;
  1564. switch (dwValueType) {
  1565. case REG_SZ:
  1566. //
  1567. // string data
  1568. //
  1569. tData = TAG_DATA_STRING;
  1570. break;
  1571. case REG_DWORD:
  1572. tData = TAG_DATA_DWORD;
  1573. break;
  1574. case REG_QWORD:
  1575. tData = TAG_DATA_QWORD;
  1576. break;
  1577. case REG_BINARY:
  1578. tData = TAG_DATA_BITS;
  1579. break;
  1580. default:
  1581. DBGPRINT((sdlError,
  1582. "SdbQueryDataExTagID",
  1583. "The entry 0x%x contains bad valuetype information 0x%x\n",
  1584. tiData,
  1585. dwValueType));
  1586. Status = ERROR_INTERNAL_DB_CORRUPTION;
  1587. goto ErrHandle;
  1588. break;
  1589. }
  1590. tiValue = SdbFindFirstTag(pdb, tiData, tData);
  1591. //
  1592. // Find what the data size is if needed
  1593. //
  1594. if (!tiValue) {
  1595. DBGPRINT((sdlWarning,
  1596. "SdbQueryDataExTagID",
  1597. "The entry 0x%x contains no value\n",
  1598. tiData));
  1599. Status = ERROR_NOT_FOUND;
  1600. goto ErrHandle;
  1601. }
  1602. //
  1603. // For those who have no size quite yet...
  1604. // (binary and a string)
  1605. //
  1606. switch (dwValueType) {
  1607. case REG_SZ:
  1608. pchBuffer = SdbGetStringTagPtr(pdb, tiValue);
  1609. if (pchBuffer == NULL) {
  1610. DBGPRINT((sdlWarning,
  1611. "SdbQueryDataExTagID",
  1612. "The entry 0x%x contains bad string value 0x%x\n",
  1613. tiData,
  1614. tiValue));
  1615. Status = ERROR_NOT_FOUND;
  1616. goto ErrHandle;
  1617. }
  1618. cbSize = (_tcslen(pchBuffer) + 1) * sizeof(*pchBuffer);
  1619. lpValue = (LPVOID)pchBuffer;
  1620. break;
  1621. case REG_BINARY:
  1622. cbSize = SdbGetTagDataSize(pdb, tiValue); // binary tag
  1623. lpValue = SdbpGetMappedTagData(pdb, tiValue);
  1624. if (lpValue == NULL) {
  1625. DBGPRINT((sdlWarning,
  1626. "SdbQueryDataExTagID",
  1627. "The entry 0x%x contains bad binary value 0x%x\n",
  1628. tiData,
  1629. tiValue));
  1630. Status = ERROR_NOT_FOUND;
  1631. goto ErrHandle;
  1632. }
  1633. break;
  1634. case REG_DWORD:
  1635. dwData = SdbReadDWORDTag(pdb, tiValue, 0);
  1636. cbSize = sizeof(dwData);
  1637. lpValue = (LPVOID)&dwData;
  1638. break;
  1639. case REG_QWORD:
  1640. ullData = SdbReadQWORDTag(pdb, tiValue, 0);
  1641. cbSize = sizeof(ullData);
  1642. lpValue = (LPVOID)&ullData;
  1643. break;
  1644. }
  1645. //
  1646. // At this point we have everything we need to get the pointer to data.
  1647. //
  1648. }
  1649. //
  1650. // Fix the output params and exit.
  1651. //
  1652. Status = ERROR_SUCCESS;
  1653. if (cbSize == 0) {
  1654. goto SkipCopy;
  1655. }
  1656. if (lpBuffer == NULL || (lpdwBufferSize != NULL && *lpdwBufferSize < cbSize)) {
  1657. Status = ERROR_INSUFFICIENT_BUFFER;
  1658. goto SkipCopy;
  1659. }
  1660. //
  1661. // Buffer size checked out, now if buffer exists -- copy
  1662. //
  1663. if (lpBuffer != NULL) {
  1664. RtlMoveMemory(lpBuffer, lpValue, cbSize);
  1665. }
  1666. SkipCopy:
  1667. if (lpdwBufferSize) {
  1668. *lpdwBufferSize = cbSize;
  1669. }
  1670. if (lpdwDataType) {
  1671. *lpdwDataType = dwValueType;
  1672. }
  1673. if (ptiData) {
  1674. *ptiData = tiData;
  1675. }
  1676. ErrHandle:
  1677. if (pszNameBuffer != NULL) {
  1678. STACK_FREE(pszNameBuffer);
  1679. }
  1680. return Status;
  1681. }
  1682. DWORD
  1683. SdbQueryDataEx(
  1684. IN HSDB hSDB, // database handle
  1685. IN TAGREF trExe, // tagref of the matching exe
  1686. IN LPCTSTR lpszDataName, // if this is null, will try to return all the policy names
  1687. OUT LPDWORD lpdwDataType, // pointer to data type (REG_SZ, REG_BINARY, etc)
  1688. OUT LPVOID lpBuffer, // buffer to fill with information
  1689. IN OUT LPDWORD lpdwBufferSize, // pointer to buffer size
  1690. OUT TAGREF* ptrData // optional pointer to the retrieved data tag
  1691. )
  1692. {
  1693. BOOL bSuccess;
  1694. PDB pdb = NULL;
  1695. TAGID tiExe = TAGID_NULL;
  1696. TAGID tiData;
  1697. NTSTATUS Status;
  1698. bSuccess = SdbTagRefToTagID(hSDB, trExe, &pdb, &tiExe);
  1699. if (!bSuccess) {
  1700. DBGPRINT((sdlError,
  1701. "SdbQueryDataEx",
  1702. "Failed to convert tagref 0x%x to tagid\n",
  1703. trExe));
  1704. Status = ERROR_INVALID_PARAMETER;
  1705. goto ErrHandle;
  1706. }
  1707. Status = SdbQueryDataExTagID(pdb,
  1708. tiExe,
  1709. lpszDataName,
  1710. lpdwDataType,
  1711. lpBuffer,
  1712. lpdwBufferSize,
  1713. &tiData);
  1714. //
  1715. // See that we convert the output param
  1716. //
  1717. if (ptrData != NULL && NT_SUCCESS(Status)) {
  1718. if (!SdbTagIDToTagRef(hSDB, pdb, tiData, ptrData)) {
  1719. Status = ERROR_INVALID_DATA;
  1720. }
  1721. }
  1722. ErrHandle:
  1723. return Status;
  1724. }
  1725. BOOL
  1726. SdbReadEntryInformation(
  1727. IN HSDB hSDB,
  1728. IN TAGREF trExe,
  1729. OUT PSDBENTRYINFO pEntryInfo
  1730. )
  1731. /*++
  1732. Return: BUGBUG: ?
  1733. Desc: BUGBUG: ?
  1734. --*/
  1735. {
  1736. BOOL bSuccess = FALSE;
  1737. TAGID tiExe;
  1738. TAGID tiData;
  1739. TAGID tiExeID;
  1740. TAGID tiPolicy;
  1741. TAGID tiRegPath;
  1742. PDB pdb;
  1743. SDBENTRYINFO EntryInfo;
  1744. RtlZeroMemory(&EntryInfo, sizeof(EntryInfo));
  1745. bSuccess = SdbTagRefToTagID(hSDB, trExe, &pdb, &tiExe);
  1746. if (!bSuccess) {
  1747. DBGPRINT((sdlError,
  1748. "SdbReadEntryInformation",
  1749. "Failed to convert tagref 0x%x to tagid\n",
  1750. trExe));
  1751. goto ErrHandle;
  1752. }
  1753. //
  1754. // Get the EXE's ID
  1755. //
  1756. tiExeID = SdbFindFirstTag(pdb, tiExe, TAG_EXE_ID);
  1757. if (tiExeID == TAGID_NULL) {
  1758. DBGPRINT((sdlError,
  1759. "SdbReadEntryInformation",
  1760. "Failed to read TAG_EXE_ID for tiExe 0x%x !\n",
  1761. tiExe));
  1762. goto ErrHandle;
  1763. }
  1764. bSuccess = SdbReadBinaryTag(pdb,
  1765. tiExeID,
  1766. (PBYTE)&EntryInfo.guidID,
  1767. sizeof(EntryInfo.guidID));
  1768. if (!bSuccess) {
  1769. DBGPRINT((sdlError,
  1770. "SdbReadEntryInformation",
  1771. "Failed to read GUID referenced by 0x%x\n",
  1772. tiExeID));
  1773. goto ErrHandle;
  1774. }
  1775. //
  1776. // Get the database id
  1777. //
  1778. if (!SdbGetDatabaseID(pdb, &EntryInfo.guidDB)) {
  1779. DBGPRINT((sdlError,
  1780. "SdbReadEntryInformation",
  1781. "Failed to read GUID of the database\n"));
  1782. goto ErrHandle;
  1783. }
  1784. //
  1785. // Retrieve entry flags as referenced by the registry
  1786. //
  1787. if (!SdbGetEntryFlags(&EntryInfo.guidID, &EntryInfo.dwFlags)) {
  1788. DBGPRINT((sdlWarning,
  1789. "SdbReadEntryInformation",
  1790. "No flags for tiExe 0x%x\n",
  1791. tiExe));
  1792. EntryInfo.dwFlags = 0;
  1793. } else {
  1794. DBGPRINT((sdlInfo,
  1795. "SdbReadEntryInformation",
  1796. "Retrieved flags for this app 0x%x.\n",
  1797. EntryInfo.dwFlags));
  1798. }
  1799. //
  1800. // Read the data tags
  1801. //
  1802. tiData = SdbFindFirstTag(pdb, tiExe, TAG_DATA);
  1803. EntryInfo.tiData = tiData;
  1804. if (tiData == TAGID_NULL) {
  1805. //
  1806. // This is not a data entry
  1807. //
  1808. DBGPRINT((sdlWarning,
  1809. "SdbReadEntryInformation",
  1810. "Entry tiExe 0x%x does not contain TAG_DATA.\n",
  1811. tiExe));
  1812. }
  1813. if (pEntryInfo != NULL) {
  1814. RtlMoveMemory(pEntryInfo, &EntryInfo, sizeof(*pEntryInfo));
  1815. }
  1816. bSuccess = TRUE;
  1817. ErrHandle:
  1818. return bSuccess;
  1819. }
  1820. //
  1821. // We may be compiled UNICODE or ANSI
  1822. // If we are compiled UNICODE we need to use UNICODE sprintf and convert
  1823. // the result back to ANSI for output with DbgPrint. This is accomplished
  1824. // by %ls format in DbgPrint. Format and Function name are always passed
  1825. // in as ANSI though. TCHAR strings are formatted just with %s
  1826. //
  1827. void
  1828. PrepareFormatForUnicode(
  1829. PCH fmtUnicode,
  1830. PCH format
  1831. )
  1832. {
  1833. PCH pfmt;
  1834. CHAR ch;
  1835. size_t nch;
  1836. long width;
  1837. PCH pend;
  1838. strcpy(fmtUnicode, format);
  1839. pfmt = fmtUnicode;
  1840. while('\0' != (ch = *pfmt++)) {
  1841. if (ch == '%') {
  1842. if (*pfmt == '%') {
  1843. continue;
  1844. }
  1845. //
  1846. // Skip the characters that relate to - + 0 ' ' #
  1847. //
  1848. nch = strspn(pfmt, "-+0 #");
  1849. pfmt += nch;
  1850. //
  1851. // Parse the width.
  1852. //
  1853. if (*pfmt == '*') {
  1854. //
  1855. // Parameter defines the width
  1856. //
  1857. ++pfmt;
  1858. } else {
  1859. //
  1860. // See whether we have width
  1861. //
  1862. if (isdigit(*pfmt)) {
  1863. pend = NULL;
  1864. width = atol(pfmt);
  1865. while (isdigit(*pfmt)) {
  1866. ++pfmt;
  1867. }
  1868. }
  1869. }
  1870. //
  1871. // Now we can have: .precision
  1872. //
  1873. if (*pfmt == '.') {
  1874. ++pfmt;
  1875. width = atol(pfmt);
  1876. while (isdigit(*pfmt)) {
  1877. ++pfmt;
  1878. }
  1879. }
  1880. //
  1881. // Now is the format (one of: h, l, L, I64)
  1882. //
  1883. ch = *pfmt;
  1884. pend = strchr("hlLNFw", ch);
  1885. if (pend != NULL) {
  1886. ++pfmt; // move past the modifier char
  1887. } else {
  1888. if (ch == 'I' && !strncpy(pfmt, "I64", 3)) {
  1889. pfmt += 3;
  1890. }
  1891. }
  1892. //
  1893. // We should have a type character here.
  1894. //
  1895. if (*pfmt == 's') {
  1896. //
  1897. // Convert to UPPER, making it UNICODE string with ansi vsnprintf
  1898. //
  1899. *pfmt = 'S';
  1900. }
  1901. //
  1902. // Move past the format char if we are not at the end
  1903. //
  1904. if (*pfmt != '\0') {
  1905. ++pfmt;
  1906. }
  1907. }
  1908. }
  1909. }