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.

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