User Types
Defining your user types allow the following
   - 1) Displaying decoded content (Notice: content is fully displayed only in the detailed view for better speed performances)
   - 2) Parameter size auto retrieval : you don't need to specify the ":DataSize=" or ":PointedDataSize=" parameter option in your monitoring file

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

If you want to monitor one of your software built with Microsoft Visual Studio,
use Debug Info Viewer to automatically generate all types used by your application

Example of decoding for my testing strange type described below

   - Requirements
   - User Types file content / Syntax

   - Include other User Types files with #include
   - Automatically load multiples struct definition at startup
   - User Types file content / Syntax

   - Supported Standard Pragma ( #pragma pack(push), #pragma pack(Value), #pragma pack(pop) )

WinApiOverride Specific Pragma
   - #pragma next_field_define_values_file("File")
   - #pragma next_enum_size(X)
   - #next_field_endianness(little_endian/big_endian)
   - #pragma next_struct_endianness(little_endian/big_endian[,true/false = false])
   - #pragma next_field_must_XXX
       #pragma next_field_must_match(x) / #pragma next_field_must_match("string")
       #pragma next_field_must_match_one_of(x,y,z) / #pragma next_field_must_match_one_of("String1","String2","String3")
       #pragma next_field_must_be_less_or_equal(x)
       #pragma next_field_must_be_greater_or_equal(x)
       #pragma next_field_must_be_between_inclusive(x,y)


Requirements

To be supported

   - 1) the name of the file must be the name of the type, with the ".txt" extension
By the way for the "MSG" type we must have a "MSG.txt" file
the * and the prefixes "P", "LP", "PC", "LPC" are managed by WinApiOverride.
That means your "MSG.txt" file will be automatically loaded for "MSG", "MSG*", "PMSG", "LPMSG", "PCMSG", "LPCMSG"

You don't have to touch your api monitoring file :
when your monitoring file is parsed, WinApiOverride will automatically search the associated type file

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 monitoring file, the translation is done by WinApiOverride.
Only text file name needs to be affected

   - 2) The file containing the type definition must be put in the "UserTypes" directory or "UserTypes\YourModuleName" directory.
By the way for the "MSG" type the "MSG.txt" file can be under "UserTypes\user32.dll" folder
Using the module name as subdirectory is better to avoid confusion.
Example : two modules using the same struct name for different struct content.
So you should put in the "UserTypes" folder only types shared by different modules.

Example 1: simple type

Inside the monitoring file, your definition is
user32.dll|BOOL TranslateMessage(MSG *lpMsg)

And inside "UserTypes" or "UserTypes\user32.dll" directory, you must have an "MSG.txt" file with the following content :
  1. typedef struct tagMSG {
  2. HWND hwnd;
  3. UINT message;
  4. WPARAM wParam;
  5. LPARAM lParam;
  6. DWORD time;
  7. POINT pt;
  8. }MSG,*PMSG,*NPMSG,*LPMSG;

User Types file content / Syntax :

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 never used as a parameter, you could put subtypes in the same file, before the type definition, like in your source code.


Example 2: 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 other user 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"

Automatically load multiples struct definition at startup

User Types file content / Syntax
"_AutoLoadedTypes_.txt" file is present in the "\UserTypes\" directory and force preloading of some types.
if you want to preload some types, you can put directly the definition inside the file, or add a #include "MyTypeDef.txt" to it.
This is usefull if you have some file defining multiples type definition. This avoid one file per type.
An _AutoLoadedTypes_.txt file can be put in each sub directory of "\UserTypes\" ex: \UserTypes\MyApp.exe\_AutoLoadedTypes_.txt
This allow to keep the root file "\UserTypes\_AutoLoadedTypes_.txt" untouched.
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,X) // where X is a number
#pragma pack(pop,X) // where X is a number

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


WinApiOverride Specific Pragma
The following pragmas are not standard and WinApiOverride defined only

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

#pragma next_enum_size(X)
#pragma next_enum_size(X) // where X is a number which specifies the size of the enum in bytes
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;
    
In WinApiOverride detailed vue, 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;        
            ...
        };