[RTL]
authorThomas Faber <thomas.faber@reactos.org>
Sat, 19 Oct 2013 17:48:27 +0000 (17:48 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 19 Oct 2013 17:48:27 +0000 (17:48 +0000)
- Implement Rtl MemoryStream functions. Patch by David Quintana.
CORE-7492

svn path=/trunk/; revision=60705

reactos/dll/ntdll/CMakeLists.txt
reactos/dll/ntdll/def/ntdll.spec
reactos/include/ndk/rtlfuncs.h
reactos/include/ndk/rtltypes.h
reactos/lib/rtl/CMakeLists.txt
reactos/lib/rtl/memstream.c [new file with mode: 0644]

index 83e9999..9e51fc2 100644 (file)
@@ -52,6 +52,7 @@ target_link_libraries(ntdll
                       rtl
                       ntdllsys
                       libcntpr
+                      uuid
                       ${PSEH_LIB})
 
 add_pch(ntdll include/ntdll.h)
index a8c3d92..b45adaf 100644 (file)
 @ stdcall -arch=x86_64 RtlAddFunctionTable(ptr long long)
 ;@ stdcall RtlAddMandatoryAce(ptr long long long long ptr)
 @ stdcall RtlAddRefActivationContext(ptr)
-;@ stdcall RtlAddRefMemoryStream
+@ stdcall RtlAddRefMemoryStream(ptr)
 @ stdcall RtlAddVectoredContinueHandler(long ptr)
 @ stdcall RtlAddVectoredExceptionHandler(long ptr)
 ;@ stdcall RtlAddressInSectionTable
 @ stdcall RtlCheckRegistryKey(long ptr)
 @ stdcall RtlClearAllBits(ptr)
 @ stdcall RtlClearBits(ptr long long)
-;@ stdcall RtlCloneMemoryStream
-;@ stdcall RtlCommitMemoryStream
+@ stdcall RtlCloneMemoryStream(ptr ptr)
+@ stdcall RtlCommitMemoryStream(ptr long)
 @ stdcall RtlCompactHeap(long long)
 @ stdcall RtlCompareMemory(ptr ptr long)
 @ stdcall RtlCompareMemoryUlong(ptr long long)
 @ stdcall RtlCopyLuid(ptr ptr)
 @ stdcall RtlCopyLuidAndAttributesArray(long ptr ptr)
 ;@ stdcall RtlCopyMappedMemory
-;@ stdcall RtlCopyMemoryStreamTo
-;@ stdcall RtlCopyOutOfProcessMemoryStreamTo
+@ stdcall RtlCopyMemoryStreamTo(ptr ptr int64 ptr ptr)
+@ stdcall RtlCopyOutOfProcessMemoryStreamTo(ptr ptr int64 ptr ptr) RtlCopyMemoryStreamTo
 ;@ stdcall RtlCopyRangeList ; 5.0 and 5.1 only
 @ stdcall RtlCopySecurityDescriptor(ptr ptr)
 @ stdcall RtlCopySid(long ptr ptr)
 @ stdcall -arch=win32 -ret64 RtlExtendedMagicDivide(double double long)
 @ stdcall RtlFillMemory(ptr long long)
 @ stdcall RtlFillMemoryUlong(ptr long long)
-;@ stdcall RtlFinalReleaseOutOfProcessMemoryStream
+@ stdcall RtlFinalReleaseOutOfProcessMemoryStream(ptr)
 @ stdcall RtlFindActivationContextSectionGuid(long ptr long ptr ptr)
 @ stdcall RtlFindActivationContextSectionString(long ptr long ptr ptr)
 @ stdcall RtlFindCharInUnicodeString(long ptr ptr ptr)
 @ stdcall RtlInitAnsiString(ptr str)
 @ stdcall RtlInitAnsiStringEx(ptr str)
 @ stdcall RtlInitCodePageTable(ptr ptr)
-;@ stdcall RtlInitMemoryStream
+@ stdcall RtlInitMemoryStream(ptr)
 @ stdcall RtlInitNlsTables(ptr ptr ptr ptr)
-;@ stdcall RtlInitOutOfProcessMemoryStream
+@ stdcall RtlInitOutOfProcessMemoryStream(ptr)
 @ stdcall RtlInitString(ptr str)
 @ stdcall RtlInitUnicodeString(ptr wstr)
 @ stdcall RtlInitUnicodeStringEx(ptr wstr)
 @ stdcall RtlLocalTimeToSystemTime(ptr ptr)
 @ stdcall RtlLockBootStatusData(ptr)
 @ stdcall RtlLockHeap(long)
-;@ stdcall RtlLockMemoryStreamRegion
+@ stdcall RtlLockMemoryStreamRegion(ptr int64 int64 long)
 ;@ stdcall RtlLogStackBackTrace
 @ stdcall RtlLookupAtomInAtomTable(ptr wstr ptr)
 @ stdcall RtlLookupElementGenericTable(ptr ptr)
 @ stdcall RtlQueryInformationAcl(ptr ptr long long)
 @ stdcall RtlQueryInformationActivationContext(long long ptr long ptr long ptr)
 @ stdcall RtlQueryInformationActiveActivationContext(long ptr long ptr)
-;@ stdcall RtlQueryInterfaceMemoryStream
+@ stdcall RtlQueryInterfaceMemoryStream(ptr ptr ptr)
 ;@ stdcall RtlQueryProcessBackTraceInformation
 @ stdcall RtlQueryProcessDebugInformation(long long ptr)
 ;@ stdcall RtlQueryProcessHeapInformation
 @ stdcall RtlRandom(ptr)
 @ stdcall RtlRandomEx(ptr)
 @ stdcall RtlReAllocateHeap(long long ptr long)
-;@ stdcall RtlReadMemoryStream
-;@ stdcall RtlReadOutOfProcessMemoryStream
+@ stdcall RtlReadMemoryStream(ptr ptr long ptr)
+@ stdcall RtlReadOutOfProcessMemoryStream(ptr ptr long ptr)
 @ stdcall RtlRealPredecessor(ptr)
 @ stdcall RtlRealSuccessor(ptr)
 @ stdcall RtlRegisterSecureMemoryCacheCallback(ptr)
 @ stdcall RtlRegisterWait(ptr ptr ptr ptr long long)
 @ stdcall RtlReleaseActivationContext(ptr)
-;@ stdcall RtlReleaseMemoryStream
+@ stdcall RtlReleaseMemoryStream(ptr)
 @ stdcall RtlReleasePebLock()
 @ stdcall RtlReleasePrivilege(ptr)
 @ stdcall RtlReleaseRelativeName(ptr)
 @ stdcall RtlResetRtlTranslations(ptr)
 @ stdcall -arch=x86_64 RtlRestoreContext(ptr ptr)
 @ stdcall RtlRestoreLastWin32Error(long) RtlSetLastWin32Error
-;@ stdcall RtlRevertMemoryStream
+@ stdcall RtlRevertMemoryStream(ptr)
 @ stdcall RtlRunDecodeUnicodeString(long ptr)
 @ stdcall RtlRunEncodeUnicodeString(long ptr)
 @ stdcall RtlSecondsSince1970ToTime(long ptr)
 @ stdcall RtlSecondsSince1980ToTime(long ptr)
-;@ stdcall RtlSeekMemoryStream
+@ stdcall RtlSeekMemoryStream(ptr int64 long ptr)
 @ stdcall RtlSelfRelativeToAbsoluteSD2(ptr ptr)
 @ stdcall RtlSelfRelativeToAbsoluteSD(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr)
 @ stdcall RtlSetAllBits(ptr)
 @ stdcall RtlSetIoCompletionCallback(long ptr long)
 @ stdcall RtlSetLastWin32Error(long)
 @ stdcall RtlSetLastWin32ErrorAndNtStatusFromNtStatus(long)
-;@ stdcall RtlSetMemoryStreamSize
+@ stdcall RtlSetMemoryStreamSize(ptr int64)
 @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long)
 @ stdcall RtlSetProcessIsCritical(long ptr long)
 ;@ stdcall RtlSetProperties ; RtlSetProperties
 @ stdcall RtlSleepConditionVariableSRW(ptr ptr ptr long)
 @ stdcall RtlSplay(ptr)
 ;@ stdcall RtlStartRXact
