簡體   English   中英

如何從注冊表中讀取REG_BINARY值相關值?

[英]How can i read a REG_BINARY values associated value from registry?

在注冊表中有一個(或多個)密鑰,具體取決於您有多少台顯示器HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\DEL404C\\{Some Unique ID}\\Device Parameters\\EDID這是一個REG_BINARY key 在我的情況下,這是:

00 FF FF FF FF FF FF 00 10 AC 4C 40 53 43 34 42 34 14 01 03 0A 2F 1E 78 EE EE 95 A3 54
4C 99 26 0F 50 54 A5 4B 00 71 4F 81 80 B3 00 01 01 01 01 01 01 01 01 01 01 21 39 90 30 
62 1A 27 40 68 B0 36 00 DA 28 11 00 00 1C 00 00 00 FF 00 34 57 31 4D 44 30 43 53 42 34 
43 53 0A 00 00 00 FC 00 44 45 4C 4C 20 50 32 32 31 30 0A 20 20 00 00 00 FD 00 38 4B 1E 
53 10 00 0A 20 20 20 20 20 20 00 FA

此reg_binary值包含有關已連接監視器的信息(如序列號和類型)。 我只需要這兩個值。 我的問題是如何使用C或C ++讀取這些值?

我有一個VB腳本,可以這樣做:
'你可以判斷該位置是否包含一個序列號如果它以&H00 00 00 ff開頭&H00 00 00 ff strSerFind=Chr(&H00) & Chr(&H00) & Chr(&H00) & Chr(&HfF)

'或型號說明如果以&H00 00 00 fc開頭

strMdlFind=Chr(&H00) & Chr(&H00) & Chr(&H00) & Chr(&Hfc)

此鏈接還包含有關EDID的信息: http//en.wikipedia.org/wiki/Extended_display_identification_data

有人可以幫助我,我怎么能用C做到這一點? 我只能找到VB腳本示例,但不幸的是我不理解它們,對我來說這也很重要。

你提到想要“序列號”和“類型”。 沒有“類型”,但有制造商ID和產品ID。 在大多數情況下,這些不會作為有意義的字符串存儲在您獲取的信息中......它們只是數值。 它們都在前16個字節中。

我會根據您引用的規范解碼開頭。


字節0,1,2,3,4,5,6,7 - 標題信息

這應該是文字字符串“00h FFh FFh FFh FFh FFh FFh FFh 00h”,它用作我們正在查看有效EDID塊的健全性檢查。 您的數據完全符合我們的預期:

00 FF FF FF FF FF FF 00

字節8和9 - 制造商ID。

這些ID由Microsoft分配,並且是三字母代碼。 哦,當然,他們可以用ASCII“浪費”三個完整的字節。 但那太本事了。 因此,他們在標題的極其“非魔法”數字上燒掉了八個字節,並發明了一種“巧妙”的方式將這三個字母編碼為由兩個字節保存的16位。 他們怎么把它拉下來?

        +--------+--------+
        | Byte 8 | Byte 9 |
--------+--------+--------+
Bit #    76543210 76543210
-----------------=---------
Meaning  0αααααββ βββγγγγγ

因此,字節8的最高位始終為零,剩余的15位被分成3組,每組5位(我稱之為α,β和γ)。 每個都被解釋為一個字母,其中“00001 = A”; “00010 = B”; ......“11010 = Z”。

你有:

10 AC

十六進制10AC表示為16位二進制位是0001000010101100 所以讓我們再次把那張桌子帶回來:

        +--------+--------+
        | Byte 8 | Byte 9 |
--------+--------+--------+
Bit #    76543210 76543210
-----------------=---------
Meaning  0αααααββ βββγγγγγ
-----------------=---------
Yours    00010000 10101100

所以α = 00100 (十進制4), β = 00101 (十進制5), γ = 01100 (十進制12)。 使用這些十進制數作為英文字母的索引,我們得到DEL。 通過這種神秘的巫術,我們確定您的顯示器很可能是由戴爾制造的。 :)

字節10和11 - 產品ID代碼

這是一個由制造商分配的雙字節數字,存儲為“LSB優先”。 這就是說第一個字節是最不重要的位置值。 你有:

