How can I find out the REG_BINARY value associated with the registry?

There is one (or more) keys in the registry, depending on how many monitors you have HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\DEL404C\{Some Unique ID}\Device Parameters\EDID , which is a REG_BINARY key . In my case, this is:

 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 

This reg_binary value contains information (for example, serial number and type) about the connected monitor. I need only these two values. My question is: how can I read these values ​​using C or C ++?

I have a VB script that can do this:
'you can indicate if this field contains a serial number. If it starts with &H00 00 00 ff strSerFind=Chr(&H00) & Chr(&H00) & Chr(&H00) & Chr(&HfF)

'or a description of the model. If it starts with &H00 00 00 fc

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

This link also contains information about EDID: http://en.wikipedia.org/wiki/Extended_display_identification_data

Can someone help me how can I do this in C? I can only find VB script examples, but unfortunately I do not understand them, and that would be very important to me.

+2
source share
3 answers
  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; } } 

name it as follows:

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

You mentioned the desire for "serial number" and "type." There is no "type", but there is a manufacturer identifier and a product identifier. For the most part, they are not stored as meaningful strings in the information you return ... they are just numeric values. And they are all in the first 16 bytes.

I will decode the beginning according to the specification you are quoting.


Bytes 0,1,2,3,4,5,6,7 - Header Information

This should be the literal string "00h FFh FFh FFh FFh FFh FFh 00h", which serves as a health check that we are considering a valid EDID block. Your data begins exactly with what we expect:

 00 FF FF FF FF FF FF 00 

Bytes 8 and 9 - The identifier of the manufacturer.

These identifiers are assigned by Microsoft and are three-letter codes. Of course, they could "spend" three integer bytes in ASCII for this. But that would be too reasonable. Thus, they collected eight bytes on an extremely “non-magic” header number and invented a “brilliant” way to encode these three letters into sixteen bits stored in two bytes. How did they take it off?

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

Thus, the high-order bit of byte 8 is always zero, and the remaining 15 bits are divided into three groups of 5 bits each (which I named α, β, and γ). Each of them is interpreted as a letter, where "00001 = A"; "00010 = B"; ... "11010 = Z".

You have:

 10 AC 

And the hexadecimal 10AC , expressed as 16 binary bits, is 0001000010101100 . So bring this table back:

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

So α = 00100 (decimal number 4), β = 00101 (decimal number 5), γ = 01100 (decimal number 12). Using these decimal numbers as indices in the English alphabet, we get DEL. Thanks to this magical witchcraft, we determined that your monitor was most likely made by Dell. :)

Bytes 10 and 11 - Product Identifier Code

This is a two-byte number assigned by the manufacturer, which is stored as "LSB first". This means that the first byte is the least significant place value. You have:

 4C 40 

What we need to interpret as a 404C hexadecimal number.

Byte 12,13,14,15 - Serial number.

This is a 32-bit value assigned by the manufacturer and does not require a format. It is "usually stored as LSB first", but not required.

 53 43 34 42 

You can interpret this as 0x53433442 , or 0x42344353 , or something else ... as long as you are incompatible in comparing one value with another.


So, now you see only three letters and some numbers. Once you get the bytes into the buffer, there are many ways to extract information. @freerider provided some information about this, I will just add a little more.

The EDID standard says that what you get as a description is 128 bytes. This applies to the registry key, and you can probably assume that if 128 bytes are not corrupted, this is damage. So, using the code provided by @freerider, you wouldn't have to skip anything more than that ... you could technically go down to just 16 if that is the only part of the EDID that you are interested in:

 #define EDID_BUFFER_SIZE 128 // in idiomatic C++ it 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 } 

(Note: I prefer to avoid using sizeof on arrays like @freerider sizeof( Buffer ) above. Although this will technically work in this case, it does not return the number of elements in the array ... rather the number of bytes that the array occupies in memory . In this case, the elements are actually bytes, so they will work .. but you quickly run into problems, for example, when you pass an array to another function with a pointer, and suddenly it starts reporting its size as the size of the pointer ...)

Also, your question about how to extract structural data from a byte buffer is very general and so fundamental to C-style programming that if you don’t know where to start, then you should probably work through simpler programs . Getting three five-bit segments from the manufacturer’s name includes things like bit offsets, bit masking, or bit fields. Array traversal addresses addresses and indexing methods of arrays, etc.

The closest parallel question I could find right now is this:

extract IP from byte buffer

There are many ways to do this, but the interesting thing is that you can define the layout of the structure in memory and then tell the program “hey, this memory block that I found is laid out just like I defined the structure. So let me extract the information from it just as if I defined an object in my program "...

But then you should be sensitive to issues such as data structure alignment. This is because the way your compiler naturally places objects in memory does not necessarily match what you think it will do:

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

With the information above, you can at least take a picture while reading some lessons and find out what works. If you cannot understand one part of the problem, then break this small part as your own question and show what you tried and why it did not work ...

+5
source

This previous question explains how to get EDID using C / C ++ / C #. This is not through the registry, but how long does it work ...

Win32 code for obtaining EDID in Windows XP / 7

If you still want to read the registry, use RegQueryValueEx and friends.

+2
source

All Articles