Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Debug Monitor string

0.00/5 (No votes)
31 Dec 2003 1  
Hooking to debug shared memory.

Sample screenshot

Sample screenshot

Introduction

Code Project is not only distributing millions of programming ideas but it also is reducing coding time. There are a number of classes ready in sample applications which can be used directly in your new application with or without modification, thus it is reducing the time in coding.

So, I thought let me contribute my code also. Even though it is simple and nothing new, may be it will be useful for others.

How to hook into debug shared memory

Trace statement writes in DBWIN_BUFFER shared file. It also uses DBWIN_DATA_READY and DBWIN_BUFFER_READY events to sync read and write operations in shared memory. To read from this shared memory file and signal event, followings function are required.

  1. SetEvent
  2. ResetEvent
  3. CreateEvent
  4. CloseHandle
  5. CreateFileMapping
  6. MapViewOfFile
  7. UnmapViewOfFile
  8. WaitForSingleObject

These functions are in kernel32.dll. There are two options to use this function in managed code.

  • COM wrapper - around 20 machine instructions overhead.
  • P/Invoke - around 5 machine instructions overhead.

I chose P/Invoke because it is faster compared to COM wrapper.

DLLImports

Here are all the import signatures.

//SET EVENT

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean SetEvent(IntPtr hEvent);

//RESET EVENT

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean ResetEvent(IntPtr hEvent);

//OPEN EVENT

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr OpenEvent(UInt32 
dwDesiredAccess,Boolean bInheritHandle,String lpName);

//GET LAST ERROR

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern UInt32 GetLastError();

//CREATE EVENT

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr CreateEvent(IntPtr 
lpEventAttributes,Boolean bManualReset,Boolean bInitialState,String lpName);

//CLOSE HANDLE

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean CloseHandle(IntPtr hObject);

//CREATE FILE MAPPING

[DllImport("Kernel32")]
private static extern IntPtr CreateFileMapping(IntPtr hFile, 
  IntPtr pAttributes, UInt32 flProtect,UInt32 dwMaximumSizeHigh, 
  UInt32 dwMaximumSizeLow, String pName);

//MAP VIEW FILE

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr 
  MapViewOfFile(IntPtr hFileMappingObject, 
  UInt32 dwDesiredAccess,UInt32 dwFileOffsetHigh, 
  UInt32 dwFileOffsetLow,UInt32 dwNumberOfBytesToMap);

//UNMAP VIEW FILE

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean UnmapViewOfFile(IntPtr lpBaseAddress);

//WAIT FOR SINGLE OBJECT

[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle,
  Int32 dwMilliseconds);

Hook

Here is the code to create sync events and to map memory file:

public bool Initialize(out String szError){
    bool bResult = false;
    szError = "";
     
    //create ready event

    m_hReady = m_oNative.win32CreateEvent(IntPtr.Zero,
                    false,false,"DBWIN_DATA_READY");
    if(m_hReady != IntPtr.Zero)
    {
        //create ack event

        m_hAck = m_oNative.win32CreateEvent(IntPtr.Zero,
                    false,false,"DBWIN_BUFFER_READY");
        if(m_hAck != IntPtr.Zero)
        {
            //create shared file

            m_hSharedFile = 
              m_oNative.win32CreateFileMapping(CWin32.InvalidHandleValue,
              IntPtr.Zero,CWin32.PAGE_READWRITE,0,1024,"DBWIN_BUFFER");
            if(m_hSharedFile != IntPtr.Zero)
            {
                //map shared file

                m_hShareAddress = 
                  m_oNative.win32MapViewOfFile(m_hSharedFile,
                  CWin32.FILE_MAP_READ,0,0,512);
                if(m_hShareAddress != IntPtr.Zero)
                {
                    bResult = true;
                }
                else
                {
                    szError = "Error to map file";
                }
            }
            else
            {
                szError = "Error to create memory map file DBWIN_BUFFER";
            }
        }
        else
        {
            szError = "Error to create event DBWIN_BUFFER_READY";
        }
    }
    else
    {
        szError = "Error to create event DBWIN_DATA_READY";
    }
    return bResult;
}

Wait for Data

public staticvoid Run()
{
    m_oNative.win32SetEvent(m_hAck);
    while(fRunning)
    {
        m_oNative.win32WaitForSingleObject(m_hReady,-1);
        UInt32 nApp = (UInt32)Marshal.ReadInt32(m_hShareAddress);
        Byte[] data = new Byte[2000];
        for(int i =0; i < 2000; i++)
        {
            Byte temp = Marshal.ReadByte(m_hShareAddress,i+4);
            if(temp == 13 || temp == 0)
                break;
            data[i] = temp;
        }
        System.Text.Encoding myASCII = System.Text.Encoding.ASCII;
        String szData = myASCII.GetString(data);
        int nIndex = szData.IndexOf("\0");
        if(nIndex != -1)
            szData = szData.Substring(0,nIndex);
        szData = szData.Trim();
        DebugDataEventArgs args = new DebugDataEventArgs(nApp,szData);
        CDebugHelper.DbgHandler(args);
        m_oNative.win32SetEvent(m_hAck);
    }
}

UnHook

public bool DeInitialize()
{
    bool bResult = false;
    //Close ready event handle

    if(m_oNative.win32CloseHandle(m_hReady))
    {
        //Close ack event handle

        if(m_oNative.win32CloseHandle(m_hAck))
        {
            //Unmap view file

            if(m_oNative.win32UnmapViewOfFile(m_hShareAddress))
            {
                bResult = true;
            }
        }
    }
    return bResult; 
}

Testing

There are three test applications included with this.

  • ConDms.exe - console version of debug monitor string.
  • WinDms.exe - windows version of debug monitor string.
  • Test.exe - test program to send trace string.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here