4C 40

我們需要將其解釋為十六進制數404C

字節12,13,14,15 - 序列號。

這是制造商分配的32位值,不需要格式。 它“通常存儲為LSB優先”,但不一定是。

53 43 34 42

您可以將其解釋為0x534334420x42344353 ,或者其他任何...只要您在將一個值與另一個值進行比較時保持一致。


所以現在你看到它只有三個字母和一些數字。 將字節放入緩沖區后,有很多方法可以提取信息。 @freerider提供了一些關於這方面的信息,我只想再多說一些。

EDID標准說你作為描述得到的是128字節。 這是注冊表項的情況,您可以假設如果沒有正好128個字節則它已損壞。 所以使用@freerider提供的代碼,沒有必要傳遞大於那個...如果那是你感興趣的EDID的唯一部分,你可以從技術上下降到16:

#define EDID_BUFFER_SIZE 128
// in idiomatic C++ it's better to say:
//     const size_t edidBufferSize = 128;

BYTE edidBuffer[EDID_BUFFER_SIZE];
DWORD nLength = GetLocalMachineProfileBuffer( Buffer, EDID_BUFFER_SIZE );
if (nLength != EDID_BUFFER_SIZE) {
    // handle error case, not a valid EDID block
} else {
    // valid EDID block, do extraction:
    // * manufacturer ID
    // * product ID
    // * serial number
}

除此之外,你關於如何從字節緩沖區中提取結構數據的問題是一個非常普遍的問題,並且是C風格編程的基礎,如果你不知道從哪里開始那么你應該通過更簡單的程序。 從制造商名稱中獲取三個五位段涉及位移,位屏蔽或位字段等操作。 通過數組處理地址以及如何索引數組和類似的東西。

我現在可以隨意找到的最接近的平行問題是:

從字節緩沖區中提取IP

有很多方法可以做到這一點,但有趣的是你可以在內存中定義一個結構的布局,然后告訴程序“嘿,我找到的這個內存塊就像我定義的結構一樣。所以讓我吧從中提取信息就像我在程序中定義對象一樣“......

但是,您必須對數據結構對齊等問題保持敏感。 那是因為編譯器自然地將對象放入內存的方式不一定與您認為的那樣匹配:

http://en.wikipedia.org/wiki/Data_structure_alignment

根據上述信息,您至少應該能夠閱讀一些教程並了解哪些有用。 如果你無法找出問題的一部分,那么將這個小部分作為自己的問題打破,並顯示你嘗試了什么以及為什么它不起作用......

上一個問題解釋了如何使用C / C ++ / C#獲取EDID。 它不是通過注冊表,但只要它工作...

在Windows XP / 7中獲取EDID的Win32代碼

如果您仍想閱讀注冊表,請使用RegQueryValueEx和朋友。

   DWORD GetLocalMachineProfileBuffer(BYTE* pBuffer, DWORD nMaxLength )
    {
        CString szSubKey = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\DEL404C{Some Unique ID}\Device Parameters\EDID";

        DWORD   rc; 
        DWORD   dwType; 
        HKEY    hOpenedKey;

        if( ERROR_SUCCESS == RegOpenKeyEx (
                HKEY_LOCAL_MACHINE, // handle of open key 
                szSubKey,               // address of name of subkey to open 
                0,                  // reserved 
                KEY_READ,       // security access mask 
                &hOpenedKey            // address of handle of open key 
                ) )
        {
            rc = RegQueryValueEx( 
                hOpenedKey, 
                (const char*)szValueName, 
                0, 
                &dwType, 
                (LPBYTE)pBuffer, 
                &nMaxLength ); 
            if( rc != ERROR_SUCCESS ) 
            { 
                return (DWORD)-1;
            } 
            else 
            { 
                ASSERT( dwType == REG_BINARY ); 
            } 

            RegCloseKey( hOpenedKey );
            return nMaxLength; 
        }
        else
        {
            return (DWORD)-1;
        }   
    }

這樣叫:

BYTE Buffer[20000];
DWORD nLength = GetLocalMachineProfileBuffer( Buffer, sizeof( Buffer ) );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM