// // 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; }