Получение и разбор информации DMI
От: McQwerty Россия  
Дата: 23.03.04 18:30
Оценка:
Всем привет.
Нужно было получить температуру камня. Рекомендовалось WMI или DMI,
С WMI ничего не вышло — нет ничего по Win32_Fan. Попробовал через DMI — ничего
тоже не вышло, хотя много чего интересного получил. Если кому нужно — можно взять
и довести до ума.

Это кусок кода для чтения памяти по указанному физическому адресу.
Исходный код не мой — я использовал нарытый и немножко его модифицировал.
/*****************************************************************************/

#define InitializeObjectAttributes(p,n,a,r,s) { \
    (p)->Length = sizeof( OBJECT_ATTRIBUTES );  \
    (p)->RootDirectory = r;                     \
    (p)->Attributes = a;                        \
    (p)->ObjectName = n;                        \
    (p)->SecurityDescriptor = s;                \
    (p)->SecurityQualityOfService = NULL;       \
    }

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; // windbgkd
typedef DWORD NTSTATUS;

typedef NTSTATUS (__stdcall *__NtUnmapViewOfSection)(
  IN HANDLE  ProcessHandle,
  IN PVOID  BaseAddress
);

typedef NTSTATUS (__stdcall *__NtOpenSection)(
  OUT PHANDLE  SectionHandle,
  IN ACCESS_MASK  DesiredAccess,
  IN POBJECT_ATTRIBUTES  ObjectAttributes
);

typedef NTSTATUS (__stdcall *__NtMapViewOfSection)(
  IN HANDLE  SectionHandle,
  IN HANDLE  ProcessHandle,
  IN OUT PVOID  *BaseAddress,
  IN ULONG  ZeroBits,
  IN ULONG  CommitSize,
  IN OUT PLARGE_INTEGER  SectionOffset, /* optional */
  IN OUT PULONG  ViewSize,
  IN DWORD  InheritDisposition,
  IN ULONG  AllocationType,
  IN ULONG  Protect
);

typedef VOID (__stdcall *__RtlInitUnicodeString)(
  IN OUT PUNICODE_STRING  DestinationString,
  IN PCWSTR  SourceString
);

typedef ULONG (__stdcall *__RtlNtStatusToDosError) (
  IN NTSTATUS Status
);

void ReadBIOSRegion (DWORD dwAddress, DWORD dwSize, LPVOID pDestAddress)
{
    HANDLE hSectionHandle = (HANDLE) -1;;
    PDWORD pAddress = (PDWORD) (LPVOID) dwAddress;
    DWORD  dwLength = ((dwSize + 0x0FFF) / 0x1000) * 0x1000;
    LPBYTE pVirtualAddress = NULL;
    PHYSICAL_ADDRESS ViewBase = { 0 };

    UNICODE_STRING szPhysmemString;
    OBJECT_ATTRIBUTES oaAttributes;

    HINSTANCE hDLL = GetModuleHandle ("ntdll.dll");
    __NtOpenSection NtOpenSection = (__NtOpenSection) GetProcAddress (hDLL, "NtOpenSection");
    __NtMapViewOfSection NtMapViewOfSection = (__NtMapViewOfSection) GetProcAddress (hDLL, "NtMapViewOfSection");
    __NtUnmapViewOfSection NtUnmapViewOfSection = (__NtUnmapViewOfSection) GetProcAddress (hDLL, "NtUnmapViewOfSection");
    __RtlInitUnicodeString RtlInitUnicodeString = (__RtlInitUnicodeString) GetProcAddress (hDLL, "RtlInitUnicodeString");
    __RtlNtStatusToDosError RtlNtStatusToDosError = (__RtlNtStatusToDosError) GetProcAddress (hDLL, "RtlNtStatusToDosError");

    RtlInitUnicodeString( &szPhysmemString, L"\\device\\physicalmemory" ); 
    InitializeObjectAttributes( &oaAttributes, &szPhysmemString,0x00000040L, NULL, NULL ); 

    NtOpenSection( &hSectionHandle, SECTION_MAP_READ, &oaAttributes );

    ViewBase.QuadPart = (ULONGLONG) (pAddress);

    ViewBase.QuadPart = (ULONGLONG) (((DWORD) pAddress) & 0xFFFFF000);
    INT ntStatus = NtMapViewOfSection 
    (
        hSectionHandle,
        (HANDLE) -1,
        (PVOID*) &pVirtualAddress,
        0L,
        dwLength,
        &ViewBase,
        &dwLength,
        1,
        0,
        PAGE_READONLY
    );
    DWORD xxx = RtlNtStatusToDosError (ntStatus);

    CopyMemory (pDestAddress, (pVirtualAddress + (dwAddress % 0x1000)), dwSize);

    NtUnmapViewOfSection((HANDLE)-1,pVirtualAddress);
    CloseHandle(hSectionHandle);
} // ReadBIOSRegion

