//////////////////////////////////////////////////////////////////////////////////////////////////////////// // Microsoft WMI OLE DB Provider // // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved. // // Module : CMDPARAM.CPP - ICommandWithParameters interface implementation // //////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "headers.h" #include "command.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Increments a reference count for the object. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpICommandWithParameters::AddRef(void) { DEBUGCODE(InterlockedIncrement((long*)&m_cRef)); return m_pcmd->AddRef(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Decrement the object's reference count and deletes the object when the new reference count is zero. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CImpICommandWithParameters::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(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces the // called object supports. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpICommandWithParameters::QueryInterface( REFIID riid, LPVOID * ppv ) { return m_pcmd->QueryInterface(riid, ppv); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Get a list of the command's parameters, their names, and their required types. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpICommandWithParameters::GetParameterInfo( DB_UPARAMS* pcParams, DBPARAMINFO** prgParamInfo, OLECHAR** ppNamesBuffer ) { HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; TRY_BLOCK; //========================================================= // Serialize access //========================================================= CAutoBlock cab(m_pcmd->GetCriticalSection()); //========================================================= // Clear previous Error Object for this thread //========================================================= g_pCError->ClearErrorInfo(); //========================================================= // Initialize buffers //========================================================= if ( pcParams ) { *pcParams = 0; } if ( prgParamInfo ) { *prgParamInfo = NULL; } if ( ppNamesBuffer ) { *ppNamesBuffer = NULL; } //========================================================= // Validate Agruments //========================================================= if ( (pcParams == NULL) || (prgParamInfo == NULL) ) { hr = E_INVALIDARG; } else //========================================================= // If the consumer has not supplied parameter information. //========================================================= if ( m_pcmd->m_pQuery->GetParamCount() == 0 ) { //===================================================== // Command Object must be in prepared state //===================================================== if ( !(m_pcmd->m_pQuery->GetStatus() & CMD_READY) ) { hr = DB_E_NOTPREPARED; } } if(SUCCEEDED(hr)) { hr = m_pcmd->GetParameterInfo(pcParams, prgParamInfo, ppNamesBuffer, &IID_ICommandWithParameters); } hr = hr == S_OK ? hr : g_pCError->PostHResult(hr,&IID_ICommandWithParameters); CATCH_BLOCK_HRESULT(hr,L"ICommandWithParameters::GetParameterInfo"); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Map parameter names to parameter ordinals // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpICommandWithParameters::MapParameterNames( DB_UPARAMS cParamNames, const OLECHAR* rgParamNames[], DB_LPARAMS rgParamOrdinals[] ) { HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; TRY_BLOCK; //========================================================= // Serialize access //========================================================= CAutoBlock cab(m_pcmd->GetCriticalSection()); //============================================================== // Clear previous Error Object for this thread //============================================================== g_pCError->ClearErrorInfo(); if(cParamNames != 0) { if (rgParamNames == NULL || rgParamOrdinals == NULL){ hr = E_INVALIDARG; } else //============================================================== // If the consumer has not supplied parameter information. //============================================================== if ( m_pcmd->m_pQuery->GetParamCount() == 0 ){ //========================================================== // Command Text must be set //========================================================== if (!(m_pcmd->m_pQuery->GetStatus() & CMD_TEXT_SET)){ hr = DB_E_NOCOMMAND; } else //========================================================== // Command Object must be in prepared state //========================================================== if ( !(m_pcmd->m_pQuery->GetStatus() & CMD_READY) ){ hr = DB_E_NOTPREPARED; } } if(SUCCEEDED(hr)) { hr = m_pcmd->MapParameterNames(cParamNames, rgParamNames, rgParamOrdinals, &IID_ICommandWithParameters); } } hr = hr == S_OK ? hr : g_pCError->PostHResult(hr,&IID_ICommandWithParameters); CATCH_BLOCK_HRESULT(hr,L"ICommandWithParameters::MapParameterNames"); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Override the provider's parameter information. // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CImpICommandWithParameters::SetParameterInfo( DB_UPARAMS cParams, const DB_UPARAMS rgParamOrdinals[], const DBPARAMBINDINFO rgParamBindInfo[] ) { ULONG i; BOOL fNamedParams = (cParams > 0) ? TRUE : FALSE; HRESULT hr = S_OK; CSetStructuredExceptionHandler seh; TRY_BLOCK; //========================================================= // Serialize access //========================================================= CAutoBlock cab(m_pcmd->GetCriticalSection()); //=================================================================== // Clear previous Error Object for this thread //=================================================================== g_pCError->ClearErrorInfo(); if ( (cParams != 0) && (rgParamOrdinals == NULL) ){ hr = E_INVALIDARG; } else { //=================================================================== // Scan for invalid arguments in the arrays //=================================================================== for( i = 0; i < cParams; i++ ){ if ( !rgParamOrdinals[i] || (rgParamBindInfo && !(rgParamBindInfo[i].pwszDataSourceType)) ) { hr = E_INVALIDARG; } else if (rgParamBindInfo && rgParamBindInfo[i].pwszName == NULL) { fNamedParams = FALSE; } } if(SUCCEEDED(hr)) { //=================================================================== // Don't allow parameters to be set if we've got a rowset open //=================================================================== if ( m_pcmd->IsRowsetOpen() ){ hr = DB_E_OBJECTOPEN; } else { //=================================================================== // Need to unprepare the statement when parameter info is changed and // set named params //=================================================================== if ((m_pcmd->m_pQuery->GetStatus() & CMD_READY) && m_pcmd->m_pQuery->GetParamCount() > 0 && fNamedParams){ m_pcmd->UnprepareHelper(UNPREPARE_RESET_STMT); } hr = m_pcmd->SetParameterInfo(cParams, rgParamOrdinals, rgParamBindInfo); } } } hr = hr == S_OK ? hr : g_pCError->PostHResult(hr,&IID_ICommandWithParameters); CATCH_BLOCK_HRESULT(hr,L"ICommandWithParameters::SetParameterInfo"); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Get a list of the command's parameters, their names, and their required types. // //////////////////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CCommand::GetParameterInfo( DB_UPARAMS* pcParams, DBPARAMINFO** prgDBParamInfo, WCHAR** ppNamesBuffer, const IID* piid ) { HRESULT hr = S_OK; SHORT sw = 0; ULONG cNumParams = 0; ULONG cbNames = 0; DBPARAMINFO* pTempInfo; WCHAR* pwszNameBuffer; PPARAMINFO pParamInfo; ULONG iParam; //================================================================================= // If the consumer has set info for at least one parameter, // we only return info on the parameters set by the consumer //================================================================================= if (m_pQuery->GetParamCount() > 0){ //============================================================================= // Count the params set by the consumer //============================================================================= cNumParams = 0; for (iParam = 0; iParam <(unsigned) m_pQuery->GetParamCount(); iParam++){ pParamInfo = (PPARAMINFO)m_pQuery->GetParam(iParam); if (pParamInfo){ cNumParams++; if (ppNamesBuffer && pParamInfo->pwszParamName) cbNames += (wcslen(pParamInfo->pwszParamName)+1)*sizeof(WCHAR); } } } else{ hr = S_OK; if (!m_pQuery->m_prgProviderParamInfo && m_pQuery->GetParamCount()){ //========================================================================= // Get the parameter info //========================================================================= hr = GetParamInfo(piid); } if( hr == S_OK ){ cNumParams = m_pQuery->GetParamCount(); if (ppNamesBuffer){ for (iParam = 0; iParam < cNumParams; iParam++){ pParamInfo = m_pQuery->m_prgProviderParamInfo + iParam; if (pParamInfo->pwszParamName) cbNames += (wcslen(pParamInfo->pwszParamName)+1)*sizeof(WCHAR); } } } } //================================================================================== // Check if we have any parameters //================================================================================== if ( cNumParams ){ //============================================================================== // Allocate memory to return the information //============================================================================== *prgDBParamInfo = (DBPARAMINFO*)g_pIMalloc->Alloc(cNumParams*sizeof(DBPARAMINFO)); if ( !*prgDBParamInfo ){ hr = g_pCError->PostHResult(E_OUTOFMEMORY, piid); } else{ hr = S_OK; if (cbNames){ *ppNamesBuffer = (WCHAR*)g_pIMalloc->Alloc(cbNames); if (!*ppNamesBuffer){ hr = g_pCError->PostHResult(E_OUTOFMEMORY, piid); } } if( S_OK == hr ){ //====================================================================== // Initialize memory //====================================================================== memset(*prgDBParamInfo, 0, (cNumParams*sizeof(DBPARAMINFO))); //====================================================================== // Describe the Parameter Markers //====================================================================== if (m_pQuery->GetParamCount() > 0){ //================================================================== // Return the parameter information set by the consumer //================================================================== pwszNameBuffer = ppNamesBuffer? *ppNamesBuffer : NULL; pTempInfo = *prgDBParamInfo; for (iParam = 0; iParam < (unsigned)m_pQuery->GetParamCount(); iParam++) { pParamInfo = (PPARAMINFO) m_pQuery->GetParam(iParam); if (!pParamInfo) continue; //============================================================== // Fill 'er up //============================================================== pTempInfo->dwFlags = pParamInfo->dwFlags; pTempInfo->iOrdinal = iParam+1; if (pwszNameBuffer && pParamInfo->pwszParamName) { pTempInfo->pwszName = pwszNameBuffer; wcscpy(pwszNameBuffer, pParamInfo->pwszParamName); pwszNameBuffer += wcslen(pParamInfo->pwszParamName) + 1; } //============================================================== // pTempInfo->pTypeInfo already NULL //============================================================== pTempInfo->ulParamSize = pParamInfo->ulParamSize; pTempInfo->wType = pParamInfo->wOLEDBType, pTempInfo++; } } else{ //================================================================== // Return the parameter information derived from the command. //================================================================== pwszNameBuffer = ppNamesBuffer? *ppNamesBuffer : NULL; pTempInfo = *prgDBParamInfo; for (iParam = 0; iParam <(ULONG) m_pQuery->GetParamCount(); iParam++){ pParamInfo = m_pQuery->m_prgProviderParamInfo + iParam; //============================================================== // Fill 'er up //============================================================== pTempInfo->dwFlags = pParamInfo->dwFlags; pTempInfo->iOrdinal = iParam+1; if (pwszNameBuffer && pParamInfo->pwszParamName){ pTempInfo->pwszName = pwszNameBuffer; wcscpy(pwszNameBuffer, pParamInfo->pwszParamName); pwszNameBuffer += wcslen(pParamInfo->pwszParamName) + 1; } //============================================================== // pTempInfo->pTypeInfo already NULL //============================================================== pTempInfo->ulParamSize = pParamInfo->ulParamSize; pTempInfo->wType = pParamInfo->wOLEDBType, pTempInfo++; } } } } } if ( SUCCEEDED(hr) ){ *pcParams = cNumParams; } else{ *pcParams = 0; if (*prgDBParamInfo){ g_pIMalloc->Free(*prgDBParamInfo); *prgDBParamInfo = NULL; } if (ppNamesBuffer && *ppNamesBuffer){ g_pIMalloc->Free(*ppNamesBuffer); ppNamesBuffer = NULL; } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // This method allows client to define the parameters. // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CCommand::SetParameterInfo( DB_UPARAMS cParams, const DB_UPARAMS rgParamOrdinals[], const DBPARAMBINDINFO rgParamBindInfo[] ) { HRESULT hr = S_OK; PPARAMINFO pParamInfo = NULL; DBORDINAL iMax = 0; DBORDINAL iParams; CDataMap DataMap; DBTYPE wDataType = 0; BOOL bOveridden = FALSE; BOOL bRet = FALSE; //===================================================================== // If given no params, discard all user param info and return //===================================================================== if (!cParams){ m_pQuery->DeleteConsumerParamInfo(); hr = S_OK; } else { //===================================================================== // If there's no rgParamBindInfo, we're to discard the param information //===================================================================== if ( !rgParamBindInfo ){ ULONG_PTR iElem = 0; //================================================================= // Discard the param info //================================================================= for (iParams = 0; iParams < cParams; iParams++){ iElem = rgParamOrdinals[iParams]; if (iElem > 0 && iElem <= (unsigned)m_pQuery->GetParamCount()){ m_pQuery->RemoveParam(iElem-1); delete pParamInfo; } } hr = S_OK; bRet = TRUE; } //===================================================================== // Find the max param ordinal and check for valid param names //===================================================================== iMax = rgParamOrdinals[0]; for (iParams = 0; iParams < cParams; iParams++){ if (iMax < rgParamOrdinals[iParams]) { iMax = rgParamOrdinals[iParams]; } if(rgParamBindInfo[iParams].pwszName != NULL) /* { hr = DB_E_BADPARAMETERNAME; } else */ if (wcslen(rgParamBindInfo[iParams].pwszName )== 0){ hr = DB_E_BADPARAMETERNAME; } } if(SUCCEEDED(hr)) { DBORDINAL iOrdinal; //===================================================================== // Loop over bind info and set or override the param info //===================================================================== for (iParams = 0; iParams < cParams; iParams++){ iOrdinal = rgParamOrdinals[iParams]; //================================================================= // Add the consumer-provided information to our cache //================================================================= try { pParamInfo = new PARAMINFO; } catch(...) { SAFE_DELETE_PTR(pParamInfo); throw; } if (NULL == pParamInfo){ hr = (E_OUTOFMEMORY); } else { pParamInfo->dwFlags = rgParamBindInfo[iParams].dwFlags; pParamInfo->ulParamSize = rgParamBindInfo[iParams].ulParamSize; pParamInfo->iOrdinal = iOrdinal; DataMap.TranslateParameterStringToOLEDBType( wDataType, rgParamBindInfo[iParams].pwszDataSourceType); pParamInfo->wOLEDBType = wDataType; if (rgParamBindInfo[iParams].pwszName){ ULONG cwchName = wcslen(rgParamBindInfo[iParams].pwszName); try { pParamInfo->pwszParamName = new WCHAR[cwchName+1]; } catch(...) { SAFE_DELETE_ARRAY(pParamInfo->pwszParamName); throw; } if (NULL == pParamInfo->pwszParamName){ SAFE_DELETE_PTR(pParamInfo); hr = (E_OUTOFMEMORY); } else { wcscpy(pParamInfo->pwszParamName,rgParamBindInfo[iParams].pwszName); } } if(SUCCEEDED(hr)) { // Remove the parameter if a parameter alread exist at the ordinal if (iOrdinal > 0 && iOrdinal <= (unsigned)m_pQuery->GetParamCount()){ m_pQuery->RemoveParam(iOrdinal-1); SAFE_DELETE_ARRAY(pParamInfo->pwszParamName); SAFE_DELETE_PTR(pParamInfo); bOveridden = TRUE; } // If there is already a parameter at this ordinal , remove // that and insert this new one hr = m_pQuery->AddConsumerParamInfo(iOrdinal-1,pParamInfo); if( FAILED(hr)){ break; } if( hr == S_OK && bOveridden == TRUE) { hr = DB_S_TYPEINFOOVERRIDDEN; } } } } // for loop } // If succeeded(hr) } hr = hr == S_OK ? hr : g_pCError->PostHResult(hr, &IID_ICommandWithParameters); return hr; } /////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Gets the parameter information for each param marker present in the command. // /////////////////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CCommand::GetParamInfo( const IID *piid ) { PPARAMINFO prgParamInfo = NULL; if (m_CError.Size()) { m_CError.FreeErrors(); } m_pQuery->SetProviderParamInfo(prgParamInfo); return S_OK; } ////////////////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CCommand::MapParameterNames( DB_UPARAMS cParamNames, const OLECHAR* rgParamNames[], DB_LPARAMS rgParamOrdinals[], const IID* piid ) { HRESULT hr = S_OK; ULONG iName = 0; ULONG iParam = 0; ULONG cParam = 0; ULONG cErrors = 0; //======================================================= // Check if we have any parameters //======================================================= if ( cParamNames ) { cParam = m_pQuery->GetParamCount(); if (cParam > 0){ for (iName = 0; iName < cParamNames; iName++){ for (iParam = 0; iParam < cParam; iParam++){ PPARAMINFO pParamInfo; pParamInfo = (PPARAMINFO) m_pQuery->GetParam(iParam); if (pParamInfo && pParamInfo->pwszParamName && !_wcsicmp(rgParamNames[iName],pParamInfo->pwszParamName)){ rgParamOrdinals[iName] = LONG(iParam + 1); break; } } if (iParam == cParam){ rgParamOrdinals[iName] = 0; cErrors++; } } } else{ if (!m_pQuery->m_prgProviderParamInfo && m_pQuery->GetParamCount() && !(m_pQuery->GetStatus())){ //======================================================= // Get the parameter info //======================================================= if (SUCCEEDED(hr = GetParamInfo(piid))){ cParam = m_pQuery->GetParamCount(); for (iName = 0; iName < cParamNames; iName++) { for (iParam = rgParamNames[iName]? 0 : cParam; iParam < cParam; iParam++){ PPARAMINFO pParamInfo = m_pQuery->m_prgProviderParamInfo + iParam; if (pParamInfo->pwszParamName && !_wcsicmp(rgParamNames[iName],pParamInfo->pwszParamName)){ rgParamOrdinals[iName] = LONG(iParam + 1); break; } } } if (iParam == cParam) { rgParamOrdinals[iName] = 0; cErrors++; } } } } if (!cErrors) { hr = S_OK; } else if (cErrors < cParamNames) { hr = DB_S_ERRORSOCCURRED; } else { hr = DB_E_ERRORSOCCURRED; } } hr = hr == S_OK ? hr : g_pCError->PostHResult(hr, &IID_ICommandWithParameters); return hr; }