ReactOS  0.4.14-dev-614-gbfd8a84
memory.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include "bios/umamgr.h"
#include "dos.h"
#include "dos/dem.h"
#include "memory.h"
#include "process.h"
#include "himem.h"
Include dependency graph for memory.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define FIRST_MCB_SEGMENT   (SYSTEM_ENV_BLOCK + 0x200)
 
#define USER_MEMORY_SIZE   (0x9FFE - FIRST_MCB_SEGMENT)
 
#define DosMemValidate()
 

Functions

static BOOLEAN ValidateMcb (PDOS_MCB Mcb)
 
static VOID DosCombineFreeBlocks (WORD StartBlock)
 
WORD DosAllocateMemory (WORD Size, WORD *MaxAvailable)
 
BOOLEAN DosResizeMemory (WORD BlockData, WORD NewSize, WORD *MaxAvailable)
 
BOOLEAN DosFreeMemory (WORD BlockData)
 
BOOLEAN DosLinkUmb (VOID)
 
BOOLEAN DosUnlinkUmb (VOID)
 
VOID DosChangeMemoryOwner (WORD Segment, WORD NewOwner)
 
WORD DosGetPreviousUmb (WORD UmbSegment)
 
VOID DosInitializeUmb (VOID)
 
VOID DosInitializeMemory (VOID)
 

Macro Definition Documentation

◆ DosMemValidate

#define DosMemValidate ( )

Definition at line 82 of file memory.c.

◆ FIRST_MCB_SEGMENT

#define FIRST_MCB_SEGMENT   (SYSTEM_ENV_BLOCK + 0x200)

Definition at line 28 of file memory.c.

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file memory.c.

◆ USER_MEMORY_SIZE

#define USER_MEMORY_SIZE   (0x9FFE - FIRST_MCB_SEGMENT)

Definition at line 29 of file memory.c.

Function Documentation

◆ DosAllocateMemory()

WORD DosAllocateMemory ( WORD  Size,
WORD MaxAvailable 
)

Definition at line 136 of file memory.c.

