# EEAddIn Sample: Debugging Expression Evaluator Add-In

The EEAddin sample shows how to extend the native debugger expression evaluator using the Expression Evaluator Add-In API.

Security Note
This sample code is provided to illustrate a concept and should not be used in applications or Web sites, as it may not illustrate the safest coding practices.

# EE Add-In API

The expression evaluator is the part of the debugger that interprets (evaluates) expressions. When you set a breakpoint on an expression or type an expression in a debugger window, the expression evaluator interprets the input. For details, see Expressions in the Debugger. With the Expression Evaluator Add-In API, you can extend the expression evaluator to handle new types.

To extend the expression evaluator for a new type, you need to write a function as part of a Win32 DLL (in the same directory as autoexp.dat) and export it by name. You also need to add a line to the autoexp.dat file. You can extend the expression evaluator for more than one type by exporting multiple functions from the DLL.

# Building and Running the Sample

The steps required to build and run this sample fall into three parts.

Note
If you are running Visual C++ Express Edition, you might need to install the Platform SDK before running this sample. For information on how to do this, see How to: Use Visual C++ Express Edition with the Microsoft Platform SDK.

#### To build and run the sample

1. Build an expression evaluator Add-In DLL (eeaddin.dll).

2. Edit autoexp.dat to use the expression evaluator Add-In DLL.

3. Test the Add-In by creating a project that uses the custom data type evaluated by autoexp.dat.

The following procedures explain these steps in detail.

#### To build the expression evaluator Add-In DLL

1. In Visual Studio, open the solution eeaddin.sln.

2. From the Build menu, click Build.

3. Copy the resulting eeaddin.dll to your common7\ide directory (the same directory that contains devenv.exe).

4. From the File menu, click Close Solution.

#### To edit autoexp.dat

1. From the File menu, point to Open and click File.

2. In the Open File dialog box, find the file autoexp.dat (in the common7\packages\debugger directory) and click Open.

3. Edit autoexp.dat to add the following lines:

       _SYSTEMTIME=$ADDIN(eeaddin.dll,AddIn_SystemTime)
       _FILETIME=$ADDIN(eeaddin.dll,AddIn_FileTime)

   Save autoexp.dat.

#### To create a project that uses the custom data types

1. From the File menu, point to New and click Project.

2. In the New Project dialog box, highlight Visual C++ Projects, click MFC Application, enter a name for the project, and click OK.

3. In the MFC Application Wizard, click Finish. The project must be an MFC application because in the next step you will add MFC functions.

4. In the MFC application, add a SYSTEMTIME or FILETIME object.

       SYSTEMTIME *s = new SYSTEMTIME();
       FILETIME *f = new FILETIME();
       GetSystemTime(s);
       SystemTimeToFileTime(s,f);

5. From the Build menu, click Build.

6. Start debugging and examine your SYSTEMTIME or FILETIME objects in the watch window.

# How the Sample Works

To extend the expression evaluator for a custom data type, you write a custom viewer function in the expression evaluator Add-In DLL. The function uses a pointer to an object in the memory space of the program being debugged (not the memory space of the expression evaluator you are extending). You cannot use normal casts with this pointer. You must read it and the data it points to using a callback function. A callback pointer of type `DEBUGHELPER*` points to an object with various methods.

The syntax looks like this:

    HRESULT WINAPI CustomViewer(
       DWORD dwAddress,       // low 32-bits of address
       DEBUGHELPER *pHelper,  // callback pointer to access helper functions
       int nBase,             // decimal or hex
       BOOL bIgnore,          // not used
       char *pResult,         // where the result needs to go
       size_t max,            // how large the above buffer is
       DWORD dwReserved       // always pass zero
    )

The sample has two implementations of this type of function, `AddIn_SystemTime` and `AddIn_FileTime` in timeaddin.cpp. The `DEBUGHELPER` struct (defined in custview.h) consists of function pointers that can assist you in writing your extension. This pointer is passed to your `CustomViewer` function, and you can use it to call the helper functions.

You can get the processor type with `pHelper->GetProcessorType`. There are two methods for reading memory, `pHelper->ReadDebuggeeMemory` and `pHelper->ReadDebuggeeMemoryEx`. `ReadDebuggeeMemoryEx` handles 64-bit addresses and is supported by the Visual Studio .NET debugger. `ReadDebuggeeMemory` does not handle 64-bit addresses and is supported by the Visual Studio .NET and Visual C++ 6.0 debuggers. If your Add-In is designed for the Visual Studio .NET debugger only, you can use `ReadDebuggeeMemoryEx`. If your Add-In needs to work with Visual C++ 6.0 also, you must check the `dwVersion` field and avoid calling `ReadDebuggeeMemoryEx` for Visual C++ 6.0.

The following code works with both debuggers and reads the contents of a localobject (whose type is `MyType`) from the program being debugged:

    DWORDLONG qwRealAddress;
    DWORD dwGot;
    MyType localobject;
    if (pHelper->dwVersion<0x20000)
    {
       // Visual C++ 6.0 version
       qwRealAddress = dwAddress;
       pHelper->ReadDebuggeeMemory( pHelper, dwAddress,
          sizeof(localobject), &localobject, &dwGot );
    }
    else
    {
       qwRealAddress = pHelper->GetRealAddress(pHelper);
       pHelper->ReadDebuggeeMemoryEx( pHelper, qwRealAddress,
          sizeof(localobject), &localobject, &dwGot );
    }
    // TODO: display localobject here

# Editing autoexp.dat

In the `[AutoExpand]` section of autoexp.dat, the lines you will add have the following syntax:

    type=$ADDIN(dllname.dll,exportname)

For example:

    _SYSTEMTIME=$ADDIN(eeaddin.dll,AddIn_SystemTime)

or:

    _FILETIME=$ADDIN(eeaddin.dll,AddIn_FileTime)

If the DLL is not in the directory containing devenv.exe or on the PATH, you must use a full path name for the DLL. The exportname argument is case sensitive and must exactly match the exported name you got when you ran `dumpbin –exports` on your DLL.

To test the debugger with the new Add-In, first stop debugging any program you were debugging when you installed the new DLL, and then start a new debugger session.

Note The Add-In runs within the debugger, so if your code crashes, you will crash the IDE.