/*++ Copyright (c) 1997 Microsoft Corporation Module Name: string.c Abstract: The string stack portion of the un-assembler Author: Stephane Plante Environment: Any Revision History: --*/ #include "pch.h" NTSTATUS StringStackAllocate( OUT PSTRING_STACK *StringStack ) /*++ Routine Description: This routine allocates memory and returns a string stack object Arguments: String Stack - Where to store a pointer to the stack Return Value: NTSTATUS --*/ { PSTRING_STACK tempStack; NTSTATUS status = STATUS_SUCCESS; // // Make sure that we have some place to store the stack pointer // ASSERT( StringStack != NULL ); // // Allocate a block of memory for the stack // tempStack = MEMORY_ALLOCATE( sizeof(STRING_STACK) + ( STRING_GROWTH_RATE - 1 ) ); if (tempStack == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto StringStackAllocateExit; } // // Setup the control block of the stack // tempStack->Signature = (ULONG) STRING_SIGNATURE; tempStack->StackSize = STRING_GROWTH_RATE; tempStack->TopOfStack = 0; // // Zero out the current elements on the stack // MEMORY_ZERO( tempStack->Stack, STRING_GROWTH_RATE ); // // Return the stack pointer // StringStackAllocateExit: *StringStack = tempStack; return status; } NTSTATUS StringStackClear( IN OUT PSTRING_STACK *StringStack ) /*++ Routine Description: This routine wipes out the contents of the stack and restarts it as if it was new allocated. Saves some from freeing and reallocating a stack Arguments: StringStack - Where to find a pointer to the stack Return Value: NTSTATUS --*/ { PSTRING_STACK localStack; // // Make sure that we point to something // ASSERT( StringStack != NULL && *StringStack != NULL ); ASSERT( (*StringStack)->Signature == STRING_SIGNATURE ); // // Zero out the stack // localStack = *StringStack; MEMORY_ZERO( localStack->Stack, localStack->StackSize ); // // Reset the TOS to the root // localStack->TopOfStack = 0; // // Done // return STATUS_SUCCESS; } NTSTATUS StringStackFree( IN OUT PSTRING_STACK *StringStack ) /*++ Routine Description: This routine frees the string stack Arguments: StringStack - Where to find a pointer to the stack Return Value: NTSTATUS --*/ { // // Make sure that we point to something // ASSERT( StringStack != NULL && *StringStack != NULL ); ASSERT( (*StringStack)->Signature == STRING_SIGNATURE ); // // Free the stack // MEMORY_FREE( *StringStack ); // // Point the stack to nowhere // *StringStack = NULL; return STATUS_SUCCESS; } NTSTATUS StringStackPop( IN OUT PSTRING_STACK *StringStack, IN ULONG NumBytes, OUT PUCHAR *String ) /*++ Routine Description: This routine returns a pointer to the requested offset from the end of the stack Note: String points to memory that can be freed at any time. It is the caller's responsibility to make a copy Arguments: StringStack - Where to find a pointer to the stack NumBytes - Number of bytes to pop off String - Pointer to the bytes. Return Value: NTSTATUS --*/ { PSTRING_STACK localStack; // // Make sure that we point to something // ASSERT( StringStack != NULL ); ASSERT( (*StringStack)->Signature == STRING_SIGNATURE ); ASSERT( String != NULL ); // // Is there an item that we can remove from the stack? // localStack = *StringStack; if ( localStack->TopOfStack == 0 || localStack->TopOfStack < NumBytes) { return STATUS_FAIL_CHECK; } // // Return a pointer to the requested bytes // localStack->TopOfStack -= NumBytes; *String = &( localStack->Stack[ localStack->TopOfStack ] ); return STATUS_SUCCESS; } NTSTATUS StringStackPush( IN OUT PSTRING_STACK *StringStack, IN ULONG StringLength, IN PUCHAR String ) /*++ Routine Description: This routine obtains a pointer for an object on the top of the stack and increments the top to point to something that can be then be used again. Arguments: StringStack - Where to find a pointer to the stack String - String to push onto stack StringLength - How many bytes to push onto the stack Return Value: NTSTATUS --*/ { PSTRING_STACK localStack; PSTRING_STACK tempStack; ULONG newSize; // // Make sure that we point to something // ASSERT( StringStack != NULL ); ASSERT( String != NULL ); // // Find the stack pointer and make sure that the signature is still // valid // localStack = *StringStack; ASSERT( localStack->Signature == STRING_SIGNATURE ); // // Do we have enough space on the stack? // if ( localStack->TopOfStack + StringLength > localStack->StackSize ) { // // Figure out how many bytes by which to grow the stack and how // large the total stack should be // newSize = sizeof(STRING_STACK) + localStack->StackSize + STRING_GROWTH_RATE - 1; // // Grow the stack // tempStack = MEMORY_ALLOCATE( newSize ); if (tempStack == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } // // Empty the new stack and copy the old one to it // MEMORY_ZERO( tempStack->Stack, newSize - sizeof(STRING_STACK) + 1); MEMORY_COPY( tempStack, localStack , newSize - STRING_GROWTH_RATE); // // Make sure that the new stack has the correct size // tempStack->StackSize += STRING_GROWTH_RATE; // // Free the old stack // StringStackFree( StringStack ); // // Set the stack to point to the new one // *StringStack = localStack = tempStack; } // // Grab a pointer to the part that we will return to the caller // MEMORY_COPY( &(localStack->Stack[ localStack->TopOfStack] ), String, StringLength ); // // Find the new Top of Stack // localStack->TopOfStack += StringLength; // // Done // return STATUS_SUCCESS; } NTSTATUS StringStackRoot( IN OUT PSTRING_STACK *StringStack, OUT PUCHAR *RootElement ) /*++ Routine Description: This routine returns the topmost stack location that is in current use Arguments: Stack - Where the stack is located RootElement - Where to store the pointer to the root stack element Return Value: NTSTATUS --*/ { ASSERT( StringStack != NULL && *StringStack != NULL ); ASSERT( (*StringStack)->Signature == STRING_SIGNATURE ); // // Grab the top stack location // *RootElement = (PUCHAR) (*StringStack)->Stack; // // Done // return STATUS_SUCCESS; }