Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
stack.c
Abstract:
This provides a generic stack handler to push/pop things onto it
Author:
Stephane Plante (splante)
Environment:
User, Kernel
--*/
#include "pch.h"
NTSTATUS StackAllocate( OUT PSTACK *Stack, IN ULONG StackElementSize ) /*++
Routine Description:
This routine allocates memory and returns a stack object
Arguments:
Stack - Where to store a pointer to the stack StackElementSize - How much space on the stack a single element takes up
Return Value:
NTSTATUS
--*/ { PSTACK tempStack; NTSTATUS status = STATUS_SUCCESS;
//
// Make sure that we have some place to store the stack pointer
//
ASSERT( Stack != NULL ); ASSERT( StackElementSize != 0 );
//
// Allocate a block of memory for the stack
//
tempStack = MEMORY_ALLOCATE( sizeof(STACK) + ( (STACK_GROWTH_RATE * StackElementSize) - 1) ); if (tempStack == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES; goto StackAllocateExit; }
//
// Setup the control block of the stack
//
tempStack->Signature = (ULONG) STACK_SIGNATURE; tempStack->StackSize = STACK_GROWTH_RATE * StackElementSize; tempStack->StackElementSize = StackElementSize; tempStack->TopOfStack = 0;
//
// Zero out the current elements on the stack
//
MEMORY_ZERO( &(tempStack->Stack[0]), STACK_GROWTH_RATE * StackElementSize );
//
// Return the stack pointer
//
StackAllocateExit: *Stack = tempStack; return status;
}
NTSTATUS StackFree( IN OUT PSTACK *Stack ) /*++
Routine Description:
This routine frees the stack
Arguments:
Stack - Where to find a pointer to the stack
Return Value:
NTSTATUS
--*/ { //
// Make sure that we point to something
//
ASSERT( Stack != NULL ); ASSERT( (*Stack)->Signature == STACK_SIGNATURE );
//
// Free the stack
//
MEMORY_FREE( *Stack );
//
// Point the stack to nowhere
//
*Stack = NULL;
return STATUS_SUCCESS; }
NTSTATUS StackParent( IN OUT PSTACK *Stack, IN PVOID Child, OUT PVOID Parent ) /*++
Routine Description:
This routine returns a pointer to the stack location that is before the given Child.
Arguments:
Stack - The stack to operate on Child - This is the node whose parent we want Parent - This is where we store a pointer to the parent stack loc
Return Value:
NTSTATUS
--*/ { PSTACK localStack; ULONG Addr = (ULONG) Child;
//
// Make sure that we point to something
//
ASSERT( Stack != NULL ); ASSERT( (*Stack)->Signature == STACK_SIGNATURE ); ASSERT( Parent != NULL );
//
// make sure that the child node actually lies on the stack
//
localStack = *Stack; if ( Addr < (ULONG) localStack->Stack || Addr > (ULONG) &(localStack->Stack[localStack->TopOfStack + 1]) - localStack->StackElementSize ) {
*( (PULONG *)Parent) = NULL; return STATUS_FAIL_CHECK;
}
//
// Make sure that the child node isn't the first element
//
if (Addr < (ULONG) &(localStack->Stack[localStack->StackElementSize]) ) {
*( (PULONG *)Parent) = NULL; return STATUS_SUCCESS;
}
//
// Set the parent to be one before the child
//
*( (PULONG *)Parent) = (PULONG) (Addr - localStack->StackElementSize);
//
// Done
//
return STATUS_SUCCESS; }
NTSTATUS StackPop( IN OUT PSTACK *Stack ) /*++
Routine Description:
This routine reclaims the memory used for a stack location and wipes out whatever data existed in the reclaimed area
Arguments:
Stack - Where to find a pointer to the stack
Return Value:
NTSTATUS
--*/ { PSTACK localStack;
//
// Make sure that we point to something
//
ASSERT( Stack != NULL ); ASSERT( (*Stack)->Signature == STACK_SIGNATURE );
//
// Is there an item that we can remove from the stack?
//
localStack = *Stack; if ( localStack->TopOfStack == 0) {
return STATUS_FAIL_CHECK;
}
//
// Wipe out the top-most element on the stack
//
localStack->TopOfStack -= localStack->StackElementSize; MEMORY_ZERO( &( localStack->Stack[ localStack->TopOfStack ] ), localStack->StackElementSize );
return STATUS_SUCCESS; }
NTSTATUS StackPush( IN OUT PSTACK *Stack, OUT PVOID StackElement ) /*++
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:
Stack - Where to find a pointer to the stack StackElement - Pointer to the element to be added to the stack
Return Value:
NTSTATUS
--*/ { PSTACK localStack; PSTACK tempStack; ULONG newSize; ULONG deltaSize;
//
// Make sure that we point to something
//
ASSERT( Stack != NULL ); ASSERT( StackElement != NULL );
//
// Find the stack pointer and make sure that the signature is still
// valid
//
localStack = *Stack; ASSERT( localStack->Signature == STACK_SIGNATURE );
//
// Do we have enough space on the stack?
//
if ( localStack->TopOfStack >= localStack->StackSize ) {
//
// Figure out how many bytes by which to grow the stack and how
// large the total stack should be
//
deltaSize = (STACK_GROWTH_RATE * localStack->StackElementSize); newSize = sizeof(STACK) + localStack->StackSize + deltaSize - 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[0]), newSize - sizeof(STACK) + 1); MEMORY_COPY( tempStack, localStack , newSize - deltaSize);
//
// Make sure that the new stack has the correct size
//
tempStack->StackSize += deltaSize;
//
// Free the old stack
//
StackFree( Stack );
//
// Set the stack to point to the new one
//
*Stack = localStack = tempStack;
}
//
// Grab a pointer to the part that we will return to the caller
//
*( (PUCHAR *)StackElement) = &(localStack->Stack[ localStack->TopOfStack ]);
//
// Find the new Top of Stack
//
localStack->TopOfStack += localStack->StackElementSize;
//
// Done
//
return STATUS_SUCCESS; }
NTSTATUS StackRoot( IN OUT PSTACK *Stack, OUT PVOID RootElement ) /*++
Routine Description:
This routine returns the first element on the stack
Arguments:
Stack - Where the stack is located RootElement - Where to store the pointer to the root stack element
Return Value:
NTSTATUS
--*/ { PSTACK localStack;
ASSERT( Stack != NULL && *Stack != NULL ); ASSERT( (*Stack)->Signature == STACK_SIGNATURE );
localStack = *Stack; if (localStack->TopOfStack < localStack->StackElementSize) {
//
// There is no stack location we can use
//
*( (PUCHAR *)RootElement) = NULL; return STATUS_UNSUCCESSFUL;
}
//
// Grab the root element
//
*( (PUCHAR *)RootElement) = localStack->Stack;
//
// Done
//
return STATUS_SUCCESS; }
NTSTATUS StackTop( IN OUT PSTACK *Stack, OUT PVOID TopElement ) /*++
Routine Description:
This routine returns the topmost stack location that is in current use
Arguments:
Stack - Where the stack is located TopElement - Where to store the pointer to the top stack element
Return Value:
NTSTATUS
--*/ { PSTACK localStack; ULONG offset;
ASSERT( Stack != NULL ); ASSERT( (*Stack)->Signature == STACK_SIGNATURE );
localStack = *Stack; if (localStack->TopOfStack < localStack->StackElementSize) {
//
// No stack locations are in current use
//
*( (PUCHAR *)TopElement) = NULL; return STATUS_UNSUCCESSFUL;
} else {
offset = localStack->TopOfStack - localStack->StackElementSize; }
//
// Grab the top stack location
//
*( (PUCHAR *)TopElement) = &(localStack->Stack[ offset ]);
//
// Done
//
return STATUS_SUCCESS; }
|