Click here to Skip to main content
15,883,868 members
Articles / Programming Languages / C
Tip/Trick

Debug with RPC

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
25 Apr 2012CPOL5 min read 14.6K   247   2   1
Life debug plug-in of non debugable host

Introduction

This tip is not for NMAKE experts.

Background

At start we have our project cool_addon.dll that is intended for use with a non-debugable host. In practice such are most add-ons for known big applications like AutoCAD or IE. Here is an abstract sample of how to debug such an add-on with minimal recanting from a common developing process. As a base we use an ubiquitous Hello World from PSDK. This sample is live but uses a wide protocol that does not want to work on my single local machine. But MSDN has notes about the same project with a pipe oriented connection. It is a fish to consolidate them, all working as described. This NMAKE project has the main structure of our debug solution. Only things missing are compatible wrappers on both ends. Thus we begin.

Using the code

I use VS9 so all comments are about this environment.

First create a separate solution, and at once create a BlackBox - host simulator.  It used to study developing this system. BlackBox must load cool_addon.dll and make its testing calls. Place a reference to the compiled release at a convenient place like Service->External tools or near shortcut.

Next create an optional empty project rpc_core_dbg. To avoid compile errors set it as the tool project or .lib maybe. This project only launches MIDL, the purpose is not binary, RPC code only. Add a renamed copy of .idl and .acf from 'Hello world'. In my case VS does not understand the .acf format and I excluded it from compiling. It is reached with MIDL settings. Changing interface the name, uuid and implicit_handle name are not required, as you wish. The content of the interface can be fully cleared except the Shutdown function. It will be used for debugging the control. Now to the body of the interface declaration add declarations of functions listed in your .def, suffix/prefix and attribute them as demand RPC. Rename functions needed to be distinguish RCP from target to bind. Here it is all pithiness of the content of this project - create RPC transport code with compatible interface. To generate the common way, in project settings change the MIDL output header to rpc_core_dbg.h and output the path to  $(SolutionDir) for simply reaching current result - rpc_core_dbg.h, rpc_core_dbg_c.c, rpc_core_dbg_s.c in the relative projects. Where the .c generated transport code is for implementation on the appropriate end. rpc_core_dbg.h is solely for this transport. Extend MIDL command line with

/acf rpc_core_dbg.acf /client stub /server stub /rpcss /target NT51

This switches subjects for experiment, as do other MIDL settings. Performing the compilation of this project real only generates code, no binary executable. So it must be excluded from any configuration, because _.c files still need correction and surplus regeneration will harm its full ready view. Other settings has no effect on this task. I clear them.

The host simulator is on, now the client stub.  Add to solution new DLL project face_addon that fully repeated main cool_addon with settings and dll interface. Best way is using the same .def directly from source project and other shared files from solution top, so set additional include directoryes to $(SolutionDir). Add to this project rpc_core_dbg.h rpc_core_dbg_c.c . Set output binary name as original cool_addon.dll. Generally it is wrapper to rpc calls with interface of original cool_addon.dll. Changes about rpc for dllmain are borrowed from Hello project. Preparing and finalising of rpc calls united to singles at begin and to unloading library respectively. Clear prc is not wait apperance of target. It return error and client continues self wait in this situation. Simplest compilation will rise C1853 - C++c disaccord on rpc_core_dbg_c.c . It require separate .pch. Setting for precompiled header of this file: Create new nonStdAfx.h, named other.pch. But compiler again rises C1189 - version wrong, MIDL defines it for self only.  Well, strictly define required version:

C++
#ifdef TARGET_IS_NT51_OR_LATER
#undef TARGET_IS_NT51_OR_LATER 
#endif
#define _TARGET_IS_NT51_OR_LATER 1

Anywhere inside nonStdAfx.h, I place it to shared targetver.h near others. Linker must have Rpcrt4.lib reference. Write it to project settings or like #pragma comment(lib, "Rpcrt4.lib") i place to StdAfx.h. Regenerated by MIDL rpc_core_dbg_c.c   not conatains required reference to its precompiled header #include "nonStdAfx.h".   I am add this stroke handly each time. That is "payment")  lazy write corrector).

Last step - server stub and back wrapper. Create executable Debugee project, not principal console or window. Anywhere call RPC server implementation. RPC server never leaved listen mode and is invisible/nonobstacle for debugging. So calm debugee seems like deadlock. RPC activity occurs direct in interface implementation where we place target call. Any requirements are the same as for client. Exept rpc_core_dbg_s.c using, note - _s postfix. Rename in cool_addon project settings binary output as dbg_addon.dll and use it in Debugee. Renaming output required another .def for this name. Or point output of Debugee and cool_addon to another folder. Maybe you prefer superpose original code in one project as .exe when debug and target .dll on release. This allow skip wrappers on server side but obtain naming conflicts that of course can solved witn #if. In conjunction with separating output such config seems more beauty. But i gather worst variant here). Here very many words, graph inside attached zip can help to sort dependencies. 

Points of Interest

Test. What you launch first doesn't matter. Set breakpoints in the cool_addon project, input any stroke in the host simulator. Debug.

Preparing exchanges is separate theme. Interesting point - interface function: double ArrayStringMess_dbg([in,out, size_is( 3 ), string]char**pp); generates a MIDL2291 warning, but code still truly work in both directions.

Sorry for bad English. Good luck! 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Russian Federation Russian Federation
freelance

Comments and Discussions

 
QuestionSomebody understand this text ? Pin
Jasper4C#29-Apr-12 3:14
Jasper4C#29-Apr-12 3:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.