windows-nt/Source/XPSP1/NT/base/win32/server/mmapstm.c

192 lines
6 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
mmapstm.c
Abstract:
IStream over a memory-mapped file, derived (in the C++ sense) from
RTL_MEMORY_STREAM. Note the semantics and implementation here
of IStream::Stat are specialized for use by sxs.
Author:
Jay Krell (a-JayK) June 2000
Revision History:
--*/
#include "basesrv.h"
#include "nturtl.h"
#include "mmapstm.h"
// REVIEW
#define BASE_SRV_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosErrorNoTeb(x))
//#define BASE_SRV_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosError(x))
//#define BASE_SRV_HRESULT_FROM_STATUS(x) HRESULT_FROM_NT(x)
#define DPFLTR_LEVEL_HRESULT(x) (SUCCEEDED(x) ? DPFLTR_TRACE_LEVEL : DPFLTR_ERROR_LEVEL)
#define DPFLTR_LEVEL_STATUS(x) ((NT_SUCCESS(x) || x == STATUS_SXS_CANT_GEN_ACTCTX) ? DPFLTR_TRACE_LEVEL : DPFLTR_ERROR_LEVEL)
const static RTL_STREAM_VTABLE_TEMPLATE(BASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE)
MmapStreamVTable =
{
BaseSrvQueryInterfaceMemoryMappedStream,
BaseSrvAddRefMemoryMappedStream,
BaseSrvReleaseMemoryMappedStream,
BaseSrvReadMemoryMappedStream,
BaseSrvWriteMemoryMappedStream,
BaseSrvSeekMemoryMappedStream,
BaseSrvSetMemoryMappedStreamSize,
BaseSrvCopyMemoryMappedStreamTo,
BaseSrvCommitMemoryMappedStream,
BaseSrvRevertMemoryMappedStream,
BaseSrvLockMemoryMappedStreamRegion,
BaseSrvUnlockMemoryMappedStreamRegion,
BaseSrvStatMemoryMappedStream,
BaseSrvCloneMemoryMappedStream
};
VOID
STDMETHODCALLTYPE
BaseSrvInitMemoryMappedStream(
PBASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE MmapStream
)
{
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__));
// call the base class constructor
RtlInitMemoryStream(&MmapStream->MemStream);
// replace the base vtable with our own
MmapStream->MemStream.StreamVTable = (IStreamVtbl*)&MmapStreamVTable;
// replace the virtual destructor with our own
MmapStream->MemStream.Data.FinalRelease = BaseSrvFinalReleaseMemoryMappedStream;
// initialize our extra data
MmapStream->FileHandle = NULL;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() exiting\n", __FUNCTION__));
}
HRESULT
STDMETHODCALLTYPE
BaseSrvStatMemoryMappedStream(
PBASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE MmapStream,
STATSTG* Stat,
DWORD Flags
)
{
//
// We should be able to merge RTL_FILE_STREAM and RTL_MEMORY_STREAM somehow,
// but RTL_FILE_STREAM so far we aren't using and it doesn't implement Stat, so..
//
NTSTATUS Status = STATUS_SUCCESS;
HRESULT Hr = NOERROR;
FILE_BASIC_INFORMATION FileBasicInfo;
IO_STATUS_BLOCK IoStatusBlock;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__));
if (Stat == NULL) {
// You would expect this to be E_INVALIDARG,
// but IStream docs say to return STG_E_INVALIDPOINTER.
Hr = STG_E_INVALIDPOINTER;
goto Exit;
}
// we don't support returning the string because
// we don't have ole32.dll for CoTaskMem*
Stat->pwcsName = NULL;
ASSERT(Flags & STATFLAG_NONAME);
if (MmapStream->FileHandle != NULL) {
Status = NtQueryInformationFile(
MmapStream->FileHandle,
&IoStatusBlock,
&FileBasicInfo,
sizeof(FileBasicInfo),
FileBasicInformation
);
if (!NT_SUCCESS(Status)) {
Hr = BASE_SRV_HRESULT_FROM_STATUS(Status);
goto Exit;
}
} else {
// NOTE: This is acceptable for the sxs consumer.
// It is not necessarily acceptable to everyone.
// Do not change it without consulting sxs.
RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
}
Stat->type = STGTY_LOCKBYTES;
// NOTE we do not report the size of the file, but the size
// of the mapped view; if we implemented IStream::Stat for RTL_MEMORY_STREAM,
// it would return the same thing here.
// (to get file times and size, use FileNetworkOpenInformation)
Stat->cbSize.QuadPart = (MmapStream->MemStream.Data.End - MmapStream->MemStream.Data.Begin);
Stat->mtime.dwLowDateTime = FileBasicInfo.LastWriteTime.LowPart;
Stat->mtime.dwHighDateTime = FileBasicInfo.LastWriteTime.HighPart;
Stat->ctime.dwLowDateTime = FileBasicInfo.CreationTime.LowPart;
Stat->ctime.dwHighDateTime = FileBasicInfo.CreationTime.HighPart;
Stat->atime.dwLowDateTime = FileBasicInfo.LastAccessTime.LowPart;
Stat->atime.dwHighDateTime = FileBasicInfo.LastAccessTime.HighPart;
// there is FileAccessInformation, but this hardcoding should suffice
Stat->grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
Stat->grfLocksSupported = 0;
Stat->clsid = CLSID_NULL;
Stat->grfStateBits = 0;
Stat->reserved = 0;
Hr = NOERROR;
Exit:
#if !DBG
if (DPFLTR_LEVEL_STATUS(Status) == DPFLTR_ERROR_LEVEL)
#endif
DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(Hr), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Hr);
return Hr;
}
VOID
STDMETHODCALLTYPE
BaseSrvFinalReleaseMemoryMappedStream(
PRTL_MEMORY_STREAM_WITH_VTABLE MemStream
)
{
NTSTATUS Status;
PBASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE MmapStream;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__));
MmapStream = CONTAINING_RECORD(MemStream, BASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE, MemStream);
if (MemStream->Data.Begin != NULL) {
Status = NtUnmapViewOfSection(NtCurrentProcess(), MemStream->Data.Begin);
RTL_SOFT_ASSERT(NT_SUCCESS(Status));
// REVIEW Should we provide RtlFinalReleaseMemoryStream and move these
// lines there?
MemStream->Data.Begin = NULL;
MemStream->Data.End = NULL;
MemStream->Data.Current = NULL;
}
if (MmapStream->FileHandle != NULL) {
Status = NtClose(MmapStream->FileHandle);
RTL_SOFT_ASSERT(NT_SUCCESS(Status));
MmapStream->FileHandle = NULL;
}
// RtlFinalReleaseMemoryStream(MemStream);
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() exiting\n", __FUNCTION__));
}