Struct Viewer



The struct viewer dialog allows to quickly decode a struct at a specified offset.

Clicking a field highlights the field into the struct.

If the associated document is in Read/Write mode, double clicking field value (or representation value at the bottom) allows to quickly change the field value. Presse enter to validate the change, or escape to cancel the change.

   - Toolbar
   - Add / Edit Struct
   - Syntax
       User Types
       User Defines


Toolbar
Add Structure
Edit Structure Properties
Remove Selected Structure(s)
Remove All Structures
Expand All Structures
Collapse All Structures
Save Structures List: save current strutures list into a file for future reloading
Reload Structures List: reload a saved list of structures
Open Structures Folder
Open Defines Folder
Reload Structures And Defines Definitions

Add / Edit Struct
After clicking the add or edit structure, the following dialog will allow you to
   - Select the structure
   - Specify the document associated to the structure
   - Specify the start offset of the structure

As processor type and endianess can have impact on struct parsing, you can specify them too.



Syntax
Notice : Structure definition files and user define types files are fully compatible with WinApiOverride

User Types
User Types are located into the "UserTypes" directory or "UserTypes\ModuleName" directory

The following user types are supported
   - enum
   - struct
   - union
   - bits fields

The content of the file is a C/C++ syntax, so you can make copy and paste from your source code.

For enum definitions, the following operations are allowed : +, -, *, /, ||, &&, !, |, &, ^, ~, <<, >> , ? :

If your type need subtypes, you could put subtypes in the same file, before the type definition, like in your source code.
Specific cases :
As file name can't have ":", "<" or ">" symbols, user type file name must follow the following replacement rules

- for "Class::Type" type, a "Class..Type.txt" file will be searched ( ":" replaced by ".")
- for "TemplateType<MyType>", "TemplateType(MyType).txt" file will be searched ( "<" replaced by "(" and ">" by ")")

Notice : You still can let "Class::Type" or "TemplateType<MyType>" type in your definitions content, the translation is done by Helium Hex Editor.
Only text file name needs to be affected
Example: supported syntax
  1. typedef union
  2. {
  3. DWORD u1;
  4. BYTE u2;
  5. BYTE u3;
  6. }UNION_1;
  7.  
  8. typedef struct
  9. {
  10. UNION_1 u;
  11. DWORD* pdw;
  12. BYTE bArray[5];
  13. char* str;
  14. DWORD dwArray[2][2];
  15. DWORD dw;
  16. }STRUCT_1;
  17. typedef STRUCT_1* PSTRUCT_1;
  18.  
  19. enum enum1
  20. {
  21. FOO_1 = 0x123,
  22. FOO_2,
  23. FOO_3 = 2*FOO_1
  24. };
  25. enum enum2
  26. {
  27. FOO_21 = 0x123,
  28. FOO_22,
  29. FOO_23 = 0x456
  30. };
  31.  
  32. typedef struct
  33. {
  34. STRUCT_1 S[2];
  35. DWORD dw1, dw2;
  36. /* some comment
  37. *
  38. */
  39. union _u
  40. {
  41. DWORD LSB:1,
  42. b2:1,
  43. b3:1,
  44. b4:1,
  45. unused:27,
  46. MSB:1;
  47. DWORD RawValue;
  48. // 0x8000000A = 1000 0000 0000 0000 0000 0000 0000 1010
  49. }U;
  50. DWORD dw4;
  51.  
  52.  
  53. struct Date {
  54. DWORD nWeekDay : 3; // 0..7 (3 bits)
  55. DWORD nMonthDay : 6; // 0..31 (6 bits)
  56. DWORD : 0; // Force alignment to next boundary.
  57. DWORD nMonth : 5; // 0..12 (5 bits)
  58. DWORD nYear : 8; // 0..100 (8 bits)
  59. DWORD Foo : 30; // just to force another DWORD
  60. }d;
  61.  
  62. enum1 e1[2];
  63. enum2 e2;
  64. }STRUCT_2,*PSTRUCT_2;
#include : Include other user type files with #include
Allow to includes Types definition from another type definition.
This is usefull only if required type doesn't has a file associated.
If required type file exists it will be automatically parsed and you don't need #include
     #include "OtherUserType.txt"

