374 lines
7.1 KiB
C
374 lines
7.1 KiB
C
/*++
|
||
|
||
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;
|
||
}
|