Lazarus

Free Pascal => General => Topic started by: Sestus on September 23, 2021, 02:15:30 pm

Title: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 23, 2021, 02:15:30 pm
Hello,
i need to store a FileHandle that is of the type THandle inside a specific position in my ByteArray. The number stored inside the handle normally is about 49 000 000. When i access the Array via
Code: Pascal  [Select][+][-]
  1. //Exportieren der Datei
  2.                  hOpenResult := XWF_OpenItem(CurrentVolume, nItemID, $01); //Öffnen des Files, returned Handle, bei 0 unsuccessful
  3.  
  4. //Erzeugung des Hashs in XWF
  5.                  HashTypeBuf[0] := $11;
  6.                  HashTypeBuf[1] := hOpenResult;
  7.  
the second number stored inside the array is NOT the number inside the FileHandle as i want it. I thought the problem may be that on byte isn't sufficient for that huge number so i think 4 bytes to store the number would do the trick. My problem now is that i don't know how to access multiple bytes in the byte array so i can store the huge number inside for example the four bytes starting at HashTypeBuf[1].
Would be much appreciated if someone can help. :)
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Bart on September 23, 2021, 02:26:06 pm
You can cast a THandle to array[0..SizeOf(THandle)-1] bytes and then access and store the individual bytes.
Code: Pascal  [Select][+][-]
  1. type
  2.   THandleAsBytes = array[0..SizeOf(THandle)-1] byte;
  3. ...
  4.   HashTypeBuf[1] := THandleAsBytes(Handle)[0];
  5.   ... etc.
You might get into trouble if Endianness changes.

Bart
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 23, 2021, 02:47:23 pm
So when i do it like this
Code: Pascal  [Select][+][-]
  1. var
  2. THandleAsBytes             :   array[0..SizeOf(THandle)-1] of Byte;
  3. ...
  4. hOpenResult := XWF_OpenItem(CurrentVolume, nItemID, $01); //Öffnen des Files, returned Handle, bei 0 unsuccessful
  5. //Erzeugung des Hashs in XWF
  6. HashTypeBuf[0] := $10;
  7. HashTypeBuf[1] := THandleAsBytes(hOpenResult)[0];
  8.  
it doesn't compile but maybe i understood something wrong I'm still kinda new to FPC sry :)
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Zvoni on September 23, 2021, 04:15:54 pm
How "big" is the Array HashTypeBuf?
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 23, 2021, 05:10:14 pm
I have it just declared like that
Code: Pascal  [Select][+][-]
  1. HashTypeBuf                :   array of Byte;
and after it like that
Code: Pascal  [Select][+][-]
  1. SetLength(HashTypeBuf,                                     16);
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Warfley on September 23, 2021, 05:52:50 pm
You can access any type as any other type through pointers, and Pointers function like arrays.
Accessing the bytes of a handle
Code: Pascal  [Select][+][-]
  1. PByte(@Handle)[0]; // PByte is byte pointer
  2. PByte(@Handle)[1];
  3. ...
And to access a byte array as handle:
Code: Pascal  [Select][+][-]
  1. PHandle(Pointer(ByteArray))^;
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Zvoni on September 23, 2021, 05:53:19 pm
Should be enough.
Have you tried to „Move“ (memcopy) the array?
Title: Re: Accessing multiple bytes inside bytearray?
Post by: engkin on September 23, 2021, 05:58:24 pm
Code: Pascal  [Select][+][-]
  1.  type
  2.   PHandle=^THandle;
  3. ...
  4.   PHandle(@HashTypeBuf[1])^:=hOpenResule;
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Remy Lebeau on September 23, 2021, 06:16:50 pm
Code: Pascal  [Select][+][-]
  1. Move(hOpenResult, HashTypeBuf[1], SizeOf(hOpenResult));
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 23, 2021, 06:44:15 pm
With Move(hOpenResult, HashTypeBuf[1], SizeOf(hOpenResult)); the array fills. Before the second Byte only was filles with a 160, with the new command it's 160, 67, 226, 2. The original value of hOpenResult was hOpenResult = 48382880 though. Do i have to declare the values before to be hex so in the array its right?
I will put the explanation of the original function from the api doc here so maybe if I'm doing something complety wrong here point me to the right spot.

"x10: flag to make this function compute the requested value(s) during the call if the hash value is not stored in the volume snapshot yet, which requires v19.7 or later, and a handle to the file (hItem) must be stored in the buffer at offset 4, i.e. directly after the DWORD value"... hItem im my case should be hOpenResult. The DWORD value is $10.