Supported Standard Pragma ( #pragma pack(push), #pragma pack(Value), #pragma pack(pop) )
The following #pragma pack are supported:
#pragma pack(push)
#pragma pack(X) // where X is a number
#pragma pack(pop)

    #pragma pack(push)
    #pragma pack(1)  
    typedef struct
    {
        BYTE b;
        WORD w;
        DWORD dw;
    }STRUCT1;
    #pragma pack(pop)


Specific Pragma
The following pragmas are not standard and Helium Hex Editor / WinApiOverride defined only

#pragma next_field_define_values_file("File")
Using this pragma allows to provide the define text value instead of the raw value
File path provided is relative path from the "UserDefines" directory
        struct __tagVARIANT
        {
            #pragma next_field_define_values_file("VARTYPE_Defines.txt")
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            ...
        }
    
when decoding something like VT_UI4 will displayed instead of 19

#pragma next_enum_size(X)
#pragma next_enum_size(X) // where X is a number
Allow to specify a size for a pseudo enum. This is usefull when UINT8,UINT16,... are used as enum.
The availability to specify an enum instead of such type provides you a quick decoding way.
Parameter will show the enum text instead of the raw value
        #pragma next_enum_size(1)
        typedef enum
        {
            E1_value0=0,
            E1_value1,
            E1_value2,
        }ENUM1;
    
        #pragma next_enum_size(2)
        typedef enum
        {
            E2_value0=0,
            E2_value1,
            E2_value2,
        }ENUM2; 
    


#next_field_endianness(little_endian/big_endian)
The next field endianness is modified
By default if no endianness is specified, endianness is little_endian
        typedef struct
        {
            WORD w;
            DWORD dw;
            STRUCT2 Struct2; // in this case, Struct2 will be parsed as a big endian struct
        }STRUCT1;    
    


#pragma next_struct_endianness(little_endian/big_endian[,true/false = false])
The second paramter, which is optional (default value=false), specifies if endianness applies to substructures (true) or not (false)
By default if no endianness is specified, endianness is little_endian
        #pragma next_struct_endianness(big_endian,true)
        typedef struct
        {
            WORD w;
            DWORD dw;
            STRUCT2 Struct2; // in this case, Struct2 will be parsed as a big endian struct
        }STRUCT1;
        All the fields and nested structs of the previous struct will be parsed as big endian
    
        #pragma next_struct_endianness(big_endian,false)
        typedef struct
        {
            WORD w;
            DWORD dw;
            STRUCT2 Struct2; // in this case, Struct2 will be parsed as a little endian struct, 
                             // even if all other fields are parsed as big endian fields
        }STRUCT3; 
    


#pragma next_field_must_XXX
All the following #pragma next_field_must_XXX pragma are for quick field value checking.
The background color of the field is set to green (if field match condition) or red (field doesn't match condition)
The background color of owning struct is green if all fields with "#pragma next_field_must_XXX" conditions match,
and red as soon as at least a single child field doesn't match the condition
        typedef struct
        {
            WORD w;
            
            #pragma next_field_must_match(2)
            DWORD dw;
            
            STRUCT2 Struct2;
        }STRUCT1;
    
The background color of dw is green if dw==2, red else.
In this case as we get only one child with condition, the background color of STRUCT1 will be the same as the background color of dw


#pragma next_field_must_match(x) / #pragma next_field_must_match("string")
the next field must match the provided content
        typedef struct
        {
            ...
            #pragma next_field_must_match(2)
            DWORD dw;       
            
            #pragma next_field_must_match("Some String")
            LPCSTR String;
            
            #pragma next_field_must_match("Some String")
            LPWCSTR wString;
            ...
        };  
    


#pragma next_field_must_match_one_of(x,y,z) / #pragma next_field_must_match_one_of("String1","String2","String3")
#pragma next_field_must_match_one_of(x,y,z,...) where x,y,z,... are values or strings
the next field must match one of the provided content
        typedef struct
        {
            ...
            #pragma next_field_must_match_one_of(1,8,64,128,256,512,1024,2048)
            DWORD dw;
            
            #pragma next_field_must_match_one_of("AnsiString1","AnsiString2","AnsiString3")
            CHAR String[256];
    
            #pragma next_field_must_match_one_of("UnicodeString1","UnicodeString2","UnicodeString3")
            WCHAR wString[256];
            ...
        };  
    


#pragma next_field_must_be_less_or_equal(x)
#pragma next_field_must_be_less_or_equal(x) where x is a value the next field must be less or equal to x (Value<=x)
        typedef struct
        {
            ...
            #pragma next_field_must_be_less_or_equal(80)
            DWORD dw;
            
            #pragma next_field_must_be_less_or_equal(0x28)
            DWORD dw2;           
            ...
        };
    


#pragma next_field_must_be_greater_or_equal(x)
#pragma next_field_must_be_greater_or_equal(x) where x is a value the next field must be greater or equal to x (Value>=x)
        typedef struct
        {
            ...
            #pragma next_field_must_be_greater_or_equal(3)
            DWORD dw;
            
            #pragma next_field_must_be_greater_or_equal(0x28)
            DWORD dw2;        
            ...
        };
    


#pragma next_field_must_be_between_inclusive(x,y)
#pragma next_field_must_be_between_inclusive(x,y) where x and y are values the next field must be greater or equal to x and lower or equal to y ( x <= Value <= y )
        typedef struct
        {
            ...
            #pragma next_field_must_be_between_inclusive(10,56)
            DWORD dw;
            
            #pragma next_field_must_be_between_inclusive(2.7,2.95)
            double dbl; 
    
            #pragma next_field_must_be_between_inclusive(2.5,4.5)
            float f;        
            ...
        };
    
User Defines
User Defines are located into the "UserDefines" or "UserDefines\ModuleName" directory
Only integer defines are supported (no floats or strings support)
For defines content, the following operations are allowed : +, -, *, /, ||, &&, !, |, &, ^, ~, <<, >> , ? :, <,>, ==, <=,>=

Example of content :
  1. #define FOO1 45
  2. #define FOO2 1024
  3. #define FOO3 32
  4. #define FOO4 (FOO1+FOO3)
  5. #define FOO5 3
  6. #define FOO6 8
  7.  
  8. #define FOO11 (FOO1 +1 -5*(FOO1-FOO2) +( (1+ FOO2/FOO1) *2))
  9. #define FOO12 (FOO1 | FOO3)
  10. #define FOO13 (~FOO3)
  11. #define FOO14 (FOO2^FOO1)
  12. #define FOO15 ((FOO2<FOO1) ? FOO3 : 7)