137 {
138  WORD Result = 0, Segment = SysVars->FirstMcb, MaxSize = 0;
139  PDOS_MCB CurrentMcb;
140  BOOLEAN SearchUmb = FALSE;
141 
142  DPRINT("DosAllocateMemory: Size 0x%04X\n", Size);
143 
144  DosMemValidate();
145 
146  if (SysVars->UmbLinked && SysVars->UmbChainStart != 0xFFFF &&
148  {
149  /* Search UMB first */
151  SearchUmb = TRUE;
152  }
153 
154  while (TRUE)
155  {
156  /* Get a pointer to the MCB */
157  CurrentMcb = SEGMENT_TO_MCB(Segment);
158 
159  /* Make sure it's valid */
160  if (!ValidateMcb(CurrentMcb))
161  {
162  DPRINT1("The DOS memory arena is corrupted!\n");
164  return 0;
165  }
166 
167  /* Only check free blocks */
168  if (CurrentMcb->OwnerPsp != 0) goto Next;
169 
170  /* Combine this free block with adjoining free blocks */
172 
173  /* Update the maximum block size */
174  if (CurrentMcb->Size > MaxSize) MaxSize = CurrentMcb->Size;
175 
176  /* Check if this block is big enough */
177  if (CurrentMcb->Size < Size) goto Next;
178 
180  {
181  case DOS_ALLOC_FIRST_FIT:
182  {
183  /* For first fit, stop immediately */
184  Result = Segment;
185  goto Done;
186  }
187 
188  case DOS_ALLOC_BEST_FIT:
189  {
190  /* For best fit, update the smallest block found so far */
191  if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size))
192  {
193  Result = Segment;
194  }
195 
196  break;
197  }
198 
199  case DOS_ALLOC_LAST_FIT:
200  {
201  /* For last fit, make the current block the result, but keep searching */
202  Result = Segment;
203  break;
204  }
205  }
206 
207 Next:
208  /* If this was the last MCB in the chain, quit */
209  if (CurrentMcb->BlockType == 'Z')
210  {
211  /* Check if nothing was found while searching through UMBs */
212  if ((Result == 0) && SearchUmb && (Sda->AllocStrategy & DOS_ALLOC_HIGH_LOW))
213  {
214  /* Search low memory */
216  SearchUmb = FALSE;
217  continue;
218  }
219 
220  break;
221  }
222 
223  /* Otherwise, update the segment and continue */
224  Segment += CurrentMcb->Size + 1;
225  }
226 
227 Done:
228  DosMemValidate();
229 
230  /* If we didn't find a free block, bail out */
231  if (Result == 0)
232  {
233  DPRINT("DosAllocateMemory FAILED. Maximum available: 0x%04X\n", MaxSize);
235  if (MaxAvailable) *MaxAvailable = MaxSize;
236  return 0;
237  }
238 
239  /* Get a pointer to the MCB */
240  CurrentMcb = SEGMENT_TO_MCB(Result);
241 
242  /* Check if the block is larger than requested */
243  if (CurrentMcb->Size > Size)
244  {
245  /* It is, split it into two blocks */
247  {
248  PDOS_MCB NextMcb = SEGMENT_TO_MCB(Result + Size + 1);
249 
250  /* Initialize the new MCB structure */
251  NextMcb->BlockType = CurrentMcb->BlockType;
252  NextMcb->Size = CurrentMcb->Size - Size - 1;
253  NextMcb->OwnerPsp = 0;
254 
255  /* Update the current block */
256  CurrentMcb->BlockType = 'M';
257  CurrentMcb->Size = Size;
258  }
259  else
260  {
261  /* Save the location of the current MCB */
262  PDOS_MCB PreviousMcb = CurrentMcb;
263 
264  /* Move the current MCB higher */
265  Result += CurrentMcb->Size - Size;
266  CurrentMcb = SEGMENT_TO_MCB(Result);
267 
268  /* Initialize the new MCB structure */
269  CurrentMcb->BlockType = PreviousMcb->BlockType;
270  CurrentMcb->Size = Size;
271  CurrentMcb->OwnerPsp = 0;
272 
273  /* Update the previous block */
274  PreviousMcb->BlockType = 'M';
275  PreviousMcb->Size -= Size + 1;
276  }
277  }
278 
279  /* Take ownership of the block */
280  CurrentMcb->OwnerPsp = Sda->CurrentPsp;
281  RtlCopyMemory(CurrentMcb->Name, SEGMENT_TO_MCB(Sda->CurrentPsp - 1)->Name, sizeof(CurrentMcb->Name));
282 
283  DosMemValidate();
284 
285  /* Return the segment of the data portion of the block */
286  return Result + 1;
287 }
WORD LastErrorCode
Definition: dos.h:151
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define DOS_ALLOC_HIGH
Definition: memory.h:17
static VOID DosCombineFreeBlocks(WORD StartBlock)
Definition: memory.c:85
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
unsigned char BOOLEAN
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
WORD FirstMcb
Definition: dos.h:77
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
unsigned short WORD
Definition: ntddk_ex.h:93
#define DOS_ALLOC_HIGH_LOW
Definition: memory.h:18
WORD OwnerPsp
Definition: memory.h:31
PDOS_SDA Sda
Definition: dos.c:48
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
BYTE UmbLinked
Definition: dos.h:100
PDOS_SYSVARS SysVars
Definition: dos.c:47
CHAR BlockType
Definition: memory.h:30
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
WORD UmbChainStart
Definition: dos.h:102
CHAR Name[8]
Definition: memory.h:34
WORD Size
Definition: memory.h:32
BYTE AllocStrategy
Definition: dos.h:143
#define DosMemValidate()
Definition: memory.c:82
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosCopyEnvironmentBlock(), DosCountryInitialize(), DosCreateDeviceEx(), DosInt21h(), DosLoadDriver(), DosLoadExecutableInternal(), DosMouseInitialize(), and DosResizeHandleTable().

◆ DosChangeMemoryOwner()

VOID DosChangeMemoryOwner ( WORD  Segment,
WORD  NewOwner 
)

Definition at line 532 of file memory.c.

533 {
535  Mcb->OwnerPsp = NewOwner;
536 }
_Inout_ PVOID Segment
Definition: exfuncs.h:893
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosLoadExecutableInternal().

