3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
19 /* $Id: main.c,v 1.155 2003/05/16 17:35:12 ekohl Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
29 /* INCLUDES *****************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/ntoskrnl.h>
33 #include <reactos/resource.h>
34 #include <internal/mm.h>
35 #include <internal/ifs.h>
36 #include <internal/module.h>
37 #include <internal/ldr.h>
38 #include <internal/ex.h>
39 #include <internal/ps.h>
40 #include <internal/ke.h>
41 #include <internal/io.h>
42 #include <internal/po.h>
43 #include <internal/cc.h>
44 #include <internal/se.h>
45 #include <internal/v86m.h>
46 #include <internal/kd.h>
47 #include <internal/trap.h>
48 #include "../dbg/kdb.h"
49 #include <internal/registry.h>
50 #include <internal/nls.h>
51 #include <reactos/bugcodes.h>
54 #include <internal/ntosdbg.h>
60 #include <internal/debug.h>
62 /* GLOBALS *******************************************************************/
64 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
65 ULONG EXPORTED NtGlobalFlag
= 0;
66 CHAR EXPORTED KeNumberProcessors
;
67 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
68 ULONG EXPORTED KeDcacheFlushCount
= 0;
69 ULONG EXPORTED KeIcacheFlushCount
= 0;
70 static LOADER_MODULE KeLoaderModules
[64];
71 static UCHAR KeLoaderModuleStrings
[64][256];
72 static UCHAR KeLoaderCommandLine
[256];
73 static ADDRESS_RANGE KeMemoryMap
[64];
74 static ULONG KeMemoryMapRangeCount
;
75 static ULONG FirstKrnlPhysAddr
;
76 static ULONG LastKrnlPhysAddr
;
77 static ULONG LastKernelAddress
;
78 volatile BOOLEAN Initialized
= FALSE
;
80 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
83 /* FUNCTIONS ****************************************************************/
86 RtlpCheckFileNameExtension(PCHAR FileName
,
91 Ext
= strrchr(FileName
, '.');
94 if ((Extension
== NULL
) || (*Extension
== 0))
100 if (*Extension
!= '.')
103 if (_stricmp(Ext
, Extension
) == 0)
111 InitSystemSharedUserPage (PCSZ ParameterLine
)
113 UNICODE_STRING ArcDeviceName
;
114 UNICODE_STRING ArcName
;
115 UNICODE_STRING BootPath
;
116 UNICODE_STRING DriveDeviceName
;
117 UNICODE_STRING DriveName
;
118 WCHAR DriveNameBuffer
[20];
120 PWCHAR ArcNameBuffer
;
124 OBJECT_ATTRIBUTES ObjectAttributes
;
127 BOOLEAN BootDriveFound
;
131 * The shared user page has been zeroed-out right after creation.
132 * There is NO need to do this again.
135 SharedUserData
->NtProductType
= NtProductWinNt
;
137 BootDriveFound
= FALSE
;
140 * Retrieve the current dos system path
141 * (e.g.: C:\reactos) from the given arc path
142 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
143 * Format: "<arc_name>\<path> [options...]"
146 /* create local parameter line copy */
147 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
148 strcpy (ParamBuffer
, (char *)ParameterLine
);
149 DPRINT("%s\n", ParamBuffer
);
151 /* cut options off */
152 p
= strchr (ParamBuffer
, ' ');
157 DPRINT("%s\n", ParamBuffer
);
160 p
= strchr (ParamBuffer
, '\\');
163 DPRINT("Boot path: %s\n", p
);
164 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
169 DPRINT("Boot path: %s\n", "\\");
170 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
172 DPRINT("Arc name: %s\n", ParamBuffer
);
174 /* Only arc name left - build full arc name */
175 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
176 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
177 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
178 DPRINT("Arc name: %wZ\n", &ArcName
);
180 /* free ParamBuffer */
181 ExFreePool (ParamBuffer
);
183 /* allocate arc device name string */
184 ArcDeviceName
.Length
= 0;
185 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
186 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
188 InitializeObjectAttributes (&ObjectAttributes
,
194 Status
= NtOpenSymbolicLinkObject (&Handle
,
195 SYMBOLIC_LINK_ALL_ACCESS
,
197 RtlFreeUnicodeString (&ArcName
);
198 if (!NT_SUCCESS(Status
))
200 RtlFreeUnicodeString (&BootPath
);
201 RtlFreeUnicodeString (&ArcDeviceName
);
202 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
208 Status
= NtQuerySymbolicLinkObject (Handle
,
212 if (!NT_SUCCESS(Status
))
214 RtlFreeUnicodeString (&BootPath
);
215 RtlFreeUnicodeString (&ArcDeviceName
);
216 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
221 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
224 /* allocate device name string */
225 DriveDeviceName
.Length
= 0;
226 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
227 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
229 for (i
= 0; i
< 26; i
++)
231 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
232 RtlInitUnicodeString (&DriveName
,
235 InitializeObjectAttributes (&ObjectAttributes
,
241 Status
= NtOpenSymbolicLinkObject (&Handle
,
242 SYMBOLIC_LINK_ALL_ACCESS
,
244 if (!NT_SUCCESS(Status
))
246 DPRINT("Failed to open link %wZ\n",
251 Status
= NtQuerySymbolicLinkObject (Handle
,
254 if (!NT_SUCCESS(Status
))
256 DPRINT("Failed query open link %wZ\n",
260 DPRINT("Opened link: %wZ ==> %wZ\n",
261 &DriveName
, &DriveDeviceName
);
263 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
265 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
266 swprintf(SharedUserData
->NtSystemRoot
,
267 L
"%C:%wZ", 'A' + i
, &BootPath
);
269 BootDriveFound
= TRUE
;
275 RtlFreeUnicodeString (&BootPath
);
276 RtlFreeUnicodeString (&DriveDeviceName
);
277 RtlFreeUnicodeString (&ArcDeviceName
);
279 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData
->DosDeviceMap
);
281 if (BootDriveFound
== FALSE
)
283 DbgPrint("No system drive found!\n");
290 ExpInitializeExecutive(VOID
)
292 LARGE_INTEGER Timeout
;
293 HANDLE ProcessHandle
;
295 ULONG BootDriverCount
;
305 * Fail at runtime if someone has changed various structures without
306 * updating the offsets used for the assembler code.
308 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
309 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
310 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
311 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
312 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
313 assert(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
314 assert(FIELD_OFFSET(ETHREAD
, ThreadsProcess
) == ETHREAD_THREADS_PROCESS
);
315 assert(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
316 KPROCESS_DIRECTORY_TABLE_BASE
);
317 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
318 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
319 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
321 assert(FIELD_OFFSET(KPCR
, ExceptionList
) == KPCR_EXCEPTION_LIST
);
322 assert(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
323 assert(FIELD_OFFSET(KPCR
, CurrentThread
) == KPCR_CURRENT_THREAD
);
327 KeLowerIrql(DISPATCH_LEVEL
);
331 MmInit1(FirstKrnlPhysAddr
,
334 (PADDRESS_RANGE
)&KeMemoryMap
,
335 KeMemoryMapRangeCount
);
337 /* Create default nls tables */
338 RtlpCreateDefaultNlsTables();
341 * Initialize the kernel debugger
343 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
348 KeLowerIrql(PASSIVE_LEVEL
);
351 KeBugCheck(SECURITY_INITIALIZATION_FAILED
);
356 KeBugCheck(SECURITY1_INITIALIZATION_FAILED
);
358 PiInitProcessManager();
362 if (KdPollBreakIn ())
364 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
368 * Display version number and copyright/warranty message
370 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
371 KERNEL_VERSION_BUILD_STR
")\n");
372 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
373 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
374 "Public License, and you\n");
375 HalDisplayString("are welcome to change it and/or distribute copies of it "
377 HalDisplayString("conditions. There is absolutely no warranty for "
380 /* Initialize all processors */
381 KeNumberProcessors
= 0;
383 while (!HalAllProcessorsStarted())
385 PVOID ProcessorStack
;
387 if (KeNumberProcessors
!= 0)
389 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
390 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
392 /* Allocate a stack for use when booting the processor */
393 /* FIXME: The nonpaged memory for the stack is not released after use */
395 ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
) + MM_STACK_SIZE
;
396 Ki386InitialStackArray
[((int)KeNumberProcessors
)] =
397 (PVOID
)(ProcessorStack
- MM_STACK_SIZE
);
398 HalInitializeProcessor(KeNumberProcessors
, ProcessorStack
);
399 KeNumberProcessors
++;
402 if (KeNumberProcessors
> 1)
405 "Found %d system processors. [%lu MB Memory]\n",
407 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
412 "Found 1 system processor. [%lu MB Memory]\n",
413 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
415 HalDisplayString(str
);
418 * Initialize various critical subsystems
420 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
425 LdrInitModuleManagement();
426 CmInitializeRegistry();
431 FsRtlpInitFileLockingImplementation();
433 /* Report all resources used by hal */
434 HalReportResourceUsage();
437 * Initalize services loaded at boot time
439 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
440 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
442 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
443 KeLoaderModules
[i
].String
,
444 KeLoaderModules
[i
].ModStart
,
445 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
449 /* Pass 2: import system hive registry chunk */
451 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
453 start
= KeLoaderModules
[i
].ModStart
;
454 length
= KeLoaderModules
[i
].ModEnd
- start
;
456 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
457 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
460 name
= (PCHAR
)KeLoaderModules
[i
].String
;
467 if (!_stricmp (name
, "system") ||
468 !_stricmp (name
, "system.hiv"))
470 CPRINT("Process system hive registry chunk at %08lx\n", start
);
472 CmImportSystemHive((PCHAR
)start
, length
);
476 /* Pass 3: import hardware hive registry chunk */
477 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
479 start
= KeLoaderModules
[i
].ModStart
;
480 length
= KeLoaderModules
[i
].ModEnd
- start
;
481 name
= (PCHAR
)KeLoaderModules
[i
].String
;
482 if (!_stricmp (name
, "hardware") ||
483 !_stricmp (name
, "hardware.hiv"))
485 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
486 CmImportHardwareHive((PCHAR
)start
, length
);
490 /* Create dummy keys if no hardware hive was found */
491 CmImportHardwareHive (NULL
, 0);
494 /* Initialize volatile registry settings */
495 if (SetupBoot
== FALSE
)
497 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
501 * Enter the kernel debugger before starting up the boot drivers
507 IoCreateDriverList();
511 /* Pass 4: process boot loaded drivers */
513 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
515 start
= KeLoaderModules
[i
].ModStart
;
516 length
= KeLoaderModules
[i
].ModEnd
- start
;
517 name
= (PCHAR
)KeLoaderModules
[i
].String
;
518 if (RtlpCheckFileNameExtension(name
, ".sys") ||
519 RtlpCheckFileNameExtension(name
, ".sym"))
521 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
522 name
, start
, length
);
523 LdrInitializeBootStartDriver((PVOID
)start
, name
, length
);
525 if (RtlpCheckFileNameExtension(name
, ".sys"))
529 if (BootDriverCount
== 0)
531 DbgPrint("No boot drivers available.\n");
535 /* Create ARC names for boot devices */
538 /* Create the SystemRoot symbolic link */
539 CPRINT("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
540 Status
= IoCreateSystemRootLink((PUCHAR
)KeLoaderBlock
.CommandLine
);
541 if (!NT_SUCCESS(Status
))
542 KeBugCheck(INACCESSIBLE_BOOT_DEVICE
);
544 #ifdef DBGPRINT_FILE_LOG
545 /* On the assumption that we can now access disks start up the debug
548 #endif /* DBGPRINT_FILE_LOG */
555 PiInitDefaultLocale();
558 * Start the motherboard enumerator (the HAL)
560 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
563 * Load boot start drivers
565 IopLoadBootStartDrivers();
568 * Load Auto configured drivers
570 LdrLoadAutoConfigDrivers();
573 IoDestroyDriverList();
576 * Assign drive letters
578 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
584 * Initialize shared user page:
585 * - set dos system path, dos device map, etc.
587 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
590 * Launch initial process
592 Status
= LdrLoadInitialProcess(&ProcessHandle
,
594 if (!NT_SUCCESS(Status
))
596 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
600 * Crash the system if the initial process terminates within 5 seconds.
602 Timeout
.QuadPart
= -50000000LL;
603 Status
= NtWaitForSingleObject(ProcessHandle
,
606 if (Status
!= STATUS_TIMEOUT
)
608 KeBugCheckEx(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
611 NtClose(ThreadHandle
);
612 NtClose(ProcessHandle
);
614 PsTerminateSystemThread(STATUS_SUCCESS
);
619 KiSystemStartup(BOOLEAN BootProcessor
)
621 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
626 ExpInitializeExecutive();
629 /* Do application processor initialization */
630 KeApplicationProcessorInit();
631 PsApplicationProcessorInit();
632 KeLowerIrql(PASSIVE_LEVEL
);
633 PsIdleThreadMain(NULL
);
639 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
641 * FUNCTION: Called by the boot loader to start the kernel
643 * LoaderBlock = Pointer to boot parameters initialized by the boot
645 * NOTE: The boot parameters are stored in low memory which will become
646 * invalid after the memory managment is initialized so we make a local copy.
651 ULONG last_kernel_address
;
652 extern ULONG _bss_end__
;
657 /* Low level architecture specific initialization */
661 * Copy the parameters to a local buffer because lowmem will go away
663 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
664 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
665 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
666 KeLoaderBlock
.ModsCount
++;
667 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
670 * Convert a path specification in the grub format to one understood by the
671 * rest of the kernel.
673 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
675 ULONG DiskNumber
= 0, PartNumber
= 0;
681 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
682 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
684 DiskNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
685 PartNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
687 strcpy(Temp
, &((PUCHAR
)_LoaderBlock
->CommandLine
)[7]);
688 if ((options
= strchr(Temp
, ' ')) != NULL
)
697 if ((s1
= strrchr(Temp
, '/')) != NULL
)
700 if ((s1
= strrchr(Temp
, '/')) != NULL
)
705 sprintf(KeLoaderCommandLine
,
706 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
707 DiskNumber
, PartNumber
+ 1, Temp
, options
);
709 p
= KeLoaderCommandLine
;
710 while (*p
!= 0 && *p
!= ' ')
718 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
722 strcpy(KeLoaderCommandLine
, (PUCHAR
)_LoaderBlock
->CommandLine
);
724 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
726 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
727 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
728 KeLoaderModules
[0].ModStart
= 0xC0000000;
729 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
730 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
733 if ((s
= strrchr((PUCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
735 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
739 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
741 KeLoaderModules
[i
].ModStart
-= 0x200000;
742 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
743 KeLoaderModules
[i
].ModEnd
-= 0x200000;
744 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
745 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
749 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
752 HalBase
= KeLoaderModules
[1].ModStart
;
754 PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
759 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)0xC0000000, &DriverSize
);
761 LdrHalBase
= (ULONG_PTR
)DriverBase
;
762 last_kernel_address
= DriverBase
+ DriverSize
;
765 * Process ntoskrnl.exe
767 LdrSafePEProcessModule((PVOID
)0xC0000000, (PVOID
)0xC0000000, (PVOID
)DriverBase
, &DriverSize
);
769 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000;
770 LastKrnlPhysAddr
= last_kernel_address
- 0xc0000000 + 0x200000;
771 LastKernelAddress
= last_kernel_address
;
774 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
775 KeLoaderBlock
.Flags
&= ~MB_FLAGS_MMAP_INFO
;
778 KeMemoryMapRangeCount
= 0;
779 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
781 /* We have a memory map from the nice BIOS */
782 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
784 while (i
< KeLoaderBlock
.MmapLength
)
786 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
787 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
788 sizeof(ADDRESS_RANGE
));
789 KeMemoryMapRangeCount
++;