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

683 lines
23 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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;
}