◆ DosCombineFreeBlocks()

static VOID DosCombineFreeBlocks ( WORD  StartBlock)
static

Definition at line 85 of file memory.c.

86 {
87  /* NOTE: This function is always called with valid MCB blocks */
88 
89  PDOS_MCB CurrentMcb = SEGMENT_TO_MCB(StartBlock), NextMcb;
90 
91  /* If the block is not free, quit */
92  if (CurrentMcb->OwnerPsp != 0) return;
93 
94  /*
95  * Loop while the current block is not the last one. It can happen
96  * that the block is not the last one at the beginning, but becomes
97  * the last one at the end of the process. This happens in the case
98  * where its next following blocks are free but not combined yet,
99  * and they are terminated by a free last block. During the process
100  * all the blocks are combined together and we end up in the situation
101  * where the current (free) block is followed by the last (free) block.
102  * At the last step of the algorithm the current block becomes the
103  * last one.
104  */
105  while (CurrentMcb->BlockType != 'Z')
106  {
107  /* Get a pointer to the next MCB */
108  NextMcb = SEGMENT_TO_MCB(StartBlock + CurrentMcb->Size + 1);
109 
110  /* Make sure it's valid */
111  if (!ValidateMcb(NextMcb))
112  {
113  DPRINT1("The DOS memory arena is corrupted!\n");
115  return;
116  }
117 
118  /* Check if the next MCB is free */
119  if (NextMcb->OwnerPsp == 0)
120  {
121  /* Combine them */
122  CurrentMcb->Size += NextMcb->Size + 1;
123  CurrentMcb->BlockType = NextMcb->BlockType;
124  NextMcb->BlockType = 'I';
125  }
126  else
127  {
128  /* No more adjoining free blocks */
129  break;
130  }
131  }
132 }
WORD LastErrorCode
Definition: dos.h:151
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
WORD OwnerPsp
Definition: memory.h:31
PDOS_SDA Sda
Definition: dos.c:48
CHAR BlockType
Definition: memory.h:30
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
WORD Size
Definition: memory.h:32
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosAllocateMemory(), and DosResizeMemory().

◆ DosFreeMemory()

BOOLEAN DosFreeMemory ( WORD  BlockData)

Definition at line 418 of file memory.c.

419 {
420  PDOS_MCB Mcb = SEGMENT_TO_MCB(BlockData - 1);
421 
422  DPRINT("DosFreeMemory: BlockData 0x%04X\n", BlockData);
423 
424  if (BlockData == 0)
425  {
427  return FALSE;
428  }
429 
430  DosMemValidate();
431 
432  /* Make sure the MCB is valid */
433  if (!ValidateMcb(Mcb))
434  {
435  DPRINT("MCB block type '%c' not valid!\n", Mcb->BlockType);
437  return FALSE;
438  }
439 
440  /* Mark the block as free */
441  Mcb->OwnerPsp = 0;
442 
443  return TRUE;
444 }
WORD LastErrorCode
Definition: dos.h:151
#define TRUE
Definition: types.h:120
#define ERROR_INVALID_BLOCK
Definition: winerror.h:112
void DPRINT(...)
Definition: polytest.cpp:61
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
PDOS_SDA Sda
Definition: dos.c:48
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define DosMemValidate()
Definition: memory.c:82
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosCreateDeviceEx(), DosDeleteDevice(), DosInt21h(), DosLoadDriver(), DosLoadExecutableInternal(), DosMouseCleanup(), DosResizeHandleTable(), and DosTerminateProcess().

◆ DosGetPreviousUmb()

WORD DosGetPreviousUmb ( WORD  UmbSegment)

Definition at line 544 of file memory.c.

