Paradox Community
Search:

 Welcome |  What is Paradox |  Paradox Folk |  Paradox Solutions |
 Interactive Paradox |  Paradox Programming |  Internet/Intranet Development |
 Support Options |  Classified Ads |  Wish List |  Submissions 


Paradox Programming Articles  |  Beyond Help Articles  |  Tips & Tricks Articles  


Formatted Hexadecimal Memory Dumper
© 2002 Rick Kelly
www.crooit.com


Introduction

For the developer working with Win32 structures or other random memory locations, there are times when visually inspecting memory contents may be necessary.

Given a memory pointer and a length, our goal is to produce a standard text file that looks like:

Memory Address=00EF90E8 Length=32
00EF90E8  0000  1C 02 00 00 41 00 6C 00 61 00 73 00 6B 00 61 00   ....A.l.a.s.k.a.
00EF90F8  0010  6E 00 20 00 53 00 74 00 61 00 6E 00 64 00 61 00   n. .S.t.a.n.d.a.
Where we not only show the raw hexadecimal contents but a sanitized ASCII string value as well.


Win32 API References

The following Win32 API method is used to retrieve a value from memory and save it in a Paradox variable.
Uses "kernel32.dll"
  MoveFromMemory(
    wDestination cPtr,
    wSource cLong,
    wLength cLong) cLong [stdcall "RtlMoveMemory"]
endUses

Overview

A neat trick we will use takes advantage of how Intel® words and double-words are loaded and stored from low byte to high byte. For instance, a stored word or Type SmallInt with value 16 looks like x'1000'. We can fetch one byte from memory, store it in the first byte of a SmallInt and then use normal OPAL for further processing.

Our method below will take a LongInt pointer and LongInt length, produce a normal text file with a specified name of the memory contents, and optionally, run the Windows Notepad program so we can see the results.
method HexDump(liPointer LongInt,
               liLength LongInt,
               stFileName String,
               loNotePad Logical)
var
  siAny      SmallInt
  stHex      String
  stAny      String
  stASCII    String
  liMemory   LongInt
  ts         TextStream
  liSegments LongInt
  liIndex    LongInt
  stAlias    String
endVar
switch
  case ts.open(stFileName,"NW") = False :
  otherwise :
    stHex = toHex(liPointer)
    stAny = "Memory Address="
             + upper(stHex.substr(3,8))
             + " Length="
             + strval(liLength)
             + chr(13)
             + chr(10)
    ts.writeLine(stAny)
;
; Calculate the number of 16 byte segments we are going to process
;
    liSegments = longInt(ceil(liLength / 16.0))
;
; Loop through memory and decode
;
    for liIndex from 1 to liSegments
      stHex = toHex(liPointer)
      stAny = upper(stHex.substr(3,8)) + "  "
      stHex = toHex((liIndex * 16) - 16)
      stAny = stAny
              + upper(stHex.substr(7,4))
              + "  "
      stASCII = "  "
      for liMemory from liPointer to liPointer + iif(liLength < 16,liLength - 1,15)
        siAny = 0
        MoveFromMemory(siAny,liMemory,1)
        stHex = toHex(siAny)
        stAny = stAny
                + upper(stHex.substr(9,2))
                + " "
;
; Show only standard ASCII character set
;
        switch
          case siAny >= 32 and
               siAny <= 126 :
            stASCII = stASCII
                      + chr(siAny)
          otherwise :
            stASCII = stASCII
                      + "."
        endSwitch
      endFor
;
; If this is the last block and it is not
; an even multiple of 16, pad it with
; some spaces
;
      switch
        case liIndex <> liSegments :
        case liLength >= 16 :
        otherwise :
          stAny = stAny
                  + space((16 - liLength) * 3 + 3)
      endSwitch
      ts.writeLine(stAny + stASCII)
      liPointer = liPointer + 16
      liLength = liLength - 16
    endFor
    ts.close()
endSwitch
;
; Optional launch of Notepad
;
switch
  case loNotePad = True :
;
; Check if alias was used
;
    switch
      case stFileName.substr(1,1) = ":" :
;
; Isolate Alias and get path
;
        stFileName = stFileName.substr(2,stFileName.size() - 1)
        siAny = stFileName.search(":")
        stAlias = stFileName.substr(1,siAny - 1)
        stFileName = getAliasPath(stAlias)
                     + "\\"
                     + stFileName.substr(siAny + 1,
                                         stFileName.size() - siAny)
    endSwitch
;
; Launch Notepad
;
    execute("notepad.exe " + stFileName,No,ExeShowMaximized)
endSwitch
endMethod

Example

The following script (download available here) will retrieve a Windows TimeZone structure and call HexDump.
Uses "kernel32.dll"
  MoveFromMemory(wDestination cPtr,
                 wSource cLong,
                 wLength cLong) cLong [stdcall "RtlMoveMemory"]
  GlobalAlloc(wFlags cLong,
              dwBytes cLong) cLong [stdcall]
  GlobalFree(hMem cLong) cLong [stdcall]
  GetTimeZoneInformation(wTZI cLong) cLong [stdcall]
endUses

method run(var eventInfo Event)
var
  liPointer LongInt
  liLength  LongInt
  liReturn  LongInt
endVar
;
; TimeZone Structure
;
; + 0   = Bias
; + 4   = Standard Name (32 SmallInt values)
; + 68  = Standard Date Structure
; + 84  = Standard Bias
; + 88  = Daylight Name (32 SmallInt values)
; + 152  = Daylight Date Structure
; + 168  = Daylight Bias
;
; Total Length = 172 bytes
;
; Date Structure (all type SmallInt)
;   Year,Month,Day of Week,Day,Hour,Minute,Second,Millisecond
;
  liLength = 172
  liPointer = GlobalAlloc(fromHex("0x40"),liLength)
;
; Retrieve Time Zone Structure
;
  liReturn = GetTimeZoneInformation(liPointer)
  HexDump(liPointer,liLength,":PRIV:__mdump.txt",True)
  liReturn = GlobalFree(liPointer)
endMethod


Discussion of this article


 Feedback |  Paradox Day |  Who Uses Paradox |  I Use Paradox |  Downloads 


 The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation.
 Paradox is a registered trademark of Corel Corporation.


 Modified: 15 May 2003
 Terms of Use / Legal Disclaimer


 Copyright © 2001- 2003 Paradox Community. All rights reserved. 
 Company and product names are trademarks or registered trademarks of their respective companies. 
 Authors hold the copyrights to their own works. Please contact the author of any article for details.