COLINFO.CPP
//-------------------------------------------------------------------- 
// 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 ); 
}