sysheap.inc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. {
  2. Basic heap handling for windows platforms
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2001-2005 by Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {*****************************************************************************
  12. OS Memory allocation / deallocation
  13. ****************************************************************************}
  14. { In kernel mode we can either use FPC's build in memory manager or we use a
  15. custom non-chunking manager. The problem with the build in one is that the
  16. driver developer has far less control of the allocated memory blocks. }
  17. { memory functions }
  18. {$ifdef KMODE}
  19. function ExAllocatePoolWithTag(PoolType: LongInt; NumberOfBytes: PtrUInt; Tag: LongWord): Pointer; stdcall; external ntdll name 'ExAllocatePoolWithTag';
  20. procedure ExFreePoolWithTag(P: Pointer; Tag: LongWord); stdcall; external ntdll name 'ExFreePoolWithTag';
  21. {$else KMODE}
  22. function RtlAllocateHeap(hHeap : THandle; dwFlags : LongWord; Size : PtrUInt): Pointer;
  23. stdcall; external ntdll name 'RtlAllocateHeap';
  24. function RtlFreeHeap(hHeap : THandle; dwFlags : LongWord; MemoryPointer : Pointer): Boolean;
  25. stdcall; external ntdll name 'RtlFreeHeap';
  26. function RtlCreateHeap(Flags: LongWord; Base: Pointer; SizeToReserve: PtrUInt;
  27. SizeToCommit: PtrUInt; Lock: Pointer; Parameters: Pointer): THandle;
  28. stdcall; external ntdll name 'RtlCreateHeap';
  29. var
  30. SysHeap: THandle = 0;
  31. procedure PrepareSysHeap;
  32. begin
  33. if IsLibrary then
  34. // create a new heap (flag is HEAP_GROWABLE)
  35. SysHeap := RtlCreateHeap(2, Nil, 65534, 65534, Nil, Nil)
  36. else
  37. // use the heap passed on startup
  38. SysHeap := THandle(PSimplePEB(CurrentPEB)^.ProcessHeap);
  39. end;
  40. {$endif KMODE}
  41. {$ifndef KMODE}
  42. // default memory manager
  43. function SysOSAlloc(size: ptruint): pointer;
  44. begin
  45. if SysHeap = 0 then
  46. PrepareSysHeap;
  47. SysOSAlloc := RtlAllocateHeap(SysHeap, 0, size);
  48. end;
  49. {$define HAS_SYSOSFREE}
  50. procedure SysOSFree(p: pointer; size: ptruint);
  51. begin
  52. // if heap isn't set, then nothing was allocated
  53. if SysHeap <> 0 then
  54. RtlFreeHeap(SysHeap, 0, p);
  55. end;
  56. {$else KMODE}
  57. // custom non-chunking memory manager for kernel mode
  58. // memory layout:
  59. // <PtrUInt>: Size of reserved chunk
  60. // <Tag>: Tag that was used in ExAllocateFromPoolWithTag (needed in free)
  61. // <...>: Userdata
  62. function SysGetMem(Size: PtrUInt): Pointer;
  63. var
  64. tag: LongWord;
  65. pooltype: LongInt;
  66. begin
  67. if HeapUsePagedPool then
  68. pooltype := 1
  69. else
  70. pooltype := 0;
  71. tag := Ord(HeapPoolTag[1]) + Ord(HeapPoolTag[2]) shl 8 +
  72. Ord(HeapPoolTag[3]) shl 16 + Ord(HeapPoolTag[4]) shl 24;
  73. // the kernel keeps track of our memory, but there's no way to ask it
  74. // so we need to track the size by ourself
  75. SysGetMem := ExAllocatePoolWithTag(pooltype, Size + SizeOf(PtrUInt) + SizeOf(LongWord), tag);
  76. // save the size
  77. PPtrUInt(SysGetMem)^ := Size;
  78. SysGetMem := SysGetMem + SizeOf(PtrUInt);
  79. // save the tag
  80. PLongWord(SysGetMem)^ := tag;
  81. SysGetMem := SysGetMem + SizeOf(LongWord);
  82. end;
  83. function SysFreeMem(p: Pointer): PtrUInt;
  84. var
  85. tag: PLongWord;
  86. begin
  87. tag := p - SizeOf(LongWord);
  88. // we need to pass the tag we used to allocate the memory (else: BSOD)
  89. ExFreePoolWithTag(p - SizeOf(PtrUInt) - SizeOf(LongWord), tag^);
  90. SysFreeMem := 0;
  91. end;
  92. function SysFreeMemSize(p: Pointer; Size: PtrUInt): PtrUInt;
  93. begin
  94. SysFreeMemSize := 0;
  95. if (Size > 0) and (p <> nil) then
  96. Result := SysFreeMem(p);
  97. end;
  98. Function SysAllocMem(Size: PtrUInt): Pointer;
  99. begin
  100. SysAllocMem := SysGetMem(Size);
  101. if SysAllocMem <> nil then
  102. FillChar(SysAllocMem^, Size, 0);
  103. end;
  104. Function SysReAllocMem (var p: pointer; Size: PtrUInt): Pointer;
  105. begin
  106. SysReAllocMem := SysGetMem(Size);
  107. Move(p^, SysReAllocMem^, Size);
  108. p := SysReAllocMem;
  109. end;
  110. function SysTryResizeMem(var p: Pointer; size: PtrUInt): Boolean;
  111. var
  112. res: pointer;
  113. begin
  114. res := SysGetMem(Size);
  115. SysTryResizeMem := (res <> Nil) or (Size = 0);
  116. if SysTryResizeMem then
  117. p := res;
  118. end;
  119. function SysMemSize(P : pointer): PtrUInt;
  120. begin
  121. SysMemSize := PPtrUInt(P - SizeOf(PtrUInt) - SizeOf(LongWord))^;
  122. end;
  123. function SysGetHeapStatus: THeapStatus;
  124. begin
  125. FillChar(SysGetHeapStatus, SizeOf(SysGetHeapStatus), 0);
  126. end;
  127. function SysGetFPCHeapStatus: TFPCHeapStatus;
  128. begin
  129. FillChar(SysGetFPCHeapStatus, SizeOf(SysGetHeapStatus), 0);
  130. end;
  131. {$endif KMODE}