windows-nt/Source/XPSP1/NT/admin/pchealth/client/common/pfcommon/pfdb.cpp
2020-09-26 16:20:57 +08:00

1053 lines
26 KiB
C++

/********************************************************************
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
pfdb.cpp
Abstract:
encapsulates all database activity
Revision History:
DerekM created 05/01/99
DerekM modified 02/26/00
DerekM modified 03/24/00
********************************************************************/
#include "stdafx.h"
#include <adoid.h>
#include "pfdb.h"
/////////////////////////////////////////////////////////////////////////////
// tracing stuff
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
/////////////////////////////////////////////////////////////////////////////
// CPFDB- init & termination
// **************************************************************************
CPFDB::CPFDB()
{
m_rgpParams = NULL;
m_pParams = NULL;
m_pCmd = NULL;
m_pConn = NULL;
m_pRS = NULL;
m_pFields = NULL;
m_fNeedReset = FALSE;
m_cSlots = 0;
m_iLastSlot = (DWORD)-1;
m_cte = adCmdUnspecified;
}
// **************************************************************************
CPFDB::~CPFDB()
{
this->Cleanup();
}
/////////////////////////////////////////////////////////////////////////////
// CPFDB- IUnknown
// **************************************************************************
STDMETHODIMP_(ULONG) CPFDB::AddRef(void)
{
USE_TRACING("CPFDB::AddRef");
m_cRef++;
return m_cRef;
}
// **************************************************************************
STDMETHODIMP_(ULONG) CPFDB::Release(void)
{
USE_TRACING("CPFDB::Release");
m_cRef--;
if (m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
/////////////////////////////////////////////////////////////////////////////
// CPFDB- internal methods
// **************************************************************************
void CPFDB::Cleanup(void)
{
USE_TRACING("CPFDB::Cleanup");
if (m_rgpParams != NULL)
{
DWORD i;
for (i = 0; i < m_cSlots; i++)
{
if (m_rgpParams[i] != NULL)
m_rgpParams[i]->Release();
}
MyFree(m_rgpParams);
}
m_bstrConn.Empty();
m_bstrCmd.Empty();
if (m_pParams != NULL)
m_pParams->Release();
if (m_pCmd != NULL)
m_pCmd->Release();
if (m_pConn != NULL)
m_pConn->Release();
if (m_pFields != NULL)
m_pFields->Release();
if (m_pRS != NULL)
{
m_pRS->Close();
m_pRS->Release();
}
m_rgpParams = NULL;
m_pParams = NULL;
m_pCmd = NULL;
m_pConn = NULL;
m_pRS = NULL;
m_pFields = NULL;
m_fNeedReset = FALSE;
m_cSlots = 0;
m_iLastSlot = (DWORD)-1;
m_cte = adCmdUnspecified;
}
// **************************************************************************
HRESULT CPFDB::AddParameterObj(DWORD iPos)
{
USE_TRACING("CPFDB::CreateParameter");
VARIANT varEmpty;
HRESULT hr = NOERROR;
if (iPos >= m_cSlots)
{
LPVOID pv;
DWORD cSlots;
cSlots = MyMax(m_cSlots * 2, c_cInitialProps);
cSlots = MyMax(cSlots , iPos + 1);
pv = MyAlloc(cSlots * sizeof(ADOParameter *));
VALIDATEEXPR(hr, (pv == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
CopyMemory(pv, m_rgpParams, m_cSlots * sizeof(ADOParameter *));
MyFree(m_rgpParams);
m_rgpParams = (ADOParameter **)pv;
m_cSlots = cSlots;
}
// create the parameter and set up the direction
VariantInit(&varEmpty);
TESTHR(hr, m_pCmd->CreateParameter(NULL, adEmpty, adParamInput, 0,
varEmpty, &m_rgpParams[iPos]));
if (FAILED(hr))
goto done;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::TestConnAndRefresh(void)
{
USE_TRACING("CPFDB::AttemptReset");
ADORecordset *pRS = NULL;
CComBSTR bstr;
HRESULT hr = NOERROR;
// if these are missing, we are totally screwed. So tell the caller
// about and share the annoyance
VALIDATEEXPR(hr, (m_pCmd == NULL ||
(m_pConn == NULL && m_bstrConn.m_str == NULL)), E_FAIL);
if (FAILED(hr))
goto done;
// ok, first try to do a bogus send to see if the connection is there or
// not...
TESTHR(hr, bstr.Append(L"SELECT 1"));
if (FAILED(hr))
goto done;
TESTHR(hr, m_pCmd->put_CommandText(bstr.m_str));
if (FAILED(hr))
goto done;
// if this succeeds, there's nothing wrong with the connection (yeah, we
// actually WANT this to fail...)
TESTHR(hr, m_pCmd->Execute(NULL, NULL, adCmdText | adExecuteNoRecords,
&pRS));
if (SUCCEEDED(hr))
{
hr = S_FALSE;
goto done;
}
// ok, so the connection is somehow screwed up so try to fix it...
VALIDATEEXPR(hr, (m_bstrConn.m_str == NULL), E_FAIL);
if (FAILED(hr))
goto done;
m_pConn->Close();
TESTHR(hr, m_pConn->Open(m_bstrConn.m_str, NULL, NULL,
adConnectUnspecified));
if (FAILED(hr))
goto done;
// might have to reset all of the parameter objects at this point &
// re-add them to the command object.
done:
if (pRS != NULL)
{
pRS->Close();
pRS->Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CPFDB- exposed methods
// **************************************************************************
HRESULT CPFDB::Init(LPCWSTR wszConn, DWORD dwTimeout)
{
USE_TRACING("CPFDB::Init");
ADOConnection *pConn = NULL;
CComBSTR bstrConn;
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (wszConn == NULL || dwTimeout == 0));
if (FAILED(hr))
goto done;
TESTHR(hr, CoCreateInstance(CLSID_CADOConnection, NULL,
CLSCTX_INPROC_SERVER, IID_IADOConnection,
(LPVOID *)&pConn));
if (FAILED(hr))
goto done;
TESTHR(hr, pConn->put_CommandTimeout(dwTimeout));
if (FAILED(hr))
hr = NOERROR;
TESTHR(hr, bstrConn.Append(wszConn));
if (FAILED(hr))
goto done;
TESTHR(hr, pConn->Open(bstrConn.m_str, NULL, NULL, adConnectUnspecified));
if (FAILED(hr))
goto done;
TESTHR(hr, this->Init(pConn, dwTimeout, bstrConn.m_str));
if (FAILED(hr))
goto done;
// if the Init method succeeded, then it took control of the bstr, so we
// don't want to free when we exit.
bstrConn.Detach();
done:
if (pConn != NULL)
pConn->Release();
return hr;
}
// **************************************************************************
HRESULT CPFDB::Init(ADOConnection *pConn, DWORD dwTimeout, BSTR bstrConn)
{
USE_TRACING("CPFDB::Init");
ADOParameters *pParams = NULL;
ADOCommand *pCmd = NULL;
CComBSTR bstrConnNew;
HRESULT hr = NOERROR;
// can't have both the connection string and connection object NULL...
VALIDATEPARM(hr, (pConn == NULL));
if (FAILED(hr))
goto done;
// get the connection string for the object
if (bstrConn == NULL)
{
TESTHR(hr, pConn->get_ConnectionString(&bstrConnNew));
if (FAILED(hr))
goto done;
}
else
{
bstrConnNew.Attach(bstrConn);
}
// set up the command object
TESTHR(hr, CoCreateInstance(CLSID_CADOCommand, NULL, CLSCTX_INPROC_SERVER,
IID_IADOCommand25, (LPVOID *)&pCmd));
if (FAILED(hr))
goto done;
TESTHR(hr, pCmd->put_CommandTimeout(dwTimeout));
if (FAILED(hr))
hr = NOERROR;
TESTHR(hr, pCmd->putref_ActiveConnection(pConn));
if (FAILED(hr))
goto done;
TESTHR(hr, pCmd->get_Parameters(&pParams));
if (FAILED(hr))
goto done;
// free up anything that already exists
this->Cleanup();
// save off what we just allocated...
pConn->AddRef();
m_pConn = pConn;
m_pCmd = pCmd;
m_pParams = pParams;
pParams = NULL;
pCmd = NULL;
if (bstrConnNew.m_str != NULL)
m_bstrConn.Attach(bstrConnNew.Detach());
done:
if (pParams != NULL)
pParams->Release();
if (pCmd != NULL)
pCmd->Release();
return hr;
}
// **************************************************************************
HRESULT CPFDB::Begin(LPCWSTR wszCmd, CommandTypeEnum cte)
{
USE_TRACING("CPFDB::Begin");
HRESULT hr = NOERROR;
// validate params
VALIDATEPARM(hr, (wszCmd == NULL));
if (FAILED(hr))
goto done;
// make sure we've been initialized
VALIDATEEXPR(hr, (m_pCmd == NULL), E_FAIL);
if (FAILED(hr))
goto done;
if (m_fNeedReset)
{
TESTHR(hr, this->Reset());
if (FAILED(hr))
goto done;
}
// set the command text
TESTHR(hr, m_bstrCmd.Append(wszCmd));
if (FAILED(hr))
goto done;
TESTHR(hr, m_pCmd->put_CommandText(m_bstrCmd.m_str));
if (FAILED(hr))
goto done;
TESTHR(hr, m_pCmd->put_CommandType(cte));
if (FAILED(hr))
goto done;
m_cte = cte;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::Reset(void)
{
USE_TRACING("CPFDB::Reset");
HRESULT hr = NOERROR;
// check if we need to reset internal stuff
if (m_fNeedReset && m_pParams != NULL)
{
VARIANT var;
long cParams, i;
// got to delete everything in the parameters object cuz ADO is
// stupid and won't let us reuse parameter objects.
TESTHR(hr, m_pParams->get_Count(&cParams));
if (FAILED(hr))
goto done;
VariantInit(&var);
V_VT(&var) = VT_I4;
V_I4(&var) = 0;
for (i = 0; i < cParams; i++)
{
TESTHR(hr, m_pParams->Delete(var));
if (FAILED(hr))
goto done;
if (m_rgpParams != NULL && m_rgpParams[i] != NULL)
{
m_rgpParams[i]->Release();
m_rgpParams[i] = NULL;
}
}
}
m_bstrCmd.Empty();
if (m_pFields != NULL)
m_pFields->Release();
if (m_pRS != NULL)
{
m_pRS->Close();
m_pRS->Release();
}
m_pFields = NULL;
m_pRS = NULL;
m_fNeedReset = FALSE;
m_iLastSlot = (DWORD)-1;
m_cte = adCmdUnspecified;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::AddInParam(VARIANT &varData, DataTypeEnum dtADO, DWORD iPos)
{
USE_TRACING("CPFDB::AddInParam");
VARIANT var;
HRESULT hr = NOERROR;
DWORD dwSize;
VALIDATEEXPR(hr, (m_fNeedReset || m_pCmd == NULL), E_FAIL);
if (FAILED(hr))
goto done;
VariantInit(&var);
// if he passed in -1, it means to use 1 more than the last parameter
// added so far.
if (iPos == (DWORD)-1)
iPos = m_iLastSlot + 1;
// check if we need to alloc a new parameter
TESTHR(hr, this->AddParameterObj(iPos));
if (FAILED(hr))
goto done;
// set the fact that it's an input parameter
TESTHR(hr, m_rgpParams[iPos]->put_Direction(adParamInput));
if (FAILED(hr))
goto done;
// if we got passed in a BSTR with a NULL string, convert it
// to an empty parameter.
if (V_VT(&varData) == VT_BSTR && V_BSTR(&varData) == NULL)
V_VT(&varData) = VT_EMPTY;
// ok, so we have some special case handling for adLongVarWChar types.
// If we have data for it (type is set to VT_BSTR) then we gotta get
// the size of that data & pass it to the parameter object.
// If we don't have data for it (type set to VT_EMPTY) then we gotta
// change the data type to adVarWChar cuz adLongVarWChar expects a non-
// zero size when u append it to the Parameters collection. Stupid ADO.
// more ADO stupidity. If the size of a string isn't specified, ADO will
// determine the max size of the column and tack on spaces until the
// string we send up is the size of the column. So we need to specify a
// size or we'll end up using WAY more space that we need to.
switch(dtADO)
{
case adLongVarWChar:
case adLongVarBinary:
case adLongVarChar:
case adVarWChar:
case adVarChar:
case adVarBinary:
if (V_VT(&varData) == VT_BSTR && *(V_BSTR(&varData)) != L'\0')
{
switch(dtADO)
{
case adLongVarWChar:
case adLongVarChar:
case adVarWChar:
case adVarChar:
dwSize = SysStringLen(V_BSTR(&varData));
break;
case adLongVarBinary:
case adVarBinary:
dwSize = SysStringByteLen(V_BSTR(&varData));
break;
}
}
else if (V_VT(&varData) == (VT_ARRAY | VT_UI1) &&
(dtADO == adVarBinary || dtADO == adLongVarBinary))
{
dwSize = V_ARRAY(&varData)->rgsabound[0].cElements -
V_ARRAY(&varData)->rgsabound[0].lLbound;
}
else
{
dwSize = 0;
switch(dtADO)
{
case adLongVarWChar:
case adVarWChar:
case adLongVarChar:
case adVarChar:
dtADO = adBSTR;
break;
}
}
// gotta set the size of these
TESTHR(hr, m_rgpParams[iPos]->put_Size(dwSize));
if (FAILED(hr))
goto done;
break;
}
// set the type
TESTHR(hr, m_rgpParams[iPos]->put_Type(dtADO));
if (FAILED(hr))
goto done;
TESTHR(hr, m_rgpParams[iPos]->put_Value(varData));
if (FAILED(hr))
goto done;
if (iPos > m_iLastSlot || m_iLastSlot == (DWORD)-1)
m_iLastSlot = iPos;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::AddOutParam(DataTypeEnum dtADO, DWORD iPos, BOOL fSPRetVal,
DWORD cchSize)
{
USE_TRACING("CPFDB::AddOutParam");
HRESULT hr = NOERROR;
VALIDATEEXPR(hr, (m_fNeedReset || m_pCmd == NULL), E_FAIL);
if (FAILED(hr))
goto done;
// if he passed in -1, it means to use 1 more than the last parameter
// added so far.
if (iPos == (DWORD)-1)
iPos = m_iLastSlot + 1;
// check if we need to alloc a new parameter
TESTHR(hr, this->AddParameterObj(iPos));
if (FAILED(hr))
goto done;
// set the type
TESTHR(hr, m_rgpParams[iPos]->put_Type(dtADO));
if (FAILED(hr))
goto done;
// set the fact that it's an output parameter
if (fSPRetVal)
{
TESTHR(hr, m_rgpParams[iPos]->put_Direction(adParamReturnValue));
}
else
{
TESTHR(hr, m_rgpParams[iPos]->put_Direction(adParamOutput));
}
if (FAILED(hr))
goto done;
// if we have a string output parameter, we gotta set the size
// of the string we want returned to us. Why can't ADO just
// return us the string in a BSTR? Cuz ADO is stupid.
if (dtADO == adVarWChar || dtADO == adBSTR || dtADO == adVarChar)
{
TESTHR(hr, m_rgpParams[iPos]->put_Size(cchSize));
if (FAILED(hr))
goto done;
}
if (iPos > m_iLastSlot || m_iLastSlot == (DWORD)-1)
m_iLastSlot = iPos;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::Execute(BOOL fNeedRS)
{
USE_TRACING("CPFDB::Commit");
ADORecordset *pRS = NULL;
IDispatch *pdisp = NULL;
HRESULT hr = NOERROR;
DWORD i;
LONG lVal;
BOOL fConnReset = FALSE;
#if defined(DEBUG) || defined(_DEBUG)
ParameterDirectionEnum pdDbgADO[32];
DataTypeEnum dtDbgADO[32];
VARIANT varDbgVal[32];
DWORD iDbg;
ZeroMemory(pdDbgADO, sizeof(pdDbgADO));
ZeroMemory(dtDbgADO, sizeof(dtDbgADO));
ZeroMemory(varDbgVal, sizeof(varDbgVal));
#endif
// don't want to try this if we failed once or the command object
// doesn't exist
VALIDATEEXPR(hr, (m_fNeedReset || m_pCmd == NULL), E_FAIL);
if (FAILED(hr))
goto done;
m_fNeedReset = TRUE;
// put all of the parameters into the query...
for (i = 0; i < m_iLastSlot + 1; i++)
{
// we cannot have an empty parameter cuz ADO will choke if we do.
// And we can't fill it with a default empty parameter (ie of some
// random type) cuz ADO will complain that it doesn't know how to
// (essentially) convert NULL into NULL or some such stuff.
VALIDATEEXPR(hr, (m_rgpParams[i] == NULL), E_FAIL);
if (FAILED(hr))
goto done;
#if defined(DEBUG) || defined(_DEBUG)
if (i < 32)
{
VariantInit(&varDbgVal[i]);
m_rgpParams[i]->get_Direction(&pdDbgADO[i]);
m_rgpParams[i]->get_Type(&dtDbgADO[i]);
m_rgpParams[i]->get_Value(&varDbgVal[i]);
}
#endif
TESTHR(hr, m_rgpParams[i]->QueryInterface(IID_IDispatch,
(LPVOID *)&pdisp));
_ASSERT(SUCCEEDED(hr));
TESTHR(hr, m_pParams->Append(pdisp));
if (FAILED(hr))
goto done;
pdisp->Release();
pdisp = NULL;
}
// execute the sucker
lVal = (fNeedRS) ? m_cte : m_cte | adExecuteNoRecords;
TESTHR(hr, m_pCmd->Execute(NULL, NULL, lVal, &pRS));
if (FAILED(hr))
goto done;
// ok, if we have the recordset. If the caller wanted one, check & see if
// it has any data & fetch the first set of fields out of it...
if (fNeedRS)
{
VARIANT_BOOL vbf;
if (pRS == NULL)
{
hr = S_FALSE;
goto done;
}
TESTHR(hr, pRS->get_EOF(&vbf));
if (FAILED(hr))
goto done;
if (vbf == VARIANT_TRUE)
{
hr = S_FALSE;
goto done;
}
TESTHR(hr, pRS->get_Fields(&m_pFields));
if (FAILED(hr))
goto done;
m_pRS = pRS;
pRS = NULL;
}
done:
#if defined(DEBUG) || defined(_DEBUG)
for (iDbg = 0; iDbg < m_iLastSlot + 1; iDbg++)
VariantClear(&(varDbgVal[iDbg]));
#endif
if (pRS != NULL)
{
pRS->Close();
pRS->Release();
}
if (pdisp != NULL)
pdisp->Release();
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetOutParam(VARIANT &varParam, VARIANT *pvar, VARTYPE vt)
{
USE_TRACING("CPFDB::GetOutParam");
ADOParameter *pParam = NULL;
VARIANT varParamID;
HRESULT hr = NOERROR;
_ASSERT(pvar != NULL && m_pParams != NULL && m_fNeedReset);
VariantClear(pvar);
TESTHR(hr, m_pParams->get_Item(varParam, &pParam));
if (FAILED(hr))
goto done;
TESTHR(hr, pParam->get_Value(pvar));
if (FAILED(hr))
goto done;
if (vt != VT_ILLEGAL && V_VT(pvar) != vt)
{
TESTHR(hr, VariantChangeType(pvar, pvar, 0, vt));
if (FAILED(hr))
{
VariantClear(pvar);
goto done;
}
}
done:
if (pParam != NULL)
pParam->Release();
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetOutParam(BSTR bstrParam, VARIANT *pvar, VARTYPE vt)
{
USE_TRACING("CPFDB::GetOutParam");
VARIANT varParam;
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (bstrParam == NULL || pvar == NULL));
if (FAILED(hr))
goto done;
// make sure we've been initialized & that we've executed an SP...
VALIDATEEXPR(hr, (m_pParams == NULL || m_fNeedReset == FALSE), E_FAIL);
if (FAILED(hr))
goto done;
// do not free this VARIANT cuz we don't own the BSTR
VariantInit(&varParam);
V_VT(&varParam) = VT_BSTR;
V_BSTR(&varParam) = bstrParam;
TESTHR(hr, this->GetOutParam(varParam, pvar, vt));
if (FAILED(hr))
goto done;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetOutParam(DWORD iParam, VARIANT *pvar, VARTYPE vt)
{
USE_TRACING("CPFDB::GetOutParam");
VARIANT varParam;
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (pvar == NULL));
if (FAILED(hr))
goto done;
// make sure we've been initialized & that we've executed an SP...
VALIDATEEXPR(hr, (m_pParams == NULL || m_fNeedReset == FALSE), E_FAIL);
if (FAILED(hr))
goto done;
if (iParam == (DWORD)-1)
iParam = m_iLastSlot;
// we can't get the parameter via the array we've stored so we have to
// ask the parameter object for it
if (iParam >= m_cSlots)
{
VariantInit(&varParam);
V_VT(&varParam) = VT_I4;
V_I4(&varParam) = iParam;
TESTHR(hr, this->GetOutParam(varParam, pvar, vt));
if (FAILED(hr))
goto done;
}
// WOOHOO!! Life is good when u can just accessed cached stuff...
else
{
VariantClear(pvar);
TESTHR(hr, m_rgpParams[iParam]->get_Value(pvar));
if (FAILED(hr))
goto done;
if (V_VT(pvar) != vt && vt != VT_ILLEGAL && V_VT(pvar) != VT_NULL &&
V_VT(pvar) != VT_EMPTY)
{
TESTHR(hr, VariantChangeType(pvar, pvar, 0, vt));
if (FAILED(hr))
{
VariantClear(pvar);
goto done;
}
}
}
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetNextRow(void)
{
USE_TRACING("CPFDB::GetNextRow");
VARIANT_BOOL vbf;
HRESULT hr = NOERROR;
VALIDATEEXPR(hr, (m_pRS == NULL || m_fNeedReset == FALSE), E_FAIL);
if (FAILED(hr))
goto done;
if (m_pFields != NULL)
{
m_pFields->Release();
m_pFields = NULL;
}
TESTHR(hr, m_pRS->MoveNext());
if (FAILED(hr))
goto done;
// see if we're at the end of th line & if so, free everything up...
TESTHR(hr, m_pRS->get_EOF(&vbf));
if (FAILED(hr))
goto done;
if (vbf == VARIANT_TRUE)
{
m_pRS->Close();
m_pRS->Release();
m_pRS = NULL;
hr = S_FALSE;
goto done;
}
TESTHR(hr, m_pRS->get_Fields(&m_pFields));
if (FAILED(hr))
goto done;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetData(VARIANT &varField, VARIANT *pvarData)
{
USE_TRACING("CPFDB::GetData");
ADOField *pField = NULL;
HRESULT hr = NOERROR;
LONG lVal;
ADO_LONGPTR llSize;
_ASSERT(pvarData != NULL && m_pFields != NULL && m_fNeedReset);
TESTHR(hr, m_pFields->get_Item(varField, &pField));
if (FAILED(hr))
goto done;
TESTHR(hr, pField->get_Attributes(&lVal));
if (FAILED(hr))
goto done;
// get the actual data out of the field- if it has adFldLong set, then
// retrieve it using the GetChunk method cuz ADO likes it this way.
if ((lVal & adFldLong) != 0)
{
TESTHR(hr, pField->get_ActualSize(&llSize));
if (FAILED(hr))
goto done;
// NTRAID#NTBUG9-374453-2001/4/21-reinerf
// we only ever read 4gig of data since GetChunk still only takes a LONG
lVal = min(MAXLONG, llSize);
TESTHR(hr, pField->GetChunk(lVal, pvarData));
if (FAILED(hr))
goto done;
}
else
{
TESTHR(hr, pField->get_Value(pvarData));
if (FAILED(hr))
goto done;
}
done:
if (pField != NULL)
pField->Release();
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetData(BSTR bstrField, VARIANT *pvarData)
{
USE_TRACING("CPFDB::GetData");
VARIANT varField;
HRESULT hr = NOERROR;
LONG cFields;
VALIDATEPARM(hr, (bstrField == NULL || pvarData == NULL));
if (FAILED(hr))
goto done;
VALIDATEEXPR(hr, (m_pFields == NULL || m_fNeedReset == FALSE), E_FAIL);
if (FAILED(hr))
goto done;
// don't free this VARIANT since we don't own the BSTR
VariantInit(&varField);
V_VT(&varField) = VT_BSTR;
V_BSTR(&varField) = bstrField;
TESTHR(hr, this->GetData(varField, pvarData));
if (FAILED(hr))
goto done;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetData(DWORD iField, VARIANT *pvarData)
{
USE_TRACING("CPFDB::GetData");
ADOField *pField = NULL;
VARIANT varField;
HRESULT hr = NOERROR;
LONG cFields;
VALIDATEPARM(hr, (pvarData == NULL));
if (FAILED(hr))
goto done;
VALIDATEEXPR(hr, (m_pFields == NULL || m_fNeedReset == FALSE), E_FAIL);
if (FAILED(hr))
goto done;
TESTHR(hr, m_pFields->get_Count(&cFields));
if (FAILED(hr))
goto done;
VALIDATEEXPR(hr, (iField >= (DWORD)cFields),
Err2HR(RPC_S_INVALID_BOUND));
if (FAILED(hr))
goto done;
VariantInit(&varField);
V_VT(&varField) = VT_I4;
V_I4(&varField) = iField;
TESTHR(hr, this->GetData(varField, pvarData));
if (FAILED(hr))
goto done;
done:
return hr;
}
// **************************************************************************
HRESULT CPFDB::GetErrors(ADOErrors **ppErrs)
{
USE_TRACING("CPFDB::GetErrors");
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (ppErrs == NULL));
if (FAILED(hr))
goto done;
VALIDATEEXPR(hr, (m_pConn == NULL), E_FAIL);
if (FAILED(hr))
goto done;
TESTHR(hr, m_pConn->get_Errors(ppErrs));
if (FAILED(hr))
goto done;
done:
return hr;
}