Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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