I have a stream in a compound storage. I want to read its data into a byte array. I'm confused about what I need to put in the second parameter of lpSrc->Read(). I want to read the ENTIRE file into my unsigned char* (byte*) array:
unsigned char* rawData;
LPSTREAM lpSrc = NULL;
HRESULT hrRet = STG_E_INVALIDPARAMETER;
TRY
{
USES_CONVERSION;
HRESULT hrSrc = pStg->GetStg()->OpenStream(CT2COLE(szStream),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrSrc != NOERROR)
{
hrRet = hrSrc;
}
else
{
ULONG ul;
hrRet = lpSrc->Read(rawData, /*???*/, &ul);
}
}
CATCH_ALL(e)
{
hrRet = STG_E_UNKNOWN;
}
END_CATCH_ALL
I've tried many variations on reading the stream, so I'm not entirely sure this is the way I should do it in the first place. How do i solve this problem?
I'm confused about what I need to put in the second parameter of lpSrc->Read().
The answer is in the documentation:
ISequentialStream::Read method
pv [out]
A pointer to the buffer which the stream data is read into.
cb [in]
The number of bytes of data to read from the stream object.
pcbRead [out]
A pointer to a ULONG variable that receives the actual number of bytes read from the stream object.
You have to specify the number of bytes you want to read from the stream into your buffer.
I want to read the ENTIRE file into my unsigned char* (byte*) array:
That means you have to know how many bytes are available in the stream in the first place. You get that from the IStream::Stat()
method. Then you have to allocate your rawData
buffer to that size before you can then read data into the buffer.
Try something like this:
#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)(-1))
#endif
unsigned char* rawData;
LPSTREAM lpSrc = NULL;
HRESULT hrRet = STG_E_INVALIDPARAMETER;
TRY
{
USES_CONVERSION;
hrRet = pStg->GetStg()->OpenStream(
CT2COLE(szStream),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrRet == S_OK)
{
STATSTG stat;
hrRet = lpSrc->Stat(&stat, STATFLAG_NONAME);
if (hrRet == S_OK)
{
if (stat.cbSize.QuadPart > SIZE_MAX)
{
hrRet = HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
}
else
{
size_t size = (size_t) stat.cbSize.QuadPart;
rawData = malloc(size);
if (!rawData)
{
hrRet = E_OUTOFMEMORY;
}
else
{
unsigned char *ptr = rawData;
size_t sizeLeft = size;
while (sizeLeft != 0)
{
ULONG ul;
hrRet = lpSrc->Read(ptr, (sizeLeft >= MAXDWORD) ? MAXDWORD : (DWORD) sizeLeft, &ul);
if (FAILED(hrRet) || (ul == 0)) break;
ptr += ul;
sizeLeft -= ul;
}
if (SUCCEEDED(hrRet))
{
if (sizeLeft != 0) size -= sizeLeft;
// use rawData up to size number of bytes as needed...
}
free(rawData);
}
}
}
lpSrc->Release();
}
}
CATCH_ALL(e)
{
hrRet = E_UNEXPECTED;
}
END_CATCH_ALL