Get Physical RAM size in kernel mode

Hello Guys,

Another newbie question here and I would like to ask if there are ways to get the physical ram size value in kernel mode windows. I am writing a driver in kernel mode that will get the value of the installed physical ram on a machine.

What I have found was this registry HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\System Resources\Physical Memory/.Translated but this type is of REG_RESOURCE_LIST. Is there any ways to read this registry just to get the physical ram size installed on my machine? And also, If it can be done through an API, I would like to know what API to use in kernel mode to get this value.

Thanks.

ZwQuerySystemInformation(), infoclass SystemBasicInformation, is your friend here among other things, it returns the number of physical pages in the system, as well as page size. By mlutiplying the former by the latter you can get an answer to your question…

Anton Bassov

I don’t think that this is documented, Anton. I have no issue with this in this case, as for whatever reason there is no documented
way to do this, but without the layout of SYSTEM_BASIC_INFORMATION, he can’t do much with this. If it is documented (other than the
single field of ‘NumberOfProcessors’), my apologizes.

Cheers,

mm

xxxxx@hotmail.com wrote:

ZwQuerySystemInformation(), infoclass SystemBasicInformation, is your friend here among other things, it returns the number of physical pages in the system, as well as page size. By mlutiplying the former by the latter you can get an answer to your question…

Anton Bassov

Martin O’Brien wrote:

I don’t think that this is documented, Anton. I have no issue with
this in this case, as for whatever reason there is no documented way
to do this, but without the layout of SYSTEM_BASIC_INFORMATION, he
can’t do much with this. If it is documented (other than the single
field of ‘NumberOfProcessors’), my apologizes.

On the other hand, having this piece of information is not going to do
him any good, so I’m not sure it matters.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I’m not exactly sure what you mean here, Tim: That knowing the amount of physical memory isn’t necessarily all that useful or that
SYSTEM_BASIC_INFORMATION doesn’t contain this information?

Thanks,

mm

Tim Roberts wrote:

Martin O’Brien wrote:
> I don’t think that this is documented, Anton. I have no issue with
> this in this case, as for whatever reason there is no documented way
> to do this, but without the layout of SYSTEM_BASIC_INFORMATION, he
> can’t do much with this. If it is documented (other than the single
> field of ‘NumberOfProcessors’), my apologizes.

On the other hand, having this piece of information is not going to do
him any good, so I’m not sure it matters.

Martin O’Brien wrote:

I’m not exactly sure what you mean here, Tim: That knowing the amount
of physical memory isn’t necessarily all that useful or that
SYSTEM_BASIC_INFORMATION doesn’t contain this information?

The former: knowing the amount of physical memory isn’t that useful. He
didn’t tell us what he wanted it for, but it’s a pretty good bet he’s
doing it the wrong way.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I would agree that there isn’t much good that can be done with this information. I just think that keeping it undocumented doesn’t
serve much purpose, because a lot of people try to do this, and I don’t see the potential for damage by using it as any greater than
the potential for damage by coming up with your own ways of figuring out the information, like parsing the SMBIOS tables.

Cheers,

mm

Tim Roberts wrote:

Martin O’Brien wrote:
> I’m not exactly sure what you mean here, Tim: That knowing the amount
> of physical memory isn’t necessarily all that useful or that
> SYSTEM_BASIC_INFORMATION doesn’t contain this information?

The former: knowing the amount of physical memory isn’t that useful. He
didn’t tell us what he wanted it for, but it’s a pretty good bet he’s
doing it the wrong way.

> I don’t see the potential for damage by using it as any greater than the potential
>or damage by coming up with your own ways of figuring out the information,

like parsing the SMBIOS tables.

First, there is no damage in parsing SMBIOS tables, because it does not require anything undocumented - from the OS’s perspective, all you do is mapping physical memory to the virtual address and reading it.

Second, SMBIOS tables do not provide memory info -this info may be obtained from BIOS either legacy way via INT 15 ( which cannot be done after the OS got booted, because it requires a caller to be in a real mode) , or via ACPI tables…