-;@ stdcall RtlStatMemoryStream
+@ stdcall RtlStatMemoryStream(ptr ptr long)
 @ stdcall RtlStringFromGUID(ptr ptr)
 @ stdcall RtlSubAuthorityCountSid(ptr)
 @ stdcall RtlSubAuthoritySid(ptr long)
 @ stdcall RtlUniform(ptr)
 @ stdcall RtlUnlockBootStatusData(ptr)
 @ stdcall RtlUnlockHeap(long)
-;@ stdcall RtlUnlockMemoryStreamRegion
+@ stdcall RtlUnlockMemoryStreamRegion(ptr int64 int64 long)
 @ stdcall -register RtlUnwind(ptr ptr ptr ptr)
 @ stdcall -arch=x86_64 RtlUnwindEx(long long ptr long ptr)
 @ stdcall RtlUpcaseUnicodeChar(long)
 @ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
 @ stdcall RtlWakeAllConditionVariable(ptr)
 @ stdcall RtlWakeConditionVariable(ptr)
-;@ stdcall RtlWriteMemoryStream
+@ stdcall RtlWriteMemoryStream(ptr ptr long ptr)
 @ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
 @ stdcall RtlZeroHeap(ptr long)
 @ stdcall RtlZeroMemory(ptr long)
index 3205fa1..0b13329 100644 (file)
@@ -4152,6 +4152,180 @@ RtlComputeImportTableHash(
 );
 #endif
 
