ILockBytes::ReadAt
ReadAt reads a specified number of bytes starting at a specified offset from the beginning of the byte array.
Syntax
HRESULT ReadAt( ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead );
Parameters
Parameter | Description |
---|---|
ulOffset [in] |
Specifies the starting point from the beginning of the byte array for reading data |
pv [in] |
Pointer to the buffer into which the byte array is read. |
cb [in] |
Specifies the number of bytes of data to attempt to read from the byte array. |
pcbRead [out] |
Pointer to the location where this method will write the actual number of bytes read from the byte array. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes that were read. |
Return Value
Term | Definition |
---|---|
NOERROR |
The method succeeded. |
E_UNEXPECTED |
Rowset is in a "zombied" state. |
STG_E_INVALIDPOINTER |
A pointer that was passed was not valid. |
Remarks
The following example shows how to use the ILockBytes::ReadAt method to retrieve binary large object (BLOB) data. This example reads image data from the "Photo" column of the Employees table.
Example
// Declarations
HRESULT hr;
DBBINDING rgBindings[1];
DBPROP dbprop[1];
DBPROPSET dbpropset[1];
DBOBJECT dbObject;
BYTE pData[100]; //buffer for holding the ILockBytes pointer
HROW rghRows[1]; // Array of row handles obtained from the rowset object
HROW *prghRows = rghRows;
BYTE pBuffer[1000]; //Buffer for holding a chunck of BLOB data
ULARGE_INTEGER ulOffset;
ULONG cRows = 0;
IDBInitialize *pIDBInitialize = NULL;
IDBProperties *pIDBProperties = NULL;
IDBCreateSession *pIDBCreateSession = NULL;
IDBCreateCommand *pIDBCreateCommand = NULL;
ICommandText *pICommandText = NULL;
IAccessor *pIAccessor = NULL;
IRowset *pIRowset = NULL;
ILockBytes *pILockBytes = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
if (FAILED(hr = CoInitialize(NULL)))
{
return;
}
VariantInit(&dbprop[0].vValue);
// Create an instance of the OLE DB Provider
hr = CoCreateInstance(CLSID_SQLSERVERCE_3_0, 0, CLSCTX_INPROC_SERVER,
IID_IDBInitialize, (void**)&pIDBInitialize);
if(FAILED(hr))
{
//Send error-specific message and do error handling
goto Exit;
}
// Initialize a property with name of the database
// Open an exsiting database myDatabase
dbprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
dbprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
dbprop[0].vValue.vt = VT_BSTR;
dbprop[0].vValue.bstrVal = SysAllocString(L"\\windows\\MyDB.sdf");
if(NULL == dbprop[0].vValue.bstrVal)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
// Initialize the property set
dbpropset[0].guidPropertySet = DBPROPSET_DBINIT;
dbpropset[0].rgProperties = dbprop;
dbpropset[0].cProperties = sizeof(dbprop)/sizeof(dbprop[0]);
//Set initialization properties.
hr = pIDBInitialize->QueryInterface(IID_IDBProperties,
(void **)&pIDBProperties);
if(FAILED(hr))
{
goto Exit;
}
// Sets properties in the data source and initialization property groups
hr = pIDBProperties->SetProperties(1, dbpropset);
if(FAILED(hr))
{
goto Exit;
}
// Initializes a data source object
hr = pIDBInitialize->Initialize();
if(FAILED(hr))
{
goto Exit;
}
// Get the IDBCreateSession interface
hr = pIDBInitialize->QueryInterface(IID_IDBCreateSession,
(void**)&pIDBCreateSession);
if (FAILED(hr))
{
//Send error-specific message and do error handling
goto Exit;
}
// Get the interface to create a command
hr = pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand,
(IUnknown**) &pIDBCreateCommand);
if (FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
// Create the new command that uses parameters.
hr = pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**) &pICommandText);
if (FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
// Specify the command text using parameter markers in the query syntax.
// We know that this command will return 1 row and one image column (Photo).
hr = pICommandText->SetCommandText(DBGUID_DBSQL, L"SELECT Photo FROM Employees WHERE \"Employee ID\" = 2");
if (FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
hr = pICommandText->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown**) &pIRowset);
if(FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
// Create the acessor object and column specific bindings.
hr = pIRowset->QueryInterface(IID_IAccessor, (void**) &pIAccessor);
if (FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
// Create the bindings for the photo (BLOB) column
dbObject.dwFlags = STGM_READ;
dbObject.iid = IID_ILockBytes;
rgBindings[0].iOrdinal = 1;
rgBindings[0].obStatus = 0;
rgBindings[0].obLength = rgBindings[0].obStatus + sizeof(DBSTATUS);
rgBindings[0].obValue = rgBindings[0].obLength + sizeof(ULONG);
rgBindings[0].pTypeInfo = NULL;
rgBindings[0].pObject = &dbObject;
rgBindings[0].pBindExt = NULL;
rgBindings[0].dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
rgBindings[0].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBindings[0].eParamIO = DBPARAMIO_NOTPARAM;
rgBindings[0].cbMaxLen = sizeof(IUnknown*);
rgBindings[0].dwFlags = 0;
rgBindings[0].wType = DBTYPE_IUNKNOWN;
rgBindings[0].bPrecision = 0;
rgBindings[0].bScale = 0;
// Create accessor.
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, rgBindings,
0, &hAccessor, NULL);
if(FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
//Get the first row
hr = pIRowset->GetNextRows(NULL, 0, 1, &cRows, &prghRows);
if(FAILED(hr) || (0 == cRows))
{
//Send an error-specific message and do error handling.
goto Exit;
}
//Get the ILockBytes pointer
hr = pIRowset->GetData(rghRows[0], hAccessor, pData);
if(FAILED(hr))
{
//Send an error-specific message and do error handling.
goto Exit;
}
if(DBSTATUS_S_OK != *(DBSTATUS*)(pData + rgBindings[0].obStatus))
{
//Send an error-specific message and do error handling.
goto Exit;
}
// Get the ILockBytes pointer from the buffer.
pILockBytes = *(ILockBytes**)(pData + rgBindings[0].obValue);
// Initialize Offset.
ulOffset.QuadPart = 0;
// Retrieve data from the interface in chunks.
// The infinite loop, for(;;), will terminate when the ReadAt call fails
// or if less bytes are returned than were requested.
for(;;)
{
ULONG cbRead;
// Read data at the specified offset
hr = pILockBytes->ReadAt(ulOffset, pBuffer, sizeof(pBuffer)-sizeof(WCHAR),
&cbRead);
/////////////////////////////////////////////////////////////////////////
// Do some useful things here with the chunks of data
/////////////////////////////////////////////////////////////////////////
if(cbRead < sizeof(pBuffer)-sizeof(WCHAR) || FAILED(hr)) break;
ulOffset.QuadPart += cbRead;
}
//If more rows need to be read, then release the ILockBytes pointer and
// row handle here
Exit:
// When finished, clear the properties arrays and release interfaces.
// Uninitialize the environment.
return;
See Also
Reference
ILockBytes::SetSize
ILockBytes::Stat
ILockBytes::WriteAt
Other Resources
ILockBytes (SQL Server Compact Edition)