如何两次打开一个复合文档?
Cline 2006-10-21 04:49:22 如何两次打开一个复合文档,第一次以读的方式打开,并且Keep一些IStorage接口指针.第二次以读写方式打开,然后先读取流中数把,最后写入新的数据.代码如下,运行到Ln95:时报"Access denied"错误.
如果把Ln42的共享方式改成STGM_SHARE_DENY_NONE,本行报"Invalid flags".
如果把Ln42行去掉,Ln95能成功.
//Create a compound file
const WCHAR* pwszFileName = L"C:\\Test.stg";
const WCHAR* pwszStorageName = L"TestStorage";
const WCHAR* pwszStreamName = L"TestStream";
CComPtr<IStorage> pRootStg;
HRESULT hr = ::StgCreateDocfile(pwszFileName, STGM_READWRITE|STGM_CREATE |STGM_SHARE_EXCLUSIVE, 0, &pRootStg) ;
ASSERT(SUCCEEDED(hr));
//Create a sub storage
CComPtr<IStorage> pSubStg;
hr = pRootStg->CreateStorage(pwszStorageName,STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &pSubStg);
ASSERT(SUCCEEDED(hr));
//Create a stream inside of the sub storage
CComPtr<IStream> pStream;
hr = pSubStg->CreateStream(pwszStreamName,STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0 , 0, &pStream);
ASSERT(SUCCEEDED(hr));
//Write some data to the stream
const TCHAR* pszTestData = _T("Test data");
ULONG ulWrittenLen = 0;
hr = pStream->Write(pszTestData, sizeof(TCHAR) * _tcslen(pszTestData), &ulWrittenLen);
ASSERT(SUCCEEDED(hr));
//Release all strorage and stream
pStream = NULL;
pSubStg = NULL;
pRootStg = NULL;
//Open this compound file with readable mode.
CComPtr<IStorage> pRootStgR;
CComPtr<IStorage> pSubStgR;
for(;;)
{
//Open root storage
hr = ::StgOpenStorage(pwszFileName, NULL, STGM_DIRECT_SWMR|STGM_READ|STGM_SHARE_DENY_NONE, NULL, 0, &pRootStgR);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
//Open sub storage
Ln42: hr = pRootStgR->OpenStorage(pwszStorageName, NULL, STGM_DIRECT_SWMR|STGM_READ|STGM_SHARE_EXCLUSIVE, NULL, 0, &pSubStgR);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
break;
}
//Open this compound file with writable mode
CComPtr<IStorage> pRootStgW;
CComPtr<IStorage> pSubStgW;
char* pszOldData = NULL;
for(;;)
{
//Open root storage
hr = ::StgOpenStorage(pwszFileName, NULL, STGM_DIRECT_SWMR|STGM_READWRITE|STGM_SHARE_DENY_WRITE, NULL, 0, &pRootStgW);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
//Open sub storage
hr = pRootStgW->OpenStorage(pwszStorageName, NULL, STGM_DIRECT_SWMR|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &pSubStgW);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
//Open stream
CComPtr<IStream> pStreamW;
hr = pSubStgW->OpenStream(pwszStreamName, NULL, STGM_DIRECT_SWMR|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &pStreamW);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
//Read old data
STATSTG Status;
hr = pStreamW->Stat(&Status, STATFLAG_DEFAULT);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
pszOldData = new char[Status.cbSize.LowPart + 1];
ULONG ulReadLen = 0;
hr = pStreamW->Read(pszOldData, Status.cbSize.LowPart, &ulReadLen);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
ASSERT(ulReadLen == Status.cbSize.LowPart);
pszOldData[Status.cbSize.LowPart] = '\0';
//Clean old data
ULARGE_INTEGER ZERO_INTEGER;
ZERO_INTEGER.HighPart = 0;
ZERO_INTEGER.LowPart = 0;
Ln95: hr = pStreamW->SetSize(ZERO_INTEGER);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
break;
//Write new data
const TCHAR* pszNewData = _T("New data");
hr = pStreamW->Write(pszNewData, sizeof(TCHAR) * _tcslen(pszNewData), &ulWrittenLen);
ASSERT(SUCCEEDED(hr));
break;
}
if(pszOldData)
delete[] pszOldData;