My current code:
Code: Pascal  [Select][+][-]
  1.                  hOpenResult := XWF_OpenItem(CurrentVolume, nItemID, $01); //Öffnen des Files, returned Handle, bei 0 unsuccessful
  2.  
  3.                  //Erzeugung des Hashs in XWF
  4.                  HashTypeBuf[0] := $10;
  5.                  Move(hOpenResult, HashTypeBuf[1], SizeOf(hOpenResult));
  6.                  GetHashOK := XWF_GetHashValue(nItemID, @HashTypeBuf[0]); //Hash Value mithilfe XWF Funktion berechnen
   
Title: Re: Accessing multiple bytes inside bytearray?
Post by: ASerge on September 24, 2021, 03:49:41 am
You might get into trouble if Endianness changes.
There are conversion functions like NtoBE (https://lazarus-ccr.sourceforge.io/docs/rtl/system/ntobe.html). Example:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3.  
  4. procedure Test;
  5. type
  6.   THandleAsBytes = array[0..SizeOf(THandle)-1] of Byte;
  7. var
  8.   hOpenResult: THandle;
  9.   hOpenResultAsBytes: THandleAsBytes absolute hOpenResult;
  10.   HashTypeBuf: array of Byte;
  11. begin
  12.   SetLength(HashTypeBuf, 100);
  13.   hOpenResult := NtoBE($12345678); // A function that returns a handle $12345678
  14.   HashTypeBuf[1] := hOpenResultAsBytes[0];
  15.   Writeln(HashTypeBuf[1]);  // 18 (=$12 even for little-endian, x86 processor)
  16. end;
  17.  
  18. begin
  19.   Test;
  20.   Readln;
  21. end.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: PascalDragon on September 24, 2021, 08:59:30 am
I thought the problem may be that on byte isn't sufficient for that huge number so i think 4 bytes to store the number would do the trick.

Please note that the size of a handle depends on the platform, it might be 2, 4 or 8 Byte.

Also it might be a bad idea to use the handle as a hash as the value contained in the handle might change between runs. Where did you get the handle from and what are you trying to achieve with your hash?
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 24, 2021, 01:20:20 pm
The XWF GetHashValue function writes the Hash value into the HashTypeBuf Buffer. The Handle has to be stored in the buffer before because the GetHashValue function needs the handle at offset 4 to work correctly. After the hash is in the buffer i want to write it into a string to later compare it with another string which is also a hash to see if its one and the same file.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: PascalDragon on September 24, 2021, 01:25:53 pm
But that's my point: a hash of the handle is nothing unique. If you open a file again it might get a different handle also if you open a file twice it will be the same file but different handles.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 24, 2021, 01:33:42 pm
The function does NOT compute a Hash for the handle. The handle is just for the function to work correctly. Normally the function will create a Hash for a file inside the program in which i want to implement my programm. I only need the handle because the documentary states that to work it needs this at offset 4. So as i understood it i get a hash inside the declared buffer which overrides the values that where previously there such as $10 and the handle to the file.
The problem now is that the numbers that get written inside the buffer are not the result of hOpenResult. So i think there is some kind of conversion with hex numbers or something going on but i dont know how to fix that.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Zvoni on September 24, 2021, 02:36:15 pm
I finally figured out, what's been bugging me:

HashTypeBuf is an Array of Byte, and the OP uses it for the second Parameter for XWF_GetHashValue
As the Doc's state:
Quote
and a handle to the file (hItem) must be stored in the buffer at offset 4, i.e. directly after the DWORD value
There: Directly after the DWORD-Value.
A DWORD is 4 Bytes.
How in blazes is
HashTypeBuf[1] := hOpenResultAsBytes[0];
supposed to work?
Offset 4 would be HashTypeBuf[4] (0..3 would be the 4 Bytes for this DWORD Value)

EDIT: The original C-Declaration is
Code: C  [Select][+][-]
  1. BOOL XWF_GetHashValue(
  2.    LONG nItemID,
  3.    LPVOID lpBuffer
  4. );
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 24, 2021, 04:30:59 pm
So you say it would make more sense like this:
Code: Pascal  [Select][+][-]
  1. hOpenResult := XWF_OpenItem(CurrentVolume, nItemID, $01); //Öffnen des Files, returned Handle, bei 0 unsuccessful
  2.  
  3. //Erzeugung des Hashs in XWF
  4. HashTypeBuf[0] := $10;
  5. Move(hOpenResult, HashTypeBuf[4], SizeOf(hOpenResult));
  6. GetHashOK := XWF_GetHashValue(nItemID, @HashTypeBuf[0]);
  7.  
What you said made sense to me finally. So thanks for that. Sadly the function still doesn't work. At this point the only thing i can think of is that the handle isn't stored correctly or something. As i iterated before, the numbers inside the array do not match with the original handle from hOpenItem. Its probably because the number ist to big to store for one byte (around 49 000 000). I dont know if i have to translate the big number first into a hex value or something. Something is still not quite right.
Thanks for the continued support I really appreciate it . :)
I'll attach a picture with the values that are currently inside the buffer.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: 440bx on September 24, 2021, 06:04:09 pm
Sadly the function still doesn't work.

