//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1991 - 1992. // // File: filest.cxx // // Contents: Generic 16/32 filestream code // // History: 20-Nov-91 DrewB Created // //--------------------------------------------------------------- #include #pragma hdrstop #include //+--------------------------------------------------------------------------- // // Member: CFileStream::CFileStream, public // // Synopsis: Empty object constructor // // History: 26-Oct-92 DrewB Created // //---------------------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_CFS) #endif CFileStream::CFileStream(IMalloc * const pMalloc) : _pMalloc(pMalloc) { _cReferences = 1; _hFile = INVALID_FH; _hReserved = INVALID_FH; _pgfst = NULL; _grfLocal = 0; _sig = CFILESTREAM_SIG; #if WIN32 == 100 || WIN32 > 200 _hMapObject = NULL; _pbBaseAddr = NULL; _cbFileSize = 0; #endif #ifdef WIN32 _ulLowPos = 0xffffffff; #if DBG == 1 _ulSeeks = 0; _ulRealSeeks = 0; #endif #endif #ifdef ASYNC _ppc = NULL; #endif } //+-------------------------------------------------------------- // // Member: CFileStream::InitFlags, public // // Synopsis: Constructor for flags only // // Arguments: [dwStartFlags] - Startup flags // [df] - Permissions // // History: 08-Apr-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_InitFlags) #endif SCODE CFileStream::InitFlags(DWORD dwStartFlags, DFLAGS df) { SCODE sc = S_OK; CGlobalFileStream *pgfstTemp; olMem(pgfstTemp = new (_pMalloc) CGlobalFileStream(_pMalloc, NULL, df, dwStartFlags)); _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfstTemp); _pgfst->Add(this); // Fall through EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CFileStream::InitFromGlobal, public // // Synopsis: Initializes a filestream with a global filestream // // Arguments: [pgfst] - Global object // // History: 26-Oct-92 DrewB Created // //---------------------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_InitFromGlobal) #endif void CFileStream::InitFromGlobal(CGlobalFileStream *pgfst) { _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfst); _pgfst->AddRef(); _pgfst->Add(this); } //+-------------------------------------------------------------- // // Member: CFileStream::vRelease, public // // Synopsis: PubList support // // History: 19-Aug-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_vRelease) #endif ULONG CFileStream::vRelease(void) { LONG lRet; olDebugOut((DEB_ITRACE, "In CFileStream::vRelease:%p()\n", this)); olAssert(_cReferences > 0); lRet = InterlockedDecrement(&_cReferences); if (lRet == 0) { #ifdef ASYNC if (_ppc != NULL) { #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif SCODE sc; sc = TakeSem(); olAssert(SUCCEEDED(sc)); CPerContext *ppc = _ppc; _ppc = NULL; delete this; #ifdef MULTIHEAP BOOL fLastRef = ppc->LastRef(); #endif ppc->ReleaseSharedMem(); #ifdef MULTIHEAP if (fLastRef) g_smAllocator.Uninit(); #endif } else #endif delete this; } return (ULONG)lRet; olDebugOut((DEB_ITRACE, "Out CFileStream::vRelease\n")); } //+-------------------------------------------------------------- // // Member: CFileStream::Release, public // // Synopsis: Releases resources for an LStream // // Returns: Appropriate status code // // History: 20-Feb-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_Release) #endif STDMETHODIMP_(ULONG) CFileStream::Release(void) { ULONG ulRet; olDebugOut((DEB_ITRACE, "In CFileStream::Release()\n")); #ifdef CFS_SECURE if (FAILED(Validate()) || _cReferences < 1) return 0; #else olAssert(_cReferences >= 1); #endif ulRet = CFileStream::vRelease(); olDebugOut((DEB_ITRACE, "Out CFileStream::Release\n")); return ulRet; } //+-------------------------------------------------------------- // // Member: CFileStream::AddRef, public // // Synopsis: Increases the ref count // // History: 27-Feb-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_AddRef) #endif STDMETHODIMP_(ULONG) CFileStream::AddRef(void) { ULONG ulRet; olDebugOut((DEB_ITRACE, "In CFileStream::AddRef()\n")); #ifdef CFS_SECURE if (FAILED(Validate())) return 0; #endif CFileStream::vAddRef(); ulRet = _cReferences; olDebugOut((DEB_ITRACE, "Out CFileStream::AddRef, %ld\n", _cReferences)); return ulRet; } //+-------------------------------------------------------------- // // Member: CFileStream::GetName, public // // Synopsis: Returns the internal path // // Arguments: [ppwcsName] - Name pointer return // // Returns: Appropriate status code // // Modifies: [ppwcsName] // // History: 24-Mar-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_GetName) #endif SCODE CFileStream::GetName(WCHAR **ppwcsName) { SCODE sc; olDebugOut((DEB_ITRACE, "In CFileStream::GetName(%p)\n", ppwcsName)); olAssert(_pgfst->HasName()); olChk(DfAllocWC(lstrlenW(_pgfst->GetName())+1, ppwcsName)); lstrcpyW(*ppwcsName, _pgfst->GetName()); olDebugOut((DEB_ITRACE, "Out CFileStream::GetName => %ws\n", *ppwcsName)); EH_Err: return sc; } //+-------------------------------------------------------------- // // Member: CFileStream::QueryInterface, public // // Synopsis: Returns an object for the requested interface // // Arguments: [iid] - Interface ID // [ppvObj] - Object return // // Returns: Appropriate status code // // Modifies: [ppvObj] // // History: 26-Mar-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_QueryInterface) #endif STDMETHODIMP CFileStream::QueryInterface(REFIID iid, void **ppvObj) { SCODE sc; olDebugOut((DEB_ITRACE, "In CFileStream::QueryInterface(?, %p)\n", ppvObj)); #ifdef CFS_SECURE olChk(ValidateOutPtrBuffer(ppvObj)); *ppvObj = NULL; olChk(ValidateIid(iid)); olChk(Validate()); #endif sc = S_OK; if (IsEqualIID(iid, IID_IFileLockBytes) || IsEqualIID(iid, IID_IUnknown)) { *ppvObj = (IFileLockBytes *)this; CFileStream::vAddRef(); } else if (IsEqualIID(iid, IID_ILockBytes)) { *ppvObj = (ILockBytes *)this; CFileStream::vAddRef(); } else if (IsEqualIID(iid, IID_IMarshal)) { *ppvObj = (IMarshal *)this; CFileStream::vAddRef(); } #ifdef ASYNC else if (IsEqualIID(iid, IID_IFillLockBytes)) { *ppvObj = (IFillLockBytes *)this; CFileStream::vAddRef(); } else if (IsEqualIID(iid, IID_IFillInfo)) { *ppvObj = (IFillInfo *)this; CFileStream::vAddRef(); } #endif #if WIN32 >= 300 else if (IsEqualIID(iid, IID_IAccessControl)) { DWORD grfMode = 0; if (_pgfst->GetDFlags() & DF_TRANSACTED) grfMode |= STGM_TRANSACTED; if (_pgfst->GetDFlags() & DF_ACCESSCONTROL) grfMode |= STGM_EDIT_ACCESS_RIGHTS; // check if underlying file system supports security if (SUCCEEDED(sc = InitAccessControl(_hFile, grfMode, TRUE, NULL))) { *ppvObj = (IAccessControl *) this; CFileStream::vAddRef(); } else sc = E_NOINTERFACE; } #endif else { sc = E_NOINTERFACE; } olDebugOut((DEB_ITRACE, "Out CFileStream::QueryInterface => %p\n", ppvObj)); #ifdef CFS_SECURE EH_Err: #endif return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CFileStream::Unmarshal, public // // Synopsis: Creates a duplicate FileStream // // Arguments: [ptsm] - Marshal stream // [ppv] - New filestream return // [mshlflags] - Marshal flags // // Returns: Appropriate status code // // Modifies: [ppv] // // History: 14-Apr-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_Unmarshal) // Marshal_Text #endif SCODE CFileStream::Unmarshal(IStream *pstm, void **ppv, DWORD mshlflags) { SCODE sc; WCHAR wcsPath[_MAX_PATH]; CFileStream *pfst; CGlobalFileStream *pgfst; olDebugOut((DEB_ITRACE, "In CFileStream::Unmarshal(%p, %p, %lu)\n", pstm, ppv, mshlflags)); #ifdef ASYNC CPerContext pcSharedMemory(NULL); CGlobalContext *pgc; CPerContext *ppc; ContextId cntxid; CDfMutex mtx; BOOL fIsAsync; ULONG cbRead; olChk(pstm->Read(&fIsAsync, sizeof(BOOL), &cbRead)); if (cbRead != sizeof(BOOL)) { olErr(EH_Err, STG_E_READFAULT); } if (fIsAsync) { #ifdef MULTIHEAP olChk(UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid)); #endif olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pgc)); TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH]; pgc->GetMutexName(atcMutexName); olChkTo(EH_pgc, mtx.Init(atcMutexName)); olChkTo(EH_pgc, mtx.Take(INFINITE)); #ifdef MULTIHEAP olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, FALSE, FALSE, cntxid, FALSE)); #else olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, FALSE, FALSE, FALSE)); #endif olChkTo(EH_ppc, UnmarshalPointer(pstm, (void **)&pgfst)); pfst = pgfst->Find(GetCurrentContextId()); if (pfst) { pfst->AddRef(); // Demand scratch: If this is a scratch ILockBytes, // it may need to be initialized, since a transacted // storage above this object may have been opened // after a direct root mode storage was marshaled if (pgfst->HasName()) { olChkTo(EH_pfst, pfst->InitUnmarshal(NULL)); } #ifdef DCOM if (mshlflags == MSHLFLAGS_NORMAL) { pgc->Release(); } #endif ppc->Release(); } else { olMemTo(EH_pgfst, pfst = new (pgfst->GetMalloc()) CFileStream(pgfst->GetMalloc())); pfst->InitFromGlobal(pgfst); if (pgfst->HasName()) { lstrcpyW(wcsPath, pgfst->GetName()); olChkTo(EH_pfst, pfst->InitUnmarshal(wcsPath)); } pfst->SetContext(ppc); //We only need a reference on the shared mem portion of // the per context, not the whole thing. ppc->DecRef(); #ifdef DCOM if (mshlflags == MSHLFLAGS_NORMAL) { pgc->Release(); } #endif } mtx.Release(); } else { #endif olChk(UnmarshalPointer(pstm, (void **)&pgfst)); pfst = pgfst->Find(GetCurrentContextId()); if (pfst) { pfst->AddRef(); // Demand scratch: If this is a scratch ILockBytes, // it may need to be initialized, since a transacted // storage above this object may have been opened // after a direct mode root storage was marshaled if (pgfst->HasName()) { olChkTo(EH_pfst, pfst->InitUnmarshal(NULL)); } } else { olMemTo(EH_pgfst, pfst = new (pgfst->GetMalloc()) CFileStream(pgfst->GetMalloc())); pfst->InitFromGlobal(pgfst); if (pgfst->HasName()) { lstrcpyW(wcsPath, pgfst->GetName()); olChkTo(EH_pfst, pfst->InitUnmarshal(wcsPath)); } } #ifdef ASYNC } #endif *ppv = (void *)pfst; olDebugOut((DEB_ITRACE, "Out CFileStream::Unmarshal => %p\n", *ppv)); EH_pfst: if (FAILED(sc)) pfst->Release(); EH_pgfst: #ifdef DCOM if (mshlflags == MSHLFLAGS_NORMAL) pgfst->Release(); #endif #ifdef ASYNC return sc; EH_ppc: ppc->Release(); EH_mtx: mtx.Release(); EH_pgc: if (mshlflags == MSHLFLAGS_NORMAL) { pgc->Release(); } EH_mem: //BUGBUG: Should we really be doing this? #ifdef MULTIHEAP pcSharedMemory.SetThreadAllocatorState(NULL); g_smAllocator.Uninit(); // delete the file mapping in error case g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL); #endif #endif //ASYNC EH_Err: return sc; } //+-------------------------------------------------------------- // // Member: CFileStream::GetUnmarshalClass, public // // Synopsis: Returns the class ID // // Arguments: [riid] - IID of object // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Unreferenced // [pcid] - CLSID return // // Returns: Appropriate status code // // Modifies: [pcid] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_GetUnmarshalClass) #endif STDMETHODIMP CFileStream::GetUnmarshalClass(REFIID riid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPCLSID pcid) { SCODE sc; olDebugOut((DEB_ITRACE, "In CFileStream::GetUnmarshalClass(" "riid, %p, %lu, %p, %lu, %p)\n", pv, dwDestContext, pvDestContext, mshlflags, pcid)); UNREFERENCED_PARM(pv); UNREFERENCED_PARM(mshlflags); #ifdef CFS_SECURE olChk(ValidateOutBuffer(pcid, sizeof(CLSID))); memset(pcid, 0, sizeof(CLSID)); olChk(ValidateIid(riid)); if (dwDestContext != 0 || pvDestContext != NULL) olErr(EH_Err, STG_E_INVALIDFLAG); olChk(Validate()); #endif *pcid = CLSID_DfMarshal; sc = S_OK; olDebugOut((DEB_ITRACE, "Out CFileStream::GetUnmarshalClass\n")); #ifdef CFS_SECURE EH_Err: #endif return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CFileStream::GetMarshalSizeMax, public // // Synopsis: Returns the size needed for the marshal buffer // // Arguments: [iid] - IID of object being marshaled // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Marshal flags // [pcbSize] - Size return // // Returns: Appropriate status code // // Modifies: [pcbSize] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_GetMarshalSizeMax) #endif STDMETHODIMP CFileStream::GetMarshalSizeMax(REFIID iid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPDWORD pcbSize) { SCODE sc; UNREFERENCED_PARM(pv); olChk(Validate()); sc = GetStdMarshalSize(iid, IID_ILockBytes, dwDestContext, pvDestContext, mshlflags, pcbSize, sizeof(CFileStream *), #ifdef ASYNC NULL, FALSE, _ppc, #else NULL, #endif FALSE); EH_Err: return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CFileStream::MarshalInterface, public // // Synopsis: Marshals a given object // // Arguments: [pstStm] - Stream to write marshal data into // [iid] - Interface to marshal // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Marshal flags // // Returns: Appropriate status code // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_MarshalInterface) #endif STDMETHODIMP CFileStream::MarshalInterface(IStream *pstStm, REFIID iid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags) { SCODE sc; #ifdef ASYNC BOOL fIsAsync = (_ppc != NULL); #endif olDebugOut((DEB_ITRACE, "In CFileStream::MarshalInterface(" "%p, iid, %p, %lu, %p, %lu)\n", pstStm, pv, dwDestContext, pvDestContext, mshlflags)); UNREFERENCED_PARM(pv); #ifdef CFS_SECURE if (dwDestContext != 0 || pvDestContext != NULL) olErr(EH_Err, STG_E_INVALIDFLAG); olChk(Validate()); #endif #if WIN32 == 100 || WIN32 > 200 TurnOffMapping(); #endif olChk(StartMarshal(pstStm, iid, IID_ILockBytes, mshlflags)); #ifdef ASYNC ULONG cbWritten; olHChk(pstStm->Write(&fIsAsync, sizeof(BOOL), &cbWritten)); if (cbWritten != sizeof(BOOL)) { olErr(EH_Err, STG_E_WRITEFAULT); } if (fIsAsync) { #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); olChk(MarshalSharedMemory(pstStm, _ppc)); #endif olChk(MarshalContext(pstStm, _ppc, dwDestContext, pvDestContext, mshlflags, FALSE, FALSE)); olChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst))); #ifdef WIN32 if (mshlflags != MSHLFLAGS_TABLEWEAK) _pgfst->AddRef(); #endif } else #endif { olChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst))); #ifdef WIN32 if (mshlflags != MSHLFLAGS_TABLEWEAK) _pgfst->AddRef(); #endif } olDebugOut((DEB_ITRACE, "Out CFileStream::MarshalInterface\n")); EH_Err: return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CFileStream::UnmarshalInterface, public // // Synopsis: Non-functional // // Arguments: [pstStm] - // [iid] - // [ppvObj] - // // Returns: Appropriate status code // // Modifies: [ppvObj] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_UnmarshalInterface) #endif STDMETHODIMP CFileStream::UnmarshalInterface(IStream *pstStm, REFIID iid, void **ppvObj) { return ResultFromScode(STG_E_INVALIDFUNCTION); } //+-------------------------------------------------------------- // // Member: CFileStream::StaticReleaseMarshalData, public static // // Synopsis: Releases any references held in marshal data // // Arguments: [pstStm] - Marshal data stream // // Returns: Appropriate status code // // History: 02-Feb-94 DrewB Created // // Notes: Assumes standard marshal header has already been read // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_ReleaseMarshalData) #endif #ifdef WIN32 SCODE CFileStream::StaticReleaseMarshalData(IStream *pstStm, DWORD mshlflags) { SCODE sc; CGlobalFileStream *pgfst; olDebugOut((DEB_ITRACE, "In CFileStream::StaticReleaseMarshalData:(" "%p, %lX)\n", pstStm, mshlflags)); #ifdef ASYNC BOOL fIsAsync; ULONG cbRead; olChk(pstStm->Read(&fIsAsync, sizeof(BOOL), &cbRead)); if (cbRead != sizeof(BOOL)) { olErr(EH_Err, STG_E_READFAULT); } if (fIsAsync) { #ifdef MULTIHEAP ContextId cntxid; CPerContext pcSharedMemory(NULL); // bootstrap object olChk(UnmarshalSharedMemory(pstStm, mshlflags, &pcSharedMemory, &cntxid)); #endif olChk(ReleaseContext(pstStm, FALSE, FALSE, mshlflags)); } #endif olChk(UnmarshalPointer(pstStm, (void **)&pgfst)); if (mshlflags != MSHLFLAGS_TABLEWEAK) pgfst->Release(); olDebugOut((DEB_ITRACE, "Out CFileStream::StaticReleaseMarshalData\n")); EH_Err: return sc; } #endif //+-------------------------------------------------------------- // // Member: CFileStream::ReleaseMarshalData, public // // Synopsis: Non-functional // // Arguments: [pstStm] - // // Returns: Appropriate status code // // History: 18-Sep-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_ReleaseMarshalData) #endif #ifdef WIN32 STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm) { SCODE sc; DWORD mshlflags; IID iid; olDebugOut((DEB_ITRACE, "In CFileStream::ReleaseMarshalData:%p(%p)\n", this, pstStm)); #ifdef CFS_SECURE olChk(Validate()); #endif olChk(SkipStdMarshal(pstStm, &iid, &mshlflags)); olAssert(IsEqualIID(iid, IID_ILockBytes)); sc = StaticReleaseMarshalData(pstStm, mshlflags); olDebugOut((DEB_ITRACE, "Out CFileStream::ReleaseMarshalData\n")); EH_Err: return ResultFromScode(sc); } #else STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm) { return ResultFromScode(STG_E_INVALIDFUNCTION); } #endif //+-------------------------------------------------------------- // // Member: CFileStream::DisconnectObject, public // // Synopsis: Non-functional // // Arguments: [dwReserved] - // // Returns: Appropriate status code // // History: 18-Sep-92 DrewB Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_DisconnectObject) // invalid #endif STDMETHODIMP CFileStream::DisconnectObject(DWORD dwReserved) { return ResultFromScode(STG_E_INVALIDFUNCTION); } //+-------------------------------------------------------------- // // Member: CFileStream::GetLocksSupported, public // // Synopsis: Return lock capabilities // // Arguments: [pdwLockFlags] -- place holder for lock flags // // Returns: Appropriate status code // // History: 12-Jul-93 AlexT Created // //--------------------------------------------------------------- #ifdef CODESEGMENTS #pragma code_seg(SEG_CFS_GetLocksSupported) #endif STDMETHODIMP CFileStream::GetLocksSupported(DWORD *pdwLockFlags) { *pdwLockFlags = LOCK_EXCLUSIVE | LOCK_ONLYONCE; return(ResultFromScode(S_OK)); }