Sunday, April 17, 2011

Debug Monitor string

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.
SetEvent
ResetEvent
CreateEvent
CloseHandle
CreateFileMapping
MapViewOfFile
UnmapViewOfFile
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)
    {

Read more: Codeproject