Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Hex from Registry to Integer 2

Status
Not open for further replies.

MoonchildHK

Programmer
Jun 5, 2001
22
HK
HI All,

I have been trying to get this right for ages, and have ended up with about 10 lines of code for what I;m sure can be done in 1 statement!

I have a block of data stored in the registry. The block is binary: Ax Bx Cx Dx Ex Fx Gx Hx (8 Bytes)

Here is my problem: ExFx is an Integer I need to extract from the data block. I have tried using sscanf to get the data but can't get it right.. when I look at the data using RegEdit the bytes I need look like this:

93 b8 (For this example)

Now, I have already copied the data from the registry into memory pointed to by a pointer (char *data).

When I do something like this :

int a = *(data + 4)

.. I should get 147, but I end up with -109

My plan was to do

int a = *(data + 4)
int b = *(data + 5)

int number = (a*255) + b;

But now I have a horrible piece of code (where I search for "FFFFFF" in a string respresentation of the hex value and then replace it with "000000" to make it non-negative.

Any ideas would be most welcome :)

Thanks in Advance




 
I'm using:
WORD Hex2Int(char * Data, char Length)
{
WORD Result = 0;
WORD x;
if(Length) while(Length--)
{
Result <<= 4;
x = *(Data++);
if ((x >= (char)'0') && (x <= (char)'9')) Result += x - '0';
else if((x >= (char)'A') && (x <= (char)'F')) Result += x - ('A' + 10);
else if((x >= (char)'a') && (x <= (char)'f')) Result += x - ('a' + 10);
else
{
return(-1);
}
}
return(Result);
}


Totte
 
Are you storing the characters 'A' 'B' 'C' or the actual hex values A B C? When you put an x above, does that represent any number 0 through 9 or are you really storing the character 'x'?

Chris
 
I am storing the numeric values... in my explanation I am showing the XX as it is seen when using RegEdit and examining binary data.

So if I am looking at an ASCII representation of the data it is just garbage.

Thanks for the routine Totte, but this one converts from an ASCII representation of a hex number right? So if I had a string with &quot;A4E1&quot; in it for example I could use your routine. In my case, the string would be unreadable (most likely) so it would not work.. the actual value of the character (rather then it's ASCII representation) is the numeb I need. My main problem seems to be that I end up with Negative numbers in some cases.

Thanks
 
OH I think I see what you mean now. Well, here's what I would do.

unsigned char BinaryData[8];

MyRegVariable->ReadBinaryData(&quot;Key Name&quot;, BinaryData, 8);
unsigned char FirstNumber = BinaryData[0];
unsigned char SecNumber = BinaryData[1];
etc...

I may have the index backwards, BinaryData[7] may be the first number. You get the idea though.

Just remember that unsigned is key to your problem. After obtaining the number, use the function:
AnsiString __fastcall IntToHex(__int64 Value, int Digits);

Instead of a 64 bit number though, you'll pass in the unsigned char.

Good luck,
Chris
 
Just an extra note...if you want to pull out 2 bytes at a time (looks like what you needed above), it's pretty simple.

Use instead:
unsigned short int BinaryData[4];

Chris
 
OK, i get it.
How about storing the number in a overlayed structure and picking the things You want:
union
{
char Charwise [8]; // Signed byte
BYTE Bytewise [8]; // Unsigned byte
int Intwise [4]; // Signed int
WORD Wordwise [4]; // Unsigned int
long Longwise [2]; // Signed long
DWORD Dwordwise[2]; // Unsigned long
// And whatever the 64-bit value is called, i don't recall
} RegHex;

Then You can pick it anyway You like.

Totte
 
Thanks all for you great advice, but I am still still stuck!

I am doing this now;

Code:
 unsigned char data[16];
 unsigned int data2[8];
 unsigned int days;

  sucess = Reg->ReadBinaryData(&quot;RegData&quot;, data, 16);
  if(sucess) {
      // This is a 1 byte number
      days = data[6];
      }

  sucess = Reg->ReadBinaryData(&quot;RegData&quot;, data2, 8);
  if(sucess) {   
      // This is a 2 byte number (actually a unix timestamp)
      start = data[10];
      }
  }

Now, when using RegEdit I see the following (some things replaced by xx here):

xx xx xx xx xx xx 5b xx xx xx 93 bd xx xx xx xx

So what I should get is that days = 91 and start = 37821. Days is working fine, but start ends up as 48531.

Any ideas?

I guess although I am fine with VCL and TCP sockets, my fundamental C++ is lacking a little :-(

Thanks for the help :)
 
The first thing that stands out is that you are reading start=data[10]; when you should be reading data2[5]. This is probably the problem.

Another approach is to just use one array &quot;data&quot; and append the bytes together like this:

unsigned int start = (((unsigned int)data[10] << 8) | data[11]);

This will allow you to save from declaring an extra array and also save you from having to read in twice from the registry, although this is probably of no redeeming value in reality. :)

Good luck,
Chris
 
Ok finaly got it working!

Thanks for all the help, here is what I end up with:

Code:
    char data[16];
    int days, a, start;

    sucess = Reg->ReadBinaryData(&quot;RegData&quot;, data, 16);
    if(sucess) {
        days = data[6];
        if(days < 0)
            days &= 255;

        a = data[10];
        if(a < 0)
            a &= 255;
        start = a * 256;

        a = data[11];
        if(a < 0)
            a &= 255;
        start += a;
        }

In other places I am also using the IntToHex routine, much easier then using sprintf. Next step is to make it work with 2 byes and a data union which should be easy now, so thanks for all the advice :)
 
Forgive me but why don't you do like this:

union
{
BYTE Bytes[16];
struct
{
BYTE Unused1[6];
BYTE days;
BYTE Unused2[3];
WORD start;
} Usefull;
} Reg_Datas;

if(Reg->ReadBinaryData(&quot;RegData&quot;,data,16))
{
// It was OK, they're read from the registry
// Now You can access the values by:
// days = Reg_Datas.Usefull.days and
// start = Reg_Datas.Usefull.start
}


Totte
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top