windows-nt/Source/XPSP1/NT/ds/adsi/router/crsembed.cxx
2020-09-26 16:20:57 +08:00

665 lines
20 KiB
C++

//-----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: CRSEmbed.cxx
//
// Contents: IUnknown embedder for temptable.
//
// Functions:
//
// Notes:
//
//
// History: 08/30/96 | RenatoB | Created
//----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// @class CRowsetInfo | embedding of Rowset,
// to give our IrowsetInfo interface
//
//
//-----------------------------------------------------------------------------
// Includes
#include "oleds.hxx"
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::QueryInterface
//
// Synopsis: @mfunc QueryInterface.
// IUknown implementation.
// IID_IUnknown and IID_IRowsetInfo are not delegated
// All other IID's are delegated to _pRowset
//
//-----------------------------------------------------------------------.
HRESULT
CRowsetInfo::QueryInterface(
REFIID riid,
LPVOID *ppv
)
{
HRESULT hr;
if (ppv == NULL)
RRETURN(E_INVALIDARG);
*ppv = NULL;
if (riid == IID_IUnknown) {
*ppv = (IRowsetInfo FAR *) this;
AddRef();
}
if (riid == IID_IRowsetInfo) {
*ppv = (IRowsetInfo FAR *) this;
AddRef();
}
//delegate all the rest to the TempTable Rowset
if (_pRowset == NULL)
RRETURN(E_UNEXPECTED);
hr=((LPUNKNOWN)_pRowset)->QueryInterface(riid, ppv);
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::CRowsetInfo
//
// Synopsis: @mfunc Ctor
//
// Arguments:
//
//
// Returns: @rdesc NONE
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
CRowsetInfo::CRowsetInfo(
IUnknown *pUnkOuter, // controlling unknown)
IUnknown *pParentObject, // RowProvider
CSessionObject *pCSession, // Session that created rowset
CCommandObject *pCCommand // Command object that created rowset
)
{
_pUnkOuter= (pUnkOuter == NULL) ? this : pUnkOuter;
_pRowset = NULL;
_pParentObject = pParentObject;
_pCSession= pCSession;
_pCCommand = pCCommand;
_pMalloc = NULL;
_dwStatus = 0;
_cPropertySets = 0;
_pPropertySets = NULL;
if (_pCCommand !=NULL)
_pCCommand->IncrementOpenRowsets();
//this section is for IRowsetInfo and IUnknown methods.
InitializeCriticalSection(&_csRowsetInfo);
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::~CRowsetInfo
//
// Synopsis: @mfunc Dtor
//
// Arguments:
//
//
// Returns: @rdesc NONE
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
CRowsetInfo::~CRowsetInfo()
{
// release _pPropertySets
FreePropertySets(_cPropertySets, _pPropertySets);
if (_pMalloc!= NULL) _pMalloc->Release();
if (_pCCommand !=NULL) {
_pCCommand->DecrementOpenRowsets();
_pCCommand->Release();
_pCCommand = NULL;
}
if (_pCSession != NULL) {
_pCSession->Release();
_pCSession = NULL;
}
if (_pParentObject != NULL){
_pParentObject->Release();
_pParentObject=NULL;
}
if (_pRowset != NULL){
((LPUNKNOWN)_pRowset)->Release();
_pRowset=NULL;
}
if ( _pCRowsetInfo!= NULL) {
delete _pCRowsetInfo;
_pCRowsetInfo = NULL;
}
DeleteCriticalSection(&_csRowsetInfo);
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::FInit
//
// Synopsis: @mfunc Initializer
//
// Called by: CreateTempTable
// Called when: After calling pIServiceProvider->ProvideService
// Synopsis: @mfunc Initializer
//
// Arguments:
//
//
// Returns: @rdesc NONE
// @flag S_OK | Interface is supported
// @flag E_OUTOFMEMORY | Interface is not supported by the TempTable
// @flag E_INVALIDARG | One or more arguments are invalid.
//
// Modifies:
//
// History: 08/30/96 RenatoB Created
//
//----------------------------------------------------------------------------
HRESULT
CRowsetInfo::FInit(
IUnknown *pRowset) // TmpTable interface
{
HRESULT hr;
hr = S_OK;
_pRowset = pRowset;
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetReferencedRowset
//
// Synopsis: @mfunc Returns an interface pointer to the rowset to which a bookmark applies
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// iOrdinal [in] Bookmark column for which to get related rowset. Must be 0 in this impl.
// riid [in] IID of the interface pointer to return in *ppReferencedRowset.
// ppReferencedRowset[out] pointer to Rowset object referenced by Bookmark
//
//
// Returns: @rdesc NONE
// S_OK | Interface is supported
// E_INVALIDARG | ppReferencedRowset was a NULL pointer
// E_FAIL | provider specific error
// E_NOINTERFACE | Rowset does not support interface
// DB_E_NOTAREFENCEDCOLUMN | iOrdinal was not 0
//
//----------------------------------------------------------------------------
HRESULT
CRowsetInfo::GetReferencedRowset(
DBORDINAL iOrdinal,
REFIID riid,
IUnknown** ppReferencedRowset
)
{
CAutoBlock(&(_csRowsetInfo));
if (ppReferencedRowset == NULL)
RRETURN(E_INVALIDARG);
if (iOrdinal != 0)
RRETURN(DB_E_BADORDINAL);
RRETURN(QueryInterface(
riid,
(void**)ppReferencedRowset)
);
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetSpecificaton
//
// Synopsis: @mfunc Returns an interface pointer to the command that created the rowset
//
// Called by: Client
// Called when: Any time
//
// Arguments:
// riid [in] IID of the interface pointer to return in *ppSpecification.
// ppSpecification [out] pointer to command
//
//
// Returns: @rdesc NONE
// S_OK | Interface is supported
// E_INVALIDARG | ppSpecification was a NULL pointer
// E_FAIL | provider specific error
// E_NOINTERFACE | Command does not support interface
// S_FALSE | Rowset does not have command that created it
//----------------------------------------------------------------------------
HRESULT
CRowsetInfo::GetSpecification(
REFIID riid,
IUnknown** ppSpecification
)
{
CAutoBlock(&(_csRowsetInfo));
if (ppSpecification == NULL)
RRETURN(E_INVALIDARG);
if ( _pParentObject == NULL)
RRETURN(S_FALSE);
RRETURN(_pParentObject->QueryInterface(riid, (void**)ppSpecification));
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::GetProperties
//
// Synopsis: @mfunc GetProperties
// Overloads the TempTable's IRowsetInfo::GetProperties.
// The first time this function is called, it calls the
// TmpTable IRowsetInfo::GetProperties with cPropertyIdSets == 0
//
// Called by: Client.
// Called when: Any time.
//
// Arguments:
// cPropertyIDSets[in] The number of DBPROPIDSET structures in rgProperttySets
// rgPropertyIDSets[in] Array of cPropertyIDSets of DBPROIDSET structs.
// pcPropertySets[out] number of DBPROPSET returned in *prgPropertySets
// prgPropertySets[out] pointer to array of DBPROPSET structures, having the
// value and status of requested properties
//
// Returns: @rdesc HRESULT
// S_OK Success
// DB_S_ERRORSOCCURRED Values were not supported for some properties
// E_FAIL A provider-specific error occurred
// E_INVALIDARG cPropertyIDSets > 0 and rgPropertyIdSEts = NULL
// pcPropertySets or prgPropertySets was NULL pointer
// In al element of rgPropertyIDSets, cPropertyIDs was not zero
// and rgPropertyIDs was a Null pointer
// E_OUTOFMEMORY Provider could not allocate memory
// DB_E_ERRORSOCCURRED Values were not returned for any properties
//-----------------------------------------------------------------------.
HRESULT
CRowsetInfo::GetProperties(
const ULONG cPropertyIDSets,
const DBPROPIDSET rgPropertyIDSets[],
ULONG* pcPropertySets,
DBPROPSET** prgPropertySets
)
{
CAutoBlock(&(_csRowsetInfo));
// mplPropertyIDsets maps the position of a property set in rgPropertyIDSets[]
// within _pPropertySets. It has (-1) if not mappable
LONG mplPropertyIDSets[50];
// mplPropertySets maps the position of a property within its corresponding
// rgProperties in _pPropertySets. It has (-1) if not mappable.
LONG position;
HRESULT hr = S_OK;
ULONG i;
ULONG j;
ULONG ibPropertyIDsets;
ULONG ibPropertySets;
BOOL bPartialSuccess = FALSE;
BOOL bErrorsOccurred = FALSE;
//validate arguments
if ( ((cPropertyIDSets > 0) && ( rgPropertyIDSets == NULL)) ||
(pcPropertySets == NULL) ||
(prgPropertySets == NULL) )
RRETURN(E_INVALIDARG);
for (i = 0; i< cPropertyIDSets; i++) {
if ((rgPropertyIDSets[i].cPropertyIDs > 0) &&
(rgPropertyIDSets[i].rgPropertyIDs ==NULL))
RRETURN(E_INVALIDARG);
}
//Initializate, if needed
if (_dwStatus == 0) InitProperties();
if (_dwStatus & STAT_INITERROR) //initialization was unsuccessful
RRETURN(E_FAIL);
// If CPropertyIDSets == 0, just copy
*pcPropertySets = 0;
*prgPropertySets = NULL;
//case when cPropertyIDSets == 0
if (cPropertyIDSets == 0) {
//allocate memory for the property sets
*prgPropertySets = (DBPROPSET*) _pMalloc->Alloc(
_cPropertySets*sizeof(DBPROPSET)
);
if (*prgPropertySets == NULL) {
hr = E_OUTOFMEMORY;
goto error;
};
*pcPropertySets = _cPropertySets;
// copy the array of property sets and make rgProperties equal to NULL
memcpy(
(void*) *prgPropertySets,
(void*) _pPropertySets,
_cPropertySets*sizeof(DBPROPSET)
);
for (i = 0; i< _cPropertySets; i++)
(*prgPropertySets)[i].rgProperties = NULL;
// make copies of each of the rgProperties contained in _pPropertySets
for (i = 0; i< _cPropertySets ; i++) {
(*prgPropertySets)[i].rgProperties=
(DBPROP*)_pMalloc->Alloc(
_pPropertySets[i].cProperties*sizeof(DBPROP)
);
if ((*prgPropertySets)[i].rgProperties == NULL) {
hr = E_OUTOFMEMORY;
goto error;
};
memcpy(
(void*)((*prgPropertySets)[i].rgProperties),
(void*) (_pPropertySets[i].rgProperties),
_pPropertySets[i].cProperties*sizeof(DBPROP)
);
};
RRETURN(S_OK);
};
// This is the case when cPropertyIDSets != 0
// First, allocate memory
*prgPropertySets = (DBPROPSET*) _pMalloc->Alloc(
cPropertyIDSets*sizeof(DBPROPSET)
);
if (*prgPropertySets == NULL) {
hr = E_OUTOFMEMORY;
goto error;
};
memset((void*)*prgPropertySets, 0, sizeof(DBPROPSET)*cPropertyIDSets );
*pcPropertySets= cPropertyIDSets;
memset(mplPropertyIDSets, 0, sizeof(LONG)*cPropertyIDSets );
for (i=0; i<cPropertyIDSets; i++) {
(*prgPropertySets)[i].guidPropertySet =
rgPropertyIDSets[i].guidPropertySet;
mplPropertyIDSets[i] = SearchGuid(
rgPropertyIDSets[i].guidPropertySet
);
if (mplPropertyIDSets[i] < 0) {
bErrorsOccurred = TRUE;
(*prgPropertySets)[i].cProperties = 0;
(*prgPropertySets)[i].rgProperties = NULL;
(*prgPropertySets)[i].guidPropertySet =
rgPropertyIDSets[i].guidPropertySet;
}
else {
//The PropertySet is supported. Remember its position in ibPropertyIDsets
ibPropertyIDsets = mplPropertyIDSets[i];
//We write the property-set's GUID
(*prgPropertySets)[i].guidPropertySet =
rgPropertyIDSets[i].guidPropertySet;
if (rgPropertyIDSets[i].cPropertyIDs == 0) {
//the client is asking for all properties
bPartialSuccess = TRUE;
(*prgPropertySets)[i].rgProperties=
(DBPROP*)_pMalloc->Alloc(
_pPropertySets[ibPropertyIDsets].cProperties*sizeof(DBPROP)
);
if ((*prgPropertySets)[i].rgProperties == NULL) {
hr = E_OUTOFMEMORY;
goto error;
};
(*prgPropertySets)[i].cProperties=
_pPropertySets[ibPropertyIDsets].cProperties;
memcpy(
(void*) ((*prgPropertySets)[i].rgProperties),
(void*) _pPropertySets[ibPropertyIDsets].rgProperties,
_pPropertySets[ibPropertyIDsets].cProperties*sizeof(DBPROP)
);
}
else {
//the client asks for some properties only. Alloc and clear memory
(*prgPropertySets)[i].rgProperties=
(DBPROP*)_pMalloc->Alloc(rgPropertyIDSets[i].cPropertyIDs
*sizeof(DBPROP));
if ((*prgPropertySets)[i].rgProperties == NULL) {
hr = E_OUTOFMEMORY;
goto error;
};
(*prgPropertySets)[i].cProperties =
rgPropertyIDSets[i].cPropertyIDs;
memset(
((*prgPropertySets)[i].rgProperties),
0,
rgPropertyIDSets[i].cPropertyIDs*sizeof(DBPROP)
);
//iterate and set values
for (j=0; j <rgPropertyIDSets[i].cPropertyIDs; j++) {
position =
SearchPropid(
ibPropertyIDsets,
rgPropertyIDSets[i].rgPropertyIDs[j]
);
if (position < 0) {
//could not find a property
bErrorsOccurred = TRUE;
(*prgPropertySets)[i].rgProperties[j].dwPropertyID =
rgPropertyIDSets[i].rgPropertyIDs[j];
(*prgPropertySets)[i].rgProperties[j].dwStatus =
DBPROPSTATUS_NOTSUPPORTED;
}
else {
bPartialSuccess= TRUE;
ibPropertySets = position;
memcpy(
(void*)&((*prgPropertySets)[i].rgProperties[j] ),
(void*)&(_pPropertySets[ibPropertyIDsets].
rgProperties[ibPropertySets]),
sizeof(DBPROP));
}
}
}
}
}
if ((bPartialSuccess == TRUE) && (bErrorsOccurred == FALSE))
RRETURN(S_OK);
if (bPartialSuccess == TRUE)
RRETURN(DB_S_ERRORSOCCURRED);
hr = DB_E_ERRORSOCCURRED;
goto error;
error:
FreePropertySets( *pcPropertySets, *prgPropertySets);
*pcPropertySets = NULL;
*prgPropertySets = NULL;
RRETURN(hr);
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::FreePropertySets
//
// Synopsis: @mfunc releases the memory of property sets
//
// Arguments:
// cPropertySets [in] number of property sets to be freed
// rgPropertySets [in/out] array with the property sets to be released
// Called by: Provider
// Called when: By the destructor, or for method that needs cleanup
// of property sets
//----------------------------------------------------------------------------
void
CRowsetInfo::FreePropertySets(
ULONG cPropertySets,
DBPROPSET *rgPropertySets
)
{
ULONG i;
if ((cPropertySets > 0) && (rgPropertySets == NULL)) {
return;
}
if (cPropertySets == 0) return;
if (_pMalloc == NULL) {
return;
}
//Free the individual arrays of properties
for (i=0; i< cPropertySets; i++) {
if ((rgPropertySets[i].cProperties > 0) &&
(rgPropertySets[i].rgProperties != NULL))
_pMalloc->Free(rgPropertySets[i].rgProperties);
};
//Free the array of propertysets
_pMalloc->Free(rgPropertySets);
}
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::InitProperties
//
// Synopsis: @mfunc initilizes _cPropertySets and _pPropertySets from
// _pRowset
//
//----------------------------------------------------------------------------
HRESULT CRowsetInfo::InitProperties(void)
{
HRESULT hr;
IRowsetInfo* pRowsetInfo = NULL;
hr = CoGetMalloc(MEMCTX_TASK, &_pMalloc);
if (FAILED(hr)) {
goto error;
}
if (_pRowset == NULL) {
hr = E_FAIL;
goto error;
};
hr = _pRowset->QueryInterface(IID_IRowsetInfo, (void**) &pRowsetInfo);
if (FAILED (hr)) {
goto error;
};
hr= pRowsetInfo->GetProperties(0, NULL, &_cPropertySets, &_pPropertySets);
if (FAILED(hr)) {
goto error;
}
_dwStatus =STAT_DIDINIT;
pRowsetInfo->Release();
RRETURN(S_OK);
error:
_dwStatus = STAT_INITERROR;
if (_pMalloc != NULL) {
_pMalloc->Release();
_pMalloc = NULL;
}
if (pRowsetInfo != NULL)
pRowsetInfo->Release();
;
RRETURN(hr);
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::SearchGuid
//
// Synopsis: @mfunc
//
// Arguments: riid [in] GUID to be searched for
//
// Returns:
// The position of the GUID withing _pPropertySets. Returns -1
// if not found
//
//----------------------------------------------------------------------------
LONG CRowsetInfo::SearchGuid(GUID riid)
{
ULONG i;
for (i = 0; i < _cPropertySets; i++) {
if (_pPropertySets[i].guidPropertySet == riid) return (i);
};
return -1;
};
//+---------------------------------------------------------------------------
//
// Function: CRowsetInfo::SearchPropid
//
// Synopsis: @mfunc Searchs for a Propid within _PropertySets
//
// Arguments:
// ibPropertySet [in] The index, within _pPropertySets,
// of the DBPROPSET to be searched
// dwPropertyID [in] The propid to be searched
// Returns:
// The position of the DBPROP with propid=dwPropertyID
// within _pPropertySets[ibPropertySet]. Returns -1
// if not found
//
//----------------------------------------------------------------------------
LONG CRowsetInfo::SearchPropid(
ULONG ibPropertySet,
DWORD dwPropertyID)
{
ULONG i;
for (i = 0; i < _pPropertySets[ibPropertySet].cProperties; i++) {
if (_pPropertySets[ibPropertySet].rgProperties[i].dwPropertyID ==dwPropertyID )
return (i);
};
return -1;
};