+//
+// MemoryStream functions
+//
+#ifdef NTOS_MODE_USER
+
+NTSYSAPI
+VOID
+NTAPI
+RtlInitMemoryStream(
+    _Out_ PRTL_MEMORY_STREAM Stream
+);
+
+NTSYSAPI
+VOID
+NTAPI
+RtlInitOutOfProcessMemoryStream(
+    _Out_ PRTL_MEMORY_STREAM Stream
+);
+
+NTSYSAPI
+VOID
+NTAPI
+RtlFinalReleaseOutOfProcessMemoryStream(
+    _In_ PRTL_MEMORY_STREAM Stream
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlQueryInterfaceMemoryStream( 
+    _In_ struct IStream *This,
+    _In_ REFIID RequestedIid,
+    _Outptr_ PVOID *ResultObject
+);
+
+NTSYSAPI
+ULONG
+NTAPI
+RtlAddRefMemoryStream( 
+    _In_ struct IStream *This
+);
+
+NTSYSAPI
+ULONG
+NTAPI
+RtlReleaseMemoryStream( 
+    _In_ struct IStream *This
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlReadMemoryStream( 
+    _In_ struct IStream *This,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesRead
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlReadOutOfProcessMemoryStream( 
+    _In_ struct IStream *This,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesRead
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlSeekMemoryStream( 
+    _In_ struct IStream *This,
+    _In_ LARGE_INTEGER RelativeOffset,
+    _In_ ULONG Origin,
+    _Out_opt_ PULARGE_INTEGER ResultOffset
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlCopyMemoryStreamTo( 
+    _In_ struct IStream *This,
+    _In_ struct IStream *Target,
+    _In_ ULARGE_INTEGER Length,
+    _Out_opt_ PULARGE_INTEGER BytesRead,
+    _Out_opt_ PULARGE_INTEGER BytesWritten
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlCopyOutOfProcessMemoryStreamTo( 
+    _In_ struct IStream *This,
+    _In_ struct IStream *Target,
+    _In_ ULARGE_INTEGER Length,
+    _Out_opt_ PULARGE_INTEGER BytesRead,
+    _Out_opt_ PULARGE_INTEGER BytesWritten
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlStatMemoryStream( 
+    _In_ struct IStream *This,
+    _Out_ struct tagSTATSTG *Stats,
+    _In_ ULONG Flags
+);
+
+// Dummy functions
+NTSYSAPI
+HRESULT
+NTAPI
+RtlWriteMemoryStream( 
+    _In_ struct IStream *This,
+    _In_reads_bytes_(Length) CONST VOID *Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesWritten
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlSetMemoryStreamSize( 
+    _In_ struct IStream *This,
+    _In_ ULARGE_INTEGER NewSize
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlCommitMemoryStream( 
+    _In_ struct IStream *This,
+    _In_ ULONG CommitFlags
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlRevertMemoryStream( 
+    _In_ struct IStream *This
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlLockMemoryStreamRegion( 
+    _In_ struct IStream *This,
+    _In_ ULARGE_INTEGER Offset,
+    _In_ ULARGE_INTEGER Length,
+    _In_ ULONG LockType
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlUnlockMemoryStreamRegion( 
+    _In_ struct IStream *This,
+    _In_ ULARGE_INTEGER Offset,
+    _In_ ULARGE_INTEGER Length,
+    _In_ ULONG LockType
+);
+
+NTSYSAPI
+HRESULT
+NTAPI
+RtlCloneMemoryStream( 
+    _In_ struct IStream *This,
+    _Outptr_ struct IStream **ResultStream
+);
+
+#endif // NTOS_MODE_USER
+
 #ifdef __cplusplus
 }
 #endif
index 825d62b..7620c5c 100644 (file)
@@ -1559,6 +1559,44 @@ typedef struct _MESSAGE_RESOURCE_DATA
 
 #endif /* !NTOS_MODE_USER */
 
+#ifdef NTOS_MODE_USER
+
+//
+// Memory Stream
+//
+#ifndef CONST_VTBL
+#ifdef CONST_VTABLE
+#define CONST_VTBL const
+#else
+#define CONST_VTBL
+#endif
+#endif
+
+struct IStreamVtbl;
+struct IStream;
+struct tagSTATSTG;
+
+typedef struct _RTL_MEMORY_STREAM RTL_MEMORY_STREAM, *PRTL_MEMORY_STREAM;
+
+typedef VOID 
+(NTAPI *PRTL_MEMORY_STREAM_FINAL_RELEASE_ROUTINE)(
+    _In_ PRTL_MEMORY_STREAM Stream
+);
+
+struct _RTL_MEMORY_STREAM
+{
+    CONST_VTBL struct IStreamVtbl *Vtbl;
+    LONG RefCount;
+    ULONG Unk1;
+    PVOID Current;
+    PVOID Start;
+    PVOID End;
+    PRTL_MEMORY_STREAM_FINAL_RELEASE_ROUTINE FinalRelease;
+    HANDLE ProcessHandle;
+};
+
+#endif /* NTOS_MODE_USER */
+
 #ifdef __cplusplus
 }
 #endif
index 56e698e..e584c06 100644 (file)
@@ -33,6 +33,7 @@ list(APPEND SOURCE
     heapuser.c
     image.c
     interlck.c
+    memstream.c
     message.c
     largeint.c
     luid.c
diff --git a/reactos/lib/rtl/memstream.c b/reactos/lib/rtl/memstream.c
new file mode 100644 (file)
index 0000000..776fbc6
--- /dev/null
@@ -0,0 +1,469 @@
+/* COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            lib/rtl/mem.c
+ * PURPOSE:         MemoryStream functions
+ * PROGRAMMER:      David Quintana (gigaherz@gmail.com)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define COBJMACROS
+#define CONST_VTABLE
+
+#include <rtl.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* VIRTUAL METHOD TABLES ******************************************************/
+
+const struct IStreamVtbl RtlMemoryStreamVtbl =
+{
+    RtlQueryInterfaceMemoryStream,
+    RtlAddRefMemoryStream,
+    RtlReleaseMemoryStream,
+    RtlReadMemoryStream,
+    RtlWriteMemoryStream,
+    RtlSeekMemoryStream,
+    RtlSetMemoryStreamSize,
+    RtlCopyMemoryStreamTo,
+    RtlCommitMemoryStream,
+    RtlRevertMemoryStream,
+    RtlLockMemoryStreamRegion,
+    RtlUnlockMemoryStreamRegion,
+    RtlStatMemoryStream,
+    RtlCloneMemoryStream,
+};
+
+const struct IStreamVtbl RtlOutOfProcessMemoryStreamVtbl =
+{
+    RtlQueryInterfaceMemoryStream,
+    RtlAddRefMemoryStream,
+    RtlReleaseMemoryStream,
+    RtlReadOutOfProcessMemoryStream,
+    RtlWriteMemoryStream,
+    RtlSeekMemoryStream,
+    RtlSetMemoryStreamSize,
+    RtlCopyMemoryStreamTo,
+    RtlCommitMemoryStream,
+    RtlRevertMemoryStream,
+    RtlLockMemoryStreamRegion,
+    RtlUnlockMemoryStreamRegion,
+    RtlStatMemoryStream,
+    RtlCloneMemoryStream,
+};
+
+/* FUNCTIONS ******************************************************************/
+
+static
+PRTL_MEMORY_STREAM
+IStream_To_RTL_MEMORY_STREAM(
+    _In_ IStream *Interface)
+{
+    if (Interface == NULL)
+        return NULL;
+
+    return CONTAINING_RECORD(Interface, RTL_MEMORY_STREAM, Vtbl);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RtlInitMemoryStream(
+    _Out_ PRTL_MEMORY_STREAM Stream)
+{
+    RtlZeroMemory(Stream, sizeof(RTL_MEMORY_STREAM));
+    Stream->Vtbl = &RtlMemoryStreamVtbl;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RtlInitOutOfProcessMemoryStream(
+    _Out_ PRTL_MEMORY_STREAM Stream)
+{
+    RtlZeroMemory(Stream, sizeof(RTL_MEMORY_STREAM));
+    Stream->Vtbl = &RtlOutOfProcessMemoryStreamVtbl;
+    Stream->FinalRelease = RtlFinalReleaseOutOfProcessMemoryStream;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+RtlFinalReleaseOutOfProcessMemoryStream(
+    _In_ PRTL_MEMORY_STREAM Stream)
+{
+    UNIMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlQueryInterfaceMemoryStream(
+    _In_ IStream *This,
+    _In_ REFIID RequestedIid,
+    _Outptr_ PVOID *ResultObject)
+{
+    if (IsEqualGUID(RequestedIid, &IID_IUnknown) ||
+        IsEqualGUID(RequestedIid, &IID_ISequentialStream) ||
+        IsEqualGUID(RequestedIid, &IID_IStream))
+    {
+        IStream_AddRef(This);
+        *ResultObject = This;
+        return S_OK;
+    }
+
+    *ResultObject = NULL;
+    return E_NOINTERFACE;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlAddRefMemoryStream(
+    _In_ IStream *This)
+{
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+
+    return InterlockedIncrement(&Stream->RefCount);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+RtlReleaseMemoryStream(
+    _In_ IStream *This)
+{
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+    LONG Result;
+
+    Result = InterlockedDecrement(&Stream->RefCount);
+
+    if (Result == 0)
+    {
+        if (Stream->FinalRelease)
+            Stream->FinalRelease(Stream);
+    }
+
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlReadMemoryStream(
+    _In_ IStream *This,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesRead)
+{
+    ULONG CopyLength;
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+    SIZE_T Available = (PUCHAR)Stream->End - (PUCHAR)Stream->Current;
+
+    if (BytesRead)
+        *BytesRead = 0;
+
+    if (!Length)
+        return S_OK;
+
+    CopyLength = min(Available, Length);
+
+    RtlMoveMemory(Buffer, Stream->Current, CopyLength);
+
+    Stream->Current = (PUCHAR)Stream->Current + CopyLength;
+
+    *BytesRead = CopyLength;
+
+    return S_OK;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlReadOutOfProcessMemoryStream(
+    _In_ IStream *This,
+    _Out_writes_bytes_(Length) PVOID Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesRead)
+{
+    NTSTATUS Status;
+    ULONG CopyLength;
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+    SIZE_T Available = (PUCHAR)Stream->End - (PUCHAR)Stream->Current;
+
+    if (BytesRead)
+        *BytesRead = 0;
+
+    if (!Length)
+        return S_OK;
+
+    CopyLength = min(Available, Length);
+
+    Status = NtReadVirtualMemory(Stream->ProcessHandle,
+                                 Stream->Current,
+                                 Buffer,
+                                 CopyLength,
+                                 BytesRead);
+
+    if (NT_SUCCESS(Status))
+        Stream->Current = (PUCHAR)Stream->Current + *BytesRead;
+
+    return HRESULT_FROM_WIN32(RtlNtStatusToDosError(Status));
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlSeekMemoryStream(
+    _In_ IStream *This,
+    _In_ LARGE_INTEGER RelativeOffset,
+    _In_ ULONG Origin,
+    _Out_opt_ PULARGE_INTEGER ResultOffset)
+{
+    PVOID NewPosition;
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+
+    switch (Origin)
+    {
+        case STREAM_SEEK_SET:
+            NewPosition = (PUCHAR)Stream->Start + RelativeOffset.QuadPart;
+            break;
+
+        case STREAM_SEEK_CUR:
+            NewPosition = (PUCHAR)Stream->Current + RelativeOffset.QuadPart;
+            break;
+
+        case STREAM_SEEK_END:
+            NewPosition = (PUCHAR)Stream->End - RelativeOffset.QuadPart;
+            break;
+
+        default:
+            return E_INVALIDARG;
+    }
+
+    if (NewPosition < Stream->Start || NewPosition > Stream->End)
+        return STG_E_INVALIDPOINTER;
+
+    Stream->Current = NewPosition;
+
+    if (ResultOffset)
+        ResultOffset->QuadPart = (PUCHAR)Stream->Current - (PUCHAR)Stream->Start;
+
+    return S_OK;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlCopyMemoryStreamTo(
+    _In_ IStream *This,
+    _In_ IStream *Target,
+    _In_ ULARGE_INTEGER Length,
+    _Out_opt_ PULARGE_INTEGER BytesRead,
+    _Out_opt_ PULARGE_INTEGER BytesWritten)
+{
+    CHAR Buffer[1024];
+    ULONGLONG TotalSize;
+    ULONG Left, Amount;
+    HRESULT Result;
+
+    if (BytesRead)
+        BytesRead->QuadPart = 0;
+    if (BytesWritten)
+        BytesWritten->QuadPart = 0;
+
+    if (!Target)
+        return S_OK;
+
+    if (!Length.QuadPart)
+        return S_OK;
+
+    /* Copy data */
+    TotalSize = Length.QuadPart;
+    while (TotalSize)
+    {
+        Left = min(TotalSize, sizeof(Buffer));
+
+        /* Read */
+        Result = IStream_Read(This, Buffer, Left, &Amount);
+        if (BytesRead)
+            BytesRead->QuadPart += Amount;
+        if (FAILED(Result) || Amount == 0)
+            break;
+
+        Left = Amount;
+
+        /* Write */
+        Result = IStream_Write(Target, Buffer, Left, &Amount);
+        if (BytesWritten)
+            BytesWritten->QuadPart += Amount;
+        if (FAILED(Result) || Amount != Left)
+            break;
+
+        TotalSize -= Left;
+    }
+    return Result;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlStatMemoryStream(
+    _In_ IStream *This,
+    _Out_ STATSTG *Stats,
+    _In_ ULONG Flags)
+{
+    PRTL_MEMORY_STREAM Stream = IStream_To_RTL_MEMORY_STREAM(This);
+
+    if (!Stats)
+        return STG_E_INVALIDPOINTER;
+
+    RtlZeroMemory(Stats, sizeof(STATSTG));
+    Stats->type = STGTY_STREAM;
+    Stats->cbSize.QuadPart = (PUCHAR)Stream->End - (PUCHAR)Stream->Start;
+
+    return S_OK;
+}
+
+/* DUMMY FUNCTIONS ************************************************************/
+/*
+ * The following functions return E_NOTIMPL in Windows Server 2003.
+ */
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlWriteMemoryStream(
+    _In_ IStream *This,
+    _In_reads_bytes_(Length) CONST VOID *Buffer,
+    _In_ ULONG Length,
+    _Out_opt_ PULONG BytesWritten)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(Buffer);
+    UNREFERENCED_PARAMETER(Length);
+    UNREFERENCED_PARAMETER(BytesWritten);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlSetMemoryStreamSize(
+    _In_ IStream *This,
+    _In_ ULARGE_INTEGER NewSize)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(NewSize);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlCommitMemoryStream(
+    _In_ IStream *This,
+    _In_ ULONG CommitFlags)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(CommitFlags);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlRevertMemoryStream(
+    _In_ IStream *This)
+{
+    UNREFERENCED_PARAMETER(This);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlLockMemoryStreamRegion(
+    _In_ IStream *This,
+    _In_ ULARGE_INTEGER Offset,
+    _In_ ULARGE_INTEGER Length,
+    _In_ ULONG LockType)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(Offset);
+    UNREFERENCED_PARAMETER(Length);
+    UNREFERENCED_PARAMETER(LockType);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlUnlockMemoryStreamRegion(
+    _In_ IStream *This,
+    _In_ ULARGE_INTEGER Offset,
+    _In_ ULARGE_INTEGER Length,
+    _In_ ULONG LockType)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(Offset);
+    UNREFERENCED_PARAMETER(Length);
+    UNREFERENCED_PARAMETER(LockType);
+
+    return E_NOTIMPL;
+}
+
+/*
+ * @implemented
+ */
+HRESULT
+NTAPI
+RtlCloneMemoryStream(
+    _In_ IStream *This,
+    _Outptr_ IStream **ResultStream)
+{
+    UNREFERENCED_PARAMETER(This);
+    UNREFERENCED_PARAMETER(ResultStream);
+
+    return E_NOTIMPL;
+}