//--------------------------------------------------------------------
// Microsoft OLE DB Sample Provider
// (C) Copyright 1994 - 1996 Microsoft Corporation. All Rights Reserved.
//
// @doc
//
// @module COLINFO.CPP | IColumnsInfo interface implementation
//
// Includes ------------------------------------------------------------------
#include "headers.h"
// Code ----------------------------------------------------------------------
// IColumnsInfo specific methods
// CImpIColumnsInfo::GetColumnInfo -------------------------------------------
//
// @mfunc Returns the column metadata needed by most consumers.
//
// @rdesc HRESULT
// @flag S_OK | The method succeeded
// @flag E_OUTOFMEMORY | Out of memory
// @flag E_INVALIDARG | pcColumns or prginfo or ppStringsbuffer was NULL
//
STDMETHODIMP CImpIColumnsInfo::GetColumnInfo
(
ULONG* pcColumns, //@parm OUT | Number of columns in rowset
DBCOLUMNINFO** prgInfo, //@parm OUT | Array of DBCOLUMNINFO Structures
WCHAR** ppStringsBuffer //@parm OUT | Storage for all string values
)
{
ULONG icol,
icolStart;
DBCOLUMNINFO* rgdbcolinfo;
WCHAR* pstrBuffer;
// Usual argument checking, prescribed by the spec.
if (pcColumns == NULL || prgInfo == NULL || ppStringsBuffer == NULL)
return ResultFromScode( E_INVALIDARG );
// Fill in with something, in case of error later.
*pcColumns = 0;
*prgInfo = NULL;
*ppStringsBuffer = NULL;
icolStart = 1;
rgdbcolinfo = (DBCOLUMNINFO *) g_pIMalloc->Alloc( m_pObj->m_cCols*sizeof( DBCOLUMNINFO ));
if (rgdbcolinfo == NULL)
return ResultFromScode( E_OUTOFMEMORY );
memcpy( rgdbcolinfo, &(m_pObj->m_rgdbcolinfo[icolStart]), m_pObj->m_cCols*sizeof( DBCOLUMNINFO ));
// Copy the heap for column names.
if (m_pObj->m_cbHeapUsed)
{
ptrdiff_t dp;
pstrBuffer = (WCHAR *) g_pIMalloc->Alloc( m_pObj->m_cbHeapUsed );
if (pstrBuffer == NULL)
{
g_pIMalloc->Free( rgdbcolinfo );
return ResultFromScode( E_OUTOFMEMORY );
}
memcpy( pstrBuffer, m_pObj->m_pbHeap, m_pObj->m_cbHeapUsed );
dp = (LONG) pstrBuffer - (LONG) (m_pObj->m_pbHeap);
dp >>= 1;
/* Loop through columns and adjust pointers to column names. */
for (icol =0; icol < m_pObj->m_cCols; icol++)
{
if (rgdbcolinfo[icol].pwszName)
rgdbcolinfo[icol].pwszName += dp;
}
}
*prgInfo = rgdbcolinfo;
*ppStringsBuffer = pstrBuffer;
*pcColumns = m_pObj->m_cCols;
return ResultFromScode( S_OK );
}
// CImpIColumnsInfo::MapColumnIDs --------------------------------------------
//
// @mfunc Returns an array of ordinals of the columns in a rowset that are
// identified by the specified column IDs.
//
// @rdesc HRESULT
// @flag S_OK | The method succeeded
// @flag E_INVALIDARG | cColumnIDs was not 0 and rgColumnIDs was NULL,
// rgColumns was NULL
// @flag DB_E_COLUMNUNAVAILABLE | An element of rgColumnIDs was invalid
//
STDMETHODIMP CImpIColumnsInfo::MapColumnIDs
(
ULONG cColumnIDs, //@parm IN | Number of Column IDs to map
const DBIDrgColumnIDs[], //@parm IN | Column IDs to map
ULONG rgColumns[] //@parm OUT | Ordinal values
)
{
BOOL fError = FALSE;
ULONG i;
// Check arguments
if ((cColumnIDs != 0) && (NULL == rgColumnIDs))
return ResultFromScode( E_INVALIDARG );
if (NULL == rgColumns)
return ResultFromScode( E_INVALIDARG );
if (0 == cColumnIDs)
{
return ResultFromScode( S_OK );
}
// Walk the Column ID structs and determine
// the ordinal value
for (i=0; i < cColumnIDs; i++)
{
if ((rgColumnIDs[i].uName.ulPropid < 1) ||
(rgColumnIDs[i].uName.ulPropid > m_pObj->m_cCols) ||
(rgColumnIDs[i].eKind != DBKIND_GUID_PROPID) ||
(rgColumnIDs[i].uGuid.guid != GUID_NULL))
{
rgColumns[i] = DB_INVALIDCOLUMN;
fError = TRUE;
}
else
rgColumns[i] = rgColumnIDs[i].uName.ulPropid;
}
if (TRUE == fError)
return ResultFromScode( DB_S_ERRORSOCCURRED );
return ResultFromScode( S_OK );
}