|
|
/*++
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__)); }
|