windows-nt/Source/XPSP1/NT/com/ole32/cs/backend/qry.cxx
2020-09-26 16:20:57 +08:00

1707 lines
52 KiB
C++

//
// Author: DebiM/UShaji
// Date: Jan 97 - Apr 98
//
// Class Store Query and Fetch Implementation
//
//
//---------------------------------------------------------------------
//
#include "cstore.hxx"
//
// List of Attributes for On-Demand Package Lookup Query
//
LPOLESTR pszInstallInfoAttrNames[] =
{
PKGFILEEXTNLIST, LOCALEID, ARCHLIST, PACKAGEFLAGS, SCRIPTPATH, PKGCLSIDLIST,
PACKAGETYPE, PKGUSN, VERSIONHI, VERSIONLO, UPGRADESPACKAGES, UILEVEL,
PACKAGENAME, HELPURL, PUBLISHER, REVISION, PRODUCTCODE, OBJECTDN,
OBJECTGUID
};
DWORD cInstallInfoAttr = 19;
//
// List of Attributes for Enumeration of Packages (with Filters)
//
LPOLESTR pszPackageInfoAttrNames[] =
{
PACKAGEFLAGS, PACKAGETYPE, SCRIPTPATH, SCRIPTSIZE, PKGUSN, LOCALEID, ARCHLIST,
PACKAGENAME, VERSIONHI, VERSIONLO, UPGRADESPACKAGES, UILEVEL, PUBLISHER, HELPURL,
REVISION, PRODUCTCODE, OBJECTGUID, OBJECTDN
};
DWORD cPackageInfoAttr = 18;
//
// List of Attributes for GetPackageDetail() method
//
LPOLESTR pszPackageDetailAttrNames[] =
{
PACKAGEFLAGS, PACKAGETYPE, SCRIPTPATH, SCRIPTSIZE, SETUPCOMMAND, HELPURL, PKGUSN,
VERSIONHI, VERSIONLO, UILEVEL, UPGRADESPACKAGES, ARCHLIST, LOCALEID, PKGCLSIDLIST,
PKGIIDLIST, PKGTLBIDLIST, PKGFILEEXTNLIST, PACKAGENAME, MSIFILELIST, PKGCATEGORYLIST,MVIPC,
PRODUCTCODE, REVISION, OBJECTGUID
};
DWORD cPackageDetailAttr = 24;
LPOLESTR pszDeleteAttrNames[] =
{
PACKAGEFLAGS, OBJECTDN
};
DWORD cDeleteAttr = 2;
//
// List of Attributes for App Categories
//
LPOLESTR pszCategoryAttrNames[] =
{
LOCALEDESCRIPTION, CATEGORYCATID
};
DWORD cCategoryAttr = 2;
BOOL MatchPlatform(
CSPLATFORM *pReqPlatform,
CSPLATFORM *pPkgPlatform,
BOOL fX86OnAlpha)
{
//
// Make sure this is the correct platform
//
if (pReqPlatform->dwPlatformId != pPkgPlatform->dwPlatformId)
{
return FALSE;
}
//
// ProcessorArch must match
//
if (pReqPlatform->dwProcessorArch != pPkgPlatform->dwProcessorArch)
{
//
// If the caller didn't request x86 on alpha, inequality between
// architectures is automatic disqualification
//
if (!fX86OnAlpha)
{
return FALSE;
}
//
// Caller specified that we should allow x86 packages on alpha --
// see if we are in that situation, and only disqualify the package if not
//
if ( ! ((PROCESSOR_ARCHITECTURE_ALPHA == pReqPlatform->dwProcessorArch) &&
(PROCESSOR_ARCHITECTURE_INTEL == pPkgPlatform->dwProcessorArch)))
{
return FALSE;
}
}
//
// Check the OS version, hi part first -- this requested platform must be at least as
// high as the package platform -- if not, it is disqualified
//
if (pReqPlatform->dwVersionHi < pPkgPlatform->dwVersionHi)
{
return FALSE;
}
//
// If the hi version is the same, check the low part of the os version
//
if (pReqPlatform->dwVersionHi == pPkgPlatform->dwVersionHi)
{
//
// If the requested platform is less than the package, it cannot
// support that package, so the package is disqualified.
//
if (pReqPlatform->dwVersionLo < pPkgPlatform->dwVersionLo)
{
return FALSE;
}
}
//
// We passed all the tests -- the package matches the requested platform
//
return TRUE;
}
// this has to change if the Msi can give us a preferred list etc.
DWORD PlatformWt(
CSPLATFORM *pReqPlatform,
CSPLATFORM *pPkgPlatform,
BOOL fX86OnAlpha)
{
if (MatchPlatform(pReqPlatform,
pPkgPlatform,
fX86OnAlpha))
{
return PRI_ARCH_PREF1;
}
return 0;
}
DWORD ClassContextWt(DWORD ClsCtx)
{
if (ClsCtx & CLSCTX_INPROC_SERVER)
return PRI_CLSID_INPSVR;
if (ClsCtx & CLSCTX_LOCAL_SERVER)
return PRI_CLSID_LCLSVR;
if (ClsCtx & CLSCTX_REMOTE_SERVER)
return PRI_CLSID_REMSVR;
return 0;
}
//
//
void GetCurrentUsn(LPOLESTR pStoreUsn)
{
//
// Get the current time as USN for the Class Store container
//
SYSTEMTIME SystemTime;
GetSystemTime(&SystemTime);
wsprintf (pStoreUsn, L"%04d%02d%02d%02d%02d%02d",
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond);
}
void TimeToUsn (LPOLESTR szTimeStamp, CSUSN *pUsn)
{
SYSTEMTIME SystemTime;
if (szTimeStamp)
{
CSDBGPrint((L"szTimeStamp = %s", szTimeStamp));
UINT l = wcslen(szTimeStamp) - 1;
LPOLESTR pStr = szTimeStamp;
for (UINT i=0; i < l; ++i)
{
if (*pStr == L' ')
*pStr = L'0';
++pStr;
}
swscanf (szTimeStamp, L"%4d%2d%2d%2d%2d%2d",
&SystemTime.wYear,
&SystemTime.wMonth,
&SystemTime.wDay,
&SystemTime.wHour,
&SystemTime.wMinute,
&SystemTime.wSecond);
SystemTimeToFileTime(&SystemTime, (LPFILETIME) pUsn);
}
else
pUsn->dwHighDateTime = pUsn->dwLowDateTime = 0;
}
HRESULT UsnGet(ADS_ATTR_INFO Attr, CSUSN *pUsn)
{
//
// Read the USN for the Class Store container or Package
//
WCHAR *szTimeStamp=NULL;
UnpackStrFrom(Attr, &szTimeStamp);
TimeToUsn (szTimeStamp, pUsn);
return S_OK;
}
// FetchInstallData
//-----------------
//
//
// Gets the result set of the ondemand lookup query to locate an install package.
// Returns the properties of the most likely Package in PackageInfo structure.
//
// In case more than one package meets the criteria, their priorities are returned.
// BUGBUG:: In case of E_OUTOFMEMORY in Unpack, we return the packages
// that we have already got.
HRESULT FetchInstallData(HANDLE hADs,
ADS_SEARCH_HANDLE hADsSearchHandle,
QUERYCONTEXT *pQryContext,
uCLSSPEC *pclsspec,
LPOLESTR pszFileExt,
ULONG cRows,
ULONG *pcRowsFetched,
PACKAGEDISPINFO *pPackageInfo,
UINT *pdwPriority,
BOOL OnDemandInstallOnly
)
{
HRESULT hr = S_OK;
UINT i, j;
LPOLESTR szUsn = NULL;
ULONG cCount = 0;
LPOLESTR * pszList = NULL;
DWORD * pdwList = NULL;
ADS_SEARCH_COLUMN column;
CSPLATFORM PkgPlatform;
//
// Get the rows
//
//
// Clear the caller supplied buffer in case the call to
// get the first row fails
//
memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
*pcRowsFetched = 0;
if (*pcRowsFetched == cRows)
return S_OK;
for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle);
((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS));
hr = ADSIGetNextRow(hADs, hADsSearchHandle))
{
//
// Get the data from each row
//
//
// Clear the caller supplied buffer in case previous
// trips through this loop have written data
//
memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
if(FAILED(hr))
{
//
// BUGBUG. Missing cleanup.
//
return hr;
}
//
// If querying by file ext check match and priority
// .
*pdwPriority = 0;
if (pszFileExt)
{
//Column = fileExtension
hr = ADSIGetColumn(hADs, hADsSearchHandle, PKGFILEEXTNLIST, &column);
cCount = 0;
if (SUCCEEDED(hr))
UnpackStrArrFrom(column, &pszList, &cCount);
UINT cLen = wcslen(pszFileExt);
for (j=0; j < cCount; ++j)
{
LPOLESTR pStr = NULL;
if (wcslen(pszList[j]) != (cLen+3))
continue;
if (wcsncmp(pszList[j], pszFileExt, wcslen(pszFileExt)) != 0)
continue;
*pdwPriority = (wcstoul(pszList[j]+(cLen+1), &pStr, 10))*PRI_EXTN_FACTOR;
break;
}
if (SUCCEEDED(hr))
ADSIFreeColumn(hADs, &column);
CoTaskMemFree(pszList); pszList = NULL;
//
// If none matched skip this package
//
if (j == cCount)
continue;
}
//Column = packageFlags
//
// Need to get this so we can properly interpret the machine
// architecture settings since there is at least one flag,
// ACTFLG_X86OnAlpha, that affects our processing of the
// machine architecture. Also need one of the flags to
// do language matches.
//
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGEFLAGS, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwActFlags));
ADSIFreeColumn(hADs, &column);
}
else
continue;
//
// Now check Locale and Platform -- only do this
// if a locale was specified
//
if (0 != pQryContext->Locale)
{
DWORD Wt = 0, MaxWt = 0;
LANGID DesiredLang;
DesiredLang = LANGIDFROMLCID(pQryContext->Locale);
//Column = localeID
hr = ADSIGetColumn(hADs, hADsSearchHandle, LOCALEID, &column);
cCount = 0;
if (SUCCEEDED(hr))
{
// Minor BUGBUG:: int converted to long.
cCount = 0;
UnpackDWArrFrom(column, &pdwList, &cCount);
ADSIFreeColumn(hADs, &column);
}
for (j=0; j < cCount; ++j)
{
//
// If the caller specifies LANG_SYSTEM_DEFAULT, we interpret this
// to mean that the caller wants us to choose apps according
// to the language precedence in GetLanguagePriority. If some
// other langid was given, we then only accept exact matches and
// give those matches the highest priority, PRI_LANG_ALWAYSMATCH
//
if (LANG_SYSTEM_DEFAULT == DesiredLang)
{
Wt = GetLanguagePriority (
LANGIDFROMLCID(pdwList[j]),
pPackageInfo->dwActFlags);
}
else
{
Wt = (DesiredLang == LANGIDFROMLCID(pdwList[j])) ?
PRI_LANG_ALWAYSMATCH :
0;
}
if (Wt > MaxWt)
MaxWt = Wt;
}
//
// If none matched skip this package
//
if (pdwList)
CoTaskMemFree(pdwList);
pdwList = NULL;
// if nothing matched, quit
if (MaxWt == 0)
continue;
*pdwPriority += MaxWt;
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, ARCHLIST, &column);
// machineArchitecture
if (SUCCEEDED(hr))
{
// Minor BUGBUG:: int converted to long.
cCount = 0;
DWORD Wt = 0, MaxWt = 0;
UnpackDWArrFrom(column, &pdwList, &cCount);
ADSIFreeColumn(hADs, &column);
for (j=0; j < cCount; ++j)
{
PackPlatform (pdwList[j], &PkgPlatform);
Wt = PlatformWt (&(pQryContext->Platform),
&PkgPlatform,
pPackageInfo->dwActFlags & ACTFLG_X86OnAlpha);
if (Wt > MaxWt)
MaxWt = Wt;
}
if (pdwList)
CoTaskMemFree(pdwList);
pdwList = NULL;
//
// If none matched skip this package
//
if (MaxWt == 0)
continue;
*pdwPriority += MaxWt;
}
else
continue;
// passed all the filters.
//
// Does it support AutoInstall?
//
if ((OnDemandInstallOnly) && (!(pPackageInfo->dwActFlags & ACTFLG_OnDemandInstall)))
continue;
// If it is neither Published nor Assigned then skip it.
if ((!(pPackageInfo->dwActFlags & ACTFLG_Published)) &&
(!(pPackageInfo->dwActFlags & ACTFLG_Assigned)))
{
continue;
}
// If it is an Orphaned App OR Uninstalled App do not return.
if ((pPackageInfo->dwActFlags & ACTFLG_Orphan) ||
(pPackageInfo->dwActFlags & ACTFLG_Uninstall))
{
continue;
}
//Column = OBJECTGUID
hr = ADSIGetColumn(hADs, hADsSearchHandle, OBJECTGUID, &column);
if (SUCCEEDED(hr))
{
LPOLESTR pStr = NULL;
UnpackGUIDFrom(column, &(pPackageInfo->PackageGuid));
ADSIFreeColumn(hADs, &column);
}
//Column = ScriptPath
hr = ADSIGetColumn(hADs, hADsSearchHandle, SCRIPTPATH, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszScriptPath));
ADSIFreeColumn(hADs, &column);
}
//Column = comClassID
hr = ADSIGetColumn(hADs, hADsSearchHandle, PKGCLSIDLIST, &column);
cCount = 0;
if (SUCCEEDED(hr))
{
UnpackStrArrFrom(column, &pszList, &cCount);
if (cCount)
{
if (pclsspec->tyspec == TYSPEC_CLSID)
{
DWORD i=0, Ctx = 0;
WCHAR szClsid[STRINGGUIDLEN], *szPtr = NULL;
StringFromGUID(pclsspec->tagged_union.clsid, szClsid);
for (i = 0; i < cCount; i++)
if (wcsncmp(pszList[i], szClsid, STRINGGUIDLEN-1) == 0)
break;
//
// The below assert is only hit if there is bad data -- if we find the
// clsid, i will not be cCount, and cCount will never be 0. Basically,
// we're asserting that the search should always succeed if the ds data
// is good.
//
ASSERT(i != cCount);
if (i == cCount)
continue;
if (wcslen(pszList[i]) > (STRINGGUIDLEN-1))
Ctx = wcstoul(pszList[i]+STRINGGUIDLEN, &szPtr, 16);
if ((Ctx & (pQryContext->dwContext)) == 0)
{
CoTaskMemFree(pszList);
ADSIFreeColumn(hADs, &column);
// none of the class context matched.
continue;
}
else
*pdwPriority += ClassContextWt((Ctx & pQryContext->dwContext));
}
pPackageInfo->pClsid = (GUID *)CoTaskMemAlloc(sizeof(GUID));
if (wcslen(pszList[0]) > (STRINGGUIDLEN-1))
pszList[0][STRINGGUIDLEN-1] = L'\0';
// Only access the first entry
if (pPackageInfo->pClsid)
GUIDFromString(pszList[0], pPackageInfo->pClsid);
// o/w return NULL.
CoTaskMemFree(pszList);
}
ADSIFreeColumn(hADs, &column);
}
//Column = packageType
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGETYPE, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, (DWORD *)&(pPackageInfo->PathType));
ADSIFreeColumn(hADs, &column);
}
//Column = lastUpdateSequence
hr = ADSIGetColumn(hADs, hADsSearchHandle, PKGUSN, &column);
if (SUCCEEDED(hr))
{
UnpackStrFrom(column, &szUsn);
TimeToUsn (szUsn, (CSUSN *)(&(pPackageInfo->Usn)));
ADSIFreeColumn(hADs, &column);
}
else {
ReleasePackageInfo(pPackageInfo);
continue;
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, PRODUCTCODE, &column);
if (SUCCEEDED(hr))
{
UnpackGUIDFrom(column, &(pPackageInfo->ProductCode));
ADSIFreeColumn(hADs, &column);
}
//Column = versionNumberHi
hr = ADSIGetColumn(hADs, hADsSearchHandle, VERSIONHI, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwVersionHi));
ADSIFreeColumn(hADs, &column);
}
//Column = versionNumberLo
hr = ADSIGetColumn(hADs, hADsSearchHandle, VERSIONLO, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwVersionLo));
ADSIFreeColumn(hADs, &column);
}
//Column = revision
hr = ADSIGetColumn(hADs, hADsSearchHandle, REVISION, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwRevision));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, UPGRADESPACKAGES, &column);
if (SUCCEEDED(hr))
{
LPOLESTR *pProp = NULL;
hr = UnpackStrArrAllocFrom(column, &pProp, (DWORD *)&(pPackageInfo->cUpgrades));
if (pPackageInfo->cUpgrades)
pPackageInfo->prgUpgradeInfoList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*
(pPackageInfo->cUpgrades));
if (pPackageInfo->prgUpgradeInfoList)
{
memset(pPackageInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pPackageInfo->cUpgrades));
for (j=0; j < ( pPackageInfo->cUpgrades); ++j)
{
WCHAR *pStr = NULL;
LPOLESTR ptr = (pPackageInfo->prgUpgradeInfoList[j].szClassStore) = pProp[j];
UINT len = wcslen (ptr);
if (len <= 41)
continue;
*(ptr + len - 3) = NULL;
(pPackageInfo->prgUpgradeInfoList[j].Flag) = wcstoul(ptr+(len-2), &pStr, 16);
*(ptr + len - 3 - 36 - 2) = L'\0';
/* -GUID-'::'*/
GUIDFromString(ptr+len-3-36, &(pPackageInfo->prgUpgradeInfoList[j].PackageGuid));
}
pPackageInfo->cUpgrades = j; // we might have skipped some.
}
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, UILEVEL, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, (DWORD *)&(pPackageInfo->InstallUiLevel));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGENAME, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszPackageName));
ADSIFreeColumn(hADs, &column);
CSDBGPrint((L"FetchInstallData:: Returning Package %s", pPackageInfo->pszPackageName));
}
else {
ReleasePackageInfo(pPackageInfo);
continue;
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, HELPURL, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszUrl));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, PUBLISHER, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszPublisher));
ADSIFreeColumn(hADs, &column);
}
// source list
hr = ADSIGetColumn(hADs, hADsSearchHandle, MSIFILELIST, &column);
if (SUCCEEDED(hr))
{
LPOLESTR *rpszSourceList = NULL, psz = NULL, pStr = NULL;
DWORD Loc = 0, cSources = 0;
UnpackStrArrFrom(column, &(rpszSourceList), &cSources);
// reorder and allocate spaces.
if (cSources > 1)
{
pPackageInfo->fHasTransforms = 1;
/*
pPackageInfo->pszSourceList = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*
(pPackageInfo->cSources));
// if we could not, plod on, the caller will get back as much as possible.
if (!(pPackageInfo->pszSourceList)) {
pPackageInfo->cSources = 0;
}
memset(pPackageInfo->pszSourceList, 0, sizeof(LPOLESTR)*(pPackageInfo->cSources));
for (count = 0; count < (pPackageInfo->cSources); count++)
{
pPackageInfo->pszSourceList[count] = (LPOLESTR)CoTaskMemAlloc(
sizeof(WCHAR)*(wcslen(rpszSourceList[count])+1));
if (!(pPackageInfo->pszSourceList[count]))
break;
}
// if mem couldn't be allocated
if (count != pPackageInfo->cSources) {
for (count = 0; count < (pPackageInfo->cSources); count++)
if ((pPackageInfo->pszSourceList[count]))
CoTaskMemFree(pPackageInfo->pszSourceList[count]);
CoTaskMemFree(pPackageInfo->pszSourceList);
pPackageInfo->cSources = 0;
}
for (count = 0; count < (pPackageInfo->cSources); count++)
{
psz = wcschr(rpszSourceList[count], L':');
*psz = L'\0';
Loc = wcstoul(rpszSourceList[count], &pStr, 10);
wsprintf(pPackageDetail->pszSourceList[Loc], L"%s", psz+1);
}
*/
}
else
pPackageInfo->fHasTransforms = 0;
ADSIFreeColumn(hADs, &column);
CoTaskMemFree(rpszSourceList);
}
++pPackageInfo;
++pdwPriority;
(*pcRowsFetched)++;
if (*pcRowsFetched == cRows)
break;
}
//
// Check if we found as many as asked for
//
if (*pcRowsFetched != cRows)
return S_FALSE;
return S_OK;
}
// FetchPackageInfo
//-----------------
//
// Gets the result set of the query : List of Package objects.
// Returns the properties in PackageInfo structure.
//
HRESULT FetchPackageInfo(HANDLE hADs,
ADS_SEARCH_HANDLE hADsSearchHandle,
DWORD dwFlags,
CSPLATFORM *pPlatform,
ULONG cRows,
ULONG *pcRowsFetched,
PACKAGEDISPINFO *pPackageInfo,
BOOL *fFirst
)
{
HRESULT hr = S_OK;
UINT i, j;
ULONG cPlatforms = 0;
DWORD * dwPlatformList=NULL;
LCID * dwLocaleList=NULL;
DWORD dwPackageFlags;
ULONG cFetched = 0;
ULONG cRowsLeft = 0;
CSPLATFORM PkgPlatform;
ADS_SEARCH_COLUMN column;
LPOLESTR szUsn = NULL;
BOOL fX86OnAlpha;
*pcRowsFetched = 0;
cRowsLeft = cRows;
if (!cRowsLeft)
return S_OK;
// The LDAP filter performs a part of the selection
// The flag filters are interpreted on the client after obtaining the result set
for (;(cRowsLeft);)
{
if ((*fFirst) && (!(*pcRowsFetched))) {
*fFirst = FALSE;
hr = ADSIGetFirstRow(hADs, hADsSearchHandle);
}
else
hr = ADSIGetNextRow(hADs, hADsSearchHandle);
if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
break;
dwPackageFlags = 0;
// Get the Flag Value: Column = packageFlags
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGEFLAGS, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &dwPackageFlags);
ADSIFreeColumn(hADs, &column);
}
else
continue;
//
// Check flag values to see if this package meets the filter
//
//
// If it is an Orphaned App, we only return it for APPINFO_ALL.
//
if ((dwPackageFlags & ACTFLG_Orphan) && (!(dwFlags & APPINFO_ALL)))
{
continue;
}
// If it is an Uninstalled App return it if asked for by APPINFO_ALL
if ((dwPackageFlags & ACTFLG_Uninstall) && (!(dwFlags & APPINFO_ALL)))
{
continue;
}
if ((dwFlags & APPINFO_PUBLISHED) && (!(dwPackageFlags & ACTFLG_Published)))
{
continue;
}
if ((dwFlags & APPINFO_ASSIGNED) && (!(dwPackageFlags & ACTFLG_Assigned)))
{
continue;
}
if ((dwFlags & APPINFO_VISIBLE) && (!(dwPackageFlags & ACTFLG_UserInstall)))
{
continue;
}
if ((dwFlags & APPINFO_AUTOINSTALL) && (!(dwPackageFlags & ACTFLG_OnDemandInstall)))
{
continue;
}
//
// Move the data into PackageInfo structure
//
memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
//Column = packageType
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGETYPE, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, (DWORD *)&(pPackageInfo->PathType));
ADSIFreeColumn(hADs, &column);
}
if (( dwFlags & APPINFO_MSI ) && (pPackageInfo->PathType != DrwFilePath))
continue;
pPackageInfo->LangId = LANG_NEUTRAL;
//
// If the package flags specify that we should ignore locale, or the
// caller specified that all locale's are acceptable, skip the language
// checks
//
if ( ! (dwPackageFlags & ACTFLG_IgnoreLanguage) &&
! (dwFlags & APPINFO_ALLLOCALE) )
{
LANGID PackageLangId;
DWORD cLanguages;
hr = ADSIGetColumn(hADs, hADsSearchHandle, LOCALEID, &column);
dwLocaleList = NULL;
if (SUCCEEDED(hr))
{
// type change. shouldn't affect anything.
UnpackDWArrFrom(column, &dwLocaleList, &cLanguages);
ADSIFreeColumn(hADs, &column);
}
else
continue;
//
// We only care about the first language returned -- originally
// the packages in the ds could support multiple locales, but
// we now only support one language
//
if (cLanguages)
{
PackageLangId = LANGIDFROMLCID(dwLocaleList[0]);
}
CoTaskMemFree(dwLocaleList);
if (!cLanguages || !MatchLanguage(PackageLangId, dwPackageFlags))
continue;
pPackageInfo->LangId = PackageLangId;
}
if (pPlatform != NULL)
{
//Column = machineArchitecture
hr = ADSIGetColumn(hADs, hADsSearchHandle, ARCHLIST, &column);
cPlatforms = 0;
dwPlatformList = NULL;
if (SUCCEEDED(hr))
{
UnpackDWArrFrom(column, &dwPlatformList, &cPlatforms);
ADSIFreeColumn(hADs, &column);
}
else
continue;
for (j=0; j < cPlatforms; ++j)
{
PackPlatform (dwPlatformList[j], &PkgPlatform);
if (MatchPlatform (pPlatform,
&PkgPlatform,
dwPackageFlags & ACTFLG_X86OnAlpha))
break;
}
if (dwPlatformList)
CoTaskMemFree(dwPlatformList);
//
// If none matched skip this package
//
if (j == cPlatforms)
continue;
}
pPackageInfo->dwActFlags = dwPackageFlags;
//Column = packageName. freeing this????
hr = ADSIGetColumn(hADs, hADsSearchHandle, PACKAGENAME, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszPackageName));
CSDBGPrint((L"FetchPackageInfo:: Returning Package %s", pPackageInfo->pszPackageName));
ADSIFreeColumn(hADs, &column);
}
else {
ReleasePackageInfo(pPackageInfo);
continue;
}
//Column = OBJECTGUID
hr = ADSIGetColumn(hADs, hADsSearchHandle, OBJECTGUID, &column);
if (SUCCEEDED(hr))
{
UnpackGUIDFrom(column, &(pPackageInfo->PackageGuid));
ADSIFreeColumn(hADs, &column);
}
//Column = ScriptPath
hr = ADSIGetColumn(hADs, hADsSearchHandle, SCRIPTPATH, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszScriptPath));
ADSIFreeColumn(hADs, &column);
}
//Column = ScriptSize
hr = ADSIGetColumn(hADs, hADsSearchHandle, SCRIPTSIZE, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->cScriptLen));
ADSIFreeColumn(hADs, &column);
}
//Column = lastUpdateSequence,
hr = ADSIGetColumn(hADs, hADsSearchHandle, PKGUSN, &column);
if (SUCCEEDED(hr))
{
UnpackStrFrom(column, &szUsn);
TimeToUsn (szUsn, (CSUSN *)(&(pPackageInfo->Usn)));
ADSIFreeColumn(hADs, &column);
}
else {
ReleasePackageInfo(pPackageInfo);
continue;
}
// ProductCode
hr = ADSIGetColumn(hADs, hADsSearchHandle, PRODUCTCODE, &column);
if (SUCCEEDED(hr))
{
UnpackGUIDFrom(column, &(pPackageInfo->ProductCode));
ADSIFreeColumn(hADs, &column);
}
//Column = versionNumberHi
hr = ADSIGetColumn(hADs, hADsSearchHandle, VERSIONHI, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwVersionHi));
ADSIFreeColumn(hADs, &column);
}
//Column = versionNumberLo
hr = ADSIGetColumn(hADs, hADsSearchHandle, VERSIONLO, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwVersionLo));
ADSIFreeColumn(hADs, &column);
}
//Column = revision
hr = ADSIGetColumn(hADs, hADsSearchHandle, REVISION, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, &(pPackageInfo->dwRevision));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, UPGRADESPACKAGES, &column);
if (SUCCEEDED(hr))
{
LPOLESTR *pProp = NULL;
hr = UnpackStrArrAllocFrom(column, &pProp, (DWORD *)&(pPackageInfo->cUpgrades));
if (pPackageInfo->cUpgrades)
pPackageInfo->prgUpgradeInfoList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*
(pPackageInfo->cUpgrades));
if (pPackageInfo->prgUpgradeInfoList)
{
memset(pPackageInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pPackageInfo->cUpgrades));
for (j=0; j < ( pPackageInfo->cUpgrades); ++j)
{
WCHAR *pStr = NULL;
LPOLESTR ptr = (pPackageInfo->prgUpgradeInfoList[j].szClassStore) = pProp[j];
UINT len = wcslen (ptr);
if (len <= 41)
continue;
*(ptr + len - 3) = NULL;
(pPackageInfo->prgUpgradeInfoList[j].Flag) = wcstoul(ptr+(len-2), &pStr, 16);
*(ptr + len - 3 - 36 - 2) = L'\0';
/* -GUID-'::'*/
GUIDFromString(ptr+len-3-36, &(pPackageInfo->prgUpgradeInfoList[j].PackageGuid));
}
pPackageInfo->cUpgrades = j; // we might have skipped some.
}
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, UILEVEL, &column);
if (SUCCEEDED(hr))
{
UnpackDWFrom(column, (DWORD *)&(pPackageInfo->InstallUiLevel));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, HELPURL, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszUrl));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, PUBLISHER, &column);
if (SUCCEEDED(hr))
{
UnpackStrAllocFrom(column, &(pPackageInfo->pszPublisher));
ADSIFreeColumn(hADs, &column);
}
hr = ADSIGetColumn(hADs, hADsSearchHandle, MSIFILELIST, &column);
if (SUCCEEDED(hr))
{
LPOLESTR *rpszSourceList = NULL, psz = NULL, pStr = NULL;
DWORD Loc = 0, cSources=0;
UnpackStrArrFrom(column, &(rpszSourceList), &cSources);
// reorder and allocate spaces.
if (cSources > 1)
{
pPackageInfo->fHasTransforms = 1;
/*
(LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*
(pPackageInfo->cSources));
// if we could not, plod on, the caller will get back as much as possible.
if (!(pPackageInfo->pszSourceList)) {
pPackageInfo->cSources = 0;
}
memset(pPackageInfo->pszSourceList, 0, sizeof(LPOLESTR)*(pPackageInfo->cSources));
for (count = 0; count < (pPackageInfo->cSources); count++)
{
pPackageInfo->pszSourceList[count] = (LPOLESTR)CoTaskMemAlloc(
sizeof(WCHAR)*(wcslen(rpszSourceList[count])+1));
if (!(pPackageInfo->pszSourceList[count]))
break;
}
// if mem couldn't be allocated
if (count != pPackageInfo->cSources) {
for (count = 0; count < (pPackageInfo->cSources); count++)
if ((pPackageInfo->pszSourceList[count]))
CoTaskMemFree(pPackageInfo->pszSourceList[count]);
CoTaskMemFree(pPackageInfo->pszSourceList);
pPackageInfo->cSources = 0;
}
for (count = 0; count < (pPackageInfo->cSources); count++)
{
psz = wcschr(rpszSourceList[count], L':');
*psz = L'\0';
Loc = wcstoul(rpszSourceList[count], &pStr, 10);
wsprintf(pPackageDetail->pszSourceList[Loc], L"%s", psz+1);
}
*/
}
else
pPackageInfo->fHasTransforms = 0;
CoTaskMemFree(rpszSourceList);
ADSIFreeColumn(hADs, &column);
}
++pPackageInfo;
cRowsLeft--;
(*pcRowsFetched)++;
}
if (!cRowsLeft)
return S_OK;
return S_FALSE;
}
// FetchCategory
//--------------
//
// List of columns this routine fetches.
//
HRESULT FetchCategory(HANDLE hADs,
ADS_SEARCH_HANDLE hADsSearchHandle,
APPCATEGORYINFOLIST *pCategoryInfoList,
LCID Locale
)
{
HRESULT hr = S_OK;
ADS_SEARCH_COLUMN column;
LPOLESTR * pszDesc = NULL;
DWORD cdesc = 0, i = 0;
LPOLESTR szCatid = NULL;
for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle), i = 0;
((SUCCEEDED(hr)) && ((hr) != S_ADS_NOMORE_ROWS));
hr = ADSIGetNextRow(hADs, hADsSearchHandle), i++)
{
// Get the data from each row ignoring the error returned.
// allocated number of buffers.
if (i >= (pCategoryInfoList->cCategory))
break;
//Column = description
hr = ADSIGetColumn(hADs, hADsSearchHandle, LOCALEDESCRIPTION, &column);
cdesc = 0; pszDesc = NULL;
if (SUCCEEDED(hr))
UnpackStrArrFrom(column, &pszDesc, &cdesc);
(pCategoryInfoList->pCategoryInfo)[i].Locale = Locale;
(pCategoryInfoList->pCategoryInfo)[i].pszDescription =
(LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*128);
// BUGBUG:: Restricting the desc to 128.
if ((pCategoryInfoList->pCategoryInfo)[i].pszDescription)
GetCategoryLocaleDesc(pszDesc, cdesc, &((pCategoryInfoList->pCategoryInfo)[i].Locale),
(pCategoryInfoList->pCategoryInfo)[i].pszDescription);
if (SUCCEEDED(hr))
ADSIFreeColumn(hADs, &column);
if (pszDesc)
CoTaskMemFree(pszDesc);
// catid
hr = ADSIGetColumn(hADs, hADsSearchHandle, CATEGORYCATID, &column);
if (SUCCEEDED(hr))
{
UnpackGUIDFrom(column, &((pCategoryInfoList->pCategoryInfo)[i].AppCategoryId));
ADSIFreeColumn(hADs, &column);
}
}
pCategoryInfoList->cCategory = i;
return S_OK;
}
HRESULT GetClassDetail(WCHAR *szClassPath, CLASSDETAIL *pClassDetail)
{
HRESULT hr = S_OK;
WCHAR *szGUID = NULL;
ADS_ATTR_INFO *pAttrsGot = NULL;
HANDLE hADs = NULL;
LPOLESTR AttrNames[] = {PROGIDLIST, TREATASCLSID, CLASSCLSID};
DWORD posn = 0, cProp = 0, cgot = 0;
hr = ADSIOpenDSObject(szClassPath, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
&hADs);
RETURN_ON_FAILURE(hr);
hr = ADSIGetObjectAttributes(hADs, AttrNames, 3, &pAttrsGot, &cgot);
ERROR_ON_FAILURE(hr);
posn = GetPropertyFromAttr(pAttrsGot, cgot, CLASSCLSID);
if (posn < cgot) {
UnpackStrFrom(pAttrsGot[posn], &szGUID);
GUIDFromString(szGUID, &(pClassDetail->Clsid));
}
else
{
hr = CS_E_OBJECT_NOTFOUND;
ERROR_ON_FAILURE(hr);
}
posn = GetPropertyFromAttr(pAttrsGot, cgot, PROGIDLIST);
if (posn < cgot)
UnpackStrArrAllocFrom(pAttrsGot[posn], &(pClassDetail->prgProgId),
&(pClassDetail->cProgId));
posn = GetPropertyFromAttr(pAttrsGot, cgot, TREATASCLSID);
if (posn < cgot)
{
UnpackStrFrom(pAttrsGot[posn], &szGUID);
GUIDFromString(szGUID, &(pClassDetail->TreatAs));
}
Error_Cleanup:
if (pAttrsGot)
FreeADsMem(pAttrsGot);
if (hADs)
ADSICloseDSObject(hADs);
return hr;
}
HRESULT GetPackageDetail (HANDLE hPackageADs, WCHAR *szClassContainerPath,
PACKAGEDETAIL *pPackageDetail)
{
HRESULT hr = S_OK;
GUID PkgGuid;
DWORD *pdwArch = NULL, count = 0;
PLATFORMINFO *pPlatformInfo = NULL;
INSTALLINFO *pInstallInfo = NULL;
ACTIVATIONINFO *pActInfo = NULL;
ADS_ATTR_INFO *pAttr = NULL;
DWORD posn, cgot = 0;
DWORD cClasses = 0;
LPOLESTR *szClasses = NULL;
DWORD dwUiLevel = 0;
DWORD cProgId = 0;
LPOLESTR *pszProgId = NULL;
memset (pPackageDetail, 0, sizeof (PACKAGEDETAIL));
hr = ADSIGetObjectAttributes(hPackageADs, pszPackageDetailAttrNames, cPackageDetailAttr,
&pAttr, &cgot);
RETURN_ON_FAILURE(hr);
pInstallInfo = pPackageDetail->pInstallInfo = (INSTALLINFO *) CoTaskMemAlloc(sizeof (INSTALLINFO));
if (!pInstallInfo)
ERROR_ON_FAILURE((hr=E_OUTOFMEMORY));
memset(pInstallInfo, NULL, sizeof(INSTALLINFO));
posn = GetPropertyFromAttr(pAttr, cgot, PACKAGEFLAGS);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], (DWORD *)&(pInstallInfo->dwActFlags));
else
ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
posn = GetPropertyFromAttr(pAttr, cgot, PACKAGETYPE);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], (DWORD *)&(pInstallInfo->PathType));
else
ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
posn = GetPropertyFromAttr(pAttr, cgot, SCRIPTPATH);
if (posn < cgot)
UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszScriptPath));
posn = GetPropertyFromAttr(pAttr, cgot, SCRIPTSIZE);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], &(pInstallInfo->cScriptLen));
posn = GetPropertyFromAttr(pAttr, cgot, SETUPCOMMAND);
if (posn < cgot)
UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszSetupCommand));
posn = GetPropertyFromAttr(pAttr, cgot, HELPURL);
if (posn < cgot)
UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszUrl));
posn = GetPropertyFromAttr(pAttr, cgot, PKGUSN);
if (posn < cgot)
UsnGet(pAttr[posn], (CSUSN *)&(pInstallInfo->Usn));
else
ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
posn = GetPropertyFromAttr(pAttr, cgot, PRODUCTCODE);
if (posn < cgot)
UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->ProductCode));
posn = GetPropertyFromAttr(pAttr, cgot, MVIPC);
if (posn < cgot)
UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->Mvipc));
// doesn't matter if the property itself is multivalued.
posn = GetPropertyFromAttr(pAttr, cgot, OBJECTGUID);
if (posn < cgot)
UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->PackageGuid));
posn = GetPropertyFromAttr(pAttr, cgot, VERSIONHI);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwVersionHi));
posn = GetPropertyFromAttr(pAttr, cgot, VERSIONLO);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwVersionLo));
posn = GetPropertyFromAttr(pAttr, cgot, REVISION);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwRevision));
posn = GetPropertyFromAttr(pAttr, cgot, UILEVEL);
if (posn < cgot)
UnpackDWFrom(pAttr[posn], &dwUiLevel);
pInstallInfo->InstallUiLevel = dwUiLevel;
posn = GetPropertyFromAttr(pAttr, cgot, UPGRADESPACKAGES);
if (posn < cgot)
{
LPOLESTR *pProp = NULL;
UnpackStrArrAllocFrom(pAttr[posn], &pProp, (DWORD *)&(pInstallInfo->cUpgrades));
if (pInstallInfo->cUpgrades)
pInstallInfo->prgUpgradeInfoList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*
pInstallInfo->cUpgrades);
if (!(pInstallInfo->prgUpgradeInfoList))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
memset(pInstallInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pInstallInfo->cUpgrades));
for (count = 0; (count < (pInstallInfo->cUpgrades)); count++)
{
WCHAR *pStr = NULL;
LPOLESTR ptr = (pInstallInfo->prgUpgradeInfoList[count].szClassStore) = pProp[count];
UINT len = wcslen (ptr);
if (len <= 41)
continue;
*(ptr + len - 3) = NULL;
pInstallInfo->prgUpgradeInfoList[count].Flag = wcstoul(ptr+(len-2), &pStr, 16);
*(ptr + len - 3 - 36 - 2) = L'\0';
/* -GUID-'::'*/
GUIDFromString(ptr+len-3-36, &(pInstallInfo->prgUpgradeInfoList[count].PackageGuid));
}
pInstallInfo->cUpgrades = count; // we might have skipped some.
}
pPlatformInfo = pPackageDetail->pPlatformInfo =
(PLATFORMINFO *) CoTaskMemAlloc(sizeof (PLATFORMINFO));
if (!pPlatformInfo)
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
memset(pPlatformInfo, NULL, sizeof(PLATFORMINFO));
posn = GetPropertyFromAttr(pAttr, cgot, ARCHLIST);
if (posn < cgot)
// Minor BUGBUG:: int converted to long.
UnpackDWArrFrom(pAttr[posn], &pdwArch, (unsigned long *)&(pPlatformInfo->cPlatforms));
pPlatformInfo->prgPlatform = (CSPLATFORM *)CoTaskMemAlloc(sizeof(CSPLATFORM)*
(pPlatformInfo->cPlatforms));
if (!(pPlatformInfo->prgPlatform))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; (count < (pPlatformInfo->cPlatforms)); count++)
PackPlatform (pdwArch[count], (pPlatformInfo->prgPlatform)+count);
CoTaskMemFree(pdwArch);
posn = GetPropertyFromAttr(pAttr, cgot, LOCALEID);
if (posn < cgot)
// Minor BUGBUG:: int converted to long.
UnpackDWArrFrom(pAttr[posn], &(pPlatformInfo->prgLocale),
(unsigned long *)&(pPlatformInfo->cLocales));
//
// fill in ActivationInfo.
//
pActInfo = pPackageDetail->pActInfo =
(ACTIVATIONINFO *) CoTaskMemAlloc(sizeof (ACTIVATIONINFO));
if (!pActInfo) {
hr = E_OUTOFMEMORY;
ERROR_ON_FAILURE(hr);
}
memset(pActInfo, NULL, sizeof(ACTIVATIONINFO));
// get the progids so that we can eliminate progids from Clsids that do not match.
posn = GetPropertyFromAttr(pAttr, cgot, PKGCLSIDLIST);
cClasses = 0; szClasses = NULL;
if (posn < cgot)
UnpackStrArrFrom(pAttr[posn], &szClasses, &cClasses);
pActInfo->cClasses = cClasses;
if (cClasses)
{
pActInfo->pClasses = (CLASSDETAIL *) CoTaskMemAlloc (cClasses * sizeof(CLASSDETAIL));
if (!(pActInfo->pClasses))
return E_OUTOFMEMORY;
memset (pActInfo->pClasses, NULL, cClasses * sizeof(CLASSDETAIL));
for (count = 0; count < cClasses; count++)
{
WCHAR *szADsFullClassPath=NULL;
WCHAR szClassName[_MAX_PATH];
if (wcslen(szClasses[count]) > (STRINGGUIDLEN-1))
{
WCHAR *szPtr = NULL;
szClasses[count][STRINGGUIDLEN-1] = L'\0';
pActInfo->pClasses[count].dwComClassContext =
wcstoul(szClasses[count]+STRINGGUIDLEN, &szPtr, 16);
}
wsprintf(szClassName, L"CN=%s", szClasses[count]);
BuildADsPathFromParent(szClassContainerPath, szClassName, &szADsFullClassPath);
hr = GetClassDetail(szADsFullClassPath, &(pActInfo->pClasses[count]));
ERROR_ON_FAILURE(hr);
// remove all the progids that do not belong to this package.
FreeADsMem(szADsFullClassPath);
}
CoTaskMemFree(szClasses);
}
posn = GetPropertyFromAttr(pAttr, cgot, PKGIIDLIST);
cClasses = 0; szClasses = NULL;
if (posn < cgot)
UnpackStrArrFrom(pAttr[posn], &szClasses, &cClasses);
pActInfo->cInterfaces = cClasses;
if (cClasses)
{
pActInfo->prgInterfaceId = (IID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
if (!(pActInfo->prgInterfaceId))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; count < cClasses; count++)
{
GUIDFromString(szClasses[count], (pActInfo->prgInterfaceId + count));
}
CoTaskMemFree(szClasses);
}
posn = GetPropertyFromAttr(pAttr, cgot, PKGTLBIDLIST);
cClasses = 0; szClasses = NULL;
if (posn < cgot)
UnpackStrArrFrom(pAttr[posn], &szClasses, &cClasses);
pActInfo->cTypeLib = cClasses;
if (cClasses)
{
pActInfo->prgTlbId = (IID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
if (!(pActInfo->prgTlbId))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; count < cClasses; count++)
{
GUIDFromString(szClasses[count], (pActInfo->prgTlbId + count));
}
CoTaskMemFree(szClasses);
}
posn = GetPropertyFromAttr(pAttr, cgot, PKGFILEEXTNLIST);
cClasses = 0;
if (posn < cgot)
UnpackStrArrAllocFrom(pAttr[posn], &(pActInfo->prgShellFileExt), &cClasses);
pActInfo->cShellFileExt = cClasses;
if (cClasses)
{
pActInfo->prgPriority = (UINT *)CoTaskMemAlloc(cClasses * sizeof(UINT));
if (!(pActInfo->prgPriority))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; count < cClasses; count++)
{
LPOLESTR pStr=NULL;
UINT cLen = wcslen((pActInfo->prgShellFileExt)[count]);
*((pActInfo->prgShellFileExt)[count] + (cLen - 3)) = NULL;
(pActInfo->prgPriority)[count] =
wcstoul((pActInfo->prgShellFileExt)[count]+(cLen-2), &pStr, 10);
}
}
//
// fill in package misc info
//
posn = GetPropertyFromAttr(pAttr, cgot, PACKAGENAME);
if (posn < cgot)
UnpackStrAllocFrom(pAttr[posn], &(pPackageDetail->pszPackageName));
else
ERROR_ON_FAILURE(hr=CS_E_OBJECT_NOTFOUND);
posn = GetPropertyFromAttr(pAttr, cgot, MSIFILELIST);
if (posn < cgot) {
LPOLESTR *rpszSourceList = NULL, psz = NULL, pStr = NULL;
DWORD Loc = 0;
UnpackStrArrFrom(pAttr[posn], &(rpszSourceList),
(DWORD *)&(pPackageDetail->cSources));
// reorder and allocate spaces.
if (pPackageDetail->cSources)
{
pPackageDetail->pszSourceList = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*
(pPackageDetail->cSources));
if (!(pPackageDetail->pszSourceList))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
for (count = 0; count < (pPackageDetail->cSources); count++)
{
psz = wcschr(rpszSourceList[count], L':');
*psz = L'\0';
Loc = wcstoul(rpszSourceList[count], &pStr, 10);
pPackageDetail->pszSourceList[Loc] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(psz+1)+1));
if (!(pPackageDetail->pszSourceList[Loc]))
ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
wsprintf(pPackageDetail->pszSourceList[Loc], L"%s", psz+1);
}
}
CoTaskMemFree(rpszSourceList);
}
posn = GetPropertyFromAttr(pAttr, cgot, PKGCATEGORYLIST);
cClasses = 0; szClasses = NULL;
if (posn < cgot)
UnpackStrArrFrom(pAttr[posn], &szClasses, &cClasses);
if (cClasses)
{
pPackageDetail->rpCategory = (GUID *)CoTaskMemAlloc (sizeof(GUID) * cClasses);
if (!(pPackageDetail->rpCategory))
ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
pPackageDetail->cCategories = cClasses;
for (count = 0; count < cClasses; count++)
{
GUIDFromString(szClasses[count], (pPackageDetail->rpCategory + count));
}
CoTaskMemFree(szClasses);
}
return S_OK;
Error_Cleanup:
ReleasePackageDetail(pPackageDetail);
memset(pPackageDetail, 0, sizeof(PACKAGEDETAIL));
if (pAttr)
FreeADsMem(pAttr);
return hr;
}