545 {
546  PDOS_MCB CurrentMcb;
547  WORD Segment, PrevSegment = 0; // FIXME: or use UmbChainStart ??
548 
549  if (SysVars->UmbChainStart == 0xFFFF)
550  return 0;
551 
552  /* Start scanning the UMB chain */
554  while (TRUE)
555  {
556  /* Get a pointer to the MCB */
557  CurrentMcb = SEGMENT_TO_MCB(Segment);
558 
559  /* Make sure it's valid */
560  if (!ValidateMcb(CurrentMcb))
561  {
562  DPRINT1("The UMB DOS memory arena is corrupted!\n");
564  return 0;
565  }
566 
567  /* We went over the UMB segment, quit */
568  if (Segment >= UmbSegment) break;
569 
570  PrevSegment = Segment;
571 
572  /* If this was the last MCB in the chain, quit */
573  if (CurrentMcb->BlockType == 'Z') break;
574 
575  /* Otherwise, update the segment and continue */
576  Segment += CurrentMcb->Size + 1;
577  }
578 
579  return PrevSegment;
580 }
WORD LastErrorCode
Definition: dos.h:151
#define TRUE
Definition: types.h:120
_Inout_ PVOID Segment
Definition: exfuncs.h:893
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
unsigned short WORD
Definition: ntddk_ex.h:93
PDOS_SDA Sda
Definition: dos.c:48
PDOS_SYSVARS SysVars
Definition: dos.c:47
CHAR BlockType
Definition: memory.h:30
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
WORD UmbChainStart
Definition: dos.h:102
WORD Size
Definition: memory.h:32
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosInitializeUmb().

◆ DosInitializeMemory()

VOID DosInitializeMemory ( VOID  )

Definition at line 665 of file memory.c.

666 {
667  PDOS_MCB Mcb;
668 
669  /* Set the initial allocation strategy to "best fit" */
671 
672  /* Initialize conventional memory; we don't have UMBs yet */
673  SysVars->FirstMcb = FIRST_MCB_SEGMENT; // The Arena Head
675  SysVars->UmbChainStart = 0xFFFF;
676 
678 
679  /* Initialize the MCB */
680  Mcb->BlockType = 'Z';
681  Mcb->Size = USER_MEMORY_SIZE;
682  Mcb->OwnerPsp = 0;
683 }
#define USER_MEMORY_SIZE
Definition: memory.c:29
WORD FirstMcb
Definition: dos.h:77
#define FIRST_MCB_SEGMENT
Definition: memory.c:28
PDOS_SDA Sda
Definition: dos.c:48
BYTE UmbLinked
Definition: dos.h:100
PDOS_SYSVARS SysVars
Definition: dos.c:47
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
WORD UmbChainStart
Definition: dos.h:102
BYTE AllocStrategy
Definition: dos.h:143
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosKRNLInitialize().

◆ DosInitializeUmb()

VOID DosInitializeUmb ( VOID  )

Definition at line 582 of file memory.c.

