windows-nt/Source/XPSP1/NT/com/ole32/stg/async/docfile/asyncapi.cxx

374 lines
8.7 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1994.
//
// File: asyncapi.cxx
//
// Contents: APIs for async docfiles
//
// Classes:
//
// Functions:
//
// History: 19-Dec-95 PhilipLa Created
//
//----------------------------------------------------------------------------
#include "astghead.cxx"
#pragma hdrstop
#ifndef ASYNC
#define USE_FILELKB
#endif
#include "asyncapi.hxx"
#include "filllkb.hxx"
#ifdef USE_FILELKB
#include "filebyte.hxx"
#endif
#ifdef ASYNC
#include <expdf.hxx>
#endif
#if DBG == 1
DECLARE_INFOLEVEL(astg);
#endif
#ifdef ASYNC
#ifdef COORD
SCODE DfFromLB(CPerContext *ppc,
ILockBytes *plst,
DFLAGS df,
DWORD dwStartFlags,
SNBW snbExclude,
ITransaction *pTransaction,
CExposedDocFile **ppdfExp,
CLSID *pcid);
#else
SCODE DfFromLB(CPerContext *ppc,
ILockBytes *plst,
DFLAGS df,
DWORD dwStartFlags,
SNBW snbExclude,
CExposedDocFile **ppdfExp,
CLSID *pcid);
#endif //COORD
#endif //ASYNC
STDAPI StgOpenAsyncDocfileOnIFillLockBytes(IFillLockBytes *pflb,
DWORD grfMode,
DWORD asyncFlags,
IStorage **ppstgOpen)
{
#ifdef ASYNC
SCODE sc;
ILockBytes *pilb;
IStorage *pstg;
IFileLockBytes *pfl;
sc = ValidateInterface(pflb, IID_IFillLockBytes);
if (FAILED(sc))
{
return sc;
}
sc = ValidateOutPtrBuffer(ppstgOpen);
if (FAILED(sc))
{
return sc;
}
*ppstgOpen = NULL;
//We're going to do a song and dance here because the ILockBytes
//implementation we return from StgGetIFillLockBytesOnFile won't
//let you QI for ILockBytes (because those methods aren't thread safe,
//among other things). Instead we QI for a private interface and do
//a direct cast if that succeeds. Otherwise we're on someone else's
//implementation so we just go right for ILockBytes.
sc = pflb->QueryInterface(IID_IFileLockBytes, (void **)&pfl);
if (FAILED(sc))
{
sc = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
if (FAILED(sc))
{
return sc;
}
}
else
{
pilb = (ILockBytes *)((CFileStream *)pfl);
}
//If we're operating on the docfile owned ILockBytes, then we can
// go directly to DfFromLB instead of using StgOpenStorageOnILockBytes
// which will avoid creating another shared heap.
if (pfl != NULL)
{
pfl->Release();
pilb = NULL;
CFileStream *pfst = (CFileStream *)pflb;
CPerContext *ppc = pfst->GetContextPointer();
#ifdef MULTIHEAP
CSafeMultiHeap smh(ppc);
#endif
#ifdef COORD
astgChk(DfFromLB(ppc,
pfst,
ModeToDFlags(grfMode),
pfst->GetStartFlags(),
NULL,
NULL,
(CExposedDocFile **)&pstg,
NULL));
#else
astgChk(DfFromLB(ppc,
pfst,
ModeToDFlags(grfMode),
pfst->GetStartFlags(),
NULL,
(CExposedDocFile **)&pstg,
NULL));
#endif
//Note: Don't release the ILB reference we got from the QI
// above, since DfFromLB recorded that pointer but didn't
// AddRef it.
pfst->AddRef(); // CExposedDocfile will release this reference
}
else
{
IFillLockBytes *pflb2;
if (SUCCEEDED(pilb->QueryInterface(IID_IDefaultFillLockBytes,
(void **)&pflb2)))
{
CFillLockBytes *pflbDefault = (CFillLockBytes *)pflb;
CPerContext *ppc;
pflb2->Release();
astgChk(StgOpenStorageOnILockBytes(pilb,
NULL,
grfMode,
NULL,
0,
&pstg));
//Get PerContext pointer from pstg
ppc = ((CExposedDocFile *)pstg)->GetContext();
pflbDefault->SetContext(ppc);
}
else
{
astgChk(StgOpenStorageOnILockBytes(pilb,
NULL,
grfMode,
NULL,
0,
&pstg));
}
pilb->Release();
pilb = NULL;
}
astgChkTo(EH_stg, ((CExposedDocFile *)pstg)->InitConnection(NULL));
((CExposedDocFile *)pstg)->SetAsyncFlags(asyncFlags);
*ppstgOpen = pstg;
return NOERROR;
EH_stg:
pstg->Release();
Err:
if (pilb != NULL)
pilb->Release();
if (sc == STG_E_PENDINGCONTROL)
{
sc = E_PENDING;
}
return ResultFromScode(sc);
#else
HRESULT hr;
ILockBytes *pilb;
IStorage *pstg;
hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
if (FAILED(hr))
{
return hr;
}
hr = StgOpenStorageOnILockBytes(pilb,
NULL,
grfMode,
NULL,
0,
&pstg);
pilb->Release();
if (FAILED(hr))
{
if (hr == STG_E_PENDINGCONTROL)
{
hr = E_PENDING;
}
return hr;
}
BOOL fDefault = FALSE;
IFillLockBytes *pflbDefault;
hr = pflb->QueryInterface(IID_IDefaultFillLockBytes,
(void **)&pflbDefault);
if (SUCCEEDED(hr))
{
fDefault = TRUE;
pflbDefault->Release();
}
*ppstgOpen = new CAsyncRootStorage(pstg, pflb, fDefault);
if (*ppstgOpen == NULL)
{
return STG_E_INSUFFICIENTMEMORY;
}
else
{
((CAsyncRootStorage *)(*ppstgOpen))->SetAsyncFlags(asyncFlags);
}
return NOERROR;
#endif //ASYNC
}
STDAPI StgGetIFillLockBytesOnILockBytes( ILockBytes *pilb,
IFillLockBytes **ppflb)
{
SCODE sc = S_OK;
CFillLockBytes *pflb = NULL;
sc = ValidateOutPtrBuffer(ppflb);
if (FAILED(sc))
{
return sc;
}
sc = ValidateInterface(pilb, IID_ILockBytes);
if (FAILED(sc))
{
return sc;
}
pflb = new CFillLockBytes(pilb);
if (pflb == NULL)
{
return STG_E_INSUFFICIENTMEMORY;
}
sc = pflb->Init();
if (FAILED(sc))
{
pflb->Release();
*ppflb = NULL;
return sc;
}
*ppflb = pflb;
return NOERROR;
}
STDAPI StgGetIFillLockBytesOnFile(OLECHAR const *pwcsName,
IFillLockBytes **ppflb)
{
#ifndef USE_FILELKB
SCODE sc;
IMalloc *pMalloc;
CFileStream *plst;
CFillLockBytes *pflb;
CPerContext *ppc;
astgChk(ValidateNameW(pwcsName, _MAX_PATH));
astgChk(ValidateOutPtrBuffer(ppflb));
DfInitSharedMemBase();
astgHChk(DfCreateSharedAllocator(&pMalloc, FALSE));
astgMemTo(EH_Malloc, plst = new (pMalloc) CFileStream(pMalloc));
astgChkTo(EH_plst, plst->InitGlobal(RSF_CREATE,
DF_DIRECT | DF_READ |
DF_WRITE | DF_DENYALL));
astgChkTo(EH_plst, plst->InitFile(pwcsName));
astgMemTo(EH_plstInit, ppc = new (pMalloc) CPerContext(pMalloc));
astgChkTo(EH_ppc, ppc->InitNewContext());
//We want 0 normal references on the per context, and one reference
// to the shared memory.
ppc->DecRef();
plst->SetContext(ppc);
plst->StartAsyncMode();
astgChkTo(EH_plstInit, ppc->InitNotificationEvent(plst));
*ppflb = (IFillLockBytes *)plst;
return S_OK;
EH_ppc:
delete ppc;
EH_plstInit:
plst->Delete();
EH_plst:
plst->Release();
EH_Malloc:
pMalloc->Release();
Err:
return sc;
#else
SCODE sc;
CFileLockBytes *pflb = NULL;
pflb = new CFileLockBytes;
if (pflb == NULL)
{
return STG_E_INSUFFICIENTMEMORY;
}
sc = pflb->Init(pwcsName);
if (SUCCEEDED(sc))
{
sc = StgGetIFillLockBytesOnILockBytes(pflb, ppflb);
}
return sc;
#endif // ASYNC
}
#if DBG == 1
STDAPI StgGetDebugFileLockBytes(OLECHAR const *pwcsName, ILockBytes **ppilb)
{
#ifdef ASYNC
return STG_E_UNIMPLEMENTEDFUNCTION;
#else
SCODE sc;
CFileLockBytes *pflb;
*ppilb = NULL;
pflb = new CFileLockBytes;
if (pflb == NULL)
{
return STG_E_INSUFFICIENTMEMORY;
}
sc = pflb->Init(pwcsName);
if (FAILED(sc))
{
delete pflb;
pflb = NULL;
}
*ppilb = pflb;
return sc;
#endif // ASYNC
}
#endif