windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/oledb/cmdtext.cpp
2020-09-26 16:20:57 +08:00

867 lines
30 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Microsoft WMI OLE DB Provider
//
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// Module : CMDTEXT.CPP - ICommandText interface implementation
// Also has implementation of CUtlParam class
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "command.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpICommandText::AddRef(void)
{
DEBUGCODE(InterlockedIncrement( (long*) &m_cRef));
return m_pcmd->GetOuterUnknown()->AddRef();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpICommandText::Release(void)
{
DEBUGCODE(long lRef = InterlockedDecrement((long*)&m_cRef));
DEBUGCODE(if( lRef < 0 ){
ASSERT("Reference count on Object went below 0!")
})
return m_pcmd->GetOuterUnknown()->Release();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::QueryInterface( REFIID riid, LPVOID * ppv )
{
return m_pcmd->GetOuterUnknown()->QueryInterface(riid, ppv);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Echos the current command as text, including all post-processing operations added.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::GetCommandText( GUID* pguidDialect, LPOLESTR* ppwszCommand )
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
//===============================================================================
// At the creation of the CAutoBlock object a critical section
// is entered. This is because the method manipulates shared structures
// access to which must be serialized . The critical
// section is left when this method terminate and the destructor
// for CAutoBlock is called.
//===============================================================================
CAutoBlock cab( m_pcmd->GetCriticalSection() );
//===============================================================================
// Clear previous Error Object for this thread
//===============================================================================
g_pCError->ClearErrorInfo();
//===============================================================================
// Check Function Arguments
//===============================================================================
if ( ppwszCommand == NULL ){
hr = E_INVALIDARG;
}
else
//===============================================================================
// If the command has not been set, make sure the buffer
// contains an empty stringt to return to the consumer
//===============================================================================
if(!(m_pcmd->m_pQuery->GetStatus() & CMD_TEXT_SET)){
hr = DB_E_NOCOMMAND;
}
else
{
//===============================================================================
// Copy our saved text into the newly allocated string
//===============================================================================
m_pcmd->m_pQuery->GetQuery(*ppwszCommand);
//===============================================================================
// If the text we're giving back is a different dialect than was
// requested, let the caller know what dialect the text is in
//===============================================================================
if (pguidDialect && *pguidDialect != DBGUID_DEFAULT && *pguidDialect!= DBGUID_WQL &&
*pguidDialect != DBGUID_LDAP && *pguidDialect != GUID_NULL && *pguidDialect != DBGUID_WMI_METHOD
&& *pguidDialect != DBGUID_LDAPSQL){
hr = DB_S_DIALECTIGNORED;
}
}
if ( FAILED(hr) ){
if ( pguidDialect )
{
memset(pguidDialect, 0, sizeof(GUID));
}
}
else
{
if(pguidDialect)
{
GUID guidTemp = m_pcmd->m_pQuery->GetDialectGuid();
memcpy(pguidDialect, &guidTemp,sizeof(GUID));
}
}
hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
CATCH_BLOCK_HRESULT(hr,L"ICommandText::GetCommandText");
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Sets the current command text
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::SetCommandText( REFGUID rguidDialect, LPCOLESTR pwszCommand )
{
HRESULT hr = S_OK;
VARIANT varQryLang;
VariantInit(&varQryLang);
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
//=========================================================================
// At the creation of the CAutoBlock object a critical section
// is entered. This is because the method manipulates shared structures
// access to which must be serialized . The critical
// section is left when this method terminate and the destructor
// for CAutoBlock is called.
//=========================================================================
CAutoBlock cab( m_pcmd->GetCriticalSection() );
//=========================================================================
// Clear previous Error Object for this thread
//=========================================================================
g_pCError->ClearErrorInfo();
//=========================================================================
// Don't allow text to be set if we've got a rowset open
//=========================================================================
if ( m_pcmd->IsRowsetOpen() ){
return g_pCError->PostHResult((DB_E_OBJECTOPEN), &IID_ICommandText);
}
//=========================================================================
// Check Dialect
//=========================================================================
if (rguidDialect != DBGUID_WQL && rguidDialect != DBGUID_DEFAULT &&
rguidDialect != DBGUID_LDAP && rguidDialect != DBGUID_WMI_METHOD &&
rguidDialect != DBGUID_LDAPSQL){
return g_pCError->PostHResult((DB_E_DIALECTNOTSUPPORTED), &IID_ICommandText);
}
if(rguidDialect == DBGUID_WMI_METHOD)
{
m_pcmd->m_pQuery->SetType(METHOD_ROWSET);
}
//=========================================================================
// Unprepare if we've already got something prepared
//=========================================================================
m_pcmd->UnprepareHelper(UNPREPARE_NEW_CMD);
// NTRaid 134165
if(SUCCEEDED(hr = m_pcmd->GetQueryLanguage(varQryLang)))
{
//=========================================================================
// Delete the old text
//=========================================================================
if(SUCCEEDED(hr = m_pcmd->m_pQuery->InitQuery(varQryLang.bstrVal)))
{
//=========================================================================
// Save the new text
//=========================================================================
if (pwszCommand && *pwszCommand){
hr = m_pcmd->m_pQuery->SetQuery(pwszCommand,rguidDialect);
}
else{
//=========================================================================
// There is no text
//=========================================================================
hr = m_pcmd->m_pQuery->SetDefaultQuery();
}
}
}
if(SUCCEEDED(hr))
{
// If everything is fine then set the datasource persist info to dirty
m_pcmd->m_pCDBSession->m_pCDataSource->SetPersistDirty();
// Clear the column information
SAFE_DELETE_PTR(m_pcmd->m_pColumns);
m_pcmd->m_cTotalCols = 0;
m_pcmd->m_cCols = 0;
m_pcmd->m_cNestedCols = 0;
}
VariantClear(&varQryLang);
hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
CATCH_BLOCK_HRESULT(hr,L"ICommandText::SetCommandText");
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Return an interface from the session object that created this command object
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::GetDBSession( REFIID riid, IUnknown** ppSession)
{
HRESULT hr;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
//=========================================================================
// At the creation of the CAutoBlock object a critical section
// is entered. This is because the method manipulates shared structures
// access to which must be serialized . The critical
// section is left when this method terminate and the destructor
// for CAutoBlock is called.
//=========================================================================
CAutoBlock cab( m_pcmd->GetCriticalSection() );
//=========================================================================
// Clear previous Error Object for this thread
//=========================================================================
g_pCError->ClearErrorInfo();
//=========================================================================
// Check Arguments
//=========================================================================
if (ppSession == NULL){
return g_pCError->PostHResult((E_INVALIDARG), &IID_ICommandText);
}
//=========================================================================
// Initialize output param
//=========================================================================
*ppSession = NULL;
//=========================================================================
// Query for the interface on the session object. If failure,
// return the error from QueryInterface.
//=========================================================================
hr = (m_pcmd->m_pCDBSession->GetOuterUnknown())->QueryInterface(riid, (VOID**)ppSession);
hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
CATCH_BLOCK_HRESULT(hr,L"ICommandText::GetSession");
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// The consumer can allocate a secondary thread in which to cancel
// the currently executing thread. This cancel will only succeed if
// the result set is still being generated. If the rowset object is being
// created, then it will be to late to cancel.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::Cancel(void)
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
TRY_BLOCK;
//=========================================================================
// Clear previous Error Object for this thread
//=========================================================================
g_pCError->ClearErrorInfo();
m_pcmd->m_pQuery->m_pcsQuery->Enter();
if (m_pcmd->m_pQuery){
HRESULT retcode = m_pcmd->m_pQuery->CancelQuery();
if( S_OK == retcode){
m_pcmd->m_pQuery->InitQuery(); // ?
}
else{
hr = DB_E_CANTCANCEL;
}
m_pcmd->m_pQuery->SetCancelStatus(CMD_EXEC_CANCELED);
}
else{
m_pcmd->m_pQuery->SetCancelStatus(CMD_EXEC_CANCELED | CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
}
m_pcmd->m_pQuery->m_pcsQuery->Leave();
hr = hr != S_OK ? g_pCError->PostHResult(hr, &IID_ICommandText): hr;
CATCH_BLOCK_HRESULT(hr,L"ICommandText::Cancel");
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Execute the command.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpICommandText::Execute( IUnknown* pUnkOuter,
REFIID riid, //@parm IN | Interface ID of the interface being queried for.
DBPARAMS* pParams, //@parm INOUT | Parameter Array
DBROWCOUNT* pcRowsAffected, //@parm OUT | count of rows affected by command
IUnknown** ppRowsets //@parm OUT | Pointer to interface that was instantiated
)
{
HRESULT hr = S_OK;
CSetStructuredExceptionHandler seh;
VARIANT varQryLang;
VariantInit(&varQryLang);
TRY_BLOCK;
//=========================================================================
// At the creation of the CAutoBlock object a critical section is entered.
// This is because the method manipulates shared structures access to which
// must be serialized . The critical section is left when this method
// terminate and the destructor for CAutoBlock is called.
//=========================================================================
CAutoBlock cab( m_pcmd->GetCriticalSection() );
m_pcmd->m_pQuery->m_pcsQuery->Enter();
if (m_pcmd->m_pQuery->GetCancelStatus() & CMD_EXEC_CANCELED_BEFORE_CQUERY_SET){
m_pcmd->m_pQuery->ClearCancelStatus(CMD_EXEC_CANCELED | CMD_EXEC_CANCELED_BEFORE_CQUERY_SET);
}
if (m_pcmd->m_pQuery->GetStatus() & CMD_EXECUTED_ONCE){
m_pcmd->m_pQuery->ClearStatus(CMD_EXECUTED_ONCE);
}
// get the QueryLanguage Property and set it on the
// query object
// NTRaid 134165
if(SUCCEEDED(hr = m_pcmd->GetQueryLanguage(varQryLang)))
{
hr = m_pcmd->m_pQuery->SetQueryLanguage(varQryLang.bstrVal);
}
m_pcmd->m_pQuery->m_pcsQuery->Leave();
//=========================================================================
// Clear previous Error Object for this thread
//=========================================================================
g_pCError->ClearErrorInfo();
if(SUCCEEDED(hr))
{
//=========================================================================
// Execute the command
//=========================================================================
hr = m_pcmd->Execute(pUnkOuter, riid, pParams, pcRowsAffected, ppRowsets);
}
VariantClear(&varQryLang);
CATCH_BLOCK_HRESULT(hr,L"ICommandText::Execute");
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//*********************************************************************************************************
//
// CUtlParam class
//
//*********************************************************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This routine builds the binding information needed to execute a command with parameters
//
// HRESULT indicating status
// S_OK | No problem processing parameter or statement
// E_FAIL | Provider specific error
// E_OUTOFMEMORY | Not enough resources
// E_UNEXPECTED | Zombie State
// DB_E_BADACCESSORHANDLE | Accessor handle invalid
// DB_E_BADACCESSORTYPE | Non-Parameter Accessor used
// DB_E_BADPARAMETER | Parameter information not correct
// DB_E_BADPARAMETERCOUNT | Bad Parameter Count
// DB_E_DUPLICATEPARAM | Same parameter used twice
///////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CUtlParam::BuildBindInfo( CCommand *pcmd, DBPARAMS *pParams, const IID* piid)
{
HRESULT hr = S_OK;
// NTRaid::111812
// 06/07/00
PACCESSOR pAccessor = NULL;
DBORDINAL iBind;
DBCOUNTITEM iParamSet;
DBBINDING *pBind;
// DBTYPE wType;
ULONG cErrors = 0;
DBORDINAL iParam;
BYTE *pbData;
ULONG cBindInfo;
ULONG iDupBind;
WMIBINDINFO *pBindInfo;
BOOL fDeriveParamsFromSql = FALSE;
//==========================================================
// Copy DBPARAMS struct (C++ bitwise copy)
//==========================================================
m_dbparams = *pParams;
//==========================================================
// Add an extra reference count to the user's accessor,
// since we're now holding a pointer to it in m_dbparams
//==========================================================
m_pIAccessor = pcmd->GetIAccessorPtr();
m_pIAccessor->AddRefAccessor(m_dbparams.hAccessor, NULL);
//==========================================================
// Obtain pointer to the accessor that the user passed to us
//==========================================================
m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer(pParams->hAccessor, &pAccessor);
m_cbRowSize = 999;
//==========================================================
// Make sure at least one binding for each parameter
//==========================================================
m_cParams = pcmd->GetParamCount();
if (pAccessor->cBindings < m_cParams){
hr = DB_E_PARAMNOTOPTIONAL;
}
else
{
//==========================================================
// Allocate mem ory for binding information
//==========================================================
iDupBind = m_cParams;
cBindInfo = max(m_cParams, pAccessor->cBindings);
m_prgBindInfo = new WMIBINDINFO[cBindInfo];
if (NULL == m_prgBindInfo){
hr = E_OUTOFMEMORY;
}
else
{
memset(m_prgBindInfo, 0, sizeof(WMIBINDINFO)*cBindInfo);
//==========================================================
// Process each binding of the given accessor
//==========================================================
for (iBind = 0; iBind < pAccessor->cBindings; iBind++){
//======================================================
// Get the pointer to the binding of interest
//======================================================
pBind = pAccessor->rgBindings + iBind;
//======================================================
// Make sure this binding's ordinal is valid
//======================================================
if (!pBind->iOrdinal || pBind->iOrdinal > m_cParams){
//==================================================
// This is a bad accessor; set status if bound
//==================================================
SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
//==================================================
// Count this error and look for more
//==================================================
cErrors++;
continue;
}
iParam = pBind->iOrdinal - 1;
//======================================================
// Save the binding
//======================================================
if (NULL == m_prgBindInfo[iParam].pBinding){
m_prgBindInfo[iParam].pBinding = pBind;
if (pBind->eParamIO & DBPARAMIO_OUTPUT)
m_prgBindInfo[iParam].wFlags |= DBPARAMIO_OUTPUT;
if (pBind->eParamIO & DBPARAMIO_INPUT)
m_prgBindInfo[iParam].wFlags |= DBPARAMIO_INPUT;
}
else {
//==================================================
// Multiple bindings for this parameter
//==================================================
pBindInfo = m_prgBindInfo + iDupBind++;
pBindInfo->pBinding = pBind;
pBindInfo->pNextBindInfo =
m_prgBindInfo[iParam].pNextBindInfo;
m_prgBindInfo[iParam].pNextBindInfo = pBindInfo;
if (pBind->eParamIO & DBPARAMIO_OUTPUT)
m_prgBindInfo[iParam].wFlags |= DBPARAMIO_OUTPUT;
if (pBind->eParamIO & DBPARAMIO_INPUT){
if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT){
//==========================================
// A bad accessor; set status if bound
//==========================================
SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
//==========================================
// Count this error and look for more
//==========================================
cErrors++;
continue;
}
m_prgBindInfo[iParam].wFlags |= DBPARAMIO_INPUT;
}
}
//======================================================
// Get the parameter type from the accessor
//======================================================
switch (pBind->eParamIO){
case DBPARAMIO_INPUT:
case DBPARAMIO_OUTPUT:
case DBPARAMIO_INPUT|DBPARAMIO_OUTPUT:
break;
case DBPARAMIO_NOTPARAM:
default:
// This is a bad accessor; set status if bound
SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
// Count this error and look for more
cErrors++;
continue;
}
for (pbData = (BYTE*)m_dbparams.pData, iParamSet = 0;iParamSet < m_dbparams.cParamSets;pbData += m_cbRowSize, iParamSet++ ){
//=========================================================================
// If this is not an output param and we aren't given a value
// or a DBSTATUS_S_ISNULL, that's an error
//=========================================================================
BOOL fOutput = m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT;
if ((!fOutput ) && !(pBind->dwPart & DBPART_VALUE) && (!(pBind->dwPart & DBPART_STATUS)
|| *(DBSTATUS *)((BYTE *)pbData + pBind->obStatus) != DBSTATUS_S_ISNULL) ) {
// This is a bad accessor; set status if bound
if (pBind->dwPart & DBPART_STATUS){
*(DBSTATUS *)(pbData + pBind->obStatus) =DBSTATUS_E_BADACCESSOR;
}
// Count this error and look for more
cErrors++;
break;
}
if ((pBind->dwPart & DBPART_STATUS) && DBSTATUS_S_DEFAULT == *(DBSTATUS*)((BYTE*)pbData + pBind->obStatus)) {
m_dwStatus |= CUTLPARAM_DEFAULT_PARAMS;
}
}
} // end of outer for loop
// Any errors in processing bindings?
if (cErrors){
hr = DB_E_ERRORSOCCURRED;
}
else
if (SUCCEEDED(hr = BuildParamInfo(pcmd, piid)))
{
for (iParam = 0; iParam < m_cParams; iParam++){
if ((m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT) && !((m_prgBindInfo[iParam].pParamInfo->dwFlags & DBPARAMFLAGS_ISINPUT))
|| ((m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT) && !(m_prgBindInfo[iParam].pParamInfo->dwFlags & DBPARAMFLAGS_ISOUTPUT))){
// This is a bad accessor; set status if bound
SetStatus(pBind, DBSTATUS_E_BADACCESSOR);
for (pBindInfo = m_prgBindInfo[iParam].pNextBindInfo; pBindInfo; pBindInfo = pBindInfo->pNextBindInfo)
SetStatus(pBindInfo->pBinding, DBSTATUS_E_BADACCESSOR);
// Count this error and look for more
cErrors++;
}
}
if (cErrors)
{
hr = DB_E_ERRORSOCCURRED;
}
}
} // if memory is allocated properly
} // else for checking for DB_E_PARAMNOTOPTIONAL error
hr = hr != S_OK ? g_pCError->PostHResult(hr, piid): hr;
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This routine builds the parameter information for the command from the binding information.
//
// HRESULT indicating status
// S_OK | No problem processing parameter or statement
// E_FAIL | Provider specific error
// E_OUTOFMEMORY | Not enough resources
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CUtlParam::BuildParamInfo( CCommand *pcmd, const IID* piid )
{
HRESULT hr = S_OK;
ULONG iParam(0);
PPARAMINFO pParamInfo;
DBBINDING *pBind;
BYTE* pbData = NULL;
DWORD* pdwLength;
DWORD dwLength(0);
DBSTATUS* pdwStatus;
DBSTATUS dwStatus(0);
DBLENGTH cbMaxLen(0);
VARIANT varValue;
VariantInit(&varValue);
m_rgpParamInfo = new PPARAMINFO[m_cParams];
if (NULL == m_rgpParamInfo)
{
hr = E_OUTOFMEMORY;
}
else
{
memset(m_rgpParamInfo, 0, sizeof(PPARAMINFO)*m_cParams);
for (iParam = 0; iParam < m_cParams; iParam++){
VariantClear(&varValue);
pParamInfo = pcmd->GetParamInfo(iParam);
if (pParamInfo){
m_rgpParamInfo[m_cParamInfo++] = pParamInfo;
pParamInfo->dwFlags = DBPARAMFLAGS_ISNULLABLE;
if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_INPUT)
pParamInfo->dwFlags |= DBPARAMFLAGS_ISINPUT;
if (m_prgBindInfo[iParam].wFlags & DBPARAMIO_OUTPUT)
pParamInfo->dwFlags |= DBPARAMFLAGS_ISOUTPUT;
//=========================================================
// Bind the parameter
//=========================================================
pBind = GetBinding(m_prgBindInfo+iParam);
if( pBind ){
BindParamData(1, iParam+1, pBind, &pParamInfo->pbData, &pdwLength, (ULONG*)&pParamInfo->cbColLength, &pdwStatus, &dwStatus, &(pParamInfo->wOLEDBType));
//=========================================================
// Get the data type for variant params
//=========================================================
if (pParamInfo->wOLEDBType == DBTYPE_VARIANT && pParamInfo->pbData != NULL)
pParamInfo->wOLEDBType = V_VT((VARIANT *)pParamInfo->pbData);
// For variable length params, find the max len
cbMaxLen = 0;
if (DBTYPE_STR == pParamInfo->wOLEDBType || DBTYPE_WSTR == pParamInfo->wOLEDBType
|| DBTYPE_BSTR == pParamInfo->wOLEDBType || DBTYPE_BYTES == pParamInfo->wOLEDBType)
{
ULONG iParamSet;
DBTYPE wDstType = (DBTYPE_BSTR == pParamInfo->wOLEDBType) ? DBTYPE_WSTR : pParamInfo->wOLEDBType;
cbMaxLen = pBind->cbMaxLen;
for (iParamSet = 2; iParamSet <= m_dbparams.cParamSets; iParamSet++)
{
DBTYPE wSrcType;
//==========================================
// Bind the parameter
//==========================================
pBind = m_prgBindInfo[iParam].pBinding;
BindParamData(iParamSet, iParam+1, pBind, &pbData, &pdwLength, &dwLength, &pdwStatus, &dwStatus, &wSrcType);
cbMaxLen = pBind->cbMaxLen;
}
// Initialize the parameter info
BOOL bArray = FALSE;
CDataMap Map;
if(hr == S_OK)
{
hr = Map.MapOLEDBTypeToCIMType(pParamInfo->wOLEDBType, pParamInfo->CIMType ) ;
if( S_OK == hr ){
WORD wTmp = 0;
DBLENGTH uSize = 0;
DWORD dwFlags = 0;
// if the length as obtained from BindParamData is 0 and if the parameter
// is input then get the size of parameter for the type
if(pParamInfo->cbColLength == 0 && (pParamInfo->dwFlags & DBPARAMIO_INPUT))
{
hr = Map.MapCIMTypeToOLEDBType(pParamInfo->CIMType, wTmp, uSize, dwFlags );
if( hr == S_OK ){
pParamInfo->cbColLength = pParamInfo->cbValueMax = pParamInfo->ulParamSize = uSize;
}
}
}
}
}
m_prgBindInfo[iParam].pParamInfo = pParamInfo;
}
}
}
}
//Exit:
hr = hr != S_OK ? g_pCError->PostHResult(E_OUTOFMEMORY, piid): hr;
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Sets the bind status for all parameters, except the one that caused the command to fail,
// to DBSTATUS_E_UNAVAILABLE.
//
// Nothing
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
void CUtlParam::SetParamsUnavailable( ULONG iParamSetFailed, ULONG iParamFailed, BOOL fBackOut )
{
assert(iParamSetFailed);
ULONG iParam;
ULONG iParamSet;
BYTE* pbData;
PWMIBINDINFO pBindInfo;
for ( iParamSet = fBackOut? 1 : iParamSetFailed, pbData= (BYTE*)m_dbparams.pData + (iParamSet-1)*m_cbRowSize;
iParamSet <= m_dbparams.cParamSets; iParamSet++, pbData += m_cbRowSize){
for ( iParam = 1, pBindInfo = m_prgBindInfo; iParam <= m_cParams; iParam++, pBindInfo++){
DBSTATUS* pdbstatus = (DBSTATUS *) (pbData + pBindInfo->pBinding->obStatus);
if (pBindInfo->pBinding->dwPart & DBPART_STATUS){
if (iParamSet != iParamSetFailed || iParam != iParamFailed
|| *pdbstatus == DBSTATUS_S_OK
|| *pdbstatus == DBSTATUS_S_ISNULL
|| *pdbstatus == DBSTATUS_S_DEFAULT){
*pdbstatus = DBSTATUS_E_UNAVAILABLE;
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
void CUtlParam::BindParamData( ULONG iParamSet, ULONG iParam, DBBINDING* pBinding,BYTE** ppbValue,
DWORD** ppdwLength, DWORD* pdwLength,DBSTATUS** ppdwStatus,
DBSTATUS* pdwStatus, DBTYPE* pdbtype )
{
assert(iParamSet && iParamSet <= m_dbparams.cParamSets);
assert(iParam && iParam <= m_cParams);
assert(pBinding);
assert(pBinding->iOrdinal == iParam);
assert(ppbValue);
assert(ppdwLength);
assert(pdwLength);
assert(ppdwStatus);
assert(pdwStatus);
BYTE* pbData = (BYTE*)m_dbparams.pData + (iParamSet-1)*m_cbRowSize;
*pdbtype = pBinding->wType & ~DBTYPE_BYREF;
if (pBinding->dwPart & DBPART_VALUE){
*ppbValue = pbData + pBinding->obValue;
if (pBinding->wType & DBTYPE_BYREF){
assert(!IsBadReadPtr(*ppbValue,sizeof(BYTE*)));
*ppbValue = *(BYTE**)*ppbValue;
}
}
else{
*ppbValue = NULL;
}
if (pBinding->dwPart & DBPART_STATUS){
assert(!IsBadReadPtr(pbData+pBinding->obStatus,sizeof(DBSTATUS)));
*ppdwStatus = (DBSTATUS*)(pbData + pBinding->obStatus);
*pdwStatus = **ppdwStatus;
}
else{
*ppdwStatus = NULL;
*pdwStatus = DBSTATUS_S_OK;
}
*ppdwLength = (pBinding->dwPart & DBPART_LENGTH) ? (DWORD*)(pbData + pBinding->obLength) : NULL;
if (*pdwStatus != DBSTATUS_S_OK || *ppbValue == NULL || pBinding->eParamIO == DBPARAMIO_OUTPUT){
*pdwLength = 0;
}
//NTRaid:111761
// 06/07/00
else
if(*ppdwLength)
{
*pdwLength = *(*ppdwLength);
}
else
{
*pdwLength = 0;
}
// check NULL data
if (*pdwStatus == DBSTATUS_S_OK && *ppbValue && (*pdbtype == DBTYPE_VARIANT || *pdbtype == DBTYPE_PROPVARIANT)
&& V_VT((VARIANT *)(*ppbValue)) == VT_NULL){
*pdwStatus = DBSTATUS_S_ISNULL;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
ULONG CUtlParam::AddRef ( void)
{
return InterlockedIncrement( (long*) &m_cRef);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
ULONG CUtlParam::Release(void)
{
assert( m_cRef > 0 );
ULONG cRef = InterlockedDecrement( (long*) &m_cRef);
if (!cRef)
delete this;
return cRef;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CUtlParam::CUtlParam()
{
m_cRef = 0;
m_cbRowSize = 0;
m_cParams = 0;
m_cParamInfo = 0;
m_dwStatus = 0;
m_pIAccessor = NULL;
m_prgBindInfo = NULL;
m_rgpParamInfo = NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
CUtlParam::~CUtlParam()
{
}