windows-nt/Source/XPSP1/NT/base/ntsetup/textmode/kernel/spmemory.c

240 lines
4.2 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
spmemory.c
Abstract:
Memory allocation routines for text setup.
Author:
Ted Miller (tedm) 29-July-1993
Revision History:
--*/
#include "spprecmp.h"
#pragma hdrstop
PVOID
SpMemAlloc(
IN SIZE_T Size
)
{
return(SpMemAllocEx(Size,'pteS', PagedPool));
}
PVOID
SpMemAllocNonPagedPool(
IN SIZE_T Size
)
{
return(SpMemAllocEx(Size,'pteS', NonPagedPool));
}
PVOID
SpMemAllocEx(
IN SIZE_T Size,
IN ULONG Tag,
IN POOL_TYPE Type
)
/*++
Routine Description:
This function is guaranteed to succeed.
Arguments:
Return Value:
--*/
{
PSIZE_T p;
//
// Add space for storing the size of the block.
//
#if defined(SETUP_TEST_USERMODE)
p = RtlAllocateHeap(RtlProcessHeap(), 0, Size + (2 * sizeof(SIZE_T)));
#else
p = ExAllocatePoolWithTag(Type, Size + (2 * sizeof(SIZE_T)), Tag);
#endif
if(!p) {
SpOutOfMemory();
}
//
// Store the size of the block, and return the address
// of the user portion of the block.
//
*p = Tag;
*(p + 1) = Size;
return(p + 2);
}
PVOID
SpMemRealloc(
IN PVOID Block,
IN SIZE_T NewSize
)
/*++
Routine Description:
This function is guaranteed to succeed.
Arguments:
Return Value:
--*/
{
PSIZE_T NewBlock;
SIZE_T OldSize;
ULONG OldTag;
//
// Get the size of the block being reallocated.
//
OldTag = (ULONG)((PSIZE_T)Block)[-2];
OldSize = ((PSIZE_T)Block)[-1];
//
// Allocate a new block of the new size.
//
NewBlock = SpMemAllocEx(NewSize, OldTag, PagedPool);
ASSERT(NewBlock);
//
// Copy the old block to the new block.
//
if (NewSize < OldSize) {
RtlCopyMemory(NewBlock, Block, NewSize);
} else {
RtlCopyMemory(NewBlock, Block, OldSize);
}
//
// Free the old block.
//
SpMemFree(Block);
//
// Return the address of the new block.
//
return(NewBlock);
}
VOID
SpMemFree(
IN PVOID Block
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
extern PWSTR CommonStrings[11];
unsigned long i;
if (Block == NULL)
return;
for( i = 0; i < sizeof(CommonStrings)/sizeof(PWSTR); i++ ) {
if( (PWSTR)Block == CommonStrings[i] ) {
return;
}
}
//
// Free the block at its real address.
//
#if defined(SETUP_TEST_USERMODE)
RtlFreeHeap(RtlProcessHeap(), 0, (PULONG_PTR)Block - 2);
#else
ExFreePool((PULONG_PTR)Block - 2);
#endif
}
VOID
SpOutOfMemory(
VOID
)
{
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Out of memory\n"));
#if !defined(SETUP_TEST_USERMODE)
if(VideoInitialized) {
if(KbdLayoutInitialized) {
ULONG ValidKeys[2] = { KEY_F3,0 };
//
// We run a high risk of getting into an infinite loop
// here because SpStartScreen will result in a call to
// SpMemAlloc(), which will fail and call SpOutOfMemory
// again. In order to get around this, we'll jettison
// some memory that we won't need anymore (since we're
// about to die). These should give us enough memory
// to display the messages below.
//
SpFreeBootVars();
SpFreeArcNames();
while(1) {
SpStartScreen(SP_SCRN_OUT_OF_MEMORY,5,0,FALSE,TRUE,DEFAULT_ATTRIBUTE);
SpDisplayStatusOptions(
DEFAULT_STATUS_ATTRIBUTE,
SP_STAT_F3_EQUALS_EXIT,
0
);
if(SpWaitValidKey(ValidKeys,NULL,NULL) == KEY_F3) {
SpDone(0,FALSE,TRUE);
}
}
} else {
//
// we haven't loaded the layout dll yet, so we can't prompt for a keypress to reboot
//
SpStartScreen(SP_SCRN_OUT_OF_MEMORY_RAW,5,0,FALSE,TRUE,DEFAULT_ATTRIBUTE);
SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE, SP_STAT_KBD_HARD_REBOOT, 0);
while(TRUE); // Loop forever
}
} else {
SpDisplayRawMessage(SP_SCRN_OUT_OF_MEMORY_RAW, 2);
while(TRUE); // loop forever
}
#endif
}