123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- {
- Basic heap handling for windows platforms
- This file is part of the Free Pascal run time library.
- Copyright (c) 2001-2005 by Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {*****************************************************************************
- OS Memory allocation / deallocation
- ****************************************************************************}
- { In kernel mode we can either use FPC's build in memory manager or we use a
- custom non-chunking manager. The problem with the build in one is that the
- driver developer has far less control of the allocated memory blocks. }
- { memory functions }
- {$ifdef KMODE}
- function ExAllocatePoolWithTag(PoolType: LongInt; NumberOfBytes: PtrUInt; Tag: LongWord): Pointer; stdcall; external ntdll name 'ExAllocatePoolWithTag';
- procedure ExFreePoolWithTag(P: Pointer; Tag: LongWord); stdcall; external ntdll name 'ExFreePoolWithTag';
- {$else KMODE}
- function RtlAllocateHeap(hHeap : THandle; dwFlags : LongWord; Size : PtrUInt): Pointer;
- stdcall; external ntdll name 'RtlAllocateHeap';
- function RtlFreeHeap(hHeap : THandle; dwFlags : LongWord; MemoryPointer : Pointer): Boolean;
- stdcall; external ntdll name 'RtlFreeHeap';
- function RtlCreateHeap(Flags: LongWord; Base: Pointer; SizeToReserve: PtrUInt;
- SizeToCommit: PtrUInt; Lock: Pointer; Parameters: Pointer): THandle;
- stdcall; external ntdll name 'RtlCreateHeap';
- var
- SysHeap: THandle = 0;
- procedure PrepareSysHeap;
- begin
- if IsLibrary then
- // create a new heap (flag is HEAP_GROWABLE)
- SysHeap := RtlCreateHeap(2, Nil, 65534, 65534, Nil, Nil)
- else
- // use the heap passed on startup
- SysHeap := THandle(PSimplePEB(CurrentPEB)^.ProcessHeap);
- end;
- {$endif KMODE}
- {$ifndef KMODE}
- // default memory manager
- function SysOSAlloc(size: ptruint): pointer;
- begin
- if SysHeap = 0 then
- PrepareSysHeap;
- SysOSAlloc := RtlAllocateHeap(SysHeap, 0, size);
- end;
- {$define HAS_SYSOSFREE}
- procedure SysOSFree(p: pointer; size: ptruint);
- begin
- // if heap isn't set, then nothing was allocated
- if SysHeap <> 0 then
- RtlFreeHeap(SysHeap, 0, p);
- end;
- {$else KMODE}
- // custom non-chunking memory manager for kernel mode
- // memory layout:
- // <PtrUInt>: Size of reserved chunk
- // <Tag>: Tag that was used in ExAllocateFromPoolWithTag (needed in free)
- // <...>: Userdata
- function SysGetMem(Size: PtrUInt): Pointer;
- var
- tag: LongWord;
- pooltype: LongInt;
- begin
- if HeapUsePagedPool then
- pooltype := 1
- else
- pooltype := 0;
- tag := Ord(HeapPoolTag[1]) + Ord(HeapPoolTag[2]) shl 8 +
- Ord(HeapPoolTag[3]) shl 16 + Ord(HeapPoolTag[4]) shl 24;
- // the kernel keeps track of our memory, but there's no way to ask it
- // so we need to track the size by ourself
- SysGetMem := ExAllocatePoolWithTag(pooltype, Size + SizeOf(PtrUInt) + SizeOf(LongWord), tag);
- // save the size
- PPtrUInt(SysGetMem)^ := Size;
- SysGetMem := SysGetMem + SizeOf(PtrUInt);
- // save the tag
- PLongWord(SysGetMem)^ := tag;
- SysGetMem := SysGetMem + SizeOf(LongWord);
- end;
- function SysFreeMem(p: Pointer): PtrUInt;
- var
- tag: PLongWord;
- begin
- tag := p - SizeOf(LongWord);
- // we need to pass the tag we used to allocate the memory (else: BSOD)
- ExFreePoolWithTag(p - SizeOf(PtrUInt) - SizeOf(LongWord), tag^);
- SysFreeMem := 0;
- end;
- function SysFreeMemSize(p: Pointer; Size: PtrUInt): PtrUInt;
- begin
- SysFreeMemSize := 0;
- if (Size > 0) and (p <> nil) then
- Result := SysFreeMem(p);
- end;
- Function SysAllocMem(Size: PtrUInt): Pointer;
- begin
- SysAllocMem := SysGetMem(Size);
- if SysAllocMem <> nil then
- FillChar(SysAllocMem^, Size, 0);
- end;
- Function SysReAllocMem (var p: pointer; Size: PtrUInt): Pointer;
- begin
- SysReAllocMem := SysGetMem(Size);
- Move(p^, SysReAllocMem^, Size);
- p := SysReAllocMem;
- end;
- function SysTryResizeMem(var p: Pointer; size: PtrUInt): Boolean;
- var
- res: pointer;
- begin
- res := SysGetMem(Size);
- SysTryResizeMem := (res <> Nil) or (Size = 0);
- if SysTryResizeMem then
- p := res;
- end;
- function SysMemSize(P : pointer): PtrUInt;
- begin
- SysMemSize := PPtrUInt(P - SizeOf(PtrUInt) - SizeOf(LongWord))^;
- end;
- function SysGetHeapStatus: THeapStatus;
- begin
- FillChar(SysGetHeapStatus, SizeOf(SysGetHeapStatus), 0);
- end;
- function SysGetFPCHeapStatus: TFPCHeapStatus;
- begin
- FillChar(SysGetFPCHeapStatus, SizeOf(SysGetHeapStatus), 0);
- end;
- {$endif KMODE}
|