I'll attach a picture with the values that are currently inside the buffer.
You cannot expect the debugger to show you a DWORD stored in a byte array because the debugger is told that there is an array of bytes not DWORDs.  That's why it's showing a value that is "different" (it really isn't) than what you are expecting.  It's showing the last byte of the DWORD instead of the whole DWORD (as it should.)

Play with this little program and notice that if you hover over ByteArray, you'll get a "different" value than when you hover over DwordPtr.  The difference is just that when hovering over ByteArray, the debugger shows a byte arrangement, when hovering over DwordPtr, it shows the DWORD stored at ByteArray[4].
Code: Pascal  [Select][+][-]
  1. {$APPTYPE       CONSOLE}
  2.  
  3. {$TYPEDADDRESS  ON}
  4.  
  5. {$LONGSTRINGS   OFF}
  6.  
  7. { --------------------------------------------------------------------------- }
  8.  
  9.  
  10. program _BytesAndDwords;
  11.  
  12. uses
  13.   Windows,
  14.  
  15.   sysutils
  16.   ;
  17.  
  18. var
  19.   ByteArray     : packed array[0..255] of byte;
  20.  
  21.   DwordPtr      : PDWORD;
  22.  
  23. const
  24.   HandleValue   = $76543210;      { large number                              }
  25.  
  26.  
  27. begin
  28.   writeln;
  29.   writeln;
  30.  
  31.   writeln('  HandleValue : ', '$' + IntToHex(HandleValue, 0));
  32.  
  33.   DwordPtr := PDWORD(@ByteArray[4]);
  34.  
  35.   DwordPtr^ := HandleValue;
  36.  
  37.   DwordPtr  := DwordPtr;          { to hover over DwordPtr in debugger        }
  38.  
  39.   writeln;
  40.   writeln('  HandleValue : ', '$' + IntToHex(DwordPtr^, 0));
  41.  
  42.   { note the difference with this                                             }
  43.  
  44.   ByteArray[4] := ByteArray[4];   { hover over ByteArray                      }
  45.  
  46.   writeln;
  47.   writeln('  HandleValue : ', '$' + IntToHex(ByteArray[4], 0));
  48.  
  49.  
  50.   writeln;
  51.   writeln;
  52.   writeln('press ENTER/RETURN to end this program');
  53.   readln;
  54. end.
  55.  

Note: line 33 and 35 could be combined into a single statement.  They are separate only for "demonstration" purposes.

HTH.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 24, 2021, 07:11:55 pm
Ok than first of all thanks to all that answered. Maybe the problem lays somewehere else then. Maybe i'll write the developer again so i get the function to work properly. :)
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Remy Lebeau on September 24, 2021, 08:48:42 pm
EDIT: The original C-Declaration is
Code: C  [Select][+][-]
  1. BOOL XWF_GetHashValue(
  2.    LONG nItemID,
  3.    LPVOID lpBuffer
  4. );

Here is the rest of the documentation for that function:

https://www.x-ways.net/forensics/x-tensions/XWF_functions.html

Quote
Available in v16.8 and later. May be used to retrieve the hash value of a file if one has been computed or to get it computed if not. Whether or not a hash value has been computed previously can be checked separately by calling XWF_GetItemInformation if required (as prior to v19.7 this function did not check that and returned TRUE already if no I/O error occurred). To find out the type of hash value, call XWF_GetVSProp with XWF_VSPROP_HASHTYPE1 or XWF_VSPROP_HASHTYPE2.

When the function is called, the buffer is assumed to start with a DWORD value. That value determines what the function does. The same buffer will be used to accommodate the requested hash value when control is returned to the caller (if the function succeeds). The required buffer size depends on the hash type. The following DWORD values are currently defined:

  • Case 1: < 0x00000100:
    0x01: flag to retrieve the primary hash value
    0x02: flag to retrieve the secondary hash value, requires v18.0 SR-12, v18.1 SR-7, v18.2 SR-5, v18.3 SR-4 or later
    0x10: flag to make this function compute the requested value(s) during the call if the hash value is not stored in the volume snapshot yet, which requires v19.7 or later, and a handle to the file (hItem) must be stored in the buffer at offset 4, i.e. directly after the DWORD value

    Note that only v19.7 and later can retrieve or compute two hash values at the same time. The buffer must be large enough to accommodate both hash values. If two hash values are requested and retrieved, the first hash value will be stored at the start of the buffer (buffer offset 0). The offset in the buffer where the second hash value starts depends on the size (and thus the type) of the first hash value. Prior to v19.7 you needed two separate calls to retrieve both hash values.
  • Case 2: >= 0x00000100:
    Subject to change at any time (yes, literally): In v18.8 and later, this function may also be used to retrieve pre-computed PhotoDNA hash values from the volume snapshot. For that purpose the buffer must be filled with a DWORD value of 0x00000100 or greater. 0x00000100 retrieves the 1st, 0x00000101 the 2nd, 0x00000102 the 3rd, and 0x00000103 the 4th PhotoDNA hash value (only 1 at a time). Note that for most files with graphical data, if at all, X-Ways Forensics computes only 1 such hash value. More than 1 hash value may be present if the user requested additional matching attempts with horizontal flipping and/or if X-Ways Forensics is uncertain about the vertical orientation of certain TIFF files. Note that it depends on the user whether or not PhotoDNA hash values are permanently stored in the database, which is a precondition for this function to work. The buffer must have space for 144 bytes when retrieving PhotoDNA hash values. The function returns TRUE if a PhotoDNA hash value was available and actually copied into lpBuffer.

So, in this situation, I would NOT use a byte array at all, I would use a packed record instead, eg:

Code: Pascal  [Select][+][-]
  1. const
  2.   HashSize = ...; // set as needed, depending on the hash size being requested...
  3. type
  4.   MyHashRec = packed record
  5.     case Integer of
  6.       0: (funcType: DWORD;
  7.           hItem: THandle);
  8.       1: (Hash1: array[0..HashSize-1] of Byte;
  9.           Hash2: array[0..HashSize-1] of Byte);
  10.   end;
  11.  
  12. var
  13.   rec: MyHashRec;
  14.   hOpenResult: THandle;
  15.   ...
  16. begin
  17.   ...
  18.   hOpenResult := XWF_OpenItem(CurrentVolume, nItemID, $01); //Öffnen des Files, returned Handle, bei 0 unsuccessful
  19.   ...
  20.   rec.funcType := $10;
  21.   rec.hItem := hOpenResult;
  22.   GetHashOK := XWF_GetHashValue(nItemID, @rec);
  23.   if GetHashOK then
  24.   begin
  25.     // use rec.Hash1 and rec.Hash2 as needed...
  26.   end;
  27.   ...
  28. end;
  29.  
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 24, 2021, 10:32:08 pm
First thanks again. I never heard of that data type and inserted the code in my project. I think all the values during running are as intended. Still the XWF_GetHashValue function gives back false and doesn't compute a hash into the buffer/record. At this point i don't know what I could be mssing here. Before your last reply I wrote the developers if I'm missing something. Apart from that I don't really know what I could do else. :/
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Zvoni on September 25, 2021, 09:19:16 am
Is the source code of the function available?
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 25, 2021, 11:21:32 am
Just that API in this zip.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Zvoni on September 25, 2021, 01:10:20 pm
Something else: are you calling with cdecl or stdcall?
What i could find it‘s stdcall

https://github.com/hmrc/XT_XWF-2-RT/blob/master/XT_API.pas
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 25, 2021, 01:31:36 pm
Yes i think it's stdcall.
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Thaddy on September 25, 2021, 01:44:27 pm
So you mean it is Windows only?
Usually, X platform, stdcall is not so "standard", cdecl is usually the standard....
Title: Re: Accessing multiple bytes inside bytearray?
Post by: Sestus on September 25, 2021, 01:46:18 pm
Yeah i mean i use the API from the link. And i work on windows so for me ot works.
TinyPortal © 2005-2018