|
From: Jack \(Butch\) G. <bu...@qw...> - 2001-09-23 00:00:24
|
I was playing with virtual alloc today and noticed slightly different
behavior between Windows 2000 and Reactos. Basically if you call
VirtualAlloc() with a NULL pointer and the MEM_COMMIT flag, the function
fails. On windows 2000, this acts just like you had done a MEM_RESERVE to
reserve the memory, followed by a call again with the MEM_COMMIT flag set.
This specific form of the call (e.g. VirtualAlloc(NULL, size, MEM_COMMIT,
PAGE_READWRITE) is used in the microsoft CRT in the functions that implement
malloc(). This can keep Microsoft compiled applications from working in
Reactos. Not sure if this is desired or not.
I include a fix for this which I implemented in NtAllocateVirtualMemory().
If this semantic is not desired in this function, it can be moved back out
to VirtualAllocEx().
Thanks
Jack (Butch) Griffin.
Fix for this ( new version of NtAllocateVirtualMemory)
--------------------------------------------------------
NTSTATUS STDCALL
NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
IN OUT PVOID* UBaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG URegionSize,
IN ULONG AllocationType,
IN ULONG Protect)
/*
* FUNCTION: Allocates a block of virtual memory in the process address
space
* ARGUMENTS:
* ProcessHandle = The handle of the process which owns the virtual
memory
* BaseAddress = A pointer to the virtual memory allocated. If you
* supply a non zero value the system will try to
* allocate the memory at the address supplied. It
round
* it down to a multiple of the page size.
* ZeroBits = (OPTIONAL) You can specify the number of high order bits
* that must be zero, ensuring that the memory will be
* allocated at a address below a certain value.
* RegionSize = The number of bytes to allocate
* AllocationType = Indicates the type of virtual memory you like to
* allocated, can be a combination of MEM_COMMIT,
* MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
* Protect = Indicates the protection type of the pages allocated, can
be
* a combination of PAGE_READONLY, PAGE_READWRITE,
* PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
* PAGE_NOACCESS
* REMARKS:
* This function maps to the win32 VirtualAllocEx. Virtual memory is
* process based so the protocol starts with a ProcessHandle. I
* splitted the functionality of obtaining the actual address and
* specifying the start address in two parameters ( BaseAddress and
* StartAddress ) The NumberOfBytesAllocated specify the range and the
* AllocationType and ProctectionType map to the other two parameters.
* RETURNS: Status
*/
{
PEPROCESS Process;
MEMORY_AREA* MemoryArea;
ULONG Type;
NTSTATUS Status;
PMADDRESS_SPACE AddressSpace;
PMM_SEGMENT Segment;
PVOID BaseAddress;
ULONG RegionSize;
PVOID PBaseAddress;
ULONG PRegionSize;
DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
"ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
*UBaseAddress,ZeroBits,*URegionSize,AllocationType,
Protect);
/*
* Check the validity of the parameters
*/
if ((Protect & PAGE_FLAGS_VALID_FROM_USER_MODE) != Protect)
{
return(STATUS_INVALID_PAGE_PROTECTION);
}
if ((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == 0)
{
return(STATUS_INVALID_PARAMETER);
}
if (((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == MEM_COMMIT) &&
(*UBaseAddress == 0))
{
NTSTATUS status ;
status = NtAllocateVirtualMemory(ProcessHandle,
UBaseAddress,
ZeroBits,
URegionSize,
MEM_RESERVE,
Protect) ;
if (!NT_SUCCESS(status))
return status;
status = NtAllocateVirtualMemory(ProcessHandle,
UBaseAddress,
ZeroBits,
URegionSize,
MEM_COMMIT,
Protect) ;
if (!NT_SUCCESS(status))
return status ;
return STATUS_SUCCESS ;
}
PBaseAddress = *UBaseAddress;
PRegionSize = *URegionSize;
BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress);
RegionSize = PAGE_ROUND_UP(PBaseAddress + PRegionSize) -
PAGE_ROUND_DOWN(PBaseAddress);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
return(Status);
}
Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE;
DPRINT("Type %x\n", Type);
AddressSpace = &Process->AddressSpace;
MmLockAddressSpace(AddressSpace);
if ((PBaseAddress != 0) &&
((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == MEM_COMMIT))
{
MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace,
BaseAddress);
if (MemoryArea != NULL &&
MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
MemoryArea->Length >= RegionSize)
{
Status = MmComplexVirtualMemoryOperation(AddressSpace,
MemoryArea,
BaseAddress,
RegionSize,
Type,
Protect);
/* FIXME: Reserve/dereserve swap pages */
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
return(Status);
}
else if (MemoryArea != NULL)
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_UNSUCCESSFUL);
}
}
Segment = ExAllocatePoolWithTag(NonPagedPool,
sizeof(MM_SEGMENT),
TAG_MM_SEGMENT);
if (Segment == NULL)
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_UNSUCCESSFUL);
}
Status = MmCreateMemoryArea(Process,
&Process->AddressSpace,
MEMORY_AREA_VIRTUAL_MEMORY,
&BaseAddress,
RegionSize,
Protect,
&MemoryArea,
PBaseAddress != 0);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
return(Status);
}
InitializeListHead(&MemoryArea->Data.VirtualMemoryData.SegmentListHead);
Segment->Type = Type;
Segment->Protect = Protect;
Segment->Length = RegionSize;
InsertTailList(&MemoryArea->Data.VirtualMemoryData.SegmentListHead,
&Segment->SegmentListEntry);
if ((AllocationType & MEM_COMMIT) &&
((Protect & PAGE_READWRITE) ||
(Protect & PAGE_EXECUTE_READWRITE)))
{
MmReserveSwapPages(RegionSize);
}
*UBaseAddress = BaseAddress;
*URegionSize = RegionSize;
DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize);
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_SUCCESS);
}
====================================================
= To remove yourself from this mailing list, go to =
= http://www.reactos.com/home/mailing.html =
====================================================
|