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

966 lines
28 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: filstm.cxx
//
// Contents: CNtFileStream implementation
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
#include "headers.cxx"
#pragma hdrstop
#include "filstm.hxx"
#define ValidateLockType(lt) \
((lt) == LOCK_EXCLUSIVE || (lt) == LOCK_ONLYONCE)
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::QueryInterface, public
//
// Synopsis: Returns an object for the requested interface
//
// Arguments: [iid] - Interface ID
// [ppvObj] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppvObj]
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::QueryInterface(REFIID iid, void **ppvObj)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In CNtFileStream::QueryInterface:%p(riid, %p)\n",
this, ppvObj));
if (!IsValidIid(iid))
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
ssChk(Validate());
if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
{
*ppvObj = (IStream *)this;
CNtFileStream::AddRef();
}
else if(IsEqualIID(iid, IID_IOverlappedStream))
{
*ppvObj = (IOverlappedStream *) this;
CNtFileStream::AddRef();
}
else
{
sc = E_NOINTERFACE;
*ppvObj = NULL;
}
ssDebugOut((DEB_TRACE, "Out CNtFileStream::QueryInterface => %p\n",
*ppvObj));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::CNtFileStream, public
//
// Synopsis: Empty object constructor
//
// History: 30-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
CNtFileStream::CNtFileStream(void)
{
ssDebugOut((DEB_ITRACE, "In CNtFileStream::CNtFileStream:%p()\n", this));
_sig = 0;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::CNtFileStream\n"));
ENLIST_TRACKING(CNtFileStream);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::InitCommon, private
//
// Synopsis: Common initialization code
//
// Arguments: [co] - For detecting creation flags
//
// Returns: Appropriate status code
//
// History: 28-Jul-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE CNtFileStream::InitCommon(CREATEOPEN co)
{
NTSTATUS nts;
SCODE sc;
IO_STATUS_BLOCK iosb;
FILE_POSITION_INFORMATION fpi;
FILE_END_OF_FILE_INFORMATION feofi;
ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitCommon:%p(%d)\n",
this, co));
// If we're supposed to be creating, truncate
// STGM_CREATE must have been passed since FAILIFTHERE always will fail
if (co == CO_CREATE)
{
feofi.EndOfFile.LowPart = 0;
feofi.EndOfFile.HighPart = 0;
nts = NtSetInformationFile(_h, &iosb, &feofi,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(nts))
ssErr(EH_Err, NtStatusToScode(nts));
}
// Make sure the file pointer is at zero
fpi.CurrentByteOffset.LowPart = 0;
fpi.CurrentByteOffset.HighPart = 0;
nts = NtSetInformationFile(_h, &iosb, &fpi,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
else
sc = S_OK;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitCommon\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::InitFromHandle, public
//
// Synopsis: Constructor
//
// Arguments: [h] - Handle to duplicate
// [grfMode] - Mode of handle
//
// Returns: Appropriate status code
//
// History: 08-Jul-93 DrewB Created
//
// Notes: Takes a new reference on the given handle
//
//----------------------------------------------------------------------------
SCODE CNtFileStream::InitFromHandle(HANDLE h,
DWORD grfMode,
CREATEOPEN co,
LPSTGSECURITY pssSecurity)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitFromHandle:%p("
"%p, %lX, %d, %p)\n", this, h, grfMode, co, pssSecurity));
ssChk(ValidateMode(grfMode));
if (pssSecurity != NULL)
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
ssChk(ReopenNtHandle(h, grfMode, FD_FILE, &_h));
ssAssert(co != CO_CREATE || (grfMode & STGM_CREATE));
ssChk(InitCommon(co));
_grfMode = grfMode;
_sig = CNTFILESTREAM_SIG;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitFromHandle\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::InitFromPath, public
//
// Synopsis: Constructor
//
// Arguments: [h] - Handle to duplicate
// [grfMode] - Mode of handle
//
// Returns: Appropriate status code
//
// History: 08-Jul-95 HenryLee Created
//
// Notes: Takes a new reference on the given handle
//
//----------------------------------------------------------------------------
SCODE CNtFileStream::InitFromPath(HANDLE hParent,
const WCHAR *pwcsName,
DWORD grfMode,
DWORD grfAttr,
CREATEOPEN co,
LPSTGSECURITY pssSecurity)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitFromPath:%p("
"%p, %lX, %ws, %d, %p)\n", this, hParent, pwcsName,
grfMode, co, pssSecurity));
ssChk(ValidateMode(grfMode));
if (pssSecurity != NULL)
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
ssChk(GetNtHandle(hParent, pwcsName, grfMode, grfAttr, co, FD_FILE,
(LPSECURITY_ATTRIBUTES) pssSecurity,&_h));
//ssAssert(co != CO_CREATE || (grfMode & STGM_CREATE));
ssChk(InitCommon(co));
_grfMode = grfMode;
_sig = CNTFILESTREAM_SIG;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitFromPath\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::InitClone, public
//
// Synopsis: Constructor
//
// Arguments: [h] - Handle to duplicate
// [grfMode] - Mode of handle
//
// Returns: Appropriate status code
//
// History: 08-Jul-93 DrewB Created
//
// Notes: Takes a new reference on the given handle
//
//----------------------------------------------------------------------------
SCODE CNtFileStream::InitClone(HANDLE h, DWORD grfMode)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitClone:%p(%p, %lX)\n",
this, h, grfMode));
ssChk(ValidateMode(grfMode));
ssChk(DupNtHandle(h, &_h));
_grfMode = grfMode;
_sig = CNTFILESTREAM_SIG;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitClone\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::~CNtFileStream, public
//
// Synopsis: Destructor
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
CNtFileStream::~CNtFileStream(void)
{
ssDebugOut((DEB_ITRACE, "In CNtFileStream::~CNtFileStream:%p()\n", this));
_sig = CNTFILESTREAM_SIGDEL;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::~CNtFileStream\n"));
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Read, public
//
// Synopsis: Read from a stream
//
// Arguments: [pb] - Buffer
// [cb] - Count of bytes to read
// [pcbRead] - Return number of bytes read
//
// Returns: Appropriate status code
//
// Modifies: [pcbRead]
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Read(VOID *pb, ULONG cb, ULONG *pcbRead)
{
SCODE sc;
NTSTATUS nts;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Read:%p(%p, %lu, %p)\n",
this, pb, cb, pcbRead));
sc = S_OK;
ssChk(Validate());
ssAssert(_h != NULL);
nts = NtReadFile(_h, NULL, NULL, NULL, &iosb, pb, cb, NULL, NULL);
if (!NT_SUCCESS(nts))
{
if (nts != STATUS_END_OF_FILE)
sc = NtStatusToScode(nts);
else
iosb.Information = 0;
}
if (pcbRead)
{
if (SUCCEEDED(sc))
*pcbRead = iosb.Information;
else
*pcbRead = 0;
}
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Read => %lu\n",
iosb.Information));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Write, public
//
// Synopsis: Write to a stream
//
// Arguments: [pb] - Buffer
// [cb] - Count of bytes to write
// [pcbWritten] - Return of bytes written
//
// Returns: Appropriate status code
//
// Modifies: [pcbWritten]
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Write(VOID const *pb,
ULONG cb,
ULONG *pcbWritten)
{
SCODE sc;
NTSTATUS nts;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Write:%p(%p, %lu, %p)\n",
this, pb, cb, pcbWritten));
sc = S_OK;
ssChk(Validate());
ssAssert(_h != NULL);
nts = NtWriteFile(_h, NULL, NULL, NULL, &iosb, (void *)pb, cb,
NULL, NULL);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
if (pcbWritten)
{
if (SUCCEEDED(sc))
*pcbWritten = iosb.Information;
else
*pcbWritten = 0;
}
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Write => %lu\n",
iosb.Information));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Seek, public
//
// Synopsis: Seek to a point in a stream
//
// Arguments: [dlibMove] - Offset to move by
// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
// [plibNewPosition] - Return of new offset
//
// Returns: Appropriate status code
//
// Modifies: [plibNewPosition]
//
// History: 28-Jun-93 DrewB Created
//
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Seek(LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition)
{
SCODE sc;
NTSTATUS nts;
IO_STATUS_BLOCK iosb;
FILE_POSITION_INFORMATION fpi;
FILE_STANDARD_INFORMATION fsi;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Seek:%p(%ld:%ld, %lu, %p)\n",
this, dlibMove.HighPart, dlibMove.LowPart, dwOrigin,
plibNewPosition));
if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
dwOrigin != STREAM_SEEK_END)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
ssAssert(_h != NULL);
switch(dwOrigin)
{
case STREAM_SEEK_SET:
fpi.CurrentByteOffset.LowPart = dlibMove.LowPart;
fpi.CurrentByteOffset.HighPart = dlibMove.HighPart;
break;
case STREAM_SEEK_CUR:
nts = NtQueryInformationFile(_h, &iosb, &fpi,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
if (!NT_SUCCESS(nts))
ssErr(EH_Err, NtStatusToScode(nts));
// Check for seek before beginning and overflow
if (dlibMove.HighPart < 0)
{
if ((-dlibMove.QuadPart) > fpi.CurrentByteOffset.QuadPart)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
}
else if (!((fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart) >=
fpi.CurrentByteOffset.QuadPart))
{
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
}
fpi.CurrentByteOffset.QuadPart =
fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart;
break;
case STREAM_SEEK_END:
nts = NtQueryInformationFile(_h, &iosb, &fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (!NT_SUCCESS(nts))
ssErr(EH_Err, NtStatusToScode(nts));
// Check for seek before beginning and overflow
if (dlibMove.HighPart < 0)
{
if ((-dlibMove.QuadPart) > fsi.EndOfFile.QuadPart)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
}
else if (!((fsi.EndOfFile.QuadPart + dlibMove.QuadPart) >=
fsi.EndOfFile.QuadPart))
{
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
}
fpi.CurrentByteOffset.QuadPart =
fsi.EndOfFile.QuadPart + dlibMove.QuadPart;
break;
}
sc = S_OK;
nts = NtSetInformationFile(_h, &iosb, &fpi,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
else if (plibNewPosition)
*plibNewPosition = *(ULARGE_INTEGER *)&fpi.CurrentByteOffset;
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Seek => %lu:%lu\n",
fpi.CurrentByteOffset.HighPart,
fpi.CurrentByteOffset.LowPart));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::SetSize, public
//
// Synopsis: Sets the size of a stream
//
// Arguments: [ulNewSize] - New size
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::SetSize(ULARGE_INTEGER ulNewSize)
{
SCODE sc;
IO_STATUS_BLOCK iosb;
FILE_END_OF_FILE_INFORMATION feofi;
NTSTATUS nts;
ssDebugOut((DEB_TRACE, "In CNtFileStream::SetSize:%p(%lu:%lu)\n",
this, ulNewSize.HighPart, ulNewSize.LowPart));
sc = S_OK;
ssChk(Validate());
feofi.EndOfFile.LowPart = ulNewSize.LowPart;
feofi.EndOfFile.HighPart = (ULONG)ulNewSize.HighPart;
ssAssert(_h != NULL);
nts = NtSetInformationFile(_h, &iosb, &feofi,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(nts))
ssErr(EH_Err, NtStatusToScode(nts));
ssDebugOut((DEB_TRACE, "Out CNtFileStream::SetSize\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::CopyTo, public
//
// Synopsis: Copies information from one stream to another
//
// Arguments: [pstm] - Destination
// [cb] - Number of bytes to copy
// [pcbRead] - Return number of bytes read
// [pcbWritten] - Return number of bytes written
//
// Returns: Appropriate status code
//
// Modifies: [pcbRead]
// [pcbWritten]
//
// History: 28-Jun-93 DrewB Created
//
// Notes: We do our best to handle overlap correctly. This allows
// CopyTo to be used to insert and remove space within a
// stream.
//
// In the error case, we make no gurantees as to the
// validity of pcbRead, pcbWritten, or either stream's
// seek position.
//
//----------------------------------------------------------------------------
#define CBBUFFER 8192
STDMETHODIMP CNtFileStream::CopyTo(IStream *pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER *pcbRead,
ULARGE_INTEGER *pcbWritten)
{
SCODE sc;
LARGE_INTEGER cbRead = {0, 0}, cbWritten = {0, 0}, cbDone;
LARGE_INTEGER liPosFrom, liPosTo, liTmp;
LARGE_INTEGER liZero = {0, 0};
LARGE_INTEGER liStep;
LARGE_INTEGER licb;
BOOL fForward;
ULONG ulcbDone, cbDo;
SafeBytePtr pbBuffer;
ssDebugOut((DEB_TRACE, "In CNtFileStream::CopyTo:%p("
"%p, %lu:%lu, %p, %p)\n",
this, pstm, cb.HighPart, cb.LowPart, pcbRead, pcbWritten));
// BUGBUG - Possible 63-bit overflow problems?
if (!IsValidInterface(pstm))
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
sc = S_OK;
ssChk(Validate());
if (cb.HighPart >= 0x80000000)
cb.HighPart = 0x7fffffff;
licb = *(LARGE_INTEGER *)&cb;
pbBuffer.Attach(new BYTE[CBBUFFER]);
ssMem((BYTE *)pbBuffer);
ssHChk(Seek(liZero, STREAM_SEEK_CUR, (ULARGE_INTEGER *)&liPosFrom));
ssHChk(pstm->Seek(liZero, STREAM_SEEK_CUR,
(ULARGE_INTEGER *)&liPosTo));
// Determine which direction to copy to avoid overlap problems
if (!(liPosFrom.QuadPart >= liPosTo.QuadPart) &&
(licb.QuadPart > liStep.QuadPart))
{
liStep.HighPart = -1;
liStep.LowPart = (ULONG)(-CBBUFFER);
fForward = FALSE;
// Seek to the end of the copy area plus one step
// so that we're in place for the loop seek backwards
liTmp.QuadPart = liPosFrom.QuadPart + licb.QuadPart;
liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
ssHChk(Seek(liTmp, STREAM_SEEK_SET, NULL));
liTmp.QuadPart = liPosTo.QuadPart + licb.QuadPart;
liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
ssHChk(pstm->Seek(liTmp, STREAM_SEEK_SET, NULL));
// We seek backwards by twice the step size, once
// to back up beyond the step we just read and once
// more to back up to a fresh step worth of data
ssAssert(CBBUFFER <= 0x3fffffff);
liStep.LowPart *= 2;
}
else
{
liStep.HighPart = 0;
liStep.LowPart = CBBUFFER;
fForward = TRUE;
}
cbDone.HighPart = 0;
for (;;)
{
if (licb.HighPart == 0 && licb.LowPart < CBBUFFER)
cbDo = licb.LowPart;
else
cbDo = CBBUFFER;
if (!fForward)
{
// If we're doing the last fragment make sure we don't overshoot
// when backing up
if (cbDo < CBBUFFER)
{
liStep.LowPart /= 2;
liStep.LowPart -= CBBUFFER-(LONG)cbDo;
}
// Seek backwards to fresh data
ssHChkTo(EH_End, Seek(liStep, STREAM_SEEK_CUR, NULL));
ssHChkTo(EH_End, pstm->Seek(liStep, STREAM_SEEK_CUR, NULL));
}
ssHChkTo(EH_End, Read(pbBuffer, cbDo, &cbDone.LowPart));
if (cbDone.LowPart == 0)
break;
cbRead.QuadPart = cbRead.QuadPart + cbDone.QuadPart;
ssHChkTo(EH_End, pstm->Write(pbBuffer, cbDone.LowPart,
&ulcbDone));
if (ulcbDone != cbDone.LowPart)
ssErr(EH_End, STG_E_WRITEFAULT);
cbWritten.QuadPart = cbWritten.QuadPart + cbDone.QuadPart;
licb.QuadPart = licb.QuadPart - cbDone.QuadPart;
if (licb.HighPart < 0 ||
(licb.HighPart == 0 && licb.LowPart == 0))
break;
}
EH_End:
if (pcbRead)
*(LARGE_INTEGER *)pcbRead = cbRead;
if (pcbWritten)
*(LARGE_INTEGER *)pcbWritten = cbWritten;
ssDebugOut((DEB_TRACE, "Out CNtFileStream::CopyTo => %lu:%lu, %lu:%lu\n",
cbRead.HighPart, cbRead.LowPart, cbWritten.HighPart,
cbWritten.LowPart));
// Fall through
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Commit, public
//
// Synopsis: Commits transacted changes
//
// Arguments: [grfCommitFlags] - Flags
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Commit(DWORD grfCommitFlags)
{
NTSTATUS nts;
SCODE sc;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Commit:%p(%lX)\n",
this, grfCommitFlags));
ssChk(VerifyCommitFlags(grfCommitFlags));
ssChk(Validate());
ssAssert(_h != NULL);
nts = NtFlushBuffersFile(_h, &iosb);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
else
sc = S_OK;
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Commit => %lX\n", sc));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Revert, public
//
// Synopsis: Reverts transacted changes
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Revert(void)
{
ssDebugOut((DEB_TRACE, "Stb CNtFileStream::Revert()\n"));
return NOERROR;
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::LockRegion, public
//
// Synopsis: Locks a portion of the stream
//
// Arguments: [libOffset] - Offset to lock at
// [cb] - Length of lock
// [dwLockType] - LockType
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::LockRegion(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
SCODE sc;
NTSTATUS nts;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In CNtFileStream::LockRegion:%p("
"%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
sc = S_OK;
ssChk(Validate());
ssChk(ValidateLockType(dwLockType));
ssAssert(_h != NULL);
nts = NtLockFile(_h, NULL, NULL, NULL, &iosb, (PLARGE_INTEGER)&libOffset,
(PLARGE_INTEGER)&cb, 0, TRUE, TRUE);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
else
sc = S_OK;
ssDebugOut((DEB_TRACE, "Out CNtFileStream::LockRegion\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::UnlockRegion, public
//
// Synopsis: Unlocks a locked region
//
// Arguments: [libOffset] - Offset to lock at
// [cb] - Length of lock
// [dwLockType] - LockType
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::UnlockRegion(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
SCODE sc;
NTSTATUS nts;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In CNtFileStream::UnlockRegion:%p("
"%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
sc = S_OK;
ssChk(Validate());
ssChk(ValidateLockType(dwLockType));
ssAssert(_h != NULL);
nts = NtUnlockFile(_h, &iosb, (PLARGE_INTEGER)&libOffset,
(PLARGE_INTEGER)&cb, 0);
if (!NT_SUCCESS(nts))
sc = NtStatusToScode(nts);
else
sc = S_OK;
ssDebugOut((DEB_TRACE, "Out CNtFileStream::UnlockRegion\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Stat, public
//
// Synopsis: Fills in a buffer of information about this object
//
// Arguments: [pstatstg] - Buffer
//
// Returns: Appropriate status code
//
// Modifies: [pstatstg]
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
{
SCODE sc;
STATSTG stat;
FILEDIR fd;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Stat:%p(%p, %lX)\n",
this, pstatstg, grfStatFlag));
ssChk(VerifyStatFlag(grfStatFlag));
ssChk(Validate());
__try
{
// \CONTENTS must be appended to name
ssAssert(_h != NULL);
sc = StatNtHandle(_h, grfStatFlag,
sizeof(CONTENTS_STREAM)+sizeof(WCHAR), &stat,
NULL, NULL, &fd);
if (SUCCEEDED(sc))
{
if (stat.pwcsName)
{
WCHAR *pwcs;
pwcs = stat.pwcsName+lstrlenW(stat.pwcsName);
*pwcs++ = L'\\';
lstrcpyW(pwcs, CONTENTS_STREAM);
}
stat.grfMode = _grfMode;
stat.type = STGTY_STREAM;
stat.mtime.dwLowDateTime = stat.mtime.dwHighDateTime = 0;
stat.atime.dwLowDateTime = stat.atime.dwHighDateTime = 0;
stat.ctime.dwLowDateTime = stat.ctime.dwHighDateTime = 0;
stat.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
*pstatstg = stat;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
if (stat.pwcsName)
ssVerSucc(CoMemFree(stat.pwcsName));
sc = HRESULT_FROM_NT(GetExceptionCode());
}
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Stat\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::Clone, public
//
// Synopsis: Clones a stream
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtFileStream::Clone(IStream **ppstm)
{
SCODE sc;
SafeCNtFileStream pfs;
ssDebugOut((DEB_TRACE, "In CNtFileStream::Clone:%p(%p)\n",
this, ppstm));
sc = S_OK;
ssChk(Validate());
pfs.Attach(new CNtFileStream());
ssMem((CNtFileStream *)pfs);
ssAssert(_h != NULL);
ssChk(pfs->InitClone(_h, _grfMode));
TRANSFER_INTERFACE(pfs, IStream, ppstm);
ssDebugOut((DEB_TRACE, "Out CNtFileStream::Clone => %p\n", *ppstm));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtFileStream::ValidateMode, private
//
// Synopsis: Validates a mode
//
// Arguments: [grfMode] - Mode
//
// Returns: Appropriate status code
//
// History: 09-Jul-93 DrewB Created
//
// Notes: Streams allow any sharing permissions but ignore all of them
//
//----------------------------------------------------------------------------
SCODE CNtFileStream::ValidateMode(DWORD grfMode)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In CNtFileStream::ValidateMode:%p(0x%lX)\n",
this, grfMode));
if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY | STGM_DELETEONRELEASE |
STGM_CONVERT)))
sc = STG_E_INVALIDFLAG;
else
sc = S_OK;
ssDebugOut((DEB_ITRACE, "Out CNtFileStream::ValidateMode => 0x%lX\n"));
return sc;
}