I am working with a project which handles large compound file. Now I
face a problem with IStream::Write().
IStream::Write()retuns an error STG_E_DOCFILETOOLARGE (Error:"The
compound file is too large for the current implementation").
I am trying to write in a compound file created with 512 Byte sectors
(Info MSDN see below). The current file size is about 300 MByte and
the number of streams are about 100000 ! The error occurs only with
Win 2000 SP3 and XP SP1. In Win NT 4.0 SP6a it works !!! When I create
the file with 4096 Byte sectors in StgCreateStorageEx, IStream::Write
works for Win 2000 and XP too. Now my question: Is this a bug?
Info from MSDN Library:
The compound file implementation can be configured to use 512 or 4096
byte sectors, as defined in the STGOPTIONS structure.
File size limits:
512: 2 gigabytes (GB)
4096: Up to file system limits
Number of elements in a file:
512: Unlimited, but performance may degrade if
elements number in the thousands
4096: Unlimited
A Code Snipshot is given below -
bool Create(CComBSTR cbstr)
{
STGOPTIONS stgopts;
stgopts.usVersion = 1;// Win2000: 1, WinXP: STGOPTIONS_VERSION =
2
stgopts.reserved = 0;
stgopts.ulSectorSize = 512; // 512 or 4096
stgopts.pwcsTemplateFile = NULL;
CComPtr<IStorage> cptrIStorageRoot;
HRESULT hr = StgCreateStorageEx(cbstr,
STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
STGFMT_DOCFILE, 0,
&stgopts,
NULL,
__uuidof(IStorage),
(void**)&cptrIStorageRoot);
if (FAILED(hr)) return false;
int iSignalCount = 6;
int iStreamCount = 100000;
int iStreamSize = 1024;
DWORD grfMode = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
std::vector< CComPtr<IStorage> > vec_cptrIStorages;
vec_cptrIStorages.resize(iSignalCount);
WCHAR wcDataStorage[32];
for (int i = 0; i < iSignalCount; i++)
{
swprintf(wcDataStorage, L"SignalTest%d", i);
hr = cptrIStorageRoot->CreateStorage(wcDataStorage, grfMode, 0, 0,
&vec_cptrIStorages[i]);
if (FAILED(hr)) return false;
}
WCHAR wcDataStream[32];
for (int i = 0; i < iSignalCount; i++)
{
for (int j = 0; j < iStreamCount; j++)
{
CComPtr<IStream> cptrIStream;
swprintf(wcDataStream, L"StreamTest%d", j);
hr = vec_cptrIStorages[i]->CreateStream(wcDataStream,
grfMode,
0,
0,
&cptrIStream);
if (FAILED(hr)) return false;
}
}
BYTE* pbData = new BYTE[iStreamSize];
ULONG ulWritten;
for (int j = 0; j < iStreamCount; j++)
{
for (int i = 0; i < iSignalCount; i++)
{
CComPtr<IStream> cptrIStream;
swprintf(wcDataStream, L"StreamTest%d", j);
hr = vec_cptrIStorages[i]->OpenStream(wcDataStream,
0,
grfMode,
0,
&cptrIStream);
if (FAILED(hr)) return false;
hr = cptrIStream->Write(pbData, iStreamSize, &ulWritten);
ASSERT(SUCCEEDED(hr));
if (FAILED(hr))
{
CString cstrMessage;
cstrMessage.Format(_T("Error IStream::Write %X at Stream %d Signal
%d"), hr, j, i);
AfxMessageBox(cstrMessage);
return false;
}
}
}
if (pbData) delete [] pbData;
AfxMessageBox(_T("Succeeded!!!"));
return true;
}
We are using Visual C++ 7.0.
Example code uses:
Number of Storages: 6
Number of Streams: 100000 per storage
Stream size: 1024 Byte
StgCreateStorageEx (Win XP SP1 or Win 2000 SP3):
With 512 Byte cluster: Error at file size grows to 347 MByte.
With 4096 Byte cluster: Succeeded => File Size is 696 MByte.
StgCreateDocFile (Win NT SP6a):
Succeeded !!!
Is this a bug or any limitation ? When should I use 4096 Byte cluster?
Bye.
Mainul Hossain
Polytec GmbH
Germany