From fec54daadda821f16f5afa8bb24d14bf3da7639d Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sat, 19 Oct 2013 17:48:27 +0000 Subject: [PATCH] [RTL] - Implement Rtl MemoryStream functions. Patch by David Quintana. CORE-7492 svn path=/trunk/; revision=60705 --- reactos/dll/ntdll/CMakeLists.txt | 1 + reactos/dll/ntdll/def/ntdll.spec | 38 +-- reactos/include/ndk/rtlfuncs.h | 174 ++++++++++++ reactos/include/ndk/rtltypes.h | 38 +++ reactos/lib/rtl/CMakeLists.txt | 1 + reactos/lib/rtl/memstream.c | 469 +++++++++++++++++++++++++++++++ 6 files changed, 702 insertions(+), 19 deletions(-) create mode 100644 reactos/lib/rtl/memstream.c diff --git a/reactos/dll/ntdll/CMakeLists.txt b/reactos/dll/ntdll/CMakeLists.txt index 83e999970fd..9e51fc2ce7a 100644 --- a/reactos/dll/ntdll/CMakeLists.txt +++ b/reactos/dll/ntdll/CMakeLists.txt @@ -52,6 +52,7 @@ target_link_libraries(ntdll rtl ntdllsys libcntpr + uuid ${PSEH_LIB}) add_pch(ntdll include/ntdll.h) diff --git a/reactos/dll/ntdll/def/ntdll.spec b/reactos/dll/ntdll/def/ntdll.spec index a8c3d92b747..b45adaf0ec1 100644 --- a/reactos/dll/ntdll/def/ntdll.spec +++ b/reactos/dll/ntdll/def/ntdll.spec @@ -405,7 +405,7 @@ @ 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 @@ -440,8 +440,8 @@ @ 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) @@ -464,8 +464,8 @@ @ 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) @@ -571,7 +571,7 @@ @ 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) @@ -658,9 +658,9 @@ @ 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) @@ -735,7 +735,7 @@ @ 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) @@ -781,7 +781,7 @@ @ 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 @@ -800,14 +800,14 @@ @ 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) @@ -820,12 +820,12 @@ @ 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) @@ -844,7 +844,7 @@ @ 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 @@ -869,7 +869,7 @@ @ 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) @@ -907,7 +907,7 @@ @ 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) @@ -938,7 +938,7 @@ @ 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) diff --git a/reactos/include/ndk/rtlfuncs.h b/reactos/include/ndk/rtlfuncs.h index 3205fa1a7c8..0b1332923b9 100644 --- a/reactos/include/ndk/rtlfuncs.h +++ b/reactos/include/ndk/rtlfuncs.h @@ -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 diff --git a/reactos/include/ndk/rtltypes.h b/reactos/include/ndk/rtltypes.h index 825d62bc13f..7620c5c7f99 100644 --- a/reactos/include/ndk/rtltypes.h +++ b/reactos/include/ndk/rtltypes.h @@ -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 diff --git a/reactos/lib/rtl/CMakeLists.txt b/reactos/lib/rtl/CMakeLists.txt index 56e698e14e4..e584c063a6e 100644 --- a/reactos/lib/rtl/CMakeLists.txt +++ b/reactos/lib/rtl/CMakeLists.txt @@ -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 index 00000000000..776fbc64f77 --- /dev/null +++ b/reactos/lib/rtl/memstream.c @@ -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 + +#define NDEBUG +#include + +/* 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; +}