//---------------------------------------------------------------------------- // Microsoft OLE DB Implementation For Index Server // (C) Copyright 1997 By Microsoft Corporation. // // @doc // // @module PTPROPS.CPP | // // @rev 1 | 10-13-97 | Briants | Created // // Includes ------------------------------------------------------------------ #pragma hdrstop #include "msidxtr.h" // Constants and Static Struct ----------------------------------------------- #define CALC_CCH_MINUS_NULL(p1) (sizeof(p1) / sizeof(*(p1))) - 1 // Code ---------------------------------------------------------------------- // CScopeData::CScopeData --------------------------------------------------- // // @mfunc Constructor // CScopeData::CScopeData() { m_cRef = 1; m_cScope = 0; m_cMaxScope = 0; m_cbData = 0; m_cbMaxData = 0; m_rgbData = NULL; m_rgulDepths = NULL; m_rgCatalogOffset = NULL; m_rgScopeOffset = NULL; m_rgMachineOffset = NULL; } // CScopeData::~CScopeData --------------------------------------------------- // // @mfunc Destructor // CScopeData::~CScopeData() { delete m_rgulDepths; delete m_rgCatalogOffset; delete m_rgScopeOffset; delete m_rgMachineOffset; delete m_rgbData; } // CScopeData::Reset --------------------------------------------------------- // // @mfunc Reset the scope count and offsets back to initial state. // // @rdesc HRESULT | status of methods success / failure // @flags OTHER | from called methods // HRESULT CScopeData::Reset(void) { // Reset the offsets to unused for (ULONG i = 0; i 0 ); ULONG cRef = InterlockedDecrement( (long *) &m_cRef ); if( 0 == cRef ) { delete this; return 0; } return cRef; } // CScopeData::GetData ------------------------------------------------------- // // @mfunc Copies the current value of our scope data into the passed in // variant // // @rdesc HRESULT | status of methods success / failure // @flags S_OK | retrieved the scope data // @flags E_INVALIDARG | Unknown PropId requested // @flags OTHER | from called methods // HRESULT CScopeData::GetData( ULONG uPropId, //@parm IN | id of scope data to return VARIANT* pvValue, //@parm INOUT | Variant to return data in LPCWSTR pcwszCatalog ) { assert( pvValue ); HRESULT hr; ULONG ul; SAFEARRAYBOUND rgsabound[1]; SAFEARRAY FAR* psa = NULL; rgsabound[0].lLbound = 0; rgsabound[0].cElements = m_cScope; // Make sure that we free any memory that may be held by the variant. VariantClear(pvValue); switch( uPropId ) { LONG rgIx[1]; case PTPROPS_SCOPE: { // Create a 1 dim safe array of type BSTR psa = SafeArrayCreate(VT_BSTR, 1, rgsabound); if( psa ) { for(ul=0; ul 0 ); // Check to see if there is room in the Data buffer, if not // reallocate data buffer if( m_cbData + cb > m_cbMaxData ) { ULONG cbTempMax = m_cbMaxData + ( (cb < CB_SCOPE_DATA_BUFFER_INC) ? (CB_SCOPE_DATA_BUFFER_INC) : (cb + CB_SCOPE_DATA_BUFFER_INC) ); m_rgbData = renewx( m_rgbData, m_cbMaxData, cbTempMax ); m_cbMaxData = cbTempMax; } // copy data and terminator RtlCopyMemory( (m_rgbData + m_cbData), pData, cb ); // Set the offset where the new value can be found *pulOffset = m_cbData; // Adjust offset to start on an 8 Byte boundary. assert( (m_cbData % 8) == 0 ); // @devnote: After this calculation, m_cchData may actually be larger // than m_cchMaxData. This is OK, because FindOffsetBuffer will re-alloc // the next time around. m_cbData += cb + (8 - (cb % 8)); } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH return sc; } // CScopeData::SetTemporaryMachine ------------------------------------------- // // @mfunc Stores the machine name used for setting machine properties // in the compiler environment. // // @rdesc HRESULT | status of methods success / failure // @flags OTHER | from called methods // HRESULT CScopeData::SetTemporaryMachine ( LPWSTR pwszMachine, // @parm IN | machine to store ULONG cch // @parm IN | count of characters for new scope, exclude terminator ) { HRESULT hr; ULONG ulOffset; assert( pwszMachine ); assert( wcslen(pwszMachine) == cch ); // Increment count of characters to include null terminator cch++; hr = CacheData(pwszMachine, (cch * sizeof(WCHAR)), &ulOffset); if( SUCCEEDED(hr) ) { m_rgMachineOffset[m_cScope] = ulOffset; } return hr; } // CScopeData::SetTemporaryCatalog ------------------------------------------- // // @mfunc Stores the catalog name used for setting scope properties // in the compiler environment. // // @rdesc HRESULT | status of methods success / failure // @flags S_OK | Data value stored at returned offset. // @flags OTHER | from called methods // HRESULT CScopeData::SetTemporaryCatalog ( LPWSTR pwszCatalog, // @parm IN | catalog name ULONG cch ) { assert( pwszCatalog ); assert( wcslen(pwszCatalog) == cch ); ULONG ulOffset; // Increment count of characters to include null terminator cch++; // Store the catalog value HRESULT hr = CacheData( pwszCatalog, (cch * sizeof(WCHAR)), &ulOffset ); if( SUCCEEDED(hr) ) m_rgCatalogOffset[m_cScope] = ulOffset; return hr; } // CScopeData::SetTemporaryScope --------------------------------------------- // // @mfunc Stores the scope name used for setting scope properties // in the compiler environment. // // @rdesc HRESULT | status of methods success / failure // @flags OTHER | from called methods // HRESULT CScopeData::SetTemporaryScope ( LPWSTR pwszScope, // @parm IN | scope to store ULONG cch // @parm IN | count of characters for new scope, exclude terminator ) { HRESULT hr; ULONG ulOffset; assert( pwszScope ); assert( wcslen(pwszScope) == cch ); // Increment count of characters to include null terminator cch++; hr = CacheData(pwszScope, (cch * sizeof(WCHAR)), &ulOffset); if( SUCCEEDED(hr) ) { m_rgScopeOffset[m_cScope] = ulOffset; // @devnote: Fixup for '/' being in the scope, Index Server requires // this to rewritten. for (WCHAR *wcsLetter = (WCHAR*)(m_rgbData + ulOffset); *wcsLetter != L'\0'; wcsLetter++) if (L'/' == *wcsLetter) *wcsLetter = L'\\'; // path names needs backslashes, not forward slashes } return hr; } // CScopeData::IncrementScopeCount ------------------------------------------- // // @mfunc Increments the number of temporary scopes defined. It also // copies the depth values to the next scope in case multiple // scopes are defined with the same traversal depth. // // @rdesc HRESULT | status of methods success / failure // @flags S_OK | Activated next scope arrays element // @flags E_OUTOFMEMORY | could allocate enough resources to do this. // HRESULT CScopeData::IncrementScopeCount() { SCODE sc = S_OK; TRY { ULONG cCurScope = m_cScope + 1; // Check if re-alloc must be done. if( cCurScope >= m_cMaxScope ) { ULONG cNewMaxScope = m_cMaxScope + SCOPE_BUFFERS_INCREMENT; m_rgulDepths = renewx( m_rgulDepths, m_cMaxScope, cNewMaxScope ); m_rgScopeOffset = renewx( m_rgScopeOffset, m_cMaxScope, cNewMaxScope ); m_rgCatalogOffset = renewx( m_rgCatalogOffset, m_cMaxScope, cNewMaxScope ); m_rgMachineOffset = renewx( m_rgMachineOffset, m_cMaxScope, cNewMaxScope ); // If the is the initial Allocation, then make our current scope // equal to 0 if( m_cMaxScope == 0 ) cCurScope = 0; // Initialize new elements for (ULONG i = cCurScope; i m_rgwchCiColumn[1] = L'\0'; // Second is Null Term m_cchMaxRestriction = 0; m_cchRestriction = 0; m_pwszRestriction = NULL; m_pwszRestrictionAppendPtr = NULL; m_fLeftParen = false; } // CImpIParserTreeProperties::~CImpIParserTreeProperties ----------------------- // // @mfunc Destructor // // @rdesc None // CImpIParserTreeProperties::~CImpIParserTreeProperties() { FreeErrorDescriptions(); delete [] m_pwszRestriction; delete [] m_pwszCatalog; if( 0 != m_pCScopeData ) m_pCScopeData->Release(); } // CImpIParserTreeProperties::FInit ------------------------------- // // @mfunc Initialize class // // @rdesc HResult indicating the status of the method // @flag S_OK | Init'd // HRESULT CImpIParserTreeProperties::FInit( LPCWSTR pcwszCatalog, //@parm IN | Current Catalog LPCWSTR pcwszMachine ) //@parm IN | Current Machine { SCODE sc = S_OK; TRY { Win4Assert( 0 != pcwszCatalog ); Win4Assert( 0 == m_pwszCatalog ); XPtrST xCatalog( CopyString(pcwszCatalog) ); sc = CreateNewScopeDataObject( pcwszMachine ); if (SUCCEEDED(sc) ) m_pwszCatalog = xCatalog.Acquire(); } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH return sc; } // CImpIParserTreeProperties::GetTreeProperties ------------------------------- // // @mfunc Allows retrieval of properties // // @rdesc HResult indicating the status of the method // @flag S_OK | Property Value retrieved // STDMETHODIMP CImpIParserTreeProperties::GetProperties( ULONG eParseProp, //@parm IN | property to return value for VARIANT* vParseProp //@parm IN | Value of property ) { // Require a buffer assert( vParseProp ); //@TODO should we have to do this, or assume it is clean. VariantClear(vParseProp); switch( eParseProp ) { case PTPROPS_SCOPE: case PTPROPS_DEPTH: case PTPROPS_MACHINE: return m_pCScopeData->GetData(eParseProp, vParseProp); break; case PTPROPS_CATALOG: return m_pCScopeData->GetData(eParseProp, vParseProp, m_pwszCatalog); break; case PTPROPS_CIRESTRICTION: V_BSTR(vParseProp) = SysAllocString(m_pwszRestriction); V_VT(vParseProp) = VT_BSTR; break; case PTPROPS_ERR_IDS: V_I4(vParseProp) = m_iErrOrd; V_VT(vParseProp) = VT_I4; break; case PTPROPS_ERR_HR: V_I4(vParseProp) = m_LastHR; V_VT(vParseProp) = VT_I4; break; case PTPROPS_ERR_DISPPARAM: { HRESULT hr = NOERROR; SAFEARRAYBOUND rgsabound[1]; V_VT(vParseProp) = VT_BSTR | VT_ARRAY; V_ARRAY(vParseProp) = NULL; rgsabound[0].lLbound = 0; rgsabound[0].cElements = m_cErrParams; // Create a 1 dim safe array of type BSTR SAFEARRAY FAR* psa = SafeArrayCreate(VT_BSTR, 1, rgsabound); if( psa ) { LONG rgIx[1]; for(ULONG ul=0; ulAddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } // CImpIParserTreeProperties::AddRef ------------------------------------------ // // @mfunc Increments a persistence count for the object // // @rdesc Current reference count // STDMETHODIMP_(ULONG) CImpIParserTreeProperties::AddRef (void) { return InterlockedIncrement( (long*) &m_cRef); } // CImpIParserTreeProperties::Release ----------------------------------------- // // @mfunc Decrements a persistence count for the object and if // persistence count is 0, the object destroys itself. // // @rdesc Current reference count // STDMETHODIMP_(ULONG) CImpIParserTreeProperties::Release (void) { assert( m_cRef > 0 ); ULONG cRef = InterlockedDecrement( (long *) &m_cRef ); if( 0 == cRef ) { delete this; return 0; } return cRef; } // CImpIParserTreeProperties::SetCiColumn ------------------------------------- // // @mfunc Store the current column name to be applied to the // restriction later // // @rdesc None // void CImpIParserTreeProperties::SetCiColumn ( LPWSTR pwszColumn // @parm IN | column name for this portion of restriction ) { // Should alway remain a assert( *m_rgwchCiColumn == L' ' ); assert( wcslen(pwszColumn) <= MAX_CCH_COLUMNNAME ); // Copy column name into buffer. wcscpy(&m_rgwchCiColumn[1], pwszColumn); } // CImpIParserTreeProperties::AppendCiRestriction ----------------------------- // // @mfunc Appends the given string to the end of the contructed CiRestriction. // // @rdesc HRESULT | status of methods success / failure // @flags S_OK // @flags E_OUTOFMEMORY // HRESULT CImpIParserTreeProperties::AppendCiRestriction ( LPWSTR pwsz, // @parm IN | latest addition to the generated CiRestriction ULONG cch // @parm IN | count of characters for new token, exclude terminator ) { SCODE sc = S_OK; TRY { assert( 0 != pwsz && 0 != cch ); assert( wcslen(pwsz) == cch ); // cch should NOT include space for terminator // Determine if buffer is large enough or needs to be expanded. if( m_cchRestriction + cch > m_cchMaxRestriction ) { ULONG cchNew = m_cchRestriction + ( (cch >= CCH_CIRESTRICTION_INCREMENT) ? (CCH_CIRESTRICTION_INCREMENT + cch) : CCH_CIRESTRICTION_INCREMENT); LPWSTR pwszTemp = renewx( m_pwszRestriction, m_cchMaxRestriction, cchNew ); if ( 0 != pwszTemp ) { // First allocation Processing if( 0 == m_cchMaxRestriction ) { *pwszTemp = L'\0'; m_cchRestriction = 1; } // Recalculate Append Pointer m_pwszRestrictionAppendPtr = pwszTemp + (m_pwszRestrictionAppendPtr - m_pwszRestriction); // Set member variable to new buffer. m_pwszRestriction = pwszTemp; // Set Max number of character slots m_cchMaxRestriction = cchNew; } else return E_OUTOFMEMORY; } assert( m_pwszRestriction ); assert( *m_pwszRestrictionAppendPtr == L'\0' ); //Should always be on Null Terminator wcscpy( m_pwszRestrictionAppendPtr, pwsz ); m_cchRestriction += cch; m_pwszRestrictionAppendPtr += cch; } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH return sc; } // CImpIParserTreeProperties::UseCiColumn ------------------------------------- // // @mfunc Copies the current CiRestriction column name to the CiRestriction // // @rdesc HRESULT | status of methods success / failure // @flags S_OK // @flags OTHER | from called methods // HRESULT CImpIParserTreeProperties::UseCiColumn ( WCHAR wch // @parm IN | prefix for column access ) { SCODE sc = S_OK; // Do we have a column name stored if( m_rgwchCiColumn[1] != L'\0' ) { m_rgwchCiColumn[0] = wch; sc = AppendCiRestriction( m_rgwchCiColumn, wcslen(m_rgwchCiColumn) ); if( SUCCEEDED(sc) ) { if( true == m_fLeftParen ) { sc = AppendCiRestriction(L" (", CALC_CCH_MINUS_NULL(L" (")); m_fLeftParen = false; } else { sc = AppendCiRestriction(L" ", CALC_CCH_MINUS_NULL(L" ")); } } m_rgwchCiColumn[0] = L' '; } return sc; } // CImpIParserTreeProperties::CreateNewScopeDataObject ------------------------- // // @mfunc Creates a new ScopeData container // // @rdesc HRESULT | status of methods success / failure // @flags S_OK // @flags E_FAIL | FInit failed // @flags E_OUTOFMEMORY // HRESULT CImpIParserTreeProperties::CreateNewScopeDataObject ( LPCWSTR pcwszMachine // @param IN | the current default machine ) { Assert( 0 != pcwszMachine ); SCODE sc = S_OK; TRY { // Allocate ScopeData container // @devnote: After this allocation has succeeded, all // deletions of this object should be done through refcounts XInterface xpScopeData( new CScopeData() ); sc = xpScopeData->FInit( pcwszMachine ); if( SUCCEEDED(sc) ) { if ( m_pCScopeData ) m_pCScopeData->Release(); m_pCScopeData = xpScopeData.Acquire(); } } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH return sc; } // CImpIParserTreeProperties::ReplaceScopeDataPtr ------------------------- // // @mfunc Take ownership of the ScopeData // // @rdesc void // void CImpIParserTreeProperties::ReplaceScopeDataPtr(CScopeData* pCScopeData) { assert( pCScopeData ); if( m_pCScopeData ) { ULONG ulRef = m_pCScopeData->Release(); assert( ulRef == 0 ); } m_pCScopeData = pCScopeData; m_pCScopeData->AddRef(); }