583 {
584  BOOLEAN Result;
585  USHORT UmbSegment = 0x0000, PrevSegment;
586  USHORT Size;
587  PDOS_MCB Mcb, PrevMcb;
588 
589  ASSERT(SysVars->UmbChainStart == 0xFFFF);
590 
591  // SysVars->UmbLinked = FALSE;
592 
593  /* Try to allocate all the UMBs */
594  while (TRUE)
595  {
596  /* Find the maximum amount of memory that can be allocated */
597  Size = 0xFFFF;
598  Result = UmaDescReserve(&UmbSegment, &Size);
599 
600  /* If we are out of UMBs, bail out */
601  if (!Result && Size == 0) // XMS_STATUS_OUT_OF_UMBS
602  break;
603 
604  /* We should not have succeeded! */
605  ASSERT(!Result);
606 
607  /* 'Size' now contains the size of the biggest UMB block. Request it. */
608  Result = UmaDescReserve(&UmbSegment, &Size);
609  ASSERT(Result); // XMS_STATUS_SUCCESS
610 
611  /* If this is our first UMB block, initialize the UMB chain */
612  if (SysVars->UmbChainStart == 0xFFFF)
613  {
614  /* Initialize the link MCB to the UMB area */
615  // NOTE: We use the fact that UmbChainStart is still == 0xFFFF
616  // so that we initialize this block from 9FFF:0000 up to FFFF:000F.
617  // It will be splitted as needed just below.
618  Mcb = SEGMENT_TO_MCB(SysVars->FirstMcb + USER_MEMORY_SIZE + 1); // '+1': Readjust the fact that USER_MEMORY_SIZE is based using 0x9FFE instead of 0x9FFF
619  Mcb->BlockType = 'Z'; // At the moment it is really the last block
620  Mcb->Size = (SysVars->UmbChainStart /* UmbSegment */ - SysVars->FirstMcb - USER_MEMORY_SIZE - 2) + 1;
621  Mcb->OwnerPsp = SYSTEM_PSP;
622  RtlCopyMemory(Mcb->Name, "SC ", sizeof("SC ")-1);
623 
624 #if 0 // Keep here for reference; this will be deleted as soon as it becomes unneeded.
625  /* Initialize the UMB area */
627  Mcb->Size = UMB_END_SEGMENT - SysVars->UmbChainStart;
628 #endif
629 
630  // FIXME: We should adjust the size of the previous block!!
631 
632  /* Initialize the start of the UMB chain */
634  }
635 
636  /* Split the block */
637 
638  /* Get the previous block */
639  PrevSegment = DosGetPreviousUmb(UmbSegment);
640  PrevMcb = SEGMENT_TO_MCB(PrevSegment);
641 
642  /* Initialize the next block */
643  Mcb = SEGMENT_TO_MCB(UmbSegment + /*Mcb->Size*/(Size - 1) + 0);
644  // Mcb->BlockType = 'Z'; // FIXME: What if this block happens to be the last one??
645  Mcb->BlockType = PrevMcb->BlockType;
646  Mcb->Size = PrevMcb->Size - (UmbSegment + Size - PrevSegment) + 1;
647  Mcb->OwnerPsp = PrevMcb->OwnerPsp;
648  RtlCopyMemory(Mcb->Name, PrevMcb->Name, sizeof(PrevMcb->Name));
649 
650  /* The previous block is not the latest one anymore */
651  PrevMcb->BlockType = 'M';
652  PrevMcb->Size = UmbSegment - PrevSegment - 1;
653 
654  /* Initialize the new UMB block */
655  Mcb = SEGMENT_TO_MCB(UmbSegment);
656  Mcb->BlockType = 'M'; // 'Z' // FIXME: What if this block happens to be the last one??
657  Mcb->Size = Size - 1 - 1; // minus 2 because we need to have one arena at the beginning and one at the end.
658  Mcb->OwnerPsp = 0;
659  // FIXME: Which MCB name should we use? I need to explore more the docs!
660  RtlCopyMemory(Mcb->Name, "UMB ", sizeof("UMB ")-1);
661  // RtlCopyMemory(Mcb->Name, "SM ", sizeof("SM ")-1);
662  }
663 }
BOOLEAN UmaDescReserve(IN OUT PUSHORT Segment, IN OUT PUSHORT Size)
Definition: umamgr.c:84
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define USER_MEMORY_SIZE
Definition: memory.c:29
unsigned char BOOLEAN
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
WORD FirstMcb
Definition: dos.h:77
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
WORD OwnerPsp
Definition: memory.h:31
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
unsigned short USHORT
Definition: pedump.c:61
PDOS_SYSVARS SysVars
Definition: dos.c:47
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define SYSTEM_PSP
Definition: dos.h:39
CHAR BlockType
Definition: memory.h:30
WORD UmbChainStart
Definition: dos.h:102
CHAR Name[8]
Definition: memory.h:34
WORD DosGetPreviousUmb(WORD UmbSegment)
Definition: memory.c:544
WORD Size
Definition: memory.h:32
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosKRNLInitialize().

◆ DosLinkUmb()

BOOLEAN DosLinkUmb ( VOID  )

Definition at line 446 of file memory.c.

