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.

2436 lines
69 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. sdbapiplus.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. extern const TCHAR g_szProcessHistory[] = TEXT("__PROCESS_HISTORY");
  14. extern const TCHAR g_szCompatLayer[] = TEXT("__COMPAT_LAYER");
  15. extern const TCHAR g_szWhiteSpaceDelimiters[] = TEXT(" \t");
  16. #ifdef _DEBUG_SPEW
  17. extern DBGLEVELINFO g_rgDbgLevelInfo[];
  18. extern PCH g_szDbgLevelUser;
  19. #endif // _DEBUG_SPEW
  20. LPTSTR
  21. SdbpGetLayerFlags(
  22. IN LPTSTR pszLayerString,
  23. OUT DWORD* pdwLayerFlags
  24. )
  25. /*++
  26. Return: Beginning of the layer string after the special characters used to
  27. indicate the layer flags.
  28. Desc: We current support these layer flags:
  29. '!' means don't use any EXE entries
  30. '#' means go ahead and apply layers to system EXEs.
  31. The flags can be combined.
  32. --*/
  33. {
  34. DWORD dwLayerFlags = 0;
  35. //
  36. // Skip over the white spaces...
  37. //
  38. pszLayerString += _tcsspn(pszLayerString, g_szWhiteSpaceDelimiters);
  39. //
  40. // Next up is the ! or # or both
  41. //
  42. while (*pszLayerString != _T('\0') &&
  43. _tcschr(TEXT("!# \t"), *pszLayerString) != NULL) {
  44. if (*pszLayerString == _T('!')) {
  45. dwLayerFlags |= LAYER_USE_NO_EXE_ENTRIES;
  46. } else if (*pszLayerString == _T('#')) {
  47. dwLayerFlags |= LAYER_APPLY_TO_SYSTEM_EXES;
  48. }
  49. pszLayerString++;
  50. }
  51. if (pdwLayerFlags) {
  52. *pdwLayerFlags = dwLayerFlags;
  53. }
  54. return pszLayerString;
  55. }
  56. BOOL
  57. SdbpCheckRuntimePlatform(
  58. IN PSDBCONTEXT pContext, // pointer to the database channel
  59. IN LPCTSTR pszMatchingFile,
  60. IN DWORD dwPlatformDB
  61. )
  62. {
  63. DWORD dwPlatform = pContext->dwRuntimePlatform;
  64. BOOL bMatch = FALSE;
  65. BOOL bMatchElement;
  66. DWORD dwElement;
  67. INT i;
  68. if (dwPlatformDB == RUNTIME_PLATFORM_ANY) {
  69. return TRUE;
  70. }
  71. //
  72. // Check for all 3 supported platforms.
  73. //
  74. for (i = 0; i < 3; ++i) {
  75. dwElement = (dwPlatformDB >> (i * 8)) & RUNTIME_PLATFORM_MASK_ELEMENT;
  76. if (!(dwElement & RUNTIME_PLATFORM_FLAG_VALID)) { // this is not a valid element - move on
  77. continue;
  78. }
  79. bMatchElement = (dwPlatform == (dwElement & RUNTIME_PLATFORM_MASK_VALUE));
  80. if (dwElement & RUNTIME_PLATFORM_FLAG_NOT_ELEMENT) {
  81. bMatchElement = !bMatchElement;
  82. }
  83. bMatch |= bMatchElement;
  84. }
  85. if (dwPlatformDB & RUNTIME_PLATFORM_FLAG_NOT) {
  86. bMatch = !bMatch;
  87. }
  88. if (!bMatch) {
  89. DBGPRINT((sdlInfo,
  90. "SdbpCheckRuntimePlatform",
  91. "Platform Mismatch for \"%s\" Database(0x%lx) vs 0x%lx\n",
  92. (pszMatchingFile ? pszMatchingFile : TEXT("Unknown")),
  93. dwPlatformDB,
  94. dwPlatform));
  95. }
  96. return bMatch;
  97. }
  98. BOOL
  99. SafeNCat(
  100. LPTSTR lpszDest,
  101. int nSize,
  102. LPCTSTR lpszSrc,
  103. int nSizeAppend
  104. )
  105. {
  106. int nLen = (int)_tcslen(lpszDest);
  107. int nLenAppend = (int)_tcslen(lpszSrc);
  108. if (nSizeAppend >= 0 && nLenAppend > nSizeAppend) {
  109. nLenAppend = nSizeAppend;
  110. }
  111. if (nSize < nLen + nLenAppend + 1) {
  112. return FALSE;
  113. }
  114. RtlCopyMemory(lpszDest + nLen, lpszSrc, nLenAppend * sizeof(*lpszSrc));
  115. *(lpszDest + nLen + nLenAppend) = TEXT('\0');
  116. return TRUE;
  117. }
  118. BOOL
  119. SdbpSanitizeXML(
  120. LPTSTR pchOut,
  121. int nSize,
  122. LPCTSTR lpszXML
  123. )
  124. {
  125. LPCTSTR pch;
  126. LPCTSTR pchCur = lpszXML;
  127. const static LPCTSTR rgSC[] = { TEXT("&amp;"), TEXT("&quot;"), TEXT("&lt;"), TEXT("&gt;") };
  128. LPCTSTR rgSpecialChars = TEXT("&\"<>"); // should be the same as above
  129. LPCTSTR pchSpecial;
  130. int iReplace; // & should be first in both lists above
  131. int nLen = 0;
  132. int i;
  133. if (nSize < 1) {
  134. return FALSE;
  135. }
  136. *pchOut = TEXT('\0');
  137. while (*pchCur) {
  138. pch = _tcspbrk(pchCur, rgSpecialChars);
  139. if (NULL == pch) {
  140. // no more chars -- copy the rest
  141. if (!SafeNCat(pchOut, nSize, pchCur, -1)) {
  142. return FALSE;
  143. }
  144. break;
  145. }
  146. // copy up to pch
  147. if (!SafeNCat(pchOut, nSize, pchCur, (int)(pch - pchCur))) {
  148. return FALSE;
  149. }
  150. if (*pch == TEXT('&')) {
  151. for (i = 0; i < ARRAYSIZE(rgSC); ++i) {
  152. nLen = (int)_tcslen(rgSC[i]);
  153. if (_tcsnicmp(rgSC[i], pch, nLen) == 0) {
  154. // ok, move along, we are not touching this
  155. break;
  156. }
  157. }
  158. if (i < ARRAYSIZE(rgSC)) {
  159. // do not touch the string
  160. // nLen is the length we need to skip
  161. if (!SafeNCat(pchOut, nSize, pch, nLen)) {
  162. return FALSE;
  163. }
  164. pchCur = pch + nLen;
  165. continue;
  166. }
  167. iReplace = 0;
  168. } else {
  169. pchSpecial = _tcschr(rgSpecialChars, *pch);
  170. if (pchSpecial == NULL) {
  171. // internal error -- what is this ?
  172. return FALSE;
  173. }
  174. iReplace = (int)(pchSpecial - rgSpecialChars);
  175. }
  176. // so instead of pch we will have rgSC[i]
  177. if (!SafeNCat(pchOut, nSize, rgSC[iReplace], -1)) {
  178. return FALSE;
  179. }
  180. pchCur = pch + 1; // move on to the next char
  181. }
  182. return TRUE;
  183. }
  184. BOOL
  185. SdbTagIDToTagRef(
  186. IN HSDB hSDB,
  187. IN PDB pdb, // PDB the TAGID is from
  188. IN TAGID tiWhich, // TAGID to convert
  189. OUT TAGREF* ptrWhich // converted TAGREF
  190. )
  191. /*++
  192. Return: TRUE if a TAGREF was found, FALSE otherwise.
  193. Desc: Converts a PDB and TAGID into a TAGREF, by packing the high bits of the
  194. TAGREF with a constant that tells us which PDB, and the low bits with
  195. the TAGID.
  196. --*/
  197. {
  198. BOOL bReturn = FALSE;
  199. DWORD dwIndex = SDBENTRY_INVALID_INDEX;
  200. if (SdbpFindLocalDatabaseByPDB(hSDB, pdb, FALSE, &dwIndex)) {
  201. *ptrWhich = tiWhich | SDB_INDEX_TO_MASK(dwIndex);
  202. bReturn = TRUE;
  203. }
  204. if (!bReturn) {
  205. DBGPRINT((sdlError, "SdbTagIDToTagRef", "Bad PDB.\n"));
  206. *ptrWhich = TAGREF_NULL;
  207. }
  208. return bReturn;
  209. }
  210. BOOL
  211. SdbTagRefToTagID(
  212. IN HSDB hSDB,
  213. IN TAGREF trWhich, // TAGREF to convert
  214. OUT PDB* ppdb, // PDB the TAGREF is from
  215. OUT TAGID* ptiWhich // TAGID within that PDB
  216. )
  217. /*++
  218. Return: TRUE if the TAGREF is valid and was converted, FALSE otherwise.
  219. Desc: Converts a TAGREF type to a TAGID and a PDB. This manages the interface
  220. between NTDLL, which knows nothing of PDBs, and the shimdb, which manages
  221. three separate PDBs. The TAGREF incorporates the TAGID and a constant
  222. that tells us which PDB the TAGID is from. In this way, the NTDLL client
  223. doesn't need to know which DB the info is coming from.
  224. --*/
  225. {
  226. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  227. BOOL bReturn = TRUE;
  228. TAGID tiWhich = TAGID_NULL;
  229. PDB pdb = NULL;
  230. DWORD dwIndex;
  231. PSDBENTRY pEntry;
  232. assert(ppdb && ptiWhich);
  233. tiWhich = trWhich & TAGREF_STRIP_TAGID;
  234. dwIndex = SDB_MASK_TO_INDEX(trWhich & TAGREF_STRIP_PDB);
  235. //
  236. // Dynamically open a custom sdb.
  237. //
  238. pEntry = SDBGETENTRY(pSdbContext, dwIndex);
  239. if (pEntry->dwFlags & SDBENTRY_VALID_ENTRY) {
  240. pdb = pEntry->pdb;
  241. } else {
  242. if (pEntry->dwFlags & SDBENTRY_VALID_GUID) {
  243. //
  244. // We have a "half-baked" entry, make sure we
  245. // fill this entry in.
  246. //
  247. GUID guidDB = pEntry->guidDB;
  248. pEntry->dwFlags = 0; // invalidate an entry so that we know it's empty
  249. bReturn = SdbOpenLocalDatabaseEx(hSDB,
  250. &guidDB,
  251. SDBCUSTOM_GUID | SDBCUSTOM_USE_INDEX,
  252. &pdb,
  253. &dwIndex);
  254. if (!bReturn) {
  255. goto cleanup;
  256. }
  257. }
  258. }
  259. cleanup:
  260. if (pdb == NULL) {
  261. bReturn = FALSE;
  262. }
  263. if (!bReturn) {
  264. //
  265. // NULL out the output on failure.
  266. //
  267. pdb = NULL;
  268. tiWhich = TAGID_NULL;
  269. }
  270. if (ppdb != NULL) {
  271. *ppdb = pdb;
  272. }
  273. if (ptiWhich != NULL) {
  274. *ptiWhich = tiWhich;
  275. }
  276. return bReturn;
  277. }
  278. PDB
  279. SdbGetLocalPDB(
  280. IN HSDB hSDB
  281. )
  282. {
  283. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  284. if (pSdbContext) {
  285. return pSdbContext->pdbLocal;
  286. }
  287. return NULL;
  288. }
  289. BOOL
  290. SdbIsTagrefFromMainDB(
  291. IN TAGREF trWhich // TAGREF to test if it's from the main DB
  292. )
  293. /*++
  294. Return: TRUE if the TAGREF is from sysmain.sdb, FALSE otherwise.
  295. Desc: Checks if the provided TAGREF belongs to sysmain.sdb.
  296. --*/
  297. {
  298. return ((trWhich & TAGREF_STRIP_PDB) == PDB_MAIN);
  299. }
  300. BOOL
  301. SdbIsTagrefFromLocalDB(
  302. IN TAGREF trWhich // TAGREF to test if it's from the local DB
  303. )
  304. /*++
  305. Return: TRUE if the TAGREF is from a local SDB, FALSE otherwise.
  306. Desc: Checks if the provided TAGREF belongs to a local SDB.
  307. --*/
  308. {
  309. return ((trWhich & TAGREF_STRIP_PDB) == PDB_LOCAL);
  310. }
  311. BOOL
  312. SdbGetDatabaseGUID(
  313. IN HSDB hSDB, // HSDB of the sdbContext (optional)
  314. IN PDB pdb, // PDB of the database in question
  315. OUT GUID* pguidDB // the guid of the DB
  316. )
  317. /*++
  318. Return: TRUE if the GUID could be retrieved from the pdb, FALSE otherwise.
  319. Desc: Gets the GUID from an SDB file. If the hSDB is passed in, it will
  320. also check if the GUID is from systest or sysmain and return
  321. one of the hard-coded GUIDs for those files.
  322. --*/
  323. {
  324. if (!pdb) {
  325. DBGPRINT((sdlError, "SdbGetDatabaseGUID", "NULL pdb passed in.\n"));
  326. return FALSE;
  327. }
  328. if (!pguidDB) {
  329. DBGPRINT((sdlError, "SdbGetDatabaseGUID", "NULL pguidDB passed in.\n"));
  330. return FALSE;
  331. }
  332. if (hSDB) {
  333. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  334. DWORD dwIndex;
  335. if (SdbpFindLocalDatabaseByPDB(hSDB, pdb, FALSE, &dwIndex)) {
  336. //
  337. // Found the db, copy guid, we're done
  338. //
  339. if (pSdbContext->rgSDB[dwIndex].dwFlags & SDBENTRY_VALID_GUID) {
  340. RtlCopyMemory(pguidDB, &pSdbContext->rgSDB[dwIndex].guidDB, sizeof(*pguidDB));
  341. return TRUE;
  342. }
  343. }
  344. }
  345. return SdbGetDatabaseID(pdb, pguidDB);
  346. }
  347. PDB
  348. SdbGetPDBFromGUID(
  349. IN HSDB hSDB, // HSDB
  350. IN GUID* pguidDB // the guid of the DB
  351. )
  352. {
  353. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  354. PSDBENTRY pEntry;
  355. DWORD dwIndex;
  356. PDB pdb = NULL;
  357. if (!pSdbContext) {
  358. return NULL;
  359. }
  360. if (!SdbpFindLocalDatabaseByGUID(hSDB, pguidDB, FALSE, &dwIndex)) {
  361. return NULL;
  362. }
  363. pEntry = &pSdbContext->rgSDB[dwIndex];
  364. if (pEntry->dwFlags & SDBENTRY_VALID_ENTRY) {
  365. pdb = pEntry->pdb;
  366. } else {
  367. //
  368. // Open local db
  369. //
  370. if (!SdbOpenLocalDatabaseEx(hSDB,
  371. pguidDB,
  372. SDBCUSTOM_GUID|SDBCUSTOM_USE_INDEX,
  373. &pdb,
  374. &dwIndex)) {
  375. DBGPRINT((sdlWarning, "SdbGetPDBFromGUID", "Failed to open dormant pdb\n"));
  376. }
  377. }
  378. return pdb;
  379. }
  380. typedef struct tagFlagInfoEntry {
  381. ULONGLONG ullFlagMask; // mask of the flag
  382. DWORD dwSize; // size of the structure
  383. TAG tFlagType;
  384. TCHAR szCommandLine[1];
  385. } FLAGINFOENTRY, *PFLAGINFOENTRY;
  386. typedef struct tagFlagInfo {
  387. DWORD dwSize; // total size
  388. DWORD dwCount; // number of entries
  389. //
  390. // This member below is not allowed due to 0-size szCommandLine array, so it's implied
  391. //
  392. // FLAGINFOENTRY FlagInfoEntry[0]; // not a real array
  393. //
  394. } FLAGINFO, *PFLAGINFO;
  395. typedef struct tagFlagInfoListEntry* PFLAGINFOLISTENTRY;
  396. typedef struct tagFlagInfoListEntry {
  397. ULONGLONG ullFlagMask;
  398. TAG tFlagType;
  399. LPCTSTR pszCommandLine; // points to the currently open db
  400. DWORD dwEntrySize;
  401. PFLAGINFOLISTENTRY pNext;
  402. } FLAGINFOLISTENTRY;
  403. typedef FLAGINFOLISTENTRY* PFLAGINFOCONTEXT;
  404. #define ALIGN_ULONGLONG(p) \
  405. ((((ULONG_PTR)(p)) + (sizeof(ULONGLONG) - 1)) & ~(sizeof(ULONGLONG) - 1))
  406. BOOL
  407. SDBAPI
  408. SdbpPackCmdLineInfo(
  409. IN PVOID pvFlagInfoList,
  410. OUT PVOID* ppFlagInfo
  411. )
  412. {
  413. PFLAGINFOLISTENTRY pFlagInfoList = (PFLAGINFOLISTENTRY)pvFlagInfoList;
  414. PFLAGINFOLISTENTRY pEntry;
  415. DWORD dwSize = 0;
  416. DWORD dwFlagCount = 0;
  417. PFLAGINFO pFlagInfo;
  418. PFLAGINFOENTRY pFlagInfoEntry;
  419. pEntry = pFlagInfoList;
  420. while (pEntry != NULL) {
  421. pEntry->dwEntrySize = (DWORD)ALIGN_ULONGLONG(sizeof(FLAGINFOENTRY) +
  422. (_tcslen(pEntry->pszCommandLine) +
  423. 1) * sizeof(TCHAR));
  424. dwSize += pEntry->dwEntrySize;
  425. pEntry = pEntry->pNext;
  426. ++dwFlagCount;
  427. }
  428. dwSize += sizeof(FLAGINFO);
  429. //
  430. // Allocate memory
  431. //
  432. pFlagInfo = (PFLAGINFO)SdbAlloc(dwSize);
  433. if (pFlagInfo == NULL) {
  434. DBGPRINT((sdlError,
  435. "SdbpPackCmdLineInfo",
  436. "Failed to allocate 0x%lx bytes for FlagInfo\n",
  437. dwSize));
  438. return FALSE;
  439. }
  440. pFlagInfo->dwSize = dwSize;
  441. pFlagInfo->dwCount = dwFlagCount;
  442. pFlagInfoEntry = (PFLAGINFOENTRY)(pFlagInfo + 1);
  443. pEntry = pFlagInfoList;
  444. while (pEntry != NULL) {
  445. //
  446. // Create an entry
  447. //
  448. pFlagInfoEntry->ullFlagMask = pEntry->ullFlagMask;
  449. pFlagInfoEntry->dwSize = pEntry->dwEntrySize;
  450. pFlagInfoEntry->tFlagType = pEntry->tFlagType;
  451. //
  452. // Copy the string
  453. //
  454. StringCchCopy(&pFlagInfoEntry->szCommandLine[0],
  455. (pFlagInfoEntry->dwSize - sizeof(FLAGINFOENTRY))/sizeof(pFlagInfoEntry->szCommandLine[0]),
  456. pEntry->pszCommandLine);
  457. //
  458. // Advance to the next entry
  459. //
  460. pFlagInfoEntry = (PFLAGINFOENTRY)((PBYTE)pFlagInfoEntry + pFlagInfoEntry->dwSize);
  461. pEntry = pEntry->pNext;
  462. }
  463. *ppFlagInfo = (PVOID)pFlagInfo;
  464. return TRUE;
  465. }
  466. BOOL
  467. SDBAPI
  468. SdbpFreeFlagInfoList(
  469. IN PVOID pvFlagInfoList
  470. )
  471. {
  472. PFLAGINFOLISTENTRY pFlagInfoList = (PFLAGINFOLISTENTRY)pvFlagInfoList;
  473. PFLAGINFOLISTENTRY pNext;
  474. while (pFlagInfoList != NULL) {
  475. pNext = pFlagInfoList->pNext;
  476. SdbFree(pFlagInfoList);
  477. pFlagInfoList = pNext;
  478. }
  479. return TRUE;
  480. }
  481. BOOL
  482. SDBAPI
  483. SdbQueryFlagInfo(
  484. IN PVOID pvFlagInfo,
  485. IN TAG tFlagType,
  486. IN ULONGLONG ullFlagMask,
  487. OUT LPCTSTR* ppCmdLine
  488. )
  489. {
  490. PFLAGINFO pFlagInfo = (PFLAGINFO)pvFlagInfo;
  491. PFLAGINFOENTRY pFlagInfoEntry = (PFLAGINFOENTRY)(pFlagInfo+1);
  492. int i;
  493. for (i = 0; i < (int)pFlagInfo->dwCount; ++i) {
  494. if (pFlagInfoEntry->tFlagType == tFlagType &&
  495. pFlagInfoEntry->ullFlagMask == ullFlagMask) {
  496. if (ppCmdLine != NULL) {
  497. *ppCmdLine = &pFlagInfoEntry->szCommandLine[0];
  498. }
  499. return TRUE;
  500. }
  501. pFlagInfoEntry = (PFLAGINFOENTRY)((PBYTE)pFlagInfoEntry + pFlagInfoEntry->dwSize);
  502. }
  503. return FALSE;
  504. }
  505. BOOL
  506. SDBAPI
  507. SdbFreeFlagInfo(
  508. IN PVOID pvFlagInfo
  509. )
  510. {
  511. PFLAGINFO pFlagInfo = (PFLAGINFO)pvFlagInfo;
  512. if (pFlagInfo != NULL) {
  513. SdbFree(pFlagInfo);
  514. }
  515. return TRUE;
  516. }
  517. BOOL
  518. SDBAPI
  519. SdbpGetFlagCmdLine(
  520. IN PFLAGINFOCONTEXT* ppFlagInfo,
  521. IN HSDB hSDB,
  522. IN TAGREF trFlagRef,
  523. IN TAG tFlagType,
  524. IN ULONGLONG ullFlagMask,
  525. IN BOOL bOverwrite
  526. )
  527. {
  528. TAGREF trFlagCmdLine;
  529. BOOL bReturn = FALSE;
  530. LPCTSTR lpszCmdLine;
  531. PFLAGINFOLISTENTRY pFlagInfoListEntry;
  532. PFLAGINFOLISTENTRY pFlagPrev;
  533. //
  534. // We start by getting the cmd line
  535. //
  536. trFlagCmdLine = SdbFindFirstTagRef(hSDB, trFlagRef, TAG_COMMAND_LINE);
  537. if (trFlagCmdLine == TAGREF_NULL) { // no cmd line for this flag
  538. bReturn = TRUE;
  539. goto Cleanup;
  540. }
  541. //
  542. // Now we get the rest of the info
  543. //
  544. lpszCmdLine = SdbpGetStringRefPtr(hSDB, trFlagCmdLine);
  545. if (lpszCmdLine == NULL) {
  546. DBGPRINT((sdlError,
  547. "SdbpGetFlagCmdLine",
  548. "Failed to read TAG_COMMAND_LINE string\n"));
  549. goto Cleanup;
  550. }
  551. //
  552. // Check whether we have already command line for this flag
  553. //
  554. pFlagInfoListEntry = *ppFlagInfo;
  555. pFlagPrev = NULL;
  556. while (pFlagInfoListEntry != NULL) {
  557. if (pFlagInfoListEntry->tFlagType == tFlagType &&
  558. pFlagInfoListEntry->ullFlagMask == ullFlagMask) {
  559. break;
  560. }
  561. pFlagPrev = pFlagInfoListEntry;
  562. pFlagInfoListEntry = pFlagInfoListEntry->pNext;
  563. }
  564. if (pFlagInfoListEntry != NULL) {
  565. if (bOverwrite) { // found the same flag, overwrite
  566. if (pFlagPrev == NULL) {
  567. *ppFlagInfo = pFlagInfoListEntry->pNext;
  568. } else {
  569. pFlagPrev->pNext = pFlagInfoListEntry->pNext;
  570. }
  571. SdbFree(pFlagInfoListEntry);
  572. } else { // same entry, no overwriting
  573. bReturn = TRUE;
  574. goto Cleanup;
  575. }
  576. }
  577. //
  578. // We have everything we need - make a context entry
  579. //
  580. pFlagInfoListEntry = (PFLAGINFOLISTENTRY)SdbAlloc(sizeof(FLAGINFOLISTENTRY));
  581. if (pFlagInfoListEntry == NULL) {
  582. DBGPRINT((sdlError,
  583. "SdbpGetFlagCmdLine",
  584. "Failed to allocate FLAGINFOLISTENTRY\n"));
  585. goto Cleanup;
  586. }
  587. pFlagInfoListEntry->ullFlagMask = ullFlagMask;
  588. pFlagInfoListEntry->tFlagType = tFlagType;
  589. pFlagInfoListEntry->pszCommandLine = lpszCmdLine;
  590. pFlagInfoListEntry->pNext = *ppFlagInfo;
  591. *ppFlagInfo = pFlagInfoListEntry;
  592. bReturn = TRUE;
  593. Cleanup:
  594. return bReturn;
  595. }
  596. BOOL
  597. SDBAPI
  598. SdbQueryFlagMask(
  599. IN HSDB hSDB,
  600. IN SDBQUERYRESULT* psdbQuery,
  601. IN TAG tFlagType,
  602. OUT ULONGLONG* pullFlags,
  603. IN OUT PVOID* ppFlagInfo OPTIONAL
  604. )
  605. {
  606. DWORD dwInd;
  607. TAGREF trFlagRef;
  608. TAGREF trFlag;
  609. TAGREF trFlagMask;
  610. ULONGLONG ullFlagMask;
  611. PFLAGINFOCONTEXT pFlagInfoContext = NULL;
  612. if (pullFlags == NULL) {
  613. DBGPRINT((sdlError, "SdbQueryFlagMask", "Invalid parameter.\n"));
  614. return FALSE;
  615. }
  616. *pullFlags = 0;
  617. if (ppFlagInfo != NULL) {
  618. pFlagInfoContext = *(PFLAGINFOCONTEXT*)ppFlagInfo;
  619. }
  620. for (dwInd = 0; psdbQuery->atrExes[dwInd] != TAGREF_NULL && dwInd < SDB_MAX_EXES; dwInd++) {
  621. trFlagRef = SdbFindFirstTagRef(hSDB, psdbQuery->atrExes[dwInd], TAG_FLAG_REF);
  622. while (trFlagRef != TAGREF_NULL) {
  623. trFlag = SdbGetFlagFromFlagRef(hSDB, trFlagRef);
  624. if (trFlag == TAGREF_NULL) {
  625. DBGPRINT((sdlError,
  626. "SdbQueryFlagMask",
  627. "Failed to get TAG from TAGREF 0x%x.\n",
  628. trFlagRef));
  629. break;
  630. }
  631. ullFlagMask = 0;
  632. trFlagMask = SdbFindFirstTagRef(hSDB, trFlag, tFlagType);
  633. if (trFlagMask != TAGREF_NULL) {
  634. ullFlagMask = SdbReadQWORDTagRef(hSDB, trFlagMask, 0);
  635. }
  636. *pullFlags |= ullFlagMask;
  637. //
  638. // Now we get command line - if we have retrieved the flag mask
  639. //
  640. if (ppFlagInfo != NULL && ullFlagMask) {
  641. if (!SdbpGetFlagCmdLine(&pFlagInfoContext,
  642. hSDB,
  643. trFlagRef,
  644. tFlagType,
  645. ullFlagMask,
  646. TRUE)) {
  647. //
  648. // BUGBUG: this has to be handled as an error
  649. // Currently we do not do this b/c it is not
  650. // as important -- pFlagInfoContext will not be
  651. // touched if this function had failed
  652. //
  653. break;
  654. }
  655. }
  656. trFlagRef = SdbFindNextTagRef(hSDB, psdbQuery->atrExes[dwInd], trFlagRef);
  657. }
  658. }
  659. for (dwInd = 0;
  660. psdbQuery->atrLayers[dwInd] != TAGREF_NULL && dwInd < SDB_MAX_LAYERS;
  661. dwInd++) {
  662. trFlagRef = SdbFindFirstTagRef(hSDB, psdbQuery->atrLayers[dwInd], TAG_FLAG_REF);
  663. while (trFlagRef != TAGREF_NULL) {
  664. trFlag = SdbGetFlagFromFlagRef(hSDB, trFlagRef);
  665. if (trFlag == TAGREF_NULL) {
  666. DBGPRINT((sdlError,
  667. "SdbQueryFlagMask",
  668. "Failed to get TAG from TAGREF 0x%x.\n",
  669. trFlagRef));
  670. break;
  671. }
  672. ullFlagMask = 0;
  673. trFlagMask = SdbFindFirstTagRef(hSDB, trFlag, tFlagType);
  674. if (trFlagMask != TAGREF_NULL) {
  675. ullFlagMask = SdbReadQWORDTagRef(hSDB, trFlagMask, 0);
  676. }
  677. *pullFlags |= ullFlagMask;
  678. if (ppFlagInfo != NULL && ullFlagMask) {
  679. SdbpGetFlagCmdLine(&pFlagInfoContext,
  680. hSDB,
  681. trFlagRef,
  682. tFlagType,
  683. ullFlagMask,
  684. FALSE);
  685. }
  686. trFlagRef = SdbFindNextTagRef(hSDB, psdbQuery->atrLayers[dwInd], trFlagRef);
  687. }
  688. }
  689. if (ppFlagInfo != NULL) {
  690. *ppFlagInfo = (PVOID)pFlagInfoContext;
  691. }
  692. return TRUE;
  693. }
  694. BOOL
  695. SdbpIsPathOnCdRom(
  696. LPCTSTR pszPath
  697. )
  698. {
  699. TCHAR szDrive[5];
  700. UINT unType;
  701. if (pszPath == NULL) {
  702. DBGPRINT((sdlError,
  703. "SdbpIsPathOnCdRom",
  704. "NULL parameter passed for szPath.\n"));
  705. return FALSE;
  706. }
  707. if (pszPath[1] != _T(':') && pszPath[1] != _T('\\')) {
  708. //
  709. // Not a path we recognize.
  710. //
  711. DBGPRINT((sdlInfo,
  712. "SdbpIsPathOnCdRom",
  713. "\"%s\" not a full path we can operate on.\n",
  714. pszPath));
  715. return FALSE;
  716. }
  717. if (pszPath[1] == _T('\\')) {
  718. //
  719. // Network path.
  720. //
  721. return FALSE;
  722. }
  723. memcpy(szDrive, _T("c:\\"), 4 * sizeof(TCHAR));
  724. szDrive[0] = pszPath[0];
  725. unType = GetDriveType(szDrive);
  726. if (unType == DRIVE_CDROM) {
  727. return TRUE;
  728. }
  729. return FALSE;
  730. }
  731. BOOL
  732. SdbpBuildSignature(
  733. IN LPCTSTR pszPath,
  734. OUT LPTSTR pszPathSigned,
  735. IN DWORD cchSize // size of pszPathSigned (in characters)
  736. )
  737. {
  738. TCHAR szDir[MAX_PATH];
  739. TCHAR* pszEnd;
  740. DWORD dwSignature = 0;
  741. HANDLE hFind;
  742. WIN32_FIND_DATA ffd;
  743. int nCount = 9;
  744. _tcsncpy(szDir, pszPath, MAX_PATH);
  745. szDir[MAX_PATH - 1] = 0;
  746. pszEnd = _tcsrchr(szDir, _T('\\'));
  747. if (pszEnd != NULL) {
  748. ++pszEnd;
  749. } else {
  750. pszEnd = szDir;
  751. }
  752. *pszEnd++ = _T('*');
  753. *pszEnd = _T('\0');
  754. hFind = FindFirstFile(szDir, &ffd);
  755. if (hFind == INVALID_HANDLE_VALUE) {
  756. DBGPRINT((sdlInfo,
  757. "SdbPathRequiresSignature",
  758. "\"%s\" not a full path we can operate on.\n",
  759. pszPath));
  760. return FALSE;
  761. }
  762. do {
  763. if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  764. ffd.nFileSizeLow != 0) {
  765. dwSignature = ((dwSignature << 1) | (dwSignature >> 31)) ^ ffd.nFileSizeLow;
  766. nCount--;
  767. }
  768. if (!FindNextFile(hFind, &ffd)) {
  769. break;
  770. }
  771. } while (nCount > 0);
  772. FindClose(hFind);
  773. //
  774. // pszPath always starts with x:\\
  775. //
  776. StringCchPrintf(pszPathSigned, cchSize, _T("SIGN=%X %s"), dwSignature, pszPath + 3);
  777. return TRUE;
  778. }
  779. LPTSTR
  780. GetProcessHistory(
  781. IN LPCTSTR pEnvironment,
  782. IN LPTSTR szDir,
  783. IN LPTSTR szName
  784. )
  785. /*++
  786. Return: The __PROCESS_HISTORY content from the environment.
  787. Desc: The function retrieves Process History given the environment, an exe name and
  788. it's directory. Process History is constructed from the __PROCESS_HISTORY environment
  789. variable with an addition of the current exe path. The memory buffer returned from this
  790. function should be freed using SdbFree
  791. --*/
  792. {
  793. NTSTATUS Status;
  794. ULONG ProcessHistorySize = 0;
  795. ULONG DirLen = 0, NameLen = 0;
  796. DWORD dwBufferLength = 0;
  797. LPTSTR szProcessHistory = NULL;
  798. LPTSTR pszHistory = NULL;
  799. assert(szDir != NULL && szName != NULL);
  800. DirLen = (ULONG)_tcslen(szDir);
  801. NameLen = (ULONG)_tcslen(szName);
  802. Status = SdbpGetEnvVar(pEnvironment,
  803. g_szProcessHistory,
  804. NULL,
  805. &dwBufferLength);
  806. if (STATUS_BUFFER_TOO_SMALL == Status) {
  807. ProcessHistorySize = (DirLen + NameLen + 2 + dwBufferLength) * sizeof(TCHAR);
  808. } else {
  809. //
  810. // We assume that the environment variable is not available.
  811. //
  812. assert(Status == STATUS_VARIABLE_NOT_FOUND);
  813. ProcessHistorySize = (DirLen + NameLen + 1) * sizeof(TCHAR);
  814. }
  815. //
  816. // Allocate the buffer, regardless of whether there is
  817. // an environment variable or not. Later, we will check Status again
  818. // to see whether we need to try to query for an environment variable
  819. // with a valid buffer.
  820. //
  821. pszHistory = szProcessHistory = SdbAlloc(ProcessHistorySize);
  822. if (szProcessHistory == NULL) {
  823. DBGPRINT((sdlError,
  824. "GetProcessHistory",
  825. "Unable to allocate %d bytes for process history.\n",
  826. ProcessHistorySize));
  827. return NULL;
  828. }
  829. *pszHistory = 0;
  830. if (Status == STATUS_BUFFER_TOO_SMALL) {
  831. //
  832. // In this case we have tried to obtain the __PROCESS_HISTORY and
  833. // the variable was present as indicated by the status
  834. //
  835. Status = SdbpGetEnvVar(pEnvironment,
  836. g_szProcessHistory,
  837. szProcessHistory,
  838. &dwBufferLength);
  839. if (NT_SUCCESS(Status)) {
  840. //
  841. // See if we have ';' at the end of this.
  842. //
  843. pszHistory = szProcessHistory + dwBufferLength - 1;
  844. if (*pszHistory != TEXT(';')) {
  845. *++pszHistory = TEXT(';');
  846. }
  847. ++pszHistory;
  848. }
  849. }
  850. //
  851. // The __PROCESS_HISTORY environment variable has the following format:
  852. //
  853. // __PROCESS_HISTORY=C:\ProcessN-2.exe;D:\ProcessN-1.exe
  854. //
  855. // and then the following lines tack on the current process like so:
  856. //
  857. // __PROCESS_HISTORY=C:\ProcessN-2.exe;D:\ProcessN-1.exe;D:\Child\ProcessN.exe
  858. //
  859. RtlMoveMemory(pszHistory, szDir, DirLen * sizeof(TCHAR));
  860. pszHistory += DirLen;
  861. RtlMoveMemory(pszHistory, szName, NameLen * sizeof(TCHAR));
  862. pszHistory += NameLen;
  863. *pszHistory = TEXT('\0');
  864. return szProcessHistory;
  865. }
  866. TAGREF
  867. SdbpGetNamedLayerFromExe(
  868. IN HSDB hSDB,
  869. IN PDB pdb,
  870. IN TAGID tiLayer,
  871. OUT DWORD* pdwLayerFlags
  872. )
  873. /*++
  874. Return: A TAGREF for the layer under the EXE tag or TAGREF_NULL if there is no layer.
  875. Desc: BUGBUG: ?
  876. --*/
  877. {
  878. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  879. TAGREF trLayer;
  880. TAGID tiDatabase, tiName;
  881. TCHAR* pszName;
  882. BOOL bSuccess;
  883. //
  884. // Read the layer's name.
  885. //
  886. tiName = SdbFindFirstTag(pdb, tiLayer, TAG_NAME);
  887. if (tiName == TAGID_NULL) {
  888. DBGPRINT((sdlError, "SdbpGetNamedLayerFromExe", "Layer tag w/o a name.\n"));
  889. return TAGREF_NULL;
  890. }
  891. pszName = SdbGetStringTagPtr(pdb, tiName);
  892. if (pszName == NULL) {
  893. DBGPRINT((sdlError,
  894. "SdbpGetNamedLayerFromExe",
  895. "Cannot read the name of the layer tag.\n"));
  896. return TAGREF_NULL;
  897. }
  898. //
  899. // Need to get the layer flags here.
  900. //
  901. pszName = SdbpGetLayerFlags(pszName, pdwLayerFlags);
  902. //
  903. // First, try to find the layer in the same db as the EXE
  904. //
  905. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  906. assert(tiDatabase != TAGID_NULL);
  907. trLayer = TAGREF_NULL;
  908. tiLayer = SdbFindFirstNamedTag(pdb,
  909. tiDatabase,
  910. TAG_LAYER,
  911. TAG_NAME,
  912. pszName);
  913. if (tiLayer != TAGID_NULL) {
  914. bSuccess = SdbTagIDToTagRef(pSdbContext, pdb, tiLayer, &trLayer);
  915. if (!bSuccess) {
  916. DBGPRINT((sdlError, "SdbpGetNamedLayerFromExe", "Cannot get tag ref from tag id.\n"));
  917. }
  918. return trLayer;
  919. }
  920. if (pdb != pSdbContext->pdbMain) {
  921. //
  922. // Try it now in the main db
  923. //
  924. tiDatabase = SdbFindFirstTag(pSdbContext->pdbMain, TAGID_ROOT, TAG_DATABASE);
  925. tiLayer = SdbFindFirstNamedTag(pSdbContext->pdbMain,
  926. tiDatabase,
  927. TAG_LAYER,
  928. TAG_NAME,
  929. pszName);
  930. if (tiLayer != TAGID_NULL) {
  931. bSuccess = SdbTagIDToTagRef(pSdbContext, pSdbContext->pdbMain, tiLayer, &trLayer);
  932. if (!bSuccess) {
  933. DBGPRINT((sdlError,
  934. "SdbpGetNamedLayerFromExe",
  935. "Cannot get tag ref from tag id.\n"));
  936. }
  937. }
  938. }
  939. return trLayer;
  940. }
  941. TAGREF
  942. SDBAPI
  943. SdbGetNamedLayer(
  944. IN HSDB hSDB, // database context
  945. IN TAGREF trLayerRef // tagref of a record referencing a layer
  946. )
  947. {
  948. PDB pdb = NULL;
  949. TAGID tiLayerRef = TAGID_NULL;
  950. if (!SdbTagRefToTagID(hSDB, trLayerRef, &pdb, &tiLayerRef)) {
  951. DBGPRINT((sdlError, "SdbGetNamedLayer",
  952. "Error converting tagref 0x%lx to tagid\n", trLayerRef));
  953. return TAGREF_NULL;
  954. }
  955. return SdbpGetNamedLayerFromExe(hSDB, pdb, tiLayerRef, NULL);
  956. }
  957. //
  958. // This code is only needed when not running in Kernel Mode
  959. //
  960. TAGREF
  961. SdbGetLayerTagReg(
  962. IN HSDB hSDB,
  963. IN LPCTSTR szLayer
  964. )
  965. /*++
  966. Return: BUGBUG: ?
  967. Desc: BUGBUG: ?
  968. --*/
  969. {
  970. TAGID tiDatabase;
  971. TAGID tiLayer;
  972. TAGREF trLayer;
  973. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  974. if (pSdbContext == NULL || pSdbContext->pdbMain == NULL) {
  975. DBGPRINT((sdlError, "SdbGetLayerTagReg", "Invalid parameters.\n"));
  976. return TAGREF_NULL;
  977. }
  978. tiDatabase = SdbFindFirstTag(pSdbContext->pdbMain, TAGID_ROOT, TAG_DATABASE);
  979. tiLayer = SdbFindFirstNamedTag(pSdbContext->pdbMain,
  980. tiDatabase,
  981. TAG_LAYER,
  982. TAG_NAME,
  983. szLayer);
  984. if (tiLayer == TAGID_NULL) {
  985. DBGPRINT((sdlError, "SdbGetLayerTagReg", "No layer \"%s\" exists.\n", szLayer));
  986. return TAGREF_NULL;
  987. }
  988. if (!SdbTagIDToTagRef(hSDB, pSdbContext->pdbMain, tiLayer, &trLayer)) {
  989. DBGPRINT((sdlError,
  990. "SdbGetLayerTagReg",
  991. "Cannot get tagref for tagid 0x%x.\n",
  992. tiLayer));
  993. return TAGREF_NULL;
  994. }
  995. return trLayer;
  996. }
  997. BOOL
  998. SdbParseLayerString(
  999. IN PSDBCONTEXT pSdbContext,
  1000. IN LPTSTR pszLayerString,
  1001. IN PSDBQUERYRESULT pQueryResult,
  1002. IN PDWORD pdwLayers,
  1003. OUT DWORD* pdwLayerFlags
  1004. )
  1005. {
  1006. TCHAR* pszLayerStringStart = NULL;
  1007. TCHAR szLayer[MAX_PATH];
  1008. TAGID tiDatabase = TAGID_NULL;
  1009. TAGID tiLayer = TAGID_NULL;
  1010. PDB pdbLayer = NULL; // pdb that contains the match for the layer
  1011. UNREFERENCED_PARAMETER(pdwLayers);
  1012. pszLayerString = SdbpGetLayerFlags(pszLayerString, pdwLayerFlags);
  1013. //
  1014. // Now we should be at the beginning of the layer string.
  1015. //
  1016. while (pszLayerString != NULL && *pszLayerString != _T('\0')) {
  1017. //
  1018. // Beginning of the string, remember the ptr
  1019. //
  1020. pszLayerStringStart = pszLayerString;
  1021. //
  1022. // Move the end to the first space.
  1023. //
  1024. pszLayerString = _tcspbrk(pszLayerStringStart, g_szWhiteSpaceDelimiters);
  1025. //
  1026. // Check whether it's all the way to the end
  1027. //
  1028. if (pszLayerString != NULL) {
  1029. //
  1030. // Terminate the string...
  1031. //
  1032. *pszLayerString++ = _T('\0');
  1033. //
  1034. // Skip white space.
  1035. //
  1036. pszLayerString += _tcsspn(pszLayerString, g_szWhiteSpaceDelimiters);
  1037. }
  1038. //
  1039. // Now pszLayerStringStart points to the layer string that needs
  1040. // to be examined.
  1041. //
  1042. StringCchCopy(szLayer, CHARCOUNT(szLayer), pszLayerStringStart);
  1043. //
  1044. // Search the layer in the test database first.
  1045. //
  1046. if (pSdbContext->pdbTest != NULL) {
  1047. tiDatabase = SdbFindFirstTag(pSdbContext->pdbTest, TAGID_ROOT, TAG_DATABASE);
  1048. pdbLayer = pSdbContext->pdbTest;
  1049. tiLayer = SdbFindFirstNamedTag(pSdbContext->pdbTest,
  1050. tiDatabase,
  1051. TAG_LAYER,
  1052. TAG_NAME,
  1053. szLayer);
  1054. }
  1055. if (tiLayer == TAGID_NULL) {
  1056. //
  1057. // Now search the layer in the main database.
  1058. //
  1059. tiDatabase = SdbFindFirstTag(pSdbContext->pdbMain, TAGID_ROOT, TAG_DATABASE);
  1060. pdbLayer = pSdbContext->pdbMain;
  1061. tiLayer = SdbFindFirstNamedTag(pSdbContext->pdbMain,
  1062. tiDatabase,
  1063. TAG_LAYER,
  1064. TAG_NAME,
  1065. szLayer);
  1066. }
  1067. if (tiLayer != TAGID_NULL) {
  1068. goto foundDB;
  1069. }
  1070. //
  1071. // Check if the layer is defined in a custom database
  1072. //
  1073. {
  1074. DWORD dwLocalIndex = 0;
  1075. while (SdbOpenNthLocalDatabase((HSDB)pSdbContext, szLayer, &dwLocalIndex, TRUE)) {
  1076. tiDatabase = SdbFindFirstTag(pSdbContext->pdbLocal, TAGID_ROOT, TAG_DATABASE);
  1077. if (tiDatabase != TAGID_NULL) {
  1078. tiLayer = SdbFindFirstNamedTag(pSdbContext->pdbLocal,
  1079. tiDatabase,
  1080. TAG_LAYER,
  1081. TAG_NAME,
  1082. szLayer);
  1083. if (tiLayer != TAGID_NULL) {
  1084. pdbLayer = pSdbContext->pdbLocal;
  1085. goto foundDB;
  1086. }
  1087. } else {
  1088. DBGPRINT((sdlError, "SdbParseLayerString", "Local database is corrupted!\n"));
  1089. }
  1090. SdbCloseLocalDatabase((HSDB)pSdbContext);
  1091. }
  1092. }
  1093. foundDB:
  1094. if (tiLayer != TAGID_NULL) {
  1095. if (!SdbpAddMatch(pQueryResult,
  1096. pSdbContext,
  1097. pdbLayer,
  1098. NULL,
  1099. 0,
  1100. &tiLayer,
  1101. 1,
  1102. NULL,
  1103. 0,
  1104. NULL)) {
  1105. //
  1106. // Error would have already been logged
  1107. //
  1108. break;
  1109. }
  1110. DBGPRINT((sdlWarning|sdlLogShimViewer,
  1111. "SdbParseLayerString",
  1112. "Invoking compatibility layer \"%s\".\n",
  1113. pSdbContext,
  1114. szLayer));
  1115. }
  1116. tiLayer = TAGID_NULL;
  1117. pdbLayer = NULL;
  1118. }
  1119. return TRUE;
  1120. }
  1121. BOOL
  1122. SdbOpenNthLocalDatabase(
  1123. IN HSDB hSDB, // handle to the database channel
  1124. IN LPCTSTR pszItemName, // the name of the exectutable, without the path or the layer name
  1125. IN LPDWORD pdwIndex, // zero based index of the local DB to open
  1126. IN BOOL bLayer
  1127. )
  1128. /*++
  1129. Return: TRUE on success, FALSE otherwise.
  1130. Desc: Opens the Nth local database.
  1131. --*/
  1132. {
  1133. BOOL bRet = FALSE;
  1134. GUID guidDB;
  1135. DWORD dwIndex;
  1136. //
  1137. // Keep trying until there aren't any more user SDB files, or
  1138. // we find one we can open. This is to guard against a missing file
  1139. // causing us to ignore all further SDB files.
  1140. //
  1141. while (!bRet) {
  1142. if (!SdbGetNthUserSdb(hSDB, pszItemName, bLayer, pdwIndex, &guidDB)) {
  1143. break; // we have no more dbs
  1144. }
  1145. //
  1146. // Resolve the database we got through the local database interface
  1147. //
  1148. DBGPRINT((sdlInfo,
  1149. "SdbOpenNthLocalDatabase",
  1150. "Attempting to open local database %d\n",
  1151. *pdwIndex));
  1152. //
  1153. // See if we already have the database open
  1154. //
  1155. if (SdbpFindLocalDatabaseByGUID(hSDB, &guidDB, FALSE, &dwIndex)) {
  1156. PSDBENTRY pEntry = SDBGETENTRY(hSDB, dwIndex);
  1157. //
  1158. // This database is already open, remember, we treat pdbLocal as a junk
  1159. // pointer, which ALWAYS stores the result of this operation
  1160. //
  1161. assert(pEntry->dwFlags & SDBENTRY_VALID_ENTRY);
  1162. assert(pEntry->pdb != NULL);
  1163. ((PSDBCONTEXT)hSDB)->pdbLocal = pEntry->pdb;
  1164. bRet = TRUE;
  1165. break;
  1166. }
  1167. dwIndex = PDB_LOCAL;
  1168. bRet = SdbOpenLocalDatabaseEx(hSDB,
  1169. &guidDB,
  1170. SDBCUSTOM_GUID_BINARY|SDBCUSTOM_USE_INDEX,
  1171. NULL,
  1172. &dwIndex);
  1173. //
  1174. // In reality the function above will not do extra work to map the db
  1175. // if it already is mapped and opened (retained)
  1176. //
  1177. }
  1178. return bRet;
  1179. }
  1180. /*++
  1181. SdbGetMatchingExe
  1182. This is where the bulk of the work gets done. A full path of an EXE gets passed in,
  1183. and the function searches the database for potential matches. If a match is found,
  1184. the TAGREF of the EXE record in the database is passed back to be used for future
  1185. queries. If no match is found, the return is TAGREF_NULL.
  1186. The TAGREF returned by this function must be released by calling SdbReleaseMatchingExe
  1187. when finished with it. This only pertains to this TAGREF, not to TAGREFs in general.
  1188. ppContext is an optional parameter
  1189. if NULL, it has no effect
  1190. if not-null then it contains a pointer to the retained search context which
  1191. is useful when performing multiple search passes
  1192. using ppContext:
  1193. PVOID pContext = NULL;
  1194. SdbGetMatchingExe(TAG_EXE, L"foo\foo.exe", pEnv, &pContext, &trExe, &trLayer);
  1195. then you can use the context like this:
  1196. SdbGetMatchingExe(TAG_APPHELP_EXE, L"foo\foo.exe", pEnv, &pContext, &trExe, &trLayer);
  1197. to free the search context use
  1198. vFreeSearchDBContext(&pContext); <<< pContext is released and set to NULL
  1199. this is done to cache path-related information for a given exe file
  1200. --*/
  1201. BOOL
  1202. SdbpCleanupForExclusiveMatch(
  1203. IN PSDBCONTEXT pSdbContext,
  1204. IN PDB pdb
  1205. )
  1206. {
  1207. DWORD dwIndex;
  1208. PSDBENTRY pEntry;
  1209. //
  1210. // In doing a cleanup we do not touch the temp db since it's the one
  1211. // that is currently open (hence pdb parameter)
  1212. //
  1213. for (dwIndex = 2; dwIndex < ARRAYSIZE(pSdbContext->rgSDB); ++dwIndex) {
  1214. if (!SDBCUSTOM_CHECK_INDEX(pSdbContext, dwIndex)) {
  1215. continue;
  1216. }
  1217. pEntry = SDBGETENTRY(pSdbContext, dwIndex);
  1218. if (pEntry->pdb == pdb) {
  1219. continue;
  1220. }
  1221. //
  1222. // Nuke this entry
  1223. //
  1224. if (!SdbCloseLocalDatabaseEx((HSDB)pSdbContext, NULL, dwIndex)) {
  1225. DBGPRINT((sdlError,
  1226. "SdbpCleanupForExclusiveMatch",
  1227. "Failed to close local database\n"));
  1228. }
  1229. }
  1230. return TRUE;
  1231. }
  1232. BOOL
  1233. SdbpAddMatch(
  1234. IN OUT PSDBQUERYRESULT pQueryResult,
  1235. IN PSDBCONTEXT pSdbContext,
  1236. IN PDB pdb,
  1237. IN TAGID* ptiExes,
  1238. IN DWORD dwNumExes,
  1239. IN TAGID* ptiLayers,
  1240. IN DWORD dwNumLayers,
  1241. IN GUID* pguidExeID,
  1242. IN DWORD dwExeFlags,
  1243. IN OUT PMATCHMODE pMatchMode
  1244. )
  1245. {
  1246. DWORD dwIndex, dwLayerFlags = 0;
  1247. TAGID tiLayer;
  1248. TAGREF trLayer;
  1249. BOOL bSuccess = FALSE;
  1250. UNREFERENCED_PARAMETER(dwExeFlags);
  1251. UNREFERENCED_PARAMETER(pguidExeID);
  1252. if (pMatchMode != NULL) {
  1253. switch (pMatchMode-> Type) {
  1254. case MATCH_ADDITIVE:
  1255. //
  1256. // We're ok, add the match
  1257. //
  1258. break;
  1259. case MATCH_NORMAL:
  1260. //
  1261. // Go ahead, store the result
  1262. //
  1263. break;
  1264. case MATCH_EXCLUSIVE:
  1265. //
  1266. // Purge what we have so far
  1267. //
  1268. RtlZeroMemory(pQueryResult, sizeof(*pQueryResult));
  1269. //
  1270. // Cleanup all the custom sdbs, we will not need to apply any.
  1271. // We need to cleanse all the custom sdbs EXCEPT pdb.
  1272. // This is a tricky operation since pdb may be hosted in any of the custom sdb
  1273. // cells
  1274. //
  1275. SdbpCleanupForExclusiveMatch(pSdbContext, pdb);
  1276. break;
  1277. default:
  1278. //
  1279. // We don't know what this mode is -- error
  1280. //
  1281. DBGPRINT((sdlError,
  1282. "SdbpAddMatch",
  1283. "Unknown match mode 0x%lx\n",
  1284. (DWORD)pMatchMode->Type));
  1285. break;
  1286. }
  1287. }
  1288. //
  1289. // Check whether this sdb is a custom sdb or local sdb
  1290. //
  1291. if (SdbpIsLocalTempPDB(pSdbContext, pdb)) {
  1292. //
  1293. // Permanentize this sdb -- note that pdb may change while we are here!
  1294. //
  1295. if (SdbpRetainLocalDBEntry(pSdbContext, &pdb) == SDBENTRY_INVALID_INDEX) {
  1296. //
  1297. // Can't permanentize, forget it then
  1298. //
  1299. goto cleanup;
  1300. }
  1301. //
  1302. // the value retrieved may have been a bad one, thus we check for pdb
  1303. //
  1304. if (pdb == NULL) {
  1305. //
  1306. // this means we have a bad entry in local sdb table
  1307. //
  1308. assert(FALSE);
  1309. goto cleanup;
  1310. }
  1311. }
  1312. //
  1313. // Now pdb is either test, main or a permanentized local entry
  1314. //
  1315. if (ptiExes != NULL) {
  1316. for (dwIndex = 0; dwIndex < dwNumExes; ++dwIndex) {
  1317. if (pQueryResult->dwExeCount >= ARRAYSIZE(pQueryResult->atrExes)) {
  1318. DBGPRINT((sdlError,
  1319. "SdbpAddMatch",
  1320. "Failed to add the exe: exe count exceeded, tiExe was 0x%lx\n",
  1321. ptiExes[dwIndex]));
  1322. break;
  1323. }
  1324. bSuccess = SdbTagIDToTagRef(pSdbContext,
  1325. pdb,
  1326. ptiExes[dwIndex],
  1327. &pQueryResult->atrExes[pQueryResult->dwExeCount]);
  1328. if (!bSuccess) {
  1329. DBGPRINT((sdlError,
  1330. "SdbpAddMatch",
  1331. "Failed to convert tiExe 0x%x to trExe.\n",
  1332. ptiExes[dwIndex]));
  1333. continue;
  1334. }
  1335. ++pQueryResult->dwExeCount;
  1336. tiLayer = SdbFindFirstTag(pdb, ptiExes[dwIndex], TAG_LAYER);
  1337. while (tiLayer != TAGID_NULL) {
  1338. trLayer = SdbpGetNamedLayerFromExe(pSdbContext, pdb, tiLayer, &dwLayerFlags);
  1339. if (trLayer == TAGREF_NULL) {
  1340. DBGPRINT((sdlError,
  1341. "SdbpAddMatch",
  1342. "Failed to convert 0x%lx to layer ref\n",
  1343. tiLayer));
  1344. goto NextLayer;
  1345. }
  1346. if (pQueryResult->dwLayerCount >= ARRAYSIZE(pQueryResult->atrLayers)) {
  1347. DBGPRINT((sdlError,
  1348. "SdbpAddMatch",
  1349. "Failed to add the layer: layer count exceeded, tiExe was 0x%lx\n",
  1350. ptiExes[dwIndex]));
  1351. break;
  1352. }
  1353. pQueryResult->atrLayers[pQueryResult->dwLayerCount] = trLayer;
  1354. pQueryResult->dwLayerFlags |= dwLayerFlags;
  1355. ++pQueryResult->dwLayerCount;
  1356. NextLayer:
  1357. tiLayer = SdbFindNextTag(pdb, ptiExes[dwIndex], tiLayer);
  1358. }
  1359. }
  1360. }
  1361. if (ptiLayers != NULL) {
  1362. for (dwIndex = 0; dwIndex < dwNumLayers; ++dwIndex) {
  1363. trLayer = SdbpGetNamedLayerFromExe(pSdbContext, pdb, ptiLayers[dwIndex], &dwLayerFlags);
  1364. if (trLayer == TAGREF_NULL) {
  1365. DBGPRINT((sdlError,
  1366. "SdbpAddMatch",
  1367. "Failed to get layer from 0x%lx\n",
  1368. ptiLayers[dwIndex]));
  1369. continue;
  1370. }
  1371. if (pQueryResult->dwLayerCount >= ARRAYSIZE(pQueryResult->atrLayers)) {
  1372. DBGPRINT((sdlError,
  1373. "SdbpAddMatch",
  1374. "Failed to add the match: layer count exceeded, trLayer was 0x%lx\n",
  1375. trLayer));
  1376. break; // note that we simply truncate our match
  1377. }
  1378. pQueryResult->atrLayers[pQueryResult->dwLayerCount] = trLayer;
  1379. pQueryResult->dwLayerFlags |= dwLayerFlags;
  1380. ++pQueryResult->dwLayerCount;
  1381. }
  1382. }
  1383. bSuccess = TRUE;
  1384. cleanup:
  1385. return bSuccess;
  1386. }
  1387. BOOL
  1388. SdbpCaptureCustomSDBInformation(
  1389. IN OUT PSDBQUERYRESULT pQueryResult,
  1390. IN PSDBCONTEXT pSdbContext
  1391. )
  1392. {
  1393. DWORD dwIndex;
  1394. TAGREF trExe;
  1395. TAGREF trLayer;
  1396. DWORD dwDatabaseIndex;
  1397. PSDBENTRY pEntry;
  1398. DWORD dwMap = 0;
  1399. DWORD dwMask;
  1400. //
  1401. // Go through results, pick those sdbs that we need...
  1402. //
  1403. for (dwIndex = 0; dwIndex < pQueryResult->dwExeCount; ++dwIndex) {
  1404. //
  1405. // Get custom sdb for each tagref
  1406. //
  1407. trExe = pQueryResult->atrExes[dwIndex];
  1408. dwDatabaseIndex = SDB_MASK_TO_INDEX(trExe);
  1409. dwMask = (1UL << dwDatabaseIndex);
  1410. if (!(dwMap & dwMask)) {
  1411. //
  1412. // Copy the guid
  1413. //
  1414. pEntry = SDBGETENTRY(pSdbContext, dwDatabaseIndex);
  1415. RtlCopyMemory(&pQueryResult->rgGuidDB[dwDatabaseIndex], &pEntry->guidDB, sizeof(GUID));
  1416. dwMap |= dwMask;
  1417. }
  1418. }
  1419. for (dwIndex = 0; dwIndex < pQueryResult->dwLayerCount; ++dwIndex) {
  1420. trLayer = pQueryResult->atrLayers[dwIndex];
  1421. dwDatabaseIndex = SDB_MASK_TO_INDEX(trLayer);
  1422. dwMask = (1UL << dwDatabaseIndex);
  1423. if (!(dwMap & dwMask)) {
  1424. pEntry = SDBGETENTRY(pSdbContext, dwDatabaseIndex);
  1425. RtlCopyMemory(&pQueryResult->rgGuidDB[dwDatabaseIndex], &pEntry->guidDB, sizeof(GUID));
  1426. dwMap |= dwMask;
  1427. }
  1428. }
  1429. //
  1430. // Map to all the entries we have.
  1431. // Technically we do not need it, but just in case...
  1432. //
  1433. pQueryResult->dwCustomSDBMap = dwMap;
  1434. return TRUE;
  1435. }
  1436. BOOL
  1437. SdbGetMatchingExe(
  1438. IN HSDB hSDB OPTIONAL,
  1439. IN LPCTSTR szPath,
  1440. IN LPCTSTR szModuleName, // Optional -- only useful for 16-bit apps
  1441. IN LPCTSTR pszEnvironment,
  1442. IN DWORD dwFlags,
  1443. OUT PSDBQUERYRESULT pQueryResult
  1444. )
  1445. /*++
  1446. Return: TRUE if the specified EXE has a match in the database, FALSE otherwise.
  1447. Desc: This is where the bulk of the work gets done. A full path of an EXE gets
  1448. passed in, and the function searches the database for potential matches.
  1449. If a match is found, the TAGREF of the EXE record in the database is
  1450. passed back to be used for future queries. If no match is found, the
  1451. return is TAGREF_NULL.
  1452. The TAGREF returned by this function must be released by calling
  1453. SdbReleaseMatchingExe when finished with it. This only pertains to
  1454. this TAGREF, not to TAGREFs in general.
  1455. --*/
  1456. {
  1457. PDB pdb = NULL; // pdb that contains the match for the EXE
  1458. TAG tSection = TAG_EXE;
  1459. TAGID atiExes[SDB_MAX_EXES];
  1460. DWORD dwLayers = 0;
  1461. BOOL bReleaseDatabase = FALSE;
  1462. DWORD dwBufferSize;
  1463. DWORD dwLocalIndex = 0;
  1464. DWORD dwNumExes = 0;
  1465. MATCHMODE MatchMode = { 0 };
  1466. GUID guidExeID = { 0 };
  1467. DWORD dwExeFlags = 0;
  1468. DWORD dwLayerFlags = 0;
  1469. PSDBCONTEXT pSdbContext;
  1470. SEARCHDBCONTEXT Context;
  1471. BOOL bInstrumented = FALSE;
  1472. BOOL bMatchComplete = FALSE;
  1473. RtlZeroMemory(pQueryResult, sizeof(SDBQUERYRESULT));
  1474. RtlZeroMemory(atiExes, sizeof(atiExes));
  1475. if (hSDB == NULL) {
  1476. hSDB = SdbInitDatabase(HID_DOS_PATHS, NULL);
  1477. if (hSDB == NULL) {
  1478. DBGPRINT((sdlError, "SdbGetMatchingExe", "Failed to open the database.\n"));
  1479. return FALSE;
  1480. }
  1481. bReleaseDatabase = TRUE;
  1482. }
  1483. pSdbContext = (PSDBCONTEXT)hSDB;
  1484. //
  1485. // Initialize matching mode - we set the InterType to none (meaning the first match will
  1486. // be used to start the process) and IntraType is set to normal (does not really matter)
  1487. //
  1488. MatchMode.Type = MATCH_NORMAL;
  1489. //
  1490. // Check whether we have an instrumented run
  1491. //
  1492. bInstrumented = SDBCONTEXT_IS_INSTRUMENTED(hSDB);
  1493. assert(pSdbContext->pdbMain && szPath);
  1494. RtlZeroMemory(&Context, sizeof(Context)); // do this so that we don't trip later
  1495. //
  1496. // We shall use it later to optimize file attribute retrieval
  1497. //
  1498. Context.hMainFile = INVALID_HANDLE_VALUE;
  1499. __try {
  1500. NTSTATUS Status;
  1501. TCHAR szCompatLayer[MAX_PATH + 1];
  1502. //
  1503. // Check for system exes that WE KNOW we don't want to patch
  1504. //
  1505. DBGPRINT((sdlInfo, "SdbGetMatchingExe", "Looking for \"%s\".\n", szPath));
  1506. if (_tcsnicmp(szPath, TEXT("\\??\\"), 4) == 0 ||
  1507. _tcsnicmp(szPath, TEXT("\\SystemRoot\\"), 12) == 0) {
  1508. goto out;
  1509. }
  1510. //
  1511. // If the search context had been supplied use it, otherwise create one
  1512. //
  1513. if (!SdbpCreateSearchDBContext(&Context, szPath, szModuleName, pszEnvironment)) {
  1514. DBGPRINT((sdlError, "SdbGetMatchingExe", "Failed to create search DB context.\n"));
  1515. goto out;
  1516. }
  1517. //
  1518. // Make sure no local database is opened.
  1519. //
  1520. SdbCloseLocalDatabase(hSDB);
  1521. if (!(dwFlags & SDBGMEF_IGNORE_ENVIRONMENT)) {
  1522. //
  1523. // See if there's an environment variable set called "__COMPAT_LAYER".
  1524. // If so, grab the layers from that variable.
  1525. //
  1526. dwBufferSize = sizeof(szCompatLayer) / sizeof(szCompatLayer[0]);
  1527. Status = SdbpGetEnvVar(pszEnvironment,
  1528. g_szCompatLayer,
  1529. szCompatLayer,
  1530. &dwBufferSize);
  1531. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1532. DBGPRINT((sdlWarning,
  1533. "SdbGetMatchingExe",
  1534. "__COMPAT_LAYER name cannot exceed 256 characters.\n"));
  1535. }
  1536. if (NT_SUCCESS(Status)) {
  1537. SdbParseLayerString(pSdbContext,
  1538. szCompatLayer,
  1539. pQueryResult,
  1540. &dwLayers,
  1541. &dwLayerFlags);
  1542. if (dwLayerFlags & LAYER_USE_NO_EXE_ENTRIES) {
  1543. //
  1544. // This is an exclusive matching case, once we determined
  1545. // that the layers cannot be appended to we get out.
  1546. //
  1547. goto out;
  1548. }
  1549. }
  1550. }
  1551. //
  1552. // At this point we might have all the info from the env variable.
  1553. // See if we do, and if so -- check bAppendLayer
  1554. //
  1555. dwBufferSize = sizeof(szCompatLayer);
  1556. if (SdbGetPermLayerKeys(szPath, szCompatLayer, &dwBufferSize, GPLK_ALL)) {
  1557. SdbParseLayerString(pSdbContext,
  1558. szCompatLayer,
  1559. pQueryResult,
  1560. &dwLayers,
  1561. &dwLayerFlags);
  1562. if (dwLayerFlags & LAYER_USE_NO_EXE_ENTRIES) {
  1563. goto out;
  1564. }
  1565. } else {
  1566. if (dwBufferSize > sizeof(szCompatLayer)) {
  1567. DBGPRINT((sdlWarning,
  1568. "SdbGetMatchingExe",
  1569. "Layers in registry cannot exceed %d characters\n",
  1570. sizeof(szCompatLayer)/sizeof(szCompatLayer[0])));
  1571. }
  1572. }
  1573. //
  1574. // This block deals with searching local sdbs
  1575. //
  1576. dwLocalIndex = 0;
  1577. while (SdbOpenNthLocalDatabase(hSDB, Context.szName, &dwLocalIndex, FALSE)) {
  1578. dwNumExes = SdbpSearchDB(pSdbContext,
  1579. pSdbContext->pdbLocal,
  1580. tSection,
  1581. &Context,
  1582. atiExes,
  1583. &guidExeID,
  1584. &dwExeFlags,
  1585. &MatchMode);
  1586. if (dwNumExes) {
  1587. pdb = pSdbContext->pdbLocal;
  1588. //
  1589. // Report matches in local sdb with mode
  1590. //
  1591. DBGPRINT((sdlInfo,
  1592. "SdbGetMatchingExe",
  1593. "Found in local database.\n"));
  1594. if (!bMatchComplete) {
  1595. //
  1596. // Add the match in
  1597. //
  1598. if (!SdbpAddMatch(pQueryResult,
  1599. pSdbContext,
  1600. pdb,
  1601. atiExes,
  1602. dwNumExes,
  1603. NULL, 0, // no layers
  1604. &guidExeID,
  1605. dwExeFlags,
  1606. &MatchMode)) {
  1607. //
  1608. // Failed to secure a match, stop matching
  1609. //
  1610. goto out;
  1611. }
  1612. }
  1613. //
  1614. // We have "current running state" flags in dwMatchingMode
  1615. //
  1616. if (MatchMode.Type != MATCH_ADDITIVE) {
  1617. if (bInstrumented) {
  1618. //
  1619. // We are running instrumented, prevent further storing of results
  1620. //
  1621. bMatchComplete = TRUE;
  1622. //
  1623. // Modify match mode so that we keep matching to see if
  1624. // we get any more matches.
  1625. //
  1626. MatchMode.Type = MATCH_ADDITIVE;
  1627. } else {
  1628. goto out;
  1629. }
  1630. }
  1631. //
  1632. // Note that we do not leak local sdb here since the match was made
  1633. // in a local sdb. Since we added the match, local sdb is "permanentized"
  1634. //
  1635. }
  1636. //
  1637. // If the match was added, there is no local db to close.
  1638. // However the call below will just (quietly) exit, no harm done.
  1639. //
  1640. SdbCloseLocalDatabase(hSDB);
  1641. }
  1642. //
  1643. // Search systest.sdb database
  1644. //
  1645. if (pSdbContext->pdbTest != NULL) {
  1646. dwNumExes = SdbpSearchDB(pSdbContext,
  1647. pSdbContext->pdbTest,
  1648. tSection,
  1649. &Context,
  1650. atiExes,
  1651. &guidExeID,
  1652. &dwExeFlags,
  1653. &MatchMode);
  1654. if (dwNumExes) {
  1655. pdb = pSdbContext->pdbTest;
  1656. if (!bMatchComplete) {
  1657. if (!SdbpAddMatch(pQueryResult,
  1658. pSdbContext,
  1659. pdb,
  1660. atiExes,
  1661. dwNumExes,
  1662. NULL,
  1663. 0, // no layers
  1664. &guidExeID,
  1665. dwExeFlags,
  1666. &MatchMode)) {
  1667. goto out;
  1668. }
  1669. }
  1670. if (MatchMode.Type != MATCH_ADDITIVE) {
  1671. if (bInstrumented) {
  1672. //
  1673. // We are running instrumented, prevent further storing of results
  1674. //
  1675. bMatchComplete = TRUE;
  1676. //
  1677. // Modify match mode so that we keep matching to see if we
  1678. // get any more matches.
  1679. //
  1680. MatchMode.Type = MATCH_ADDITIVE;
  1681. } else {
  1682. goto out;
  1683. }
  1684. }
  1685. DBGPRINT((sdlInfo, "SdbGetMatchingExe", "Using SysTest.sdb\n"));
  1686. goto out;
  1687. }
  1688. }
  1689. //
  1690. // Search the main db
  1691. //
  1692. dwNumExes = SdbpSearchDB(pSdbContext,
  1693. pSdbContext->pdbMain,
  1694. tSection,
  1695. &Context,
  1696. atiExes,
  1697. &guidExeID,
  1698. &dwExeFlags,
  1699. &MatchMode);
  1700. if (dwNumExes) {
  1701. pdb = pSdbContext->pdbMain;
  1702. if (!bMatchComplete) {
  1703. if (!SdbpAddMatch(pQueryResult,
  1704. pSdbContext,
  1705. pdb,
  1706. atiExes,
  1707. dwNumExes,
  1708. NULL,
  1709. 0, // no layers
  1710. &guidExeID,
  1711. dwExeFlags,
  1712. &MatchMode)) { // also match mode!!!
  1713. goto out;
  1714. }
  1715. }
  1716. DBGPRINT((sdlInfo, "SdbGetMatchingExe", "Using Sysmain.sdb\n"));
  1717. goto out;
  1718. }
  1719. out:
  1720. //
  1721. // We are done matching. Before we return, we need to capture all the
  1722. // custom sdb entries that we used while producing the result of this query.
  1723. //
  1724. SdbpCaptureCustomSDBInformation(pQueryResult, pSdbContext);
  1725. } __except (SHIM_EXCEPT_HANDLER) {
  1726. RtlZeroMemory(pQueryResult, sizeof(SDBQUERYRESULT));
  1727. }
  1728. if (dwLayers >= SDB_MAX_LAYERS) {
  1729. DBGPRINT((sdlWarning,
  1730. "SdbGetMatchingExe",
  1731. "Hit max layer limit at %d. Perhaps we need to bump it.\n",
  1732. dwLayers));
  1733. }
  1734. //
  1735. // Free search context stuff
  1736. //
  1737. SdbpReleaseSearchDBContext(&Context);
  1738. if (bReleaseDatabase) {
  1739. SdbReleaseDatabase(hSDB);
  1740. }
  1741. return (pQueryResult->atrExes[0] != TAGREF_NULL ||
  1742. pQueryResult->atrLayers[0] != TAGREF_NULL);
  1743. }
  1744. void
  1745. SdbReleaseMatchingExe(
  1746. IN HSDB hSDB,
  1747. IN TAGREF trExe
  1748. )
  1749. /*++
  1750. Return: void.
  1751. Desc: Releases globally allocated data and closes a local database, if it exists.
  1752. The TAGREF of the exe is passed in purely for possible future use.
  1753. --*/
  1754. {
  1755. UNREFERENCED_PARAMETER(trExe);
  1756. SdbpCleanupLocalDatabaseSupport(hSDB);
  1757. }
  1758. SHIMVIEWER_OPTION g_eShimViewerOption = SHIMVIEWER_OPTION_UNINITIAZED;
  1759. #ifndef WIN32A_MODE
  1760. SHIMVIEWER_OPTION
  1761. SdbGetShowDebugInfoOption(
  1762. void
  1763. )
  1764. {
  1765. UNICODE_STRING ustrKeyPath = {0};
  1766. UNICODE_STRING ustrValue;
  1767. NTSTATUS status;
  1768. OBJECT_ATTRIBUTES ObjectAttributes;
  1769. HANDLE KeyHandle;
  1770. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  1771. ULONG KeyValueBuffer[64];
  1772. ULONG KeyValueLength;
  1773. g_eShimViewerOption = SHIMVIEWER_OPTION_NO;
  1774. //
  1775. // Check if the user wants the debug spew. If for some reason we can't
  1776. // get the info, we'll return success anyway and not show any debug info.
  1777. //
  1778. if (!SdbpBuildUserKeyPath(APPCOMPAT_KEY_PATH_W_WITH_SLASH, &ustrKeyPath)) {
  1779. DBGPRINT((sdlWarning,
  1780. "GetShowDebugInfoOption",
  1781. "Failed to format current user key path for \"%s\"",
  1782. APPCOMPAT_LOCATION_W));
  1783. goto out;
  1784. }
  1785. InitializeObjectAttributes(
  1786. &ObjectAttributes,
  1787. &ustrKeyPath,
  1788. OBJ_CASE_INSENSITIVE,
  1789. NULL,
  1790. NULL);
  1791. status = NtOpenKey(
  1792. &KeyHandle,
  1793. KEY_QUERY_VALUE | SdbpGetWow64Flag(),
  1794. &ObjectAttributes);
  1795. SdbFree(ustrKeyPath.Buffer);
  1796. if (!NT_SUCCESS(status)) {
  1797. DBGPRINT((sdlWarning,
  1798. "GetShowDebugInfoOption",
  1799. "Failed to open Key HKCU\\%s Status 0x%lx",
  1800. APPCOMPAT_LOCATION_W,
  1801. status));
  1802. goto out;
  1803. }
  1804. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)&KeyValueBuffer;
  1805. RtlInitUnicodeString(&ustrValue, SHIMENG_SHOW_DEBUG_INFO);
  1806. status = NtQueryValueKey(
  1807. KeyHandle,
  1808. &ustrValue,
  1809. KeyValuePartialInformation,
  1810. KeyValueInformation,
  1811. sizeof(KeyValueBuffer),
  1812. &KeyValueLength);
  1813. NtClose(KeyHandle);
  1814. if (!NT_SUCCESS(status)) {
  1815. DBGPRINT((sdlWarning,
  1816. "GetShowDebugInfoOption",
  1817. "Failed to read value info for value %s for key HKCU\\%s Status 0x%lx",
  1818. SHIMENG_SHOW_DEBUG_INFO,
  1819. APPCOMPAT_LOCATION_W,
  1820. status));
  1821. goto out;
  1822. }
  1823. if (KeyValueInformation->Type != REG_DWORD) {
  1824. DBGPRINT((sdlWarning,
  1825. "GetShowDebugInfoOption",
  1826. "Unexpected value type 0x%x for value %s under key HKCU\\%s",
  1827. KeyValueInformation->Type,
  1828. SHIMENG_SHOW_DEBUG_INFO,
  1829. APPCOMPAT_LOCATION_W));
  1830. goto out;
  1831. }
  1832. if (*(DWORD*)(&KeyValueInformation->Data[0]) != 0) {
  1833. g_eShimViewerOption = SHIMVIEWER_OPTION_YES;
  1834. }
  1835. out:
  1836. return g_eShimViewerOption;
  1837. }
  1838. #endif // WIN32A_MODE
  1839. int __cdecl
  1840. ShimDbgPrint(
  1841. int iLevelAndFlags,
  1842. PCH pszFunctionName,
  1843. PCH Format,
  1844. ...
  1845. )
  1846. {
  1847. int nch = 0;
  1848. #ifdef _DEBUG_SPEW
  1849. CHAR Buffer[2048];
  1850. INT i;
  1851. PCH pchLevel = NULL;
  1852. PCH pchBuffer = Buffer;
  1853. PCH pchEnd = pchBuffer;
  1854. PCH pszFormat = NULL;
  1855. PCH pszMessage= Buffer;
  1856. va_list arglist;
  1857. size_t cchRemaining = CHARCOUNT(Buffer);
  1858. int iLevel = FILTER_DBG_LEVEL(iLevelAndFlags);
  1859. HSDB hSDB = NULL;
  1860. HRESULT hr;
  1861. BOOL bSendInfoToSV; // Do we want to send spew to shimviewer?
  1862. //
  1863. // Check to see whether the debug output is initialized
  1864. //
  1865. if (g_iShimDebugLevel == SHIM_DEBUG_UNINITIALIZED) {
  1866. g_iShimDebugLevel = GetShimDbgLevel();
  1867. }
  1868. //
  1869. // Check to see whether we need to print anything.
  1870. // The criteria is such that we won't print a thing if iLevel does not fit,
  1871. // but we will use the pipe when it is provided.
  1872. //
  1873. bSendInfoToSV = !!(iLevelAndFlags & sdlLogShimViewer);
  1874. if (!bSendInfoToSV && iLevel > g_iShimDebugLevel) {
  1875. return 0;
  1876. }
  1877. #ifndef WIN32A_MODE
  1878. if (bSendInfoToSV) {
  1879. if (g_eShimViewerOption == SHIMVIEWER_OPTION_UNINITIAZED) {
  1880. SdbGetShowDebugInfoOption();
  1881. }
  1882. }
  1883. #endif // WIN32A_MODE
  1884. PREPARE_FORMAT(pszFormat, Format);
  1885. if (pszFormat == NULL) {
  1886. //
  1887. // Can't convert format for debug output
  1888. //
  1889. return 0;
  1890. }
  1891. va_start(arglist, Format);
  1892. //
  1893. // Now on to the contents
  1894. //
  1895. if (bSendInfoToSV) {
  1896. //
  1897. // The first arg then is hSDB
  1898. //
  1899. hSDB = va_arg(arglist, HSDB);
  1900. //
  1901. // For pipe out we prepend output with [pid:0x%.8lx]
  1902. //
  1903. StringCchPrintfExA(pchBuffer,
  1904. CHARCOUNT(Buffer),
  1905. &pchEnd,
  1906. &cchRemaining,
  1907. 0,
  1908. "[pid: 0x%.8lx]",
  1909. GetCurrentProcessId());
  1910. pszMessage = pchEnd;
  1911. }
  1912. //
  1913. // Do we have a comment for this debug level? if so, print it
  1914. //
  1915. for (i = 0; i < DEBUG_LEVELS; ++i) {
  1916. if (g_rgDbgLevelInfo[i].iLevel == iLevel) {
  1917. pchLevel = (PCH)g_rgDbgLevelInfo[i].szStrTag;
  1918. break;
  1919. }
  1920. }
  1921. if (pchLevel == NULL) {
  1922. pchLevel = g_szDbgLevelUser;
  1923. }
  1924. StringCchPrintfExA(pchEnd,
  1925. cchRemaining,
  1926. &pchEnd,
  1927. &cchRemaining,
  1928. 0,
  1929. "[%-4hs]",
  1930. pchLevel);
  1931. if (pszFunctionName) {
  1932. //
  1933. // Single-byte char going into UNICODE buffer
  1934. //
  1935. StringCchPrintfExA(pchEnd, cchRemaining, &pchEnd, &cchRemaining, 0, "[%-20hs] ", pszFunctionName);
  1936. }
  1937. //
  1938. // _vsntprintf this will not work for UNICODE Win2000
  1939. //
  1940. hr = StringCchVPrintfExA(pchEnd, cchRemaining, &pchEnd, &cchRemaining, 0, pszFormat, arglist);
  1941. if (FAILED(hr)) {
  1942. return 0;
  1943. }
  1944. va_end(arglist);
  1945. #ifndef WIN32A_MODE
  1946. if (bSendInfoToSV) {
  1947. SdbpWriteToShimViewer(hSDB, Buffer);
  1948. }
  1949. nch = DbgPrint("%s", pszMessage);
  1950. STACK_FREE(pszFormat);
  1951. #else // WIN32A_MODE
  1952. OutputDebugString(pszMessage);
  1953. nch = (int)(pchEnd - pszMessage);
  1954. #endif // WIN32A_MODE
  1955. #endif // _DEBUG_SPEW
  1956. return nch;
  1957. }