497 lines
14 KiB
C++
497 lines
14 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: ntlkb.cxx
|
|
//
|
|
// Contents: ILockBytes for an NT handle
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <ntlkb.hxx>
|
|
#include <stgutil.hxx>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CNtLockBytes::QueryInterface:%p(riid, %p)\n",
|
|
this, ppvObj));
|
|
if (!IsValidIid(iid))
|
|
sc = STG_E_INVALIDPARAMETER;
|
|
else if (IsEqualIID(iid, IID_ILockBytes) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (ILockBytes *)this;
|
|
CNtLockBytes::AddRef();
|
|
sc = S_OK;
|
|
}
|
|
else
|
|
{
|
|
sc = E_NOINTERFACE;
|
|
*ppvObj = NULL;
|
|
}
|
|
ssDebugOut((DEB_TRACE, "Out CNtLockBytes::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::CNtLockBytes, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
// 24-Mar-95 HenryLee Save drive letter for Stat problem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CNtLockBytes::CNtLockBytes(BOOL fOfs)
|
|
{
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::CNtLockBytes:%p()\n", this));
|
|
_fOfs = fOfs;
|
|
_wcDrive = L'\0';
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::CNtLockBytes\n"));
|
|
ENLIST_TRACKING(CNtLockBytes);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::InitFromPath, public
|
|
//
|
|
// Synopsis: Constructs from the given path
|
|
//
|
|
// Arguments: [hParent] - Parent handle
|
|
// [pwcsName] - Path
|
|
// [grfMode] - Mode
|
|
// [co] - Create or open
|
|
// [pssSecurity] - Security
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
// 24-Mar-95 HenryLee Save drive letter for Stat problem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CNtLockBytes::InitFromPath(HANDLE hParent,
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
CREATEOPEN co,
|
|
LPSECURITY_ATTRIBUTES pssSecurity)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::InitFromPath:%p("
|
|
"%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName,
|
|
grfMode, co, pssSecurity));
|
|
|
|
ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
|
|
FD_FILE, pssSecurity, &_h));
|
|
_grfMode = grfMode;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
|
|
ssDebugOut((DEB_IWARN, "CNtLockBytes::InitFromPath %p"
|
|
"handle %p thread %lX\n",
|
|
this, (HANDLE)_h, GetCurrentThreadId()));
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::InitFromPath\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::InitFromHandle, public
|
|
//
|
|
// Synopsis: Initialization by handle
|
|
//
|
|
// Arguments: [h] - Handle
|
|
// [grfMode] - Mode
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 21-Sep-93 DrewB Created
|
|
// 24-Mar-95 HenryLee Save drive letter for Stat problem
|
|
//
|
|
// Notes: Takes a new reference on the handle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CNtLockBytes::InitFromHandle(HANDLE h,
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::InitFromHandle:%p(%p, %lX)\n",
|
|
this, h, grfMode));
|
|
|
|
|
|
ssChk(DupNtHandle(h, &_h));
|
|
|
|
_grfMode = grfMode;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
|
|
ssDebugOut((DEB_IWARN, "CNtLockBytes::InitFromHandle %p"
|
|
"handle %p thread %lX\n",
|
|
this, (HANDLE)_h, GetCurrentThreadId()));
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::InitFromHandle\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::~CNtLockBytes, public debugging
|
|
//
|
|
// Synopsis: Stub for placing shutdown debug messages
|
|
//
|
|
// History: 01-Oct-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if DBG == 1
|
|
CNtLockBytes::~CNtLockBytes(void)
|
|
{
|
|
ssDebugOut((DEB_IWARN, "~CNtLockBytes %p handle %p thread %lX\n",
|
|
this, (HANDLE)_h, GetCurrentThreadId()));
|
|
}
|
|
#endif
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::ReadAt, public
|
|
//
|
|
// Synopsis: Reads bytes at a specific point in a stream
|
|
//
|
|
// Arguments: [ulPosition] - Offset in file to read at
|
|
// [pb] - Buffer
|
|
// [cb] - Count of bytes to read
|
|
// [pcbRead] - Return of bytes read
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbRead]
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::ReadAt(ULARGE_INTEGER ulPosition,
|
|
VOID *pb,
|
|
ULONG cb,
|
|
ULONG *pcbRead)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::ReadAt:%p("
|
|
"%lu:%lu, %p, %lu, %p)\n", this, ulPosition.HighPart,
|
|
ulPosition.LowPart, pb, cb, pcbRead));
|
|
|
|
sc = S_OK;
|
|
ssAssert(_h != NULL);
|
|
nts = NtReadFile(_h, NULL, NULL, NULL, &iosb, pb, cb,
|
|
(LARGE_INTEGER *)&ulPosition, 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_ITRACE, "Out CNtLockBytes::ReadAt => %lu\n", *pcbRead));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::WriteAt, public
|
|
//
|
|
// Synopsis: Writes bytes at a specific point in a stream
|
|
//
|
|
// Arguments: [ulPosition] - Offset in file
|
|
// [pb] - Buffer
|
|
// [cb] - Count of bytes to write
|
|
// [pcbWritten] - Return of bytes written
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pcbWritten]
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::WriteAt(ULARGE_INTEGER ulPosition,
|
|
VOID const *pb,
|
|
ULONG cb,
|
|
ULONG *pcbWritten)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::WriteAt:%p("
|
|
"%lu:%lu, %p, %lu, %p)\n", this, ulPosition.HighPart,
|
|
ulPosition.LowPart, pb, cb, pcbWritten));
|
|
|
|
sc = S_OK;
|
|
ssAssert(_h != NULL);
|
|
nts = NtWriteFile(_h, NULL, NULL, NULL, &iosb, (void *)pb, cb,
|
|
(LARGE_INTEGER *)&ulPosition, NULL);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
if (pcbWritten)
|
|
{
|
|
if (SUCCEEDED(sc))
|
|
*pcbWritten = iosb.Information;
|
|
else
|
|
*pcbWritten = 0;
|
|
}
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::WriteAt => %lu\n",
|
|
*pcbWritten));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::Flush, public
|
|
//
|
|
// Synopsis: Flushes buffers
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 24-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::Flush(void)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::Flush:%p()\n", this));
|
|
|
|
ssAssert(_h != NULL);
|
|
nts = NtFlushBuffersFile(_h, &iosb);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::Flush => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::SetSize, public
|
|
//
|
|
// Synopsis: Sets the size of the LStream
|
|
//
|
|
// Arguments: [ulSize] - New size
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::SetSize(ULARGE_INTEGER ulSize)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
FILE_END_OF_FILE_INFORMATION feofi;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::SetSize:%p(%lu:%lu)\n",
|
|
this, ulSize.HighPart, ulSize.LowPart));
|
|
|
|
sc = S_OK;
|
|
|
|
feofi.EndOfFile.LowPart = ulSize.LowPart;
|
|
feofi.EndOfFile.HighPart = ulSize.HighPart;
|
|
ssAssert(_h != NULL);
|
|
nts = NtSetInformationFile(_h, &iosb, &feofi,
|
|
sizeof(FILE_END_OF_FILE_INFORMATION),
|
|
FileEndOfFileInformation);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::SetSize => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::LockRegion, public
|
|
//
|
|
// Synopsis: Gets a lock on a portion of the LStream
|
|
//
|
|
// Arguments: [ulStartOffset] - Lock start
|
|
// [cbLockLength] - Length
|
|
// [dwLockType] - Exclusive/Read only
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::LockRegion(ULARGE_INTEGER ulStartOffset,
|
|
ULARGE_INTEGER cbLockLength,
|
|
DWORD dwLockType)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::LockRegion:%p("
|
|
"%lu:%lu, %lu:%lu, %lu)\n", this, ulStartOffset.HighPart,
|
|
ulStartOffset.LowPart, cbLockLength.HighPart,
|
|
cbLockLength.LowPart, dwLockType));
|
|
|
|
ssAssert(_h != NULL);
|
|
nts = NtLockFile(_h, NULL, NULL, NULL, &iosb,
|
|
(PLARGE_INTEGER)&ulStartOffset,
|
|
(PLARGE_INTEGER)&cbLockLength, 0, TRUE, TRUE);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::LockRegion => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::UnlockRegion, public
|
|
//
|
|
// Synopsis: Releases an existing lock
|
|
//
|
|
// Arguments: [ulStartOffset] - Lock start
|
|
// [cbLockLength] - Length
|
|
// [dwLockType] - Lock type
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 17-Aug-93 DrewB Created
|
|
//
|
|
// Notes: Must match an existing lock exactly
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::UnlockRegion(ULARGE_INTEGER ulStartOffset,
|
|
ULARGE_INTEGER cbLockLength,
|
|
DWORD dwLockType)
|
|
{
|
|
SCODE sc;
|
|
NTSTATUS nts;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::UnlockRegion:%p("
|
|
"%lu:%lu, %lu:%lu, %lu)\n", this, ulStartOffset.HighPart,
|
|
ulStartOffset.LowPart, cbLockLength.HighPart,
|
|
cbLockLength.LowPart, dwLockType));
|
|
|
|
ssAssert(_h != NULL);
|
|
nts = NtUnlockFile(_h, &iosb, (PLARGE_INTEGER)&ulStartOffset,
|
|
(PLARGE_INTEGER)&cbLockLength, 0);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::UnlockRegion => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CNtLockBytes::Stat, public
|
|
//
|
|
// Synopsis: Fills in a stat buffer for this object
|
|
//
|
|
// Arguments: [pstatstg] - Buffer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pstatstg]
|
|
//
|
|
// History: 25-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
STDMETHODIMP CNtLockBytes::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SCODE sc;
|
|
STATSTG stat;
|
|
FILEDIR fd;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CNtLockBytes::Stat:%p(%p, %d)\n",
|
|
this, pstatstg, grfStatFlag));
|
|
|
|
ssAssert(_h != NULL);
|
|
sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
stat.grfMode = _grfMode;
|
|
stat.type = STGTY_LOCKBYTES;
|
|
stat.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
|
|
|
|
// As a hack way of determining whether this ILockBytes
|
|
// lives on OFS or not, we return our OFSness through dwStgFmt,
|
|
// which is unused for ILockBytes
|
|
stat.STATSTG_dwStgFmt = _fOfs;
|
|
|
|
// Now we tack on the drive letter to the filename, since
|
|
// NtQueryInformationFile doesn't return the drive letter,
|
|
// and NtQueryObject returns something like
|
|
// "\Device\Harddisk1\Partition1"
|
|
SetDriveLetter (stat.pwcsName, _wcDrive);
|
|
|
|
*pstatstg = stat;
|
|
}
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::Stat => %lX\n", sc));
|
|
return ssResult(sc);
|
|
}
|