|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
memstm.c
Abstract:
This modules implements IStream over a block of memory.
Author:
Jay Krell (a-JayK) June 2000
Revision History:
--*/
#define RTL_DECLARE_STREAMS 1
#define RTL_DECLARE_MEMORY_STREAM 1
#include "ntos.h"
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "objidl.h"
#define RTLP_MEMORY_STREAM_NOT_IMPL(x) \
ASSERT(MemoryStream != NULL); \ KdPrintEx((DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "NTDLL: %s() E_NOTIMPL", __FUNCTION__)); \ return E_NOTIMPL;
#if !defined(RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS)
#if defined(RTLP_HRESULT_FROM_STATUS)
#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) RTLP_HRESULT_FROM_STATUS(x)
#else
#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosErrorNoTeb(x))
//#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosError(x))
//#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_NT(x)
#endif
#endif
#define DPFLTR_LEVEL_HRESULT(x) (SUCCEEDED(x) ? DPFLTR_TRACE_LEVEL : DPFLTR_ERROR_LEVEL)
const static RTL_STREAM_VTABLE_TEMPLATE(RTL_MEMORY_STREAM_WITH_VTABLE) MemoryStreamVTable = { RtlQueryInterfaceMemoryStream, RtlAddRefMemoryStream, RtlReleaseMemoryStream, RtlReadMemoryStream, RtlWriteMemoryStream, RtlSeekMemoryStream, RtlSetMemoryStreamSize, RtlCopyMemoryStreamTo, RtlCommitMemoryStream, RtlRevertMemoryStream, RtlLockMemoryStreamRegion, RtlUnlockMemoryStreamRegion, RtlStatMemoryStream, RtlCloneMemoryStream };
const static RTL_STREAM_VTABLE_TEMPLATE(RTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE) OutOfProcessMemoryStreamVTable = { RtlQueryInterfaceOutOfProcessMemoryStream, RtlAddRefOutOfProcessMemoryStream, RtlReleaseOutOfProcessMemoryStream, RtlReadOutOfProcessMemoryStream, RtlWriteOutOfProcessMemoryStream, RtlSeekOutOfProcessMemoryStream, RtlSetOutOfProcessMemoryStreamSize, RtlCopyOutOfProcessMemoryStreamTo, RtlCommitOutOfProcessMemoryStream, RtlRevertOutOfProcessMemoryStream, RtlLockOutOfProcessMemoryStreamRegion, RtlUnlockOutOfProcessMemoryStreamRegion, RtlStatOutOfProcessMemoryStream, RtlCloneOutOfProcessMemoryStream };
VOID STDMETHODCALLTYPE RtlInitOutOfProcessMemoryStream( PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { ASSERT(MemoryStream != NULL); RtlZeroMemory(&MemoryStream->Data, sizeof(MemoryStream->Data)); MemoryStream->Data.FinalRelease = RtlFinalReleaseOutOfProcessMemoryStream; MemoryStream->StreamVTable = (const IStreamVtbl*)&OutOfProcessMemoryStreamVTable; }
VOID STDMETHODCALLTYPE RtlFinalReleaseOutOfProcessMemoryStream( PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { NTSTATUS Status = STATUS_SUCCESS; ASSERT(MemoryStream != NULL); if (MemoryStream->Data.Process != NULL) { Status = NtClose(MemoryStream->Data.Process); RTL_SOFT_ASSERT(NT_SUCCESS(Status)); MemoryStream->Data.Process = NULL; } }
VOID STDMETHODCALLTYPE RtlInitMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { ASSERT(MemoryStream != NULL); RtlZeroMemory(&MemoryStream->Data, sizeof(MemoryStream->Data)); MemoryStream->StreamVTable = (const IStreamVtbl*)&MemoryStreamVTable; }
ULONG STDMETHODCALLTYPE RtlAddRefMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { LONG ReferenceCount;
KdPrintEx(( DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning, refcount is %ld\n", __FUNCTION__, MemoryStream->Data.ReferenceCount )); ASSERT(MemoryStream != NULL);
ReferenceCount = InterlockedIncrement(&MemoryStream->Data.ReferenceCount); return ReferenceCount; }
ULONG STDMETHODCALLTYPE RtlReleaseMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { LONG ReferenceCount; ASSERT(MemoryStream != NULL);
KdPrintEx(( DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning, refcount is %ld\n", __FUNCTION__, MemoryStream->Data.ReferenceCount ));
ReferenceCount = InterlockedDecrement(&MemoryStream->Data.ReferenceCount); if (ReferenceCount == 0 && MemoryStream->Data.FinalRelease != NULL) { MemoryStream->Data.FinalRelease(MemoryStream); } return ReferenceCount; }
HRESULT STDMETHODCALLTYPE RtlQueryInterfaceMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, const IID* Interface, PVOID* Object ) { KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL); ASSERT(Interface != NULL); ASSERT(Object != NULL);
if (IsEqualGUID(Interface, &IID_IUnknown) || IsEqualGUID(Interface, &IID_IStream) || IsEqualGUID(Interface, &IID_ISequentialStream) ) { InterlockedIncrement(&MemoryStream->Data.ReferenceCount); *Object = (IStream*)(&MemoryStream->StreamVTable); return NOERROR; } return E_NOINTERFACE; }
HRESULT STDMETHODCALLTYPE RtlReadOutOfProcessMemoryStream( PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream, PVOID Buffer, ULONG BytesToRead, ULONG* BytesRead ) { NTSTATUS Status = STATUS_SUCCESS; HRESULT Hr = NOERROR; const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current); SIZE_T NumberOfBytesReadSizeT = 0;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL);
if (BytesRemaining < BytesToRead) { BytesToRead = (ULONG)BytesRemaining; } Status = NtReadVirtualMemory( MemoryStream->Data.Process, MemoryStream->Data.Current, Buffer, BytesToRead, &NumberOfBytesReadSizeT); if (Status == STATUS_PARTIAL_COPY) { Status = STATUS_SUCCESS; } if (!NT_SUCCESS(Status)) { Hr = RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(Status); goto Exit; } MemoryStream->Data.Current += NumberOfBytesReadSizeT; *BytesRead = (ULONG)NumberOfBytesReadSizeT; Exit: KdPrintEx(( DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(Hr), "NTDLL: %s(BytesRead:%lu) exiting 0x%08lx\n", __FUNCTION__, (BytesRead != NULL) ? *BytesRead : 0, Hr )); return Hr; }
HRESULT STDMETHODCALLTYPE RtlReadMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, PVOID Buffer, ULONG BytesToRead, ULONG* BytesRead ) { HRESULT Hr = NOERROR; const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current);
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL);
ASSERT(MemoryStream != NULL); ASSERT(MemoryStream->Data.End >= MemoryStream->Data.Current);
if (BytesRemaining < BytesToRead) { BytesToRead = (ULONG)BytesRemaining; } RtlCopyMemory(Buffer, MemoryStream->Data.Current, BytesToRead); MemoryStream->Data.Current += BytesToRead; *BytesRead = BytesToRead;
KdPrintEx(( DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(Hr), "NTDLL: %s(BytesRead:%lu) exiting 0x%08lx\n", __FUNCTION__, (BytesRead != NULL) ? *BytesRead : 0, Hr )); return Hr; }
HRESULT STDMETHODCALLTYPE RtlWriteMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, const VOID* Buffer, ULONG BytesToWrite, ULONG* BytesWritten ) { RTLP_MEMORY_STREAM_NOT_IMPL(Write); }
HRESULT STDMETHODCALLTYPE RtlSeekMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, LARGE_INTEGER Distance, DWORD Origin, ULARGE_INTEGER* NewPosition ) { HRESULT Hr = NOERROR; PUCHAR NewPointer;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL);
//
// "It is not, however, an error to seek past the end of the stream.
// Seeking past the end of the stream is useful for subsequent write
// operations, as the stream will at that time be extended to the seek
// position immediately before the write is done."
//
// As long as we don't allow writing, we are not going to allow this.
//
switch (Origin) { case STREAM_SEEK_SET: NewPointer = MemoryStream->Data.Begin + Distance.QuadPart; break; case STREAM_SEEK_CUR: NewPointer = MemoryStream->Data.Current + Distance.QuadPart; break; case STREAM_SEEK_END: NewPointer = MemoryStream->Data.End - Distance.QuadPart; break; default: Hr = STG_E_INVALIDFUNCTION; goto Exit; } if (NewPointer < MemoryStream->Data.Begin || NewPointer > MemoryStream->Data.End) { Hr = STG_E_INVALIDPOINTER; goto Exit; }
MemoryStream->Data.Current = NewPointer; NewPosition->QuadPart = NewPointer - MemoryStream->Data.Begin; Hr = NOERROR; Exit: KdPrintEx((DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(Hr), "NTDLL: %s() exiting 0x%08lx\n", __FUNCTION__, Hr)); return Hr; }
HRESULT STDMETHODCALLTYPE RtlSetMemoryStreamSize( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, ULARGE_INTEGER NewSize ) { RTLP_MEMORY_STREAM_NOT_IMPL(SetSize); }
HRESULT STDMETHODCALLTYPE RtlCopyOutOfProcessMemoryStreamTo( PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream, IStream* AnotherStream, ULARGE_INTEGER NumberOfBytesToCopyLargeInteger, ULARGE_INTEGER* NumberOfBytesRead, ULARGE_INTEGER* NumberOfBytesWrittenLargeInteger ) { RTLP_MEMORY_STREAM_NOT_IMPL(CopyTo); } HRESULT STDMETHODCALLTYPE RtlCopyMemoryStreamTo( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, IStream* AnotherStream, ULARGE_INTEGER NumberOfBytesToCopyLargeInteger, ULARGE_INTEGER* NumberOfBytesRead, ULARGE_INTEGER* NumberOfBytesWrittenLargeInteger ) { HRESULT Hr = NOERROR; ULONG NumberOfBytesToCopyUlong = 0; ULONG NumberOfBytesWrittenUlong = 0; const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current);
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL);
if (NumberOfBytesToCopyLargeInteger.HighPart != 0) { NumberOfBytesToCopyUlong = MAXULONG; } else { NumberOfBytesToCopyUlong = (ULONG)NumberOfBytesToCopyLargeInteger.QuadPart; }
if (BytesRemaining < NumberOfBytesToCopyUlong) { NumberOfBytesToCopyUlong = (ULONG)BytesRemaining; }
Hr = AnotherStream->lpVtbl->Write(AnotherStream, MemoryStream->Data.Current, NumberOfBytesToCopyUlong, &NumberOfBytesWrittenUlong); if (FAILED(Hr)) { NumberOfBytesRead->QuadPart = 0; NumberOfBytesWrittenLargeInteger->QuadPart = 0; } else { NumberOfBytesRead->QuadPart = NumberOfBytesWrittenUlong; NumberOfBytesWrittenLargeInteger->QuadPart = NumberOfBytesWrittenUlong; } Hr = NOERROR; //Exit:
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(Hr), "NTDLL: %s() exiting 0x%08lx\n", __FUNCTION__, Hr)); return Hr; }
HRESULT STDMETHODCALLTYPE RtlCommitMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, ULONG Flags ) { RTLP_MEMORY_STREAM_NOT_IMPL(Commit); }
HRESULT STDMETHODCALLTYPE RtlRevertMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream ) { RTLP_MEMORY_STREAM_NOT_IMPL(Revert); }
HRESULT STDMETHODCALLTYPE RtlLockMemoryStreamRegion( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, ULARGE_INTEGER Offset, ULARGE_INTEGER NumberOfBytes, ULONG LockType ) { RTLP_MEMORY_STREAM_NOT_IMPL(LockRegion); }
HRESULT STDMETHODCALLTYPE RtlUnlockMemoryStreamRegion( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, ULARGE_INTEGER Offset, ULARGE_INTEGER NumberOfBytes, ULONG LockType ) { RTLP_MEMORY_STREAM_NOT_IMPL(UnlockRegion); }
HRESULT STDMETHODCALLTYPE RtlStatMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, STATSTG* StatusInformation, ULONG Flags ) { HRESULT hr = NOERROR;
KdPrintEx((DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "NTDLL: %s() beginning\n", __FUNCTION__)); ASSERT(MemoryStream != NULL);
if (StatusInformation == NULL) { hr = STG_E_INVALIDPOINTER; goto Exit; }
if (Flags != STATFLAG_NONAME) { hr = STG_E_INVALIDFLAG; goto Exit; }
StatusInformation->pwcsName = NULL; StatusInformation->type = STGTY_STREAM; StatusInformation->cbSize.QuadPart = ((ULONG_PTR) MemoryStream->Data.End) - ((ULONG_PTR) MemoryStream->Data.Begin); StatusInformation->mtime.dwLowDateTime = 0; StatusInformation->mtime.dwHighDateTime = 0; StatusInformation->ctime.dwLowDateTime = 0; StatusInformation->ctime.dwHighDateTime = 0; StatusInformation->atime.dwLowDateTime = 0; StatusInformation->atime.dwHighDateTime = 0; StatusInformation->grfMode = STGM_READ; StatusInformation->grfLocksSupported = 0; StatusInformation->clsid = CLSID_NULL; StatusInformation->grfStateBits = 0; StatusInformation->reserved = 0;
hr = NOERROR;
Exit: KdPrintEx((DPFLTR_SXS_ID, DPFLTR_LEVEL_HRESULT(hr), "NTDLL: %s() exiting 0x%08lx\n", __FUNCTION__, hr));
return hr; }
HRESULT STDMETHODCALLTYPE RtlCloneMemoryStream( PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream, IStream** NewStream ) { RTLP_MEMORY_STREAM_NOT_IMPL(Clone); }
|