c ++ - Hvordan kan jeg læse en REG\_BINARY værdier tilknyttet værdi fra registreringsdatabasen?

Indlæg af Hanne Mølgaard Plasc

Problem



I registreringsdatabasen er der en (eller flere) nøgle afhængig af hvor mange skærme du har HKEY\_LOCAL\_MACHINESYSTEMCurrentControlSetEnumDISPLAYDEL404C{Some Unique ID}Device ParametersEDID, hvilket er en REG\_BINARY key. I mit tilfælde er dette:


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


Denne reg\_binary-værdi indeholder oplysninger (f.eks. Serienummer og type) om den tilsluttede skærm. Jeg har kun brug for disse to værdier. Mit spørgsmål er, hvordan kan jeg læse disse værdier ved hjælp af C eller C ++?


Jeg har et VB script, som kan gøre dette:

'du kan fortælle Hvis placeringen indeholder et serienummer Hvis det starter med &H00 00 00 ff
strSerFind=Chr(&H00) & Chr(&H00) & Chr(&H00) & Chr(&HfF)


'eller en modelbeskrivelse Hvis den starter med &H00 00 00 fc


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


Dette link indeholder også oplysninger om EDID: http://en.wikipedia.org/wiki/Extended\_display\_identification\_data[27]


Kan nogen hjælpe mig, hvordan kan jeg gøre dette i C? Jeg kan kun finde VB script eksempler, men jeg forstår desværre ikke dem, og det ville også være meget vigtigt for mig.

Bedste reference


   DWORD GetLocalMachineProfileBuffer(BYTE* pBuffer, DWORD nMaxLength )
    {
        CString szSubKey = "HKEY\_LOCAL\_MACHINESYSTEMCurrentControlSetEnumDISPLAYDEL404C{Some Unique ID}Device ParametersEDID";

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


kalder det sådan:


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

Andre referencer 1


Du nævner at have 'serienummer' og 'type'. Der er ingen 'type', men der er et producent-id og et produkt-id. For det meste er disse ikke gemt som meningsfulde strenge i de oplysninger, du kommer tilbage ... de er bare numeriske værdier. Og de er alle i de første 16 byte.


Jeg vil afkode begyndelsen i henhold til den spec, du nævner.





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


Dette bør være den bogstavelige streng '00h FFh FFh FFh FFh FFh FFh 00h', som tjener som en sanity, kontrollerer, at vi ser på en gyldig EDID-blok. Dine data starter med, hvad vi forventer:


00 FF FF FF FF FF FF 00


Bytes 8 og 9 - Producent ID.


Disse id'er er tildelt af Microsoft og er trebogstavskoder. Åh, de kunne have 'spildt' tre hele bytes i ASCII for dette. Men det ville have været for fornuftigt. Så de fritterede væk otte byte på et ekstremt 'ikke-magisk' nummer til overskriften og opfandt en 'genial' måde at kode disse tre bogstaver i de seksten bits, der blev holdt af to byte. Hvordan drækker de det?


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


Så den højeste ordre bit af Byte 8 er altid nul, og de resterende 15 bit er opdelt i tre grupper på 5 bits (som jeg har kaldt α, β og γ). Hver er fortolket som et brev, hvor '00001=A ';' 00010=B '; ...' 11010=Z '.


Du har fået:


10 AC


Og hexadecimal 10AC udtrykt som 16 binære bits er 0001000010101100. Så lad os bringe bordet tilbage igen:


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


α = 00100 (decimal 4), β = 00101 (decimal 5), γ = 01100 (decimal 12). Ved hjælp af disse decimaltal som indekser i det engelske alfabet får vi D-E-L. Ved denne banefulde trolldom har vi fastslået, at din skærm sandsynligvis er lavet af Dell. :)


Bytes 10 og 11 - Produkt ID kode


Dette er et tobyte nummer, tildelt af producenten, gemt som 'LSB først'. Det vil sige, at den første byte er den mindst betydningsfulde stedværdi. Du har:


4C 40


Som vi skal fortolke som det hexadecimale nummer 404C.


Bytes 12,13,14,15 - Serienummer.


Dette er en 32-bit værdi tildelt af producenten, som ikke har krav til formatet. Det er 'normalt gemt som LSB først', men det skal ikke være.


53 43 34 42


Du kan fortolke det som 0x53433442 eller 0x42344353, eller hvad som helst ... så længe du er konsekvent i at sammenligne en værdi mod en anden.





Så nu ser du det er kun tre bogstaver og nogle tal. Når du har fået bytes til en buffer, er der mange måder at hente informationen på. @Freerider gav nogle oplysninger om det, jeg vil bare smide lidt mere .


EDID-standarden siger, at hvad du kommer tilbage som en beskrivelse er 128 bytes. Det er tilfældet med registreringsdatabasenøglen her, og du kan nok antage, at hvis der ikke er lige 128 bytes det er korrupt. Så ved at bruge koden fra @freerider, er der ingen grund til at passere i noget større end det ... du kunne teknisk gå ned til kun 16 hvis det er den eneste del af EDID du er interesseret i:


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


(Bemærk: Jeg foretrækker at undgå at bruge sizeof på arrays som @freerider 's sizeof( Buffer ) ovenfor. Selv om det vil fungere teknisk i dette tilfælde, returnerer det ikke antallet af elementer i arrayet ... snarere antallet af byte arrayet optager i hukommelsen. I dette tilfælde forekommer elementerne rent faktisk byte, så det vil fungere ... men du løber hurtigt ind i problemer, som når du sender et array til en anden funktion ved peger og pludselig begynder det at rapportere sin størrelse som størrelsen på en pointer ...) [28]


Udover det, er dit spørgsmål om, hvordan man henter strukturelle data ud af en buffer af bytes en meget generel, og det er så grundlæggende for C-style programmering, at hvis du ikke ved, hvor du skal starte med det, skal du nok arbejde igennem enklere programmer. Ved at få de tre fem-bits segmenter ud af producentens navn involverer ting som bitskift, bitmaskering eller bitfelter. At gå gennem arrayet omhandler adresser og hvordan man kan indeksere arrayer og lignende.


Det nærmeste parallelle spørgsmål jeg kunne finde for øjeblikket lige nu er dette:


udpakker IP fra en buffer af bytes


Masser af måder at gøre det på, men en interessant er at du kan definere layoutet af en struktur i hukommelsen og derefter fortælle programmet 'hej, denne blok af hukommelse jeg fandt er lagt ud som den struktur jeg definerede. Så lad mig Uddrag oplysninger fra det så enkelt som om jeg 'definerede objektet i mit program' ...


Men så er du nødt til at være følsom over for spørgsmål som datastrukturjustering. Det er fordi din kompilator naturligt sætter genstande i hukommelsen ikke nødvendigvis svarer til det, du tror det ville gøre:


http://en.wikipedia.org/wiki/Data\_structure\_alignment[30]


Med ovenstående oplysninger skal du i det mindste være i stand til at lave et skud ved at læse nogle vejledninger og se hvad der virker. Hvis du ikke kan finde ud af en del af problemet, så bryde den lille del ud som sit eget spørgsmål, og vis hvad du forsøgte, og hvorfor det ikke fungerede ...

Andre referencer 2


Dette tidligere spørgsmål forklarer, hvordan man får EDID med C/C ++/C #. Det er ikke gennem registreringsdatabasen, men så længe det virker ...


Win32 kode for at få EDID i Windows XP/7


Hvis du stadig vil læse registreringsdatabasen, skal du bruge RegQueryValueEx og venner. [32]