NT4/private/ole32/stg/exp/filest.cxx
2020-09-30 17:12:29 +02:00

955 lines
25 KiB
C++

//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 1992.
//
// File: filest.cxx
//
// Contents: Generic 16/32 filestream code
//
// History: 20-Nov-91 DrewB Created
//
//---------------------------------------------------------------
#include <exphead.cxx>
#pragma hdrstop
#include <marshl.hxx>
//+---------------------------------------------------------------------------
//
// 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));
}