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.

1030 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. apphelp.c
  5. Abstract:
  6. This module implements high-level functions to access msi installer information
  7. Author:
  8. vadimb created sometime in 2000
  9. Revision History:
  10. --*/
  11. #include "sdbp.h"
  12. /*++
  13. // Local function prototype
  14. //
  15. //
  16. --*/
  17. PDB
  18. SdbpGetNextMsiDatabase(
  19. IN HSDB hSDB,
  20. IN LPCTSTR lpszLocalDB,
  21. IN OUT PSDBMSIFINDINFO pFindInfo
  22. );
  23. TAGID
  24. SdbpFindPlatformMatch(
  25. IN HSDB hSDB,
  26. IN PDB pdb,
  27. IN TAGID tiMatch, // current match using the GUID index
  28. IN PSDBMSIFINDINFO pFindInfo
  29. )
  30. {
  31. TAGID tiRuntimePlatform;
  32. DWORD dwRuntimePlatform;
  33. LPCTSTR pszGuid = NULL;
  34. #ifndef WIN32A_MODE
  35. UNICODE_STRING ustrGUID = { 0 };
  36. #else
  37. TCHAR szGUID[64]; // guid is about 38 chars + 0
  38. #endif // WIN32A_MODE
  39. TAGID tiOSSKU;
  40. DWORD dwOSSKU;
  41. if (tiMatch != TAGID_NULL) {
  42. #ifndef WIN32A_MODE
  43. GUID_TO_UNICODE_STRING(&pFindInfo->guidID, &ustrGUID);
  44. pszGuid = ustrGUID.Buffer;
  45. #else // WIN32A_MODE
  46. GUID_TO_STRING(&pFindInfo->guidID, szGUID, CHARCOUNT(szGUID));
  47. pszGuid = szGUID;
  48. #endif // WIN32A_MODE
  49. }
  50. while (tiMatch != TAGID_NULL) {
  51. tiRuntimePlatform = SdbFindFirstTag(pdb, tiMatch, TAG_RUNTIME_PLATFORM);
  52. if (tiRuntimePlatform != TAGID_NULL) {
  53. dwRuntimePlatform = SdbReadDWORDTag(pdb, tiRuntimePlatform, RUNTIME_PLATFORM_ANY);
  54. //
  55. // Check for the platform match
  56. //
  57. if (!SdbpCheckRuntimePlatform(hSDB, pszGuid, dwRuntimePlatform)) {
  58. goto CheckNextMatch;
  59. }
  60. }
  61. // check for SKU match
  62. tiOSSKU = SdbFindFirstTag(pdb, tiMatch, TAG_OS_SKU);
  63. if (tiOSSKU) {
  64. dwOSSKU = SdbReadDWORDTag(pdb, tiOSSKU, OS_SKU_ALL);
  65. if (dwOSSKU != OS_SKU_ALL) {
  66. PSDBCONTEXT pDBContext = (PSDBCONTEXT)hSDB;
  67. //
  68. // Check for the OS SKU match
  69. //
  70. if (!(dwOSSKU & pDBContext->dwOSSKU)) {
  71. DBGPRINT((sdlInfo,
  72. "SdbpCheckExe",
  73. "MSI OS SKU Mismatch %s Database(0x%lx) vs 0x%lx\n",
  74. (pszGuid ? pszGuid : TEXT("Unknown")),
  75. dwOSSKU,
  76. pDBContext->dwOSSKU));
  77. goto CheckNextMatch;
  78. }
  79. }
  80. }
  81. break; // if we are here -- both sku and platform match
  82. CheckNextMatch:
  83. tiMatch = SdbFindNextGUIDIndexedTag(pdb, &pFindInfo->sdbFindInfo);
  84. }
  85. #ifndef WIN32A_MODE
  86. FREE_GUID_STRING(&ustrGUID);
  87. #endif // WIN32A_MODE
  88. return tiMatch;
  89. }
  90. TAGREF
  91. SDBAPI
  92. SdbpFindFirstMsiMatch(
  93. IN HSDB hSDB,
  94. IN LPCTSTR lpszLocalDB,
  95. OUT PSDBMSIFINDINFO pFindInfo
  96. )
  97. /*++
  98. Return: TAGREF of a matching MSI transform in whatever database we have found to be valid
  99. the state of the search is updated (pFindInfo->sdbLookupState) or TAGREF_NULL if
  100. there were no matches in any of the remaining databases
  101. Desc: When this function is called first, the state is set to LOOKUP_NONE - the local
  102. db is up for lookup first, followed by arbitrary number of other lookup states.
  103. --*/
  104. {
  105. TAGREF trMatch = TAGREF_NULL;
  106. TAGID tiMatch = TAGID_NULL;
  107. PDB pdb;
  108. do {
  109. //
  110. // If we have a database to look into first, use it, otherwise grab the
  111. // next database from the list of things we use.
  112. //
  113. pdb = SdbpGetNextMsiDatabase(hSDB, lpszLocalDB, pFindInfo);
  114. //
  115. // There is no database for us to look at - get out
  116. //
  117. if (pdb == NULL) {
  118. //
  119. // All options are out -- get out now
  120. //
  121. break;
  122. }
  123. tiMatch = SdbFindFirstGUIDIndexedTag(pdb,
  124. TAG_MSI_PACKAGE,
  125. TAG_MSI_PACKAGE_ID,
  126. &pFindInfo->guidID,
  127. &pFindInfo->sdbFindInfo);
  128. //
  129. // Skip entries that do not match our runtime platform
  130. //
  131. tiMatch = SdbpFindPlatformMatch(hSDB, pdb, tiMatch, pFindInfo);
  132. } while (tiMatch == TAGID_NULL);
  133. if (tiMatch != TAGID_NULL) {
  134. //
  135. // We have a match if we are here, state information is stored in pFindInfo with
  136. // sdbLookupState containing the NEXT search state for us to feast on.
  137. //
  138. if (!SdbTagIDToTagRef(hSDB, pdb, tiMatch, &trMatch)) {
  139. DBGPRINT((sdlError,
  140. "SdbpFindFirstMsiMatch",
  141. "Failed to convert tagid 0x%x to tagref\n",
  142. tiMatch));
  143. return TAGREF_NULL;
  144. }
  145. }
  146. return trMatch;
  147. }
  148. TAGREF
  149. SDBAPI
  150. SdbpFindNextMsiMatch(
  151. IN HSDB hSDB,
  152. IN PDB pdb,
  153. OUT PSDBMSIFINDINFO pFindInfo
  154. )
  155. {
  156. TAGREF trMatch = TAGREF_NULL;
  157. TAGID tiMatch = TAGID_NULL;
  158. tiMatch = SdbFindNextGUIDIndexedTag(pdb, &pFindInfo->sdbFindInfo);
  159. if (tiMatch == TAGID_NULL) {
  160. return TAGREF_NULL;
  161. }
  162. tiMatch = SdbpFindPlatformMatch(hSDB, pdb, tiMatch, pFindInfo);
  163. if (tiMatch == TAGID_NULL) {
  164. return TAGREF_NULL;
  165. }
  166. if (!SdbTagIDToTagRef(hSDB, pdb, tiMatch, &trMatch)) {
  167. DBGPRINT((sdlError,
  168. "SdbpFindFirstMsiMatch",
  169. "Failed to convert tagid 0x%x to tagref\n",
  170. tiMatch));
  171. return TAGREF_NULL;
  172. }
  173. return trMatch;
  174. }
  175. TAGREF
  176. SDBAPI
  177. SdbFindFirstMsiPackage_Str(
  178. IN HSDB hSDB,
  179. IN LPCTSTR lpszGuid,
  180. IN LPCTSTR lpszLocalDB,
  181. OUT PSDBMSIFINDINFO pFindInfo
  182. )
  183. /*++
  184. Return: BUGBUG: ?
  185. Desc: BUGBUG: ?
  186. --*/
  187. {
  188. GUID guidID;
  189. if (!SdbGUIDFromString(lpszGuid, &guidID)) {
  190. DBGPRINT((sdlError,
  191. "SdbFindFirstMsiPackage_Str",
  192. "Failed to convert guid from string %s\n",
  193. lpszGuid));
  194. return TAGREF_NULL;
  195. }
  196. return SdbFindFirstMsiPackage(hSDB, &guidID, lpszLocalDB, pFindInfo);
  197. }
  198. //
  199. // The workings of MSI database search:
  200. //
  201. // 1. Function SdbpGetNextMsiDatabase returns the database corresponding to the
  202. // state stored in sdbLookupState
  203. // 2. Only non-null values are returned and the state is advanced to the next
  204. // valid value. For instance, if we were not able to open a local (supplied) database
  205. // we try main database - if that was a no-show, we try test db, if that is not available,
  206. // we try custom dbs
  207. // 3. When function returns NULL - it means that no more dbs are available for lookup
  208. PDB
  209. SdbpGetNextMsiDatabase(
  210. IN HSDB hSDB,
  211. IN LPCTSTR lpszLocalDB,
  212. IN OUT PSDBMSIFINDINFO pFindInfo
  213. )
  214. /*++
  215. Func: SdbpGetNextMsiDatabase
  216. Returns the next database to be looked at
  217. or NULL if no more databases are availalble
  218. Uses pFindInfo->sdbLookupState and updates it upon exit
  219. --*/
  220. {
  221. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  222. PDB pdbRet;
  223. LPTSTR pszGuid;
  224. SDBMSILOOKUPSTATE LookupState = LOOKUP_DONE;
  225. #ifndef WIN32A_MODE
  226. UNICODE_STRING ustrGUID = { 0 };
  227. NTSTATUS Status;
  228. #else
  229. TCHAR szGUID[64]; // guid is about 38 chars + 0
  230. #endif
  231. do {
  232. pdbRet = NULL;
  233. switch (pFindInfo->sdbLookupState) {
  234. case LOOKUP_DONE: // no next state
  235. break;
  236. case LOOKUP_NONE: // initial state, start with local db
  237. LookupState = LOOKUP_LOCAL;
  238. break;
  239. case LOOKUP_LOCAL:
  240. SdbCloseLocalDatabase(hSDB);
  241. if (lpszLocalDB != NULL) {
  242. if (!SdbOpenLocalDatabase(hSDB, lpszLocalDB)) {
  243. DBGPRINT((sdlWarning,
  244. "SdbpGetNextMsiDatabase",
  245. "Cannot open database \"%s\"\n",
  246. lpszLocalDB));
  247. } else {
  248. pdbRet = pContext->pdbLocal;
  249. }
  250. }
  251. LookupState = LOOKUP_CUSTOM;
  252. break;
  253. case LOOKUP_CUSTOM:
  254. #ifndef WIN32A_MODE
  255. Status = GUID_TO_UNICODE_STRING(&pFindInfo->guidID, &ustrGUID);
  256. if (!NT_SUCCESS(Status)) {
  257. DBGPRINT((sdlError,
  258. "SdbGetNextMsiDatabase",
  259. "Failed to convert guid to string, status 0x%lx\n",
  260. Status));
  261. break;
  262. }
  263. pszGuid = ustrGUID.Buffer;
  264. #else
  265. GUID_TO_STRING(&pFindInfo->guidID, szGUID, CHARCOUNT(szGUID));
  266. pszGuid = szGUID;
  267. #endif
  268. SdbCloseLocalDatabase(hSDB);
  269. if (SdbOpenNthLocalDatabase(hSDB, pszGuid, &pFindInfo->dwCustomIndex, FALSE)) {
  270. pdbRet = pContext->pdbLocal;
  271. //
  272. // The state does not change when we have a match
  273. //
  274. assert(pdbRet != NULL);
  275. } else {
  276. LookupState = LOOKUP_TEST;
  277. }
  278. break;
  279. case LOOKUP_TEST:
  280. pdbRet = pContext->pdbTest;
  281. //
  282. // Next one is custom
  283. //
  284. LookupState = LOOKUP_MAIN;
  285. break;
  286. case LOOKUP_MAIN:
  287. pdbRet = pContext->pdbMain;
  288. LookupState = LOOKUP_DONE;
  289. break;
  290. default:
  291. DBGPRINT((sdlError,
  292. "SdbGetNextMsiDatabase",
  293. "Unknown MSI Lookup State 0x%lx\n",
  294. pFindInfo->sdbLookupState));
  295. LookupState = LOOKUP_DONE;
  296. break;
  297. }
  298. pFindInfo->sdbLookupState = LookupState;
  299. } while (pdbRet == NULL && pFindInfo->sdbLookupState != LOOKUP_DONE);
  300. #ifndef WIN32A_MODE
  301. FREE_GUID_STRING(&ustrGUID);
  302. #endif
  303. return pdbRet;
  304. }
  305. TAGREF
  306. SDBAPI
  307. SdbFindFirstMsiPackage(
  308. IN HSDB hSDB, // HSDB context
  309. IN GUID* pGuidID, // GUID that we're looking for
  310. IN LPCTSTR lpszLocalDB, // optional path to local db, dos path style
  311. OUT PSDBMSIFINDINFO pFindInfo // pointer to our search context
  312. )
  313. /*++
  314. Return: BUGBUG: ?
  315. Desc: BUGBUG: ?
  316. --*/
  317. {
  318. //
  319. // Initialize MSI search structure
  320. //
  321. RtlZeroMemory(pFindInfo, sizeof(*pFindInfo));
  322. pFindInfo->guidID = *pGuidID; // store the guid ptr in the context
  323. pFindInfo->sdbLookupState = LOOKUP_NONE;
  324. pFindInfo->trMatch = SdbpFindFirstMsiMatch(hSDB, lpszLocalDB, pFindInfo);
  325. return pFindInfo->trMatch;
  326. }
  327. TAGREF
  328. SDBAPI
  329. SdbFindNextMsiPackage(
  330. IN HSDB hSDB,
  331. IN OUT PSDBMSIFINDINFO pFindInfo
  332. )
  333. /*++
  334. Return: BUGBUG: ?
  335. Desc: BUGBUG: ?
  336. --*/
  337. {
  338. PDB pdb = NULL;
  339. TAGID tiMatch;
  340. TAGREF trMatch = TAGREF_NULL;
  341. assert(hSDB != NULL && pFindInfo != NULL);
  342. if (pFindInfo->trMatch == TAGREF_NULL) {
  343. DBGPRINT((sdlError, "SdbFindNextMsiPackage", "No more matches\n"));
  344. return trMatch;
  345. }
  346. //
  347. // Take the last match and look in the same database
  348. //
  349. if (!SdbTagRefToTagID(hSDB, pFindInfo->trMatch, &pdb, &tiMatch)) {
  350. DBGPRINT((sdlError,
  351. "SdbFindNextMsiPackage",
  352. "Failed to convert tagref 0x%x to tagid\n",
  353. pFindInfo->trMatch));
  354. return trMatch;
  355. }
  356. //
  357. // Call to find the next match in this (current) database
  358. //
  359. trMatch = SdbpFindNextMsiMatch(hSDB, pdb, pFindInfo);
  360. if (trMatch != TAGREF_NULL) {
  361. pFindInfo->trMatch = trMatch;
  362. return trMatch;
  363. }
  364. //
  365. // So in this (current) database we have no further matches, look for the first match
  366. // in the next db
  367. //
  368. trMatch = SdbpFindFirstMsiMatch(hSDB, NULL, pFindInfo);
  369. //
  370. // We have found a match -- or not, store supplemental information and return.
  371. //
  372. pFindInfo->trMatch = trMatch;
  373. return trMatch;
  374. }
  375. DWORD
  376. SDBAPI
  377. SdbEnumMsiTransforms(
  378. IN HSDB hSDB,
  379. IN TAGREF trMatch,
  380. OUT TAGREF* ptrBuffer,
  381. IN OUT DWORD* pdwBufferSize
  382. )
  383. /*++
  384. Return: BUGBUG: ?
  385. Desc: Enumerate fixes for a given MSI package.
  386. --*/
  387. {
  388. TAGID tiMatch = TAGID_NULL;
  389. TAGID tiTransform;
  390. DWORD nTransforms = 0;
  391. DWORD dwError = ERROR_SUCCESS;
  392. PDB pdb;
  393. //
  394. // Get a list of transforms available for this entry
  395. //
  396. if (!SdbTagRefToTagID(hSDB, trMatch, &pdb, &tiMatch)) {
  397. DBGPRINT((sdlError,
  398. "SdbEnumerateMsiTransforms",
  399. "Failed to convert tagref 0x%x to tagid\n",
  400. trMatch));
  401. return ERROR_INTERNAL_DB_CORRUPTION;
  402. }
  403. if (ptrBuffer == NULL) {
  404. //
  405. // We should have the pdwBufferSize not NULL in this case.
  406. //
  407. if (pdwBufferSize == NULL) {
  408. DBGPRINT((sdlError,
  409. "SdbEnumerateMsiTransforms",
  410. "when ptrBuffer is not specified, pdwBufferSize should not be NULL\n"));
  411. return ERROR_INVALID_PARAMETER;
  412. }
  413. }
  414. //
  415. // Now start enumerating transforms. Count them first.
  416. //
  417. if (pdwBufferSize != NULL) {
  418. tiTransform = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_TRANSFORM_REF);
  419. while (tiTransform != TAGID_NULL) {
  420. nTransforms++;
  421. tiTransform = SdbFindNextTag(pdb, tiMatch, tiTransform);
  422. }
  423. //
  424. // Both buffer size and buffer specified, see if we fit in.
  425. //
  426. if (ptrBuffer == NULL || *pdwBufferSize < nTransforms * sizeof(TAGREF)) {
  427. *pdwBufferSize = nTransforms * sizeof(TAGREF);
  428. DBGPRINT((sdlInfo,
  429. "SdbEnumerateMsiTransforms",
  430. "Buffer specified is too small\n"));
  431. return ERROR_INSUFFICIENT_BUFFER;
  432. }
  433. }
  434. //
  435. // Now we have counted them all and either the buffer size is not supplied
  436. // or it has enough room, do it again now
  437. // The only case when we are here is ptrBuffer != NULL
  438. //
  439. assert(ptrBuffer != NULL);
  440. __try {
  441. tiTransform = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_TRANSFORM_REF);
  442. while (tiTransform != TAGID_NULL) {
  443. if (!SdbTagIDToTagRef(hSDB, pdb, tiTransform, ptrBuffer)) {
  444. DBGPRINT((sdlError,
  445. "SdbEnumerateMsiTransforms",
  446. "Failed to convert tagid 0x%x to tagref\n",
  447. tiTransform));
  448. return ERROR_INTERNAL_DB_CORRUPTION;
  449. }
  450. //
  451. // Advance the pointer
  452. //
  453. ++ptrBuffer;
  454. //
  455. // Lookup next transform
  456. //
  457. tiTransform = SdbFindNextTag(pdb, tiMatch, tiTransform);
  458. }
  459. if (pdwBufferSize != NULL) {
  460. *pdwBufferSize = nTransforms * sizeof(TAGREF);
  461. }
  462. } __except(EXCEPTION_EXECUTE_HANDLER) {
  463. dwError = ERROR_INVALID_DATA;
  464. }
  465. return dwError;
  466. }
  467. BOOL
  468. SDBAPI
  469. SdbReadMsiTransformInfo(
  470. IN HSDB hSDB,
  471. IN TAGREF trTransformRef,
  472. OUT PSDBMSITRANSFORMINFO pTransformInfo
  473. )
  474. /*++
  475. Return: BUGBUG: ?
  476. Desc: BUGBUG: ?
  477. --*/
  478. {
  479. TAGID tiTransformRef = TAGID_NULL;
  480. TAGID tiName = TAGID_NULL;
  481. TAGID tiFile = TAGID_NULL;
  482. PDB pdb = NULL;
  483. TAGREF trTransform = TAGREF_NULL;
  484. TAGREF trFileTag = TAGREF_NULL;
  485. TAGREF trFile = TAGREF_NULL;
  486. TAGREF trFileName = TAGREF_NULL;
  487. DWORD dwLength;
  488. LPTSTR pszFileName = NULL;
  489. RtlZeroMemory(pTransformInfo, sizeof(*pTransformInfo));
  490. if (!SdbTagRefToTagID(hSDB, trTransformRef, &pdb, &tiTransformRef)) {
  491. DBGPRINT((sdlError,
  492. "SdbReadMsiTransformInfo",
  493. "Failed to convert tagref 0x%lx to tagid\n",
  494. trTransformRef));
  495. return FALSE;
  496. }
  497. if (SdbGetTagFromTagID(pdb, tiTransformRef) != TAG_MSI_TRANSFORM_REF) {
  498. DBGPRINT((sdlError,
  499. "SdbReadMsiTransformInfo",
  500. "Bad Transform reference 0x%lx\n",
  501. trTransformRef));
  502. return FALSE;
  503. }
  504. //
  505. // First find the name.
  506. //
  507. tiName = SdbFindFirstTag(pdb, tiTransformRef, TAG_NAME);
  508. if (tiName) {
  509. pTransformInfo->lpszTransformName = SdbGetStringTagPtr(pdb, tiName);
  510. }
  511. //
  512. // Then locate the transform itself.
  513. //
  514. trTransform = SdbGetItemFromItemRef(hSDB,
  515. trTransformRef,
  516. TAG_NAME,
  517. TAG_MSI_TRANSFORM_TAGID,
  518. TAG_MSI_TRANSFORM);
  519. if (trTransform == TAGREF_NULL) {
  520. //
  521. // We can't do it, return TRUE however.
  522. // Reason: Caller will have the name of the transform
  523. // and should know what to do.
  524. //
  525. return TRUE;
  526. }
  527. pTransformInfo->trTransform = trTransform;
  528. //
  529. // Now that we have the transform entry get the description and the bits.
  530. //
  531. trFileTag = SdbFindFirstTagRef(hSDB, trTransform, TAG_MSI_TRANSFORM_TAGID);
  532. if (trFileTag != TAGREF_NULL) {
  533. //
  534. // Read the reference to an actual file within this db
  535. //
  536. tiFile = SdbReadDWORDTagRef(hSDB, trFileTag, (DWORD)TAGID_NULL);
  537. //
  538. // If we attained the tiFile - note that it is an id within
  539. // the current database, so make a trFile out of it.
  540. //
  541. if (tiFile) {
  542. if (!SdbTagIDToTagRef(hSDB, pdb, tiFile, &trFile)) {
  543. DBGPRINT((sdlError,
  544. "SdbReadMsiTransformInfo",
  545. "Failed to convert File tag to tagref 0x%lx\n",
  546. tiFile));
  547. trFile = TAGREF_NULL;
  548. }
  549. }
  550. }
  551. if (trFile == TAGREF_NULL) {
  552. //
  553. // We wil have to look by (file) name.
  554. //
  555. trFileName = SdbFindFirstTagRef(hSDB, trTransform, TAG_MSI_TRANSFORM_FILE);
  556. if (trFileName == TAGREF_NULL) {
  557. DBGPRINT((sdlError,
  558. "SdbReadMsiTransformInfo",
  559. "Failed to get MSI Transform for tag 0x%x\n",
  560. trTransform));
  561. return FALSE;
  562. }
  563. dwLength = SdbpGetStringRefLength(hSDB, trFileName);
  564. STACK_ALLOC(pszFileName, (dwLength + 1) * sizeof(TCHAR));
  565. if (pszFileName == NULL) {
  566. DBGPRINT((sdlError,
  567. "SdbReadMsiTransformInfo",
  568. "Failed to allocate buffer for %ld characters tag 0x%lx\n",
  569. dwLength,
  570. trFileName));
  571. return FALSE;
  572. }
  573. //
  574. // Now read the filename.
  575. //
  576. if (!SdbReadStringTagRef(hSDB, trFileName, pszFileName, dwLength + 1)) {
  577. DBGPRINT((sdlError,
  578. "SdbReadMsiTransformInfo",
  579. "Failed to read filename string tag, length %d characters, tag 0x%x\n",
  580. dwLength,
  581. trFileName));
  582. STACK_FREE(pszFileName);
  583. return FALSE;
  584. }
  585. //
  586. // Locate the transform in the library (of the current file first, if
  587. // not found -- in the main db then).
  588. //
  589. trFile = SdbpGetLibraryFile(pdb, pszFileName);
  590. if (trFile == TAGREF_NULL) {
  591. trFile = SdbpGetMainLibraryFile(hSDB, pszFileName);
  592. }
  593. STACK_FREE(pszFileName);
  594. }
  595. pTransformInfo->trFile = trFile;
  596. return TRUE;
  597. }
  598. BOOL
  599. SDBAPI
  600. SdbCreateMsiTransformFile(
  601. IN HSDB hSDB,
  602. IN LPCTSTR lpszFileName,
  603. OUT PSDBMSITRANSFORMINFO pTransformInfo
  604. )
  605. /*++
  606. Return: BUGBUG: ?
  607. Desc: BUGBUG: ?
  608. --*/
  609. {
  610. TAGREF trBits;
  611. DWORD dwSize;
  612. PBYTE pBuffer = NULL;
  613. BOOL bSuccess = FALSE;
  614. if (pTransformInfo->trFile == TAGREF_NULL) {
  615. DBGPRINT((sdlError,
  616. "SdbCreateMsiTransformFile",
  617. "File for transform \"%s\" was not found\n",
  618. pTransformInfo->lpszTransformName));
  619. goto out;
  620. }
  621. trBits = SdbFindFirstTagRef(hSDB, pTransformInfo->trFile, TAG_FILE_BITS);
  622. if (trBits == TAGREF_NULL) {
  623. DBGPRINT((sdlError,
  624. "SdbCreateMsiTransformFile",
  625. "File bits not found tag 0x%x\n",
  626. trBits));
  627. goto out;
  628. }
  629. dwSize = SdbpGetTagRefDataSize(hSDB, trBits);
  630. pBuffer = (PBYTE)SdbAlloc(dwSize);
  631. if (pBuffer == NULL) {
  632. DBGPRINT((sdlError,
  633. "SdbCreateMsiTransformFile",
  634. "Failed to allocate %d bytes.\n",
  635. dwSize));
  636. goto out;
  637. }
  638. //
  639. // Now read the DLL's bits.
  640. //
  641. if (!SdbpReadBinaryTagRef(hSDB, trBits, pBuffer, dwSize)) {
  642. DBGPRINT((sdlError,
  643. "SdbCreateMsiTransformFile",
  644. "Can't read transform bits.\n"));
  645. goto out;
  646. }
  647. if (!SdbpWriteBitsToFile(lpszFileName, pBuffer, dwSize)) {
  648. DBGPRINT((sdlError,
  649. "SdbCreateMsiTransformFile",
  650. "Can't write transform bits to disk.\n"));
  651. goto out;
  652. }
  653. bSuccess = TRUE;
  654. out:
  655. if (pBuffer != NULL) {
  656. SdbFree(pBuffer);
  657. }
  658. return bSuccess;
  659. }
  660. BOOL
  661. SDBAPI
  662. SdbGetMsiPackageInformation(
  663. IN HSDB hSDB,
  664. IN TAGREF trMatch,
  665. OUT PMSIPACKAGEINFO pPackageInfo
  666. )
  667. {
  668. PDB pdb = NULL;
  669. TAGID tiMatch;
  670. TAGID tiPackageID;
  671. TAGID tiExeID;
  672. TAGID tiApphelp;
  673. TAGID tiCustomAction;
  674. BOOL bSuccess;
  675. RtlZeroMemory(pPackageInfo, sizeof(*pPackageInfo));
  676. if (!SdbTagRefToTagID(hSDB, trMatch, &pdb, &tiMatch)) {
  677. DBGPRINT((sdlError,
  678. "SdbGetMsiPackageInformation",
  679. "Failed to convert tagref 0x%lx to tagid\n",
  680. trMatch));
  681. return FALSE;
  682. }
  683. //
  684. // Fill in important id's
  685. //
  686. if (!SdbGetDatabaseID(pdb, &pPackageInfo->guidDatabaseID)) {
  687. DBGPRINT((sdlError,
  688. "SdbGetMsiPackageInformation",
  689. "Failed to get database id, tagref 0x%lx\n",
  690. trMatch));
  691. return FALSE;
  692. }
  693. //
  694. // Retrieve match id (unique one)
  695. //
  696. tiPackageID = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_PACKAGE_ID);
  697. if (tiPackageID == TAGID_NULL) {
  698. DBGPRINT((sdlError,
  699. "SdbGetMsiPackageInformation",
  700. "Failed to get msi package id, tagref = 0x%lx\n",
  701. trMatch));
  702. return FALSE;
  703. }
  704. bSuccess = SdbReadBinaryTag(pdb,
  705. tiPackageID,
  706. (PBYTE)&pPackageInfo->guidMsiPackageID,
  707. sizeof(pPackageInfo->guidMsiPackageID));
  708. if (!bSuccess) {
  709. DBGPRINT((sdlError,
  710. "SdbGetMsiPackageInformation",
  711. "Failed to read MSI Package ID referenced by 0x%x\n",
  712. trMatch));
  713. return FALSE;
  714. }
  715. tiExeID = SdbFindFirstTag(pdb, tiMatch, TAG_EXE_ID);
  716. if (tiExeID == TAGID_NULL) {
  717. DBGPRINT((sdlError,
  718. "SdbGetMsiPackageInformation",
  719. "Failed to read TAG_EXE_ID for tagref 0x%x\n",
  720. trMatch));
  721. return FALSE;
  722. }
  723. bSuccess = SdbReadBinaryTag(pdb,
  724. tiExeID,
  725. (PBYTE)&pPackageInfo->guidID,
  726. sizeof(pPackageInfo->guidID));
  727. if (!bSuccess) {
  728. DBGPRINT((sdlError,
  729. "SdbGetMsiPackageInformation",
  730. "Failed to read EXE ID referenced by tagref 0x%x\n",
  731. trMatch));
  732. return FALSE;
  733. }
  734. //
  735. // Set the flags to indicate whether apphelp or shims are available for
  736. // this package
  737. // note that shims/layers might be set for the subordinate actions and not
  738. // for the package itself. If custom_action tag exists however -- we need to check
  739. // with the full api later.
  740. //
  741. tiApphelp = SdbFindFirstTag(pdb, tiMatch, TAG_APPHELP);
  742. if (tiApphelp != TAGID_NULL) {
  743. pPackageInfo->dwPackageFlags |= MSI_PACKAGE_HAS_APPHELP;
  744. }
  745. //
  746. // Check to see whether we have any shims/layers
  747. //
  748. tiCustomAction = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_CUSTOM_ACTION);
  749. if (tiCustomAction != TAGID_NULL) {
  750. pPackageInfo->dwPackageFlags |= MSI_PACKAGE_HAS_SHIMS;
  751. }
  752. return TRUE;
  753. }
  754. TAGREF
  755. SDBAPI
  756. SdbFindMsiPackageByID(
  757. IN HSDB hSDB,
  758. IN GUID* pguidID
  759. )
  760. {
  761. TAGID tiMatch;
  762. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  763. FIND_INFO FindInfo;
  764. TAGREF trMatch = TAGREF_NULL;
  765. //
  766. // We search only the LOCAL database in this case
  767. //
  768. tiMatch = SdbFindFirstGUIDIndexedTag(pContext->pdbLocal,
  769. TAG_MSI_PACKAGE,
  770. TAG_EXE_ID,
  771. pguidID,
  772. &FindInfo);
  773. if (tiMatch == TAGID_NULL) {
  774. return trMatch;
  775. }
  776. if (!SdbTagIDToTagRef(hSDB, pContext->pdbLocal, tiMatch, &trMatch)) {
  777. DBGPRINT((sdlError,
  778. "SdbFindMsiPackageByID",
  779. "Failed to convert tagid 0x%lx to tagref\n",
  780. tiMatch));
  781. }
  782. return trMatch;
  783. }
  784. TAGREF
  785. SDBAPI
  786. SdbFindCustomActionForPackage(
  787. IN HSDB hSDB,
  788. IN TAGREF trPackage,
  789. IN LPCTSTR lpszCustomAction
  790. )
  791. {
  792. PDB pdb = NULL;
  793. TAGID tiMatch = TAGID_NULL;
  794. TAGREF trReturn = TAGREF_NULL;
  795. TAGID tiCustomAction;
  796. if (!SdbTagRefToTagID(hSDB, trPackage, &pdb, &tiMatch)) {
  797. DBGPRINT((sdlError,
  798. "SdbFindCustomActionForPackage",
  799. "Failed to convert tagref 0x%lx to tagid\n",
  800. trPackage));
  801. return TAGREF_NULL;
  802. }
  803. //
  804. // Now, for this tiMatch look for a custom action
  805. //
  806. tiCustomAction = SdbFindFirstNamedTag(pdb,
  807. tiMatch,
  808. TAG_MSI_CUSTOM_ACTION,
  809. TAG_NAME,
  810. lpszCustomAction);
  811. if (tiCustomAction != TAGID_NULL) {
  812. if (!SdbTagIDToTagRef(hSDB, pdb, tiCustomAction, &trReturn)) {
  813. DBGPRINT((sdlError,
  814. "SdbFindCustomActionForPackage",
  815. "Failed to convert tagid 0x%lx to tagref\n",
  816. tiCustomAction));
  817. trReturn = TAGREF_NULL;
  818. }
  819. }
  820. return trReturn;
  821. }