|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
ntrtlstringandbuffer.h
Abstract:
Broken out from nturtl and rtl so I can move it between them in seperate trees without merge madness. To be integrated into ntrtl.h
Author:
Jay Krell (a-JayK) December 2000
Environment:
Revision History:
--*/
#ifndef _NTRTL_STRING_AND_BUFFER_
#define _NTRTL_STRING_AND_BUFFER_
#if _MSC_VER >= 1100
#pragma once
#endif
#ifdef __cplusplus
extern "C" { #endif
#if defined (_MSC_VER)
#if ( _MSC_VER >= 800 )
#pragma warning(disable:4514)
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable:4001)
#pragma warning(disable:4201)
#pragma warning(disable:4214)
#endif
#endif
//
// not NTSYSAPI so easily statically linked to
//
//
// These work for both UNICODE_STRING and STRING.
// That's why "plain" 0 and sizeof(Buffer[0]) is used.
//
// odd but correct use of RTL_STRING_IS_PUT_AT_SAFE instead of RTL_STRING_IS_GET_AT_SAFE,
// we are reaching past the Length
#define RTL_STRING_IS_NUL_TERMINATED(s) (RTL_STRING_IS_PUT_AT_SAFE(s, RTL_STRING_GET_LENGTH_CHARS(s), 0) \
&& RTL_STRING_GET_AT_UNSAFE(s, RTL_STRING_GET_LENGTH_CHARS(s)) == 0)
#define RTL_STRING_NUL_TERMINATE(s) ((VOID)(ASSERT(RTL_STRING_IS_PUT_AT_SAFE(s, RTL_STRING_GET_LENGTH_CHARS(s), 0)), \
((s)->Buffer[RTL_STRING_GET_LENGTH_CHARS(s)] = 0)))
#define RTL_NUL_TERMINATE_STRING(s) (RTL_STRING_NUL_TERMINATE(s)) /* compatibility */
#define RTL_STRING_MAKE_LENGTH_INCLUDE_TERMINAL_NUL(s) ((VOID)(ASSERT(RTL_STRING_IS_NUL_TERMINATED(s)), \
((s)->Length += sizeof((s)->Buffer[0]))))
#define RTL_STRING_IS_EMPTY(s) ((s)->Length == 0)
#define RTL_STRING_GET_LAST_CHAR(s) (RTL_STRING_GET_AT((s), RTL_STRING_GET_LENGTH_CHARS(s) - 1))
#define RTL_STRING_GET_LENGTH_CHARS(s) ((s)->Length / sizeof((s)->Buffer[0]))
#define RTL_STRING_GET_MAX_LENGTH_CHARS(s) ((s)->MaximumLength / sizeof((s)->Buffer[0]))
#define RTL_STRING_GET_LENGTH_BYTES(s) ((s)->Length)
#define RTL_STRING_SET_LENGTH_CHARS_UNSAFE(s,n) ((s)->Length = (RTL_STRING_LENGTH_TYPE)(((n) * sizeof(s)->Buffer[0])))
//
// We don't provide an explicit/retail RTL_STRING_GET_AT_SAFE because it'd
// need a return value distinct from all values of c. -1? NTSTATUS? Seems too heavy.
//
// For consistency then, we also don't provide RTL_STRING_PUT_AT_SAFE.
//
#define RTL_STRING_IS_GET_AT_SAFE(s,n) ((n) < RTL_STRING_GET_LENGTH_CHARS(s))
#define RTL_STRING_GET_AT_UNSAFE(s,n) ((s)->Buffer[n])
#define RTLP_STRING_GET_AT_SAFE(s,n) (RTL_STRING_IS_GET_AT_SAFE(s,n) ? RTL_STRING_GET_AT_UNSAFE(s,n) : 0)
#define RTL_STRING_IS_PUT_AT_SAFE(s,n,c) ((n) < RTL_STRING_GET_MAX_LENGTH_CHARS(s))
#define RTL_STRING_PUT_AT_UNSAFE(s,n,c) ((s)->Buffer[n] = (c))
#define RTLP_STRING_PUT_AT_SAFE(s,n,c) ((void)(RTL_STRING_IS_PUT_AT_SAFE(s,n,c) ? RTL_STRING_PUT_AT_UNSAFE(s,n,c) : 0))
#if defined(RTL_STRING_RANGE_CHECKED)
#define RTL_STRING_GET_AT(s,n) (ASSERT(RTL_STRING_IS_GET_AT_SAFE(s,n)), \
RTL_STRING_GET_AT_UNSAFE(s,n)) #else
#define RTL_STRING_GET_AT(s,n) (RTL_STRING_GET_AT_UNSAFE(s,n))
#endif
#if defined(RTL_STRING_RANGE_CHECKED)
#define RTL_STRING_PUT_AT(s,n,c) (ASSERT(RTL_STRING_IS_PUT_AT_SAFE(s,n,c)), \
RTL_STRING_PUT_AT_UNSAFE(s,n,c)) #else
#define RTL_STRING_PUT_AT(s,n,c) (RTL_STRING_PUT_AT_UNSAFE(s,n,c))
#endif
//
// preallocated heap-growable buffers
//
struct _RTL_BUFFER;
#if !defined(RTL_BUFFER)
// This is duplicated in ntldr.h.
#define RTL_BUFFER RTL_BUFFER
typedef struct _RTL_BUFFER { PUCHAR Buffer; PUCHAR StaticBuffer; SIZE_T Size; SIZE_T StaticSize; SIZE_T ReservedForAllocatedSize; // for future doubling
PVOID ReservedForIMalloc; // for future pluggable growth
} RTL_BUFFER, *PRTL_BUFFER;
#endif
#define RTLP_BUFFER_IS_HEAP_ALLOCATED(b) ((b)->Buffer != (b)->StaticBuffer)
//++
//
// NTSTATUS
// RtlInitBuffer(
// OUT PRTL_BUFFER Buffer,
// IN PUCHAR StaticBuffer,
// IN SIZE_T StaticSize
// );
//
// Routine Description:
//
// Initialize a preallocated heap-growable buffer.
//
// Arguments:
//
// Buffer - "this"
// StaticBuffer - preallocated storage for Buffer to use until/unless more than StaticSize is needed
// StaticSize - the size of StaticBuffer in bytes
//
// Return Value:
//
// STATUS_SUCCESS
//
//--
#define RtlInitBuffer(Buff, StatBuff, StatSize) \
do { \ (Buff)->Buffer = (StatBuff); \ (Buff)->Size = (StatSize); \ (Buff)->StaticBuffer = (StatBuff); \ (Buff)->StaticSize = (StatSize); \ } while (0)
#define RTL_ENSURE_BUFFER_SIZE_NO_COPY (0x00000001)
NTSTATUS NTAPI RtlpEnsureBufferSize( IN ULONG Flags, IN OUT PRTL_BUFFER Buffer, IN SIZE_T NewSizeBytes );
//++
//
// NTSTATUS
// RtlEnsureBufferSize(
// IN OUT PRTL_BUFFER Buffer,
// IN SIZE_T NewSizeBytes
// );
//
// Routine Description:
//
// If Buffer is smaller than NewSize, grow it to NewSize, using the static buffer if it
// is large enough, else heap allocating
//
// Arguments:
//
// Flags -
// RTL_ENSURE_BUFFER_SIZE_NO_COPY
// Buffer -
// NewSizeBytes -
//
// Return Value:
//
// STATUS_SUCCESS
// STATUS_NO_MEMORY
//
//--
#define RtlEnsureBufferSize(Flags, Buff, NewSizeBytes) \
( ((Buff) != NULL && (NewSizeBytes) <= (Buff)->Size) \ ? STATUS_SUCCESS \ : RtlpEnsureBufferSize((Flags), (Buff), (NewSizeBytes)) \ )
//++
//
// VOID
// RtlFreeBuffer(
// IN OUT PRTL_BUFFER Buffer,
// );
//
//
// Routine Description:
//
// Free any heap allocated storage associated with Buffer.
// Notes:
// - RtlFreeBuffer returns a buffer to the state it was in after
// calling RtlInitBuffer, so you may reuse it.
// - If you want to shrink the buffer without freeing it, just poke Buffer->Size down.
// This is safe regardless of if the buffer has gone heap allocated or not.
// - You may RtlFreeBuffer an RTL_BUFFER that is all zeros. You do not need to track if you
// called RtlInitBuffer if you know you filled it with zeros.
// - You may RtlFreeBuffer an RTL_BUFFER repeatedly.
//
// Arguments:
//
// Buffer -
//
// Return Value:
//
// none, unconditional success
//
//--
#define RtlFreeBuffer(Buff) \
do { \ if ((Buff) != NULL && (Buff)->Buffer != NULL) { \ if (RTLP_BUFFER_IS_HEAP_ALLOCATED(Buff)) { \ UNICODE_STRING UnicodeString; \ UnicodeString.Buffer = (PWSTR)(PVOID)(Buff)->Buffer; \ RtlFreeUnicodeString(&UnicodeString); \ } \ (Buff)->Buffer = (Buff)->StaticBuffer; \ (Buff)->Size = (Buff)->StaticSize; \ } \ } while (0)
//
// a preallocated buffer that is "tied" to a UNICODE_STRING
//
struct _RTL_UNICODE_STRING_BUFFER;
typedef struct _RTL_UNICODE_STRING_BUFFER { UNICODE_STRING String; RTL_BUFFER ByteBuffer; UCHAR MinimumStaticBufferForTerminalNul[sizeof(WCHAR)]; } RTL_UNICODE_STRING_BUFFER, *PRTL_UNICODE_STRING_BUFFER;
//
// MAX_UNICODE_STRING_MAXLENGTH is the maximum allowed value for UNICODE_STRING::MaximumLength.
// MAX_UNICODE_STRING_LENGTH is the maximum allowed value for UNICODE_STRING::Length, allowing
// room for a terminal nul.
//
// Explanation of MAX_UNICODE_STRING_MAXLENGTH implementation
// ~0 is all bits set, maximum value in two's complement arithmetic, which C guarantees for unsigned types
// << shifts out the number of bits that fit in UNICODE_STRING::Length
// ~ and now we have all bits set that fit in UNICODE_STRING::Length,
// like if UNICODE_STRING::Length is 16 bits, we have 0xFFFF
// then mask so it is even multiple of whatever UNICODE_STRING::Buffer points to.
// If Length is changed to ULONG or SIZE_T, this macro is still correct.
// If Buffer pointed to CHAR or "WIDER_CHAR" or something else, this macro is still correct.
//
#define MAX_UNICODE_STRING_MAXLENGTH ((~((~(SIZE_T)0) << (RTL_FIELD_SIZE(UNICODE_STRING, Length) * CHAR_BIT))) & ~(sizeof(((PCUNICODE_STRING)0)->Buffer[0]) - 1))
#define MAX_UNICODE_STRING_LENGTH (MAX_UNICODE_STRING_MAXLENGTH - sizeof(((PCUNICODE_STRING)0)->Buffer[0]))
//++
//
// NTSTATUS
// RtlInitUnicodeStringBuffer(
// OUT PRTL_UNICODE_STRING_BUFFER Buffer,
// IN PUCHAR StaticBuffer,
// IN SIZE_T StaticSize
// );
//
// Routine Description:
//
//
// Arguments:
//
// Buffer -
// StaticBuffer - can be NULL, but generally is not
// StaticSize - should be at least sizeof(WCHAR), but can be zero
// ought to be an even multiple of sizeof(WCHAR)
// gets rounded to down to an even multiple of sizeof(WCHAR)
// gets clamped to MAX_UNICODE_STRING_MAXLENGTH (64k - 2)
//
// RTL_UNICODE_STRING_BUFFER contains room for the terminal nul for the
// case of StaticBuffer == NULL or StaticSize < sizeof(WCHAR), or, more likely,
// for RtlTakeRemainingStaticBuffer leaving it with no static buffer.
//
// Return Value:
//
// STATUS_SUCCESS
//
//--
#define RtlInitUnicodeStringBuffer(Buff, StatBuff, StatSize) \
do { \ SIZE_T TempStaticSize = (StatSize); \ PUCHAR TempStaticBuff = (StatBuff); \ TempStaticSize &= ~(sizeof((Buff)->String.Buffer[0]) - 1); \ if (TempStaticSize > UNICODE_STRING_MAX_BYTES) { \ TempStaticSize = UNICODE_STRING_MAX_BYTES; \ } \ if (TempStaticSize < sizeof(WCHAR)) { \ TempStaticBuff = (Buff)->MinimumStaticBufferForTerminalNul; \ TempStaticSize = sizeof(WCHAR); \ } \ RtlInitBuffer(&(Buff)->ByteBuffer, TempStaticBuff, TempStaticSize); \ (Buff)->String.Buffer = (WCHAR*)TempStaticBuff; \ if ((Buff)->String.Buffer != NULL) \ (Buff)->String.Buffer[0] = 0; \ (Buff)->String.Length = 0; \ (Buff)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)TempStaticSize; \ } while (0)
//++
//
// NTSTATUS
// RtlSyncStringToBuffer(
// IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer
// );
//
// Routine Description:
//
// After carefully modifying the underlying RTL_BUFFER, this updates
// dependent fields in the underlying UNICODE_STRING.
//
// For example, use this after you grow the buffer with RtlEnsureBufferSize,
// but that example you don't need, use RtlEnsureUnicodeStringBufferSizeChars
// or RtlEnsureStringBufferSizeBytes.
//
// Arguments:
//
// UnicodeStringBuffer -
//
// Return Value:
//
// STATUS_SUCCESS - hooray
//
//--
#define RtlSyncStringToBuffer(x) \
( \ ( ASSERT((x)->String.Length < (x)->ByteBuffer.Size) ), \ ( ASSERT((x)->String.MaximumLength >= (x)->String.Length) ), \ ( ASSERT((x)->String.MaximumLength <= (x)->ByteBuffer.Size) ), \ ( (x)->String.Buffer = (PWSTR)(x)->ByteBuffer.Buffer ), \ ( (x)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)((x)->ByteBuffer.Size) ), \ ( ASSERT(RTL_STRING_IS_NUL_TERMINATED(&(x)->String)) ), \ ( STATUS_SUCCESS ) \ )
//++
//
// NTSTATUS
// RtlSyncBufferToString(
// IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer
// );
//
// Routine Description:
//
// After carefully modifying the underlying UNICODE_STRING, this updates
// dependent fields in the underlying RTL_BUFFER.
//
// For example, use this after you the alloc the buffer with RtlAnsiStringToUnicodeString.
// This is possible because RTL_BUFFER deliberately uses the same memory allocator
// as RtlAnsiStringToUnicodeString.
//
// Arguments:
//
// UnicodeStringBuffer -
//
// Return Value:
//
// STATUS_SUCCESS - hooray
//
//--
#define RtlSyncBufferToString(Buff_) \
( \ ( (Buff_)->ByteBuffer.Buffer = (Buff_)->String.Buffer ), \ ( (Buff_)->ByteBuffer.Buffer.Size = (Buff_)->String.MaximumLength ), \ ( STATUS_SUCCESS ) \ )
//++
//
// NTSTATUS
// RtlEnsureUnicodeStringBufferSizeChars(
// IN OUT PRTL_BUFFER Buffer,
// IN USHORT NewSizeChars
// );
//
// NTSTATUS
// RtlEnsureUnicodeStringBufferSizeBytes(
// IN OUT PRTL_BUFFER Buffer,
// IN USHORT NewSizeBytes
// );
//
// Routine Description:
//
// Optionally multiply cch to go from count of character to count of bytes.
// +1 or +2 for you to account for the terminal nul.
// Delegate to underlying RtlEnsureBufferSize.
// Keep String.Buffer, .MaximumLength, and terminal nul in sync.
//
// Arguments:
//
// Buffer -
// NewSizeChars -
// NewSizeBytes - must be a multiple of sizeof(WCHAR), and we don't presently
// verify that.
//
// Return Value:
//
// STATUS_SUCCESS - hooray
// STATUS_NO_MEMORY - out of memory
// STATUS_NAME_TOO_LONG - (NewSizeChars + 1) * sizeof(WCHAR) > UNICODE_STRING_MAX_BYTES (USHORT)
//
//--
#define RtlEnsureUnicodeStringBufferSizeBytes(Buff_, NewSizeBytes_) \
( ( ((NewSizeBytes_) + sizeof((Buff_)->String.Buffer[0])) > UNICODE_STRING_MAX_BYTES ) \ ? STATUS_NAME_TOO_LONG \ : !NT_SUCCESS(RtlEnsureBufferSize(0, &(Buff_)->ByteBuffer, ((NewSizeBytes_) + sizeof((Buff_)->String.Buffer[0])))) \ ? STATUS_NO_MEMORY \ : (RtlSyncStringToBuffer(Buff_)) \ )
#define RtlEnsureUnicodeStringBufferSizeChars(Buff_, NewSizeChars_) \
(RtlEnsureUnicodeStringBufferSizeBytes((Buff_), (NewSizeChars_) * sizeof((Buff_)->String.Buffer[0])))
//++
//
// NTSTATUS
// RtlAppendUnicodeStringBuffer(
// OUT PRTL_UNICODE_STRING_BUFFER Destination,
// IN PCUNICODE_STRING Source
// );
//
// Routine Description:
//
//
// Arguments:
//
// Destination -
// Source -
//
// Return Value:
//
// STATUS_SUCCESS
// STATUS_NO_MEMORY
// STATUS_NAME_TOO_LONG (64K UNICODE_STRING length would be exceeded)
//
//--
#define RtlAppendUnicodeStringBuffer(Dest, Source) \
( ( ( (Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]) ) > UNICODE_STRING_MAX_BYTES ) \ ? STATUS_NAME_TOO_LONG \ : (!NT_SUCCESS( \ RtlEnsureBufferSize( \ 0, \ &(Dest)->ByteBuffer, \ (Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]) ) ) \ ? STATUS_NO_MEMORY \ : ( ( (Dest)->String.Buffer = (PWSTR)(Dest)->ByteBuffer.Buffer ), \ ( RtlMoveMemory( \ (Dest)->String.Buffer + (Dest)->String.Length / sizeof((Dest)->String.Buffer[0]), \ (Source)->Buffer, \ (Source)->Length) ), \ ( (Dest)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)((Dest)->String.Length + (Source)->Length + sizeof((Dest)->String.Buffer[0]))), \ ( (Dest)->String.Length = (USHORT) ((Dest)->String.Length + (Source)->Length )), \ ( (Dest)->String.Buffer[(Dest)->String.Length / sizeof((Dest)->String.Buffer[0])] = 0 ), \ ( STATUS_SUCCESS ) ) ) )
NTSTATUS NTAPI RtlMultiAppendUnicodeStringBuffer( OUT PRTL_UNICODE_STRING_BUFFER Destination, IN ULONG NumberOfSources, IN const UNICODE_STRING* SourceArray );
//++
//
// VOID
// RtlFreeUnicodeStringBuffer(
// OUT PRTL_UNICODE_STRING_BUFFER Buffer
// );
//
// Routine Description:
//
// Arguments:
//
// Buffer -
//
// Return Value:
//
// none, unconditional success
//
// If Buffer is a local, the stores are generally "dead" (their result
// is never read) and the optimizer should "kill" them (not bother performing them).
//
// A buffer can be freed multiple times.
// A buffer that has been freed is in the same state as one that just been inited.
// A buffer that is all zeros (RtlZeroMemory) can be freed. You do not need to
// track if you inited it.
//--
#define RtlFreeUnicodeStringBuffer(Buff) \
do { \ if ((Buff) != NULL) { \ RtlFreeBuffer(&(Buff)->ByteBuffer); \ (Buff)->String.Buffer = (PWSTR)(Buff)->ByteBuffer.StaticBuffer; \ if ((Buff)->String.Buffer != NULL) \ (Buff)->String.Buffer[0] = 0; \ (Buff)->String.Length = 0; \ (Buff)->String.MaximumLength = (RTL_STRING_LENGTH_TYPE)(Buff)->ByteBuffer.StaticSize; \ } \ } while (0)
//++
//
// NTSTATUS
// RtlAssignUnicodeStringBuffer(
// IN OUT PRTL_UNICODE_STRING_BUFFER Buffer,
// PCUNICODE_STRING String
// );
// Routine Description:
//
// Arguments:
//
// Buffer -
// String -
//
// Return Value:
//
// STATUS_SUCCESS
// STATUS_NO_MEMORY
//--
#define RtlAssignUnicodeStringBuffer(Buff, Str) \
(((Buff)->String.Length = 0), (RtlAppendUnicodeStringBuffer((Buff), (Str))))
//++
//
// NTSTATUS
// RtlTakeRemainingStaticBuffer(
// IN OUT PRTL_BUFFER Buffer,
// OUT PUCHAR* RemainingStaticBuffer,
// OUT SIZE_T* RemainingStaticSize
// );
//
// Routine Description:
//
// This function makes it easy to share a static buffer among
// multiple buffers, as long as the buffers are actually initialized
// and "sealed" linearly/independently/one after another with
// no "overlap" (overlap in control and dataflow, not in actual addresses).
//
// Note that if a buffer is using exactly all of its static buffer, you
// will get back 0 and STATUS_SUCCESS. This is not an error condition.
// This is why RtlInitUnicodeStringBuffer can now accept zero sized static buffers.
//
// Note that even if you violate the conditions that make this function most
// useful, your code will still work, just less quickly.
//
// A pattern that should work is allocating one static buffer and moving it "through"
// multiple buffers. Even if you run out of static space, it should work to
// move the remaining zero size static buffer forward. Of course, you'll heap allocate.
//
// Arguments:
//
// Buffer -
// RemainingStaticBuffer -
// RemainingStaticSize -
//
// Return Value:
//
// STATUS_SUCCESS
//
//--
#define RtlTakeRemainingStaticBuffer(Buff, OutBuff, OutSize) \
(((Buff)->Buffer != (Buff)->StaticBuffer) \ ? ( /* take the whole thing */ \ ( *(OutBuff) = (Buff)->StaticBuffer ), \ ( *(OutSize) = (Buff)->StaticSize ), \ /* leave the buffer with nothing */ \ ( (Buff)->StaticBuffer = NULL ), \ ( (Buff)->StaticSize = 0 ), \ ( STATUS_SUCCESS ) \ ) \ : ( /* only take what isn't being used */ \ ( *(OutBuff) = &(Buff)->StaticBuffer[(Buff)->Size] ), \ ( *(OutSize) = ((Buff)->StaticSize - (Buff)->Size) ), \ /* leave the buffer with just what it is using */ \ ( (Buff)->StaticSize = (Buff)->Size ), \ ( STATUS_SUCCESS ) \ ))
NTSTATUS NTAPI RtlPrependStringToUnicodeStringBuffer( IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer, IN PCUNICODE_STRING UnicodeString );
NTSTATUS NTAPI RtlUnicodeStringBufferRight( IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER Buffer, IN ULONG Length );
NTSTATUS NTAPI RtlUnicodeStringBufferLeft( IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER Buffer, IN ULONG Length );
NTSTATUS NTAPI RtlUnicodeStringBufferMid( IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER Buffer, IN ULONG Offset, IN ULONG Length );
NTSTATUS NTAPI RtlInsertStringIntoUnicodeStringBuffer( IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER UnicodeStringBuffer, IN ULONG Offset, IN PCUNICODE_STRING InsertString );
NTSTATUS NTAPI RtlBufferTakeValue( IN ULONG Flags, IN OUT PRTL_BUFFER DestinationBuffer, IN OUT PRTL_BUFFER SourceBuffer );
//++
//
// NTSTATUS
// RtlUnicodeStringBufferTakeValue(
// OUT NTSTATUS* Status,
// IN ULONG Flags,
// IN OUT RTL_UNICODE_STRING_BUFFER DestinationBuffer,
// IN OUT RTL_UNICODE_STRING_BUFFER SourceBuffer
// );
//
//--
#define RtlUnicodeStringBufferTakeValue(Status, Flags, DestinationBuffer, SourceBuffer) \
( \ ((Flags) != 0) \ ? (*(Status) = STATUS_INVALID_PARAMETER) \ : (!NT_SUCCESS(*(Status) = RtlBufferTakeValue(0, &(DestinationBuffer)->ByteBuffer, &(SourceBuffer)->ByteBuffer))) \ ? (*(Status)) \ : (*(Status) = RtlSyncStringToBuffer(DestinationBuffer), RtlSyncStringToBuffer(SourceBuffer)) \ )
NTSTATUS NTAPI RtlValidateBuffer( IN ULONG Flags, IN CONST RTL_BUFFER* Buffer );
NTSTATUS NTAPI RtlValidateUnicodeStringBuffer( IN ULONG Flags, IN CONST RTL_UNICODE_STRING_BUFFER* UnicodeStringBuffer );
#define RTL_FIND_AND_REPLACE_CHARACTER_IN_STRING_CASE_SENSITIVE (0x00000001)
NTSTATUS NTAPI RtlFindAndReplaceCharacterInString( ULONG Flags, PVOID Reserved, PUNICODE_STRING String, WCHAR Find, WCHAR Replace );
typedef struct _RTL_ANSI_STRING_BUFFER { ANSI_STRING String; RTL_BUFFER ByteBuffer; UCHAR MinimumStaticBufferForTerminalNul[1]; } RTL_ANSI_STRING_BUFFER, *PRTL_ANSI_STRING_BUFFER;
NTSTATUS NTAPI RtlInitAnsiStringBuffer( PRTL_ANSI_STRING_BUFFER StringBuffer, PUCHAR StaticBuffer, SIZE_T StaticSize );
VOID NTAPI RtlFreeAnsiStringBuffer( PRTL_ANSI_STRING_BUFFER AnsiStringBuffer );
NTSTATUS NTAPI RtlAssignAnsiStringBufferFromUnicodeString( PRTL_ANSI_STRING_BUFFER AnsiStringBuffer, PCUNICODE_STRING UnicodeString );
NTSTATUS NTAPI RtlAssignAnsiStringBufferFromUnicode( PRTL_ANSI_STRING_BUFFER AnsiStringBuffer, PCWSTR Unicode );
NTSTATUS NTAPI RtlUnicodeStringBufferEnsureTrailingNtPathSeperator( PRTL_UNICODE_STRING_BUFFER StringBuffer );
#ifdef __cplusplus
} // extern "C"
#endif
#if defined (_MSC_VER) && ( _MSC_VER >= 800 )
#if _MSC_VER >= 1200
#pragma warning(pop)
#else
#pragma warning(default:4001)
#pragma warning(default:4201)
#pragma warning(default:4214)
#endif
#endif
#endif
|