Anton Bassov

  1. Parsing binary data in the kernel is not at the top of the list of recommended activities, not that it’s particularly difficult
    in this case, and sometimes you do indeed have to do so.

  2. Yes it does.

System Management BIOS (SMBIOS) Reference Specification
DSP0134
Version 2.6a
Status: Preliminary Standard
May 2, 2007
Copyright

'3.3.17 Physical Memory Array (Type 16)

This structure describes a collection of memory devices that operate together to form a memory address space.’

There’s a table that describes the fields, but it doesn’t copy from the PDF in a legible way. If you want to learn about it, here
it is:

http://www.dmtf.org/standards/published_documents/DSP0134.pdf

  1. How do you get this information from ACPI, because I could use that as well.

Cheers,

mm

xxxxx@hotmail.com wrote:

> I don’t see the potential for damage by using it as any greater than the potential
>or damage by coming up with your own ways of figuring out the information,
> like parsing the SMBIOS tables.

First, there is no damage in parsing SMBIOS tables, because it does not require anything undocumented - from the OS’s perspective, all you do is mapping physical memory to the virtual address and reading it.

Second, SMBIOS tables do not provide memory info -this info may be obtained from BIOS either legacy way via INT 15 ( which cannot be done after the OS got booted, because it requires a caller to be in a real mode) , or via ACPI tables…

Anton Bassov

Martin,

'3.3.17 Physical Memory Array (Type 16) This structure describes a collection of
memory devices that operate together to form a memory address space.

I am very familiar with the doc that you have quoted, believe me. However, for the practical purposes, it is pretty useless here - it does not provide you any info about physical memory ranges, and, as far as the OS is concerned, this is the only thing that matters ( because if some range is marked as reserved by BIOS, it just does not exist, as far as OS is concerned)…

  1. How do you get this information from ACPI, because I could use that as well.

To be right honest with you, somehow I failed to decypher it from ACPI specification, and went for a “legacy” INT 15 solution when I needed this info, because I just could not afford to spend infinity on research (I hope you understand I was not doing it from a Windows driver). The only thing I know is that it can get done( apparently, by invoking ACPI methods)…

Anton Bassov

Hello Guys,

What I need for this info is just for my checking routine in my driver. I just want to know the physical ram size installed on my machine. By the way, I followed what Anton suggested and yes it is undocumented and I don’t know why it undocumented. But anyway, inorder for the ZwQuerySystemInformation to work, I just prototyped the API in my header files and also defined those structures needed like this:

