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