Types of arguments

A type in the sense of OllyDbg is the way to decode doubleword to text. Internal OllyDbg database contains descriptions of hundreds of known functions, types and structures. For example, a function may have several arguments. Each argument can be a number, a constant, a combination of flags or binary fields, or a pointer to type or structure. Value returned by the function in register EAX also has some type.

Here is a typical Windows API function:

HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor);

It has three arguments: pen style, which is one of the constants PS_xxx defined somewhere in the API headers, integer pen width, and color, which is the combination of three components (red, green and blue) together with some additional information. CreatePen() returns GDI handle. And here is the description in the database:

STDFUNC GDI32.CreatePen
  PS_X       Style
  INT        Width
  COLORREF   Color
  RETURNS    HGDI
END

This is a standard API function that preserves EBX, EBP, ESI and EDI and removes its argument from the stack (STDFUNC). It is defined in GDI32.dll, so there is no change of confusion if function with the same name is defined elsewhere.

Type PS_X is just an enumeration. If value is unknown, it will be displayed as an integer:

TYPE PS_X
  IF     0.   "PS_SOLID"
  ELSEIF 1.   "PS_DASH"
  ELSEIF 2.   "PS_DOT"
  ELSEIF 3.   "PS_DASHDOT"
  ELSEIF 4.   "PS_DASHDOTDOT"
  ELSEIF 5.   "PS_NULL"
  ELSEIF 6.   "PS_INSIDEFRAME"
  ELSEIF 7.   "PS_USERSTYLE"
  ELSEIF 8.   "PS_ALTERNATE"
  ELSE        INT
  ENDIF
END

Width of the pen is just an integer. Type COLORREF is more complicated. First, there are several subfields that must be decoded separately. Second, it would be nice to decode frequently used colours as a plain text instead of cryptical RGB(128,128,0):

TYPE COLORREF
  IF     0x00000000  "<BLACK>"
  ELSEIF 0x00FFFFFF  "<WHITE>"
  ELSEIF 0x00800000  "<BLUE>"
  ELSEIF 0x00008000  "<GREEN>"
  ELSEIF 0x00808000  "<CYAN>"
  ELSEIF 0x00000080  "<RED>"
  ELSEIF 0x00800080  "<MAGENTA>"
  ELSEIF 0x00008080  "<BROWN>"
  ELSEIF 0x00C0C0C0  "<GRAY>"
  ELSEIF 0x00808080  "<DARKGRAY>"
  ELSEIF 0x00FF0000  "<LIGHTBLUE>"
  ELSEIF 0x0000FF00  "<LIGHTGREEN>"
  ELSEIF 0x00FFFF00  "<LIGHTCYAN>"
  ELSEIF 0x000000FF  "<LIGHTRED>"
  ELSEIF 0x00FF00FF  "<LIGHTMAGENTA>"
  ELSEIF 0x0000FFFF  "<YELLOW>"
  ELSE
    SELECT FIELD     0xFF000000
      IF EQ 2        "PALETTERGB"
      ELSE           "RGB"
      ENDIF
    ENDSEL
    SELECT FIELD     0x000000FF
      TEXT "("       UINT
    ENDSEL
    SELECT FIELD     0x0000FF00
      TEXT ","       UINT
    ENDSEL
    SELECT FIELD     0x00FF0000
      TEXT ","       UINT
    ENDSEL
    TEXT ")"
    SELECT FIELD     0xFF000000
      IF NE 0
        IF NE 2
          TEXT ", flags = "
          HEX
        ENDIF
      ENDIF
    ENDSEL
  ENDIF
END

Finally, function returns HGDI. This is the GDI handle that will be decoded by OllyDbg in a special way. And here is the result:

0042437C  6A 00        PUSH 0                        ; Color = <BLACK>
0042437D  6A 00        PUSH 0                        ; Width = 0
0042437F  6A 00        PUSH 0                        ; Style = PS_SOLID
00424381  E8 5EC40300  CALL <JMP.&GDI32.CreatePen>   ; GDI32.CreatePen


Prefixed names

To describe the type internally, OllyDbg uses prefixed names. A prefixed name is a UNICODE string, at most SHORTNAME wide characters long, where first character (prefix) is a combination of flags ARG_xxx and remaining characters are the name of this type in the database. By the way, the database is extendable and users may add their own descriptions.

Prefix consists of the following bits:

ARG_VALID Always set to avoid zero prefix, but otherwise ignored by decoding routines
ARG_POINTER Type is a pointer to another type or structure
ARG_TYPE Type. Can't be used together with ARG_STRUCT or ARG_DIRECT
ARG_STRUCT (Only allowed if ARG_POINTER is also set) Pointer to the structure. Can't be used together with ARG_TYPE or ARG_DIRECT
ARG_DIRECT Direct ASCII string, used only inside the .NET streams. Can't be used together with ARG_TYPE or ARG_STRUCT
ARG_OUT (Only allowed if ARG_POINTER is also set) Output parameter of the function, undefined on call
ARG_MARK Important parameter of the function, used to comment the function
ARG_ELLIPSYS Last obligatory argument of the function with variable number of arguments

Prefix bits always form valid ASCII/UNICODE character. In the above example, prefixed names have encodings @COLORREF, @INT, @PS_X and @HGDI.