447 {
450 
451  DPRINT("Linking UMB\n");
452 
453  /* Check if UMBs are initialized and already linked */
454  if (SysVars->UmbChainStart == 0xFFFF) return FALSE;
455  if (SysVars->UmbLinked) return TRUE;
456 
457  DosMemValidate();
458 
459  /* Find the last block before the start of the UMB chain */
460  while (Segment < SysVars->UmbChainStart)
461  {
462  /* Get a pointer to the MCB */
464 
465  /* Make sure it's valid */
466  if (!ValidateMcb(Mcb))
467  {
468  DPRINT1("The DOS memory arena is corrupted!\n");
470  return FALSE;
471  }
472 
473  /* If this was the last MCB in the chain, quit */
474  if (Mcb->BlockType == 'Z') break;
475 
476  /* Otherwise, update the segment and continue */
477  Segment += Mcb->Size + 1;
478  }
479 
480  /* Make sure it's valid */
481  if (Mcb->BlockType != 'Z') return FALSE;
482 
483  /* Connect the MCB with the UMB chain */
484  Mcb->BlockType = 'M';
485 
486  DosMemValidate();
487 
489  return TRUE;
490 }
WORD LastErrorCode
Definition: dos.h:151
#define TRUE
Definition: types.h:120
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
WORD FirstMcb
Definition: dos.h:77
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
PDOS_SDA Sda
Definition: dos.c:48
BYTE UmbLinked
Definition: dos.h:100
PDOS_SYSVARS SysVars
Definition: dos.c:47
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
WORD UmbChainStart
Definition: dos.h:102
#define DosMemValidate()
Definition: memory.c:82
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosInt21h().

◆ DosResizeMemory()

BOOLEAN DosResizeMemory ( WORD  BlockData,
WORD  NewSize,
WORD MaxAvailable 
)

Definition at line 289 of file memory.c.

290 {
291  BOOLEAN Success = TRUE;
292  WORD Segment = BlockData - 1, ReturnSize = 0, NextSegment;
293  PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment), NextMcb;
294 
295  DPRINT("DosResizeMemory: BlockData 0x%04X, NewSize 0x%04X\n",
296  BlockData, NewSize);
297 
298  DosMemValidate();
299 
300  /* Make sure this is a valid and allocated block */
301  if (BlockData == 0 || !ValidateMcb(Mcb) || Mcb->OwnerPsp == 0)
302  {
304  Success = FALSE;
305  goto Done;
306  }
307 
308  ReturnSize = Mcb->Size;
309 
310  /* Check if we need to expand or contract the block */
311  if (NewSize > Mcb->Size)
312  {
313  /* We can't expand the last block */
314  if (Mcb->BlockType == 'Z')
315  {
316  DPRINT("Cannot expand memory block 0x%04X: this is the last block (size 0x%04X)!\n", Segment, Mcb->Size);
318  Success = FALSE;
319  goto Done;
320  }
321 
322  /* Get the pointer and segment of the next MCB */
323  NextSegment = Segment + Mcb->Size + 1;
324  NextMcb = SEGMENT_TO_MCB(NextSegment);
325 
326  /* Make sure it's valid */
327  if (!ValidateMcb(NextMcb))
328  {
329  DPRINT1("The DOS memory arena is corrupted!\n");
331  return FALSE;
332  }
333 
334  /* Make sure the next segment is free */
335  if (NextMcb->OwnerPsp != 0)
336  {
337  DPRINT("Cannot expand memory block 0x%04X: next segment is not free!\n", Segment);
339  Success = FALSE;
340  goto Done;
341  }
342 
343  /* Combine this free block with adjoining free blocks */
344  DosCombineFreeBlocks(NextSegment);
345 
346  /* Set the maximum possible size of the block */
347  ReturnSize += NextMcb->Size + 1;
348 
349  if (ReturnSize < NewSize)
350  {
351  DPRINT("Cannot expand memory block 0x%04X: insufficient free segments available!\n", Segment);
353  Success = FALSE;
354  goto Done;
355  }
356 
357  /* Maximize the current block */
358  Mcb->Size = ReturnSize;
359  Mcb->BlockType = NextMcb->BlockType;
360 
361  /* Invalidate the next block */
362  NextMcb->BlockType = 'I';
363 
364  /* Check if the block is larger than requested */
365  if (Mcb->Size > NewSize)
366  {
367  DPRINT("Block too large, reducing size from 0x%04X to 0x%04X\n",
368  Mcb->Size, NewSize);
369 
370  /* It is, split it into two blocks */
371  NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1);
372 
373  /* Initialize the new MCB structure */
374  NextMcb->BlockType = Mcb->BlockType;
375  NextMcb->Size = Mcb->Size - NewSize - 1;
376  NextMcb->OwnerPsp = 0;
377 
378  /* Update the current block */
379  Mcb->BlockType = 'M';
380  Mcb->Size = NewSize;
381  }
382  }
383  else if (NewSize < Mcb->Size)
384  {
385  DPRINT("Shrinking block from 0x%04X to 0x%04X\n",
386  Mcb->Size, NewSize);
387 
388  /* Just split the block */
389  NextSegment = Segment + NewSize + 1;
390  NextMcb = SEGMENT_TO_MCB(NextSegment);
391  NextMcb->BlockType = Mcb->BlockType;
392  NextMcb->Size = Mcb->Size - NewSize - 1;
393  NextMcb->OwnerPsp = 0;
394 
395  /* Update the MCB */
396  Mcb->BlockType = 'M';
397  Mcb->Size = NewSize;
398 
399  /* Combine this free block with adjoining free blocks */
400  DosCombineFreeBlocks(NextSegment);
401  }
402 
403 Done:
404  /* Check if the operation failed */
405  if (!Success)
406  {
407  DPRINT("DosResizeMemory FAILED. Maximum available: 0x%04X\n", ReturnSize);
408 
409  /* Return the maximum possible size */
410  if (MaxAvailable) *MaxAvailable = ReturnSize;
411  }
412 
413  DosMemValidate();
414 
415  return Success;
416 }
WORD LastErrorCode
Definition: dos.h:151
#define TRUE
Definition: types.h:120
static VOID DosCombineFreeBlocks(WORD StartBlock)
Definition: memory.c:85
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INVALID_BLOCK
Definition: winerror.h:112
unsigned char BOOLEAN
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
unsigned short WORD
Definition: ntddk_ex.h:93
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
PDOS_SDA Sda
Definition: dos.c:48
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
#define DosMemValidate()
Definition: memory.c:82
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosInt21h(), DosResizeHandleTable(), and DosTerminateProcess().

