//////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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() { }