|
|
//
// Author: DebiM
// Date: January 97
//
//
// Class Access Implementation
//
// This source file contains implementations for IClassAccess
// interface on CAppContainer object.
//
// It uses ADs interfaces (over LDAP) to talk to an LDAP
// provider such as NTDS.
//
//---------------------------------------------------------------------
//
#include "cstore.hxx"
void GetDefaultPlatform(CSPLATFORM *pPlatform);
BOOL CheckMatching (QUERYCONTEXT *pQryContext, INSTALLINFO *pInstallInfo, PLATFORMINFO *pPlatformInfo );
extern LPOLESTR szInstallInfoColumns; extern LPOLESTR szPackageInfoColumns;
void FreeInstallInfo(INSTALLINFO *pInstallInfo) { CoTaskMemFree(pInstallInfo->pszScriptPath); CoTaskMemFree(pInstallInfo->pszSetupCommand); CoTaskMemFree(pInstallInfo->pszUrl); CoTaskMemFree(pInstallInfo->pClsid); memset(pInstallInfo, 0, sizeof (INSTALLINFO)); }
void FreePlatformInfo(PLATFORMINFO *pPlatformInfo) { CoTaskMemFree(pPlatformInfo->prgLocale); CoTaskMemFree(pPlatformInfo->prgPlatform); }
//
// CAppContainer implementation
//
CAppContainer::CAppContainer()
{ m_fOpen = FALSE; m_ADsContainer = NULL; m_pADsClassStore = NULL; m_ADsClassContainer = NULL; m_ADsPackageContainer = NULL; m_uRefs = 1; StartQuery(&m_pIDBCreateCommand); }
//
// CAppContainer implementation
//
CAppContainer::CAppContainer(LPOLESTR szStoreName, HRESULT *phr) { IADs *pADs = NULL; LPOLESTR pszName = NULL; DWORD dwStoreVersion = 0; *phr = S_OK; #ifdef DBG
WCHAR Name[32]; DWORD NameSize = 32; if ( ! GetUserName( Name, &NameSize ) ) CSDbgPrint(("CAppContainer::CAppContainer GetUserName failed 0x%x\n", GetLastError())); else CSDbgPrint(("CAppContainer::CAppContainer as %S\n", Name)); #endif
m_fOpen = FALSE; m_ADsContainer = NULL; m_pADsClassStore = NULL; m_ADsClassContainer = NULL; m_ADsPackageContainer = NULL; //
// For every interface pointer, we create a separate session
//
StartQuery(&m_pIDBCreateCommand); // Bind to a Class Store Container Object
// Cache the interface pointer
//
wcscpy (m_szContainerName, szStoreName); *phr = ADsGetObject( szStoreName, IID_IADsContainer, (void **)&m_ADsContainer ); if (!SUCCEEDED(*phr)) return; //
// Check the Schema Version of this container
//
*phr = m_ADsContainer->QueryInterface (IID_IADs, (void **)&m_pADsClassStore); if (!SUCCEEDED(*phr)) return; *phr = GetPropertyDW (m_pADsClassStore, STOREVERSION, &dwStoreVersion); if ((!SUCCEEDED(*phr)) || (dwStoreVersion != SCHEMA_VERSION_NUMBER)) { CSDbgPrint(("CS: .. Wrong Version of Class Container:%ws\n", m_szContainerName)); *phr = CS_E_INVALID_VERSION; return; } CSDbgPrint(("CS: .. Connected to Class Container:%ws\n", m_szContainerName)); //
// Bind to the class container Object
// Cache the interface pointer
//
m_ADsClassContainer = NULL; *phr = m_ADsContainer->GetObject( NULL, CLASSCONTAINERNAME, (IDispatch **)&pADs); if (!SUCCEEDED(*phr)) return; pADs->QueryInterface(IID_IADsContainer, (void **)&m_ADsClassContainer ); *phr = pADs->get_ADsPath(&pszName); wcscpy (m_szClassName, pszName); SysFreeString(pszName); pADs->Release(); pADs = NULL; if (!SUCCEEDED(*phr)) return; //
// Bind to the Package container Object
// Cache the interface pointer
//
m_ADsPackageContainer = NULL; *phr = m_ADsContainer->GetObject( NULL, PACKAGECONTAINERNAME, (IDispatch **)&pADs); if (!SUCCEEDED(*phr)) return; pADs->QueryInterface(IID_IADsContainer, (void **)&m_ADsPackageContainer ); *phr = pADs->get_ADsPath(&pszName); wcscpy (m_szPackageName, pszName); SysFreeString(pszName); pADs->Release(); pADs = NULL; if (!SUCCEEDED(*phr)) return; m_fOpen = TRUE; m_uRefs = 1; }
CAppContainer::~CAppContainer(void) { UINT i; EndQuery(m_pIDBCreateCommand); m_pIDBCreateCommand = NULL; if (m_fOpen) { //UnlistDB (this);
m_fOpen = FALSE; } if (m_ADsClassContainer) { m_ADsClassContainer->Release(); m_ADsClassContainer = NULL; } if (m_ADsPackageContainer) { m_ADsPackageContainer->Release(); m_ADsPackageContainer = NULL; } if (m_ADsContainer) { m_ADsContainer->Release(); m_ADsContainer = NULL; } if (m_pADsClassStore) { m_pADsClassStore->Release(); m_pADsClassStore = NULL; } }
HRESULT CAppContainer::GetPackageDetails ( LPOLESTR pszPackageName, PACKAGEDETAIL *pPackageDetail) { HRESULT hr = S_OK; IADs *pPackageADs = NULL; WCHAR szRdn [_MAX_PATH]; wcscpy (szRdn, L"CN="); wcscat (szRdn, pszPackageName); hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs); if (!SUCCEEDED(hr)) return hr; hr = GetPackageDetail (pPackageADs, pPackageDetail); return hr; }
//
// ::EnumPackages
//----------------
//
// Obtains an enumerator for packages in the app container.
// Takes the following optional filter specifications:
//
// [in] pszPackageName : Substring match for a package name
// [in] pCategory : Category id of interest
// [in] dwAppFlags : following bits set to select specific ones
// Published Only APPINFO_PUBLISHED
// Assigned Only APPINFO_ASSIGNED
// Msi Only APPINFO_MSI
// Visible APPINFO_VISIBLE
// Auto-Install APPINFO_AUTOINSTALL
//
// All Locale APPINFO_ALLLOCALE
// All Platform APPINFO_ALLPLATFORM
//
//
HRESULT CAppContainer::EnumPackages ( LPOLESTR pszPackageName, GUID *pCategory, ULONGLONG *pLastUsn, DWORD dwAppFlags, IEnumPackage **ppIEnumPackage ) { HRESULT hr; CEnumPackage *pEnum; WCHAR szLdapFilter [2000]; UINT len; UINT fFilters = 0; LCID dwLocale, *pdwLocale; CSPLATFORM *pPlatform, Platform; if (!IsValidPtrOut(ppIEnumPackage, sizeof(IEnumPackage *))) return E_INVALIDARG; *ppIEnumPackage = NULL; pEnum = new CEnumPackage; if(NULL == pEnum) return E_OUTOFMEMORY; //
// Create a LDAP Search Filter based on input params
//
// Count Filters
if (pszPackageName && (*pszPackageName)) fFilters++; if (pLastUsn) fFilters++; if (pCategory) fFilters++; if (dwAppFlags & APPINFO_ASSIGNED) fFilters++;
if (fFilters == 0) { // No Conditionals
wsprintf (szLdapFilter, L"<%s>;(objectClass=packageRegistration)", m_szPackageName); len = wcslen (szLdapFilter); } else { if (fFilters == 1) { wsprintf (szLdapFilter, L"<%s>;", m_szPackageName); } else { wsprintf (szLdapFilter, L"<%s>;(&", m_szPackageName); } len = wcslen (szLdapFilter); if (pszPackageName) { //
// Validate
//
if (IsBadStringPtr(pszPackageName, _MAX_PATH)) return E_INVALIDARG; if (*pszPackageName) { wsprintf (&szLdapFilter[len], L"(%s=*%s*)", PACKAGENAME, pszPackageName); len = wcslen (szLdapFilter); } } if (pLastUsn) { //
// Validate
//
if (!IsValidReadPtrIn(pLastUsn, sizeof(ULONGLONG))) return E_INVALIDARG; wsprintf (&szLdapFilter[len], L"(%s>=%ul)", PKGUSN, *pLastUsn); len = wcslen (szLdapFilter); }
if (pCategory) { //
// Validate
//
STRINGGUID szCat; if (!IsValidReadPtrIn(pCategory, sizeof(GUID))) return E_INVALIDARG; StringFromGUID (*pCategory, szCat); wsprintf (&szLdapFilter[len], L"(%s=%s)", PKGCATEGORYLIST, szCat); len = wcslen (szLdapFilter); } if (dwAppFlags & APPINFO_ASSIGNED) // if only Assigned Packages are in demand
{ wsprintf (&szLdapFilter[len], L"(%s>=%d)", PACKAGEFLAGS, (ACTFLG_Assigned)); len = wcslen (szLdapFilter); } if (fFilters > 1) { szLdapFilter[len] = L')'; szLdapFilter[++len] = NULL; } } //
// Now append the attribute list to the search string
//
wsprintf (&szLdapFilter[len], L";%s", szPackageInfoColumns); //
// Check all local/platform flags
//
if (dwAppFlags & APPINFO_ALLLOCALE) { pdwLocale = NULL; } else { dwLocale = GetThreadLocale(); pdwLocale = &dwLocale; } if (dwAppFlags & APPINFO_ALLPLATFORM) { pPlatform = NULL; } else { pPlatform = &Platform; GetDefaultPlatform(pPlatform); } hr = pEnum->Initialize(szLdapFilter, dwAppFlags, pdwLocale, pPlatform); if (FAILED(hr)) { delete pEnum; return hr; } hr = pEnum->QueryInterface(IID_IEnumPackage,(void**) ppIEnumPackage); if (FAILED(hr)) { delete pEnum; return hr; } return S_OK; }
//
// CAppContainer::GetAppInfo
// -----------------------------
//
//
//
// Synopsis: This is the most common access point to the Class Store.
// It receives a CLSID and a QUERYCONTEXT.
// It looks up the Class Store container for a matching set
// of packages with in the context of the QUERYCONTEXT.
//
// QUERYCONTEXT includes
// Execution Context
// Locale Id
// Platform/OS
//
// If i finds an app that matches the requirements, it returns
// an INSTALLINFO structure containing installation details.
//
// Arguments: [in] clsid
// [in] pQryContext
// [out] pInstallInfo
//
// Returns: CS_E_PACKAGE_NOTFOUND
// S_OK
//
//
//
HRESULT STDMETHODCALLTYPE CAppContainer::GetAppInfo( uCLSSPEC * pclsspec, // Class Spec (GUID/Ext/MIME)
QUERYCONTEXT * pQryContext, // Query Attributes
INSTALLINFO * pInstallInfo ) //
// This is the most common method to access the Class Store.
// It queries the class store for implementations for a specific
// Class Id, or File Ext, or ProgID.
//
// If a matching implementation is available (for the object type,
// client architecture, locale and class context) then the installation
// parameters of the package is returned.
{ GUID clsid; WCHAR pszCommandText[1000]; STRINGGUID szClsid; UINT i; ULONG cRead; HRESULT hr; ULONG cSize = _MAX_PATH; BOOL fFound = FALSE; PLATFORMINFO PlatformInfo; LPOLESTR pFileExt = NULL; memset(pInstallInfo, 0, sizeof(INSTALLINFO)); if (!m_fOpen) return E_FAIL; //
// Check if the TypeSpec is MIMEType
// then map it to a CLSID
//
if (pclsspec->tyspec == TYSPEC_MIMETYPE) { //
// BUGBUG.
// Considering removal of MimeType support from Class Store
// Till it is decided the code is OUT.
return E_NOTIMPL; /*
if (IsBadStringPtr(pclsspec->tagged_union.pMimeType, _MAX_PATH)) return E_INVALIDARG; if ((pclsspec->tagged_union.pMimeType == NULL) || (*(pclsspec->tagged_union.pMimeType) == NULL)) return E_INVALIDARG; wsprintf (pszCommandText, L"<%s>;(%s=%s);name", m_szClassName, MIMETYPES, pclsspec->tagged_union.pMimeType); */ } switch (pclsspec->tyspec) { case TYSPEC_TYPELIB: if (IsNullGuid(pclsspec->tagged_union.typelibID)) return E_INVALIDARG; StringFromGUID (pclsspec->tagged_union.typelibID, szClsid); wsprintf (pszCommandText, L"<%s>;(%s=%s);", m_szPackageName, PKGTLBIDLIST, szClsid); break; case TYSPEC_IID: if (IsNullGuid(pclsspec->tagged_union.iid)) return E_INVALIDARG; StringFromGUID (pclsspec->tagged_union.iid, szClsid); wsprintf (pszCommandText, L"<%s>;(%s=%s);", m_szPackageName, PKGIIDLIST, szClsid); break; case TYSPEC_CLSID: //
// Check TreatAs
/* BUGBUG
Considering removal of support for TreatAs in Class Store. Till this is closed the code is out. if ((hr = GetTreatAs (clsid, &MapClsid, &(pPackageInfo->pszClassIconPath))) == S_OK) { //
// Put the result in the TreatAs field of PackageInfo
//
pPackageInfo->pTreatAsClsid = (GUID *)CoTaskMemAlloc(sizeof (CLSID)); memcpy (pPackageInfo->pTreatAsClsid, &MapClsid, sizeof (CLSID)); //
// BUGBUG. Must cache presence/absence of TreatAs info as it is
// a very common lookup into DS.
//
} */ if (IsNullGuid(pclsspec->tagged_union.clsid)) return E_INVALIDARG; StringFromGUID (pclsspec->tagged_union.clsid, szClsid); wsprintf (pszCommandText, L"<%s>;(%s=%s);", m_szPackageName, PKGCLSIDLIST, szClsid); break; case TYSPEC_FILEEXT: if (IsBadStringPtr(pclsspec->tagged_union.pFileExt, _MAX_PATH)) return E_INVALIDARG; if ((pclsspec->tagged_union.pFileExt == NULL) || (*(pclsspec->tagged_union.pFileExt) == NULL)) return E_INVALIDARG; /*
//
// BUGBUG. Because FileExt is stored with priority
// make sure that wildcard at end is used.
//
wsprintf (pszCommandText, L"<%s>;(%s=%s*);", m_szPackageName, PKGFILEEXTNLIST, pclsspec->tagged_union.pFileExt); */ //
// BUGBUG. Workaround for IDS bug.
// Change the below to the code above when this is fixed in NTDEV
//
wsprintf (pszCommandText, L"<%s>;(%s=%s);", m_szPackageName, QRYFILEEXT, pclsspec->tagged_union.pFileExt); pFileExt = pclsspec->tagged_union.pFileExt; break; case TYSPEC_PROGID: if (IsBadStringPtr(pclsspec->tagged_union.pProgId, _MAX_PATH)) return E_INVALIDARG; if ((pclsspec->tagged_union.pProgId == NULL) || (*(pclsspec->tagged_union.pProgId) == NULL)) return E_INVALIDARG; wsprintf (pszCommandText, L"<%s>;(%s=%s);", m_szPackageName, PKGPROGIDLIST, pclsspec->tagged_union.pProgId); break; case TYSPEC_PACKAGENAME: //
// Validate package name
//
if (IsBadStringPtr(pclsspec->tagged_union.pPackageName, _MAX_PATH)) return E_INVALIDARG; if ((pclsspec->tagged_union.pPackageName == NULL) || (*(pclsspec->tagged_union.pPackageName) == NULL)) return E_INVALIDARG; //
PACKAGEDETAIL PackageDetail; hr = GetPackageDetails (pclsspec->tagged_union.pPackageName, &PackageDetail); if (SUCCEEDED(hr)) { memcpy (pInstallInfo, PackageDetail.pInstallInfo, sizeof(INSTALLINFO)); if (PackageDetail.pActInfo) { CoTaskMemFree(PackageDetail.pActInfo->prgShellFileExt); CoTaskMemFree(PackageDetail.pActInfo->prgPriority); CoTaskMemFree(PackageDetail.pActInfo->prgInterfaceId); CoTaskMemFree(PackageDetail.pActInfo->prgTlbId); CoTaskMemFree(PackageDetail.pActInfo); } if (PackageDetail.pPlatformInfo) { CoTaskMemFree(PackageDetail.pPlatformInfo->prgPlatform); CoTaskMemFree(PackageDetail.pPlatformInfo->prgLocale); CoTaskMemFree(PackageDetail.pPlatformInfo); } CoTaskMemFree(PackageDetail.pszSourceList); CoTaskMemFree(PackageDetail.rpCategory); CoTaskMemFree(PackageDetail.pInstallInfo); } return hr; default: return E_NOTIMPL; } //
//
HACCESSOR hAccessor = NULL; IAccessor * pIAccessor = NULL; IRowset * pIRowset = NULL; ULONG cRowsFetched; INSTALLINFO InstallInfo[10]; UINT rgPriority [10]; wcscat (pszCommandText, szInstallInfoColumns); hr = ExecuteQuery (m_pIDBCreateCommand, pszCommandText, PACKAGEQUERY_COLUMN_COUNT, NULL, &hAccessor, &pIAccessor, &pIRowset ); if (!SUCCEEDED(hr)) goto done; //
// BUGBUG. Currently limited to 10.
// Must put a loop to retry more in future.
//
hr = FetchInstallData(pIRowset, hAccessor, pQryContext, pFileExt, 10, &cRowsFetched, &InstallInfo[0], &rgPriority[0] ); if ((hr != S_OK) || (cRowsFetched == 0)) { hr = CS_E_PACKAGE_NOTFOUND; } else { //
// Selected one is j
//
UINT j = 0; //
// process file-ext priority.
//
if ((pFileExt) && (cRowsFetched > 1)) { UINT Pri = rgPriority[0]; for (i=1; i < cRowsFetched; ++i) { if (rgPriority[i] > Pri) { Pri = rgPriority[i]; j = i; } } } //
// return the jth one
//
memcpy (pInstallInfo, &InstallInfo[j], sizeof(INSTALLINFO)); memset (&InstallInfo[j], NULL, sizeof(INSTALLINFO)); // Clean up all fetched except for jth one
for (i=0; i < cRowsFetched; i++) { if (i != j) FreeInstallInfo(&InstallInfo[i]); } } CloseQuery(pIAccessor, hAccessor, pIRowset); done: return hr; }
BOOL CheckMatching (QUERYCONTEXT *pQryContext, INSTALLINFO *pInstallInfo, PLATFORMINFO *pPlatformInfo ) { HRESULT hr; DWORD dwCtx, dwLocale; ULONG i; BOOL fMatch; CSPLATFORM *pPlatform; //
// Get all the specifics of this package
//
dwCtx = pInstallInfo->dwComClassContext; //
// if the implementation is a remote server,
// then skip matching platform
//
fMatch = FALSE; for (i=0; i < pPlatformInfo->cPlatforms; i++) { if (MatchPlatform (&(pQryContext->Platform), pPlatformInfo->prgPlatform+i)) { // matches
fMatch = TRUE; break; } } //
// either the locale seen is LANG_NEUTRAL (means does not matter)
// or the locale matches as specified
// then treat this as found.
// BUGBUG. In future we should be going thru the
// entire list to pick the best match
if (fMatch) { fMatch = FALSE; for (i=0; i < pPlatformInfo->cLocales; i++) { if (MatchLocale (pQryContext->Locale, pPlatformInfo->prgLocale[i])) { // Does not match the Locale requested
fMatch = TRUE; break; } } } return fMatch; }
|