◆ DosUnlinkUmb()

BOOLEAN DosUnlinkUmb ( VOID  )

Definition at line 492 of file memory.c.

493 {
496 
497  DPRINT("Unlinking UMB\n");
498 
499  /* Check if UMBs are initialized and already unlinked */
500  if (SysVars->UmbChainStart == 0xFFFF) return FALSE;
501  if (!SysVars->UmbLinked) return TRUE;
502 
503  DosMemValidate();
504 
505  /* Find the last block before the start of the UMB chain */
506  while (Segment < SysVars->UmbChainStart)
507  {
508  /* Get a pointer to the MCB */
510 
511  /* Make sure it's valid */
512  if (!ValidateMcb(Mcb))
513  {
514  DPRINT1("The DOS memory arena is corrupted!\n");
516  return FALSE;
517  }
518 
519  /* Advance to the next MCB */
520  Segment += Mcb->Size + 1;
521  }
522 
523  /* Mark the MCB as the last MCB */
524  Mcb->BlockType = 'Z';
525 
526  DosMemValidate();
527 
529  return TRUE;
530 }
WORD LastErrorCode
Definition: dos.h:151
#define TRUE
Definition: types.h:120
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
WORD FirstMcb
Definition: dos.h:77
static BOOLEAN ValidateMcb(PDOS_MCB Mcb)
Definition: memory.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
PDOS_SDA Sda
Definition: dos.c:48
BYTE UmbLinked
Definition: dos.h:100
PDOS_SYSVARS SysVars
Definition: dos.c:47
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334
#define ERROR_ARENA_TRASHED
Definition: winerror.h:110
#define DPRINT1
Definition: precomp.h:8
WORD UmbChainStart
Definition: dos.h:102
#define DosMemValidate()
Definition: memory.c:82
#define SEGMENT_TO_MCB(seg)
Definition: memory.h:15

Referenced by DosInt21h().

◆ ValidateMcb()

static BOOLEAN ValidateMcb ( PDOS_MCB  Mcb)
inlinestatic

Definition at line 44 of file memory.c.

45 {
46  return (Mcb->BlockType == 'M' || Mcb->BlockType == 'Z');
47 }
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:334

Referenced by DosAllocateMemory(), DosCombineFreeBlocks(), DosFreeMemory(), DosGetPreviousUmb(), DosLinkUmb(), DosResizeMemory(), and DosUnlinkUmb().