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.
 
 
 
 
 
 

425 lines
7.4 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
xmem.c
Abstract:
This module contains routines for allocating and freeing "extended" memory.
The memory is allocated directly from NT.
Author:
Dave Hastings (daveh) 12-Dec-1992
Notes:
Moved from dpmi32\i386
Revision History:
09-Feb-1994 (daveh)
Modified to be the common front end for the memory allocation. Calls
processor specific code to do actual allocation
--*/
#include "precomp.h"
#pragma hdrstop
#include "softpc.h"
#include <malloc.h>
ULONG
DpmiCalculateAppXmem(
VOID
);
MEM_DPMI XmemHead = { NULL, 0, &XmemHead, &XmemHead, 0};
PMEM_DPMI
DpmiAllocateXmem(
ULONG BlockSize
)
/*++
Routine Description:
This routine allocates a block of "extended" memory from NT. The
blocks allocated this way will be 64K aligned (for now). The address
of the block is returned to the segmented app in bx:cx
Arguments:
None.
Return Value:
None.
--*/
{
ULONG BlockAddress;
NTSTATUS Status;
PMEM_DPMI XmemBlock;
ULONG size;
//
// First check if this app owns more than 16 MB
//
size = DpmiCalculateAppXmem();
if (size + BlockSize > MAX_APP_XMEM) {
return NULL;
}
//
// Get a block of memory from NT (any base address)
//
BlockAddress = 0;
Status = DpmiAllocateVirtualMemory(
(PVOID)&BlockAddress,
&BlockSize
);
if (!NT_SUCCESS(Status)) {
#if DBG
OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
#endif
return NULL;
}
XmemBlock = malloc(sizeof(MEM_DPMI));
if (!XmemBlock) {
DpmiFreeVirtualMemory(
(PVOID)&BlockAddress,
&BlockSize
);
return NULL;
}
XmemBlock->Address = (PVOID)BlockAddress;
XmemBlock->Length = BlockSize;
XmemBlock->Owner = CurrentPSPSelector;
XmemBlock->Sel = 0;
XmemBlock->SelCount = 0;
INSERT_BLOCK(XmemBlock, XmemHead);
return XmemBlock;
}
BOOL
DpmiFreeXmem(
PMEM_DPMI XmemBlock
)
/*++
Routine Description:
This routine frees a block of "extended" memory from NT.
Arguments:
None.
Return Value:
None.
--*/
{
NTSTATUS Status;
PVOID BlockAddress;
ULONG BlockSize;
BlockAddress = XmemBlock->Address;
BlockSize = XmemBlock->Length;
Status = DpmiFreeVirtualMemory(
&BlockAddress,
&BlockSize
);
if (!NT_SUCCESS(Status)) {
#if DBG
OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
#endif
return FALSE;
}
DELETE_BLOCK(XmemBlock);
free(XmemBlock);
return TRUE;
}
BOOL
DpmiIsXmemHandle(
PMEM_DPMI XmemBlock
)
/*++
Routine Description:
This routine verifies that the given handle is a valid xmem handle.
Arguments:
Handle to be verified.
Return Value:
TRUE if handle is valid, FALSE otherwise.
--*/
{
PMEM_DPMI p1;
p1 = XmemHead.Next;
while(p1 != &XmemHead) {
if (p1 == XmemBlock) {
return TRUE;
}
p1 = p1->Next;
}
return FALSE;
}
PMEM_DPMI
DpmiFindXmem(
USHORT Sel
)
/*++
Routine Description:
This routine finds a block of "extended" memory based on its Selector
field.
Arguments:
None.
Return Value:
None.
--*/
{
PMEM_DPMI p1;
p1 = XmemHead.Next;
while(p1 != &XmemHead) {
if (p1->Sel == Sel) {
return p1;
}
p1 = p1->Next;
}
return NULL;
}
BOOL
DpmiReallocateXmem(
PMEM_DPMI OldBlock,
ULONG NewSize
)
/*++
Routine Description:
This routine resizes a block of "extended memory". If the change in size
is less than 4K, no change is made.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG BlockAddress;
NTSTATUS Status;
if (DpmiCalculateAppXmem() + NewSize - OldBlock->Length > MAX_APP_XMEM) {
return FALSE;
}
BlockAddress = 0;
Status = DpmiReallocateVirtualMemory(
OldBlock->Address,
OldBlock->Length,
(PVOID)&BlockAddress,
&NewSize
);
if (!NT_SUCCESS(Status)) {
#if DBG
OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
#endif
return FALSE;
}
RESIZE_BLOCK(OldBlock, BlockAddress, NewSize);
return TRUE;
}
VOID
DpmiFreeAppXmem(
USHORT Owner
)
/*++
Routine Description:
This routine frees Xmem allocated for the application
Arguments:
Client DX = client PSP selector
Return Value:
TRUE if everything goes fine.
FALSE if unable to release the memory
--*/
{
PMEM_DPMI p1, p2;
NTSTATUS Status;
PVOID BlockAddress;
ULONG BlockSize;
p1 = XmemHead.Next;
while(p1 != &XmemHead) {
if (p1->Owner == Owner) {
BlockAddress = p1->Address;
BlockSize = p1->Length;
Status = DpmiFreeVirtualMemory(
&BlockAddress,
&BlockSize
);
if (!NT_SUCCESS(Status)) {
#if DBG
OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
#endif
return;
}
p2 = p1->Next;
DELETE_BLOCK(p1);
free(p1);
p1 = p2;
continue;
}
p1 = p1->Next;
}
return;
}
ULONG
DpmiCalculateAppXmem(
VOID
)
/*++
Routine Description:
This routine calculates the Xmem allocated to the CURRENT application
Arguments:
None.
Return Value:
The size of xmem allocated to the app.
Note the size will never exceed 2 GB. We put a cap at about 16MB when
allocating memory for the app.
--*/
{
PMEM_DPMI p;
NTSTATUS Status;
ULONG Size = 0;
//
// If not current APP, we don't keep track of the xmem size
//
if (CurrentPSPSelector == 0) {
return 0;
}
//
// If CurrentPSPXmem is not zero, it is under control.
// No need to initialize it. Make sure it is not negative value.
//
if (CurrentPSPXmem != 0 && CurrentPSPXmem <= MAX_APP_XMEM) {
return CurrentPSPXmem;
}
p = XmemHead.Next;
while(p != &XmemHead) {
if (p->Owner == CurrentPSPSelector) {
Size += p->Length;
}
p = p->Next;
}
CurrentPSPXmem = Size;
return Size;
}
VOID
DpmiFreeAllXmem(
VOID
)
/*++
Routine Description:
This function frees all allocated xmem.
Arguments:
none
Return Value:
None.
--*/
{
PMEM_DPMI p1, p2;
NTSTATUS Status;
PVOID BlockAddress;
ULONG BlockSize;
p1 = XmemHead.Next;
while(p1 != &XmemHead) {
BlockAddress = p1->Address;
BlockSize = p1->Length;
Status = DpmiFreeVirtualMemory(
&BlockAddress,
&BlockSize
);
if (!NT_SUCCESS(Status)) {
#if DBG
OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
#endif
return;
}
p2 = p1->Next;
DELETE_BLOCK(p1);
free(p1);
p1 = p2;
}
CurrentPSPXmem = 0;
}