Source code of Windows XP (NT5)
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.

356 lines
5.7 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. xmem.c
  5. Abstract:
  6. This module contains routines for allocating and freeing "extended" memory.
  7. The memory is allocated directly from NT.
  8. Author:
  9. Dave Hastings (daveh) 12-Dec-1992
  10. Notes:
  11. Moved from dpmi32\i386
  12. Revision History:
  13. 09-Feb-1994 (daveh)
  14. Modified to be the common front end for the memory allocation. Calls
  15. processor specific code to do actual allocation
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include "softpc.h"
  20. #include <malloc.h>
  21. MEM_DPMI XmemHead = { NULL, 0, &XmemHead, &XmemHead, 0};
  22. PMEM_DPMI
  23. DpmiAllocateXmem(
  24. ULONG BlockSize
  25. )
  26. /*++
  27. Routine Description:
  28. This routine allocates a block of "extended" memory from NT. The
  29. blocks allocated this way will be 64K aligned (for now). The address
  30. of the block is returned to the segmented app in bx:cx
  31. Arguments:
  32. None.
  33. Return Value:
  34. None.
  35. --*/
  36. {
  37. ULONG BlockAddress;
  38. NTSTATUS Status;
  39. PMEM_DPMI XmemBlock;
  40. //
  41. // Get a block of memory from NT (any base address)
  42. //
  43. BlockAddress = 0;
  44. Status = DpmiAllocateVirtualMemory(
  45. (PVOID)&BlockAddress,
  46. &BlockSize
  47. );
  48. if (!NT_SUCCESS(Status)) {
  49. #if DBG
  50. OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
  51. #endif
  52. return NULL;
  53. }
  54. XmemBlock = malloc(sizeof(MEM_DPMI));
  55. if (!XmemBlock) {
  56. DpmiFreeVirtualMemory(
  57. (PVOID)&BlockAddress,
  58. &BlockSize
  59. );
  60. return NULL;
  61. }
  62. XmemBlock->Address = (PVOID)BlockAddress;
  63. XmemBlock->Length = BlockSize;
  64. XmemBlock->Owner = CurrentPSPSelector;
  65. XmemBlock->Sel = 0;
  66. XmemBlock->SelCount = 0;
  67. INSERT_BLOCK(XmemBlock, XmemHead);
  68. return XmemBlock;
  69. }
  70. BOOL
  71. DpmiFreeXmem(
  72. PMEM_DPMI XmemBlock
  73. )
  74. /*++
  75. Routine Description:
  76. This routine frees a block of "extended" memory from NT.
  77. Arguments:
  78. None.
  79. Return Value:
  80. None.
  81. --*/
  82. {
  83. NTSTATUS Status;
  84. PVOID BlockAddress;
  85. ULONG BlockSize;
  86. BlockAddress = XmemBlock->Address;
  87. BlockSize = XmemBlock->Length;
  88. Status = DpmiFreeVirtualMemory(
  89. &BlockAddress,
  90. &BlockSize
  91. );
  92. if (!NT_SUCCESS(Status)) {
  93. #if DBG
  94. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  95. #endif
  96. return FALSE;
  97. }
  98. DELETE_BLOCK(XmemBlock);
  99. free(XmemBlock);
  100. return TRUE;
  101. }
  102. BOOL
  103. DpmiIsXmemHandle(
  104. PMEM_DPMI XmemBlock
  105. )
  106. /*++
  107. Routine Description:
  108. This routine verifies that the given handle is a valid xmem handle.
  109. Arguments:
  110. Handle to be verified.
  111. Return Value:
  112. TRUE if handle is valid, FALSE otherwise.
  113. --*/
  114. {
  115. PMEM_DPMI p1;
  116. p1 = XmemHead.Next;
  117. while(p1 != &XmemHead) {
  118. if (p1 == XmemBlock) {
  119. return TRUE;
  120. }
  121. p1 = p1->Next;
  122. }
  123. return FALSE;
  124. }
  125. PMEM_DPMI
  126. DpmiFindXmem(
  127. USHORT Sel
  128. )
  129. /*++
  130. Routine Description:
  131. This routine finds a block of "extended" memory based on its Selector
  132. field.
  133. Arguments:
  134. None.
  135. Return Value:
  136. None.
  137. --*/
  138. {
  139. PMEM_DPMI p1;
  140. p1 = XmemHead.Next;
  141. while(p1 != &XmemHead) {
  142. if (p1->Sel == Sel) {
  143. return p1;
  144. }
  145. p1 = p1->Next;
  146. }
  147. return NULL;
  148. }
  149. BOOL
  150. DpmiReallocateXmem(
  151. PMEM_DPMI OldBlock,
  152. ULONG NewSize
  153. )
  154. /*++
  155. Routine Description:
  156. This routine resizes a block of "extended memory". If the change in size
  157. is less than 4K, no change is made.
  158. Arguments:
  159. None.
  160. Return Value:
  161. None.
  162. --*/
  163. {
  164. ULONG BlockAddress;
  165. NTSTATUS Status;
  166. BlockAddress = 0;
  167. Status = DpmiReallocateVirtualMemory(
  168. OldBlock->Address,
  169. OldBlock->Length,
  170. (PVOID)&BlockAddress,
  171. &NewSize
  172. );
  173. if (!NT_SUCCESS(Status)) {
  174. #if DBG
  175. OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
  176. #endif
  177. return FALSE;
  178. }
  179. OldBlock->Address = (PVOID)BlockAddress;
  180. OldBlock->Length = NewSize;
  181. return TRUE;
  182. }
  183. VOID
  184. DpmiFreeAppXmem(
  185. VOID
  186. )
  187. /*++
  188. Routine Description:
  189. This routine frees Xmem allocated for the application
  190. Arguments:
  191. Client DX = client PSP selector
  192. Return Value:
  193. TRUE if everything goes fine.
  194. FALSE if unable to release the memory
  195. --*/
  196. {
  197. PMEM_DPMI p1, p2;
  198. NTSTATUS Status;
  199. PVOID BlockAddress;
  200. ULONG BlockSize;
  201. p1 = XmemHead.Next;
  202. while(p1 != &XmemHead) {
  203. if (p1->Owner == CurrentPSPSelector) {
  204. BlockAddress = p1->Address;
  205. BlockSize = p1->Length;
  206. Status = DpmiFreeVirtualMemory(
  207. &BlockAddress,
  208. &BlockSize
  209. );
  210. if (!NT_SUCCESS(Status)) {
  211. #if DBG
  212. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  213. #endif
  214. return;
  215. }
  216. p2 = p1->Next;
  217. DELETE_BLOCK(p1);
  218. free(p1);
  219. p1 = p2;
  220. continue;
  221. }
  222. p1 = p1->Next;
  223. }
  224. return;
  225. }
  226. VOID
  227. DpmiFreeAllXmem(
  228. VOID
  229. )
  230. /*++
  231. Routine Description:
  232. This function frees all allocated xmem.
  233. Arguments:
  234. none
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. PMEM_DPMI p1, p2;
  240. NTSTATUS Status;
  241. PVOID BlockAddress;
  242. ULONG BlockSize;
  243. p1 = XmemHead.Next;
  244. while(p1 != &XmemHead) {
  245. BlockAddress = p1->Address;
  246. BlockSize = p1->Length;
  247. Status = DpmiFreeVirtualMemory(
  248. &BlockAddress,
  249. &BlockSize
  250. );
  251. if (!NT_SUCCESS(Status)) {
  252. #if DBG
  253. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  254. #endif
  255. return;
  256. }
  257. p2 = p1->Next;
  258. DELETE_BLOCK(p1);
  259. free(p1);
  260. p1 = p2;
  261. }
  262. }