//+--------------------------------------------------------------------------- // // 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 #include "filllkb.hxx" #ifdef ASYNC #include #endif #if DBG == 1 DECLARE_INFOLEVEL(astg); #endif #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 #ifndef KACF_OLE32ENABLEASYNCDOCFILE #define KACF_OLE32ENABLEASYNCDOCFILE 0x00000200 #endif BOOL AllowAsyncDocfile() { // By default, StgOpenAsyncDocfileOnIFillLockBytes, // StgGetIFillLockBytesOnILockBytes, // StgGetIFillLockBytesOnFile are disabled return (BOOL)APPCOMPATFLAG(KACF_OLE32ENABLEASYNCDOCFILE); } STDAPI StgOpenAsyncDocfileOnIFillLockBytes(IFillLockBytes *pflb, DWORD grfMode, DWORD asyncFlags, IStorage **ppstgOpen) { if (!AllowAsyncDocfile()) return STG_E_UNIMPLEMENTEDFUNCTION; 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); } STDAPI StgGetIFillLockBytesOnILockBytes( ILockBytes *pilb, IFillLockBytes **ppflb) { if (!AllowAsyncDocfile()) return STG_E_UNIMPLEMENTEDFUNCTION; 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) { if (!AllowAsyncDocfile()) return STG_E_UNIMPLEMENTEDFUNCTION; 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; }