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

  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. ULONG
  22. DpmiCalculateAppXmem(
  23. VOID
  24. );
  25. MEM_DPMI XmemHead = { NULL, 0, &XmemHead, &XmemHead, 0};
  26. PMEM_DPMI
  27. DpmiAllocateXmem(
  28. ULONG BlockSize
  29. )
  30. /*++
  31. Routine Description:
  32. This routine allocates a block of "extended" memory from NT. The
  33. blocks allocated this way will be 64K aligned (for now). The address
  34. of the block is returned to the segmented app in bx:cx
  35. Arguments:
  36. None.
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. ULONG BlockAddress;
  42. NTSTATUS Status;
  43. PMEM_DPMI XmemBlock;
  44. ULONG size;
  45. //
  46. // First check if this app owns more than 16 MB
  47. //
  48. size = DpmiCalculateAppXmem();
  49. if (size + BlockSize > MAX_APP_XMEM) {
  50. return NULL;
  51. }
  52. //
  53. // Get a block of memory from NT (any base address)
  54. //
  55. BlockAddress = 0;
  56. Status = DpmiAllocateVirtualMemory(
  57. (PVOID)&BlockAddress,
  58. &BlockSize
  59. );
  60. if (!NT_SUCCESS(Status)) {
  61. #if DBG
  62. OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
  63. #endif
  64. return NULL;
  65. }
  66. XmemBlock = malloc(sizeof(MEM_DPMI));
  67. if (!XmemBlock) {
  68. DpmiFreeVirtualMemory(
  69. (PVOID)&BlockAddress,
  70. &BlockSize
  71. );
  72. return NULL;
  73. }
  74. XmemBlock->Address = (PVOID)BlockAddress;
  75. XmemBlock->Length = BlockSize;
  76. XmemBlock->Owner = CurrentPSPSelector;
  77. XmemBlock->Sel = 0;
  78. XmemBlock->SelCount = 0;
  79. INSERT_BLOCK(XmemBlock, XmemHead);
  80. return XmemBlock;
  81. }
  82. BOOL
  83. DpmiFreeXmem(
  84. PMEM_DPMI XmemBlock
  85. )
  86. /*++
  87. Routine Description:
  88. This routine frees a block of "extended" memory from NT.
  89. Arguments:
  90. None.
  91. Return Value:
  92. None.
  93. --*/
  94. {
  95. NTSTATUS Status;
  96. PVOID BlockAddress;
  97. ULONG BlockSize;
  98. BlockAddress = XmemBlock->Address;
  99. BlockSize = XmemBlock->Length;
  100. Status = DpmiFreeVirtualMemory(
  101. &BlockAddress,
  102. &BlockSize
  103. );
  104. if (!NT_SUCCESS(Status)) {
  105. #if DBG
  106. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  107. #endif
  108. return FALSE;
  109. }
  110. DELETE_BLOCK(XmemBlock);
  111. free(XmemBlock);
  112. return TRUE;
  113. }
  114. BOOL
  115. DpmiIsXmemHandle(
  116. PMEM_DPMI XmemBlock
  117. )
  118. /*++
  119. Routine Description:
  120. This routine verifies that the given handle is a valid xmem handle.
  121. Arguments:
  122. Handle to be verified.
  123. Return Value:
  124. TRUE if handle is valid, FALSE otherwise.
  125. --*/
  126. {
  127. PMEM_DPMI p1;
  128. p1 = XmemHead.Next;
  129. while(p1 != &XmemHead) {
  130. if (p1 == XmemBlock) {
  131. return TRUE;
  132. }
  133. p1 = p1->Next;
  134. }
  135. return FALSE;
  136. }
  137. PMEM_DPMI
  138. DpmiFindXmem(
  139. USHORT Sel
  140. )
  141. /*++
  142. Routine Description:
  143. This routine finds a block of "extended" memory based on its Selector
  144. field.
  145. Arguments:
  146. None.
  147. Return Value:
  148. None.
  149. --*/
  150. {
  151. PMEM_DPMI p1;
  152. p1 = XmemHead.Next;
  153. while(p1 != &XmemHead) {
  154. if (p1->Sel == Sel) {
  155. return p1;
  156. }
  157. p1 = p1->Next;
  158. }
  159. return NULL;
  160. }
  161. BOOL
  162. DpmiReallocateXmem(
  163. PMEM_DPMI OldBlock,
  164. ULONG NewSize
  165. )
  166. /*++
  167. Routine Description:
  168. This routine resizes a block of "extended memory". If the change in size
  169. is less than 4K, no change is made.
  170. Arguments:
  171. None.
  172. Return Value:
  173. None.
  174. --*/
  175. {
  176. ULONG BlockAddress;
  177. NTSTATUS Status;
  178. if (DpmiCalculateAppXmem() + NewSize - OldBlock->Length > MAX_APP_XMEM) {
  179. return FALSE;
  180. }
  181. BlockAddress = 0;
  182. Status = DpmiReallocateVirtualMemory(
  183. OldBlock->Address,
  184. OldBlock->Length,
  185. (PVOID)&BlockAddress,
  186. &NewSize
  187. );
  188. if (!NT_SUCCESS(Status)) {
  189. #if DBG
  190. OutputDebugString("DPMI: DpmiAllocateXmem failed to get memory block\n");
  191. #endif
  192. return FALSE;
  193. }
  194. RESIZE_BLOCK(OldBlock, BlockAddress, NewSize);
  195. return TRUE;
  196. }
  197. VOID
  198. DpmiFreeAppXmem(
  199. USHORT Owner
  200. )
  201. /*++
  202. Routine Description:
  203. This routine frees Xmem allocated for the application
  204. Arguments:
  205. Client DX = client PSP selector
  206. Return Value:
  207. TRUE if everything goes fine.
  208. FALSE if unable to release the memory
  209. --*/
  210. {
  211. PMEM_DPMI p1, p2;
  212. NTSTATUS Status;
  213. PVOID BlockAddress;
  214. ULONG BlockSize;
  215. p1 = XmemHead.Next;
  216. while(p1 != &XmemHead) {
  217. if (p1->Owner == Owner) {
  218. BlockAddress = p1->Address;
  219. BlockSize = p1->Length;
  220. Status = DpmiFreeVirtualMemory(
  221. &BlockAddress,
  222. &BlockSize
  223. );
  224. if (!NT_SUCCESS(Status)) {
  225. #if DBG
  226. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  227. #endif
  228. return;
  229. }
  230. p2 = p1->Next;
  231. DELETE_BLOCK(p1);
  232. free(p1);
  233. p1 = p2;
  234. continue;
  235. }
  236. p1 = p1->Next;
  237. }
  238. return;
  239. }
  240. ULONG
  241. DpmiCalculateAppXmem(
  242. VOID
  243. )
  244. /*++
  245. Routine Description:
  246. This routine calculates the Xmem allocated to the CURRENT application
  247. Arguments:
  248. None.
  249. Return Value:
  250. The size of xmem allocated to the app.
  251. Note the size will never exceed 2 GB. We put a cap at about 16MB when
  252. allocating memory for the app.
  253. --*/
  254. {
  255. PMEM_DPMI p;
  256. NTSTATUS Status;
  257. ULONG Size = 0;
  258. //
  259. // If not current APP, we don't keep track of the xmem size
  260. //
  261. if (CurrentPSPSelector == 0) {
  262. return 0;
  263. }
  264. //
  265. // If CurrentPSPXmem is not zero, it is under control.
  266. // No need to initialize it. Make sure it is not negative value.
  267. //
  268. if (CurrentPSPXmem != 0 && CurrentPSPXmem <= MAX_APP_XMEM) {
  269. return CurrentPSPXmem;
  270. }
  271. p = XmemHead.Next;
  272. while(p != &XmemHead) {
  273. if (p->Owner == CurrentPSPSelector) {
  274. Size += p->Length;
  275. }
  276. p = p->Next;
  277. }
  278. CurrentPSPXmem = Size;
  279. return Size;
  280. }
  281. VOID
  282. DpmiFreeAllXmem(
  283. VOID
  284. )
  285. /*++
  286. Routine Description:
  287. This function frees all allocated xmem.
  288. Arguments:
  289. none
  290. Return Value:
  291. None.
  292. --*/
  293. {
  294. PMEM_DPMI p1, p2;
  295. NTSTATUS Status;
  296. PVOID BlockAddress;
  297. ULONG BlockSize;
  298. p1 = XmemHead.Next;
  299. while(p1 != &XmemHead) {
  300. BlockAddress = p1->Address;
  301. BlockSize = p1->Length;
  302. Status = DpmiFreeVirtualMemory(
  303. &BlockAddress,
  304. &BlockSize
  305. );
  306. if (!NT_SUCCESS(Status)) {
  307. #if DBG
  308. OutputDebugString("DPMI: DpmiFreeXmem failed to free block\n");
  309. #endif
  310. return;
  311. }
  312. p2 = p1->Next;
  313. DELETE_BLOCK(p1);
  314. free(p1);
  315. p1 = p2;
  316. }
  317. CurrentPSPXmem = 0;
  318. }