mirror of https://github.com/tongzx/nt5src
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.
991 lines
27 KiB
991 lines
27 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, CALC_CCH_MINUS_NULL(L"."));
|
|
}
|
|
|
|
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_SHALLOW )
|
|
m_rgulDepths[cCurScope] = QUERY_SHALLOW;
|
|
else
|
|
m_rgulDepths[cCurScope] = QUERY_DEEP;
|
|
|
|
// 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 );
|
|
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<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();
|
|
}
|