Use ULONG_PTR instead of ULONG when doing pointer arithmetics.
[reactos.git] / reactos / ntoskrnl / mm / marea.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998-2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/mm/marea.c
22 * PURPOSE: Implements memory areas
23 * PROGRAMMER: David Welch (welch@mcmail.com)
24 * UPDATE HISTORY:
25 * Created 22/05/98
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <roscfg.h>
31 #include <ddk/ntddk.h>
32 #include <internal/mm.h>
33 #include <internal/ps.h>
34 #include <internal/pool.h>
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 /* GLOBALS *******************************************************************/
40
41 #define TAG_MAREA TAG('M', 'A', 'R', 'E')
42
43 #ifdef DBG
44 PVOID MiMemoryAreaBugCheckAddress = (PVOID) NULL;
45 #endif /* DBG */
46
47 /* Define to track memory area references */
48 //#define TRACK_MEMORY_AREA_REFERENCES
49
50 /* FUNCTIONS *****************************************************************/
51
52 VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
53 {
54 PLIST_ENTRY current_entry;
55 MEMORY_AREA* current;
56
57 DbgPrint("MmDumpMemoryAreas()\n");
58
59 current_entry = ListHead->Flink;
60 while (current_entry!=ListHead)
61 {
62 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
63 DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
64 current->BaseAddress,current->Length,
65 current->BaseAddress+current->Length,current->Attributes,
66 current->Entry.Flink);
67 current_entry = current_entry->Flink;
68 }
69 DbgPrint("Finished MmDumpMemoryAreas()\n");
70 }
71
72 #ifdef DBG
73
74 VOID
75 MiValidateMemoryAreaPTEs(IN PMEMORY_AREA MemoryArea)
76 {
77 ULONG PteProtect;
78 ULONG i;
79
80 if (!MiInitialized)
81 return;
82
83 for (i = 0; i <= (MemoryArea->Length / PAGESIZE); i++)
84 {
85 if (MmIsPagePresent(MemoryArea->Process, MemoryArea->BaseAddress + (i * PAGESIZE)))
86 {
87 PteProtect = MmGetPageProtect(MemoryArea->Process, MemoryArea->BaseAddress + (i * PAGESIZE));
88 if (PteProtect != MemoryArea->Attributes)
89 {
90 if (MmIsCopyOnWriteMemoryArea(MemoryArea))
91 {
92 if ((PteProtect != PAGE_READONLY) && (PteProtect != PAGE_EXECUTE_READ))
93 {
94 DPRINT1("COW memory area attributes 0x%.08x\n", MemoryArea->Attributes);
95 DbgMmDumpProtection(MemoryArea->Attributes);
96 DPRINT1("PTE attributes 0x%.08x\n", PteProtect);
97 DbgMmDumpProtection(PteProtect);
98 assertmsg(FALSE, ("PTE attributes and memory area protection are different. Area 0x%.08x\n",
99 MemoryArea->BaseAddress));
100 }
101 }
102 else
103 {
104 DPRINT1("Memory area attributes 0x%.08x\n", MemoryArea->Attributes);
105 DbgMmDumpProtection(MemoryArea->Attributes);
106 DPRINT1("PTE attributes 0x%.08x\n", PteProtect);
107 DbgMmDumpProtection(PteProtect);
108 assertmsg(FALSE, ("PTE attributes and memory area protection are different. Area 0x%.08x\n",
109 MemoryArea->BaseAddress));
110 }
111 }
112 }
113 }
114 }
115
116
117 VOID
118 MiValidateMemoryArea(IN PMEMORY_AREA MemoryArea)
119 {
120 assertmsg(MemoryArea != NULL,
121 ("No memory area can exist at 0x%.08x\n", MemoryArea));
122
123 assertmsg(MemoryArea->Magic == TAG_MAREA,
124 ("Bad magic (0x%.08x) for memory area (0x%.08x). It should be 0x%.08x\n",
125 MemoryArea->Magic, MemoryArea, TAG_MAREA));
126
127 /* FIXME: Can cause page faults and deadlock on the address space lock */
128 //MiValidateMemoryAreaPTEs(MemoryArea);
129 }
130
131 #endif /* DBG */
132
133 VOID
134 MmApplyMemoryAreaProtection(IN PMEMORY_AREA MemoryArea)
135 {
136 ULONG i;
137
138 if (!MiInitialized)
139 return;
140
141 for (i = 0; i <= (MemoryArea->Length / PAGESIZE); i++)
142 {
143 if (MmIsPagePresent(MemoryArea->Process, MemoryArea->BaseAddress + (i * PAGESIZE)))
144 {
145 MmSetPageProtect(MemoryArea->Process,
146 MemoryArea->BaseAddress + (i * PAGESIZE),
147 MemoryArea->Attributes);
148 }
149 }
150 }
151
152
153 /*
154 * NOTE: If the memory area is found, then it is referenced. The caller must
155 * call MmCloseMemoryArea() after use.
156 */
157 PMEMORY_AREA
158 MmOpenMemoryAreaByAddress(IN PMADDRESS_SPACE AddressSpace,
159 IN PVOID Address)
160 {
161 PLIST_ENTRY current_entry;
162 MEMORY_AREA* current;
163 PLIST_ENTRY previous_entry;
164
165 DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
166 AddressSpace, Address);
167
168 // MmDumpMemoryAreas(&AddressSpace->MAreaListHead);
169
170 previous_entry = &AddressSpace->MAreaListHead;
171 current_entry = AddressSpace->MAreaListHead.Flink;
172 while (current_entry != &AddressSpace->MAreaListHead)
173 {
174 current = CONTAINING_RECORD(current_entry,
175 MEMORY_AREA,
176 Entry);
177 DPRINT("Scanning %x BaseAddress %x Length %x\n",
178 current, current->BaseAddress, current->Length);
179 assert(current_entry->Blink->Flink == current_entry);
180 if (current_entry->Flink->Blink != current_entry)
181 {
182 DPRINT1("BaseAddress %x\n", current->BaseAddress);
183 DPRINT1("current_entry->Flink %x ", current_entry->Flink);
184 DPRINT1("&current_entry->Flink %x\n",
185 &current_entry->Flink);
186 DPRINT1("current_entry->Flink->Blink %x\n",
187 current_entry->Flink->Blink);
188 DPRINT1("&current_entry->Flink->Blink %x\n",
189 &current_entry->Flink->Blink);
190 DPRINT1("&current_entry->Flink %x\n",
191 &current_entry->Flink);
192 }
193 assert(current_entry->Flink->Blink == current_entry);
194 assert(previous_entry->Flink == current_entry);
195 if (current->BaseAddress <= Address &&
196 (current->BaseAddress + current->Length) > Address)
197 {
198 DPRINT("%s() = %x\n",__FUNCTION__,current);
199 MmReferenceMemoryArea(current);
200 return(current);
201 }
202 if (current->BaseAddress > Address)
203 {
204 DPRINT("%s() = NULL\n",__FUNCTION__);
205 return(NULL);
206 }
207 previous_entry = current_entry;
208 current_entry = current_entry->Flink;
209 }
210 DPRINT("%s() = NULL\n",__FUNCTION__);
211 return(NULL);
212 }
213
214 /*
215 * NOTE: If the memory area is found, then it is referenced. The caller must
216 * call MmCloseMemoryArea() after use.
217 */
218 MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
219 PVOID Address,
220 ULONG Length)
221 {
222 PLIST_ENTRY current_entry;
223 MEMORY_AREA* current;
224 ULONG Extent;
225
226 DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
227 AddressSpace, Address, Length);
228
229 current_entry = AddressSpace->MAreaListHead.Flink;
230 while (current_entry != &AddressSpace->MAreaListHead)
231 {
232 current = CONTAINING_RECORD(current_entry,
233 MEMORY_AREA,
234 Entry);
235 DPRINT("current->BaseAddress %x current->Length %x\n",
236 current->BaseAddress,current->Length);
237 if (current->BaseAddress >= Address &&
238 current->BaseAddress < (Address+Length))
239 {
240 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
241 current);
242 MmReferenceMemoryArea(current);
243 return(current);
244 }
245 Extent = (ULONG)current->BaseAddress + current->Length;
246 if (Extent > (ULONG)Address &&
247 Extent < (ULONG)(Address+Length))
248 {
249 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
250 current);
251 MmReferenceMemoryArea(current);
252 return(current);
253 }
254 if (current->BaseAddress <= Address &&
255 Extent >= (ULONG)(Address+Length))
256 {
257 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
258 current);
259 MmReferenceMemoryArea(current);
260 return(current);
261 }
262 if (current->BaseAddress >= (Address+Length))
263 {
264 DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
265 return(NULL);
266 }
267 current_entry = current_entry->Flink;
268 }
269 DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
270 return(NULL);
271 }
272
273
274 VOID
275 MmCloseMemoryArea(IN PMEMORY_AREA MemoryArea)
276 {
277 MmDereferenceMemoryArea(MemoryArea);
278 }
279
280
281 static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
282 MEMORY_AREA* marea)
283 {
284 PLIST_ENTRY ListHead;
285 PLIST_ENTRY current_entry;
286 PLIST_ENTRY inserted_entry = &marea->Entry;
287 MEMORY_AREA* current;
288 MEMORY_AREA* next;
289
290 DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
291 DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
292 DPRINT("marea->Length %x\n", marea->Length);
293
294 ListHead = &AddressSpace->MAreaListHead;
295
296 current_entry = ListHead->Flink;
297 CHECKPOINT;
298 if (IsListEmpty(ListHead))
299 {
300 CHECKPOINT;
301 InsertHeadList(ListHead,&marea->Entry);
302 DPRINT("Inserting at list head\n");
303 CHECKPOINT;
304 return;
305 }
306 CHECKPOINT;
307 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
308 CHECKPOINT;
309 if (current->BaseAddress > marea->BaseAddress)
310 {
311 CHECKPOINT;
312 InsertHeadList(ListHead,&marea->Entry);
313 DPRINT("Inserting at list head\n");
314 CHECKPOINT;
315 return;
316 }
317 CHECKPOINT;
318 while (current_entry->Flink!=ListHead)
319 {
320 // CHECKPOINT;
321 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
322 next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
323 // assert(current->BaseAddress != marea->BaseAddress);
324 // assert(next->BaseAddress != marea->BaseAddress);
325 if (current->BaseAddress < marea->BaseAddress &&
326 current->Entry.Flink==ListHead)
327 {
328 DPRINT("Insert after %x\n", current_entry);
329 current_entry->Flink = inserted_entry;
330 inserted_entry->Flink=ListHead;
331 inserted_entry->Blink=current_entry;
332 ListHead->Blink = inserted_entry;
333 return;
334 }
335 if (current->BaseAddress < marea->BaseAddress &&
336 next->BaseAddress > marea->BaseAddress)
337 {
338 DPRINT("Inserting before %x\n", current_entry);
339 inserted_entry->Flink = current_entry->Flink;
340 inserted_entry->Blink = current_entry;
341 inserted_entry->Flink->Blink = inserted_entry;
342 current_entry->Flink=inserted_entry;
343 return;
344 }
345 current_entry = current_entry->Flink;
346 }
347 CHECKPOINT;
348 DPRINT("Inserting at list tail\n");
349 InsertTailList(ListHead,inserted_entry);
350 }
351
352 static PVOID MmFindGap(PMADDRESS_SPACE AddressSpace,
353 ULONG Length)
354 {
355 PLIST_ENTRY ListHead;
356 PLIST_ENTRY current_entry;
357 MEMORY_AREA* current;
358 MEMORY_AREA* next;
359 ULONG Gap;
360
361 DPRINT("MmFindGap(Length %x)\n",Length);
362
363 ListHead = &AddressSpace->MAreaListHead;
364
365 current_entry = ListHead->Flink;
366 while (current_entry->Flink!=ListHead)
367 {
368 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
369 next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
370 DPRINT("current %x current->BaseAddress %x ",current,
371 current->BaseAddress);
372 DPRINT("current->Length %x\n",current->Length);
373 DPRINT("next %x next->BaseAddress %x ",next,next->BaseAddress);
374 Gap = (next->BaseAddress ) -(current->BaseAddress + current->Length);
375 DPRINT("Base %x Gap %x\n",current->BaseAddress,Gap);
376 if (Gap >= Length)
377 {
378 return(current->BaseAddress + PAGE_ROUND_UP(current->Length));
379 }
380 current_entry = current_entry->Flink;
381 }
382
383 if (current_entry == ListHead)
384 {
385 return((PVOID)AddressSpace->LowestAddress);
386 }
387
388 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
389 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
390 // current->Length);
391 return(current->BaseAddress + PAGE_ROUND_UP(current->Length));
392 }
393
394 NTSTATUS MmInitMemoryAreas(VOID)
395 /*
396 * FUNCTION: Initialize the memory area list
397 */
398 {
399 DPRINT("MmInitMemoryAreas()\n",0);
400 return(STATUS_SUCCESS);
401 }
402
403 /* NOTE: The address space lock must be held when called */
404 NTSTATUS
405 MmFreeMemoryArea(IN PMADDRESS_SPACE AddressSpace,
406 IN PVOID BaseAddress,
407 IN ULONG Length,
408 IN PFREE_MEMORY_AREA_PAGE_CALLBACK FreePage,
409 IN PVOID FreePageContext)
410 {
411 MEMORY_AREA* MemoryArea;
412 ULONG i;
413
414 DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x, "
415 "FreePageContext %d)\n",AddressSpace,BaseAddress,Length,FreePageContext);
416
417 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress);
418 if (MemoryArea == NULL)
419 {
420 assertmsg(FALSE, ("Freeing non-existant memory area at 0x%.08x\n", BaseAddress));
421 return(STATUS_UNSUCCESSFUL);
422 }
423
424 MmCloseMemoryArea(MemoryArea);
425 InterlockedDecrement(&MemoryArea->ReferenceCount);
426 #if 0
427 assertmsg(MemoryArea->ReferenceCount == 0,
428 ("Memory area at address 0x%.08x has %d outstanding references\n",
429 BaseAddress, MemoryArea->ReferenceCount));
430 #endif
431 for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGESIZE); i++)
432 {
433 ULONG_PTR PhysicalPage = 0;
434 BOOLEAN Dirty = FALSE;
435 SWAPENTRY SwapEntry = 0;
436 PVOID VirtualPage = NULL;
437
438 VirtualPage = MemoryArea->BaseAddress + (i * PAGESIZE);
439
440 #ifdef DBG
441 if ((MiMemoryAreaBugCheckAddress != NULL)
442 && ((MiMemoryAreaBugCheckAddress >= VirtualPage)
443 && MiMemoryAreaBugCheckAddress < VirtualPage + PAGESIZE))
444 {
445 assertmsg(FALSE, ("VirtualPage 0x%.08x MiMemoryAreaBugCheckAddress 0x%.08x \n",
446 VirtualPage));
447 }
448 #endif
449
450 if (FreePage != NULL)
451 {
452 FreePage(TRUE, FreePageContext, MemoryArea,
453 VirtualPage, 0, 0, FALSE);
454 }
455
456 if (MmIsPageSwapEntry(AddressSpace->Process, VirtualPage))
457 {
458 MmDeletePageFileMapping(AddressSpace->Process,
459 VirtualPage,
460 &SwapEntry);
461 }
462 else
463 {
464 MmDeleteVirtualMapping(AddressSpace->Process,
465 VirtualPage,
466 FALSE, &Dirty, &PhysicalPage);
467 }
468 if (FreePage != NULL)
469 {
470 FreePage(FALSE, FreePageContext, MemoryArea,
471 VirtualPage, PhysicalPage, SwapEntry, Dirty);
472 }
473 }
474
475 RemoveEntryList(&MemoryArea->Entry);
476 ExFreePool(MemoryArea);
477
478 DPRINT("MmFreeMemoryArea() succeeded\n");
479
480 return(STATUS_SUCCESS);
481 }
482
483 PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
484 PMADDRESS_SPACE AddressSpace,
485 PMEMORY_AREA OriginalMemoryArea,
486 PVOID BaseAddress,
487 ULONG Length,
488 ULONG NewType,
489 ULONG NewAttributes)
490 {
491 PMEMORY_AREA Result;
492 PMEMORY_AREA Split;
493
494 Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
495 TAG_MAREA);
496 RtlZeroMemory(Result,sizeof(MEMORY_AREA));
497 Result->Type = NewType;
498 Result->BaseAddress = BaseAddress;
499 Result->Length = Length;
500 Result->Attributes = NewAttributes;
501 Result->LockCount = 0;
502 Result->ReferenceCount = 1;
503 Result->Process = Process;
504
505 if (BaseAddress == OriginalMemoryArea->BaseAddress)
506 {
507 OriginalMemoryArea->BaseAddress = BaseAddress + Length;
508 OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
509 MmInsertMemoryArea(AddressSpace, Result);
510 return(Result);
511 }
512 if ((BaseAddress + Length) ==
513 (OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
514 {
515 OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
516 MmInsertMemoryArea(AddressSpace, Result);
517
518 return(Result);
519 }
520
521 Split = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
522 TAG_MAREA);
523 RtlCopyMemory(Split,OriginalMemoryArea,sizeof(MEMORY_AREA));
524 Split->BaseAddress = BaseAddress + Length;
525 Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
526 + Length);
527
528 OriginalMemoryArea->Length = BaseAddress - OriginalMemoryArea->BaseAddress;
529
530 return(Split);
531 }
532
533 NTSTATUS
534 MmCreateMemoryArea(IN PEPROCESS Process,
535 IN PMADDRESS_SPACE AddressSpace,
536 IN ULONG Type,
537 IN OUT PVOID* BaseAddress,
538 IN ULONG Length,
539 IN ULONG Attributes,
540 OUT PMEMORY_AREA* Result,
541 IN BOOLEAN FixedAddress)
542 /*
543 * FUNCTION: Create a memory area
544 * ARGUMENTS:
545 * AddressSpace = Address space to create the area in
546 * Type = Type of the address space
547 * BaseAddress =
548 * Length = Length to allocate
549 * Attributes = Protection attributes for the memory area
550 * Result = Receives a pointer to the memory area on exit
551 * FixedAddress = Wether the memory area must be based at BaseAddress or not
552 * RETURNS: Status
553 * NOTES: Lock the address space before calling this function
554 */
555 {
556 PMEMORY_AREA MemoryArea;
557
558 DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
559 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
560 Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
561
562 if ((*BaseAddress)==0 && !FixedAddress)
563 {
564 *BaseAddress = MmFindGap(AddressSpace,
565 PAGE_ROUND_UP(Length) +(PAGESIZE*2));
566 if ((*BaseAddress)==0)
567 {
568 DPRINT("No suitable gap\n");
569 return(STATUS_NO_MEMORY);
570 }
571 (*BaseAddress)=(*BaseAddress)+PAGESIZE;
572 }
573 else
574 {
575 (*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
576 MemoryArea = MmOpenMemoryAreaByRegion(AddressSpace, *BaseAddress, Length);
577 if (MemoryArea)
578 {
579 MmCloseMemoryArea(MemoryArea);
580 DPRINT("Memory area already occupied\n");
581 return(STATUS_CONFLICTING_ADDRESSES);
582 }
583 }
584
585 DPRINT("MmCreateMemoryArea(*BaseAddress %x)\n", *BaseAddress);
586
587 *Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
588 TAG_MAREA);
589 RtlZeroMemory(*Result,sizeof(MEMORY_AREA));
590 SET_MAGIC(*Result, TAG_MAREA)
591 (*Result)->Type = Type;
592 (*Result)->BaseAddress = *BaseAddress;
593 (*Result)->Length = Length;
594 (*Result)->Attributes = Attributes;
595 (*Result)->LockCount = 0;
596 (*Result)->ReferenceCount = 1;
597 (*Result)->Process = Process;
598
599 MmApplyMemoryAreaProtection(*Result);
600
601 MmInsertMemoryArea(AddressSpace, *Result);
602
603 DPRINT("MmCreateMemoryArea() succeeded\n");
604 return(STATUS_SUCCESS);
605 }
606
607 #ifdef DBG
608
609 VOID
610 MiReferenceMemoryArea(IN PMEMORY_AREA MemoryArea,
611 IN LPSTR FileName,
612 IN ULONG LineNumber)
613 {
614 VALIDATE_MEMORY_AREA(MemoryArea);
615
616 InterlockedIncrement(&MemoryArea->ReferenceCount);
617
618 #ifdef TRACK_MEMORY_AREA_REFERENCES
619 DbgPrint("(0x%.08x)(%s:%d) Referencing memory area 0x%.08x (New ref.count %d)\n",
620 KeGetCurrentThread(), FileName, LineNumber,
621 MemoryArea->BaseAddress,
622 MemoryArea->ReferenceCount);
623 #endif /* TRACK_MEMORY_AREA_REFERENCES */
624 }
625
626
627 VOID
628 MiDereferenceMemoryArea(IN PMEMORY_AREA MemoryArea,
629 IN LPSTR FileName,
630 IN ULONG LineNumber)
631 {
632 VALIDATE_MEMORY_AREA(MemoryArea);
633
634 InterlockedDecrement(&MemoryArea->ReferenceCount);
635
636 #ifdef TRACK_MEMORY_AREA_REFERENCES
637 DbgPrint("(0x%.08x)(%s:%d) Dereferencing memory area 0x%.08x (New ref.count %d)\n",
638 KeGetCurrentThread(), FileName, LineNumber,
639 MemoryArea->BaseAddress,
640 MemoryArea->ReferenceCount);
641 #endif /* TRACK_MEMORY_AREA_REFERENCES */
642
643 assertmsg(MemoryArea->ReferenceCount > 0,
644 ("No outstanding references on memory area (0x%.08x)\n", MemoryArea));
645 }
646
647 #else /* !DBG */
648
649 VOID
650 MiReferenceMemoryArea(IN PMEMORY_AREA MemoryArea)
651 {
652 InterlockedIncrement(&MemoryArea->ReferenceCount);
653 }
654
655
656 VOID
657 MiDereferenceMemoryArea(IN PMEMORY_AREA MemoryArea)
658 {
659 InterlockedDecrement(&MemoryArea->ReferenceCount);
660 }
661
662 #endif /* !DBG */