Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

988 lines
28 KiB

//----------------------------------------------------------------------------
// 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<m_cMaxScope; i++)
{
m_rgScopeOffset[i] = UNUSED_OFFSET;
m_rgCatalogOffset[i] = UNUSED_OFFSET;
m_rgMachineOffset[i] = UNUSED_OFFSET;
}
// Set Scope Index Back to 0
m_cScope = 0;
return S_OK;
}
// CScopeData::FInit ---------------------------------------------------------
//
// @mfunc Initialize the Constructed Object
//
// @rdesc HRESULT | status of methods success / failure
// @flags OTHER | from called methods
//
HRESULT CScopeData::FInit
(
LPCWSTR pwszMachine // @param IN | current default machine
)
{
HRESULT hr;
// Allocate Scope buffers
// @devnote: IncrementScopeCount() has special logic for the first
// allocation, thus the m_cScope will remain 0 after this call
if( SUCCEEDED(hr = IncrementScopeCount()) )
{
assert( m_cScope == 0 );
// Initialize the machine
hr = SetTemporaryMachine((LPWSTR)pwszMachine, wcslen( pwszMachine ) );
}
return hr;
}
// CScopeData::AddRef ------------------------------------------
//
// @mfunc Increments a persistence count for the object
//
// @rdesc Current reference count
//
ULONG CScopeData::AddRef (void)
{
return InterlockedIncrement( (long*) &m_cRef);
}
// CScopeData::Release -----------------------------------------
//
// @mfunc Decrements a persistence count for the object and if
// persistence count is 0, the object destroys itself.
//
// @rdesc Current reference count
//
ULONG CScopeData::Release (void)
{
assert( m_cRef > 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<m_cScope; ul++)
{
rgIx[0] = ul;
BSTR bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgScopeOffset[ul]));
if( bstrVal )
{
hr = SafeArrayPutElement(psa, rgIx, bstrVal);
SysFreeString(bstrVal);
if( FAILED(hr) )
goto error_delete;
}
else
{
hr = ResultFromScode(E_OUTOFMEMORY);
goto error_delete;
}
}
V_VT(pvValue) = VT_BSTR | VT_ARRAY;
V_ARRAY(pvValue) = psa;
psa = NULL;
}
else
return ResultFromScode(E_OUTOFMEMORY);
}
break;
case PTPROPS_DEPTH:
{
// Create a 1 dim safe array of type I4
psa = SafeArrayCreate(VT_I4, 1, rgsabound);
if( psa )
{
for(ul=0; ul<m_cScope; ul++)
{
rgIx[0] = ul;
hr = SafeArrayPutElement(psa, rgIx, (void*)&m_rgulDepths[ul]);
if( FAILED(hr) )
goto error_delete;
}
V_VT(pvValue) = VT_I4 | VT_ARRAY;
V_ARRAY(pvValue) = psa;
psa = NULL;
}
else
return ResultFromScode(E_OUTOFMEMORY);
}
break;
case PTPROPS_CATALOG:
{
assert( pcwszCatalog );
// Create a 1 dim safe array of type BSTR
psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
if( psa )
{
for(ul=0; ul<m_cScope; ul++)
{
rgIx[0] = ul;
BSTR bstrVal;
// Check to see if the catalog value has been cached, if not
//
if( m_rgCatalogOffset[ul] != UNUSED_OFFSET )
{
bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgCatalogOffset[ul]));
}
else
{
bstrVal = SysAllocString(pcwszCatalog);
}
if( bstrVal )
{
hr = SafeArrayPutElement(psa, rgIx, bstrVal);
SysFreeString(bstrVal);
if( FAILED(hr) )
goto error_delete;
}
else
{
hr = ResultFromScode(E_OUTOFMEMORY);
goto error_delete;
}
}
V_VT(pvValue) = VT_BSTR | VT_ARRAY;
V_ARRAY(pvValue) = psa;
psa = NULL;
}
else
return ResultFromScode(E_OUTOFMEMORY);
}
break;
case PTPROPS_MACHINE:
{
// Create a 1 dim safe array of type BSTR
psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
if( psa )
{
for(ul=0; ul<m_cScope; ul++)
{
rgIx[0] = ul;
BSTR bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgMachineOffset[ul]));
if( bstrVal )
{
hr = SafeArrayPutElement(psa, rgIx, bstrVal);
SysFreeString(bstrVal);
if( FAILED(hr) )
goto error_delete;
}
else
{
hr = ResultFromScode(E_OUTOFMEMORY);
goto error_delete;
}
}
V_VT(pvValue) = VT_BSTR | VT_ARRAY;
V_ARRAY(pvValue) = psa;
psa = NULL;
}
else
return ResultFromScode(E_OUTOFMEMORY);
}
break;
default:
return ResultFromScode(E_INVALIDARG);
break;
}
hr = S_OK;
error_delete:
if( psa )
SafeArrayDestroy(psa);
return hr;
}
// CScopeData::CacheData -----------------------------------------------------
//
// @mfunc Manages storing data values in our buffer
//
// @rdesc HRESULT | status of methods success / failure
// @flags S_OK | Data value stored at returned offset.
// @flags E_OUTOFMEMORY | Could not allocate resources.
//
HRESULT CScopeData::CacheData(
LPVOID pData,
ULONG cb,
ULONG* pulOffset
)
{
SCODE sc = S_OK;
TRY
{
assert( pData && pulOffset && cb > 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<cNewMaxScope; i++)
{
m_rgScopeOffset[i] = UNUSED_OFFSET;
m_rgCatalogOffset[i] = UNUSED_OFFSET;
m_rgMachineOffset[i] = UNUSED_OFFSET;
}
// Save new Max Elements.
m_cMaxScope = cNewMaxScope;
}
// Transfer Depth from previous node
if ( m_rgulDepths[m_cScope] & QUERY_DEEP )
m_rgulDepths[cCurScope] = QUERY_DEEP;
else
m_rgulDepths[cCurScope] = QUERY_SHALLOW;
// Transfer Machine and Catalog from previous node
m_rgCatalogOffset[cCurScope] = m_rgCatalogOffset[m_cScope];
m_rgMachineOffset[cCurScope] = m_rgMachineOffset[m_cScope];
// Set the current # of used scopes to our new node.
m_cScope = cCurScope;
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//============================================================================
//=
//= CImpIParserTreeProperties
//=
//============================================================================
// CImpIParserTreeProperties::CImpIParserTreeProperties ------------------------
//
// @mfunc Constructor
//
// @rdesc None
//
CImpIParserTreeProperties::CImpIParserTreeProperties()
{
// Reference count.
m_cRef = 1;
m_LastHR = S_OK;
m_iErrOrd = 0;
m_cErrParams = 0;
m_dbType = 0;
m_fDesc = QUERY_SORTASCEND;
m_pctContainsColumn = NULL;
m_pCScopeData = NULL;
m_pwszCatalog = NULL;
// initialize the CiRestriction data
m_rgwchCiColumn[0] = L' '; // First character to a <space>
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<WCHAR> 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; ul<m_cErrParams; ul++)
{
rgIx[0] = ul;
BSTR bstrVal = SysAllocString(m_pwszErrParams[ul]);
if( bstrVal )
{
hr = SafeArrayPutElement(psa, rgIx, bstrVal);
SysFreeString(bstrVal);
if( FAILED(hr) )
break;
}
else
{
hr = ResultFromScode(E_OUTOFMEMORY);
break;
}
}
if( SUCCEEDED(hr) )
V_ARRAY(vParseProp) = psa;
else
SafeArrayDestroy(psa);
}
}
break;
default:
return ResultFromScode(E_INVALIDARG);
break;
}
return S_OK;
}
// CImpIParserTreeProperties::QueryInterface ----------------------------------
//
// @mfunc Returns a pointer to a specified interface. Callers use
// QueryInterface to determine which interfaces the called object
// supports.
//
// @rdesc HResult indicating the status of the method
// @flag S_OK | Interface is supported and ppvObject is set.
// @flag E_NOINTERFACE | Interface is not supported by the object
// @flag E_INVALIDARG | One or more arguments are invalid.
//
STDMETHODIMP CImpIParserTreeProperties::QueryInterface
(
REFIID riid, //@parm IN | Interface ID of the interface being queried for.
LPVOID * ppv //@parm OUT | Pointer to interface that was instantiated
)
{
if( ppv == NULL )
return ResultFromScode(E_INVALIDARG);
if( (riid == IID_IUnknown) ||
(riid == IID_IParserTreeProperties) )
*ppv = (LPVOID)this;
else
*ppv = NULL;
// If we're going to return an interface, AddRef it first
if( *ppv )
{
((LPUNKNOWN)*ppv)->AddRef();
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 <space>
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 );
// 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;
}
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<CScopeData> 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();
}