Microsoft KB Archive/313925

= BUG: Oledb32.dll Truncates Data at the Embedded Null-termination Character if a Column Is Bound to DBTYPE_WSTR =

Article ID: 313925

Article Last Modified on 5/12/2003

-

APPLIES TO


 * Microsoft Data Access Components 2.1
 * Microsoft Data Access Components 2.5
 * Microsoft Data Access Components 2.6
 * Microsoft Data Access Components 2.7

-



This article was previously published under Q313925



SYMPTOMS
When an embedded null-termination character in a varchar column is bound to an OLEDB DBTYPE_WSTR data type, OLE DB Core Services Oledb32.dll truncates the data at the null-termination character.



RESOLUTION
To work around this problem, bind the column that contains a null-termination character to a DBTYPE_BSTR data type that allows embedded nulls.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



Steps to Reproduce Behavior
Bind a varchar column that has a hexadecimal value of 0x4142430044 in the database table to a DBTYPE_WSTR data type in the application. To do this, follow these steps:   In a SQL server database named PUBS, create a table with a varchar column, as follows: CREATE TABLE myTest (col1 varchar (20) NOT NULL)   Insert a record into this table with 0x00 embedded in the data, as follows: INSERT INTO testVarchar VALUES (0x4142430044)   In Microsoft Visual C++ version 6.0, create a new Console Application project that contains the following code:
 * 1) define UNICODE
 * 2) define _UNICODE
 * 3) define DBINITCONSTANTS
 * 4) define INITGUID
 * 5) define MAX_LEN 100


 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 

void main { IDBInitialize * pIDBInitialize = NULL; IDBProperties * pIDBProperties = NULL; ICommandText *     pICommandText; IRowset *          pIRowset; IAccessor *        pIAccessor; IDBCreateSession * pIDBCreateSession; IDBCreateCommand * pIDBCreateCommand; CLSID clsid; const ULONG nProps = 1; DBPROP InitProperties[ nProps ]; DBPROPSET rgInitPropSet; HRESULT            hr; BYTE*              pRowValues; HACCESSOR          hAccessor; LONG               cRowsAffected; DBBINDING *        pDBBindings = NULL; ULONG cbRow = 0; ULONG cRowsObtained; LPOLESTR bSQLString = OLESTR( &quot;select col1 from pubs..myTest&quot; ); HROW rghRows[ 1 ]; HROW * pRows = & rghRows[ 0 ]; ULONG iRow;

VariantInit( &InitProperties[ 0 ].vValue ); InitProperties[ 0 ].dwOptions = DBPROPOPTIONS_REQUIRED; InitProperties[ 0 ].colid = DB_NULLID; InitProperties[ 0 ].dwPropertyID = DBPROP_INIT_PROVIDERSTRING; InitProperties[ 0 ].vValue.vt = VT_BSTR; InitProperties[ 0 ].vValue.bstrVal = Server=kavi1;database=pubs;uid=sa;pwd=sa; rgInitPropSet.guidPropertySet = DBPROPSET_DBINIT; rgInitPropSet.cProperties = nProps; rgInitPropSet.rgProperties = InitProperties;

CoInitialize( NULL );

CLSIDFromProgID( L&quot;SQLOLEDB&quot;, & clsid );

hr = CoCreateInstance( clsid,                NULL,                 CLSCTX_INPROC_SERVER,                 IID_IDBInitialize,                 ( void ** ) & pIDBInitialize );

if( pIDBInitialize == NULL ) {       printf( &quot;CoCreateInstance failed.\n&quot; ); return; }

pIDBInitialize->QueryInterface( IID_IDBProperties,       ( void ** ) & pIDBProperties );

hr = pIDBProperties->SetProperties( 1, & rgInitPropSet );

SysFreeString( InitProperties[ 0 ].vValue.bstrVal );

pIDBProperties->Release;

if( FAILED( hr ) ) {       printf( &quot;Set properties failed.\n&quot; ); return; }

if( FAILED( hr = pIDBInitialize->Initialize ) ) {       printf( &quot;Initialize) failed\n&quot; );    }

// Get the db session object if( FAILED( pIDBInitialize->QueryInterface( IID_IDBCreateSession,       ( void ** ) & pIDBCreateSession ) ) ) {       printf( &quot;Session Initialization failed.\n&quot; ); return; }

