NtOpenSection (L "\\ Device \\ PhysicalMemory") returns STATUS_OBJECT_NAME_NOT_FOUND
I am using SMBIOS read function for windows systems. Since API levels vary, there are several ways to support:
- without any problems
GetSystemFirmwareTable('RSMB')
is available in Windows Server 2003 and later versions; - hardcore
NtOpenSection(L"\\Device\\PhysicalMemory")
for legacy systems up to and up to Windows XP; - critical WMI data en route
L"Win32_ComputerSystemProduct"
through cumbersome COM automation calls as a backup.
Methods 1 and 3 are already implemented, but I am stuck at \ Device \ PhysicalMemory as it NtOpenSection
always gives 0xC0000034 (STATUS_OBJECT_NAME_NOT_FOUND) - definitely not one of the possible result codes in the documentation ZwOpenSection
. Of course, I know that access to this section is denied starting with Windows Server 2003sp1 and possibly Windows XP-64, so I am trying to do this on a regular Windows XP-32 system and the result is no different from the result For example, Windows 7 -64. I also know that admin rights may be required even on legacy systems, but people who came across this issue have reported more appropriate error codes for such a scenario, such as 0xC0000022 (STATUS_ACCESS_DENIED) and 0xC0000005 (STATUS_ACCESS_VIOLATION).
My approach is based on Dell's Libsmbios library , which I believe works.
UNICODE_STRING wsMemoryDevice;
OBJECT_ATTRIBUTES oObjAttrs;
HANDLE hMemory;
NTSTATUS ordStatus;
RtlInitUnicodeString(&wsMemoryDevice, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&oObjAttrs, &wsMemoryDevice,
OBJ_CASE_INSENSITIVE, NULL, NULL);
ordStatus = NtOpenSection(&hMemory, SECTION_MAP_READ, &oObjAttrs);
if (!NT_SUCCESS(ordStatus)) goto Finish;
I thought it was possible to debug this, but the built-in API seems transparent to debuggers like OllyDbg: execution returns immediately when SYSENTER takes control. So I have no idea why Windows cannot find this object. I also tried changing the name of the section, as there are several options in the examples available on the internet, but it always gives 0xC0000033 (STATUS_OBJECT_NAME_INVALID).
source to share
Finally, I found the reason for this strange behavior, thanks to you people, confirming that my piece of code (it was an actual snippet, not a fake example) actually works. The problem was that I didn't have the Windows DDK initially installed (I now have it, but I still can't integrate it with Visual Studio so that the Windows SDK will automatically integrate), so it became necessary to write the definitions manually. Specifically, when I realized what InitializeObjectAttributes
is actually a preprocessor macro and not a Win32 function, I defined it RtlInitUnicodeString
as a macro, since its effect is even simpler. However, I was not careful enough to notice that UNICODE_STRING.Length
and .MaximumLength
is really designed for content size , and buffersize instead of length , i. that is, the number of bytes , not the number of characters . Consequently, my macro was setting the fields to half of the expected value, so Windows only saw the first half of the line L"\\Device\\PhysicalMemory"
, with the obvious result.
source to share