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

213 lines
5.6 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1999, Microsoft Corp. All rights reserved.
//
// FILE
//
// MySimpleTable.cpp
//
// SYNOPSIS
//
// MySimpleTable.cpp: derived from CSimpleTable. Only difference
// is _GetDataPtr now public instead of being protected
//
// MODIFICATION HISTORY
//
// 01/26/1999 Original version.
//
//
//////////////////////////////////////////////////////////////////////
#include "precomp.hpp"
#include "simpletableex.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////////////////
//
// STRUCT
//
// DBBinding
//
// DESCRIPTION
//
// This struct extends the DBBINDING struct to provide functionality
// to initialize the struct from a DBCOLUMNINFO struct.
//
///////////////////////////////////////////////////////////////////////////////
struct DBBinding : DBBINDING
{
//////////
// 'offset' is the offset in bytes of this column's data within the
// row buffer.
//////////
void Initialize(DBCOLUMNINFO& columnInfo, DBBYTEOFFSET& offset)
{
iOrdinal = columnInfo.iOrdinal;
obValue = offset;
obLength = offset + columnInfo.ulColumnSize;
obStatus = obLength + sizeof(DBLENGTH);
pTypeInfo = NULL;
pObject = NULL;
pBindExt = NULL;
dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
eParamIO = DBPARAMIO_NOTPARAM;
dwMemOwner = (columnInfo.wType & DBTYPE_BYREF) ? DBMEMOWNER_PROVIDEROWNED
: DBMEMOWNER_CLIENTOWNED;
cbMaxLen = columnInfo.ulColumnSize;
dwFlags = 0;
wType = columnInfo.wType;
bPrecision = columnInfo.bPrecision;
bScale = columnInfo.bScale;
offset = obStatus + sizeof(DBSTATUS);
}
};
///////////////////////////////////////////////////////////////////////////////
//
// METHOD
//
// CSimpleTableEx::Attach
//
// Size bug "fixed"
//
// DESCRIPTION
//
// This method binds the table object to a new rowset. The previous rowset
// (if any) will be detached.
//
// REMARK: see "Changes" below
//
///////////////////////////////////////////////////////////////////////////////
HRESULT CSimpleTableEx::Attach(IRowset* pRowset)
{
// Make sure we didn't get a null pointer.
if (!pRowset) { return E_POINTER; }
// Detach the current rowset.
Detach();
// We don't care if this returns an error. It will just prevent
// the user from updating.
pRowset->QueryInterface(IID_IRowsetChange, (void**)&rowsetChange);
//////////
// Get the column information for the table.
//////////
CComPtr<IColumnsInfo> ColumnsInfo;
RETURN_ERROR(pRowset->QueryInterface(IID_IColumnsInfo,
(void**)&ColumnsInfo));
RETURN_ERROR(ColumnsInfo->GetColumnInfo(&numColumns,
&columnInfo,
&stringsBuffer));
//////////
// Allocate the per-column data.
//////////
// tperraut Bug 449498
columnBinding = new (std::nothrow) DBBinding[numColumns];
if ( !columnBinding )
{
return E_OUTOFMEMORY;
}
// 449498 resize changed: will not throw an exception.
// false if out of memory
if ( !dirty.resize(numColumns) )
{
return E_OUTOFMEMORY;
}
//////////
// Create a binding for each column.
//////////
bufferLength = 0;
for (DBORDINAL i = 0; i < numColumns; ++i)
{
// Compute the width of the column.
DBLENGTH width = columnInfo[i].ulColumnSize;
//////////////////////////////////////////////////////////////////
//
// CHANGES: if size is too big (1 giga byte), then size = a
// pre-defined value. Note: that's dangerous
//
//////////////////////////////////////////////////////////////////
if (SIZE_MEMO_MAX < width)
{
width = SIZE_MEMO_MAX;
}
// Add room for the null terminator.
if (columnInfo[i].wType == DBTYPE_STR)
{
width += 1;
}
else if (columnInfo[i].wType == DBTYPE_WSTR)
{
width = (width + 1) * sizeof(WCHAR);
}
// Round to an 8-byte boundary (could peek ahead and be more efficient).
width = (width + 7) >> 3 << 3;
columnInfo[i].ulColumnSize = width;
// We're using the pTypeInfo element to store the offset to our data.
// We have to store the offset now, since it will be overwritten by
// DBBinding::Initialize.
columnInfo[i].pTypeInfo = (ITypeInfo*)bufferLength;
columnBinding[i].Initialize(columnInfo[i], bufferLength);
}
//////////
// Allocate a buffer for the row data.
//////////
buffer = new (std::nothrow) BYTE[bufferLength];
if (!buffer) { return E_OUTOFMEMORY; }
//////////
// Create an accessor.
//////////
RETURN_ERROR(pRowset->QueryInterface(IID_IAccessor,
(void**)&accessor));
RETURN_ERROR(accessor->CreateAccessor(DBACCESSOR_ROWDATA,
numColumns,
columnBinding,
bufferLength,
&readAccess,
NULL));
// I used this hokey method of assigning the pointer to avoid a
// dependency on atlimpl.cpp
//
// We do this assignment last, so that the presence of a rowset means the
// entire initialization succeeded.
(rowset.p = pRowset)->AddRef();
endOfRowset = false;
return S_OK;
}