Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Type Library (TLB) Data Dumper (without WinAPI) version 1.0

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Type Library (TLB) Data Dumper (without WinAPI) version 1.0

    "Type Library (TLB) Data Dumper (without WinAPI) version 1.0" conforms to
    "The Unofficial TypeLib Data Format Specification". The original version is now
    outdated and obsolete and should be ignored (and preferably deleted from the
    forums).

    The (67.3 KB) attached file is a zipped folder containing:
    1. The compiled EXE
    2. All source files
    3. A sample ODL file (Object Definition Language)
    4. A sample TLB file (TypeLib)
    5. A sample dump file (plain text)

    • "Type Library Dumper" displays detailed information about the
      contents of TypeLib data (TypeLib data is what tells an operating
      system how to link up COM objects).
    • It was written to determine the TypeLib format so the format could be
      documented, and also to give "bep" (Bin Edit Plus) the ability to decompile
      TypeLib data.
    • It is based largely on studies of code from the ReactOS project at:
      http://www.reactos.org/en/index.html
      The primary source file used was:
      ..\reactos\dll\win32\oleaut32\typelib.c


    Features:
    • Extracts TypeLib data from the resource sections of PE format
      files (EXE, DLL, OCX, OCA...) and also from TLB files, of course.
    • Automatic handling of files based on internal format regardless
      of file extensions
    • Drag-and-drop operation (puts the file's path into the textbox)
    • Commandline operation
    • It can open EXE's even while they're running
    • A "Study Mode" to help learn more details of the TypeLib format
      (see below).


    About the "Study Mode" Feature
    • Study Mode can be enabled with the "%Study" equate.
    • It provides for logging occurrences of any type of content encountered
    • It alerts the user of the first item of interest it finds with
      a messagebox.
    • Just add code as needed to identify values or flag bits that you want
      to research. Place the code between "#If %Def(%Study)" and "#EndIf"
      statements. Example:
      #If %Def(%Study)
      Note "3 Array(s) found"
      #EndIf
    • You can also set a minimum alert priority with the "%Priority" equate.
      It will only respond to log messages prefixed with a digit equal or above
      that priority. For example, in:
      Note "4(FuncRec.FKCCIC And &H040000) <> 0"
      ...the prefix "4" is the message's priority level.
    • It marks the output file with whatever is assigned to the "$StudyMark"
      equate to help locate any discovered items. The default value is "@@@: ".


    Notes on the Program:
    • The code retains many names and comments from the ReactOS code
      it was derived from which may be misleading.
    • Information about a few parts of the format was unavailable when
      this was written, resulting in some missing details.
    • Arrows ( ==> ) are used to indicate what offset values point to.
    • Almost all values are in hex format, including those with leading
      zeros, and those containing any non-decimal characters (A, B, C, D,
      E or F).
    • A double equals sign ( "==" ) is used to show decimal equivalents
      of hex values.
    • It only dumps the "MSFT" format files for now (no "SLTG")...
    • Values of "FFFFFFFF" ( -1 ) are generally invalid, but are often
      included in the dumps.
    • An EXE or DLL file can (but rarely does) contain multiple TypeLib
      resources. This program only dumps the first one it finds.
    • A dump file is about five to ten times the size of the original
      TypeLib data.


    Notes on the Format:
    • Array descriptors only exist for arrays with element counts specified
    • Duplicate functions have duplicate names and IDs, plus (invalid)
      offsets of -1 for their parameter names. They are (presumably) expected
      to be copied from the other (identical) function.


    All the code and text of "TheirCorp's Type Library Dumper" is GPL
    licensed by TheirCorp 2008.



    • TheirCorp's SourceForge project
      includes:
    • API Helper --- a code generator for the Win32 API
    • BinEditPlus --- a decompiler and more
    • ComHelper --- a code generator for the COM programming
    • "Flex" --- an editor with novel features
    • GDI Debug --- catches programming errors that could lead
      to resource leaks
    • Import Monitor --- (an API hook) Intercepts and monitors
      calls to imported functions
    • Intricately Mergeable Templates
    • Jellyfish Pro enhancer plugin (adds drag-and-drop and more..)
    • TheirEdit --- an editor for PowerBASIC code
    • TheirNote --- a KeyNote clone
    • TheirSheet --- a spreadsheet
    • SrcFrmt --- a source code formatter
    • Tooltipper --- a tooltip code generator


    PowerBASIC article in Wikipedia
    Attached Files
    TheirCorp's projects at SourceForge

    TheirCorp's website

    sigpic

  • #2
    The Source Code

    Code:
    "DisTypeLib.bas"
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    '	"DisTypeLib.bas"
    
    'This code is based on code from the ReactOS
    'project at: http://www.reactos.org/en/index.html
    'The primary source file used was:
    '	...reactos\dll\win32\oleaut32\typelib.c
    
    'So far, it only disassembles data with the "MSFT"
    'magic value (not the "SLTG" type yet).
    
    'It is intended to be integrated into bep (Bin
    'Edit Plus) and perhaps other sub-projects
    
    'This should have a TypeLib "diff" feature
    'to help learn more about its format.
    
    'This file is GPL 2008, by TheirCorp
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    #Compile Exe "DisTypeLib.exe"
    #Dim All
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    '%Debug		= 1 'enable/disable debugging code
    %Study		= 1 'enable/disable code to help study the format
    %Priority	= 0 'set minimum priority level for logging and alerts
    
    #If %Def(%Debug)
    #Tools On
    %ProfileOn		= 1
    
    Global dbg		As Long
    Global dbs		As String
    
    Sub zz()
    
    End Sub 'zz
    
    #Else
    	#Tools Off
    
    #EndIf
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    $Caption = "TheirCorp's Type Library Dumper"
    
    %GoBtn   = 1001
    %PathTxt = 1101
    %LogTxt  = 1102
    %FileLbl = 1103
    %MsgLbl  = 1104
    
    %LogLines = 8
    '%fo  	  = 10 'output file's number
    Macro fo = 10 'output file's number
    %IsOpen		= 0
    
    Global ghDlg		As Dword
    Global LocalPath	As String   'local path
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    Declare Function GetDroppedFile(ByVal hDrop As Long, fs As String) As Long
    Declare Function ProcessFile(fs As String) As Long
    Declare CallBack Function ShowDlgProc()
    Declare Sub UpdateLog(ps As String)
    Declare Function DisSltg(cs As String) As Dword
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    #Include "MSFT.bas"
    #Include "DisTypeLib.inc"
    #Include "GetTypeLibData.bas"
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    Declare Function GetResource( _
    	cs As String,       _
    	ByVal ird As IMAGE_RESOURCE_DIRECTORY Ptr, _
    	ByVal de As Dword,  _   'value to subtract from ".link" offsets's
    	ByVal ss As Dword,   _   'section size
    	ByVal Offset As Dword _   'offset to resource section
    	) As Long
    Declare Function GetTypeLibData(cs As String, fs As String) As Long
    
    Declare Function Locale(lcid As Long) As String
    Declare Function VarType(ByVal pn As Long) As String
    Declare Function tlName(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    Declare Function tlString(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    Declare Function DisFunction(cs As String, SegDir As MSFT_SegDir, ByVal pBase As Dword, ByVal nFunc As Long, ByVal nProp As Long) As Long
    Declare Function DisTypeLib(cs As String) As Dword
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    Sub UpdateLog(ps As String)
    Static ct   As Long
    Static ls   As String
    Static ts   As String
    
    	If Len(Command$) Then
    		'MsgBox ps
    
    	Else
    		Incr ct
    
    		If Len(ps) Then
    			'Control Get Text ghDlg, %LogTxt To ls
    			'Dialog DoEvents
    			ps = ps & $CrLf
    		Else
    			ct = 1
    			ls = ""
    			ts = ""
    		End If
    
    		If ct > %LogLines Then ts = Remain$(ts, $CrLf) & ps
    		ls = ls & ps
    
    		If Left$(ps, 5) = "Ready" Then
    			Control Set Text ghDlg, %LogTxt, LTrim$(Left$(ls, 32000), Any $CrLf)
    			Dialog DoEvents
    			Control Send ghDlg, %LogTxt, %EM_SETSEL, 65536, 65536
    			Dialog DoEvents
    			Control Send ghDlg, %LogTxt, %EM_SCROLLCARET, 0, 0
    			Dialog DoEvents
    		Else
    			Control Set Text ghDlg, %LogTxt, ts
    		End If
    
    	End If
    
    End Sub 'UpdateLog
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    'returns %true, if any files were received
    Function GetDroppedFile(ByVal hDrop As Long, fs As String) As Long
    Local ct  As Dword
    Local az  As Asciiz * %MAX_PATH
    
    	ct = DragQueryFile(hDrop, &HFFFFFFFF&, "", ByVal 0&)
    
    	If ct > 0 Then
    		az = Space$(%MAX_PATH)
    		ct = DragQueryFile(hDrop, 0, az, Len(az) - 1)
    		fs = Left$(az, ct)
    		Function = %True
    	End If
    
    End Function
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    'expects "fs" to contain the path and name
    'of either a PE or TLB format file
    'It determines which type it is automatically
    Function ProcessFile(fs As String) As Long
    Local n		As Long
    Local cs	As String
    Local ls	As String
    
    	If Len(Dir$(fs)) Then
    
    		n = GetTypeLibData(cs, fs)
    
    		If n Then
    
    			UpdateLog "Processing..."
    
    			'--------------------------------------
    			'open an output file for the disassembly
    			Try
    				#If %Def(%Study)
    					CurFile = fs
    					Note "" 'reset message counter
    				#EndIf
    				ls = Mid$(fs, InStr(-1, fs, "\") + 1)
    				ls = MCase$(Extract$(ls, ".")) & ".txt"
    				Open LocalPath & "\" & ls For Output As fo
    				UpdateLog "Output file: " & ls
    			Catch
    				UpdateLog "Error opening output file: " & ls
    				Exit Function
    			End Try
    
    			If n = 1 Then DisTypeLib(cs)
    
    		End If
    
    	Else
    		UpdateLog "Couldn't find: " & fs
    	End If
    
    	If FileAttr(fo, %IsOpen) Then Close# fo
    
    End Function 'ProcessFile
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    CallBack Function ShowDlgProc()
    Local  fs   As String
    
    #If %Def(%ProfileOn)
    	Profile "Profile.txt"
    #EndIf
    
    	Select Case As Long CbMsg
    
    		'Case %WM_INITDIALOG
    
    		Case %WM_NCACTIVATE
    			Static hWndSaveFocus  As Dword
    			If IsFalse CbWParam Then
    				hWndSaveFocus = GetFocus()
    			ElseIf hWndSaveFocus Then
    				SetFocus(hWndSaveFocus)
    				hWndSaveFocus = 0
    			End If
    
    		Case %WM_DROPFILES
    			If (GetDroppedFile(CbWParam, fs)) Then
    				Control Set Text ghDlg, %PathTxt, fs
    			End If
    			DragFinish CbWParam
    
    		Case %WM_COMMAND
    			Select Case As Long CbCtl
    				Case %GoBtn
    					If CbCtlMsg = %BN_CLICKED Or CbCtlMsg = 1 Then
    						Control Get Text ghDlg, %PathTxt To fs
    						UpdateLog ""
    						ProcessFile(fs)
    						UpdateLog "Ready..."
    					End If
    			End Select
    
    	End Select
    
    End Function
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    Function PBMain() As Long
    Local lRslt As Long
    
    #If %Def(%ProfileOn)
    	Profile "Profile.txt"
    #EndIf
    
    	'get and save the local path without a trailing backslash
    	LocalPath = String$(%MAX_PATH, $Nul)
    	GetModuleFileName(ByVal 0, ByVal StrPtr(LocalPath), %MAX_PATH)
    	LocalPath = Left$(LocalPath, InStr(-1, LocalPath, "\") - 1)
    
    
    	If Len(Command$) Then
    
    		ProcessFile(Command$)
    		MsgBox "Done"
    
    	Else
    
    		Dialog New %HWND_DESKTOP, $Caption, , , 256, 138, %WS_POPUP Or %WS_BORDER _
    			Or %WS_DLGFRAME Or %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX Or _
    			%WS_VISIBLE Or %DS_MODALFRAME Or %DS_SETFOREGROUND Or %DS_3DLOOK Or _
    			%DS_NOFAILCREATE Or %DS_SETFONT, %WS_EX_WINDOWEDGE Or _
    			%WS_EX_ACCEPTFILES Or %WS_EX_CONTROLPARENT Or %WS_EX_LEFT Or _
    			%WS_EX_LTRREADING Or %WS_EX_RIGHTSCROLLBAR, To ghDlg
    
    		Control Add Label,   ghDlg, %FileLbl, "&File:", 0, 4, 19, 10, %WS_CHILD Or _
    			%WS_VISIBLE Or %WS_TABSTOP Or %SS_RIGHT, %WS_EX_LEFT Or %WS_EX_LTRREADING
    
    		Control Add TextBox, ghDlg, %PathTxt, "", 20, 2, 233, 12
    
    		Control Add Button,  ghDlg, %GoBtn, "&Go", 220, 17, 32, 14, %WS_CHILD Or _
    			%WS_VISIBLE Or %WS_BORDER Or %WS_TABSTOP Or %BS_TEXT Or _
    			%BS_DEFPUSHBUTTON Or %BS_PUSHBUTTON Or %BS_CENTER Or %BS_VCENTER, _
    			%WS_EX_LEFT Or %WS_EX_LTRREADING
    
    		Control Add Label, ghDlg, %MsgLbl, "&Messages:", 2, 22, 39, 10
    
    		Control Add TextBox, ghDlg, %LogTxt, "", 2, 34, 252, 100, %WS_CHILD Or _
    			%WS_VISIBLE Or %WS_TABSTOP Or %WS_HSCROLL Or %WS_VSCROLL Or %ES_LEFT _
    			Or %ES_MULTILINE Or %ES_AUTOHSCROLL Or %ES_AUTOVSCROLL Or %ES_WANTRETURN, _
    			%WS_EX_CLIENTEDGE Or %WS_EX_LEFT Or %WS_EX_LTRREADING Or %WS_EX_RIGHTSCROLLBAR
    
    		Dialog Send ghDlg, %DM_SETDEFID, %GoBtn, 0
    		Control Set Focus ghDlg, %PathTxt
    
    		DragAcceptFiles ghDlg, %True 'Register window to accept dropped files.
    
    		Dialog Show Modal ghDlg, Call ShowDlgProc To lRslt
    
    		Function = lRslt
    
    	End If
    
    End Function
    
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    
    "GetTypeLibData.bas"
    
    '**************************************
    '   "GetTypeLibData.bas"
    
    
    'This file is GPL 2008, by TheirCorp
    '**************************************
    
    
    
    '**************************************
    'this is a re-entrant procedure
    'ird must always arrive pointing to a resource directory
    
    'For now, this assumes all offsets are relative to the start
    'of the resource section (opinions seem to differ on this)
    Function GetResource( _
    	cs As String,       _
    	ByVal ird As IMAGE_RESOURCE_DIRECTORY Ptr, _
    	ByVal de As Dword,  _   'value to subtract from ".link" offsets's
    	ByVal ss As Dword,   _   'section size
    	ByVal Offset As Dword _   'offset to resource section
    	) As Long
    
    Local n			As Long
    Local p			As Dword
    Local pirde		As IMAGE_RESOURCE_DATA_ENTRY Ptr
    Local irde		As IMAGE_RESOURCE_DIRECTORY_ENTRY Ptr
    Local ids		As IMAGE_RESOURCE_DIRECTORY_STRING
    
    Static fResult	As Long
    Static lvl		As Long	  'recursion level
    Static rp		As Dword  'resource pointer
    Static rid		As Dword
    Static typ		As Dword
    Static ns		As String
    
    	If lvl = 0 Then rp = StrPtr(cs) '= ird 'save pointer to start of resource section
    	Incr lvl
    
    	irde = ird + SizeOf(IMAGE_RESOURCE_DIRECTORY)
    
    	' The named entries are case insensitive strings, sorted in ascending order.
    	' The entries with 16-bit IDs follow these and are also sorted in ascending order.
    	For n = 1 To @ird.NumberOfNamedEntries + @ird.NumberOfIdEntries
    
    		If (n <= @ird.NumberOfNamedEntries) And (@irde.NameID And %IMAGE_RESOURCE_NAME_IS_STRING) Then
    			'the name is a string
    			p = rp + (@irde.NameID And &H7FFFFFFF)  'offset is relative to start of resource section
    
    			rid = 0 'assign invalid value as a flag
    			ns = Remove$(Peek$(p + 2, CvWrd(Peek$(p, 2)) * 2), $Nul) 'unicode string
    			If UCase$(ns) = "TYPELIB" Then fResult = 1 'found TypeLib data
    
    		ElseIf (n > @ird.NumberOfNamedEntries) And (@irde.NameID And %IMAGE_RESOURCE_NAME_IS_STRING) = 0 Then
    
    			'it's a 16-bit ID number
    			p = LoWrd(@irde.NameID)
    			If lvl = 1 Then
    				typ = p
    			ElseIf lvl = 2 Then
    				ns = ""
    				rid = p
    			ElseIf lvl = 3 Then
    			End If
    
    		End If
    
    		p = (@irde.Offset And &H7FFFFFFF)
    
    		If (@irde.Offset And %IMAGE_RESOURCE_DATA_IS_DIRECTORY) Then 'it's a subdirectory
    			p = GetResource(cs, rp + p, de, ss, Offset)
    
    		Else    'it's actual resource data
    
    			'get offset in PE file to ImageResourceDirectoryEntry structure
    			pirde = rp + p
    
    			If fResult = 1 Then
    				Incr fResult
    				'@pirde.OffsetToData is the RVA to the resource data
    				cs = Mid$(cs, @pirde.OffsetToData - de - Offset + 1, @pirde.Size)
    			End If
    
    		End If
    
    		If fResult = 2 Then Exit For
    		irde = irde + SizeOf(IMAGE_RESOURCE_DIRECTORY_ENTRY)
    
    	Next n
    
    	Decr lvl
    	If lvl Then
    		Function = ird
    	Else
    		Function = fResult
    		fResult = 0
    	End If
    
    End Function 'GetResource
    
    '***************************************
    ' gets TypeLib data from a PE file's resource section
    Function GetTypeLibData(cs As String, fs As String) As Long
    #Register All
    Local ff		As Long 'file handle
    Local n			As Long
    Local fTlb  	As Long
    Local DosHdr	As DosHeader
    Local pPH		As PEHeader Ptr
    Local si		As SectionInfo
    Local pOH		As OptHeader Ptr
    Local pSH		As SectionHeader Ptr
    Local pDD		As DataDir Ptr
    
    
    	'--------------------------------------
    	'get the Typelib data
    	Try
    
    		ff = FreeFile
    		Open fs For Binary Access Read Lock Shared As #ff
    		Get$ #ff, 2048, cs
    
    		'----------------------------------
    		'get PE signature if present
    		LSet DosHdr = cs
    		If (Left$(cs, 2) = $PeMZ) And (Mid$(cs, DosHdr.lfanew + 1, 4) = $PePE32) Then
    
    			Decr fTlb 'disable loading the file below
    			pPH = StrPtr(cs) + DosHdr.lfanew + 4
    			pOH = pPH + SizeOf(PEHeader)
    
    			'"pOH.NumberOfRvaAndSizes" is the number of entries, not the size of the array, as someone once wrote
    			If %ResourceSection > @pOH.NumberOfRvaAndSizes Then Exit Function
    
    			pDD = pOH + SizeOf(OptHeader) + ((%ResourceSection - 1) * SizeOf(DataDir))
    			si.dRVA = @pDD.RVA
    			si.dSize = @pDD.DirSize
    
    
    			'find the section which matches si.dRVA in the section table
    			pSH = pOH + SizeOf(OptHeader) + (@pOH.NumberOfRvaAndSizes * SizeOf(DataDir))
    			For n = 1 To @pPH.NumberOfSections
    
    				If (si.dRVA => @pSH.RVA) And (si.dRVA < @pSH.RVA + @pSH.SizeOfRawData) Then
    					si.SectName         = @pSH.SectName
    					si.VirtSize         = @pSH.VirtSize             'size of unpadded section
    					si.RVA              = @pSH.RVA                  '@pSH.RVA is the offset to section when loaded
    					si.RamAdd           = @pOH.ImageBase + @pSH.RVA 'section's RAM address (for example: &H401000)
    					si.SizeOfRawData    = @pSH.SizeOfRawData        'size after padding to section alignment
    					si.PtrToRawData     = @pSH.PtrToRawData         'zero-based file offset to section
    					si.StrPos           = @pSH.PtrToRawData + 1     'one-based file offset to section
    					si.EndPos           = si.StrPos + si.SizeOfRawData
    					si.Delta            = si.RVA - si.PtrToRawData  'value to subtract from RVAs to get file offsets
    					si.Characteristics  = @pSH.Characteristics
    
    					Exit For
    
    				End If
    
    				pSH = pSH + SizeOf(SectionHeader) 'advance pSH to next section header
    
    			Next n
    
    			'get TypeLib resource
    			Seek# ff, si.StrPos
    			Get$ #ff, si.SizeOfRawData, cs
    			If GetResource(cs, StrPtr(cs), si.Delta, si.SizeOfRawData, si.PtrToRawData) = 0 Then
    				Reset cs
    				UpdateLog "No TypeLib data found in: " & fs
    			End If
    
    		End If
    
    
    		If Left$(cs, 4) = "MSFT" Then 'it's a "tlb" (TypeLib) file
    			Incr fTlb
    			Function = 1
    		ElseIf Left$(cs, 4) = "SLTG" Then
    			Incr fTlb
    			Function = 2
    		End If
    
    		If fTlb > 0 Then
    			Seek# ff, 1
    			Get$ #ff, Lof(ff), cs
    		End If
    
    		Close# ff
    
    	Catch
    		UpdateLog "Error opening input file: " & fs
    		Exit Function
    	End Try
    
    End Function 'GetTypeLibData
    
    '***************************************
    "MSFT.bas"
    '****************************************
    '	"MSFT.bas"
    
    'This code is based on code from the ReactOS
    'project at: http://www.reactos.org/en/index.html
    'The primary source file used was:
    '	...reactos\dll\win32\oleaut32\typelib.c
    
    'So far, it only disassembles data with the "MSFT"
    'magic value (not the "SLTG" type yet).
    
    'It is intended to be integrated into bep (Bin
    'Edit Plus) and perhaps other sub-projects
    
    'This should have a TypeLib "diff" feature
    'to help learn more about its format.
    
    'This file is GPL 2008, by TheirCorp
    '****************************************
    
    
    '****************************************
    '	"Study-Mode" Code
    '****************************************
    #If %Def(%Study)
    
    $StudyMark		= "@@@: " 'to help find items of interest
    Global CurFile		As String
    
    'you can set a string's priority by prefixing
    'it with a digit from 0 through 9. The minimum
    'priority is determined by the value of %Priority
    Sub Note(ps As String)
    Local n		As Long
    Static ff	As Long
    Static ct	As Long
    
    	If Len(ps) = 0 Then
    		'close it each time to make sure it's accessible to a text viewer
    		Close# ff
    		ff = 0 : ct = 0
    	Else
    
    		If ff = 0 Then
    			ff = FreeFile
    			Open "Study.txt" For Append Lock Write As #ff
    			Print# ff,
    			Print# ff, "****************************************"
    			Print# ff, "	New File: "; CurFile
    		End If
    
    		n = Val(Left$(ps, 1)) 'get priority level
    		ps = LTrim$(ps, Any " 0123456789") 'remove priority digits
    
    		If ct = 0 Then 'alert the user, if the priority is high enough
    			If n => %Priority Then
    				'MsgBox "Found something of interest" & $CrLf & ps
    				Incr ct 'disable any further alerts
    			End If
    		End If
    
    		'print marker in output file to help find items of interest
    		'(this assumes that the last file opened was the output file)
    		Print# fo,
    		Print# fo, $StudyMark; ps
    
    		'maintain a log of findings
    		Print# ff, ps
    
    	End If
    
    End Sub 'Note
    
    #EndIf
    
    
    
    
    '********************************************************************************
    '					TypeLib-Specific Equates and Data Types
    '********************************************************************************
    
    'Note:	OAIDL.h says hRefType is a DWORD
    
    %HELPDLLFLAG	= &H0100
    
    
    '****************************************
    '	"Magic" Values
    '****************************************
    %MSFT_SIGNATURE		= &H05446534D '  "MSFT"
    %SLTG_SIGNATURE		= &H047544C53 '  "SLTG"
    
    
    '****************************************
    '	Equates for Translating Flags
    '		and Codes to Text
    '****************************************
    $SysKind		= "Win16,Win32,Macintosh"
    $VarFlags		= "ReadOnly,Source,Bindable,RequestEdit,DisplayBind,DefaultBind,Hidden,Restricted,DefaultCollelem,UiDefault,NonBrowsable,Replaceable,ImmediateBind"
    $TKind			= "Enum,Record,Module,Interface,Dispatch,Coclass,Alias,Union,Max"
    $TypeFlags		= "AppObject,CanCreate,Licensed,PredeclId,Hidden,Control,Dual,Nonextensible,Oleautomation,Restricted,Aggregatable,Replaceable,Dispatchable,ReverseBind"
    $ParamFlags		= "In,Out,LCID,RetVal,Opt,HasDefault,HasCustData"
    $CallConv		= "FastCall,CDecl,Pascal,MacPascal,StdCall,FPFastCall,SysCall,MPWCDecl,MPWPascal,Max"
    $InvoKind		= "Func,PropertyGet,PropertyPut,PropertyPutRef"
    $FuncKind		= "Virtual,PureVirtual,NonVirtual,Static,Dispatch"
    
    
    '****************************************
    '	Variable-Type Codes, Masks and Flags
    '****************************************
    %VT_Empty			= 0??
    %VT_Null			= 1??
    %VT_I2				= 2??
    %VT_I4				= 3??
    %VT_R4				= 4??
    %VT_R8				= 5??
    %VT_Cy				= 6??
    %VT_Date			= 7??
    %VT_BStr			= 8??
    %VT_Dispatch		= 9??
    %VT_Error			= 10??
    %VT_Bool			= 11??
    %VT_Variant			= 12??
    %VT_Unknown			= 13??
    %VT_Decimal			= 14??
    %VT_I1				= 16??
    %VT_UI1				= 17??
    %VT_UI2				= 18??
    %VT_UI4				= 19??
    %VT_I8				= 20??
    %VT_UI8				= 21??
    %VT_Int				= 22??
    %VT_UInt			= 23??
    %VT_Void			= 24??
    %VT_HResult			= 25??
    %VT_Ptr				= 26??
    %VT_SafeArray		= 27??
    %VT_CArray			= 28??
    %VT_UserDefined		= 29??
    %VT_LPStr			= 30??
    %VT_LPWStr			= 31??
    %VT_Record			= 36??
    %VT_FileTime		= 64??
    %VT_Blob			= 65??
    %VT_Stream			= 66??
    %VT_Storage			= 67??
    %VT_Streamed_Object	= 68??
    %VT_Stored_Object	= 69??
    %VT_Blob_Object		= 70??
    %VT_CF				= 71??
    %VT_ClsID			= 72??
    
    '	flags
    %VT_Bstr_Blob		= &H00FFF??
    %VT_Vector			= &H01000??
    %VT_Array			= &H02000??
    %VT_ByRef			= &H04000??
    %VT_Reserved		= &H08000??
    
    '	masks
    %VT_Illegal			= &H0FFFF??
    %VT_IllegalMasked	= &H00FFF??
    %VT_TypeMask		= &H00FFF??
    
    
    '****************************************
    '	Calling Conventions
    '****************************************
    %CC_FASTCALL			= 0
    %CC_CDECL				= 1
    %CC_MSCPASCAL			= 2
    %CC_PASCAL				= 2
    %CC_MACPASCAL			= 3
    %CC_STDCALL				= 4
    %CC_FPFASTCALL			= 5
    %CC_SYSCALL				= 6
    %CC_MPWCDECL			= 7
    %CC_MPWPASCAL			= 8
    %CC_MAX					= 9
    
    
    '****************************************
    '	Function Types
    '****************************************
    %FUNC_VIRTUAL			= 0
    %FUNC_PUREVIRTUAL		= 1
    %FUNC_NONVIRTUAL		= 2
    %FUNC_STATIC			= 3
    %FUNC_DISPATCH			= 4
    
    
    '****************************************
    '	Function Flags
    '****************************************
    %FUNCFLAG_FRESTRICTED		= &H00001
    %FUNCFLAG_FSOURCE			= &H00002
    %FUNCFLAG_FBINDABLE			= &H00004
    %FUNCFLAG_FREQUESTEDIT		= &H00008
    %FUNCFLAG_FDISPLAYBIND		= &H00010
    %FUNCFLAG_FDEFAULTBIND		= &H00020
    %FUNCFLAG_FHIDDEN			= &H00040
    %FUNCFLAG_FUSESGETLASTERROR	= &H00080
    %FUNCFLAG_FDEFAULTCOLLELEM	= &H00100
    %FUNCFLAG_FUIDEFAULT		= &H00200
    %FUNCFLAG_FNONBROWSABLE		= &H00400
    %FUNCFLAG_FREPLACEABLE		= &H00800
    %FUNCFLAG_FIMMEDIATEBIND  	= &H01000
    #If %Def(%MAC)
    %FUNCFLAG_FORCELONG			= 2147483647
    #Endif
    
    
    '****************************************
    '	Invocation Kinds
    '****************************************
    %INVOKE_FUNC			= 1
    %INVOKE_PROPERTYGET		= 2
    %INVOKE_PROPERTYPUT		= 4
    %INVOKE_PROPERTYPUTREF	= 8
    
    
    '****************************************
    '	Parameter Flags
    '****************************************
    %PARAMFLAG_NONE			= &H000
    %PARAMFLAG_FIN			= &H001
    %PARAMFLAG_FOUT			= &H002
    %PARAMFLAG_FLCID		= &H004
    %PARAMFLAG_FRETVAL		= &H008
    %PARAMFLAG_FOPT			= &H010
    %PARAMFLAG_FHASDEFAULT	= &H020
    %PARAMFLAG_FHASCUSTDATA	= &H040
    
    
    '****************************************
    '	System Kind
    '****************************************
    %SYS_WIN16		= 0
    %SYS_WIN32		= 1
    %SYS_MAC		= 2
    
    'SYS_WIN16 --- The target operating system for the type library is 16-bit Windows systems.
    'By default, data members are packed.
    
    'SYS_WIN32 --- The target operating system for the type library is 32-bit Windows systems.
    'By default, data members are naturally aligned (for example, 2-byte integers are aligned
    'on even-byte boundaries; 4-byte integers are aligned on quad-word boundaries, and so on).
    
    'SYS_MAC --- The target operating system for the type library is Apple Macintosh. By default,
    'all data members are aligned on even-byte boundaries.
    
    
    '****************************************
    '	Type-Kinds
    '****************************************
    %TKIND_ENUM			= 0
    %TKIND_RECORD		= 1
    %TKIND_MODULE		= 2
    %TKIND_INTERFACE	= 3
    %TKIND_DISPATCH		= 4
    %TKIND_COCLASS		= 5
    %TKIND_ALIAS		= 6
    %TKIND_UNION		= 7
    %TKIND_MAX			= 8
    
    
    '****************************************
    '	Type Flags
    '****************************************
    %TYPEFLAG_FAPPOBJECT		= &H00001
    %TYPEFLAG_FCANCREATE		= &H00002
    %TYPEFLAG_FLICENSED			= &H00004
    %TYPEFLAG_FPREDECLID		= &H00008
    %TYPEFLAG_FHIDDEN			= &H00010
    %TYPEFLAG_FCONTROL			= &H00020
    %TYPEFLAG_FDUAL				= &H00040
    %TYPEFLAG_FNONEXTENSIBLE	= &H00080
    %TYPEFLAG_FOLEAUTOMATION	= &H00100
    %TYPEFLAG_FRESTRICTED		= &H00200
    %TYPEFLAG_FAGGREGATABLE		= &H00400
    %TYPEFLAG_FREPLACEABLE		= &H00800
    %TYPEFLAG_FDISPATCHABLE		= &H01000
    %TYPEFLAG_FREVERSEBIND		= &H02000
    %TYPEFLAG_MASK				= %TYPEFLAG_FREVERSEBIND - 1
    
    '****************************************
    '	Variable Kinds
    '****************************************
    'not sure if these are ever used in MSFT format data
    '%VAR_PERINSTANCE	= 0
    '%VAR_STATIC		= %VAR_PERINSTANCE + 1
    '%VAR_CONST			= %VAR_STATIC + 1
    '%VAR_DISPATCH		= %VAR_CONST + 1
    %VAR_PERINSTANCE	= 0
    %VAR_STATIC			= 1
    %VAR_CONST			= 2
    %VAR_DISPATCH		= 3
    
    
    '****************************************
    '	Variable Flags
    '****************************************
    %VARFLAG_FREADONLY			= &H00001
    %VARFLAG_FSOURCE			= &H00002
    %VARFLAG_FBINDABLE			= &H00004
    %VARFLAG_FREQUESTEDIT		= &H00008
    %VARFLAG_FDISPLAYBIND		= &H00010
    %VARFLAG_FDEFAULTBIND		= &H00020
    %VARFLAG_FHIDDEN			= &H00040
    %VARFLAG_FRESTRICTED		= &H00080
    %VARFLAG_FDEFAULTCOLLELEM	= &H00100
    %VARFLAG_FUIDEFAULT			= &H00200
    %VARFLAG_FNONBROWSABLE		= &H00400
    %VARFLAG_FREPLACEABLE		= &H00800
    %VARFLAG_FIMMEDIATEBIND		= &H01000
    
    
    
    
    '****************************************
    '	TypeLib UDTs
    '****************************************
    
    
    Union TYPEDESCUNION
    	lptdesc		As Dword Ptr 'TYPEDESC Ptr
    	lpadesc		As Dword Ptr 'ARRAYDESC Ptr
    	hRefType	As Long 'hRefType
    End Union 'TYPEDESCUNION
    
    
    Type tagTYPEDESC
    	u	As TYPEDESCUNION
    	vt	As Long 'VARTYPE
    End Type 'TYPEDESC
    
    
    Type tagPARAMDESCEX
    	cBytes				As Dword 'ULONG
    	'varDefaultValue		As Variant 'VARIANTARG
    End Type 'tagPARAMDESCEX
    
    
    Type tagPARAMDESC
    	pParamDescEx	As tagPARAMDESCEX 'or a Ptr ?
    	fParam			As Word '(USHORT)
    End Type 'tagPARAMDESC
    
    
    Type tagIDLDESC
    	Res		As Dword 'Reserved
    	fIDL	As Word 'USHORT
    End Type tagIDLDESC
    
    
    Union ELEMDESCUNION
    	idldesc		As tagIDLDESC	'info for remoting the element
    	ParamDesc	As tagPARAMDESC	'info about the parameter
    End Union
    
    
    Type tagELEMDESC
    	tdesc	As tagTYPEDESC 'the type of the element
    	u		As ELEMDESCUNION
    End Type 'tagELEMDESC
    
    
    
    '	MSFT typelibs
    'These are TypeLibs created with ICreateTypeLib2 structure of the typelib type2 header
    'it is at the beginning of a type lib file
    Type TlbHeader
    	Magic1				As Long '&H5446534D "MSFT"								00
    	Magic2				As Long '&H00010002 version number?
    	oGUID				As Long 'position of libid in GUID table (should be,  else -1)
    	LCID				As Long 'locale id
    	LCID2				As Long '												10
    	fVar			As Long '(largely) unknown flags
    				  				'* the lower nibble is SysKind
    				  				'* bit 5 is set if a helpfile is defined
    				  				'* bit 8 is set if a help dll is defined
    
    	Version				As Long 'set with SetVersion()
    	Flags				As Long 'set with SetFlags()
    	nTypeInfo			As Long 'number of TypeInfo's							20
    	HelpStr				As Long 'offset to help string in string table
    	HelpStrCnt			As Long
    	HelpCntxt			As Long
    	nName				As Long 'number of names in name table					30
    	nChars				As Long 'characters in name table
    	oName				As Long 'offset of name in string table
    	HelpFile			As Long 'offset of helpfile in string table
    	CustDat				As Long 'if -1 no custom data, else it is offset		40
    					 	 		'in custom data/GUID offset table
    	Res1				As Long 'unknown always: &H20 (GUID hash size?)
    	Res2				As Long 'unknown always: &H80 (name hash size?)
    	oDispatch			As Long 'hRefType to IDispatch, or -1 if no IDispatch
    	nImpInfos			As Long 'number of ImpInfos								50
    	'oFileName			As Long 'offset to typelib file name in string table
    End Type 'TlbHeader
    
    
    'segments in the type lib file have a structure like this:
    Type SegDesc
    	Offs	As Long 'absolute offset in file
    	nLen	As Long 'length of segment
    	Res01	As Long 'unknown always -1
    	Res02	As Long 'unknown always &H0F in the header
    					 '&H03 in the TypeInfo_data
    End Type 'SegDesc
    
    
    '	segment directory
    Type MSFT_SegDir
    	pTypInfo			As SegDesc '1 - TypeInfo table
    	pImpInfo			As SegDesc '2 - table with info for imported types
    	pImpFiles			As SegDesc '3 - import libaries
    	pRefer				As SegDesc '4 - References table
    	pLibs				As SegDesc '5 - always exists, alway same size (&H80)
    						  			 '  - hash table with offsets to GUID?????
    	pGUID				As SegDesc '6 - all GUIDs are stored here together with
    						  			 '  - offset in some table????
    	Unk01				As SegDesc '7 - always created, always same size (&H0200)
    						  			 '  - contains offsets into the name table
    	pNames				As SegDesc '8 - name table
    	pStrings			As SegDesc '9 - string table
    	pTypDesc			As SegDesc 'A - type description table
    	pArryDesc			As SegDesc 'B - array descriptions
    	pCustData			As SegDesc 'C - data table, used for custom data and default
    				  					 '  - parameter values
    	pCDGuids			As SegDesc 'D - table with offsets for the GUIDs and into
    									 '  - the custom data table
    	Unk02				As SegDesc 'E - unknown
    	Unk03				As SegDesc 'F - unknown
    End Type 'MSFT_SegDir
    
    
    'type info data
    Type TypeInfo
    	TypeKind			As Byte	'TKIND_xxx
    	Align				As Byte	'alignment
    	Unk					As Integer	'unknown
    	oFunRec				As Long '	- points past the file, if no elements
    	Alloc				As Long '	Recommended (or required?) amount of memory to allocate for...?
    	Reconst				As Long '	size of reconstituted TypeInfo data
    	Res01				As Long '10 - always? 3
    	Res02				As Long '	- always? zero
    	nFuncs				As Integer ' - count of functions
    	nProps				As Integer ' - count of properties
    	Res03				As Long '   - always? zero
    	Res04				As Long '20 - always? zero
    	Res05				As Long '   - always? zero
    	Res06				As Long '   - always? zero
    	oGUID				As Long '   - position in GUID table
    	fType				As Long '30 - Typeflags
    	oName				As Long '   - offset in name table
    	Version				As Long '   - element version
    	DocStr				As Long	'   - offset of docstring in string tab
    	HelpStrCnt			As Long '40
    	HelpCntxt			As Long
    	oCustData			As Long	'   - offset in custom data table
    #If %Def(%WORDS_BIGENDIAN)		'
    	cVft		As Integer 'virtual table size, not including inherits
    	nImplTypes	As Integer 'number of implemented interfaces
    #Else
    	nImplTypes	As Integer 'number of implemented interfaces
    	cVft	As Integer 'virtual table size, not including inherits
    #endif
    	Unk03		As Long  '50 - size in bytes, at least for structures
    
    	Type1		As Long  '	- position in type description table
    						 '	- or in base interfaces
    						 '	- if coclass: offset in reftable
    						 '	- if interface: reference to inherited if
    						 '	- if module: offset to dllname in name table
    	Type2		As Long  '	- if &H8000, entry above is valid, else it is zero?
    	Res07		As Long  '	- always? 0
    	Res08		As Long  '60 - always? -1
    End Type 'TypeInfo
    
    
    
    'information on imported types
    Type ImportInfo
    	Count		As Integer 'count
    	Flags		As Byte 'if <> 0 then oGUID is an offset to GUID, else it's a TypeInfo index in the specified typelib
    	TypeKind	As Byte	' TKIND of reference
    	oImpFile	As Long 'offset in the Import File table
    	oGuid		As Long 'offset in GUID table or TypeInfo index (see bit 16 of Res0)
    End Type 'ImportInfo
    
    
    
    'information on imported files
    Type TlbImpLib
    	oGUID	As Long
    	LCID	As Long
    	MajVer	As Word
    	MinVer	As Word
    	cSize	As Word 'divide by 4 to get the length of the file name
    End Type 'TlbImpLib
    
    
    
    'Structure of the reference data
    Type RefRecord
    	'either offset in TypeInfo table, then it's a multiple of 4...
    	'or offset in the external reference table with an offset of 1
    	RefType				As Long
    	Flags				As Long '?
    	oCustData			As Long 'custom data
    	oNext				As Long 'next offset, -1 if last
    End Type 'RefRecord
    
    
    
    'this is how a GUID is stored
    Type GuidEntry
    	oGUID		As String * 16
    	' = -2 for a TypeLib GUID
    	'TypeInfo offset for TypeInfo GUID,
    	'Otherwise, the low two bits:
    	'	= 01 for an imported TypeInfo
    	'	= 10 for an imported TypeLib (used by imported TypeInfos)
    	hRefType	As Long
    	NextHash	As Long	'offset to next GUID in the hash bucket
    End Type 'GuidEntry
    
    
    
    'some data preceding entries in the name table
    Type NameIntro
    	'is -1 if name is for neither a TypeInfo,
    	'a variable, or a function (that is, name
    	'is for a typelib or a function parameter).
    	'otherwise is the offset of the first
    	'TypeInfo that this name refers to (either
    	'to the TypeInfo itself or to a member of
    	'the TypeInfo
    	hRefType	As Long
    
    	NextHash	As Long	'offset to next name in the hash bucket
    
    	'only lower 8 bits are valid,
    	'lower-middle 8 Bits are unknown (flags?),
    	'upper 16 Bits are hash code
    	cName		As Long
    End Type 'NameIntro
    
    
    'this is only here to illustrate the storage format for strings
    'Type TlbString
    '	nLen	As Word 'length of string
    '	zStr	As String * nLen 'text of string
    '	zPad	As String$(?, "W") 'pad to Dword alignment
    'End Type TlbString
    
    
    
    Type TYPEDESC 'a substitute for a tagTYPEDESC to simplify the code
    	v1	As Integer
    	v2	As Integer
    	v3	As Integer
    	v4	As Integer
    End Type 'TYPEDESC
    
    
    
    'type for arrays
    Type SafeArrayBound
    	nElements	As Dword
    	lLBound		As Long
    End Type 'SafeArrayBound
    
    Type ARRAYDESC
    	u			As TYPEDESCUNION
    	nDims		As Word
    	tVar		As Word 'VARTYPE
    	Bounds(0)	As SafeArrayBound
    End Type 'ARRAYDESC
    
    Type CArrayDesc
    	Desc	As ARRAYDESC
    	Bnd		As SafeArrayBound
    End Type
    
    
    
    'Custom data table entries are Dword aligned by padding with (usually) "W"
    'Type CustomData
    '	nLen				As Word 'length of nLen plus bData in Words
    '	cData(nLen - 1)		As Word	'
    'End Type 'CustomData
    
    
    
    'the custom data/GUID table directory has entries like this
    Type CDGuid
    	oGUID		As Long
    	oData		As Long
    	oNext		As Long 'next offset in the table, -1 if it's the last
    End Type 'CDGuid
    
    
    
    '	Function description data
    'SizeOf(FuncRecord) = 24 (required fields only)
    'These exist in arrays along with zero or more "PropRecord"
    'elements. Each array is preceded by a Dword stating the total
    'size of the array.
    '...ArraySize		As Long
    Type FuncRecord
    	RecSize				As Word 'record size, including optional fields and ParamInfo's
    	Unk1				As Word ' zero-based function number ?
    	DataType	 		As Integer 'data type returned by the function
    
    	'If the .Flags MSB = 1, then the low byte is valid. So far it seems
    	'to always be valid, except for pointers. When MSB = 1, the low byte
    	'is the code for a data type that's equivalent to or compatible with
    	'that in .DataType.
    	Flags				As Integer
    
    	Res1				As Long 'always(?) zero
    
    #If %Def(%WORDS_BIGENDIAN)
    	cFuncDesc			As Integer 'size of reconstituted FUNCDESC and related structs
    	oVtable				As Integer 'offset in vtable
    #Else
    	oVtable				As Integer 'offset in vtable
    	cFuncDesc			As Integer 'size of reconstituted FUNCDESC and related structs
    #endif
    
    	'The bits in FKCCIC have the following meanings:
    	'0 - 2 = function kind (eg virtual)
    	'3 - 6 = Invocation kind
    	'7 means custom data is present
    	'8 - 11 = calling convention
    	'12 means one or more parameters have a default value
    	'+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    	'|               |               |               |               |
    	'| 15  14  13  12| 11  10  9   8 | 7   6   5   4 | 3   2   1   0 |
    	'+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    	'|   |   |   | D |   |   |   |   | C |   |   |   |   |   |   |   |
    	'|   |   |   | e |    Calling    | u |  Invocation   | Function  |
    	'|   |   |   | f |  Convention   | s |    Kind       |   Kind    |
    	'|   |   |   | V |               | t |               |           |
    	'|   |   |   | a |               | D |               |           |
    	'|   |   |   | l |               | a |               |           |
    	'|   |   |   | u |               | t |               |           |
    	'|   |   |   | e |   |   |   |   | a |   |   |   |   |   |   |   |
    	'+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    	FKCCIC				As Long
    
    	nParams				As Integer 'parameter count
    	Unk2				As Integer
    
    '****** Optional attribute fields, the number of them is variable ******
    	'HelpCntxt			As Long '0
    	'oHelpStr			As Long '1
    	'oEntry				As Long '2 either offset in string table or numeric as it is
    	'res2				As Long '3 unknown (-1)
    	'res3				As Long '4 unknown (-1)
    	'HelpStrCnt			As Long '5
    	'****** these are present if bit 12 of FKCCIC is set ******
    	'oCustData			As Long '6 custom data for function
    	'ArgCustData(0)		As Long '7 custom data per argument
    End Type 'FuncRecord
    
    
    
    'Parameter info: one per argument
    Type ParamInfo
    	DataType	As Integer
    	Flags		As Integer
    	oName		As Long
    	fParam		As Long
    End Type 'ParamInfo
    
    
    
    '	Property description data
    ' The size of the required fields of the PropRecord structure
    'is 20 (= &H14)
    'These exist in arrays along with zero or more "FuncRecord"
    'elements. Each array is preceded by a Dword stating the total
    'size of the array.
    Type PropRecord
    	RecSize				As Word 'size of PropRecord
    	PropNum				As Word 'Property number?
    	DataType	 		As Integer 'data type of the variable
    	Flags				As Integer 'VarFlags
    #If %Def(%WORDS_BIGENDIAN)
    	cVarDesc			As Integer 'size of reconstituted VARDESC and related structs
    	VarKind	  			As Integer 'VarKind
    #Else
    	VarKind				As Integer 'VarKind --- %VAR and %VarFlags
    	cVarDesc			As Integer 'size of reconstituted VARDESC and related structs
    #endif
    	OffsValue			As Long 'value of the variable or the offset in the data structure
    	'***** End of required fields *****
    
    	'Optional attribute fields, the number of them is variable
    	'and are determined from the record size (if there's room
    	'for it, then it's there...)
    	Unk					As Long
    	HelpCntxt			As Long
    	oHelpStr			As Long
    	Res				 	As Long 'unknown (-1)
    	oCustData			As Long 'custom data for variable
    	HelpStrCnt			As Long
    End Type 'PropRecord
    
    
    
    '****************************************
    
    'Declare Function Locale(lcid As Long) As String
    'Declare Function VarType(ByVal pn As Long) As String
    'Declare Function tlName(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    'Declare Function tlString(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    'Declare Function DisSltg(cs As String) As Dword
    'Declare Function DisFunction(cs As String, SegDir As MSFT_SegDir, ByVal pBase As Dword, ByVal nFunc As Long, ByVal nProp As Long) As Long
    'Declare Function DisTypeLib(cs As String, ps As String) As Dword
    
    '****************************************
    
    Function Locale(lcid As Long) As String
    
    Data &H0401, ARA, Arabic Saudi Arabia
    Data &H0801, ARI, Arabic Iraq
    Data &H0C01, ARE, Arabic Egypt
    Data &H1001, ARL, Arabic Libya
    Data &H1401, ARG, Arabic Algeria
    Data &H1801, ARM, Arabic Morocco
    Data &H1C01, ART, Arabic Tunisia
    Data &H2001, ARO, Arabic Oman
    Data &H2401, ARY, Arabic Yemen
    Data &H2801, ARS, Arabic Syria
    Data &H2C01, ARJ, Arabic Jordan
    Data &H3001, ARB, Arabic Lebanon
    Data &H3401, ARK, Arabic Kuwait
    Data &H3801, ARU, Arabic U.A.E.
    Data &H3C01, ARH, Arabic Bahrain
    Data &H4001, ARQ, Arabic Qatar
    Data &H0402, "BGR", Bulgarian Bulgaria
    Data &H0403, CAT, Catalan Spain
    Data &H0404, CHT, Chinese Taiwan
    Data &H0804, CHS, Chinese PRC
    Data &H0C04, ZHH, Chinese Hong Kong
    Data &H1004, ZHI, Chinese Singapore
    Data &H1404, ZHM, Chinese Macau
    Data &H0405, CSY, Czech Czech Republic
    Data &H0406, DAN, Danish Denmark
    Data &H0407, GERMANY, German Germany
    Data &H0807, DES, German Switzerland
    Data &H0C07, DEA, German Austria
    Data &H1007, DEL, German Luxembourg
    Data &H1407, DEC, German Liechtenstein
    Data &H0408, ELL, Greek Greece
    Data &H0409, USA, English United States
    Data &H0809, ENG, English United Kingdom
    Data &H0C09, ENA, English Australia
    Data &H1009, ENC, English Canada
    Data &H1409, ENZ, English New Zealand
    Data &H1809, ENI, English Ireland
    Data &H1C09, ENS, English South Africa
    Data &H2009, ENJ, English Jamaica
    Data &H2409, ENB, English Caribbean
    Data &H2809, ENL, English Belize
    Data &H2C09, ENT, English Trinidad
    Data &H3009, ENW, English Zimbabwe
    Data &H3409, ENP, English Philippines
    Data &H040A, SPAIN, Spanish Spain
    Data &H080A, ESM, Spanish Mexico
    Data &H0C0A, ESN, Spanish Spain (International Sort)
    Data &H100A, ESG, Spanish Guatemala
    Data &H140A, ESC, Spanish Costa Rica
    Data &H180A, ESA, Spanish Panama
    Data &H1C0A, ESD, Spanish Dominican Republic
    Data &H200A, ESV, Spanish Venezuela
    Data &H240A, ESO, Spanish Colombia
    Data &H280A, ESR, Spanish Peru
    Data &H2C0A, ESS, Spanish Argentina
    Data &H300A, ESF, Spanish Ecuador
    Data &H340A, ESL, Spanish Chile
    Data &H380A, ESY, Spanish Uruguay
    Data &H3C0A, ESZ, Spanish Paraguay
    Data &H400A, ESB, Spanish Bolivia
    Data &H440A, ESE, Spanish El Salvador
    Data &H480A, ESH, Spanish Honduras
    Data &H4C0A, ESI, Spanish Nicaragua
    Data &H500A, ESU, Spanish Puerto Rico
    Data &H040B, FIN, Finnish Finland
    Data &H040C, FRANCE, French France
    Data &H080C, FRB, French Belgium
    Data &H0C0C, FRC, French Canada
    Data &H100C, FRS, French Switzerland
    Data &H140C, FRL, French Luxembourg
    Data &H180C, FRM, French Monaco
    Data &H040D, HEB, Hebrew Israel
    Data &H040E, HUN, Hungarian Hungary
    Data &H040F, ISL, Icelandic Iceland
    Data &H0410, ITALY, Italian Italy
    Data &H0810, ITS, Italian Switzerland
    Data &H0411, JAPAN, Japanese Japan
    Data &H0412, KOREA, Korean Korea
    Data &H0413, NLD, Dutch Netherlands
    Data &H0813, NLB, Dutch Belgium
    Data &H0414, NOR, Norwegian Norway (Bokmål)
    Data &H0814, NON, Norwegian Norway (Nynorsk)
    Data &H0415, PLK, Polish Poland
    Data &H0416, BRAZIL, Portuguese Brazil
    Data &H0816, PTG, Portuguese Portugal
    Data &H0418, ROM, Romanian Romania
    Data &H0419, RUS, Russian Russia
    Data &H041A, HRV, Croatian Croatia
    Data &H081A, SRL, Serbian Serbia (Latin)
    Data &H0C1A, SRB, Serbian Serbia (Cyrillic)
    Data &H041B, SKY, Slovak Slovakia
    Data &H041C, SQI, Albanian Albania
    Data &H041D, SVE, Swedish Sweden
    Data &H081D, SVF, Swedish Finland
    Data &H041E, THA, Thai Thailand
    Data &H041F, TRK, Turkish Turkey
    Data &H0420, URP, Urdu Pakistan
    Data &H0421, IND, Indonesian Indonesia
    Data &H0422, UKR, Ukrainian Ukraine
    Data &H0423, BEL, Belarusian Belarus
    Data &H0424, SLV, Slovene Slovenia
    Data &H0425, ETI, Estonian Estonia
    Data &H0426, LVI, Latvian Latvia
    Data &H0427, LTH, Lithuanian Lithuania
    Data &H0827, LTC, Classic Lithuanian Lithuania
    Data &H0429, FAR, Farsi Iran
    Data &H042A, VIT, Vietnamese Viet Nam
    Data &H042B, HYE, Armenian Armenia
    Data &H042C, AZE, Azeri Azerbaijan (Latin)
    Data &H082C, AZE, Azeri Azerbaijan (Cyrillic)
    Data &H042D, EUQ, Basque Spain
    Data &H042F, MKI, Macedonian Macedonia
    Data &H0436, AFK, Afrikaans South Africa
    Data &H0437, KAT, Georgian Georgia
    Data &H0438, FOS, Faeroese Faeroe Islands
    Data &H0439, HIN, Hindi India
    Data &H043E, MSL, Malay Malaysia
    Data &H083E, MSB, Malay Brunei Darussalam
    Data &H043F, KAZ, Kazak Kazakstan
    Data &H0441, SWK, Swahili Kenya
    Data &H0443, UZB, Uzbek Uzbekistan (Latin)
    Data &H0843, UZB, Uzbek Uzbekistan (Cyrillic)
    Data &H0444, TAT, Tatar Tatarstan
    Data &H0445, BEN, Bengali India
    Data &H0446, PAN, Punjabi India
    Data &H0447, GUJ, Gujarati India
    Data &H0448, ORI, Oriya India
    Data &H0449, TAM, Tamil India
    Data &H044A, TEL, Telugu India
    Data &H044B, KAN, Kannada India
    Data &H044C, MAL, Malayalam India
    Data &H044D, "ASM", Assamese India
    Data &H044E, MAR, Marathi India
    Data &H044F, SAN, Sanskrit India
    Data &H0457, KOK, Konkani India
    Data &H0000, Language-Neutral, Language-Neutral
    Data &H0400, Process Default Language, Process Default Language
    
    Local n		As Long
    
    	For n = 1 To DataCount Step 3
    		If lcid = Val(Read$(n)) Then
    			Function = Read$(n + 2)
    			Exit For
    		End If
    	Next n
    
    End Function 'Locale
    
    '****************************************
    
    Function VarType(ByVal pn As Long) As String
    Local n		As Long
    Local ls	As String
    
    Data "Empty=0"
    Data "Null=1"
    Data "I2=2"
    Data "I4=3"
    Data "R4=4"
    Data "R8=5"
    Data "Cy=6"
    Data "Date=7"
    Data "BStr=8"
    Data "Dispatch=9"
    Data "Error=10"
    Data "Bool=11"
    Data "Variant=12"
    Data "Unknown=13"
    Data "Decimal=14"
    Data
    Data "I1=16"
    Data "UI1=17"
    Data "UI2=18"
    Data "UI4=19"
    Data "I8=20"
    Data "UI8=21"
    Data "Int=22"
    Data "UInt=23"
    Data "Void=24"
    Data "HResult=25"
    Data "Ptr=26"
    Data "SafeArray=27"
    Data "CArray=28"
    Data "UserDefined=29"
    Data "LPStr=30"
    Data "LPWStr=31"
    Data , , ,
    Data "Record=36"
    '	end of continuous sequence
    Data "FileTime=64"
    Data "Blob=65"
    Data "Stream=66"
    Data "Storage=67"
    Data "Streamed_Object=68"
    Data "Stored_Object=69"
    Data "Blob_Object=70"
    Data "CF=71"
    Data "ClsID=72"
    'Data "Bstr_Blob=4095"
    
    	pn = pn And %VT_TypeMask
    	If pn <= 36 Then
    		n = pn + 1
    	Else
    		For n = 37 To DataCount
    			If Val(Remain$(Read$(n), "=")) = pn Then Exit For
    		Next n
    	End If
    
    	ls = Extract$(Read$(n), "=")
    	Function = IIf$(Len(ls), "VT_" & ls, "(Unknown)")
    
    End Function 'VarType
    
    '****************************************
    'offs = zero-based offset into the GUID table
    Function tlGuid(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    
    	If offs => 0 Then
    		Function = GuidTxt$(Mid$(cs, SegDir.pGUID.Offs + offs + 1, 16))
    	End If
    
    End Function 'tlGuid
    
    '****************************************
    'offs = zero-based offset into the name table
    Function tlName(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    Local NameInt		As NameIntro
    
    	If offs => 0 Then
    		offs = SegDir.pNames.Offs + offs + 1
    		LSet NameInt = Mid$(cs, offs)
    		Function = $Dq & Mid$(cs, offs + SizeOf(NameIntro), NameInt.cName And &H0FF) & $Dq
    	End If
    
    End Function 'tlName
    
    '****************************************
    'offs = zero-based offset into the string table
    Function tlString(cs As String, SegDir As MSFT_SegDir, ByVal offs As Long) As String
    
    	If offs => 0 And offs < Len(cs) Then
    		offs = SegDir.pStrings.Offs + offs + 1
    		Function = $Dq & Mid$(cs, offs + 2, CvWrd(cs, offs)) & $Dq
    	End If
    
    End Function 'tlString
    
    
    '****************************************
    'cs:		TypeLib data
    'SegDir:	the segment directory
    'pBase:		the zero-based offset to the FuncRec
    'nFunc:		number of functions
    'nProp:		number of properties
    'fo:		file handle
    Function DisFunction(cs As String, SegDir As MSFT_SegDir, ByVal pBase As Dword, ByVal nFunc As Long, ByVal nProp As Long) As Long
    Local d				As Long
    Local i				As Long
    Local j				As Long
    Local n				As Long
    Local ub			As Long
    Local p				As Dword
    Local pTmp			As Dword
    Local iElem			As Long
    Local nAttr			As Long
    Local ArraySize		As Long
    Local oParamInfo	As Long
    Local oDefValue		As Long
    
    Local ls			As String
    Local FuncRec		As FuncRecord
    Local ParmInfo		As ParamInfo
    Local ElemDesc		As tagELEMDESC
    Local ParamDesc		As tagPARAMDESC
    Local NameInt		As NameIntro
    Local PropRec		As PropRecord
    
    
    	p = pBase
    	ArraySize = CvDwd(cs, pBase + 1)
    	Print# fo,
    	Print# fo, "	Function record array size:	"; Hex$(ArraySize, 8)
    	p = p + 5 'advance past the "ArraySize" value
    
    	'----------------------------------------
    	'	Other function and property data
    	n = nFunc + nProp
    	If n > 0 Then
    		ub = n - 1
    		pTmp = StrPtr(cs) + pBase + ArraySize + 4
    		ReDim IdElem(ub)	As Long At pTmp
    
    		pTmp = pTmp + (4 * n)
    		ReDim oName(ub)		As Long At pTmp
    
    		pTmp = pTmp + (4 * n)
    		ReDim Refer(ub)		As Long At pTmp
    	End If
    
    
    	If nFunc Then
    
    		Print# fo,
    		Print# fo, "	----------------------------------------"
    		Print# fo, "				Functions:"
    
    		For i = 1 To nFunc
    
    			LSet FuncRec = Mid$(cs, p)
    
    			Print# fo, "	----------------------------------------"
    			Print# fo, "	ID:			"; Hex$(IdElem(iElem), 8); " =="; Str$(IdElem(iElem))
    			Print# fo, "	Name:		"; Hex$(oName(iElem), 8); " ==> "; tlName(cs, SegDir, oName(iElem))
    			Print# fo, "	Reference:	"; Hex$(Refer(iElem), 8) 'offset to the corresponding function record
    			Incr iElem
    			Print# fo, "	Record size:	"; Hex$(FuncRec.RecSize, 4)
    			Print# fo, "	Unknown 1:		"; Hex$(FuncRec.Unk1, 4)
    			Print# fo, "	Flags:			"; Hex$(FuncRec.Flags, 4); IIf$(FuncRec.Flags < 0, " = " & VarType(FuncRec.Flags), "")
    			Print# fo, "	DataType:		"; Hex$(FuncRec.DataType, 4); " = " & VarType(FuncRec.DataType)
    
    #If %Def(%Study)
    			Print# fo,
    			Print# fo, "	Reserved 1:		"; Hex$(FuncRec.Res1, 8)
    #EndIf
    
    			Print# fo, "	Vtable offset:	"; Hex$(FuncRec.oVtable, 4)
    			Print# fo, "	Func Desc Size:	"; Hex$(FuncRec.cFuncDesc, 4)
    
    
    			'	FKCCIC
    			'The bits in FKCCIC have the following meanings:
    			'0 - 2 = function kind (eg virtual)
    			'3 - 6 = Invocation kind
    			'7 means custom data is present
    			'8 - 11 = calling convention
    			'12 means one or more parameters have a default value
    			Print# fo,
    			Print# fo, "	FKCCIC (raw):	"; Hex$(FuncRec.FKCCIC, 8)
    			If (FuncRec.FKCCIC And &H01000) Then Print# fo, "		Default value(s) present"
    			If (FuncRec.FKCCIC And &H040000) Then Print# fo, "		oEntry is numeric"
    			If (FuncRec.FKCCIC And &H080) Then Print# fo, "		Custom data present"
    
    			d = FuncRec.FKCCIC And &H0F00
    			Shift Right d, 8
    			Print# fo, "		Calling convention:	"; Hex$(d, 2); " = " & Parse$($CallConv, d + 1)
    
    			d = FuncRec.FKCCIC And &H078 'this is a bit field
    			Shift Right d, 3
    			Print# fo, "		Invocation kind:	"; Hex$(d, 2); " = ";
    			For n = 4 To 1 Step -1
    				If (d And %INVOKE_PROPERTYPUTREF) Then
    					Print# fo, Parse$($InvoKind, n);
    					If (d And &H07) Then Print# fo, ", ";
    				End If
    				Shift Left d, 1
    			Next n
    			Print# fo,
    
    			d = FuncRec.FKCCIC And 7
    			Print# fo, "		Function kind:		"; Hex$(d, 2); " = " & Parse$($FuncKind, d + 1)
    
    
    			'	Algorithm
    			'1) Dim the ParamInfo array at the end of the available space
    			'2) If (FKCCIC And &H1000) then Dim an array of default values just before the ParamInfo array
    			'3) Assume anything preceding the above arrays is the function's optional data
    			Print# fo,
    			n = FuncRec.nParams
    			Print# fo, "	Number of parameters:	"; Hex$(n, 4); " =="; Str$(n)
    
    #If %Def(%Study)
    			Print# fo, "	Unknown 2:		"; Hex$(FuncRec.Unk2, 4)
    #EndIf
    
    			oParamInfo = p + FuncRec.RecSize - (n * SizeOf(ParamInfo)) 'must be one-based
    			oDefValue = oParamInfo
    
    			'If (FuncRec.FKCCIC And &H01000) Then 'there might be default values present
    			If (FuncRec.FKCCIC And &H01000) And (n > 0) Then 'there might be default values present
    				oDefValue = oDefValue - (n * 4)
    				ReDim DefVal(n - 1)		As Long At StrPtr(cs) + oDefValue - 1 'must be zero-based
    			End If
    
    
    			'Dim array for the function's optional data, if any
    			ub = (((oDefValue - SizeOf(FuncRecord)) - p) \ 4) - 1
    			If ub => 0 Then
    
    				Print# fo, "		----------------------------------------"
    				Print# fo, "		Optional Data:"
    				ReDim OptData(ub)	As Long At StrPtr(cs) + p + SizeOf(FuncRecord) - 1 'must be zero-based
    
    				Print# fo, "		HelpContext:		"; Hex$(OptData(0), 8)
    				If ub < 1 Then Exit If
    
    				Print# fo, "		HelpString:			"; Hex$(OptData(1), 8);
    				Print# fo, " ==> " & tlString(cs, SegDir, OptData(1))
    				If ub < 2 Then Exit If
    
    				Print# fo, "		Entry:				"; Hex$(OptData(2), 8)
    
    #If %Def(%Study)
    				If ub < 3 Then Exit If
    
    				Print# fo, "		Reserved09:	"; Hex$(OptData(3), 8)
    				If ub < 4 Then Exit If
    
    				Print# fo, "		Reserved0A:	"; Hex$(OptData(4), 8)
    #EndIf
    				If ub < 5 Then Exit If
    
    				Print# fo, "		HelpStringContext:	"; Hex$(OptData(5), 8)
    				If ub < 6 Then Exit If
    
    				Print# fo, "		Custom Data:		"; Hex$(OptData(6), 8)
    
    			End If
    			Print# fo,
    
    
    			For j = 0 To n - 1
    
    				LSet ParmInfo = Mid$(cs, oParamInfo)
    				Print# fo, "		----------------------------------------"
    				Print# fo, "		Parameter number:	"; Str$(j + 1)
    				Print# fo, "		DataType:			"; Hex$(ParmInfo.DataType, 4); IIf$(ParmInfo.DataType => 0, " = " & VarType(ParmInfo.DataType), "")
    				Print# fo, "		Flags:				"; Hex$(ParmInfo.Flags, 4); " = "; VarType(ParmInfo.Flags)
    				Print# fo, "		Name:				"; Hex$(ParmInfo.oName, 8); " ==> "; tlName(cs, SegDir, ParmInfo.oName)
    				Print# fo, "		ParamFlags:			"; Hex$(ParmInfo.fParam, 8); " =	";
    				If ParmInfo.fParam Then
    					d = ParmInfo.fParam
    					For n = 7 To 1 Step -1 ' 7 = ParseCount($ParamFlags)
    						If (d And %PARAMFLAG_FHASCUSTDATA) Then
    							Print# fo, Parse$($ParamFlags, n);
    							If (d And &H03F) Then Print# fo, ", ";
    						End If
    						Shift Left d, 1
    					Next n
    					Print# fo,
    				Else
    					Print# fo, "(none)"
    				End If
    
    				'If (ParmInfo.fParam And %PARAMFLAG_FHASDEFAULT) Then
    				If (UBound(DefVal) => 0) And (ParmInfo.fParam And %PARAMFLAG_FHASDEFAULT) Then
    
    					If DefVal(j) < 0 Then 'the default value is in the lower three bytes
    						DefVal(j) = DefVal(j) And &H0FFFFFF
    					Else 'it's an offset into the CustomData table
    						DefVal(j) = Cvl(cs, SegDir.pCustData.Offs + DefVal(j) + 3)
    					End If
    					Print# fo, "		Default Value:		"; Hex$(DefVal(j), 8); " =="; Str$(DefVal(j))
    
    				End If
    
    				oParamInfo = oParamInfo + SizeOf(ParamInfo)
    
    			Next j
    
    			p = p + FuncRec.RecSize
    
    		Next i
    
    	End If 'nFunc
    
    
    
    	'do the properties
    	If nProp Then
    
    		Print# fo,
    		Print# fo, "	----------------------------------------"
    		Print# fo, "		 Properties:"
    
    		For i = 1 To nProp
    
    			LSet PropRec = Mid$(cs, p)
    
    			Print# fo, "	----------------------------------------"
    			Print# fo, "	ID:			"; Hex$(IdElem(iElem), 8); " =="; Str$(IdElem(iElem))
    			Print# fo, "	Name:		"; Hex$(oName(iElem), 8); " ==> "; tlName(cs, SegDir, oName(iElem))
    			Print# fo, "	Reference:	"; Hex$(Refer(iElem), 8) 'offset to the corresponding function record
    			Incr iElem
    			Print# fo, "	Record size (low-byte):	"; Hex$(PropRec.RecSize, 4)
    			Print# fo, "	Property number?:		"; Hex$(PropRec.PropNum, 4)
    			Print# fo, "	Flags:					"; Hex$(PropRec.Flags, 4); IIf$(PropRec.Flags < 0, " = " & VarType(PropRec.Flags), "")
    			Print# fo, "	DataType:				"; Hex$(PropRec.DataType, 4); " = "; VarType(PropRec.DataType)
    
    			Print# fo, "	Variable kind:			"; Hex$(PropRec.VarKind, 4); " = ";
    			d = PropRec.VarKind
    			For n = 13 To 1 Step -1 ' 13 = ParseCount($VarFlags)
    				If (d And %VARFLAG_FIMMEDIATEBIND) Then
    					Print# fo, Parse$($VarFlags, n);
    					If (d And &H0FFF) Then Print# fo, ", ";
    				End If
    				Shift Left d, 1
    			Next n
    			Print# fo,
    
    			Print# fo, "	Variable desc size:		"; Hex$(PropRec.cVarDesc, 4)
    			Print# fo, "	Value/Offset:			"; Hex$(PropRec.OffsValue, 8)
    
    #If %Def(%Study)
    			Print# fo, "	Unknown:				"; Hex$(PropRec.Unk, 8)
    #EndIf
    
    			If PropRec.RecSize > 20 Then '20 = (5 * SizeOf(Long))
    
    				Print# fo, "	HelpContext:			"; Hex$(PropRec.HelpCntxt, 8)
    
    				If PropRec.RecSize > 24 Then '24 = (6 * SizeOf(Long))
    					Print# fo, "	HelpString:	"; Hex$(PropRec.oHelpStr, 8);
    					Print# fo, " ==> "; tlString(cs, SegDir, PropRec.oHelpStr)
    
    					If PropRec.RecSize > 32 Then '32 = (8 * SizeOf(Long))
    
    						If PropRec.RecSize > 36 Then '36 = (9 * SizeOf(Long))
    #If %Def(%Study)
    							Print# fo, "	Reserved:			"; Hex$(PropRec.Res, 8)
    #EndIf
    							Print# fo, "	HelpStringContext:	"; Hex$(PropRec.HelpStrCnt, 8)
    						End If
    
    					End If
    
    				End If
    
    			End If
    
    			Print# fo,
    			p = p + PropRec.RecSize
    
    		Next i
    
    	End If 'nProp
    
    
    #If %Def(%Study)
    	'----------------------------------------
    	'	Dump arrays of function and property: IDs, names and references
    	'----------------------------------------
    	' This is redundant, since the information is printed along with the
    	'functions and properties they pertain to.
    	n = nFunc + nProp
    	If n > 0 Then
    
    		iElem = 0
    
    		If nFunc Then
    			Print# fo,
    			Print# fo, "	----------------------------------------"
    			Print# fo, "		 Other Function Data:"
    		End If
    
    		For iElem = 0 To ub Step 1
    
    			If n = nProp Then 'the functions are done, so do the properties
    				Print# fo,
    				Print# fo, "	----------------------------------------"
    				Print# fo, "		 Other Property Data:"
    			End If
    			Decr n
    
    			'ID number of the function or property
    			Print# fo, "	----------------------------------------"
    			Print# fo, "	ID:			"; Hex$(IdElem(iElem), 8); " =="; Str$(IdElem(iElem))
    
    			'offset to names in the name table
    			Print# fo, "	Name:		"; Hex$(oName(iElem), 8);
    			Print# fo, " ==> "; tlName(cs, SegDir, oName(iElem))
    
    			'offset to the corresponding function record
    			Print# fo, "	Reference:	"; Hex$(Refer(iElem), 8)
    			Print# fo,
    
    		Next iElem
    
    	End If
    
    #EndIf
    
    	'Function =
    
    End Function 'DisFunction
    
    '****************************************
    'cs contains the TypeLib data
    'ls contains the name of the source file
    Function DisTypeLib(cs As String) As Dword
    Local d			 As Long
    Local i			 As Long
    Local n			 As Long
    Local p			 As Long
    Local fName		 As Long 'TypeLib file name flag
    Local TlbHdr	 As TlbHeader
    Local SegDir	 As MSFT_SegDir
    Local TypInfo	 As TypeInfo
    Local ImpInfo	 As ImportInfo
    Local IFileInfo	 As TlbImpLib
    Local RefRec	 As RefRecord
    Local GuidEnt	 As GuidEntry
    Local NameInt	 As NameIntro
    Local TypDsc	 As TYPEDESC 'a simplified substitute for a tagTYPEDESC
    Local AryDsc	 As ARRAYDESC
    Local SafBnd	 As SafeArrayBound
    
    Local ls		As String
    
    
    	'--------------------------------------
    	'print the TypeLib Header
    	LSet TlbHdr = cs
    
    	'get the segment directory in advance
    	fName = IIf&((TlbHdr.fVar And %HELPDLLFLAG), 4, 0)
    	p = SizeOf(TlbHdr) + (4 * (TlbHdr.nTypeInfo)) + fName + 1
    	LSet SegDir = Mid$(cs, p)
    
    
    	Print# fo, "*************************"
    	Print# fo, "TypeLib Header"
    	Print# fo, "*************************"
    	Print# fo, "Magic 1:		"; Hex$(TlbHdr.Magic1, 8); " = "; Left$(cs, 4)	'&H5446534D """MSFT"""
    	Print# fo, "Magic 2:		"; Hex$(TlbHdr.Magic2, 8)	'&H00010002 version number?
    
    	'position of libid in guid table (should be, else -1)
    	Print# fo, "GUID:			"; Hex$(TlbHdr.oGUID, 8); " ==> "; tlGuid(cs, SegDir, TlbHdr.oGUID)
    
    	Print# fo, "Locale ID:		"; Hex$(TlbHdr.lcid, 8); " = "; Locale(TlbHdr.lcid) 'locale id
    	Print# fo, "Locale ID 2:	"; Hex$(TlbHdr.lcid2, 8)
    
    	'fVar (largely unknown):
    	'	* the lower nibble is SysKind
    	'	* bit 5 is set if a helpfile is defined
    	'	* bit 8 is set if a help dll is defined
    	Print# fo, "VarFlags:		"; Hex$(TlbHdr.fVar, 8)
    	Print# fo, "	System:		"; Parse$($SysKind, (TlbHdr.fVar And 7) + 1)
    	Print# fo, "	Help file"; IIf$((TlbHdr.fVar And 16), " ", " not "); "specified"
    	Print# fo, "	Help file is"; IIf$((TlbHdr.fVar And 256), " ", " not "); "in a DLL"
    
    	Print# fo, "Version:	"; Hex$(TlbHdr.version, 8)
    	Print# fo, "Flags:		"; Hex$(TlbHdr.Flags, 8)
    
    	Print# fo, "TypeInfo count:	"; Hex$(TlbHdr.nTypeInfo, 8); " =="; Str$(TlbHdr.nTypeInfo)	'number of TypeInfo's
    
    	Print# fo, "HelpString:			"; Hex$(TlbHdr.HelpStr, 8);	'position of HelpString in stringtable
    	Print# fo, " ==> "; tlString(cs, SegDir, TlbHdr.HelpStr)
    
    	Print# fo, "HelpStringContext:	"; Hex$(TlbHdr.HelpStrCnt, 8)
    	Print# fo, "HelpContext:		"; Hex$(TlbHdr.HelpCntxt, 8)
    
    	Print# fo, "Name Table:"
    	Print# fo, "	Names count:	"; Hex$(TlbHdr.nName, 8); " =="; Str$(TlbHdr.nName)	'number of names in name table
    	Print# fo, "	Characters:		"; Hex$(TlbHdr.nChars, 8); " =="; Str$(TlbHdr.nChars)	'number of characters in name table
    
    	Print# fo,
    	Print# fo, "TypeLib Name:	"; Hex$(TlbHdr.oName, 8); " ==> "; tlName(cs, SegDir, TlbHdr.oName) 'offset of name in name table
    	Print# fo, "Helpfile:		"; Hex$(TlbHdr.HelpFile, 8); " ==> "; tlString(cs, SegDir, TlbHdr.HelpFile) 'position of helpfile in stringtable
    
    	'if -1 no custom data, else it is offset in custom data/guid offset table
    	Print# fo, "Custom data offset:	"; Hex$(TlbHdr.CustDat, 8)
    
    #If %Def(%Study)
    	Print# fo, "Reserved1:	"; Hex$(TlbHdr.Res1, 8)		'unknown always: &H20 (guid hash size?)
    	Print# fo, "Reserved2:	"; Hex$(TlbHdr.Res2, 8)		'unknown always: &H80 (name hash size?)
    #EndIf
    
    	Print# fo, "IDispatch:			"; Hex$(TlbHdr.oDispatch, 8) 'hRefType to IDispatch, or -1 if no IDispatch
    	Print# fo, "ImportInfo count:	"; Hex$(TlbHdr.nImpInfos, 8); " =="; Str$(TlbHdr.nImpInfos) 'number of ImpInfos
    
    	p = SizeOf(TlbHdr) + 1
    	If fName Then
    		d = CvDwd(cs, p)
    		Print# fo, "TypeLib file name:			"; Hex$(d, 8); " ==> "; tlString(cs, SegDir, d)
    	End If
    
    	'--------------------------------------
    	'print the (TypeInfo ?) offsets
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "Offsets to TypeInfo Data"
    	Print# fo, "*************************"
    	p = p + fName
    	For n = 1 To TlbHdr.nTypeInfo
    		Print# fo, Hex$(CvDwd(cs, p), 8)
    		p = p + 4
    		If p => Len(cs) Then Exit For
    	Next n
    
    
    	'--------------------------------------
    	'print the segment directory contents
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "Segment Directory (Segment name: Offset, Length)..."
    	Print# fo, "*************************"
    	Print# fo, "Type Info Table:		"; Hex$(SegDir.pTypInfo.Offs, 8); ", "; Hex$(SegDir.pTypInfo.nLen, 8)
    	Print# fo, "Import Info:			"; Hex$(SegDir.pImpInfo.Offs, 8); ", "; Hex$(SegDir.pImpInfo.nLen, 8)
    	Print# fo, "Imported Libraries:		"; Hex$(SegDir.pImpFiles.Offs, 8); ", "; Hex$(SegDir.pImpFiles.nLen, 8)
    	Print# fo, "References Table:		"; Hex$(SegDir.pRefer.Offs, 8); ", "; Hex$(SegDir.pRefer.nLen, 8)
    	Print# fo, "Lib Table:				"; Hex$(SegDir.pLibs.Offs, 8); ", "; Hex$(SegDir.pLibs.nLen, 8)
    	Print# fo, "GUID Table:				"; Hex$(SegDir.pGUID.Offs, 8); ", "; Hex$(SegDir.pGUID.nLen, 8)
    	Print# fo, "Unknown 01:				"; Hex$(SegDir.Unk01.Offs, 8); ", "; Hex$(SegDir.Unk01.nLen, 8)
    	Print# fo, "Name Table:				"; Hex$(SegDir.pNames.Offs, 8); ", "; Hex$(SegDir.pNames.nLen, 8)
    	Print# fo, "String Table:			"; Hex$(SegDir.pStrings.Offs, 8); ", "; Hex$(SegDir.pStrings.nLen, 8)
    	Print# fo, "Type Descriptors:		"; Hex$(SegDir.pTypDesc.Offs, 8); ", "; Hex$(SegDir.pTypDesc.nLen, 8)
    	Print# fo, "Array Descriptors:		"; Hex$(SegDir.pArryDesc.Offs, 8); ", "; Hex$(SegDir.pArryDesc.nLen, 8)
    	Print# fo, "Custom Data:			"; Hex$(SegDir.pCustData.Offs, 8); ", "; Hex$(SegDir.pCustData.nLen, 8)
    	Print# fo, "GUID Offsets:			"; Hex$(SegDir.pCDGuids.Offs, 8); ", "; Hex$(SegDir.pCDGuids.nLen, 8)
    	Print# fo, "Unknown 02:				"; Hex$(SegDir.Unk02.Offs, 8); ", "; Hex$(SegDir.Unk02.nLen, 8)
    	Print# fo, "Unknown 03:				"; Hex$(SegDir.Unk03.Offs, 8); ", "; Hex$(SegDir.Unk03.nLen, 8)
    
    
    #If %Def(%Study)
    
    	Local fAlert		As Long
    	ReDim pSegTmp(14) As SegDesc At VarPtr(SegDir)
    	For i = 0 To 14
    
    		If pSegTmp(i).Res01 <> -1 Then
    			Print# fo, "!!!"
    			Incr fAlert
    		End If
    
    		If pSegTmp(i).Res02 <> &H0F Then
    			Print# fo, "!!!"
    			Incr fAlert
    		End If
    
    		If fAlert = 1 Then
    			MsgBox "Interesting Reserved value found"
    			Incr fAlert
    		End If
    
    	Next i
    
    	'If fAlert Then
    	Print# fo,
    	Print# fo, "@@@:	Reserved Fields"
    	Print# fo, "Segment name:	Res01, Res02..."
    	Print# fo, "*************************"
    	Print# fo, "Type Info Table:		"; Hex$(SegDir.pTypInfo.Res01, 8); ", "; Hex$(SegDir.pTypInfo.Res02, 8)
    	Print# fo, "Import Info:			"; Hex$(SegDir.pImpInfo.Res01, 8); ", "; Hex$(SegDir.pImpInfo.Res02, 8)
    	Print# fo, "Imported Libraries:		"; Hex$(SegDir.pImpFiles.Res01, 8); ", "; Hex$(SegDir.pImpFiles.Res02, 8)
    	Print# fo, "References Table:		"; Hex$(SegDir.pRefer.Res01, 8); ", "; Hex$(SegDir.pRefer.Res02, 8)
    	Print# fo, "Lib Table:				"; Hex$(SegDir.pLibs.Res01, 8); ", "; Hex$(SegDir.pLibs.Res02, 8)
    	Print# fo, "GUID Table:				"; Hex$(SegDir.pGUID.Res01, 8); ", "; Hex$(SegDir.pGUID.Res02, 8)
    	Print# fo, "Unknown 01:				"; Hex$(SegDir.Unk01.Res01, 8); ", "; Hex$(SegDir.Unk01.Res02, 8)
    	Print# fo, "Name Table:				"; Hex$(SegDir.pNames.Res01, 8); ", "; Hex$(SegDir.pNames.Res02, 8)
    	Print# fo, "String Table:			"; Hex$(SegDir.pStrings.Res01, 8); ", "; Hex$(SegDir.pStrings.Res02, 8)
    	Print# fo, "Type Descriptors:		"; Hex$(SegDir.pTypDesc.Res01, 8); ", "; Hex$(SegDir.pTypDesc.Res02, 8)
    	Print# fo, "Array Descriptors:		"; Hex$(SegDir.pArryDesc.Res01, 8); ", "; Hex$(SegDir.pArryDesc.Res02, 8)
    	Print# fo, "Custom Data:			"; Hex$(SegDir.pCustData.Res01, 8); ", "; Hex$(SegDir.pCustData.Res02, 8)
    	Print# fo, "Custom Data/GUID's:		"; Hex$(SegDir.pCDGuids.Res01, 8); ", "; Hex$(SegDir.pCDGuids.Res02, 8)
    	Print# fo, "Unknown 02:				"; Hex$(SegDir.Unk02.Res01, 8); ", "; Hex$(SegDir.Unk02.Res02, 8)
    	Print# fo, "Unknown 03:				"; Hex$(SegDir.Unk03.Res01, 8); ", "; Hex$(SegDir.Unk03.Res02, 8)
    	Print# fo,
    	'End If
    
    #EndIf
    
    
    	'--------------------------------------
    	'check two entries to be sure we found it
    	If SegDir.pTypInfo.Res02 <> &H0F Or SegDir.pImpInfo.Res02 <> &H0F Then
    		UpdateLog("Can't find the table directory")
    		Exit Function
    	End If
    
    
    
    	'**************************************
    	'	Print the data from the segments
    	'**************************************
    
    	'--------------------------------------
    	'print the TypeInfo structures
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "TypeInfo Data..."
    	Print# fo, "*************************"
    	i = 0
    	p = SegDir.pTypInfo.Offs + 1
    	n = p + SegDir.pTypInfo.nLen
    	Do Until p => n
    
    		Incr i
    		Print# fo, "-------------------------"
    		Print# fo, "TypeInfo number:	"; Format$(i)
    		LSet TypInfo = Mid$(cs, p)
    
    		Print# fo, "Type kind:	"; Hex$((TypInfo.TypeKind And 7?), 2); " = "; Parse$($TKind, (TypInfo.TypeKind And 7?) + 1)
    		d = TypInfo.Align : Shift Right d, 3
    		Print# fo, "	Alignment: ("; Hex$(TypInfo.Align, 2); "/8) = "; Hex$(d, 2)
    
    		'(function records are printed near the end of the TypeInfo section)
    
    		Print# fo, "Memory to allocate:		"; Hex$(TypInfo.Alloc, 8)
    		Print# fo, "Reconstituted Size:		"; Hex$(TypInfo.Reconst, 8)
    
    #If %Def(%Study)
    		Print# fo, "Reserved 01:	"; Hex$(TypInfo.Res01, 8)
    		Print# fo, "Reserved 02:	"; Hex$(TypInfo.Res02, 8)
    #EndIf
    
    		'counts of functions and properties
    		Print# fo,
    		Print# fo, "Function count:	"; Hex$(TypInfo.nFuncs, 4); " =="; Str$(TypInfo.nFuncs)
    		Print# fo, "Property count:	"; Hex$(TypInfo.nProps, 4); " =="; Str$(TypInfo.nProps)
    
    #If %Def(%Study)
    		Print# fo, "Reserved 03:	"; Hex$(TypInfo.Res03, 8)
    		Print# fo, "Reserved 04:	"; Hex$(TypInfo.Res04, 8)
    		Print# fo, "Reserved 05:	"; Hex$(TypInfo.Res05, 8)
    		Print# fo, "Reserved 06:	"; Hex$(TypInfo.Res06, 8)
    #EndIf
    
    		Print# fo, "GUID:	"; Hex$(TypInfo.oGUID, 8); " ==> "; tlGuid(cs, SegDir, TypInfo.oGUID)
    
    		Print# fo, "Type Flags:	"; Hex$(TypInfo.fType, 8); " = ";
    		d = TypInfo.fType 'this is a bit field
    		For n = 14 To 1 Step -1
    			If (d And %TYPEFLAG_FREVERSEBIND) Then
    				Print# fo, Parse$($TypeFlags, n);
    				If (d And %TYPEFLAG_MASK) Then Print# fo, ", ";
    			End If
    			Shift Left d, 1
    		Next n
    		Print# fo,
    
    
    		Print# fo, "Name:	"; Hex$(TypInfo.oName, 8); " ==> "; tlName(cs, SegDir, TypInfo.oName)
    		Print# fo, "Version:	"; Hex$(TypInfo.version, 8)
    
    		Print# fo, "Doc String:	"; Hex$(TypInfo.DocStr, 8);
    		Print# fo, " ==> "; tlString(cs, SegDir, TypInfo.DocStr)
    
    		Print# fo, "HelpStringContext:	"; Hex$(TypInfo.HelpStrCnt, 8)
    		Print# fo, "HelpContext:		"; Hex$(TypInfo.HelpCntxt, 8)
    
    		Print# fo,
    		Print# fo, "Custom data offset:		"; Hex$(TypInfo.oCustData, 8)
    		Print# fo, "Implemented interfaces:	"; Hex$(TypInfo.nImplTypes, 4); " =="; Str$(TypInfo.nImplTypes)
    		Print# fo, "Virtual table size:		"; Hex$(TypInfo.cVft, 4)
    		Print# fo, "Unknown 03:				"; Hex$(TypInfo.Unk03, 8)
    
    		'position in type description table or in base interfaces
    		'if coclass:	offset in reftable
    		'if interface:	reference to inherited interface
    		'if module:		offset to DLL name in name table
    
    #If %Def(%Study)
    		Select Case (TypInfo.TypeKind And &H0F)
    			'Case %TKIND_ENUM
    			'Case %TKIND_RECORD
    			'Case %TKIND_MODULE 'offset to DLL name in string table
    			'Case %TKIND_INTERFACE 'reference to inherited interface?
    			'Case %TKIND_DISPATCH
    			'Case %TKIND_COCLASS 'offset in reftable
    			Case %TKIND_ALIAS
    				Note "TKIND_ALIAS"
    			Case %TKIND_UNION
    				Note "TKIND_UNION"
    			'Case %TKIND_MAX
    			'Case Else
    
    		End Select
    #EndIf
    
    		'Print# fo, "Type1:	"; Hex$(TypInfo.Type1, 8)
    		Select Case TypInfo.TypeKind
    
    			'Case %TKIND_ENUM
    
    			'Case %TKIND_RECORD
    
    			Case %TKIND_MODULE 'offset to DLL name in string table
    				Print# fo, "DLL Name:	"; Hex$(TypInfo.Type1, 8); " ==> ";
    				If TypInfo.Type1 => 0 Then Print# fo, tlName(cs, SegDir, TypInfo.Type1)
    
    			Case %TKIND_INTERFACE 'reference to inherited interface?
    				Print# fo, "Inherited interface?:	"; Hex$(TypInfo.Type1, 8)
    
    			'Case %TKIND_DISPATCH
    
    			Case %TKIND_COCLASS 'offset in reftable
    				Print# fo, "Reference table offset:	"; Hex$(TypInfo.Type1, 8)
    
    			Case %TKIND_ALIAS 'the following is partly translated ReactOS code
    
    					If TypInfo.Type1 < 0 Then
    						d = TypInfo.Type1 And %VT_TYPEMASK
    					Else 'get index into Lib Table?
    						d = TypInfo.Type1 \ 8 '?
    					End If
    
    					If TypInfo.Type1 = %VT_UserDefined Then 'do RefType
    					End If
    
    			'Case %TKIND_UNION
    
    			'Case %TKIND_MAX
    
    			Case Else
    				Print# fo, "DataType1:	"; Hex$(TypInfo.Type1, 8)
    
    		End Select
    
    		'if &H8000, entry above is valid, else it is zero?
    		Print# fo, "DataType2:	"; Hex$(TypInfo.Type2, 8)
    
    #If %Def(%Study)
    		Print# fo, "Reserved 7:	"; Hex$(TypInfo.Res07, 8)
    		Print# fo, "Reserved 8:	"; Hex$(TypInfo.Res08, 8)
    #EndIf
    
    		Print# fo,
    		Print# fo, "Records offset:	"; Hex$(TypInfo.oFunRec, 8)
    		If TypInfo.oFunRec < Len(cs) Then 'do function/property records
    			DisFunction(cs, SegDir, TypInfo.oFunRec, TypInfo.nFuncs, TypInfo.nProps)
    		End If
    
    		p = p + SizeOf(TypInfo)
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print ImportInfo ?
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "ImportInfo"
    	Print# fo, "*************************"
    	i = 0
    	p = SegDir.pImpInfo.Offs + 1
    	n = p + SegDir.pImpInfo.nLen
    	Do Until p => n
    
    		Incr i
    		LSet ImpInfo = Mid$(cs, p)
    		Print# fo, "--------------------------------------------"
    		Print# fo, "Import Info number:	"; Format$(i)
    		Print# fo, "Count:				"; Format$(ImpInfo.Count)
    		Print# fo, "Offset in import file table:	"; Hex$(ImpInfo.oImpFile, 8)
    
    		If (ImpInfo.Flags And 1?) Then
    			Print# fo, "GUID:	"; Hex$(ImpInfo.oGuid, 8); " ==> "; tlGuid(cs, SegDir, ImpInfo.oGuid)
    		Else
    			Print# fo, "TypeInfo index:	"; Hex$(ImpInfo.oGuid, 8); " =="; Str$(ImpInfo.oGuid)
    		End If
    
    		Print# fo, "Type:	"; Parse$($TKind, ImpInfo.TypeKind)
    
    		p = p + SizeOf(ImpInfo)
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print Imported Type Libs
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "Imported Type Libs"
    	Print# fo, "*************************"
    	p = SegDir.pImpFiles.Offs + 1
    	n = p + SegDir.pImpFiles.nLen
    	Do Until p => n
    		LSet IFileInfo = Mid$(cs, p)
    		Print# fo, "--------------------------------------------"
    		Print# fo, "GUID:			"; Hex$(IFileInfo.oGUID, 8); " ==> "; tlGuid(cs, SegDir, IFileInfo.oGuid)
    		Print# fo, "Locale ID?:		"; Hex$(IFileInfo.LCID, 8); " = "; Locale(IFileInfo.LCID)
    		Print# fo, "Major version:	"; Hex$(IFileInfo.MajVer, 4)
    		Print# fo, "Minor version:	"; Hex$(IFileInfo.MinVer, 4)
    
    		d = IFileInfo.cSize
    		Shift Right d, 2
    		Print# fo, "Size = 		"; Hex$(IFileInfo.cSize, 4); "/4 = "; Hex$(d, 4)
    		Print# fo, "File name:	"; Mid$(cs, p + SizeOf(TlbImpLib), d)
    
    		p = p + ((SizeOf(TlbImpLib) + IFileInfo.cSize + 3) And Not 3) 'advance to next one
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print References Table
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "References Table"
    	Print# fo, "*************************"
    	p = SegDir.pRefer.Offs + 1
    	n = p + SegDir.pRefer.nLen
    	Do Until p => n
    		LSet RefRec = Mid$(cs, p)
    		Print# fo, "--------------------------------------------"
    
    		'if it's a multiple of 4, it's an offset in the TypeInfo table,
    		'otherwise it's an offset in the external reference table with
    		'an offset of 1
    		Print# fo, "Reference type:	"; Hex$(RefRec.RefType, 8);
    		If (RefRec.RefType And &H03) Then
    			Print# fo, "	==> (External Reference Table)"
    		Else
    			Print# fo, "	==> (TypeInfo)"
    		End If
    
    		Print# fo, "Flags:			"; Hex$(RefRec.Flags, 8)
    		If RefRec.oCustData => 0 Then Print# fo, "Custom data:	"; Hex$(RefRec.oCustData, 8)
    		If RefRec.oNext => 0 Then Print# fo, "Next offset:	"; Hex$(RefRec.oNext, 8)
    		p = p + SizeOf(RefRecord)
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print "Lib Table"	(unknown format)
    	'always exists, always the same size (&H80)
    	'...hash table with offsets to GUID?
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "Lib Table (offsets into GUID table)"
    	Print# fo, "*************************"
    	p = SegDir.pLibs.Offs + 1
    	n = p + SegDir.pLibs.nLen
    	Do Until p => n
    		d = Cvl(cs, p)
    		If d => 0 Then Print# fo, Hex$(d, 8)
    		p = p + 4
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print GUID table
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "GUID Table"
    	Print# fo, "*************************"
    	p = SegDir.pGUID.Offs + 1
    	n = p + SegDir.pGUID.nLen
    	Do Until p => n
    
    		LSet GuidEnt = Mid$(cs, p)
    		Print# fo, "--------------------------------------------"
    		Print# fo, "GUID:	"; GuidTxt$(GuidEnt.oGUID)
    		'	The meaning of .hRefType:
    		' = -2 for a TypeLib GUID
    		'TypeInfo offset for TypeInfo GUID,
    		'Otherwise, the low two bits:
    		'	= 01 for an imported TypeInfo
    		'	= 10 for an imported TypeLib (used by imported TypeInfos)
    		Print# fo, "Href Type:	"; Hex$(GuidEnt.hRefType, 8);
    		If GuidEnt.hRefType = -2 Then
    			Print# fo, " = TypeLib GUID"
    		ElseIf (GuidEnt.hRefType And 3) = 1 Then
    			Print# fo, " = Imported TypeInfo"
    		ElseIf (GuidEnt.hRefType And 3) = 2 Then
    			Print# fo, " = Imported TypeLib"
    		Else
    			Print# fo, " = Offset?"
    		End If
    
    		Print# fo, "Next hash:	"; Hex$(GuidEnt.NextHash, 8)
    		p = p + SizeOf(GuidEntry)
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print "Unknown 01" (length is "always" &H200)
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, """Unknown 01"" --- Table with Offsets into the Name Table"
    	Print# fo, "*************************"
    	p = SegDir.Unk01.Offs + 1
    	n = p + SegDir.Unk01.nLen
    	Do Until p => n
    		d = Cvl(cs, p)
    		If d => 0 Then Print# fo, Hex$(d, 8)
    		p = p + 4
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print Name Table
    	'(this keeps the offset in p zero-based)
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "Name Table"
    	Print# fo, "*************************"
    	p = SegDir.pNames.Offs
    	n = p + SegDir.pNames.nLen
    	Do Until p => n
    
    		LSet NameInt = Mid$(cs, p + 1)
    		Print# fo, "--------------------------------------------"
    		If NameInt.hRefType <> -1 Then Print# fo, "Offset:			"; Hex$(NameInt.hRefType, 8)
    		Print# fo, "Next hash:		"; Hex$(NameInt.NextHash, 8)
    		d = LoByt(NameInt.cName)
    		Print# fo, "Name length:	"; Hex$(d, 2); " =="; Str$(d)
    		Print# fo, "Flags?...		"; Hex$(HiByt(LoWrd(NameInt.cName)), 2)
    		Print# fo, "Hash code:		"; Hex$(HiWrd(NameInt.cName), 4)
    
    		p = p + SizeOf(NameInt)
    		Print# fo, $Dq; Mid$(cs, p + 1, d); $Dq
    		p = (p + d + 3) And &HFFFFFFFC 'advance to next DWord-aligned offset
    
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print String Table
    	'every entry, length-plus-text, is a minimum of eight bytes
    	'(this keeps the offset in p zero-based)
    	Print# fo,
    	Print# fo, "*************************"
    	Print# fo, "String Table"
    	Print# fo, "*************************"
    	p = SegDir.pStrings.Offs
    	n = p + SegDir.pStrings.nLen
    	i = 1 'string number
    	Do Until p => n
    		d = CvWrd(cs, p + 1)
    		Print# fo, Format$(i); ")	"; Mid$(cs, p + 3, d)
    		'advance to next Dword-aligned offset beyond minimum length of eight bytes
    		p = (p + Max&(d + 2, 8) + 3) And &HFFFFFFFC
    		Incr i
    	Loop While p <= Len(cs)
    
    
    	'--------------------------------------
    	'Print Type Descriptors
    	If SegDir.pTypDesc.nLen Then
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Type Descriptors"
    		Print# fo, "*************************"
    		p = SegDir.pTypDesc.Offs + 1
    		n = p + SegDir.pTypDesc.nLen
    		Do Until p => n
    
    			Print# fo, "-------------------------"
    			Print# fo, "Raw:	"; Hex$(CvDwd(cs, p), 8), Hex$(CvDwd(cs, p + 4), 8)
    
    			LSet TypDsc = Mid$(cs, p)
    
    			Print# fo, "Data type 1 = "; Hex$(TypDsc.v2, 4); Hex$(TypDsc.v1, 4);
    			If (TypDsc.v2 And &H7FFE) = &H7FFE Then
    				Print# fo, " = ";
    			ElseIf (TypDsc.v2 And %VT_Vector) Then
    				Print# fo, " = VT_Vector, ";
    			ElseIf (TypDsc.v2 And %VT_Array) Then
    				Print# fo, " = VT_Array, ";
    			ElseIf (TypDsc.v2 And %VT_ByRef) Then
    				Print# fo, " = VT_ByRef, ";
    			'ElseIf (TypDsc.v2 And %VT_Reserved) Then
    			Else
    				Print# fo, " = ";
    			End If
    
    			Print# fo, VarType(TypDsc.v1);
    
    			If (TypDsc.v2 And &H7FFE) = &H7FFE Then
    				Print# fo,
    			Else
    				Print# fo, " == base type: "; VarType(TypDsc.v2 And %VT_TypeMask)
    			End If
    
    
    			If LoByt(TypDsc.v1) = %VT_Ptr Or LoByt(TypDsc.v1) = %VT_SafeArray Then
    
    				If TypDsc.v4 < 0 Then  'offset into type descriptor table
    					Print# fo, "Type descriptor table offset:	"; Hex$(TypDsc.v3 And &H07FF8, 4)
    				Else 'file offset to type descriptor
    					' This doesn't sound sensible, but it looks like what the ReactOS code was doing.
    					d = MakLng(TypDsc.v2, TypDsc.v3)
    					Print# fo, "Type descriptor file offset:	"; Hex$(d And (TypDsc.v3\8), 8)
    				End If
    
    			ElseIf LoByt(TypDsc.v1) = %VT_CArray Then
    				Print# fo, "Array descriptor offset:	"; Hex$(MakLng(TypDsc.v3, TypDsc.v4), 8)
    			ElseIf LoByt(TypDsc.v1) = %VT_UserDefined Then
    				Print# fo, "Type descriptor offset:		"; Hex$(MakLng(TypDsc.v3, TypDsc.v4) And &H0FFFFFFF8&, 8)
    			End If
    
    			p = p + SizeOf(tagTYPEDESC)
    
    		Loop While p <= Len(cs)
    
    	End If
    
    
    	'--------------------------------------
    	'Print Array Descriptors
    	If SegDir.pArryDesc.nLen Then
    
    #If %Def(%Study)
    	Note "Array(s) found"
    #EndIf
    
    		' What do the lower bits of td(1) mean (when td(1) < 0)?
    		' What is td(3) (it gets over-written when td(1) < 0) ?
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Array Descriptors"
    		Print# fo, "*************************"
    		p = SegDir.pArryDesc.Offs + 1
    		n = p + SegDir.pArryDesc.nLen
    		Do Until p => n
    
    			LSet AryDsc = Mid$(cs, p)
    			ReDim td(3)		As Integer At VarPtr(AryDsc)
    
    			Print# fo, "--------------------------------------------"
    			Print# fo, "Raw:	"; Hex$(CvDwd(cs, p), 8); ", "; Hex$(CvDwd(cs, p + 4), 8); ", "; Hex$(CvDwd(cs, p + 8), 8); ", "; Hex$(CvDwd(cs, p + 12), 8)
    
    			If AryDsc.u.hRefType => 0 Then 'a pointer to ANOTHER array descriptor?
    				AryDsc.u.lpadesc = (AryDsc.u.lpadesc And &H07FFF) \ 8
    				Print# fo, "Offset to array descriptor:	"; Hex$(AryDsc.u.lpadesc, 8)
    			Else 'the low word contains the variable-type code
    				Print# fo, "hRefType:	"; Hex$(AryDsc.u.hRefType, 8)
    				AryDsc.tVar = td(0) And %VT_TypeMask
    			End If
    
    			If (AryDsc.tVar And 255) = 0 Then d = HiByt(AryDsc.tVar) Else d = AryDsc.tVar
    			Print# fo, "Variable type:	"; Hex$(AryDsc.tVar, 4); " = "; VarType(d)
    			Print# fo, "Number of dimensions:	"; Hex$(AryDsc.nDims, 4); " =="; Str$(AryDsc.nDims)
    
    			p = p + SizeOf(ARRAYDESC) - SizeOf(SafeArrayBound)
    			For i = 1 To AryDsc.nDims
    				LSet SafBnd = Mid$(cs, p)
    				Print# fo, "("; Format$(i); ")	"; "Elements: "; Hex$(SafBnd.nElements, 8); " =="; Str$(SafBnd.nElements); "	Lower bound: "; Hex$(SafBnd.lLBound, 8); " =="; Str$(SafBnd.lLBound)
    				p = p + SizeOf(SafeArrayBound)
    				If p => Len(cs) Then Exit Do
    			Next i
    
    		Loop While p <= Len(cs)
    
    	End If
    
    	'--------------------------------------
    	'Print Custom Data
    	'a guess as to the storage format...
    	'Type CustomData
    	'	cWords				As Word
    	'	aData(cWords - 1)	As Word
    	'	sGUID				As Guid
    	'End Type
    	If SegDir.pCustData.nLen Then
    
    #If %Def(%Study)
    	If SegDir.pCustData.nLen > 16 Then
    		Note "More than 16 bytes of custom data"
    	End If
    #EndIf
    		'custom data and default parameter values
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Custom Data"
    		Print# fo, "*************************"
    		p = SegDir.pCustData.Offs + 1
    		n = p + SegDir.pCustData.nLen
    		Do Until p => n
    			Print# fo, Hex$(CvDwd(cs, p), 8)
    			p = p + 4
    		Loop While p <= Len(cs)
    
    	End If
    
    
    	'--------------------------------------
    	'Print offsets of GUID's and into the
    	If SegDir.pCDGuids.nLen Then
    		'custom data table
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Offsets of GUID's"
    		Print# fo, "*************************"
    		p = SegDir.pCDGuids.Offs + 1
    		n = p + SegDir.pCDGuids.nLen
    		Do Until p => n
    			Print# fo, Hex$(CvDwd(cs, p), 8)
    			p = p + 4
    		Loop While p <= Len(cs)
    	End If
    
    	'--------------------------------------
    	'Print "Unknown 02"
    	If SegDir.Unk02.nLen Then
    #If %Def(%Study)
    	Note "Unknown 02"
    #EndIf
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Unknown 02"
    		Print# fo, "*************************"
    		p = SegDir.Unk02.Offs + 1
    		n = p + SegDir.Unk02.nLen
    		Do Until p => n
    			Print# fo, Hex$(CvDwd(cs, p), 8)
    			p = p + 4
    		Loop While p <= Len(cs)
    	End If
    
    
    	'--------------------------------------
    	'Print "Unknown 03"
    	If SegDir.Unk03.nLen Then
    #If %Def(%Study)
    	Note "Unknown 03"
    #EndIf
    		Print# fo,
    		Print# fo, "*************************"
    		Print# fo, "Unknown 03"
    		Print# fo, "*************************"
    		p = SegDir.Unk03.Offs + 1
    		n = p + SegDir.Unk03.nLen
    		Do Until p => n
    			Print# fo, Hex$(CvDwd(cs, p), 8)
    			p = p + 4
    		Loop While p <= Len(cs)
    	End If
    
    End Function
    
    '***************************************
    
    "DisTypeLib.inc"
    '**************************************
    '	"DisTypeLib.inc"
    
    
    
    'This file is GPL 2008, by TheirCorp
    '**************************************
    
    
    $PeMZ			= "MZ"
    $PePE32			= "PE" & $Nul & $Nul	 'Chr$(&H50, &H45, &H00, &H00)
    
    %SizeOfShortName				   = 8
    %IMAGE_RESOURCE_NAME_IS_STRING	   = &H080000000???
    %IMAGE_RESOURCE_DATA_IS_DIRECTORY  = &H080000000???
    %ResourceSection				   = 3
    %NumberOfDirectoryEntries		   = 16	'IMAGE_NUMBEROF_DIRECTORY_ENTRIES
    %SizeOfShortName				   = 8
    %SectionHeaderSize				   = 40	 '%IMAGE_SIZEOF_SECTION_HEADER
    %MAXSTRING						   = 120
    
    %SUBDIR				   = 16
    %WINAPI				   = 1
    %WM_USER			   = &H400
    %TRUE				   = 1
    %FALSE				   = 0
    %LF_FACESIZE		   = 32
    %MAX_PATH			   = 260 ' max. length of full pathname
    %MAX_EXT			   = 256
    %ANSI_CHARSET		   = 0
    %FF_DONTCARE		   = 0 ' Don't care or don't know.
    %FW_DONTCARE		   = 0
    %FW_NORMAL			   = 400
    %LOGPIXELSY			   = 90 ' Logical pixels/inch in Y
    
    %WM_DESTROY			   = &H2
    %WM_SETFONT			   = &H30
    %WM_COMMAND			   = &H111
    %WM_DROPFILES		   = &H233
    %WM_NCACTIVATE		   = &H86
    %WM_INITDIALOG		   = &H110
    
    %WS_CHILD			   = &H40000000
    %WS_TABSTOP			   = &H00010000
    %WS_MINIMIZEBOX		   = &H00020000
    %WS_POPUP			   = &H80000000
    %WS_VISIBLE			   = &H10000000
    %WS_CLIPSIBLINGS	   = &H04000000
    %WS_CAPTION			   = &H00C00000 ' WS_BORDER OR WS_DLGFRAME
    %WS_BORDER			   = &H00800000
    %WS_DLGFRAME		   = &H00400000
    %WS_SYSMENU			   = &H00080000
    %WS_VSCROLL			   = &H00200000
    %WS_HSCROLL			   = &H00100000
    
    %WS_EX_LEFT			   = &H00000000
    %WS_EX_LTRREADING	   = &H00000000
    %WS_EX_RIGHTSCROLLBAR  = &H00000000
    %WS_EX_CONTROLPARENT   = &H00010000
    %WS_EX_WINDOWEDGE	   = &H00000100
    %WS_EX_CLIENTEDGE	   = &H00000200
    %WS_EX_ACCEPTFILES	   = &H00000010
    %WS_EX_TOOLWINDOW	   = &H00000080
    
    %HWND_DESKTOP			   = 0
    
    %BN_CLICKED				   = 0
    %BS_TEXT				   = &H0&
    %BS_PUSHBUTTON			   = &H0&
    %BS_GROUPBOX			   = &H7&
    %BS_CENTER				   = &H300&
    %BS_TOP					   = &H400&
    %BS_VCENTER				   = &HC00&
    %BS_DEFPUSHBUTTON		   = &H1&
    %BS_ICON				   = &H40&
    %BS_BITMAP				   = &H80&
    
    %DM_SETDEFID			   = %WM_USER + 1
    
    %DS_3DLOOK				   = &H0004&
    %DS_MODALFRAME			   = &H0080& ' Can be combined with WS_CAPTION
    %DS_NOFAILCREATE		   = &H0010&
    %DS_SETFONT				   = &H0040& ' User specified font for Dlg controls
    %DS_SETFOREGROUND		   = &H0200& ' not in win3.1
    
    %ES_LEFT		 = &H0&
    %ES_MULTILINE	 = &H4&
    %ES_AUTOVSCROLL  = &H40&
    %ES_AUTOHSCROLL  = &H80&
    %ES_WANTRETURN   = &H1000&
    
    %EM_SCROLL		 = &HB5
    %SB_LINEDOWN	 = 1
    %EM_SCROLLCARET  = &HB7
    %EM_SETSEL		 = &HB1
    
    %SBS_HORZ					  = &H0&
    %SBS_VERT					  = &H1&
    %SBS_TOPALIGN				  = &H2&
    %SBS_LEFTALIGN				  = &H2&
    %SBS_BOTTOMALIGN			  = &H4&
    %SBS_RIGHTALIGN				  = &H4&
    %SBS_SIZEBOXTOPLEFTALIGN	  = &H2&
    %SBS_SIZEBOXBOTTOMRIGHTALIGN  = &H4&
    %SBS_SIZEBOX				  = &H8&
    %SBS_SIZEGRIP				  = &H10&
    
    %SS_CENTER					  = &H00000001
    %SS_RIGHT					  = &H00000002
    
    %MB_OK						  = &H00000000&
    %MB_OKCANCEL				  = &H00000001&
    %MB_ABORTRETRYIGNORE		  = &H00000002&
    %MB_YESNOCANCEL				  = &H00000003&
    %MB_YESNO					  = &H00000004&
    %MB_RETRYCANCEL				  = &H00000005&
    %MB_CANCELTRYCONTINUE		  = &H00000006&
    
    %IDOK						  = 1
    %IDCANCEL					  = 2
    %IDABORT					  = 3
    %IDRETRY					  = 4
    %IDIGNORE					  = 5
    %IDYES						  = 6
    %IDNO						  = 7
    %IDCLOSE					  = 8
    %IDHELP						  = 9
    %IDTRYAGAIN					  = 10
    %IDCONTINUE					  = 11
    %SW_SHOW					  = 5
    
    '-----------------------------------------------------------------
    %LOAD_LIBRARY_AS_DATAFILE  = &H00000002
    %RT_CURSOR				   = 1
    %RT_BITMAP				   = 2
    %RT_ICON				   = 3
    %RT_MENU				   = 4
    %RT_DIALOG				   = 5
    %RT_STRING				   = 6
    %RT_FONTDIR				   = 7
    %RT_FONT				   = 8
    %RT_ACCELERATOR			   = 9
    %RT_RCDATA				   = 10
    %RT_MESSAGETABLE		   = 11
    %RT_GROUP_CURSOR		   = 12
    %RT_GROUP_ICON			   = 14
    %RT_VERSION				   = 16
    %RT_DLGINCLUDE			   = 17
    %RT_PLUGPLAY			   = 19
    %RT_VXD					   = 20
    %RT_ANICURSOR			   = 21
    %RT_ANIICON				   = 22
    %RT_HTML				   = 23
    %RT_MANIFEST			   = 24
    
    %READ_CONTROL				 = &H00020000
    %SYNCHRONIZE				 = &H00100000
    %STANDARD_RIGHTS_READ		 = %READ_CONTROL
    %KEY_QUERY_VALUE			 = &H1
    %KEY_ENUMERATE_SUB_KEYS		 = &H8
    %KEY_NOTIFY					 = &H10
    %KEY_READ					 = %STANDARD_RIGHTS_READ Or %KEY_QUERY_VALUE Or %KEY_ENUMERATE_SUB_KEYS Or %KEY_NOTIFY And (Not %SYNCHRONIZE)
    %HKEY_CURRENT_USER			 = &H80000001
    %ERROR_SUCCESS				 = 0&
    
    
    '**************************************
    
    Type LOGFONT
    	lfHeight As Long
    	lfWidth As Long
    	lfEscapement As Long
    	lfOrientation As Long
    	lfWeight As Long
    	lfItalic As Byte
    	lfUnderline As Byte
    	lfStrikeOut As Byte
    	lfCharSet As Byte
    	lfOutPrecision As Byte
    	lfClipPrecision As Byte
    	lfQuality As Byte
    	lfPitchAndFamily As Byte
    	lfFaceName As Asciiz * %LF_FACESIZE
    End Type
    
    
    
    '**************************************
    '	PE format UDTs
    '**************************************
    
    ' For resource directory entries that have actual string names, the Name
    ' field of the directory entry points to an object of the following type.
    ' All of these string objects are stored together after the last resource
    ' directory entry and before the first resource data object.  This minimizes
    ' the impact of these variable length objects on the alignment of the fixed
    ' size directory entry objects.
    
    Type IMAGE_RESOURCE_DIRECTORY_STRING
    	Length		As Word
    	NameString  As Byte 'ASCII string
    End Type
    
    Type IMAGE_RESOURCE_DIRECTORY_ENTRY
    	NameID  As Dword	'if bit 31 is set, the name is a string
    	Offset  As Dword	'if bit 31 is set, the data is a directory
    End Type
    
    Type IMAGE_RESOURCE_DIRECTORY
    	Characteristics		As Dword
    	TimeDateStamp		As Dword
    	MajorVersion		As Word
    	MinorVersion		As Word
    	NumberOfNamedEntries As Word
    	NumberOfIdEntries   As Word
    	'DirectoryEntries(0) As IMAGE_RESOURCE_DIRECTORY_ENTRY
    End Type
    
    Type IMAGE_RESOURCE_DATA_ENTRY
    	OffsetToData	As Dword
    	Size			As Dword
    	CodePage		As Dword
    	Reserved		As Dword
    End Type
    
    
    Type SectionInfo
    	SectName			As String * %SizeOfShortName
    	VirtSize			As Dword
    	dRVA				As Dword	'RVA to specific data within section
    	dSize				As Dword	'size of specific data within section
    	RVA					As Dword
    	RamAdd				As Dword
    	SizeOfRawData		As Dword
    	PtrToRawData		As Dword
    	StrPos				As Dword
    	EndPos				As Dword
    	Delta				As Dword
    	Characteristics		As Dword
    End Type 'SectionHeader
    
    
    Type DosHeader Byte			'DOS stub in EXE file
    	Magic		As Word		'Magic number
    	cBlp		As Word		'Bytes on last page of file
    	cP			As Word		'Pages in file
    	cRlc		As Word		'Relocations
    	cParHdr		As Word		'Size of header in paragraphs
    	MinAlloc	As Word		'Minimum extra paragraphs needed
    	MaxAlloc	As Word		'Maximum extra paragraphs needed
    	ss			As Word		'Initial (relative) SS value
    	sp			As Word		'Initial SP value
    	csum		As Word		'Checksum
    	ip			As Word		'Initial IP value
    	cs			As Word		'Initial (relative) CS value
    	lfaRlc		As Word		'File address of relocation table
    	OvNo		As Word		'Overlay number
    	Res4		As Asciz * 8 '4 Reserved words
    	OemId		As Word		'OEM identifier (for oeminfo)
    	OemInfo		As Word		'OEM information oemid specific
    	Res10		As Asciz * 20 '10 Reserved words
    	lfaNew		As Long  'always at &H3C and contains the offset of PE signature
    
    End Type 'DosHeader
    
    
    Type PEHeader Byte  'officially "IMAGEFILEHEADER"
    	Machine					As Word  'machine type
    	NumberOfSections		As Word
    	TimeDateStamp			As Dword 'Number of seconds since December 31st, 1969, at 4:00 P.M
    	PointerToSymbolTable	As Dword
    	NumberOfSymbols			As Dword
    	SizeOfOptionalHeader	As Word
    	Characteristics			As Word
    End Type 'PEHeader
    
    
    Type DataDir			Byte	'IMAGE_DATA_DIRECTORY
    	RVA					As Dword
    	DirSize				As Dword
    End Type 'DataDir
    
    
    'Optional header format ("IMAGE_OPTIONAL_HEADER32").
    'this is not as "optional" as its name suggests
    Type OptHeader			Byte
    	'Standard fields.
    	Magic				As Word  '"Magic number": &H10B = PE32, &H20B = PE32+, &H107 = ROM image
    	MajLinkerVer		As Byte
    	MinLinkerVer		As Byte
    	SizeOfCode			As Dword
    	SizeOfInitData		As Dword
    	SizeOfUninitData	As Dword
    	AddrOfEntryPoint	As Dword
    	BaseOfCode			As Dword
    	BaseOfData			As Dword
    
    	'NT additional fields.
    	ImageBase			As Dword 'defaults: DLL = &H10000000, EXE = &H400000
    	SectionAlign		As Dword 'must be => file alignment
    	FileAlign			As Dword 'alignment of raw data of sections. value should be a power of 2, => 512 and <= 64K ( default = 512)
    	MajOSVer			As Word
    	MinOSVer			As Word
    	MajImageVer			As Word
    	MinImageVer			As Word
    	MajSubsysVer		As Word
    	MinSubsysVer		As Word
    	Win32VerValue		As Dword
    	SizeOfImage			As Dword 'size of image, including headers. must be a multiple of SectionAlign
    	SizeOfHeaders		As Dword 'size of: stub + PE Header + section headers rounded up to multiple of FileAlign
    	CheckSum			As Dword
    	Subsystem			As Word
    	DllCharacteristics  As Word
    	SizeOfStackReserve  As Dword
    	SizeOfStackCommit   As Dword
    	SizeOfHeapReserve   As Dword
    	SizeOfHeapCommit	As Dword
    	LoaderFlags			As Dword 'obsolete
    	NumberOfRvaAndSizes As Dword 'Number of data-directory entries in the remainder of Optional Header
    	'DataDirectory( %NumberOfDirectoryEntries ) As DataDir
    
    End Type 'OptionalHeader
    
    
    'Section header format.
    'Borland calls its code sections "CODE", rather than ".text".
    Type SectionHeader		Byte	 ' _IMAGE_SECTION_HEADER
    	SectName			As String * %SizeOfShortName
    	VirtSize			As Dword
    	'VirtualAddress		 As Dword	 'changed from "RVA"
    	RVA					As Dword
    	SizeOfRawData		As Dword
    	PtrToRawData		As Dword
    	PtrToRelocations	As Dword
    	PtrToLineNums		As Dword
    	NumberOfRelocations As Word
    	NumberOfLineNums	As Word
    	Characteristics		As Dword
    End Type 'SectionHeader
    
    
    '**************************************
    '	Declares
    '**************************************
    Declare Function CreateFontIndirect Lib "GDI32.DLL" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Dword
    Declare Function DeleteObject Lib "GDI32.DLL" Alias "DeleteObject" (ByVal hObject As Dword) As Long
    Declare Function GetDeviceCaps Lib "GDI32.DLL" Alias "GetDeviceCaps" (ByVal hdc As Dword, ByVal nIndex As Long) As Long
    
    Declare Function GetLastError Lib "KERNEL32.DLL" Alias "GetLastError" () As Long
    Declare Function GetModuleFileName Lib "KERNEL32.DLL" Alias "GetModuleFileNameA" (ByVal hModule As Dword, lpFileName As Asciiz, ByVal nSize As Dword) As Dword
    
    Declare Sub DragAcceptFiles Lib "SHELL32.DLL" Alias "DragAcceptFiles" (ByVal hwnd As Dword, ByVal fAccept As Long)
    Declare Sub DragFinish Lib "SHELL32.DLL" Alias "DragFinish" (ByVal hDrop As Dword)
    Declare Function DragQueryFile Lib "SHELL32.DLL" Alias "DragQueryFileA" (ByVal hDrop As Dword, ByVal uiFile As Dword, lpStr As Asciiz, ByVal cch As Dword) As Dword
    Declare Function SetMenu Lib "USER32.DLL" Alias "SetMenu" (ByVal hWnd As Dword, ByVal hMenu As Dword) As Long
    
    Declare Function GetDC Lib "USER32.DLL" Alias "GetDC" (ByVal hWnd As Dword) As Dword
    Declare Function GetFocus Lib "USER32.DLL" Alias "GetFocus" () As Dword
    Declare Function ReleaseDC Lib "USER32.DLL" Alias "ReleaseDC" (ByVal hWnd As Dword, ByVal hDC As Dword) As Long
    Declare Function SetFocus Lib "USER32.DLL" Alias "SetFocus" (ByVal hWnd As Dword) As Long
    
    '**************************************
    TheirCorp's projects at SourceForge

    TheirCorp's website

    sigpic

    Comment


    • #3
      Sample ODL (Object Definition Language) File and its Dump

      "Sample.odl"
      Code:
      #include <olectl.h>
      #include <idispids.h>
      
      
      [uuid(A74CD7DD-EA6F-11D4-ABF3-000102378429), version(1.0),
        helpfile("Sample.hlp"),
        helpstring("Sample ActiveX Control module"),
        control]
      
      library SampleLib
      {
      	importlib(STDOLE_TLB);
      	importlib(STDTYPE_TLB);
      
      	[uuid(A74CD7DE-EA6F-11D4-ABF3-000102378429), hidden]
      		[helpstringcontext(103), version(1.0)]
      		[helpstring("Event interface for Sample Control")]
      	dispinterface _Sample
      	{
      		properties:
      			[id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor;
      			[id(DISPID_FORECOLOR), bindable, requestedit] OLE_COLOR ForeColor;
      			[id(1)] boolean ShowGrid;
      			[id(2)] boolean XLog;
      			[id(3)] int UsesArray;
      
      			[id(4), helpstring("A custom data type to help reverse this file format.")]
      			struct SampleType {
      				int cbStructSize;
      				int hWndOwner;
      				int x;
      				int y;
      				unsigned long lpszCaption;
      				unsigned long cObjects;
      				unsigned long **lplpUnk;
      				unsigned long cPages;
      				float floats[40];
      				char lpPages[80];
      			} Sample[5];
      
      			[id(20), bindable, requestedit] int Param[12];
      
      		methods:
      			// some "void" methods (they don't return values)
      			[id(21), helpstring("An int parameter (= PowerBASIC's Long)")]
      			void Method1(int integer);
      
      			[id(22), helpstring("An array with no element count specified")]
      			void Method2(int array[]);
      
      			[id(23), helpstring("A SafeArray")]
      			void Method3(SAFEARRAY(int)); // a SafeArray
      
      
      			// the same one's as above, but these do return values
      			[id(24), helpstring("Another int parameter (= PowerBASIC's Long)")]
      			int Method4(int integer);
      
      			[id(25), helpstring("Another array with no element count specified")]
      			VARIANT Method5(int array[]);
      
      			[id(26), helpstring("Another SafeArray")]
      			double Method6(SAFEARRAY(int)); // a SafeArray
      
        	};
      
      	[uuid(A74CD7E0-EA6F-11D4-ABF3-000102378429),
      	  helpstring("Sample Control"), control]
      	coclass Sample
      	{
      		[default] dispinterface _Sample;
      	};
      
      };
      "Sample.txt"
      This is the dump file of "Sample.tlb" which was made by compiling
      "Sample.odl". This was made with the "Study Mode" code enabled,
      so it's a little cluttered.
      Code:
      *************************
      TypeLib Header
      *************************
      Magic 1:		5446534D = MSFT
      Magic 2:		00010002
      GUID:			00000000 ==> {A74CD7DD-EA6F-11D4-ABF3-000102378429}
      Locale ID:		00000409 = English United States
      Locale ID 2:	00000000
      VarFlags:		00000051
      	System:		Win32
      	Help file specified
      	Help file is not in a DLL
      Version:	00000001
      Flags:		00000002
      TypeInfo count:	00000003 == 3
      HelpString:			0000000C ==> "Sample ActiveX Control module"
      HelpStringContext:	00000000
      HelpContext:		00000000
      Name Table:
      	Names count:	0000001E == 30
      	Characters:		000000DC == 220
      
      TypeLib Name:	00000000 ==> "SampleLib"
      Helpfile:		00000000 ==> "Sample.hlp"
      Custom data offset:	0000000C
      Reserved1:	00000020
      Reserved2:	00000080
      IDispatch:			00000001
      ImportInfo count:	00000002 == 2
      
      *************************
      Offsets to TypeInfo Data
      *************************
      00000000
      00000064
      000000C8
      
      *************************
      Segment Directory (Segment name: Offset, Length)...
      *************************
      Type Info Table:		00000150, 0000012C
      Import Info:			000003CC, 00000018
      Imported Libraries:		000003E4, 0000001C
      References Table:		000003BC, 00000010
      Lib Table:				0000027C, 00000080
      GUID Table:				000002FC, 000000C0
      Unknown 01:				00000400, 00000200
      Name Table:				00000600, 00000274
      String Table:			00000874, 00000170
      Type Descriptors:		000009E4, 00000050
      Array Descriptors:		00000A34, 00000040
      Custom Data:			00000A74, 00000010
      GUID Offsets:			00000A84, 00000018
      Unknown 02:				FFFFFFFF, 00000000
      Unknown 03:				FFFFFFFF, 00000000
      
      @@@:	Reserved Fields
      Segment name:	Res01, Res02...
      *************************
      Type Info Table:		FFFFFFFF, 0000000F
      Import Info:			FFFFFFFF, 0000000F
      Imported Libraries:		FFFFFFFF, 0000000F
      References Table:		FFFFFFFF, 0000000F
      Lib Table:				FFFFFFFF, 0000000F
      GUID Table:				FFFFFFFF, 0000000F
      Unknown 01:				FFFFFFFF, 0000000F
      Name Table:				FFFFFFFF, 0000000F
      String Table:			FFFFFFFF, 0000000F
      Type Descriptors:		FFFFFFFF, 0000000F
      Array Descriptors:		FFFFFFFF, 0000000F
      Custom Data:			FFFFFFFF, 0000000F
      Custom Data/GUID's:		FFFFFFFF, 0000000F
      Unknown 02:				FFFFFFFF, 0000000F
      Unknown 03:				FFFFFFFF, 0000000F
      
      
      *************************
      TypeInfo Data...
      *************************
      -------------------------
      TypeInfo number:	1
      Type kind:	04 = Dispatch
      	Alignment: (21/8) = 04
      Memory to allocate:		00000340
      Reconstituted Size:		000002E4
      Reserved 01:	00000003
      Reserved 02:	00000000
      
      Function count:	0006 == 6
      Property count:	0007 == 7
      Reserved 03:	00000000
      Reserved 04:	00000000
      Reserved 05:	00000000
      Reserved 06:	00000000
      GUID:	00000048 ==> {A74CD7DE-EA6F-11D4-ABF3-000102378429}
      Type Flags:	00001010 = Dispatchable, Hidden
      Name:	00000018 ==> "_Sample"
      Version:	00000001
      Doc String:	0000002C ==> "Event interface for Sample Control"
      HelpStringContext:	00000067
      HelpContext:		00000000
      
      Custom data offset:		FFFFFFFF
      Implemented interfaces:	0001 == 1
      Virtual table size:		0018
      Unknown 03:				00000004
      DataType1:	FFFFFFFF
      DataType2:	00000000
      Reserved 7:	00000000
      Reserved 8:	FFFFFFFF
      
      Records offset:	00000A9C
      
      	Function record array size:	0000019C
      
      	----------------------------------------
      				Functions:
      	----------------------------------------
      	ID:			00000015 == 21
      	Name:		000001A4 ==> "Method1"
      	Reference:	00000000
      	Record size:	002C
      	Unknown 1:		0000
      	Flags:			8000 = VT_Empty
      	DataType:		0018 = VT_Void
      
      	Reserved 1:		00000000
      	Vtable offset:	0000
      	Func Desc Size:	0044
      
      	FKCCIC (raw):	0000040C
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			00000088 ==> "An int parameter (= PowerBASIC's Long)"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0016 = VT_Int
      		Flags:				8003 = VT_I4
      		Name:				000001B8 ==> "integer"
      		ParamFlags:			00000000 =	(none)
      	----------------------------------------
      	ID:			00000016 == 22
      	Name:		000001CC ==> "Method2"
      	Reference:	0000002C
      	Record size:	002C
      	Unknown 1:		0001
      	Flags:			8000 = VT_Empty
      	DataType:		0018 = VT_Void
      
      	Reserved 1:		00000000
      	Vtable offset:	0004
      	Func Desc Size:	004C
      
      	FKCCIC (raw):	0001040C
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			000000B0 ==> "An array with no element count specified"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0040 = VT_FileTime
      		Flags:				0000 = VT_Empty
      		Name:				000001E0 ==> "array"
      		ParamFlags:			00000000 =	(none)
      	----------------------------------------
      	ID:			00000017 == 23
      	Name:		000001F4 ==> "Method3"
      	Reference:	00000058
      	Record size:	002C
      	Unknown 1:		0002
      	Flags:			8000 = VT_Empty
      	DataType:		0018 = VT_Void
      
      	Reserved 1:		00000000
      	Vtable offset:	0008
      	Func Desc Size:	004C
      
      	FKCCIC (raw):	0002040C
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			000000DC ==> "A SafeArray"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0048 = VT_ClsID
      		Flags:				0000 = VT_Empty
      		Name:				00000208 ==> "__MIDL_0014"
      		ParamFlags:			00000000 =	(none)
      	----------------------------------------
      	ID:			00000018 == 24
      	Name:		00000220 ==> "Method4"
      	Reference:	00000084
      	Record size:	002C
      	Unknown 1:		0003
      	Flags:			8003 = VT_I4
      	DataType:		0016 = VT_Int
      
      	Reserved 1:		00000000
      	Vtable offset:	000C
      	Func Desc Size:	0044
      
      	FKCCIC (raw):	0003040C
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			000000EC ==> "Another int parameter (= PowerBASIC's Long)"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0016 = VT_Int
      		Flags:				8003 = VT_I4
      		Name:				000001B8 ==> "integer"
      		ParamFlags:			00000000 =	(none)
      	----------------------------------------
      	ID:			00000019 == 25
      	Name:		00000234 ==> "Method5"
      	Reference:	000000B0
      	Record size:	002C
      	Unknown 1:		0004
      	Flags:			800C = VT_Variant
      	DataType:		000C = VT_Variant
      
      	Reserved 1:		00000000
      	Vtable offset:	0010
      	Func Desc Size:	004C
      
      	FKCCIC (raw):	0004040C
      		oEntry is numeric
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			0000011C ==> "Another array with no element count specified"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0040 = VT_FileTime
      		Flags:				0000 = VT_Empty
      		Name:				000001E0 ==> "array"
      		ParamFlags:			00000000 =	(none)
      	----------------------------------------
      	ID:			0000001A == 26
      	Name:		00000248 ==> "Method6"
      	Reference:	000000DC
      	Record size:	002C
      	Unknown 1:		0005
      	Flags:			8005 = VT_R8
      	DataType:		0005 = VT_R8
      
      	Reserved 1:		00000000
      	Vtable offset:	0014
      	Func Desc Size:	004C
      
      	FKCCIC (raw):	0005040C
      		oEntry is numeric
      		Calling convention:	04 = StdCall
      		Invocation kind:	01 = Func
      		Function kind:		04 = Dispatch
      
      	Number of parameters:	0001 == 1
      	Unknown 2:		0000
      		----------------------------------------
      		Optional Data:
      		HelpContext:		00000000
      		HelpString:			0000014C ==> "Another SafeArray"
      
      		----------------------------------------
      		Parameter number:	 1
      		DataType:			0048 = VT_ClsID
      		Flags:				0000 = VT_Empty
      		Name:				0000025C ==> "__MIDL_0015"
      		ParamFlags:			00000000 =	(none)
      
      	----------------------------------------
      		 Properties:
      	----------------------------------------
      	ID:			FFFFFE0B ==-501
      	Name:		0000002C ==> "BackColor"
      	Reference:	00000108
      	Record size (low-byte):	0014
      	Property number?:		0006
      	Flags:					0000
      	DataType:				0000 = VT_Empty
      	Variable kind:			000C = RequestEdit, Bindable
      	Variable desc size:		0000
      	Value/Offset:			00240003
      	Unknown:				00000000
      
      	----------------------------------------
      	ID:			FFFFFDFF ==-513
      	Name:		00000044 ==> "ForeColor"
      	Reference:	0000011C
      	Record size (low-byte):	0014
      	Property number?:		0007
      	Flags:					0000
      	DataType:				0000 = VT_Empty
      	Variable kind:			000C = RequestEdit, Bindable
      	Variable desc size:		0000
      	Value/Offset:			00240003
      	Unknown:				00000000
      
      	----------------------------------------
      	ID:			00000001 == 1
      	Name:		0000005C ==> "ShowGrid"
      	Reference:	00000130
      	Record size (low-byte):	0014
      	Property number?:		0008
      	Flags:					8010 = VT_I1
      	DataType:				0010 = VT_I1
      	Variable kind:			0000 = 
      	Variable desc size:		0000
      	Value/Offset:			00240003
      	Unknown:				00000000
      
      	----------------------------------------
      	ID:			00000002 == 2
      	Name:		00000070 ==> "XLog"
      	Reference:	00000144
      	Record size (low-byte):	0014
      	Property number?:		0009
      	Flags:					8010 = VT_I1
      	DataType:				0010 = VT_I1
      	Variable kind:			0000 = 
      	Variable desc size:		0000
      	Value/Offset:			00240003
      	Unknown:				00000000
      
      	----------------------------------------
      	ID:			00000003 == 3
      	Name:		00000080 ==> "UsesArray"
      	Reference:	00000158
      	Record size (low-byte):	0014
      	Property number?:		000A
      	Flags:					8003 = VT_I4
      	DataType:				0016 = VT_Int
      	Variable kind:			0000 = 
      	Variable desc size:		0000
      	Value/Offset:			00240003
      	Unknown:				00000000
      
      	----------------------------------------
      	ID:			00000004 == 4
      	Name:		0000017C ==> "Sample"
      	Reference:	0000016C
      	Record size (low-byte):	001C
      	Property number?:		000B
      	Flags:					0000
      	DataType:				0030 = (Unknown)
      	Variable kind:			0000 = 
      	Variable desc size:		0000
      	Value/Offset:			00380003
      	Unknown:				00000000
      	HelpContext:			00000000
      	HelpString:	00000050 ==> "A custom data type to help reverse this file format."
      
      	----------------------------------------
      	ID:			00000014 == 20
      	Name:		00000190 ==> "Param"
      	Reference:	00000188
      	Record size (low-byte):	0014
      	Property number?:		000C
      	Flags:					0000
      	DataType:				0038 = (Unknown)
      	Variable kind:			000C = RequestEdit, Bindable
      	Variable desc size:		0000
      	Value/Offset:			00380003
      	Unknown:				00000000
      
      
      	----------------------------------------
      		 Other Function Data:
      	----------------------------------------
      	ID:			00000015 == 21
      	Name:		000001A4 ==> "Method1"
      	Reference:	00000000
      
      	----------------------------------------
      	ID:			00000016 == 22
      	Name:		000001CC ==> "Method2"
      	Reference:	0000002C
      
      
      *************************
      ImportInfo
      *************************
      --------------------------------------------
      Import Info number:	1
      Count:				0
      Offset in import file table:	00000000
      GUID:	00000078 ==> {00020400-0000-0000-C000-000000000046}
      Type:	Module
      --------------------------------------------
      Import Info number:	2
      Count:				1
      Offset in import file table:	00000000
      GUID:	00000090 ==> {66504301-BE0F-101A-8BBB-00AA00300CAB}
      Type:	Coclass
      
      *************************
      Imported Type Libs
      *************************
      --------------------------------------------
      GUID:			00000060 ==> {00020430-0000-0000-C000-000000000046}
      Locale ID?:		00000000 = Language-Neutral
      Major version:	0002
      Minor version:	0000
      Size = 		002D/4 = 000B
      File name:	stdole2.tlb
      
      *************************
      References Table
      *************************
      --------------------------------------------
      Reference type:	00000000	==> (TypeInfo)
      Flags:			00000001
      
      *************************
      Lib Table (offsets into GUID table)
      *************************
      00000078
      00000090
      00000048
      00000000
      00000060
      00000030
      000000A8
      00000018
      
      *************************
      GUID Table
      *************************
      --------------------------------------------
      GUID:	{A74CD7DD-EA6F-11D4-ABF3-000102378429}
      Href Type:	FFFFFFFE = TypeLib GUID
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{DE77BA63-517C-11D1-A2DA-0000F8773CE9}
      Href Type:	FFFFFFFF = Offset?
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{DE77BA64-517C-11D1-A2DA-0000F8773CE9}
      Href Type:	FFFFFFFF = Offset?
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{A74CD7DE-EA6F-11D4-ABF3-000102378429}
      Href Type:	00000000 = Offset?
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{00020430-0000-0000-C000-000000000046}
      Href Type:	00000002 = Imported TypeLib
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{00020400-0000-0000-C000-000000000046}
      Href Type:	00000001 = Imported TypeInfo
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{66504301-BE0F-101A-8BBB-00AA00300CAB}
      Href Type:	0000000D = Imported TypeInfo
      Next hash:	FFFFFFFF
      --------------------------------------------
      GUID:	{A74CD7E0-EA6F-11D4-ABF3-000102378429}
      Href Type:	000000C8 = Offset?
      Next hash:	FFFFFFFF
      
      *************************
      "Unknown 01" --- Table with Offsets into the Name Table
      *************************
      000001E0
      000001B8
      00000044
      00000080
      00000140
      0000012C
      000000C8
      00000208
      0000025C
      00000118
      0000017C
      00000070
      000001A4
      000001CC
      000001F4
      00000220
      00000234
      00000248
      00000018
      00000190
      00000098
      0000002C
      00000100
      000000F0
      0000005C
      000000E0
      000000B0
      00000000
      00000168
      
      *************************
      Name Table
      *************************
      --------------------------------------------
      Next hash:		FFFFFFFF
      Name length:	09 == 9
      Flags?...		00
      Hash code:		787A
      "SampleLib"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		38
      Hash code:		FC49
      "_Sample"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	09 == 9
      Flags?...		00
      Hash code:		83DE
      "BackColor"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	09 == 9
      Flags?...		00
      Hash code:		1313
      "ForeColor"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	08 == 8
      Flags?...		00
      Hash code:		5BED
      "ShowGrid"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	04 == 4
      Flags?...		00
      Hash code:		E6B9
      "XLog"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	09 == 9
      Flags?...		00
      Hash code:		629D
      "UsesArray"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	0A == 10
      Flags?...		38
      Hash code:		C5D7
      "SampleType"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	0C == 12
      Flags?...		10
      Hash code:		3770
      "cbStructSize"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	09 == 9
      Flags?...		10
      Hash code:		FEAC
      "hWndOwner"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	01 == 1
      Flags?...		10
      Hash code:		106F
      "x"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	01 == 1
      Flags?...		10
      Hash code:		106C
      "y"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	0B == 11
      Flags?...		10
      Hash code:		936A
      "lpszCaption"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	08 == 8
      Flags?...		10
      Hash code:		3FB4
      "cObjects"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		10
      Hash code:		D4A7
      "lplpUnk"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	06 == 6
      Flags?...		10
      Hash code:		3125
      "cPages"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	06 == 6
      Flags?...		10
      Hash code:		DF46
      "floats"
      --------------------------------------------
      Offset:			00000064
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		10
      Hash code:		3AFC
      "lpPages"
      --------------------------------------------
      Offset:			000000C8
      Next hash:		FFFFFFFF
      Name length:	06 == 6
      Flags?...		28
      Hash code:		84B6
      "Sample"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	05 == 5
      Flags?...		00
      Hash code:		FDCC
      "Param"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5341
      "Method1"
      --------------------------------------------
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		B48A
      "integer"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5342
      "Method2"
      --------------------------------------------
      Next hash:		FFFFFFFF
      Name length:	05 == 5
      Flags?...		00
      Hash code:		9183
      "array"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5343
      "Method3"
      --------------------------------------------
      Next hash:		FFFFFFFF
      Name length:	0B == 11
      Flags?...		00
      Hash code:		A4B2
      "__MIDL_0014"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5344
      "Method4"
      --------------------------------------------
      Offset:			00000000
      Next hash:		FFFFFFFF
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5345
      "Method5"
      --------------------------------------------
      Offset:			00000000
      Next hash:		00000154
      Name length:	07 == 7
      Flags?...		00
      Hash code:		5346
      "Method6"
      --------------------------------------------
      Next hash:		FFFFFFFF
      Name length:	0B == 11
      Flags?...		00
      Hash code:		A4B3
      "__MIDL_0015"
      
      *************************
      String Table
      *************************
      1)	Sample.hlp
      2)	Sample ActiveX Control module
      3)	Event interface for Sample Control
      4)	A custom data type to help reverse this file format.
      5)	An int parameter (= PowerBASIC's Long)
      6)	An array with no element count specified
      7)	A SafeArray
      8)	Another int parameter (= PowerBASIC's Long)
      9)	Another array with no element count specified
      10)	Another SafeArray
      11)	Sample Control
      
      *************************
      Type Descriptors
      *************************
      -------------------------
      Raw:	7FFF001D 0000000D
      Data type 1 = 7FFF001D = VT_UserDefined
      Type descriptor offset:		00000008
      -------------------------
      Raw:	4013001A 80130013
      Data type 1 = 4013001A = VT_ByRef, VT_Ptr == base type: VT_UI4
      Type descriptor table offset:	0010
      -------------------------
      Raw:	7FFE001A 00000008
      Data type 1 = 7FFE001A = VT_Ptr
      Type descriptor file offset:	00000000
      -------------------------
      Raw:	7FFE001C 00000000
      Data type 1 = 7FFE001C = VT_CArray
      Array descriptor offset:	00000000
      -------------------------
      Raw:	7FFE001C 00000010
      Data type 1 = 7FFE001C = VT_CArray
      Array descriptor offset:	00000010
      -------------------------
      Raw:	7FFF001D 00000064
      Data type 1 = 7FFF001D = VT_UserDefined
      Type descriptor offset:		00000060
      -------------------------
      Raw:	7FFE001C 00000020
      Data type 1 = 7FFE001C = VT_CArray
      Array descriptor offset:	00000020
      -------------------------
      Raw:	7FFE001C 00000030
      Data type 1 = 7FFE001C = VT_CArray
      Array descriptor offset:	00000030
      -------------------------
      Raw:	4003001A 80030016
      Data type 1 = 4003001A = VT_ByRef, VT_Ptr == base type: VT_I4
      Type descriptor table offset:	0010
      -------------------------
      Raw:	2003001B 80030016
      Data type 1 = 2003001B = VT_Array, VT_SafeArray == base type: VT_I4
      Type descriptor table offset:	0010
      
      @@@: Array(s) found
      
      *************************
      Array Descriptors
      *************************
      --------------------------------------------
      Raw:	80040004, 00080001, 00000028, 00000000
      hRefType:	80040004
      Variable type:	0004 = VT_R4
      Number of dimensions:	0001 == 1
      (1)	Elements: 00000028 == 40	Lower bound: 00000000 == 0
      --------------------------------------------
      Raw:	80100010, 00080001, 00000050, 00000000
      hRefType:	80100010
      Variable type:	0010 = VT_I1
      Number of dimensions:	0001 == 1
      (1)	Elements: 00000050 == 80	Lower bound: 00000000 == 0
      --------------------------------------------
      Raw:	00000028, 00080001, 00000005, 00000000
      Offset to array descriptor:	00000005
      Variable type:	0008 = VT_BStr
      Number of dimensions:	0001 == 1
      (1)	Elements: 00000005 == 5	Lower bound: 00000000 == 0
      --------------------------------------------
      Raw:	80030016, 00080001, 0000000C, 00000000
      hRefType:	80030016
      Variable type:	0016 = VT_Int
      Number of dimensions:	0001 == 1
      (1)	Elements: 0000000C == 12	Lower bound: 00000000 == 0
      
      *************************
      Custom Data
      *************************
      9C330013
      575748B4
      00A40013
      57570501
      
      *************************
      Offsets of GUID's
      *************************
      00000018
      00000000
      FFFFFFFF
      00000030
      00000008
      00000000
      TheirCorp's projects at SourceForge

      TheirCorp's website

      sigpic

      Comment

      Working...
      X