|
|
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
apphelp.c
Abstract:
This module implements high-level functions to access msi installer information
Author:
vadimb created sometime in 2000
Revision History:
--*/
#include "sdbp.h"
/*++
// Local function prototype
//
//
--*/ PDB SdbpGetNextMsiDatabase( IN HSDB hSDB, IN LPCTSTR lpszLocalDB, IN OUT PSDBMSIFINDINFO pFindInfo );
TAGID SdbpFindPlatformMatch( IN HSDB hSDB, IN PDB pdb, IN TAGID tiMatch, // current match using the GUID index
IN PSDBMSIFINDINFO pFindInfo ) { TAGID tiRuntimePlatform; DWORD dwRuntimePlatform; LPCTSTR pszGuid = NULL; #ifndef WIN32A_MODE
UNICODE_STRING ustrGUID = { 0 }; #else
TCHAR szGUID[64]; // guid is about 38 chars + 0
#endif // WIN32A_MODE
TAGID tiOSSKU; DWORD dwOSSKU;
if (tiMatch != TAGID_NULL) { #ifndef WIN32A_MODE
GUID_TO_UNICODE_STRING(&pFindInfo->guidID, &ustrGUID); pszGuid = ustrGUID.Buffer; #else // WIN32A_MODE
GUID_TO_STRING(&pFindInfo->guidID, szGUID, CHARCOUNT(szGUID)); pszGuid = szGUID; #endif // WIN32A_MODE
}
while (tiMatch != TAGID_NULL) {
tiRuntimePlatform = SdbFindFirstTag(pdb, tiMatch, TAG_RUNTIME_PLATFORM); if (tiRuntimePlatform != TAGID_NULL) {
dwRuntimePlatform = SdbReadDWORDTag(pdb, tiRuntimePlatform, RUNTIME_PLATFORM_ANY);
//
// Check for the platform match
//
if (!SdbpCheckRuntimePlatform(hSDB, pszGuid, dwRuntimePlatform)) { goto CheckNextMatch; } }
// check for SKU match
tiOSSKU = SdbFindFirstTag(pdb, tiMatch, TAG_OS_SKU); if (tiOSSKU) {
dwOSSKU = SdbReadDWORDTag(pdb, tiOSSKU, OS_SKU_ALL);
if (dwOSSKU != OS_SKU_ALL) {
PSDBCONTEXT pDBContext = (PSDBCONTEXT)hSDB;
//
// Check for the OS SKU match
//
if (!(dwOSSKU & pDBContext->dwOSSKU)) { DBGPRINT((sdlInfo, "SdbpCheckExe", "MSI OS SKU Mismatch %s Database(0x%lx) vs 0x%lx\n", (pszGuid ? pszGuid : TEXT("Unknown")), dwOSSKU, pDBContext->dwOSSKU)); goto CheckNextMatch; } } }
break; // if we are here -- both sku and platform match
CheckNextMatch:
tiMatch = SdbFindNextGUIDIndexedTag(pdb, &pFindInfo->sdbFindInfo); }
#ifndef WIN32A_MODE
FREE_GUID_STRING(&ustrGUID);
#endif // WIN32A_MODE
return tiMatch; }
TAGREF SDBAPI SdbpFindFirstMsiMatch( IN HSDB hSDB, IN LPCTSTR lpszLocalDB, OUT PSDBMSIFINDINFO pFindInfo ) /*++
Return: TAGREF of a matching MSI transform in whatever database we have found to be valid the state of the search is updated (pFindInfo->sdbLookupState) or TAGREF_NULL if there were no matches in any of the remaining databases
Desc: When this function is called first, the state is set to LOOKUP_NONE - the local db is up for lookup first, followed by arbitrary number of other lookup states. --*/ { TAGREF trMatch = TAGREF_NULL; TAGID tiMatch = TAGID_NULL; PDB pdb;
do { //
// If we have a database to look into first, use it, otherwise grab the
// next database from the list of things we use.
//
pdb = SdbpGetNextMsiDatabase(hSDB, lpszLocalDB, pFindInfo);
//
// There is no database for us to look at - get out
//
if (pdb == NULL) { //
// All options are out -- get out now
//
break; }
tiMatch = SdbFindFirstGUIDIndexedTag(pdb, TAG_MSI_PACKAGE, TAG_MSI_PACKAGE_ID, &pFindInfo->guidID, &pFindInfo->sdbFindInfo); //
// Skip entries that do not match our runtime platform
//
tiMatch = SdbpFindPlatformMatch(hSDB, pdb, tiMatch, pFindInfo);
} while (tiMatch == TAGID_NULL);
if (tiMatch != TAGID_NULL) { //
// We have a match if we are here, state information is stored in pFindInfo with
// sdbLookupState containing the NEXT search state for us to feast on.
//
if (!SdbTagIDToTagRef(hSDB, pdb, tiMatch, &trMatch)) { DBGPRINT((sdlError, "SdbpFindFirstMsiMatch", "Failed to convert tagid 0x%x to tagref\n", tiMatch)); return TAGREF_NULL; } }
return trMatch; }
TAGREF SDBAPI SdbpFindNextMsiMatch( IN HSDB hSDB, IN PDB pdb, OUT PSDBMSIFINDINFO pFindInfo ) { TAGREF trMatch = TAGREF_NULL; TAGID tiMatch = TAGID_NULL;
tiMatch = SdbFindNextGUIDIndexedTag(pdb, &pFindInfo->sdbFindInfo);
if (tiMatch == TAGID_NULL) { return TAGREF_NULL; }
tiMatch = SdbpFindPlatformMatch(hSDB, pdb, tiMatch, pFindInfo);
if (tiMatch == TAGID_NULL) { return TAGREF_NULL; }
if (!SdbTagIDToTagRef(hSDB, pdb, tiMatch, &trMatch)) { DBGPRINT((sdlError, "SdbpFindFirstMsiMatch", "Failed to convert tagid 0x%x to tagref\n", tiMatch)); return TAGREF_NULL; }
return trMatch; }
TAGREF SDBAPI SdbFindFirstMsiPackage_Str( IN HSDB hSDB, IN LPCTSTR lpszGuid, IN LPCTSTR lpszLocalDB, OUT PSDBMSIFINDINFO pFindInfo ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { GUID guidID;
if (!SdbGUIDFromString(lpszGuid, &guidID)) { DBGPRINT((sdlError, "SdbFindFirstMsiPackage_Str", "Failed to convert guid from string %s\n", lpszGuid));
return TAGREF_NULL; }
return SdbFindFirstMsiPackage(hSDB, &guidID, lpszLocalDB, pFindInfo); }
//
// The workings of MSI database search:
//
// 1. Function SdbpGetNextMsiDatabase returns the database corresponding to the
// state stored in sdbLookupState
// 2. Only non-null values are returned and the state is advanced to the next
// valid value. For instance, if we were not able to open a local (supplied) database
// we try main database - if that was a no-show, we try test db, if that is not available,
// we try custom dbs
// 3. When function returns NULL - it means that no more dbs are available for lookup
PDB SdbpGetNextMsiDatabase( IN HSDB hSDB, IN LPCTSTR lpszLocalDB, IN OUT PSDBMSIFINDINFO pFindInfo ) /*++
Func: SdbpGetNextMsiDatabase Returns the next database to be looked at or NULL if no more databases are availalble Uses pFindInfo->sdbLookupState and updates it upon exit --*/ { PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB; PDB pdbRet; LPTSTR pszGuid; SDBMSILOOKUPSTATE LookupState = LOOKUP_DONE; #ifndef WIN32A_MODE
UNICODE_STRING ustrGUID = { 0 }; NTSTATUS Status; #else
TCHAR szGUID[64]; // guid is about 38 chars + 0
#endif
do { pdbRet = NULL;
switch (pFindInfo->sdbLookupState) {
case LOOKUP_DONE: // no next state
break;
case LOOKUP_NONE: // initial state, start with local db
LookupState = LOOKUP_LOCAL; break;
case LOOKUP_LOCAL: SdbCloseLocalDatabase(hSDB);
if (lpszLocalDB != NULL) {
if (!SdbOpenLocalDatabase(hSDB, lpszLocalDB)) { DBGPRINT((sdlWarning, "SdbpGetNextMsiDatabase", "Cannot open database \"%s\"\n", lpszLocalDB)); } else { pdbRet = pContext->pdbLocal; } }
LookupState = LOOKUP_CUSTOM; break;
case LOOKUP_CUSTOM:
#ifndef WIN32A_MODE
Status = GUID_TO_UNICODE_STRING(&pFindInfo->guidID, &ustrGUID);
if (!NT_SUCCESS(Status)) { DBGPRINT((sdlError, "SdbGetNextMsiDatabase", "Failed to convert guid to string, status 0x%lx\n", Status)); break; }
pszGuid = ustrGUID.Buffer; #else
GUID_TO_STRING(&pFindInfo->guidID, szGUID, CHARCOUNT(szGUID)); pszGuid = szGUID; #endif
SdbCloseLocalDatabase(hSDB);
if (SdbOpenNthLocalDatabase(hSDB, pszGuid, &pFindInfo->dwCustomIndex, FALSE)) {
pdbRet = pContext->pdbLocal;
//
// The state does not change when we have a match
//
assert(pdbRet != NULL);
} else { LookupState = LOOKUP_TEST; }
break;
case LOOKUP_TEST: pdbRet = pContext->pdbTest;
//
// Next one is custom
//
LookupState = LOOKUP_MAIN; break;
case LOOKUP_MAIN: pdbRet = pContext->pdbMain; LookupState = LOOKUP_DONE; break;
default: DBGPRINT((sdlError, "SdbGetNextMsiDatabase", "Unknown MSI Lookup State 0x%lx\n", pFindInfo->sdbLookupState)); LookupState = LOOKUP_DONE; break; }
pFindInfo->sdbLookupState = LookupState;
} while (pdbRet == NULL && pFindInfo->sdbLookupState != LOOKUP_DONE);
#ifndef WIN32A_MODE
FREE_GUID_STRING(&ustrGUID); #endif
return pdbRet; }
TAGREF SDBAPI SdbFindFirstMsiPackage( IN HSDB hSDB, // HSDB context
IN GUID* pGuidID, // GUID that we're looking for
IN LPCTSTR lpszLocalDB, // optional path to local db, dos path style
OUT PSDBMSIFINDINFO pFindInfo // pointer to our search context
) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { //
// Initialize MSI search structure
//
RtlZeroMemory(pFindInfo, sizeof(*pFindInfo));
pFindInfo->guidID = *pGuidID; // store the guid ptr in the context
pFindInfo->sdbLookupState = LOOKUP_NONE;
pFindInfo->trMatch = SdbpFindFirstMsiMatch(hSDB, lpszLocalDB, pFindInfo);
return pFindInfo->trMatch; }
TAGREF SDBAPI SdbFindNextMsiPackage( IN HSDB hSDB, IN OUT PSDBMSIFINDINFO pFindInfo ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ {
PDB pdb = NULL; TAGID tiMatch; TAGREF trMatch = TAGREF_NULL;
assert(hSDB != NULL && pFindInfo != NULL);
if (pFindInfo->trMatch == TAGREF_NULL) { DBGPRINT((sdlError, "SdbFindNextMsiPackage", "No more matches\n")); return trMatch; }
//
// Take the last match and look in the same database
//
if (!SdbTagRefToTagID(hSDB, pFindInfo->trMatch, &pdb, &tiMatch)) { DBGPRINT((sdlError, "SdbFindNextMsiPackage", "Failed to convert tagref 0x%x to tagid\n", pFindInfo->trMatch)); return trMatch; }
//
// Call to find the next match in this (current) database
//
trMatch = SdbpFindNextMsiMatch(hSDB, pdb, pFindInfo);
if (trMatch != TAGREF_NULL) { pFindInfo->trMatch = trMatch; return trMatch; }
//
// So in this (current) database we have no further matches, look for the first match
// in the next db
//
trMatch = SdbpFindFirstMsiMatch(hSDB, NULL, pFindInfo);
//
// We have found a match -- or not, store supplemental information and return.
//
pFindInfo->trMatch = trMatch;
return trMatch; }
DWORD SDBAPI SdbEnumMsiTransforms( IN HSDB hSDB, IN TAGREF trMatch, OUT TAGREF* ptrBuffer, IN OUT DWORD* pdwBufferSize ) /*++
Return: BUGBUG: ?
Desc: Enumerate fixes for a given MSI package. --*/ { TAGID tiMatch = TAGID_NULL; TAGID tiTransform; DWORD nTransforms = 0; DWORD dwError = ERROR_SUCCESS; PDB pdb;
//
// Get a list of transforms available for this entry
//
if (!SdbTagRefToTagID(hSDB, trMatch, &pdb, &tiMatch)) { DBGPRINT((sdlError, "SdbEnumerateMsiTransforms", "Failed to convert tagref 0x%x to tagid\n", trMatch)); return ERROR_INTERNAL_DB_CORRUPTION; }
if (ptrBuffer == NULL) { //
// We should have the pdwBufferSize not NULL in this case.
//
if (pdwBufferSize == NULL) { DBGPRINT((sdlError, "SdbEnumerateMsiTransforms", "when ptrBuffer is not specified, pdwBufferSize should not be NULL\n")); return ERROR_INVALID_PARAMETER; } }
//
// Now start enumerating transforms. Count them first.
//
if (pdwBufferSize != NULL) { tiTransform = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_TRANSFORM_REF);
while (tiTransform != TAGID_NULL) { nTransforms++;
tiTransform = SdbFindNextTag(pdb, tiMatch, tiTransform); }
//
// Both buffer size and buffer specified, see if we fit in.
//
if (ptrBuffer == NULL || *pdwBufferSize < nTransforms * sizeof(TAGREF)) { *pdwBufferSize = nTransforms * sizeof(TAGREF); DBGPRINT((sdlInfo, "SdbEnumerateMsiTransforms", "Buffer specified is too small\n")); return ERROR_INSUFFICIENT_BUFFER; } }
//
// Now we have counted them all and either the buffer size is not supplied
// or it has enough room, do it again now
// The only case when we are here is ptrBuffer != NULL
//
assert(ptrBuffer != NULL);
__try {
tiTransform = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_TRANSFORM_REF);
while (tiTransform != TAGID_NULL) {
if (!SdbTagIDToTagRef(hSDB, pdb, tiTransform, ptrBuffer)) {
DBGPRINT((sdlError, "SdbEnumerateMsiTransforms", "Failed to convert tagid 0x%x to tagref\n", tiTransform));
return ERROR_INTERNAL_DB_CORRUPTION; }
//
// Advance the pointer
//
++ptrBuffer;
//
// Lookup next transform
//
tiTransform = SdbFindNextTag(pdb, tiMatch, tiTransform); }
if (pdwBufferSize != NULL) { *pdwBufferSize = nTransforms * sizeof(TAGREF); }
} __except(EXCEPTION_EXECUTE_HANDLER) { dwError = ERROR_INVALID_DATA; }
return dwError; }
BOOL SDBAPI SdbReadMsiTransformInfo( IN HSDB hSDB, IN TAGREF trTransformRef, OUT PSDBMSITRANSFORMINFO pTransformInfo ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { TAGID tiTransformRef = TAGID_NULL; TAGID tiName = TAGID_NULL; TAGID tiFile = TAGID_NULL; PDB pdb = NULL; TAGREF trTransform = TAGREF_NULL; TAGREF trFileTag = TAGREF_NULL; TAGREF trFile = TAGREF_NULL; TAGREF trFileName = TAGREF_NULL; DWORD dwLength; LPTSTR pszFileName = NULL;
RtlZeroMemory(pTransformInfo, sizeof(*pTransformInfo));
if (!SdbTagRefToTagID(hSDB, trTransformRef, &pdb, &tiTransformRef)) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Failed to convert tagref 0x%lx to tagid\n", trTransformRef)); return FALSE; }
if (SdbGetTagFromTagID(pdb, tiTransformRef) != TAG_MSI_TRANSFORM_REF) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Bad Transform reference 0x%lx\n", trTransformRef)); return FALSE; }
//
// First find the name.
//
tiName = SdbFindFirstTag(pdb, tiTransformRef, TAG_NAME); if (tiName) { pTransformInfo->lpszTransformName = SdbGetStringTagPtr(pdb, tiName); }
//
// Then locate the transform itself.
//
trTransform = SdbGetItemFromItemRef(hSDB, trTransformRef, TAG_NAME, TAG_MSI_TRANSFORM_TAGID, TAG_MSI_TRANSFORM);
if (trTransform == TAGREF_NULL) { //
// We can't do it, return TRUE however.
// Reason: Caller will have the name of the transform
// and should know what to do.
//
return TRUE; }
pTransformInfo->trTransform = trTransform;
//
// Now that we have the transform entry get the description and the bits.
//
trFileTag = SdbFindFirstTagRef(hSDB, trTransform, TAG_MSI_TRANSFORM_TAGID);
if (trFileTag != TAGREF_NULL) {
//
// Read the reference to an actual file within this db
//
tiFile = SdbReadDWORDTagRef(hSDB, trFileTag, (DWORD)TAGID_NULL);
//
// If we attained the tiFile - note that it is an id within
// the current database, so make a trFile out of it.
//
if (tiFile) { if (!SdbTagIDToTagRef(hSDB, pdb, tiFile, &trFile)) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Failed to convert File tag to tagref 0x%lx\n", tiFile)); trFile = TAGREF_NULL; } } }
if (trFile == TAGREF_NULL) { //
// We wil have to look by (file) name.
//
trFileName = SdbFindFirstTagRef(hSDB, trTransform, TAG_MSI_TRANSFORM_FILE);
if (trFileName == TAGREF_NULL) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Failed to get MSI Transform for tag 0x%x\n", trTransform)); return FALSE; }
dwLength = SdbpGetStringRefLength(hSDB, trFileName);
STACK_ALLOC(pszFileName, (dwLength + 1) * sizeof(TCHAR));
if (pszFileName == NULL) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Failed to allocate buffer for %ld characters tag 0x%lx\n", dwLength, trFileName)); return FALSE; }
//
// Now read the filename.
//
if (!SdbReadStringTagRef(hSDB, trFileName, pszFileName, dwLength + 1)) { DBGPRINT((sdlError, "SdbReadMsiTransformInfo", "Failed to read filename string tag, length %d characters, tag 0x%x\n", dwLength, trFileName)); STACK_FREE(pszFileName); return FALSE; }
//
// Locate the transform in the library (of the current file first, if
// not found -- in the main db then).
//
trFile = SdbpGetLibraryFile(pdb, pszFileName);
if (trFile == TAGREF_NULL) { trFile = SdbpGetMainLibraryFile(hSDB, pszFileName); }
STACK_FREE(pszFileName); }
pTransformInfo->trFile = trFile;
return TRUE; }
BOOL SDBAPI SdbCreateMsiTransformFile( IN HSDB hSDB, IN LPCTSTR lpszFileName, OUT PSDBMSITRANSFORMINFO pTransformInfo ) /*++
Return: BUGBUG: ?
Desc: BUGBUG: ? --*/ { TAGREF trBits; DWORD dwSize; PBYTE pBuffer = NULL; BOOL bSuccess = FALSE;
if (pTransformInfo->trFile == TAGREF_NULL) {
DBGPRINT((sdlError, "SdbCreateMsiTransformFile", "File for transform \"%s\" was not found\n", pTransformInfo->lpszTransformName)); goto out; }
trBits = SdbFindFirstTagRef(hSDB, pTransformInfo->trFile, TAG_FILE_BITS);
if (trBits == TAGREF_NULL) {
DBGPRINT((sdlError, "SdbCreateMsiTransformFile", "File bits not found tag 0x%x\n", trBits)); goto out; }
dwSize = SdbpGetTagRefDataSize(hSDB, trBits);
pBuffer = (PBYTE)SdbAlloc(dwSize);
if (pBuffer == NULL) { DBGPRINT((sdlError, "SdbCreateMsiTransformFile", "Failed to allocate %d bytes.\n", dwSize)); goto out; }
//
// Now read the DLL's bits.
//
if (!SdbpReadBinaryTagRef(hSDB, trBits, pBuffer, dwSize)) { DBGPRINT((sdlError, "SdbCreateMsiTransformFile", "Can't read transform bits.\n")); goto out; }
if (!SdbpWriteBitsToFile(lpszFileName, pBuffer, dwSize)) { DBGPRINT((sdlError, "SdbCreateMsiTransformFile", "Can't write transform bits to disk.\n")); goto out; }
bSuccess = TRUE;
out: if (pBuffer != NULL) { SdbFree(pBuffer); }
return bSuccess; }
BOOL SDBAPI SdbGetMsiPackageInformation( IN HSDB hSDB, IN TAGREF trMatch, OUT PMSIPACKAGEINFO pPackageInfo ) { PDB pdb = NULL; TAGID tiMatch; TAGID tiPackageID; TAGID tiExeID; TAGID tiApphelp; TAGID tiCustomAction; BOOL bSuccess;
RtlZeroMemory(pPackageInfo, sizeof(*pPackageInfo));
if (!SdbTagRefToTagID(hSDB, trMatch, &pdb, &tiMatch)) {
DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to convert tagref 0x%lx to tagid\n", trMatch));
return FALSE; }
//
// Fill in important id's
//
if (!SdbGetDatabaseID(pdb, &pPackageInfo->guidDatabaseID)) {
DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to get database id, tagref 0x%lx\n", trMatch));
return FALSE; }
//
// Retrieve match id (unique one)
//
tiPackageID = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_PACKAGE_ID);
if (tiPackageID == TAGID_NULL) {
DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to get msi package id, tagref = 0x%lx\n", trMatch));
return FALSE; }
bSuccess = SdbReadBinaryTag(pdb, tiPackageID, (PBYTE)&pPackageInfo->guidMsiPackageID, sizeof(pPackageInfo->guidMsiPackageID)); if (!bSuccess) { DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to read MSI Package ID referenced by 0x%x\n", trMatch)); return FALSE; }
tiExeID = SdbFindFirstTag(pdb, tiMatch, TAG_EXE_ID);
if (tiExeID == TAGID_NULL) {
DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to read TAG_EXE_ID for tagref 0x%x\n", trMatch));
return FALSE; }
bSuccess = SdbReadBinaryTag(pdb, tiExeID, (PBYTE)&pPackageInfo->guidID, sizeof(pPackageInfo->guidID)); if (!bSuccess) {
DBGPRINT((sdlError, "SdbGetMsiPackageInformation", "Failed to read EXE ID referenced by tagref 0x%x\n", trMatch));
return FALSE; }
//
// Set the flags to indicate whether apphelp or shims are available for
// this package
// note that shims/layers might be set for the subordinate actions and not
// for the package itself. If custom_action tag exists however -- we need to check
// with the full api later.
//
tiApphelp = SdbFindFirstTag(pdb, tiMatch, TAG_APPHELP);
if (tiApphelp != TAGID_NULL) { pPackageInfo->dwPackageFlags |= MSI_PACKAGE_HAS_APPHELP; }
//
// Check to see whether we have any shims/layers
//
tiCustomAction = SdbFindFirstTag(pdb, tiMatch, TAG_MSI_CUSTOM_ACTION);
if (tiCustomAction != TAGID_NULL) { pPackageInfo->dwPackageFlags |= MSI_PACKAGE_HAS_SHIMS; }
return TRUE;
}
TAGREF SDBAPI SdbFindMsiPackageByID( IN HSDB hSDB, IN GUID* pguidID ) { TAGID tiMatch; PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB; FIND_INFO FindInfo; TAGREF trMatch = TAGREF_NULL;
//
// We search only the LOCAL database in this case
//
tiMatch = SdbFindFirstGUIDIndexedTag(pContext->pdbLocal, TAG_MSI_PACKAGE, TAG_EXE_ID, pguidID, &FindInfo); if (tiMatch == TAGID_NULL) { return trMatch; }
if (!SdbTagIDToTagRef(hSDB, pContext->pdbLocal, tiMatch, &trMatch)) { DBGPRINT((sdlError, "SdbFindMsiPackageByID", "Failed to convert tagid 0x%lx to tagref\n", tiMatch)); }
return trMatch; }
TAGREF SDBAPI SdbFindCustomActionForPackage( IN HSDB hSDB, IN TAGREF trPackage, IN LPCTSTR lpszCustomAction ) { PDB pdb = NULL; TAGID tiMatch = TAGID_NULL; TAGREF trReturn = TAGREF_NULL; TAGID tiCustomAction;
if (!SdbTagRefToTagID(hSDB, trPackage, &pdb, &tiMatch)) {
DBGPRINT((sdlError, "SdbFindCustomActionForPackage", "Failed to convert tagref 0x%lx to tagid\n", trPackage));
return TAGREF_NULL; }
//
// Now, for this tiMatch look for a custom action
//
tiCustomAction = SdbFindFirstNamedTag(pdb, tiMatch, TAG_MSI_CUSTOM_ACTION, TAG_NAME, lpszCustomAction);
if (tiCustomAction != TAGID_NULL) { if (!SdbTagIDToTagRef(hSDB, pdb, tiCustomAction, &trReturn)) {
DBGPRINT((sdlError, "SdbFindCustomActionForPackage", "Failed to convert tagid 0x%lx to tagref\n", tiCustomAction));
trReturn = TAGREF_NULL; } }
return trReturn; }
|