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.

947 lines
24 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. dbaccess.c
  5. Abstract:
  6. This module implements APIs to access the shim database.
  7. Author:
  8. dmunsil created sometime in 1999
  9. Revision History:
  10. several people contributed (vadimb, clupu, ...)
  11. --*/
  12. #include "sdbp.h"
  13. #if defined(KERNEL_MODE) && defined(ALLOC_PRAGMA)
  14. #pragma alloc_text(PAGE, SdbReleaseDatabase)
  15. #pragma alloc_text(PAGE, SdbGetDatabaseVersion)
  16. #pragma alloc_text(PAGE, SdbGetDatabaseInformation)
  17. #pragma alloc_text(PAGE, SdbGetDatabaseID)
  18. #pragma alloc_text(PAGE, SdbFreeDatabaseInformation)
  19. #pragma alloc_text(PAGE, SdbGetDatabaseInformationByName)
  20. #pragma alloc_text(PAGE, SdbpGetDatabaseDescriptionPtr)
  21. #pragma alloc_text(PAGE, SdbpReadMappedData)
  22. #pragma alloc_text(PAGE, SdbpGetMappedData)
  23. #pragma alloc_text(PAGE, SdbOpenDatabase)
  24. #pragma alloc_text(PAGE, SdbpOpenDatabaseInMemory)
  25. #pragma alloc_text(PAGE, SdbCloseDatabaseRead)
  26. #pragma alloc_text(PAGE, SdbpOpenAndMapDB)
  27. #pragma alloc_text(PAGE, SdbpUnmapAndCloseDB)
  28. #pragma alloc_text(PAGE, SdbGetTagFromTagID)
  29. #pragma alloc_text(PAGE, SdbpGetNextTagId)
  30. #pragma alloc_text(PAGE, SdbGetFirstChild)
  31. #pragma alloc_text(PAGE, SdbGetNextChild)
  32. #pragma alloc_text(PAGE, SdbpCreateSearchPathPartsFromPath)
  33. #endif // KERNEL_MODE && ALLOC_PRAGMA
  34. void
  35. SdbReleaseDatabase(
  36. IN HSDB hSDB // handle to the database channel
  37. )
  38. /*++
  39. Return: void.
  40. Desc: This API should be called in pair with SdbInitDatabase.
  41. --*/
  42. {
  43. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  44. assert(pContext != NULL);
  45. //
  46. // Do everything under a try/except block so we don't screw the caller
  47. // if the databases are corrupt.
  48. //
  49. __try {
  50. #ifndef KERNEL_MODE
  51. SdbpCleanupLocalDatabaseSupport(hSDB);
  52. if (pContext->rgSDB[2].dwFlags & SDBENTRY_VALID_ENTRY) {
  53. SdbCloseDatabaseRead(pContext->rgSDB[2].pdb);
  54. }
  55. #endif // KERNEL_MODE
  56. if (pContext->pdbTest != NULL) {
  57. SdbCloseDatabaseRead(pContext->pdbTest);
  58. }
  59. if (pContext->pdbMain != NULL) {
  60. SdbCloseDatabaseRead(pContext->pdbMain);
  61. }
  62. //
  63. // Cleanup attributes.
  64. //
  65. SdbpCleanupAttributeMgr(pContext);
  66. #ifndef KERNEL_MODE
  67. //
  68. // Cleanup user sdb cache
  69. //
  70. SdbpCleanupUserSDBCache(pContext);
  71. #endif // KERNEL_MODE
  72. SdbFree(pContext);
  73. } __except (SHIM_EXCEPT_HANDLER) {
  74. ;
  75. }
  76. }
  77. BOOL
  78. SdbGetDatabaseVersion(
  79. IN LPCTSTR pszFileName, // the file name
  80. OUT LPDWORD lpdwMajor, // store the major version of the database
  81. OUT LPDWORD lpdwMinor // store the minor version of the database
  82. )
  83. /*++
  84. Return: void.
  85. Desc: This API should be called in pair with SdbInitDatabase.
  86. --*/
  87. {
  88. PDB pdb;
  89. SDBDATABASEINFO DBInfo;
  90. pdb = SdbAlloc(sizeof(DB));
  91. if (pdb == NULL) {
  92. DBGPRINT((sdlError, "SdbGetDatabaseVersion", "Can't allocate DB structure.\n"));
  93. return FALSE;
  94. }
  95. if (!SdbpOpenAndMapDB(pdb, pszFileName, DOS_PATH)) {
  96. DBGPRINT((sdlError,
  97. "SdbGetDatabaseVersion",
  98. "Failed to open the database \"%s\".\n",
  99. pszFileName));
  100. goto err1;
  101. }
  102. pdb->bWrite = FALSE;
  103. pdb->dwSize = SdbpGetFileSize(pdb->hFile);
  104. if (!SdbGetDatabaseInformation(pdb, &DBInfo)) {
  105. DBGPRINT((sdlError, "SdbGetDatabaseVersion", "Can't read database information.\n"));
  106. goto err2;
  107. }
  108. *lpdwMajor = DBInfo.dwVersionMajor;
  109. *lpdwMinor = DBInfo.dwVersionMinor;
  110. err2:
  111. SdbpUnmapAndCloseDB(pdb);
  112. err1:
  113. SdbFree(pdb);
  114. return TRUE;
  115. }
  116. BOOL
  117. SDBAPI
  118. SdbGetDatabaseInformation(
  119. IN PDB pdb,
  120. OUT PSDBDATABASEINFO pSdbInfo
  121. )
  122. {
  123. DB_HEADER DBHeader;
  124. BOOL bReturn = FALSE;
  125. RtlZeroMemory(pSdbInfo, sizeof(*pSdbInfo));
  126. if (!SdbpReadMappedData(pdb, 0, &DBHeader, sizeof(DB_HEADER))) {
  127. DBGPRINT((sdlError, "SdbGetDatabaseInformation", "Can't read database header.\n"));
  128. goto errHandle;
  129. }
  130. if (DBHeader.dwMagic != SHIMDB_MAGIC) {
  131. DBGPRINT((sdlError,
  132. "SdbGetDatabaseInformation",
  133. "Magic doesn't match. Magic: 0x%08X, Expected: 0x%08X.\n",
  134. DBHeader.dwMagic,
  135. (DWORD)SHIMDB_MAGIC));
  136. goto errHandle;
  137. }
  138. pSdbInfo->dwVersionMajor = DBHeader.dwMajorVersion;
  139. pSdbInfo->dwVersionMinor = DBHeader.dwMinorVersion;
  140. //
  141. // Id and description are optional
  142. //
  143. if (SdbGetDatabaseID(pdb, &pSdbInfo->guidDB)) {
  144. pSdbInfo->dwFlags |= DBINFO_GUID_VALID;
  145. }
  146. //
  147. // Now try to get valid description.
  148. //
  149. pSdbInfo->pszDescription = (LPTSTR)SdbpGetDatabaseDescriptionPtr(pdb);
  150. bReturn = TRUE;
  151. errHandle:
  152. return bReturn;
  153. }
  154. BOOL
  155. SDBAPI
  156. SdbGetDatabaseID(
  157. IN PDB pdb,
  158. OUT GUID* pguidDB
  159. )
  160. {
  161. TAGID tiDatabase;
  162. TAGID tiGuidID;
  163. BOOL bReturn = FALSE;
  164. if (!(pdb->dwFlags & DB_GUID_VALID)) {
  165. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  166. if (!tiDatabase) {
  167. DBGPRINT((sdlError, "SdbGetDatabaseID", "Failed to get root tag\n"));
  168. goto errHandle;
  169. }
  170. tiGuidID = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  171. if (!tiGuidID) {
  172. DBGPRINT((sdlWarning, "SdbGetDatabaseID", "Failed to get the database id\n"));
  173. goto errHandle;
  174. }
  175. if (!SdbReadBinaryTag(pdb, tiGuidID, (PBYTE)&pdb->guidDB, sizeof(GUID))) {
  176. DBGPRINT((sdlError,
  177. "SdbGetDatabaseID",
  178. "Failed to read database id 0x%lx\n",
  179. tiGuidID));
  180. goto errHandle;
  181. }
  182. pdb->dwFlags |= DB_GUID_VALID;
  183. }
  184. //
  185. // If we are here, GUID retrieval was successful.
  186. //
  187. if (pdb->dwFlags & DB_GUID_VALID) {
  188. RtlMoveMemory(pguidDB, &pdb->guidDB, sizeof(GUID));
  189. bReturn = TRUE;
  190. }
  191. errHandle:
  192. return bReturn;
  193. }
  194. VOID
  195. SDBAPI
  196. SdbFreeDatabaseInformation(
  197. IN PSDBDATABASEINFO pDBInfo
  198. )
  199. {
  200. if (pDBInfo != NULL && (pDBInfo->dwFlags & DBINFO_SDBALLOC)) {
  201. SdbFree(pDBInfo);
  202. }
  203. }
  204. BOOL
  205. SDBAPI
  206. SdbGetDatabaseInformationByName(
  207. IN LPCTSTR pszDatabase,
  208. OUT PSDBDATABASEINFO* ppdbInfo
  209. )
  210. /*++
  211. Return: TRUE on success, FALSE otherwise.
  212. Desc: This function retrieves database information given the database name
  213. the pointer to the SDBDATABASEINFO should be freed by the caller using
  214. SdbFreeDatabaseInformation
  215. --*/
  216. {
  217. PDB pdb = NULL;
  218. DWORD dwDescriptionSize = 0;
  219. PSDBDATABASEINFO pDbInfo = NULL;
  220. BOOL bReturn = FALSE;
  221. SDBDATABASEINFO DbInfo;
  222. assert(ppdbInfo != NULL);
  223. pdb = SdbOpenDatabase(pszDatabase, DOS_PATH);
  224. if (pdb == NULL) {
  225. DBGPRINT((sdlError,
  226. "SdbGetDatabaseInformationByName",
  227. "Error opening database file \"%s\"\n",
  228. pszDatabase));
  229. return FALSE;
  230. }
  231. //
  232. // Find the size of the database description
  233. //
  234. if (!SdbGetDatabaseInformation(pdb, &DbInfo)) {
  235. DBGPRINT((sdlError,
  236. "SdbGetDatabaseInformationByName",
  237. "Error Retrieving Database information for \"%s\"\n",
  238. pszDatabase));
  239. goto HandleError;
  240. }
  241. if (DbInfo.pszDescription != NULL) {
  242. dwDescriptionSize = (DWORD)(_tcslen(DbInfo.pszDescription) + 1) * sizeof(TCHAR);
  243. }
  244. pDbInfo = (PSDBDATABASEINFO)SdbAlloc(sizeof(SDBDATABASEINFO) + dwDescriptionSize);
  245. if (pDbInfo == NULL) {
  246. DBGPRINT((sdlError,
  247. "SdbGetDatabaseInformationByName",
  248. "Error allocating 0x%lx bytes for database information \"%s\"\n",
  249. sizeof(SDBDATABASEINFO) + dwDescriptionSize,
  250. pszDatabase));
  251. goto HandleError;
  252. }
  253. RtlMoveMemory(pDbInfo, &DbInfo, sizeof(DbInfo));
  254. pDbInfo->dwFlags |= DBINFO_SDBALLOC;
  255. //
  256. // Make it "self-contained"
  257. //
  258. if (DbInfo.pszDescription != NULL) {
  259. pDbInfo->pszDescription = (LPTSTR)(pDbInfo + 1);
  260. RtlMoveMemory(pDbInfo->pszDescription, DbInfo.pszDescription, dwDescriptionSize);
  261. }
  262. *ppdbInfo = pDbInfo;
  263. bReturn = TRUE;
  264. HandleError:
  265. if (pdb != NULL) {
  266. SdbCloseDatabaseRead(pdb);
  267. }
  268. if (!bReturn) {
  269. if (pDbInfo != NULL) {
  270. SdbFree(pDbInfo);
  271. }
  272. }
  273. return bReturn;
  274. }
  275. LPCTSTR
  276. SdbpGetDatabaseDescriptionPtr(
  277. IN PDB pdb
  278. )
  279. {
  280. TAGID tiDatabase;
  281. TAGID tiName;
  282. LPCTSTR lpszDescription = NULL;
  283. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  284. if (!tiDatabase) {
  285. DBGPRINT((sdlError,
  286. "SdbpGetDatabaseDescriptionPtr",
  287. "Failed to get database tag, db is corrupt\n"));
  288. goto errHandle;
  289. }
  290. tiName = SdbFindFirstTag(pdb, tiDatabase, TAG_NAME);
  291. if (tiName) {
  292. lpszDescription = SdbGetStringTagPtr(pdb, tiName);
  293. }
  294. errHandle:
  295. return lpszDescription;
  296. }
  297. BOOL
  298. SdbpReadMappedData(
  299. IN PDB pdb, // database handle
  300. IN DWORD dwOffset, // offset in the database where the data is to be copied from
  301. OUT PVOID pBuffer, // destination buffer
  302. IN DWORD dwSize // the region size
  303. )
  304. /*++
  305. Return: TRUE if successful, FALSE otherwise.
  306. Desc: This function reads the data (dwSize bytes) from the database
  307. starting at offset dwOffset into the buffer pBuffer provided
  308. by the caller
  309. --*/
  310. {
  311. if (pdb->dwSize < dwOffset + dwSize) {
  312. DBGPRINT((sdlError,
  313. "SdbpReadMappedData",
  314. "Attempt to read past the end of the database offset 0x%lx size 0x%lx (0x%lx)\n",
  315. dwOffset,
  316. dwSize,
  317. pdb->dwSize));
  318. return FALSE;
  319. }
  320. assert(pdb->pBase != NULL);
  321. memcpy(pBuffer, (PBYTE)pdb->pBase + dwOffset, dwSize);
  322. return TRUE;
  323. }
  324. PVOID
  325. SdbpGetMappedData(
  326. IN PDB pdb, // database handle
  327. IN DWORD dwOffset // offset in the database
  328. )
  329. /*++
  330. Return: The pointer to the data.
  331. Desc: This function returns the pointer to data within the database at
  332. offset dwOffset. It will return FALSE if dwOffset is invalid.
  333. --*/
  334. {
  335. assert(pdb);
  336. assert(pdb->pBase != NULL);
  337. if (dwOffset >= pdb->dwSize) {
  338. DBGPRINT((sdlError,
  339. "SdbpGetMappedData",
  340. "Trying to read mapped data past the end of the database offset 0x%x size 0x%x\n",
  341. dwOffset,
  342. pdb->dwSize));
  343. assert(FALSE);
  344. return NULL;
  345. }
  346. return (PBYTE)pdb->pBase + dwOffset;
  347. }
  348. PDB
  349. SdbOpenDatabase(
  350. IN LPCTSTR szPath, // full path to the DB
  351. IN PATH_TYPE eType // DOS_PATH for standard paths,
  352. // NT_PATH for internal NT paths
  353. )
  354. /*++
  355. Return: A pointer to the open DB, or NULL on failure.
  356. Desc: Opens up a shim database file, checks version and magic numbers, and creates
  357. a DB record that is passed back as a PDB. eType can be NT_PATH or DOS_PATH,
  358. and tells whether we are using NTDLL internal paths, or the more familiar
  359. DOS paths.
  360. --*/
  361. {
  362. PDB pdb;
  363. DB_HEADER DBHeader;
  364. pdb = SdbAlloc(sizeof(DB));
  365. if (pdb == NULL) {
  366. DBGPRINT((sdlError, "SdbOpenDatabase", "Can't allocate DB structure.\n"));
  367. return NULL;
  368. }
  369. if (!SdbpOpenAndMapDB(pdb, szPath, eType)) {
  370. DBGPRINT((sdlInfo,
  371. "SdbOpenDatabase",
  372. "Failed to open the database \"%s\".\n",
  373. szPath));
  374. goto err1;
  375. }
  376. pdb->bWrite = FALSE;
  377. pdb->dwSize = SdbpGetFileSize(pdb->hFile);
  378. //
  379. // Check version and magic.
  380. //
  381. if (!SdbpReadMappedData(pdb, 0, &DBHeader, sizeof(DB_HEADER))) {
  382. DBGPRINT((sdlError, "SdbOpenDatabase", "Can't read database header.\n"));
  383. goto err2;
  384. }
  385. if (DBHeader.dwMagic != SHIMDB_MAGIC) {
  386. DBGPRINT((sdlError, "SdbOpenDatbase", "Magic does not match 0x%lx\n", DBHeader.dwMagic));
  387. goto err2;
  388. }
  389. if (DBHeader.dwMajorVersion == 1) {
  390. DBGPRINT((sdlWarning, "SdbOpenDatabase", "Reading under hack from older database\n"));
  391. pdb->bUnalignedRead = TRUE;
  392. } else if (DBHeader.dwMajorVersion != SHIMDB_MAJOR_VERSION) {
  393. DBGPRINT((sdlError, "SdbOpenDatabase",
  394. "MajorVersion mismatch, MajorVersion 0x%lx Expected 0x%lx\n",
  395. DBHeader.dwMajorVersion, (DWORD)SHIMDB_MAJOR_VERSION));
  396. goto err2;
  397. }
  398. if (DBHeader.dwMagic != SHIMDB_MAGIC || DBHeader.dwMajorVersion != SHIMDB_MAJOR_VERSION) {
  399. DBGPRINT((sdlError,
  400. "SdbOpenDatabase",
  401. "Magic or MajorVersion doesn't match."
  402. "Magic: %08X, Expected: %08X; MajorVersion: %08X, Expected: %08X.\n",
  403. DBHeader.dwMagic,
  404. (DWORD)SHIMDB_MAGIC,
  405. DBHeader.dwMajorVersion,
  406. (DWORD)SHIMDB_MAJOR_VERSION));
  407. goto err2;
  408. }
  409. return pdb;
  410. err2:
  411. SdbpUnmapAndCloseDB(pdb);
  412. err1:
  413. SdbFree(pdb);
  414. return NULL;
  415. }
  416. PDB
  417. SdbpOpenDatabaseInMemory(
  418. IN LPVOID pImageDatabase, // Pointer to the image of the mapped database
  419. IN DWORD dwSize // the size of the file in bytes
  420. )
  421. /*++
  422. Return: BUGBUG: ?
  423. Desc: BUGBUG: ?
  424. --*/
  425. {
  426. PDB pdb = NULL;
  427. DB_HEADER DBHeader;
  428. pdb = SdbAlloc(sizeof(DB));
  429. if (pdb == NULL) {
  430. DBGPRINT((sdlError,
  431. "SdbpOpenDatabaseInMemory",
  432. "Failed to allocate DB structure\n"));
  433. return NULL;
  434. }
  435. pdb->bWrite = FALSE;
  436. pdb->hFile = INVALID_HANDLE_VALUE;
  437. pdb->pBase = pImageDatabase;
  438. pdb->dwSize = dwSize;
  439. pdb->dwFlags |= DB_IN_MEMORY;
  440. if (!SdbpReadMappedData(pdb, 0, &DBHeader, sizeof(DB_HEADER))) {
  441. DBGPRINT((sdlError,
  442. "SdbpOpenDatabaseInMemory",
  443. "Can't read database header\n"));
  444. goto ErrHandle;
  445. }
  446. if (DBHeader.dwMagic != SHIMDB_MAGIC || DBHeader.dwMajorVersion != SHIMDB_MAJOR_VERSION) {
  447. DBGPRINT((sdlError,
  448. "SdbpOpenDatabaseInMemory",
  449. "Magic or MajorVersion doesn't match."
  450. "Magic: %08X, Expected: %08X; MajorVersion: %08X, Expected: %08X.\n",
  451. DBHeader.dwMagic,
  452. (DWORD)SHIMDB_MAGIC,
  453. DBHeader.dwMajorVersion,
  454. (DWORD)SHIMDB_MAJOR_VERSION));
  455. goto ErrHandle;
  456. }
  457. return pdb;
  458. ErrHandle:
  459. if (pdb != NULL) {
  460. SdbFree(pdb);
  461. }
  462. return NULL;
  463. }
  464. void
  465. SdbCloseDatabaseRead(
  466. IN PDB pdb // handle to the DB to close
  467. )
  468. /*++
  469. Return: void.
  470. Desc: Closes a database that was opened for read access as it is the case
  471. with the majority of our run-time code.
  472. --*/
  473. {
  474. assert(pdb);
  475. assert(!pdb->bWrite);
  476. if (pdb->pBase != NULL) {
  477. SdbpUnmapAndCloseDB(pdb);
  478. CLEANUP_STRING_CACHE_READ(pdb);
  479. SdbFree(pdb);
  480. }
  481. }
  482. BOOL
  483. SdbpOpenAndMapDB(
  484. IN PDB pdb, // pdb to fill in with mapping handles and whatnot
  485. IN LPCTSTR pszPath, // full path of file to open
  486. IN PATH_TYPE eType // DOS_PATH for standard paths, NT_PATH for nt internal paths
  487. )
  488. /*++
  489. Return: TRUE if successful, FALSE otherwise.
  490. Desc: Opens a db file, maps it into memory, and sets up the global vars in the pdb.
  491. --*/
  492. {
  493. IMAGEFILEDATA ImageData;
  494. ImageData.dwFlags = 0;
  495. if (!SdbpOpenAndMapFile(pszPath, &ImageData, eType)) {
  496. DBGPRINT((sdlInfo, "SdbpOpenAndMapDB", "Failed to open file \"%s\"\n", pszPath));
  497. return FALSE;
  498. }
  499. pdb->hFile = ImageData.hFile;
  500. pdb->hSection = ImageData.hSection;
  501. pdb->pBase = ImageData.pBase;
  502. pdb->dwSize = (DWORD)ImageData.ViewSize;
  503. return TRUE;
  504. }
  505. BOOL
  506. SdbpUnmapAndCloseDB(
  507. IN PDB pdb // pdb to close the files and mapping info
  508. )
  509. /*++
  510. Return: TRUE if successful, FALSE otherwise.
  511. Desc: Cleans up for the specified database.
  512. --*/
  513. {
  514. BOOL bReturn;
  515. IMAGEFILEDATA ImageData;
  516. if (pdb->dwFlags & DB_IN_MEMORY) {
  517. //
  518. // database in memory
  519. //
  520. pdb->pBase = NULL;
  521. pdb->dwSize = 0;
  522. return TRUE;
  523. }
  524. ImageData.dwFlags = 0;
  525. ImageData.hFile = pdb->hFile;
  526. ImageData.hSection = pdb->hSection;
  527. ImageData.pBase = pdb->pBase;
  528. bReturn = SdbpUnmapAndCloseFile(&ImageData);
  529. //
  530. // once we nuke the file -- reset values
  531. //
  532. if (bReturn) {
  533. pdb->hFile = INVALID_HANDLE_VALUE;
  534. pdb->hSection = NULL;
  535. pdb->pBase = NULL;
  536. }
  537. return bReturn;
  538. }
  539. TAG
  540. SdbGetTagFromTagID(
  541. IN PDB pdb, // DB to use
  542. IN TAGID tiWhich // record to get the tag for
  543. )
  544. /*++
  545. Return: Just the TAG (the word-sized header) of the record.
  546. Desc: Returns just the TAG that a TAGID points to.
  547. --*/
  548. {
  549. TAG tWhich = TAG_NULL;
  550. assert(pdb && tiWhich);
  551. if (!SdbpReadMappedData(pdb, (DWORD)tiWhich, &tWhich, sizeof(TAG))) {
  552. DBGPRINT((sdlError, "SdbGetTagFromTagID", "Error reading data.\n"));
  553. return TAG_NULL;
  554. }
  555. return tWhich;
  556. }
  557. TAGID
  558. SdbpGetNextTagId(
  559. IN PDB pdb, // DB to look in
  560. IN TAGID tiWhich // tag to get the next sibling of
  561. )
  562. /*++
  563. Return: The next tag after the one passed in, or one past end of file if no more.
  564. Desc: Gets the TAGID of the next tag in the DB, or a virtual
  565. TAGID that is one past the end of the file, which means
  566. there are no more tags in the DB.
  567. This is an internal function, and shouldn't be called by
  568. external functions, as there's no clean way to tell you've
  569. walked off the end of the file. Use tiGetNextChildTag instead.
  570. --*/
  571. {
  572. //
  573. // If the tag is an unfinished list tag, point to the end of the file.
  574. //
  575. DWORD dwHeadSize;
  576. DWORD dwDataSize;
  577. if (GETTAGTYPE(SdbGetTagFromTagID(pdb, tiWhich)) == TAG_TYPE_LIST &&
  578. SdbGetTagDataSize(pdb, tiWhich) == TAG_SIZE_UNFINISHED) {
  579. DBGPRINT((sdlError, "SdbpGetNextTagId", "Reading from unfinished list.\n"));
  580. return pdb->dwSize;
  581. } else {
  582. //
  583. // be careful not to step off the end of the file
  584. //
  585. dwHeadSize = SdbpGetTagHeadSize(pdb, tiWhich);
  586. if (dwHeadSize == 0) { // note that dwDataSize can be 0, while the head size can't
  587. return pdb->dwSize;
  588. }
  589. dwDataSize = SdbGetTagDataSize(pdb, tiWhich);
  590. if (!pdb->bUnalignedRead) {
  591. dwDataSize = (dwDataSize + 1) & (~1);
  592. }
  593. return (TAGID)(tiWhich + dwHeadSize + dwDataSize);
  594. }
  595. }
  596. TAGID
  597. SdbGetFirstChild(
  598. IN PDB pdb, // DB to use
  599. IN TAGID tiParent // parent to look in
  600. )
  601. /*++
  602. Return: The first child of tiParent, or TAGID_NULL if there are none.
  603. Desc: Returns the first child of tiParent, which must point to a tag
  604. of basic type LIST.
  605. --*/
  606. {
  607. TAGID tiParentEnd;
  608. TAGID tiReturn;
  609. assert(pdb);
  610. if (tiParent != TAGID_ROOT &&
  611. GETTAGTYPE(SdbGetTagFromTagID(pdb, tiParent)) != TAG_TYPE_LIST) {
  612. DBGPRINT((sdlError,
  613. "SdbGetFirstChild",
  614. "Trying to operate on non-list, non-root tag.\n"));
  615. return TAGID_NULL;
  616. }
  617. if (tiParent == TAGID_ROOT) {
  618. tiParentEnd = pdb->dwSize;
  619. //
  620. // Skip past the header.
  621. //
  622. tiReturn = sizeof(DB_HEADER);
  623. } else {
  624. tiParentEnd = SdbpGetNextTagId(pdb, tiParent);
  625. //
  626. // Just skip past the tag and size params.
  627. //
  628. tiReturn = tiParent + sizeof(TAG) + sizeof(DWORD);
  629. }
  630. if (tiReturn >= tiParentEnd) {
  631. tiReturn = TAGID_NULL;
  632. }
  633. return tiReturn;
  634. }
  635. TAGID
  636. SdbGetNextChild(
  637. IN PDB pdb, // DB to use
  638. IN TAGID tiParent, // parent to look in
  639. IN TAGID tiPrev // previously found child
  640. )
  641. /*++
  642. Return: The next child of tiParent, or TAGID_NULL if there are none.
  643. Desc: Returns the next child of tiParent after tiPrev. tiParent must point
  644. to a tag of basic type LIST.
  645. --*/
  646. {
  647. TAGID tiParentEnd;
  648. TAGID tiReturn;
  649. assert(pdb && tiPrev);
  650. if (tiParent != TAGID_ROOT &&
  651. GETTAGTYPE(SdbGetTagFromTagID(pdb, tiParent)) != TAG_TYPE_LIST) {
  652. DBGPRINT((sdlError,
  653. "SdbGetNextChild",
  654. "Trying to operate on non-list, non-root tag.\n"));
  655. return TAGID_NULL;
  656. }
  657. if (tiParent == TAGID_ROOT) {
  658. tiParentEnd = pdb->dwSize;
  659. } else {
  660. tiParentEnd = SdbpGetNextTagId(pdb, tiParent);
  661. }
  662. //
  663. // Get the next tag.
  664. //
  665. tiReturn = SdbpGetNextTagId(pdb, tiPrev);
  666. if (tiReturn >= tiParentEnd) {
  667. tiReturn = TAGID_NULL;
  668. }
  669. return tiReturn;
  670. }
  671. BOOL
  672. SdbpCreateSearchPathPartsFromPath(
  673. IN LPCTSTR pszPath,
  674. OUT PSEARCHPATHPARTS* ppSearchPathParts
  675. )
  676. /*++
  677. Return: Returns TRUE on success, FALSE on failure.
  678. Desc: This function breaks down a search path (PROCESS_HISTORY) into
  679. parts, with each part specifying a directory where the search
  680. for a matching binary to take place. Directories are organized
  681. in such a way that the last executed binary provides the first
  682. search path.
  683. --*/
  684. {
  685. LPCTSTR pszDir = pszPath;
  686. LPCTSTR pszDirEnd = NULL;
  687. ULONG nParts = 0;
  688. ULONG i = 0;
  689. PSEARCHPATHPARTS pSearchPathParts = NULL;
  690. if (pszPath == NULL) {
  691. DBGPRINT((sdlError,
  692. "SdbpCreateSearchPathPartsFromPath",
  693. "Invalid argument.\n"));
  694. return FALSE;
  695. }
  696. //
  697. // We count search path parts by counting semicolons in the path string
  698. // numberOfParts = numberOfSemicolons + 1
  699. //
  700. pszDir = pszPath;
  701. if (*pszDir != 0) {
  702. //
  703. // At least one part there...
  704. //
  705. nParts++;
  706. }
  707. while ((pszDir = _tcschr(pszDir, _T(';'))) != NULL) {
  708. pszDir++;
  709. nParts++;
  710. }
  711. //
  712. // nParts now has the number of parts in a search path.
  713. //
  714. pSearchPathParts = (PSEARCHPATHPARTS)SdbAlloc(sizeof(SEARCHPATHPARTS) +
  715. sizeof(SEARCHPATHPART) * (nParts - 1));
  716. if (pSearchPathParts == NULL) {
  717. DBGPRINT((sdlError,
  718. "SdbpCreateSearchPathPartsFromPath",
  719. "Failed to allocate %d bytes.\n",
  720. sizeof(SEARCHPATHPARTS) + sizeof(SEARCHPATHPART) * nParts));
  721. return FALSE;
  722. }
  723. pSearchPathParts->PartCount = nParts;
  724. pszDir = pszPath + _tcslen(pszPath);
  725. while (pszDir >= pszPath) {
  726. if (*pszDir == _T('\\') && pszDirEnd == NULL) {
  727. //
  728. // Points to the backslash
  729. //
  730. pszDirEnd = pszDir;
  731. }
  732. if ((*pszDir == _T(';') || pszPath == pszDir) && pszDirEnd != NULL) {
  733. //
  734. // At this point we should have an end to the string,
  735. // If not that means we are stepping from a recently found path
  736. //
  737. if (*pszDir == _T(';')) {
  738. pszDir++;
  739. }
  740. pSearchPathParts->Parts[i].pszPart = pszDir;
  741. pSearchPathParts->Parts[i].PartLength = (ULONG)(pszDirEnd - pszDir + 1);
  742. i++;
  743. pszDirEnd = NULL;
  744. }
  745. pszDir--;
  746. }
  747. *ppSearchPathParts = pSearchPathParts;
  748. return TRUE;
  749. }