А теперь собственно попытка получения и разбора DMI
#include <pshpack1.h>
struct TSMBIOSStructureTableEntryPoint
{
    CHAR sAnchor [4]; // _SM_
    BYTE bEPSCheckSum;
    BYTE bEPSLength;
    BYTE bMajor;
    BYTE bMinor;
    WORD wMaxStructSize;
    BYTE bRevision;
    BYTE FormatterArea [5];
    CHAR sImAnchor [5]; // _DMI_
    BYTE bImCheckSum;
    WORD wTableLength;
    DWORD dwTableAddress;
    WORD nNumber;
    BYTE bBCDRevision;
}; // TSMBIOSStructureTableEntryPoint

struct TSMBIOSStructureEntryHeader
{
    BYTE nType;
    BYTE nLength;
    WORD hHandle;
}; // TSMBIOSStructureEntryHeader
#include <poppack.h>

int main ()
{
    BYTE BIOS [0x10000] = { 0 };
    ReadBIOSRegion (0xF0000, 0x10000, BIOS);

    LPBYTE pSearchSignature = BIOS;

    while (memcmp (pSearchSignature, "\x5F\x53\x4D\x5F", 4) != 0)
    {
        pSearchSignature += 16;
        if (pSearchSignature > (BIOS + sizeof (BIOS)))
        {
            printf ("Signature not found!\n");
            return 1;
        }
    }

    TSMBIOSStructureTableEntryPoint Table = { 0 };
    CopyMemory (&Table, pSearchSignature, sizeof (Table));

    if (Table. wTableLength > sizeof (BIOS))
    {
        printf ("DMI info is too large!\n");
        return 2;
    }

    ReadBIOSRegion (Table. dwTableAddress, Table. wTableLength, BIOS);

    TSMBIOSStructureEntryHeader* pEntry = (TSMBIOSStructureEntryHeader*) BIOS;

    for (int i = 0; i < Table. nNumber; i ++)
    {
        LPSTR p = ((LPSTR) pEntry) + pEntry -> nLength;

        // В зависимости от nType можно делать любой разбор
        // Я просто искал датчик температуры (nType == 34)...
        // Не нашёл...  :(
        printf ("%2d: %d [%d]\n", i, pEntry -> nType, pEntry -> nLength);

        if (*p)
        {
            while (*p)
            {
                printf (" '%s'\n", p);
                p += strlen (p) + 1;
            }

            p ++;
        }
        else
            p += 2;

        pEntry = (TSMBIOSStructureEntryHeader*) p;
    }

    return 0;
} // main
Re: Получение и разбор информации DMI
От: McQwerty Россия  
Дата: 22.07.06 12:27
Оценка:
Нашлась ошибочка в коде:

Вместо строки:
    DWORD  dwLength = ((dwSize + 0x0FFF) / 0x1000) * 0x1000;

нужно написать:
    DWORD  dwLength = ((dwSize + 0x0FFF + (dwAddress % 0x1000)) / 0x1000) * 0x1000;

Остальное, вроде, работает....
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.