typedef enum _SYSTEM_INFORMATION_CLASS {
SystemInformationClassMin = 0,
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemNotImplemented1 = 4,
SystemProcessInformation = 5,
SystemProcessesAndThreadsInformation = 5,
SystemCallCountInfoInformation = 6,
SystemCallCounts = 6,
SystemDeviceInformation = 7,
SystemConfigurationInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemProcessorTimes = 8,
SystemFlagsInformation = 9,
SystemGlobalFlag = 9,
SystemCallTimeInformation = 10,
SystemNotImplemented2 = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemLockInformation = 12,
SystemStackTraceInformation = 13,
SystemNotImplemented3 = 13,
SystemPagedPoolInformation = 14,
SystemNotImplemented4 = 14,
SystemNonPagedPoolInformation = 15,
SystemNotImplemented5 = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemPagefileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemInstructionEmulationCounts = 19,
SystemVdmBopInformation = 20,
SystemInvalidInfoClass1 = 20,
SystemFileCacheInformation = 21,
SystemCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemProcessorStatistics = 23,
SystemDpcBehaviourInformation = 24,
SystemDpcInformation = 24,
SystemFullMemoryInformation = 25,
SystemNotImplemented6 = 25,
SystemLoadImage = 26,
SystemUnloadImage = 27,
SystemTimeAdjustmentInformation = 28,
SystemTimeAdjustment = 28,
SystemSummaryMemoryInformation = 29,
SystemNotImplemented7 = 29,
SystemNextEventIdInformation = 30,
SystemNotImplemented8 = 30,
SystemEventIdsInformation = 31,
SystemNotImplemented9 = 31,
SystemCrashDumpInformation = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemLoadAndCallImage = 38,
SystemPrioritySeparation = 39,
SystemPlugPlayBusInformation = 40,
SystemNotImplemented10 = 40,
SystemDockInformation = 41,
SystemNotImplemented11 = 41,
/* SystemPowerInformation = 42, Conflicts with POWER_INFORMATION_LEVEL 1 */
SystemInvalidInfoClass2 = 42,
SystemProcessorSpeedInformation = 43,
SystemInvalidInfoClass3 = 43,
SystemCurrentTimeZoneInformation = 44,
SystemTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemSetTimeSlipEvent = 46,
SystemCreateSession = 47,
SystemDeleteSession = 48,
SystemInvalidInfoClass4 = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemAddVerifier = 52,
SystemSessionProcessesInformation = 53,
SystemInformationClassMax
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_BASIC_INFORMATION {
ULONG Unknown;
ULONG MaximumIncrement;
ULONG PhysicalPageSize;
ULONG NumberOfPhysicalPages;
ULONG LowestPhysicalPage;
ULONG HighestPhysicalPage;
ULONG AllocationGranularity;
ULONG LowestUserAddress;
ULONG HighestUserAddress;
ULONG ActiveProcessors;
UCHAR NumberProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;

NTSTATUS
ZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

I tested my driver program on my test machine with 1GB installed RAM and it works. I still need to verify to other machines with different ramsize installed though.

The fundamental issue here is whether or not your driver will be used by anyone other than yourself. If it won’t be, then no
problems. If it will, then you’ve got a lot of work to do, and your testing needs to focus on other versions of the OS and other
architectures. For example, I don’t ever recall personally using SYTEM_BASIC_INFORMATION, so I don’t know the details, but your
definition of SYSTEM_BASIC_INFORMATION will most definitely not work on a x64 platform. If you got these definitions from ReactOS,
be aware that it hasn’t been update in a while (to the best of my knowledge), and it definitely does not support x64. Your best
chance of reliably defining a structure like this is to extract it from the ntoskrnl.pdb file for each permutation of operating
system, version and architecture that you will support. Most people do this with WinDbg, but the DIA2DUMP program can also be used.
Unfortunately, I do not know of the top of my head whether this a public symbol in the average NTOSKRNL.PDB.

Good luck,

mm

xxxxx@gmail.com wrote:

Hello Guys,

What I need for this info is just for my checking routine in my driver. I just want to know the physical ram size installed on my machine. By the way, I followed what Anton suggested and yes it is undocumented and I don’t know why it undocumented. But anyway, inorder for the ZwQuerySystemInformation to work, I just prototyped the API in my header files and also defined those structures needed like this:

typedef enum _SYSTEM_INFORMATION_CLASS {
SystemInformationClassMin = 0,
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemPathInformation = 4,
SystemNotImplemented1 = 4,
SystemProcessInformation = 5,
SystemProcessesAndThreadsInformation = 5,
SystemCallCountInfoInformation = 6,
SystemCallCounts = 6,
SystemDeviceInformation = 7,
SystemConfigurationInformation = 7,
SystemProcessorPerformanceInformation = 8,
SystemProcessorTimes = 8,
SystemFlagsInformation = 9,
SystemGlobalFlag = 9,
SystemCallTimeInformation = 10,
SystemNotImplemented2 = 10,
SystemModuleInformation = 11,
SystemLocksInformation = 12,
SystemLockInformation = 12,
SystemStackTraceInformation = 13,
SystemNotImplemented3 = 13,
SystemPagedPoolInformation = 14,
SystemNotImplemented4 = 14,
SystemNonPagedPoolInformation = 15,
SystemNotImplemented5 = 15,
SystemHandleInformation = 16,
SystemObjectInformation = 17,
SystemPageFileInformation = 18,
SystemPagefileInformation = 18,
SystemVdmInstemulInformation = 19,
SystemInstructionEmulationCounts = 19,
SystemVdmBopInformation = 20,
SystemInvalidInfoClass1 = 20,
SystemFileCacheInformation = 21,
SystemCacheInformation = 21,
SystemPoolTagInformation = 22,
SystemInterruptInformation = 23,
SystemProcessorStatistics = 23,
SystemDpcBehaviourInformation = 24,
SystemDpcInformation = 24,
SystemFullMemoryInformation = 25,
SystemNotImplemented6 = 25,
SystemLoadImage = 26,
SystemUnloadImage = 27,
SystemTimeAdjustmentInformation = 28,
SystemTimeAdjustment = 28,
SystemSummaryMemoryInformation = 29,
SystemNotImplemented7 = 29,
SystemNextEventIdInformation = 30,
SystemNotImplemented8 = 30,
SystemEventIdsInformation = 31,
SystemNotImplemented9 = 31,
SystemCrashDumpInformation = 32,
SystemExceptionInformation = 33,
SystemCrashDumpStateInformation = 34,
SystemKernelDebuggerInformation = 35,
SystemContextSwitchInformation = 36,
SystemRegistryQuotaInformation = 37,
SystemLoadAndCallImage = 38,
SystemPrioritySeparation = 39,
SystemPlugPlayBusInformation = 40,
SystemNotImplemented10 = 40,
SystemDockInformation = 41,
SystemNotImplemented11 = 41,
/* SystemPowerInformation = 42, Conflicts with POWER_INFORMATION_LEVEL 1 */
SystemInvalidInfoClass2 = 42,
SystemProcessorSpeedInformation = 43,
SystemInvalidInfoClass3 = 43,
SystemCurrentTimeZoneInformation = 44,
SystemTimeZoneInformation = 44,
SystemLookasideInformation = 45,
SystemSetTimeSlipEvent = 46,
SystemCreateSession = 47,
SystemDeleteSession = 48,
SystemInvalidInfoClass4 = 49,
SystemRangeStartInformation = 50,
SystemVerifierInformation = 51,
SystemAddVerifier = 52,
SystemSessionProcessesInformation = 53,
SystemInformationClassMax
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_BASIC_INFORMATION {
ULONG Unknown;
ULONG MaximumIncrement;
ULONG PhysicalPageSize;
ULONG NumberOfPhysicalPages;
ULONG LowestPhysicalPage;
ULONG HighestPhysicalPage;
ULONG AllocationGranularity;
ULONG LowestUserAddress;
ULONG HighestUserAddress;
ULONG ActiveProcessors;
UCHAR NumberProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;

NTSTATUS
ZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

I tested my driver program on my test machine with 1GB installed RAM and it works. I still need to verify to other machines with different ramsize installed though.

> your definition of SYSTEM_BASIC_INFORMATION will most definitely not work on a x64 platform.

This is for sure - ‘ULONG HighestUserAddress’ does not really make sense on 64-bit OS, does it???

Anton Bassov

Actually I just found the info here.
http://www.cs.colorado.edu/~main/cs1300/include/ddk/ntapi.h

I’ve used SMBIOS a couple of times for this purpose, and it worked for me, but I only tried it on two systems. That being said, WMI
uses the SMBIOS tables, and XP SP2 and onwards (I assume Vista, et. c.) has a driver (mssmbios) to support it as well:

http://www.microsoft.com/whdc/system/platform/firmware/SMBIOS.mspx
http://download.microsoft.com/download/5/D/6/5D6EAF2B-7DDF-476B-93DC-7CF0072878E6/SMBIOS.doc

In particular (from SMBIOS.DOC):

ԉۢ Adding system firmware information to the crash dump aids in failure diagnosis. A given root cause may be linked to a specific
system vendor or to specific hardware attributes, such as the type and size of memory modules. This information is available in SMBIOS.’

So it sounds like it does have memory information on all SMBIOS compliant machines, but I can only speak for two such machines.

In any case, I just remembered this paper, and reread it, and there are some other options as well. The first is that the SMBIOS
table data are contained in this value:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Mssmbios\Data

Under the same key, there are also one’s for ‘BIOS’ and ‘ACPI.’

There are also two documented user mode API’s for accessing SMBIOS/ACPI information, GetSystemFirmwareTable() and
EnumSystemFirmwareTables(), but I’ve never used either, and if you are feeling like you don’t deserve to enjoy your job, you can
access all of this information using WMI.

Cheers,

mm

xxxxx@hotmail.com wrote:

Martin,

> '3.3.17 Physical Memory Array (Type 16) This structure describes a collection of
> memory devices that operate together to form a memory address space.

I am very familiar with the doc that you have quoted, believe me. However, for the practical purposes, it is pretty useless here - it does not provide you any info about physical memory ranges, and, as far as the OS is concerned, this is the only thing that matters ( because if some range is marked as reserved by BIOS, it just does not exist, as far as OS is concerned)…

> 3. How do you get this information from ACPI, because I could use that as well.

To be right honest with you, somehow I failed to decypher it from ACPI specification, and went for a “legacy” INT 15 solution when I needed this info, because I just could not afford to spend infinity on research (I hope you understand I was not doing it from a Windows driver). The only thing I know is that it can get done( apparently, by invoking ACPI methods)…

Anton Bassov

Ah! I see somebody typed in Gary Nebbett’s definitions. Helpful, as long as you bear in mind that they are Windows NT V4 vintage.

MS has indicated that for the most part they view the Query/Set System Info functions as internal, unsupported, and subject to change. I have seen these functions and structure definitions change between OS versions.

Having said that, it’s also my experience that the MS devs are *really* hesitate to change even things like this for fear of breaking compatibility.

So… like with anything undocumented… make your choice and take your chances,

Peter
OSR

Hello MM,

Do you have any resources on how to get this info from SMBIOS through kernel mode?
I am still trying to figure out how to do this and currently reading the document. And also Peter also has a point, I might encounter problems when using undocumented API. Actually the target platform is for XP SP2, Vista OS (32 and 64 bit architecture). If this method does not compromise portability to other higher versions of OS, I hope someone can provide me a code snippet for this.

Thanks.

Unfortunately, no, I couldn’t. I don’t imagine that you’re going to find anything out there that anyone can legally share with you;
it’s just to unusual, though there is really nothing all that special about it.

Sorry,

mm

xxxxx@gmail.com wrote:

Hello MM,

Do you have any resources on how to get this info from SMBIOS through kernel mode?
I am still trying to figure out how to do this and currently reading the document. And also Peter also has a point, I might encounter problems when using undocumented API. Actually the target platform is for XP SP2, Vista OS (32 and 64 bit architecture). If this method does not compromise portability to other higher versions of OS, I hope someone can provide me a code snippet for this.

Thanks.

If GetSysInformation does not work for you.

Alternatively you can use MmGetPhysicalRanges()

Again its undocumented but it works…

Regards,
Dhiren

Martin O’Brien wrote:
Unfortunately, no, I couldn’t. I don’t imagine that you’re going to find anything out there that anyone can legally share with you;
it’s just to unusual, though there is really nothing all that special about it.

Sorry,

mm

xxxxx@gmail.com wrote:
> Hello MM,
>
> Do you have any resources on how to get this info from SMBIOS through kernel mode?
> I am still trying to figure out how to do this and currently reading the document. And also Peter also has a point, I might encounter problems when using undocumented API. Actually the target platform is for XP SP2, Vista OS (32 and 64 bit architecture). If this method does not compromise portability to other higher versions of OS, I hope someone can provide me a code snippet for this.
>
> Thanks.
>


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

---------------------------------
Bring your gang together. Do your thing. Find your favourite Yahoo! Group.