Comment puis-je lire une valeur associée à REG_BINARY à partir du registre?

Dans le registre, il existe une ou plusieurs clés dépendant du nombre de moniteurs HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\DEL404C\{Some Unique ID}\Device Parameters\EDID qui est une REG_BINARY key . Dans mon cas c’est:

 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 

Cette valeur reg_binary contient des informations (telles que le numéro de série et le type) sur le moniteur connecté. J’ai seulement besoin de ces deux valeurs. Ma question est la suivante: comment puis-je lire ces valeurs en utilisant C ou C ++?

J’ai un script VB qui peut faire ceci:
‘vous pouvez dire si l’emplacement contient un numéro de série S’il commence par &H00 00 00 ff strSerFind=Chr(&H00) & Chr(&H00) & Chr(&H00) & Chr(&HfF)

‘ou une description du modèle si elle commence par &H00 00 00 fc

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

Ce lien contient également des informations sur EDID: http://en.wikipedia.org/wiki/Extended_display_identification_data

Quelqu’un pourrait-il m’aider, comment puis-je le faire en C? Je ne peux trouver que des exemples de script VB, mais malheureusement je ne les comprends pas, et ce serait très important pour moi.

  DWORD GetLocalMachineProfileBuffer(BYTE* pBuffer, DWORD nMaxLength ) { CSsortingng 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; } } 

Appelez comme ceci:

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

Vous mentionnez vouloir le “numéro de série” et le “type”. Il n’y a pas de “type” mais il y a un identifiant de fabricant et un identifiant de produit. Pour la plupart, ils ne sont pas stockés comme des chaînes significatives dans les informations que vous recevez. Ce ne sont que des valeurs numériques. Et ils sont tous dans les 16 premiers octets.

Je décoderai le début selon les spécifications que vous citez.


Octets 0,1,2,3,4,5,6,7 – Informations d’en-tête

Cela devrait être la chaîne littérale “00h FFh FFh FFh FFh FFh FFh 00h”, qui sert à vérifier que nous examinons un bloc EDID valide. Vos données commencent exactement avec ce que nous attendons:

 00 FF FF FF FF FF FF 00 

Octets 8 et 9 – Identifiant du fabricant.

Ces identifiants sont atsortingbués par Microsoft et sont des codes à trois lettres. Oh, bien sûr, ils auraient pu “gaspiller” trois octets entiers en ASCII pour cela. Mais cela aurait été trop judicieux. Donc, ils ont gaspillé huit octets sur un nombre extrêmement “non magique” pour l’en-tête, et ont inventé un moyen “ingénieux” d’encoder ces trois lettres dans les seize bits de deux octets. Comment ont-ils réussi?

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

Ainsi, le bit de poids fort de l’octet 8 est toujours nul et les 15 bits restants sont divisés en trois groupes de 5 bits (que j’ai appelés α, β et γ). Chacun est interprété comme une lettre, où “00001 = A”; “00010 = B”; … “11010 = Z”.

Tu as:

 10 AC 

Et hexadécimal 10AC exprimé en 16 bits binarys est 0001000010101100 . Remettons donc cette table en arrière:

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

Donc α = 00100 (décimal 4), β = 00101 (décimal 5), γ = 01100 (décimal 12). En utilisant ces nombres décimaux comme index dans l’alphabet anglais, nous obtenons DEL. Par cette mystérieuse sorcellerie, nous avons déterminé que votre moniteur est probablement fabriqué par Dell. 🙂

Octets 10 et 11 – Code d’identification du produit

Il s’agit d’un numéro à deux octets, atsortingbué par le fabricant, enregistré sous le nom “LSB first”. Cela signifie que le premier octet est la valeur de position la moins significative. Tu as:

 4C 40 

Ce que nous devons interpréter comme le nombre hexadécimal 404C .

Octets 12,13,14,15 – Numéro de série.

Il s’agit d’une valeur de 32 bits atsortingbuée par le fabricant qui n’a pas besoin du format. Il est “généralement stocké en LSB en premier”, mais ne doit pas nécessairement l’être.

 53 43 34 42 

Vous pouvez interpréter cela comme 0x53433442 , ou 0x42344353 , ou autre chose … tant que vous comparez une valeur à une autre.


Alors maintenant, vous ne voyez que trois lettres et quelques chiffres. Une fois que vous obtenez les octets dans un tampon, il existe de nombreuses façons d’extraire les informations. @freerider a fourni des informations à ce sujet, je vais juste en jeter un peu plus.

Le standard EDID indique que ce que vous obtenez en tant que description est de 128 octets. C’est le cas avec la clé de registre ici, et vous pouvez probablement supposer que s’il n’y a pas exactement 128 octets, il est corrompu. Donc, en utilisant le code fourni par @freerider, il n’y aurait pas besoin de passer quelque chose de plus grand que ça … vous pourriez techniquement descendre à 16 si c’est la seule partie de l’EDID qui vous intéresse:

 #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 } 

(Note: je préfère ne pas utiliser la sizeof sur les tableaux comme la sizeof( Buffer ) @ freerider ci-dessus. Bien que cela fonctionnera techniquement dans ce cas, il ne retourne pas le nombre d’éléments dans le tableau … le tableau occupe la mémoire.Dans ce cas, les éléments sont en réalité des octets, donc cela fonctionnera … mais vous rencontrez rapidement des problèmes, comme lorsque vous passez un tableau à une autre fonction par un pointeur et que soudain il commence à signaler sa taille en tant que la taille d’un pointeur …)

Au-delà de cela, votre question de savoir comment extraire des données structurelles d’un tampon d’octets est très générale et est tellement fondamentale pour la programmation de style C que si vous ne savez pas par où commencer, vous devriez probablement passer par programmes plus simples. Obtenir les trois segments de cinq bits du nom du fabricant implique des choses comme le décalage de bits, le masquage de bits ou les champs de bits. Le fait de parcourir le tableau concerne les adresses et la façon d’indexer les tableaux et autres.

La question parallèle la plus proche que je pourrais trouver en ce moment est la suivante:

extraire IP d’un tampon d’octets

Beaucoup de façons de le faire, mais un point intéressant est que vous pouvez définir la disposition d’une structure en mémoire et ensuite dire au programme “Hé, ce bloc de mémoire que j’ai trouvé est disposé comme la structure que j’ai définie. Alors laissez-moi en extraire des informations aussi simplement que si j’avais défini l’object dans mon programme “…

Mais alors, vous devez être sensible aux problèmes tels que l’alignement de la structure de données. C’est parce que la manière dont votre compilateur va naturellement mettre les objects en mémoire ne correspond pas nécessairement à ce que vous pensez qu’il ferait:

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

Avec les informations ci-dessus, vous devriez au moins être en mesure de lire certains didacticiels et de voir ce qui fonctionne. Si vous ne parvenez pas à comprendre une partie du problème, divisez cette petite partie en sa propre question et montrez ce que vous avez essayé et pourquoi cela n’a pas fonctionné …

Cette question précédente explique comment obtenir EDID avec C / C ++ / C #. Ce n’est pas à travers le registre, mais tant que cela fonctionne …

Code Win32 pour obtenir EDID sous Windows XP / 7

Si vous souhaitez toujours lire le registre, utilisez RegQueryValueEx et vos amis.