windows-nt/Source/XPSP1/NT/sdktools/infgen/simpledb.cpp
2020-09-26 16:20:57 +08:00

622 lines
16 KiB
C++

#include <tchar.h>
#include <stddef.h>
#include <mbctype.h>
#define DBINITCONSTANTS
#include <sqloledb.h>
#undef DBINITCONSTANTS
#include <oledberr.h>
#include "simpledb.h"
//
// CSimpleDatabase
//
CSimpleDatabase::CSimpleDatabase(
void
) : m_bCreated(false), m_bSession(false)
{
HRESULT hr;
CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
hr = CoCreateInstance( CLSID_MSDAINITIALIZE,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDataInitialize,
(PVOID *)&m_pDataInit );
if ( !FAILED(hr) )
{
m_bCreated = TRUE;
}
}
CSimpleDatabase::~CSimpleDatabase(
void
)
{
if ( NULL != m_pDataInit )
{
m_pDataInit->Release();
}
if ( NULL != m_pSession )
{
m_pSession->Release();
}
CoUninitialize();
}
HRESULT
CSimpleDatabase::Connect(
LPCTSTR szServer,
LPCTSTR szDatabase,
LPCTSTR szUserName,
LPCTSTR szPassword
)
{
HRESULT hr;
DBPROP props[4];
DBPROPSET rgProps[1];
DWORD dwNumProps = 0;
IDBInitialize *pDBInitialize;
IDBProperties *pDBProps;
#ifndef UNICODE
wchar_t *wszTemp;
size_t lenTemp;
#endif
if ( !m_bCreated )
{
return E_HANDLE;
}
// If this is not the first connection, reset
if ( m_bSession )
{
m_pSession->Release();
m_pSession = NULL;
m_bSession = FALSE;
}
//
// Set the connection properties
//
for ( short i = 0; i < 4; i++ )
{
VariantInit( &props[i].vValue );
}
// Server
props[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
props[0].vValue.vt = VT_BSTR;
#ifndef UNICODE
lenTemp = strlen(szServer) + 1;
wszTemp = new wchar_t[lenTemp];
if ( NULL == wszTemp )
{
return E_OUTOFMEMORY;
}
if ( 0 == MultiByteToWideChar( _getmbcp(),
0L,
szServer,
lenTemp,
wszTemp,
lenTemp ) )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
props[0].vValue.bstrVal = SysAllocString( wszTemp );
delete [] wszTemp;
#else
props[0].vValue.bstrVal = SysAllocString( szServer );
#endif
props[0].dwOptions = DBPROPOPTIONS_REQUIRED;
props[0].colid = DB_NULLID;
dwNumProps++;
if ( szDatabase )
{
// Default Database
props[1].dwPropertyID = DBPROP_INIT_CATALOG;
props[1].vValue.vt = VT_BSTR;
#ifndef UNICODE
lenTemp = strlen(szDatabase) + 1;
wszTemp = new wchar_t[lenTemp];
if ( NULL == wszTemp )
{
return E_OUTOFMEMORY;
}
if ( 0 == MultiByteToWideChar( _getmbcp(),
0L,
szDatabase,
lenTemp,
wszTemp,
lenTemp ) )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
props[1].vValue.bstrVal = SysAllocString( wszTemp );
delete [] wszTemp;
#else
props[1].vValue.bstrVal = SysAllocString( szDatabase );
#endif
props[1].dwOptions = DBPROPOPTIONS_REQUIRED;
props[1].colid = DB_NULLID;
dwNumProps++;
}
if ( szUserName )
{
// Username
props[2].dwPropertyID = DBPROP_AUTH_USERID;
props[2].vValue.vt = VT_BSTR;
#ifndef UNICODE
lenTemp = strlen(szUserName) + 1;
wszTemp = new wchar_t[lenTemp];
if ( NULL == wszTemp )
{
return E_OUTOFMEMORY;
}
if ( 0 == MultiByteToWideChar( _getmbcp(),
0L,
szUserName,
lenTemp,
wszTemp,
lenTemp ) )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
props[2].vValue.bstrVal = SysAllocString( wszTemp );
delete [] wszTemp;
#else
props[2].vValue.bstrVal = SysAllocString( szUserName );
#endif
props[2].dwOptions = DBPROPOPTIONS_REQUIRED;
props[2].colid = DB_NULLID;
dwNumProps++;
// Password
props[3].dwPropertyID = DBPROP_AUTH_PASSWORD;
props[3].vValue.vt = VT_BSTR;
#ifndef UNICODE
lenTemp = strlen(szPassword) + 1;
wszTemp = new wchar_t[lenTemp];
if ( NULL == wszTemp )
{
return E_OUTOFMEMORY;
}
if ( 0 == MultiByteToWideChar( _getmbcp(),
0L,
szPassword,
lenTemp,
wszTemp,
lenTemp ) )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
props[3].vValue.bstrVal = SysAllocString( wszTemp );
delete [] wszTemp;
#else
props[3].vValue.bstrVal = SysAllocString( szPassword );
#endif
props[3].dwOptions = DBPROPOPTIONS_REQUIRED;
props[3].colid = DB_NULLID;
dwNumProps++;
}
else
{
// Use Windows authentication
props[3].dwPropertyID = DBPROP_AUTH_INTEGRATED;
props[3].vValue.vt = VT_BSTR;
props[3].vValue.bstrVal = NULL;
props[3].dwOptions = DBPROPOPTIONS_REQUIRED;
props[3].colid = DB_NULLID;
dwNumProps++;
}
hr = m_pDataInit->CreateDBInstance( CLSID_SQLOLEDB,
NULL,
CLSCTX_INPROC_SERVER,
NULL,
IID_IDBInitialize,
(IUnknown **)&pDBInitialize );
if ( FAILED(hr) ) { return hr; }
hr = pDBInitialize->QueryInterface( IID_IDBProperties, (PVOID *)&pDBProps );
if ( FAILED(hr) ) { return hr; }
rgProps[0].guidPropertySet = DBPROPSET_DBINIT;
rgProps[0].cProperties = dwNumProps;
rgProps[0].rgProperties = props;
hr = pDBProps->SetProperties(1, rgProps);
pDBProps->Release();
if ( FAILED(hr) ) { return hr; }
hr = pDBInitialize->Initialize();
if ( FAILED(hr) )
{
pDBInitialize->Release();
return hr;
}
hr = EstablishSession( pDBInitialize );
pDBInitialize->Release();
return hr;
}
HRESULT
CSimpleDatabase::EstablishSession(
IDBInitialize *pDBInitialize
)
{
HRESULT hr;
IDBCreateSession *pCreateSession = NULL;
hr = pDBInitialize->QueryInterface( IID_IDBCreateSession,
(PVOID *)&pCreateSession );
if ( FAILED(hr) ) { return hr; }
hr = pCreateSession->CreateSession( NULL, IID_IDBCreateCommand, (IUnknown **)&m_pSession );
if ( FAILED(hr) )
{
pCreateSession->Release();
return hr;
}
pCreateSession->Release();
m_bSession = FALSE;
return S_OK;
}
HRESULT
CSimpleDatabase::Execute(
LPCTSTR szCommand,
CSimpleDBResults **ppOutResults
)
{
HRESULT hr;
ICommandText *pCommandText = NULL;
IMultipleResults *pResults = NULL;
DBROWCOUNT cRowsAffected;
if ( NULL != ppOutResults )
{
*ppOutResults = NULL;
}
hr = m_pSession->CreateCommand( NULL, IID_ICommandText, (IUnknown **)&pCommandText );
if ( FAILED(hr) ) { return hr; }
#ifndef UNICODE
size_t lenTemp = strlen(szCommand) + 1;
wchar_t *wszTemp = new wchar_t[lenTemp];
if ( NULL == wszTemp )
{
return E_OUTOFMEMORY;
}
if ( 0 == MultiByteToWideChar( _getmbcp(),
0L,
szCommand,
lenTemp,
wszTemp,
lenTemp ) )
{
pCommandText->Release();
return HRESULT_FROM_WIN32( GetLastError() );
}
hr = pCommandText->SetCommandText( DBGUID_DBSQL, wszTemp );
delete [] wszTemp;
#else
hr = pCommandText->SetCommandText( DBGUID_DBSQL, szCommand );
#endif
if ( FAILED(hr) )
{
pCommandText->Release();
return hr;
}
hr = pCommandText->Execute( NULL, IID_IMultipleResults, NULL, &cRowsAffected, (IUnknown **)&pResults );
if ( FAILED(hr) )
{
pCommandText->Release();
return hr;
}
// If the command succeeded but didn't return any results, return successfully
if ( cRowsAffected != -1 )
{
return S_FALSE;
}
*ppOutResults = new CSimpleDBResults( pResults );
pResults->Release();
if ( NULL == *ppOutResults )
{
return E_OUTOFMEMORY;
}
return S_OK;
}
//
// CSimpleDBResults
//
CSimpleDBResults::CSimpleDBResults(
IMultipleResults *pResults
) : m_pResults(NULL),
m_pCurRowset(NULL),
m_phRow(NULL),
m_rgColumnInfo(NULL),
m_pColumnBuf(NULL),
m_colInfo(NULL),
m_numColumns(0)
{
m_pResults = pResults;
m_pResults->AddRef();
NextResultSet();
}
CSimpleDBResults::~CSimpleDBResults(
void
)
{
FreeRow();
FreeRowset();
m_pResults->Release();
}
HRESULT
CSimpleDBResults::NextResultSet(
void
)
{
HRESULT hr;
DBROWCOUNT cRowsAffected;
IColumnsInfo *pColInfo = NULL;
FreeRowset();
hr = m_pResults->GetResult( NULL, 0, IID_IRowset, &cRowsAffected, (IUnknown **)&m_pCurRowset );
if ( FAILED(hr) ) { return hr; }
// Store column info
hr = m_pCurRowset->QueryInterface( IID_IColumnsInfo, (PVOID *)&pColInfo );
if ( FAILED(hr) ) { return hr; }
hr = pColInfo->GetColumnInfo( &m_numColumns, &m_rgColumnInfo, &m_pColumnBuf );
pColInfo->Release();
if ( FAILED(hr) ) { return hr; }
m_colInfo = new ColInfo[m_numColumns];
if ( NULL == m_colInfo )
{
return E_OUTOFMEMORY;
}
memset( (PVOID)m_colInfo, 0, sizeof(ColInfo) * m_numColumns );
return S_OK;
}
void
CSimpleDBResults::FreeRowset(
void
)
{
IAccessor *pAccessor = NULL;
if ( m_pCurRowset )
{
if ( FAILED(m_pCurRowset->QueryInterface( IID_IAccessor, (PVOID *)&pAccessor )) )
{
pAccessor = NULL;
}
}
if ( NULL != m_rgColumnInfo )
{
CoTaskMemFree( m_rgColumnInfo );
m_rgColumnInfo = NULL;
}
if ( NULL != m_pColumnBuf )
{
CoTaskMemFree( m_pColumnBuf );
m_pColumnBuf = NULL;
}
if ( NULL != m_colInfo )
{
for ( DWORD i = 0; i < m_numColumns; i++ )
{
#ifndef UNICODE
if ( NULL != m_colInfo[i].szColumnName )
{
delete [] m_colInfo[i].szColumnName;
}
#endif
if ( pAccessor && m_colInfo[i].hAccessor )
{
pAccessor->ReleaseAccessor( m_colInfo[i].hAccessor, NULL );
}
}
delete [] m_colInfo;
m_colInfo = NULL;
}
if ( pAccessor )
{
pAccessor->Release();
}
if ( m_pCurRowset )
{
m_pCurRowset->Release();
}
m_numColumns = 0;
}
void
CSimpleDBResults::FreeRow(
void
)
{
if ( NULL != m_phRow )
{
m_pCurRowset->ReleaseRows( 1, m_phRow, NULL, NULL, NULL );
m_phRow = NULL;
}
}
HRESULT
CSimpleDBResults::NextRow(
void
)
{
HRESULT hr;
DBCOUNTITEM cRowsReturned;
FreeRow();
hr = m_pCurRowset->GetNextRows( DB_NULL_HCHAPTER, 0, 1, &cRowsReturned, &m_phRow );
if ( DB_S_ENDOFROWSET == hr )
{
return S_FALSE;
}
else if ( FAILED(hr) )
{
return hr;
}
return S_OK;
}
HRESULT
CSimpleDBResults::GetFieldValue(
LPCTSTR szField,
LPTSTR szValue,
DWORD dwMaxChars
)
{
HRESULT hr;
DWORD col;
IAccessor *pAccessor = NULL;
DBBINDING rgBindings[1];
DBBINDSTATUS rgStatus[1];
PVOID pBuf;
szValue[0] = _T('\0');
// Look through column names for specified field
for ( col = 0; col < m_numColumns; col++ )
{
TCHAR *szColName;
#ifndef UNICODE
if ( NULL == m_colInfo[col].szColumnName )
{
size_t lenName = wcslen(m_rgColumnInfo[col].pwszName) + 1;
m_colInfo[col].szColumnName = new char[lenName];
if ( NULL == m_colInfo[col].szColumnName )
{
return E_OUTOFMEMORY;
}
if ( 0 == WideCharToMultiByte( CP_ACP,
0L,
m_rgColumnInfo[col].pwszName,
lenName,
m_colInfo[col].szColumnName,
lenName,
NULL,
NULL ) ) {
return HRESULT_FROM_WIN32( GetLastError() );
}
}
szColName = m_colInfo[col].szColumnName;
#else
szColName = m_rgColumnInfo[col].pwszName;
#endif
if ( !_tcsicmp( szColName, szField ) )
{
break;
}
}
// Column is not in current rowset
if ( col >= m_numColumns )
{
return S_FALSE;
}
if ( !m_colInfo[col].hAccessor )
{
memset( rgBindings, 0, sizeof(DBBINDING) );
rgBindings[0].iOrdinal = m_rgColumnInfo[col].iOrdinal;
rgBindings[0].dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
rgBindings[0].dwFlags = 0;
rgBindings[0].obStatus = offsetof(_BindResult, status);
rgBindings[0].obLength = offsetof(_BindResult, length);
rgBindings[0].obValue = offsetof(_BindResult, value);
rgBindings[0].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBindings[0].eParamIO = DBPARAMIO_NOTPARAM;
rgBindings[0].bPrecision = m_rgColumnInfo[col].bPrecision;
rgBindings[0].bScale = m_rgColumnInfo[col].bScale;
rgBindings[0].wType = DBTYPE_WSTR;
rgBindings[0].cbMaxLen = dwMaxChars * sizeof(WCHAR);
hr = m_pCurRowset->QueryInterface( IID_IAccessor, (PVOID *)&pAccessor );
if ( FAILED(hr) ) { return hr; }
hr = pAccessor->CreateAccessor( DBACCESSOR_ROWDATA,
1,
rgBindings,
0,
&m_colInfo[col].hAccessor,
rgStatus );
pAccessor->Release();
if ( FAILED(hr) ) { return hr; }
}
// Setup a buffer large enough to hold max results
pBuf = (PVOID)new BYTE[ sizeof(_BindResult) + dwMaxChars * sizeof(WCHAR) ];
if ( NULL == pBuf )
{
return E_OUTOFMEMORY;
}
hr = m_pCurRowset->GetData( *m_phRow, m_colInfo[col].hAccessor, pBuf );
if ( FAILED(hr) ) { return hr; }
// Skip status and length and just get the result for now
wchar_t *wszValue = (LPWSTR)((DWORD_PTR)pBuf + offsetof(_BindResult, value));
#ifndef UNICODE
if ( 0 == WideCharToMultiByte( CP_ACP,
0L,
wszValue,
-1,
szValue,
dwMaxChars,
NULL,
NULL ) ) {
return HRESULT_FROM_WIN32( GetLastError() );
}
#else
wcscpy( szValue, wszValue );
#endif
return S_OK;
}