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.

1276 lines
34 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. dbaccessplus.c
  5. Abstract:
  6. This module implements APIs to access the shim database.
  7. Author:
  8. clupu created sometime in 2001
  9. Revision History:
  10. several people contributed (vadimb, dmunsil, ...)
  11. --*/
  12. #include "sdbp.h"
  13. //
  14. // This file is not included for KERNEL_MODE
  15. //
  16. //
  17. // SdbInitDatabase is not used in Kernel mode. SdbInitDatabaseInMemory is used instead
  18. //
  19. HSDB
  20. SdbInitDatabase(
  21. IN DWORD dwFlags, // flags that tell how the database should be
  22. // initialized.
  23. IN LPCTSTR pszDatabasePath // the OPTIONAL full path to the database to be used.
  24. )
  25. /*++
  26. Return: A handle to the database.
  27. Desc: This is the first API someone needs to call to initiate comunication
  28. with the database. Should be paired with a call to SdbReleaseDatabase
  29. when finished.
  30. HID_DATABASE_FULLPATH indicates that pszDatabasePath points to the full path of the
  31. main database, when this flag is not present and pszDatabasePath
  32. is not NULL we treat it as the directory where sysmain.sdb and
  33. systest.sdb are to be found
  34. HID_DOS_PATHS indicates the format of the pszDatabasePath: when this flag is
  35. present, we treat it as being in dos c:\blah\blah format, when
  36. it's not present - we treat pszDatabasePath as being in nt format
  37. e.g. "\SystemRoot\Apppatch"
  38. HID_NO_DATABASE indicates that no database will be open at this time
  39. (pszDatabasePath is simply ignored, along with all
  40. the other flags)
  41. In addition to the flags above you can specify the type of the database that needs to be
  42. opened via the SDB_DATABASE_MAIN_* flags such as:
  43. SDB_DATABASE_MAIN_SHIM - sysmain.sdb
  44. SDB_DATABASE_MAIN_MSI - msimain.sdb
  45. SDB_DATABASE_MAIN_DRIVERS - drvmain.sdb
  46. This feature is not present on downlevel platforms.
  47. When any of the database type flags are provided, pszDatabasePath should be set to NULL
  48. --*/
  49. {
  50. TCHAR wszWinDir[MAX_PATH] = TEXT("");
  51. TCHAR wszShimDB[MAX_PATH] = TEXT("");
  52. BOOL bReturn = FALSE;
  53. PSDBCONTEXT pContext;
  54. DWORD dwFlagOpen = 0;
  55. //
  56. // Allocate the HSDB handle.
  57. //
  58. pContext = (PSDBCONTEXT)SdbAlloc(sizeof(SDBCONTEXT));
  59. if (pContext == NULL) {
  60. DBGPRINT((sdlError, "SdbInitDatabase", "Failed to allocate %d bytes for HSDB\n",
  61. sizeof(SDBCONTEXT)));
  62. return NULL;
  63. }
  64. //
  65. // See if we need to open db...
  66. //
  67. if (dwFlags & HID_NO_DATABASE) {
  68. DBGPRINT((sdlInfo, "SdbInitDatabase", "No database is open\n"));
  69. goto InitDone;
  70. }
  71. //
  72. // Determine which flag to use with the OPEN call
  73. //
  74. dwFlagOpen = (dwFlags & HID_DOS_PATHS) ? DOS_PATH : NT_PATH;
  75. //
  76. // Open the main database and do this under a try/except so we don't screw
  77. // our caller if the database is corrupt.
  78. //
  79. __try {
  80. if (dwFlags & HID_DATABASE_FULLPATH) {
  81. // we better have the ptr
  82. if (pszDatabasePath == NULL) {
  83. DBGPRINT((sdlError, "SdbInitDatabase",
  84. "Database not specified with the database path flag\n"));
  85. goto errHandle;
  86. }
  87. _tcscpy(wszShimDB, pszDatabasePath);
  88. } else {
  89. //
  90. // we do not have a database path
  91. // see if we have a database type to open as a "main" db
  92. //
  93. #ifndef WIN32A_MODE
  94. //
  95. // This code works only on UNICODE
  96. //
  97. if (dwFlags & HID_DATABASE_TYPE_MASK) {
  98. DWORD dwDatabaseType = dwFlags;
  99. DWORD dwLen;
  100. dwLen = SdbpGetStandardDatabasePath(dwDatabaseType,
  101. dwFlags,
  102. wszShimDB,
  103. CHARCOUNT(wszShimDB));
  104. if (dwLen > CHARCOUNT(wszShimDB)) {
  105. DBGPRINT((sdlError,
  106. "SdbInitDatabase",
  107. "Cannot get standard database path\n"));
  108. goto errHandle;
  109. }
  110. } else
  111. #endif // WIN32A_MODE
  112. {
  113. if (pszDatabasePath != NULL) {
  114. int nLen;
  115. _tcscpy(wszShimDB, pszDatabasePath);
  116. nLen = _tcslen(wszShimDB);
  117. if (nLen > 0 && TEXT('\\') == wszShimDB[nLen-1]) {
  118. wszShimDB[nLen-1] = TEXT('\0');
  119. }
  120. } else { // standard database path
  121. if (dwFlags & HID_DOS_PATHS) {
  122. SdbpGetAppPatchDir(wszShimDB);
  123. } else {
  124. _tcscpy(wszShimDB, TEXT("\\SystemRoot\\AppPatch"));
  125. }
  126. }
  127. _tcscat(wszShimDB, TEXT("\\sysmain.sdb"));
  128. }
  129. }
  130. pContext->pdbMain = SdbOpenDatabase(wszShimDB, dwFlagOpen);
  131. } __except(SHIM_EXCEPT_HANDLER) {
  132. pContext->pdbMain = NULL;
  133. }
  134. if (pContext->pdbMain == NULL) {
  135. DBGPRINT((sdlError, "SdbInitDatabase", "Unable to open main database sysmain.sdb.\n"));
  136. goto errHandle;
  137. }
  138. if (dwFlags & HID_DATABASE_FULLPATH) {
  139. // we are done, no test db
  140. goto InitDone;
  141. }
  142. //
  143. // Now try to open the systest.sdb if it exists.
  144. //
  145. __try {
  146. if (NULL != pszDatabasePath) {
  147. int nLen;
  148. _tcscpy(wszShimDB, pszDatabasePath);
  149. nLen = _tcslen(wszShimDB);
  150. if (nLen > 0 && TEXT('\\') == wszShimDB[nLen-1]) {
  151. wszShimDB[nLen-1] = TEXT('\0');
  152. }
  153. } else { // standard database path
  154. if (dwFlags & HID_DOS_PATHS) {
  155. SdbpGetAppPatchDir(wszShimDB);
  156. } else {
  157. _tcscpy(wszShimDB, TEXT("\\SystemRoot\\AppPatch"));
  158. }
  159. }
  160. _tcscat(wszShimDB, TEXT("\\systest.sdb"));
  161. pContext->pdbTest = SdbOpenDatabase(wszShimDB, dwFlagOpen);
  162. } __except(SHIM_EXCEPT_HANDLER) {
  163. pContext->pdbTest = NULL;
  164. }
  165. if (pContext->pdbTest == NULL) {
  166. DBGPRINT((sdlInfo, "SdbInitDatabase", "No systest.sdb found.\n"));
  167. }
  168. InitDone:
  169. //
  170. // Initialize new members (local db support)
  171. //
  172. if (pContext->pdbMain) {
  173. pContext->rgSDB[0].pdb = pContext->pdbMain;
  174. pContext->rgSDB[0].dwFlags = SDBENTRY_VALID_ENTRY|SDBENTRY_VALID_GUID;
  175. RtlCopyMemory(&pContext->rgSDB[0].guidDB, &GUID_SYSMAIN_SDB, sizeof(GUID));
  176. SDBCUSTOM_SET_MASK(pContext, SDB_MASK_TO_INDEX(PDB_MAIN));
  177. }
  178. if (pContext->pdbTest) {
  179. pContext->rgSDB[1].pdb = pContext->pdbTest;
  180. pContext->rgSDB[1].dwFlags = SDBENTRY_VALID_ENTRY|SDBENTRY_VALID_GUID;
  181. RtlCopyMemory(&pContext->rgSDB[1].guidDB, &GUID_SYSTEST_SDB, sizeof(GUID));
  182. SDBCUSTOM_SET_MASK(pContext, SDB_MASK_TO_INDEX(PDB_TEST));
  183. }
  184. //
  185. // Initialize architecture
  186. //
  187. pContext->dwRuntimePlatform = SdbpGetProcessorArchitecture();
  188. //
  189. // Initialize OS SKU and SP
  190. //
  191. SdbpGetOSSKU(&pContext->dwOSSKU, &pContext->dwSPMask);
  192. #ifndef WIN32A_MODE
  193. //
  194. // Finally, initialize the pipe
  195. //
  196. pContext->hPipe = SdbpOpenDebugPipe();
  197. #endif // WIN32A_MODE
  198. return (HSDB)pContext;
  199. errHandle:
  200. //
  201. // Cleanup on failure.
  202. //
  203. if (pContext != NULL) {
  204. if (pContext->pdbMain != NULL) {
  205. SdbCloseDatabaseRead(pContext->pdbMain);
  206. }
  207. if (pContext->pdbTest != NULL) {
  208. SdbCloseDatabaseRead(pContext->pdbTest);
  209. }
  210. SdbFree(pContext);
  211. }
  212. return NULL;
  213. }
  214. BOOL
  215. SdbpOpenAndMapFile(
  216. IN LPCTSTR szPath, // Filename
  217. OUT PIMAGEFILEDATA pImageData, // pointer to the structure to be filled
  218. IN PATH_TYPE ePathType // path type, only DOS_PATH is supported on win32
  219. )
  220. /*++
  221. Return: TRUE on success, FALSE otherwise.
  222. Desc: Opens a file and maps it into memory.
  223. --*/
  224. {
  225. HANDLE hFile;
  226. DWORD dwFlags = 0;
  227. if (pImageData->dwFlags & IMAGEFILEDATA_PBASEVALID) {
  228. //
  229. // special case, only headers are valid in our assumption
  230. //
  231. return TRUE;
  232. }
  233. if (pImageData->dwFlags & IMAGEFILEDATA_HANDLEVALID) {
  234. hFile = pImageData->hFile;
  235. dwFlags |= IMAGEFILEDATA_NOFILECLOSE;
  236. } else {
  237. hFile = SdbpOpenFile(szPath, ePathType);
  238. }
  239. if (hFile == INVALID_HANDLE_VALUE) {
  240. return FALSE;
  241. }
  242. if (!SdbpMapFile(hFile, pImageData)) {
  243. if (!(dwFlags & IMAGEFILEDATA_NOFILECLOSE)) {
  244. SdbpCloseFile(hFile);
  245. }
  246. return FALSE;
  247. }
  248. pImageData->dwFlags = dwFlags;
  249. return TRUE;
  250. }
  251. BOOL
  252. SdbpUnmapAndCloseFile(
  253. IN PIMAGEFILEDATA pImageData
  254. )
  255. /*++
  256. Return: BUGBUG: ?
  257. Desc: BUGBUG: ?
  258. --*/
  259. {
  260. HANDLE hFile;
  261. BOOL bSuccess;
  262. if (pImageData->dwFlags & IMAGEFILEDATA_PBASEVALID) { // externally supplied pointer
  263. RtlZeroMemory(pImageData, sizeof(*pImageData));
  264. return TRUE;
  265. }
  266. hFile = pImageData->hFile;
  267. bSuccess = SdbpUnmapFile(pImageData);
  268. if (hFile != INVALID_HANDLE_VALUE) {
  269. if (pImageData->dwFlags & IMAGEFILEDATA_NOFILECLOSE) {
  270. pImageData->hFile = INVALID_HANDLE_VALUE;
  271. } else {
  272. SdbpCloseFile(hFile);
  273. }
  274. }
  275. return bSuccess;
  276. }
  277. BOOL
  278. SdbpCleanupLocalDatabaseSupport(
  279. IN HSDB hSDB
  280. )
  281. {
  282. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  283. DWORD dwIndex;
  284. DWORD dwMask;
  285. //
  286. // Ee start with entry 2 -- to include local sdbs
  287. //
  288. if (pSdbContext->dwDatabaseMask & SDB_CUSTOM_MASK) {
  289. for (dwIndex = 3; dwIndex < ARRAYSIZE(pSdbContext->rgSDB); ++dwIndex) {
  290. dwMask = 1 << dwIndex;
  291. if (pSdbContext->dwDatabaseMask & dwMask) {
  292. SdbCloseLocalDatabaseEx(hSDB, NULL, dwIndex);
  293. }
  294. }
  295. }
  296. //
  297. // Always check for entry 2 (local sdb)
  298. //
  299. if (pSdbContext->pdbLocal != NULL) {
  300. SdbCloseLocalDatabaseEx(hSDB, NULL, SDB_MASK_TO_INDEX(PDB_LOCAL));
  301. }
  302. return TRUE;
  303. }
  304. BOOL
  305. SdbpIsLocalTempPDB(
  306. IN HSDB hSDB,
  307. IN PDB pdb
  308. )
  309. {
  310. PSDBENTRY pEntry = SDBGETLOCALENTRY(hSDB);
  311. if (pEntry->dwFlags & SDBENTRY_VALID_ENTRY) {
  312. return pdb == pEntry->pdb;
  313. }
  314. return FALSE;
  315. }
  316. BOOL
  317. SdbpIsMainPDB(
  318. IN HSDB hSDB,
  319. IN PDB pdb
  320. )
  321. {
  322. DWORD dwIndex;
  323. if (!SdbpFindLocalDatabaseByPDB(hSDB, pdb, FALSE, &dwIndex)) {
  324. return FALSE;
  325. }
  326. return (dwIndex == SDB_MASK_TO_INDEX(PDB_MAIN) || dwIndex == SDB_MASK_TO_INDEX(PDB_TEST));
  327. }
  328. BOOL
  329. SdbpFindLocalDatabaseByPDB(
  330. IN HSDB hSDB,
  331. IN PDB pdb,
  332. IN BOOL bExcludeLocalDB, // exclude local db entry?
  333. OUT LPDWORD pdwIndex
  334. )
  335. {
  336. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  337. DWORD dwIndex;
  338. PSDBENTRY pEntry;
  339. BOOL bSuccess = FALSE;
  340. for (dwIndex = 0; dwIndex < ARRAYSIZE(pSdbContext->rgSDB); ++dwIndex) {
  341. if (bExcludeLocalDB && dwIndex == SDB_MASK_TO_INDEX(PDB_LOCAL)) {
  342. continue;
  343. }
  344. if (!SDBCUSTOM_CHECK_INDEX(hSDB, dwIndex)) {
  345. continue;
  346. }
  347. pEntry = &pSdbContext->rgSDB[dwIndex];
  348. if ((pEntry->dwFlags & SDBENTRY_VALID_ENTRY) && (pdb == pEntry->pdb)) {
  349. bSuccess = TRUE;
  350. break;
  351. }
  352. }
  353. if (bSuccess && pdwIndex != NULL) {
  354. *pdwIndex = dwIndex;
  355. }
  356. return bSuccess;
  357. }
  358. BOOL
  359. SdbpFindLocalDatabaseByGUID(
  360. IN HSDB hSDB,
  361. IN GUID* pGuidDB,
  362. IN BOOL bExcludeLocalDB,
  363. OUT LPDWORD pdwIndex // this index (if valid) will work as an initial point for comparison
  364. )
  365. {
  366. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  367. PSDBENTRY pEntry;
  368. DWORD dwIndex;
  369. for (dwIndex = 0; dwIndex < ARRAYSIZE(pSdbContext->rgSDB); ++dwIndex) {
  370. if (bExcludeLocalDB && dwIndex == SDB_MASK_TO_INDEX(PDB_LOCAL)) {
  371. continue;
  372. }
  373. if (!SDBCUSTOM_CHECK_INDEX(hSDB, dwIndex)) {
  374. continue;
  375. }
  376. pEntry = SDBGETENTRY(hSDB, dwIndex);
  377. if (!(pEntry->dwFlags & SDBENTRY_VALID_GUID)) {
  378. //
  379. // if this happens to be a valid database -- get it's guid
  380. //
  381. if ((pEntry->dwFlags & SDBENTRY_VALID_ENTRY) && (pEntry->pdb != NULL)) {
  382. //
  383. // retrieve guid
  384. //
  385. GUID guidDB;
  386. if (SdbGetDatabaseGUID(hSDB, pEntry->pdb, &guidDB)) {
  387. pEntry->guidDB = guidDB;
  388. pEntry->dwFlags |= SDBENTRY_VALID_GUID;
  389. goto checkEntry;
  390. }
  391. }
  392. continue;
  393. }
  394. checkEntry:
  395. if (RtlEqualMemory(&pEntry->guidDB, pGuidDB, sizeof(GUID))) {
  396. if (pdwIndex) {
  397. *pdwIndex = dwIndex;
  398. }
  399. return TRUE;
  400. }
  401. }
  402. return FALSE;
  403. }
  404. DWORD
  405. SdbpFindFreeLocalEntry(
  406. IN HSDB hSDB
  407. )
  408. {
  409. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  410. DWORD dwIndex;
  411. for (dwIndex = 3; dwIndex < ARRAYSIZE(pSdbContext->rgSDB); ++dwIndex) {
  412. if (SDBCUSTOM_CHECK_INDEX(hSDB, dwIndex)) {
  413. continue;
  414. }
  415. if (!(pSdbContext->rgSDB[dwIndex].dwFlags & (SDBENTRY_VALID_ENTRY | SDBENTRY_VALID_GUID))) {
  416. return dwIndex;
  417. }
  418. }
  419. //
  420. // We have no entry
  421. //
  422. return SDBENTRY_INVALID_INDEX;
  423. }
  424. /*++
  425. returns SDBENTRY_INVALID_INDEX if none could be found
  426. if success, returns an index where the local db entry was found
  427. --*/
  428. DWORD
  429. SdbpRetainLocalDBEntry(
  430. IN HSDB hSDB,
  431. OUT PDB* ppPDB OPTIONAL // optional pointer to the pdb
  432. )
  433. {
  434. DWORD dwIndex = SDBENTRY_INVALID_INDEX;
  435. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  436. PSDBENTRY pEntry;
  437. PSDBENTRY pEntryLocal = SDBGETLOCALENTRY(hSDB);
  438. GUID guidDB;
  439. if (pEntryLocal->pdb == NULL || !(pEntryLocal->dwFlags & SDBENTRY_VALID_ENTRY)) {
  440. return SDBENTRY_INVALID_INDEX;
  441. }
  442. //
  443. // Recycling could be done here so that we reuse custom db entries which
  444. // may have been opened already (for instance set by __COMPAT_LAYER)
  445. //
  446. if (SdbGetDatabaseGUID(hSDB, pEntryLocal->pdb, &guidDB) &&
  447. SdbpFindLocalDatabaseByGUID(hSDB, &guidDB, TRUE, &dwIndex) &&
  448. dwIndex != SDBENTRY_INVALID_INDEX) {
  449. //
  450. // Close the local db
  451. //
  452. SdbCloseLocalDatabase(hSDB);
  453. pEntry = SDBGETENTRY(hSDB, dwIndex);
  454. pSdbContext->pdbLocal = pEntry->pdb;
  455. if (ppPDB != NULL) {
  456. *ppPDB = pEntry->pdb;
  457. }
  458. return dwIndex;
  459. }
  460. //
  461. // An attempt to recycle has failed -- allocate new entry
  462. //
  463. dwIndex = SdbpFindFreeLocalEntry(hSDB);
  464. if (dwIndex != SDBENTRY_INVALID_INDEX) {
  465. //
  466. // We have found an empty slot, relocate
  467. //
  468. pEntry = SDBGETENTRY(hSDB, dwIndex);
  469. RtlCopyMemory(pEntry, pEntryLocal, sizeof(SDBENTRY));
  470. RtlZeroMemory(pEntryLocal, sizeof(SDBENTRY));
  471. SDBCUSTOM_SET_MASK(hSDB, dwIndex);
  472. if (ppPDB != NULL) {
  473. *ppPDB = pEntry->pdb;
  474. }
  475. //
  476. // Note that pdbLocal is still valid, we never close this handle manually though
  477. //
  478. }
  479. return dwIndex;
  480. }
  481. BOOL
  482. SdbCloseLocalDatabaseEx(
  483. IN HSDB hSDB,
  484. IN PDB pdb,
  485. IN DWORD dwIndex
  486. )
  487. {
  488. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  489. PSDBENTRY pEntry;
  490. DWORD dwMask;
  491. if (pdb != NULL) {
  492. if (!SdbpFindLocalDatabaseByPDB(hSDB, pdb, FALSE, &dwIndex)) {
  493. return FALSE;
  494. }
  495. }
  496. dwMask = 1 << dwIndex;
  497. if (dwIndex >= ARRAYSIZE(pSdbContext->rgSDB) || !(pSdbContext->dwDatabaseMask & dwMask)) {
  498. return FALSE;
  499. }
  500. pEntry = &pSdbContext->rgSDB[dwIndex];
  501. if (pEntry->dwFlags & SDBENTRY_VALID_ENTRY) {
  502. if (pEntry->pdb) {
  503. SdbCloseDatabaseRead(pEntry->pdb);
  504. }
  505. }
  506. RtlZeroMemory(pEntry, sizeof(*pEntry));
  507. SDBCUSTOM_CLEAR_MASK(hSDB, dwIndex);
  508. if (dwIndex == SDB_MASK_TO_INDEX(PDB_LOCAL)) {
  509. pSdbContext->pdbLocal = NULL;
  510. }
  511. return TRUE;
  512. }
  513. BOOL
  514. SdbOpenLocalDatabaseEx(
  515. IN HSDB hSDB,
  516. IN LPCVOID pDatabaseID,
  517. IN DWORD dwFlags,
  518. OUT PDB* pPDB OPTIONAL,
  519. IN OUT LPDWORD pdwLocalDBMask OPTIONAL // local db mask for tagref
  520. )
  521. {
  522. PSDBCONTEXT pSdbContext = (PSDBCONTEXT)hSDB;
  523. PDB pdb;
  524. DWORD dwOpenFlags = DOS_PATH;
  525. TCHAR szDatabasePath[MAX_PATH];
  526. LPTSTR pszDatabasePath;
  527. GUID guidDB;
  528. GUID* pGuidDB;
  529. DWORD dwDatabaseType = 0;
  530. DWORD dwCount;
  531. BOOL bSuccess = FALSE;
  532. DWORD dwIndex;
  533. PSDBENTRY pEntry;
  534. if (!(SDBCUSTOM_FLAGS(dwFlags) & SDBCUSTOM_USE_INDEX)) {
  535. //
  536. // Find free local sdb entry
  537. //
  538. dwIndex = SdbpFindFreeLocalEntry(hSDB);
  539. if (dwIndex == SDBENTRY_INVALID_INDEX) {
  540. DBGPRINT((sdlError,
  541. "SdbOpenLocalDatabaseEx",
  542. "No more free entries in local db table\n"));
  543. goto cleanup;
  544. }
  545. pEntry = &pSdbContext->rgSDB[dwIndex];
  546. } else {
  547. dwIndex = *pdwLocalDBMask;
  548. if (dwIndex & TAGREF_STRIP_PDB) {
  549. dwIndex = SDB_MASK_TO_INDEX(dwIndex);
  550. }
  551. if (dwIndex >= ARRAYSIZE(pSdbContext->rgSDB)) {
  552. DBGPRINT((sdlError,
  553. "SdbOpenLocalDatabaseEx",
  554. "Bad index 0x%lx\n",
  555. dwIndex));
  556. goto cleanup;
  557. }
  558. if (dwIndex < 2) {
  559. DBGPRINT((sdlWarning,
  560. "SdbOpenLocalDatabaseEx",
  561. "Unusual use of SdbOpenLocalDatabaseEx index 0x%lx\n",
  562. dwIndex));
  563. }
  564. pEntry = &pSdbContext->rgSDB[dwIndex];
  565. SdbCloseLocalDatabaseEx(hSDB, NULL, dwIndex);
  566. }
  567. switch (SDBCUSTOM_TYPE(dwFlags)) {
  568. case SDBCUSTOM_PATH:
  569. if (SDBCUSTOM_PATH_NT & SDBCUSTOM_FLAGS(dwFlags)) {
  570. dwOpenFlags = NT_PATH;
  571. }
  572. pszDatabasePath = (LPTSTR)pDatabaseID;
  573. pGuidDB = NULL;
  574. break;
  575. case SDBCUSTOM_GUID:
  576. if (SDBCUSTOM_GUID_STRING & SDBCUSTOM_FLAGS(dwFlags)) {
  577. if (!SdbGUIDFromString((LPCTSTR)pDatabaseID, &guidDB)) {
  578. DBGPRINT((sdlError,
  579. "SdbOpenLocalDatabaseEx",
  580. "Cannot convert \"%s\" to guid\n",
  581. (LPCTSTR)pDatabaseID));
  582. goto cleanup;
  583. }
  584. pGuidDB = &guidDB;
  585. } else {
  586. pGuidDB = (GUID*)pDatabaseID;
  587. }
  588. dwCount = SdbResolveDatabase(pGuidDB,
  589. &dwDatabaseType,
  590. szDatabasePath,
  591. CHARCOUNT(szDatabasePath));
  592. if (dwCount == 0 || dwCount >= CHARCOUNT(szDatabasePath)) {
  593. DBGPRINT((sdlError,
  594. "SdbOpenLocalDatabaseEx",
  595. "Cannot resolve database, the path length is 0x%lx\n",
  596. dwCount));
  597. goto cleanup;
  598. }
  599. pszDatabasePath = szDatabasePath;
  600. break;
  601. default:
  602. DBGPRINT((sdlError, "SdbOpenLocalDatabaseEx", "Bad flags 0x%lx\n", dwFlags));
  603. goto cleanup;
  604. break;
  605. }
  606. pdb = SdbOpenDatabase(pszDatabasePath, dwOpenFlags);
  607. if (pdb == NULL) {
  608. //
  609. // dbgprint not needed here
  610. //
  611. goto cleanup;
  612. }
  613. pSdbContext->rgSDB[dwIndex].pdb = pdb;
  614. pSdbContext->rgSDB[dwIndex].dwFlags = SDBENTRY_VALID_ENTRY;
  615. SDBCUSTOM_SET_MASK(pSdbContext, dwIndex);
  616. if (pGuidDB != NULL) {
  617. RtlCopyMemory(&pSdbContext->rgSDB[dwIndex].guidDB, pGuidDB, sizeof(GUID));
  618. pSdbContext->rgSDB[dwIndex].dwFlags |= SDBENTRY_VALID_GUID;
  619. } else {
  620. RtlZeroMemory(&pSdbContext->rgSDB[dwIndex].guidDB, sizeof(GUID));
  621. }
  622. bSuccess = TRUE;
  623. cleanup:
  624. if (bSuccess) {
  625. if (dwIndex == SDB_MASK_TO_INDEX(PDB_LOCAL)) {
  626. pSdbContext->pdbLocal = pdb;
  627. }
  628. if (pdwLocalDBMask != NULL) {
  629. *pdwLocalDBMask = SDB_INDEX_TO_MASK(dwIndex);
  630. }
  631. if (pPDB != NULL) {
  632. *pPDB = pdb;
  633. }
  634. }
  635. return bSuccess;
  636. }
  637. BOOL
  638. SdbOpenLocalDatabase(
  639. IN HSDB hSDB, // handle to the database channel
  640. IN LPCTSTR pszLocalDatabase // full DOS path to the local database to open.
  641. )
  642. /*++
  643. Return: TRUE on success, FALSE otherwise.
  644. Desc: Opens a local database.
  645. --*/
  646. {
  647. DWORD dwIndex = PDB_LOCAL;
  648. BOOL bSuccess;
  649. bSuccess = SdbOpenLocalDatabaseEx(hSDB,
  650. pszLocalDatabase,
  651. (SDBCUSTOM_PATH_DOS | SDBCUSTOM_USE_INDEX),
  652. NULL,
  653. &dwIndex);
  654. return bSuccess;
  655. }
  656. BOOL
  657. SdbCloseLocalDatabase(
  658. IN HSDB hSDB // handle to the database channel
  659. )
  660. /*++
  661. Return: TRUE on success, FALSE otherwise.
  662. Desc: Closes the local database.
  663. --*/
  664. {
  665. return SdbCloseLocalDatabaseEx(hSDB, NULL, SDB_MASK_TO_INDEX(PDB_LOCAL));
  666. }
  667. TAGREF
  668. SdbGetItemFromItemRef(
  669. IN HSDB hSDB, // handle to the database channel
  670. IN TAGREF trItemRef, // TAGREF of a DLL_REF record
  671. IN TAG tagItemKey, // key that has the name of the item (TAG_NAME)
  672. IN TAG tagItemTAGID, // tag that points to the location of the desired item by it's tagid
  673. IN TAG tagItem // what to look for under Library
  674. )
  675. /*++
  676. Return: TAGREF of a DLL record that matches the DLL_REF.
  677. Desc: Given a TAGREF that points to a *tag*_REF type tag, searches through
  678. the various databases for the matching tag (generally located
  679. under the LIBRARY tag in gpdbMain).
  680. if bAllowNonMain is specified then the library section is looked up
  681. in the same database where trItemRef was found. This is used with
  682. MSI transforms - to locate and extract them from custom databases.
  683. This flag IS NOT used for other components - such as patches and
  684. shim dlls. This is ensured through the macros -
  685. SdbGetShimFromShimRef(hSDB, trShimRef)
  686. and
  687. SdbGetPatchFromPatchRef(hSDB, trPatchRef)
  688. Both of these macros call this function with bAllowNonMain set to FALSE
  689. --*/
  690. {
  691. PSDBCONTEXT pDbContext = (PSDBCONTEXT)hSDB;
  692. TAGID tiItemRef = TAGID_NULL;
  693. PDB pdbItemRef = NULL;
  694. TAGREF trReturn = TAGREF_NULL;
  695. TAGID tiReturn = TAGID_NULL;
  696. TAGID tiDatabase = TAGID_NULL;
  697. TAGID tiLibrary = TAGID_NULL;
  698. TAGID tiItemTagID = TAGID_NULL;
  699. TAGID tiItemName;
  700. LPTSTR szItemName = NULL;
  701. try {
  702. //
  703. // Find first which database contains the reference TAGREF.
  704. //
  705. if (!SdbTagRefToTagID(pDbContext, trItemRef, &pdbItemRef, &tiItemRef)){
  706. DBGPRINT((sdlError, "SdbGetItemFromItemRef", "Can't convert tag ref.\n"));
  707. goto out;
  708. }
  709. //
  710. // First check if there's a TAG_item_TAGID that tells us exactly
  711. // where the item is within the current database.
  712. //
  713. tiItemTagID = SdbFindFirstTag(pdbItemRef, tiItemRef, tagItemTAGID);
  714. if (tiItemTagID != TAGID_NULL) {
  715. tiReturn = (TAGID)SdbReadDWORDTag(pdbItemRef, tiItemTagID, 0);
  716. if (tiReturn != TAGID_NULL) {
  717. goto out;
  718. }
  719. }
  720. if (pdbItemRef == pDbContext->pdbMain) {
  721. goto checkMainDatabase;
  722. }
  723. //
  724. // Then check for the item in the LIBRARY section of the
  725. // current database.
  726. //
  727. tiDatabase = SdbFindFirstTag(pdbItemRef, TAGID_ROOT, TAG_DATABASE);
  728. if (!tiDatabase) {
  729. DBGPRINT((sdlError,
  730. "SdbGetItemFromItemRef",
  731. "Can't find DATABASE tag in db.\n"));
  732. goto checkMainDatabase;
  733. }
  734. tiLibrary = SdbFindFirstTag(pdbItemRef, tiDatabase, TAG_LIBRARY);
  735. if (!tiLibrary) {
  736. //
  737. // This library doesn't have a LIBRARY section. That's ok, go check
  738. // sysmain.sdb.
  739. //
  740. goto checkMainDatabase;
  741. }
  742. //
  743. // We need to search by name.
  744. //
  745. tiItemName = SdbFindFirstTag(pdbItemRef, tiItemRef, tagItemKey);
  746. if (!tiItemName) {
  747. goto out;
  748. }
  749. szItemName = SdbGetStringTagPtr(pdbItemRef, tiItemName);
  750. if (!szItemName) {
  751. goto out;
  752. }
  753. tiReturn = SdbFindFirstNamedTag(pdbItemRef,
  754. tiLibrary,
  755. tagItem,
  756. tagItemKey,
  757. szItemName);
  758. if (tiReturn != TAGID_NULL) {
  759. goto out;
  760. }
  761. checkMainDatabase:
  762. tiDatabase = SdbFindFirstTag(pDbContext->pdbMain, TAGID_ROOT, TAG_DATABASE);
  763. if (!tiDatabase) {
  764. DBGPRINT((sdlError,
  765. "SdbGetItemFromItemRef",
  766. "Can't find DATABASE tag in main db.\n"));
  767. goto out;
  768. }
  769. tiLibrary = SdbFindFirstTag(pDbContext->pdbMain, tiDatabase, TAG_LIBRARY);
  770. if (!tiLibrary) {
  771. DBGPRINT((sdlError,
  772. "SdbGetItemFromItemRef",
  773. "Can't find LIBRARY tag in main db.\n"));
  774. goto out;
  775. }
  776. //
  777. // We need to search by name.
  778. //
  779. if (szItemName == NULL) {
  780. tiItemName = SdbFindFirstTag(pdbItemRef, tiItemRef, tagItemKey);
  781. if (!tiItemName) {
  782. goto out;
  783. }
  784. szItemName = SdbGetStringTagPtr(pdbItemRef, tiItemName);
  785. if (!szItemName) {
  786. goto out;
  787. }
  788. }
  789. tiReturn = SdbFindFirstNamedTag(pDbContext->pdbMain,
  790. tiLibrary,
  791. tagItem,
  792. tagItemKey,
  793. szItemName);
  794. pdbItemRef = pDbContext->pdbMain;
  795. } except (SHIM_EXCEPT_HANDLER) {
  796. tiReturn = TAGID_NULL;
  797. trReturn = TAGREF_NULL;
  798. }
  799. out:
  800. if (tiReturn) {
  801. assert(pdbItemRef != NULL);
  802. if (!SdbTagIDToTagRef(pDbContext, pdbItemRef, tiReturn, &trReturn)) {
  803. trReturn = TAGREF_NULL;
  804. }
  805. }
  806. if (trReturn == TAGREF_NULL) {
  807. DBGPRINT((sdlError,
  808. "SdbGetItemFromItemRef",
  809. "Can't find tag for tag ref 0x%x.\n", trItemRef));
  810. }
  811. return trReturn;
  812. }
  813. TAGID
  814. SdbpGetLibraryFile(
  815. IN PDB pdb, // handle to the database channel
  816. IN LPCTSTR szDllName // the name of the DLL
  817. )
  818. /*++
  819. Return: The TAGID of the DLL used by the specified shim.
  820. Desc: This function gets the TAGID of the DLL with the specified name.
  821. --*/
  822. {
  823. TAGID tiDatabase;
  824. TAGID tiLibrary;
  825. TAGID tiDll = TAG_NULL;
  826. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  827. if (!tiDatabase) {
  828. DBGPRINT((sdlError, "SdbpGetLibraryFile", "Can't find DATABASE tag in main db.\n"));
  829. goto out;
  830. }
  831. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  832. if (!tiLibrary) {
  833. DBGPRINT((sdlError, "SdbpGetLibraryFile", "Can't find LIBRARY tag in main db.\n"));
  834. goto out;
  835. }
  836. tiDll = SdbFindFirstNamedTag(pdb, tiLibrary, TAG_FILE, TAG_NAME, szDllName);
  837. if (!tiDll) {
  838. DBGPRINT((sdlError,
  839. "SdbpGetLibraryFile", "Can't find FILE \"%s\" in main db library.\n",
  840. szDllName));
  841. goto out;
  842. }
  843. out:
  844. return tiDll;
  845. }
  846. BOOL
  847. SdbGetDllPath(
  848. IN HSDB hSDB, // handle to the database channel
  849. IN TAGREF trShimRef, // SHIM_REF to use to search for the DLL
  850. OUT LPTSTR pwszBuffer // Buffer to fill with the path to the DLL containing
  851. // the specified shim.
  852. )
  853. /*++
  854. Return: TRUE if the DLL was found, FALSE otherwise.
  855. Desc: Hunts for the DLL file on disk, first in the same
  856. directory as the EXE (if there was a local database opened), then
  857. in the %windir%\AppPatch directory.
  858. Always fills in a DOS_PATH type path (UNC or 'x:').
  859. --*/
  860. {
  861. BOOL bReturn = FALSE;
  862. HANDLE hFile = INVALID_HANDLE_VALUE;
  863. PBYTE pBuffer = NULL;
  864. DWORD dwSize;
  865. TAGREF trShim;
  866. TAGREF trDll;
  867. TAGREF trDllBits;
  868. TAGREF trName;
  869. TCHAR szFile[2 * MAX_PATH];
  870. TCHAR szName[MAX_PATH];
  871. assert(pwszBuffer);
  872. try {
  873. //
  874. // Initialize the return buffer.
  875. //
  876. pwszBuffer[0] = _T('\0');
  877. SdbpGetAppPatchDir(szFile);
  878. _tcscat(szFile, _T("\\"));
  879. //
  880. // Look for the SHIM record in the LIBRARY section.
  881. //
  882. trShim = SdbGetShimFromShimRef(hSDB, trShimRef);
  883. if (trShim == TAGREF_NULL) {
  884. //
  885. // No SHIM in LIBRARY. Error out.
  886. //
  887. DBGPRINT((sdlError, "SdbGetDllPath", "No SHIM in LIBRARY.\n"));
  888. goto out;
  889. }
  890. //
  891. // Get the name of the file that contains this shim.
  892. //
  893. trName = SdbFindFirstTagRef(hSDB, trShim, TAG_DLLFILE);
  894. if (trName == TAGREF_NULL) {
  895. //
  896. // Nope, and we need one. Error out.
  897. //
  898. DBGPRINT((sdlError, "SdbGetDllPath", "No DLLFILE for the SHIM in LIBRARY.\n"));
  899. goto out;
  900. }
  901. if (!SdbReadStringTagRef(hSDB, trName, szName, MAX_PATH)) {
  902. DBGPRINT((sdlError, "SdbGetDllPath", "Can't read DLL name.\n"));
  903. goto out;
  904. }
  905. //
  906. // Check if the file is already on the disk.
  907. // Look in %windir%\AppPatch directory for the DLL.
  908. //
  909. _tcscat(szFile, szName);
  910. _tcscpy(pwszBuffer, szFile);
  911. DBGPRINT((sdlInfo, "SdbGetDllPath", "Opening file \"%s\".\n", szFile));
  912. hFile = SdbpOpenFile(szFile, DOS_PATH);
  913. if (hFile != INVALID_HANDLE_VALUE) {
  914. bReturn = TRUE;
  915. goto out;
  916. }
  917. out:
  918. ;
  919. } except (SHIM_EXCEPT_HANDLER) {
  920. bReturn = FALSE;
  921. }
  922. if (hFile != INVALID_HANDLE_VALUE) {
  923. SdbpCloseFile(hFile);
  924. }
  925. if (pBuffer != NULL) {
  926. SdbFree(pBuffer);
  927. }
  928. if (bReturn) {
  929. DBGPRINT((sdlInfo, "SdbGetDllPath", "Using DLL \"%s\".\n", szFile));
  930. }
  931. return bReturn;
  932. }
  933. BOOL
  934. SdbReadPatchBits(
  935. IN HSDB hSDB, // handle to the database channel
  936. IN TAGREF trPatchRef, // PATCH_REF to use to find the PATCH
  937. OUT PVOID pBuffer, // buffer to fill with bits
  938. OUT LPDWORD lpdwBufferSize // size of passed-in buffer
  939. )
  940. /*++
  941. Return: Returns TRUE on success, FALSE on failure.
  942. Desc: Looks for the patch, first on disk, then in the DB, and fills
  943. pBuffer with the bits. If the size specified in lpdwBufferSize is
  944. less than the size of the patch this function will return in
  945. lpdwBufferSize the size required. In that case pBuffer is ignored
  946. and can be NULL.
  947. --*/
  948. {
  949. BOOL bReturn = FALSE;
  950. TAGID tiPatchRef = TAGID_NULL;
  951. PDB pdb = NULL;
  952. LPTSTR szName = NULL;
  953. TAGREF trPatch = TAGREF_NULL;
  954. TAGREF trPatchBits = TAGREF_NULL;
  955. TAGID tiName = TAGID_NULL;
  956. DWORD dwSize;
  957. try {
  958. if (!SdbTagRefToTagID(hSDB, trPatchRef, &pdb, &tiPatchRef)) {
  959. DBGPRINT((sdlError, "SdbReadPatchBits", "Can't convert tag ref.\n"));
  960. goto out;
  961. }
  962. tiName = SdbFindFirstTag(pdb, tiPatchRef, TAG_NAME);
  963. if (!tiName) {
  964. DBGPRINT((sdlError, "SdbReadPatchBits", "Can't find the name tag.\n"));
  965. goto out;
  966. }
  967. szName = SdbGetStringTagPtr(pdb, tiName);
  968. if (!szName) {
  969. DBGPRINT((sdlError, "SdbReadPatchBits", "Can't read the name of the patch.\n"));
  970. goto out;
  971. }
  972. //
  973. // Look in the main database for the patch bits.
  974. //
  975. trPatch = SdbGetPatchFromPatchRef(hSDB, trPatchRef);
  976. if (!trPatch) {
  977. DBGPRINT((sdlError, "SdbReadPatchBits", "Can't get the patch tag.\n"));
  978. goto out;
  979. }
  980. trPatchBits = SdbFindFirstTagRef(hSDB, trPatch, TAG_PATCH_BITS);
  981. if (!trPatchBits) {
  982. DBGPRINT((sdlError, "SdbReadPatchBits", "Can't get the patch bits tag.\n"));
  983. goto out;
  984. }
  985. dwSize = SdbpGetTagRefDataSize(hSDB, trPatchBits);
  986. if (dwSize == 0) {
  987. DBGPRINT((sdlError, "SdbReadPatchBits", "Corrupt database. Zero sized patch.\n"));
  988. goto out;
  989. }
  990. //
  991. // Check for buffer size.
  992. //
  993. if (dwSize > *lpdwBufferSize) {
  994. *lpdwBufferSize = dwSize;
  995. goto out;
  996. }
  997. //
  998. // Read the bits if the buffer is big enough.
  999. //
  1000. *lpdwBufferSize = dwSize;
  1001. if (!SdbpReadBinaryTagRef(hSDB, trPatchBits, pBuffer, dwSize)) {
  1002. DBGPRINT((sdlError, "SdbReadPatchBits", "Cannot get the patch bits.\n"));
  1003. goto out;
  1004. }
  1005. bReturn = TRUE;
  1006. } except (SHIM_EXCEPT_HANDLER) {
  1007. bReturn = FALSE;
  1008. }
  1009. out:
  1010. return bReturn;
  1011. }