|
|
//+---------------------------------------------------------------------------
//
// 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
|