// create the session if( FAILED( pIDBCreateSession->CreateSession( NULL,       IID_IDBCreateCommand,        ( IUnknown ** ) & pIDBCreateCommand ) ) ) {       printf( &quot;Create session failed.\n&quot; ); pIDBCreateSession->Release; return; }

// Create the command object if( FAILED( pIDBCreateCommand->CreateCommand( NULL,       IID_ICommandText,        ( IUnknown ** ) & pICommandText ) ) ) {       printf( &quot;Create command failed.\n&quot; ); return; }

pIDBCreateCommand->Release;

// provide the command, language and dialect if( FAILED( pICommandText->SetCommandText( DBGUID_DBSQL, bSQLString ) ) ) {       printf( &quot;Could not set CommandText\n&quot; ); return; }

if( FAILED( hr = pICommandText->Execute( NULL,        IID_IRowset,         NULL,         & cRowsAffected,         ( IUnknown ** ) & pIRowset ) ) ) {       printf( &quot;Execute failed\n&quot; ); return; }

pDBBindings = new DBBINDING[1];

pDBBindings[ 0 ].iOrdinal = 1; pDBBindings[ 0 ].obValue = 8; pDBBindings[ 0 ].obLength = 4; pDBBindings[ 0 ].obStatus = 0; pDBBindings[ 0 ].pTypeInfo = NULL; pDBBindings[ 0 ].pObject = NULL; pDBBindings[ 0 ].pBindExt = NULL; pDBBindings[ 0 ].dwPart = DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH; pDBBindings[ 0 ].dwMemOwner = DBMEMOWNER_CLIENTOWNED; pDBBindings[ 0 ].eParamIO = DBPARAMIO_NOTPARAM; pDBBindings[ 0 ].cbMaxLen = MAX_LEN; pDBBindings[ 0 ].dwFlags = 0; pDBBindings[ 0 ].wType = DBTYPE_WSTR; pDBBindings[ 0 ].bPrecision = 0; pDBBindings[ 0 ].bScale = 0;

pRowValues = new BYTE[ MAX_LEN ]; memset( pRowValues, 0, MAX_LEN );

// create an accessor to fetch the data with hr = pIRowset->QueryInterface( IID_IAccessor, ( void ** ) & pIAccessor);

if( FAILED( hr ) ) {       printf( &quot;QI for IAccessor failed\n&quot; ); return; }

if( FAILED( hr = pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA,            1,             pDBBindings,             sizeof( pDBBindings ),            & hAccessor,            NULL ) ) ) {       printf( &quot;CreateAccessor failed\n&quot; ); return; }

// process the rows while( TRUE ) {       hr = pIRowset->GetNextRows( 0, 0, 10, & cRowsObtained, & pRows );

// all done, there are no more rows to get if( cRowsObtained == 0 ) break;

// loop over rows obtained, getting data for each for( iRow = 0 ; iRow < cRowsObtained ; iRow++ ) {           hr = pIRowset->GetData( rghRows[ iRow ], hAccessor, pRowValues ); printf(&quot;Length of row[%d]:%d\n&quot;,iRow+1,*(pRowValues+4)); printf(&quot;Value of Col1:&quot;); for(int byteCnt=0;byteCnt<(*(pRowValues+4))-1;byteCnt++) printf( &quot;%x&quot;,(pRowValues+8)[byteCnt]); printf(&quot;\n\n&quot;); }       pIRowset->ReleaseRows( cRowsObtained, rghRows, NULL, NULL, NULL ); }   pIAccessor->ReleaseAccessor( hAccessor, NULL ); pIAccessor->Release; pIRowset->Release; pICommandText->Release; pIDBCreateSession->Release;

delete [] pDBBindings; delete [] pRowValues; if( pIDBInitialize ) if( ! FAILED( hr=pIDBInitialize->Uninitialize ) ) pIDBInitialize->Release; else printf( &quot;Uninitialize failed.\n Something didn't get released.\n&quot; ); }                     Build and run the project. Note that Oledb32.dll truncates the string at the null-termination character, so that the data that is retrieved is as follows: <pre class="fixed_text">  Length:6 Value:41042043 </li></ol>

You expect the following results: <pre class="fixed_text">        Length:10 Value:4104204300044

Additional query words: NULL termination truncation truncate DBTYPE_WSTR OLEDB Core Services

Keywords: kbbug kbfix KB313925

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.