//---------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996-1999 // // File: enumapp.cxx // // Contents: Per Class Container Package Enumeration // // // History: 09-09-96 DebiM created // 11-01-97 DebiM modified, moved to cstore // //---------------------------------------------------------------------------- #include "cstore.hxx" //IEnumPackage implementation. HRESULT CEnumPackage::QueryInterface(REFIID riid, void** ppObject) { if (riid==IID_IUnknown || riid==IID_IEnumPackage) { *ppObject=(IEnumPackage *) this; } else { return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG CEnumPackage::AddRef() { InterlockedIncrement((long*) &m_dwRefCount); return m_dwRefCount; } ULONG CEnumPackage::Release() { ULONG dwRefCount=m_dwRefCount-1; if (InterlockedDecrement((long*) &m_dwRefCount)==0) { delete this; return 0; } return dwRefCount; } // // CEnumPackage::Next // ------------------ // // // // Synopsis: This method returns the next celt number of packages // within the scope of the enumeration. // Packages are returned in the alphabetical name order. // // Arguments: [in] celt - Number of package details to fetch // INSTALLINFO *rgelt - Package detail structure // ULONG *pceltFetched - Number of packages returned // // Returns: S_OK or S_FALSE if short of packages // // // HRESULT CEnumPackage::Next(ULONG celt, PACKAGEDISPINFO *rgelt, ULONG *pceltFetched) { ULONG cgot = 0, i, j; HRESULT hr = S_OK; if ((celt > 1) && (!pceltFetched)) return E_INVALIDARG; if (pceltFetched) (*pceltFetched) = 0; // // Clear up this structure in case our fetch fails -- // we don't want callers freeing invalid memory // memset(rgelt, 0, sizeof(*rgelt) * celt); hr = FetchPackageInfo ( m_hADs, m_hADsSearchHandle, m_dwAppFlags, m_dwQuerySpec, m_pPlatform, celt, &cgot, rgelt, &m_fFirst, &m_PolicyId, m_szGpoPath, m_pRsopUserToken); if (FAILED(hr)) { // // Clear up this structure so that callers don't // try to free invalid memory when this fails // memset(rgelt, 0, sizeof(*rgelt) * celt); cgot = 0; if ( ( ( APPQUERY_RSOP_ARP == m_dwQuerySpec ) || ( APPQUERY_USERDISPLAY == m_dwQuerySpec ) ) && ( hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) ) ) { hr = S_FALSE; } } ERROR_ON_FAILURE(hr); m_dwPosition += cgot; if (pceltFetched) *pceltFetched = cgot; if (cgot != celt) hr = S_FALSE; else hr = S_OK; return hr; Error_Cleanup: return RemapErrorCode(hr, m_szPackageName); } HRESULT CEnumPackage::Skip(ULONG celt) { ULONG celtFetched = NULL, i; HRESULT hr = S_OK; PACKAGEDISPINFO *pIf = NULL; pIf = new PACKAGEDISPINFO[celt]; hr = Next(celt, pIf, &celtFetched); for (i = 0; i < celtFetched; i++) ReleasePackageInfo(pIf+i); delete [] pIf; return hr; } HRESULT CEnumPackage::Reset() { HRESULT hr = S_OK; LPOLESTR* ppszAttrs; DWORD cAttrs; m_dwPosition = 0; m_fFirst = TRUE; // execute the search and keep the handle returned. if (m_hADsSearchHandle) { ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); m_hADsSearchHandle = NULL; } ppszAttrs = GetAttributesFromQuerySpec( m_dwQuerySpec, &cAttrs); if ( ppszAttrs ) { hr = ADSIExecuteSearch( m_hADs, m_szfilter, ppszAttrs, cAttrs, &m_hADsSearchHandle); } else { hr = E_INVALIDARG; } return RemapErrorCode(hr, m_szPackageName); } CEnumPackage::CEnumPackage(CServerContext* pServerContext, GUID PolicyId, LPOLESTR pszPolicyName, LPOLESTR pszClassStorePath, PRSOPTOKEN pRsopToken ) { m_dwRefCount = 0; m_fFirst = TRUE; m_szfilter = NULL; m_dwPosition = 0; m_dwAppFlags = 0; m_pPlatform = NULL; m_hADs = NULL; m_hADsSearchHandle = NULL; memcpy (&m_PolicyId, &PolicyId, sizeof(GUID)); m_szPolicyName[0] = NULL; m_pRsopUserToken = pRsopToken; m_szPackageName[0] = L'\0'; if (pszPolicyName) { (void) StringCchCopy (m_szPolicyName, _MAX_PATH, pszPolicyName); } if ( pServerContext ) { HRESULT hrContext; hrContext = m_ServerContext.Initialize( pServerContext ); // // If this fails, we will skip subsequent initialization as well, // and any operations with this object will fail because those // intiailziations are not complete // if ( FAILED(hrContext) ) { return; } } // // Remember the path of the gpo from which we are originating // This information is needed for RSOP to determine where // the package came from // // Note that if this fails, no operations on this object will succeed // m_szGpoPath = AllocGpoPathFromClassStorePath( pszClassStorePath ); } HRESULT CEnumPackage::Initialize( WCHAR *szPackageName, WCHAR *szfilter, DWORD dwAppFlags, BOOL bPlanning, CSPLATFORM *pPlatform) { HRESULT hr = S_OK; ADS_SEARCHPREF_INFO SearchPrefs[3]; LPOLESTR* ppszAttrs; DWORD cAttrs; LONG lSecurityFlags; DWORD cPrefs; cPrefs = 2; // // Be sure we're properly initialized // if ( ! m_szGpoPath ) { return E_OUTOFMEMORY; } // // Set the security of our communications based on the preference // of the caller // lSecurityFlags = GetDsFlags(); m_szfilter = (LPOLESTR)CsMemAlloc (sizeof(WCHAR) * (wcslen(szfilter)+1)); if (!m_szfilter) return E_OUTOFMEMORY; // copy the filters, package name, flags and locale. hr = StringCchCopy(m_szfilter, wcslen(szfilter)+1, szfilter); ERROR_ON_FAILURE(hr); hr = StringCchCopy(m_szPackageName, _MAX_PATH, szPackageName); ERROR_ON_FAILURE(hr); m_dwAppFlags = ClientSideFilterFromQuerySpec( dwAppFlags, bPlanning ); m_dwQuerySpec = dwAppFlags; // open the package container. hr = DSServerOpenDSObject(&m_ServerContext, szPackageName, lSecurityFlags, &m_hADs); ERROR_ON_FAILURE(hr); // set the search preference. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL; SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER; SearchPrefs[1].vValue.Integer = SEARCHPAGESIZE; // // For RSOP, we need to add an extra search pref to obtain the security // descriptor // if ( ( APPQUERY_RSOP_ARP == dwAppFlags ) || ( APPQUERY_RSOP_LOGGING == dwAppFlags ) ) { SearchPrefs[2].dwSearchPref = ADS_SEARCHPREF_SECURITY_MASK; SearchPrefs[2].vValue.dwType = ADSTYPE_INTEGER; // // Request everything but the SACL // SearchPrefs[2].vValue.Integer = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; cPrefs ++; } hr = ADSISetSearchPreference(m_hADs, SearchPrefs, cPrefs); ERROR_ON_FAILURE(hr); // copy platform if (pPlatform) { m_pPlatform = (CSPLATFORM *) CsMemAlloc(sizeof(CSPLATFORM)); if (!m_pPlatform) ERROR_ON_FAILURE(hr=E_OUTOFMEMORY); memcpy (m_pPlatform, pPlatform, sizeof(CSPLATFORM)); } ppszAttrs = GetAttributesFromQuerySpec( m_dwQuerySpec, &cAttrs); // execute the search and keep the handle returned. hr = ADSIExecuteSearch( m_hADs, szfilter, ppszAttrs, cAttrs, &m_hADsSearchHandle); Error_Cleanup: return RemapErrorCode(hr, m_szPackageName); } CEnumPackage::~CEnumPackage() { if (m_hADsSearchHandle) ADSICloseSearchHandle(m_hADs, m_hADsSearchHandle); if (m_hADs) ADSICloseDSObject(m_hADs); if (m_szfilter) CsMemFree(m_szfilter); if (m_pPlatform) CsMemFree(m_pPlatform); if (m_szGpoPath) CsMemFree(m_szGpoPath); } //-------------------------------------------------------------- CMergedEnumPackage::CMergedEnumPackage() { m_pcsEnum = NULL; m_cEnum = 0; m_csnum = 0; m_dwRefCount = 0; } CMergedEnumPackage::~CMergedEnumPackage() { ULONG i; for (i = 0; i < m_cEnum; i++) m_pcsEnum[i]->Release(); CsMemFree(m_pcsEnum); } HRESULT __stdcall CMergedEnumPackage::QueryInterface(REFIID riid, void * * ppObject) { *ppObject = NULL; //gd if ((riid==IID_IUnknown) || (riid==IID_IEnumPackage)) { *ppObject=(IEnumPackage *) this; } else { return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG __stdcall CMergedEnumPackage::AddRef() { InterlockedIncrement((long*) &m_dwRefCount); return m_dwRefCount; } ULONG __stdcall CMergedEnumPackage::Release() { ULONG dwRefCount; if ((dwRefCount = InterlockedDecrement((long*) &m_dwRefCount))==0) { delete this; return 0; } return dwRefCount; } HRESULT __stdcall CMergedEnumPackage::Next( ULONG celt, PACKAGEDISPINFO *rgelt, ULONG *pceltFetched) { ULONG count=0, total = 0; HRESULT hr; // // Clear everything // memset( rgelt, 0, sizeof(*rgelt) * celt ); for (; m_csnum < m_cEnum; m_csnum++) { count = 0; hr = m_pcsEnum[m_csnum]->Next(celt, rgelt+total, &count); if (FAILED(hr)) { // // Release everything on failure // ULONG iAllocated; for ( iAllocated = 0; iAllocated < total; iAllocated++ ) { ReleasePackageInfo( rgelt+iAllocated ); } return hr; } total += count; celt -= count; if (!celt) break; } if (pceltFetched) *pceltFetched = total; if (!celt) return S_OK; return S_FALSE; } HRESULT __stdcall CMergedEnumPackage::Skip( ULONG celt) { PACKAGEDISPINFO *pPackageInfo = NULL; HRESULT hr = S_OK; ULONG cgot = 0, i; pPackageInfo = (PACKAGEDISPINFO *)CsMemAlloc(sizeof(PACKAGEDISPINFO)*celt); if (!pPackageInfo) return E_OUTOFMEMORY; hr = Next(celt, pPackageInfo, &cgot); for (i = 0; i < cgot; i++) ReleasePackageInfo(pPackageInfo+i); CsMemFree(pPackageInfo); return hr; } HRESULT __stdcall CMergedEnumPackage::Reset() { ULONG i; for (i = 0; ((i <= m_csnum) && (i < m_cEnum)); i++) m_pcsEnum[i]->Reset(); // ignoring all error values m_csnum = 0; return S_OK; } HRESULT CMergedEnumPackage::Initialize(IEnumPackage **pcsEnum, ULONG cEnum) { ULONG i; m_csnum = 0; m_pcsEnum = (IEnumPackage **)CsMemAlloc(sizeof(IEnumPackage *) * cEnum); if (!m_pcsEnum) return E_OUTOFMEMORY; for (i = 0; i < cEnum; i++) m_pcsEnum[i] = pcsEnum[i]; m_cEnum = cEnum; return S_OK; }