> Home > Computer Q & A

From: campid
Date: 02/07/2003 02:08PM PST
Hi guys,

Is it possible to create a DLL that acts as a 'Proxy' between a program and its DLL?

Example:
progie.exe ->> ProxyDLL ->> DLL

The reason would be to monitor Calls to the DLL and act on them.

cheers,

James.

View Accepted Answer

Question History
Comment from brianegge 02/07/2003 02:24PM PST
This is very do able, and can vary in complixity.  The most common application of this is to proxy your winsock dll. (wsock32.dll)  A commercial program that does this is CYBERsitter '97.

If you are merely taking calls, looking at them, and then passing them onto the real function, this is more of a shim than a proxy.

TracePlus is an example of a commercial shim: http://www.sstinc.com/home_winsock.html

In order to write a shim, you have to export the exact same functions that the original DLL does.

An easy example of this is with MATLAB.  All toolkits export a single function.  It's easy to put a dll in place, view the arguments, and pass it onto the original dll.  What you basically need is a header file for the DLL.  From just the dll itself, it's hard to figure out the calling parameters.
Comment from webJose 02/07/2003 11:57PM PST
You can also do that with dll injection.
Comment from campid 02/09/2003 06:18AM PST
brainegge,

Do you have any code examples for creating a basic 'shim' for the wsock32.dll?

I havent played with dll's before, I mainly code classic console apps.

I'll have a quick search on google.

cheers, James.
Accepted Answer from brianegge 02/09/2003 08:51PM PST
I don't have an example of wsock32.dll, and the people who have made shims, sell the software itself.  Winsock is a pretty complex dll, but also useful.  If you havn't writen a dll before, than creating a shim would probably be a pretty daunting task.

Lets say we want to add some functionality to the Palm Desktop software.  A listing of my C:\Palm directory shows a alarmnotify.dll.  This might be interesting to watch.  So, I check to see how complex it is by using DUMPBIN:

C:\Palm>dumpbin /EXPORTS alarmNotify.dll
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file alarmNotify.dll

File Type: DLL

 Section contains the following exports for AlarmNotify.dll

          0 characteristics
   3D1B5732 time date stamp Thu Jun 27 14:19:30 2002
       0.00 version
          1 ordinal base
          2 number of functions
          2 number of names

   ordinal hint RVA      name

         1    0 0000104D GetNotifierVersion
         2    1 00001050 HS_Notify

 Summary

       4000 .data
       1000 .rdata
       1000 .reloc
       1000 .rsrc
       5000 .text

Ok, so we have two functions.  This shouldn't be so bad to shim.  But I need to know the function prototypes.  I don't know how to get this out of the dll, but if you have a header file, it's easy to see.  I found my needed document: http://www.orangetide.com/palm/Documentation/C++SyncReference.pdf

So, now I just have to create a replacement dll.  I rename the dll to RealAlarmNotify.dll and create a new Win32 Dynamic-Link Library called AlarmNotify.  Next, I ask the wizard to create me a DLL that exports some symbols.  

I change my AlarmNotify.h file to look like:

#ifdef ALARMNOTIFY_EXPORTS
#define ALARMNOTIFY_API __declspec(dllexport)
#else
#define ALARMNOTIFY_API __declspec(dllimport)
#endif

EXTERN_C ALARMNOTIFY_API DWORD GetNotifierVersion ();
EXTERN_C ALARMNOTIFY_API BOOL HS_Notify (int nCode, int nUserId);

and the AlarmNofity.cpp to:
// AlarmNotify.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "AlarmNotify.h"
#include "crtdbg.h"

HINSTANCE hinstLib = NULL;
typedef DWORD (__cdecl *fGetNotifierVersion)();
fGetNotifierVersion procGetNotifierVersion;
typedef BOOL (__cdecl *fHS_Notify)(int,int);
fHS_Notify procHS_Notify;

BOOL APIENTRY DllMain( HANDLE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
                         )
{
   switch (ul_reason_for_call)
    {
         case DLL_PROCESS_ATTACH:
         if (hinstLib == NULL)
         {
              LPCSTR dll = "C:\\Palm\\RealAlarmNotify";
              hinstLib = LoadLibrary(dll);
              _ASSERTE(hinstLib);
              procGetNotifierVersion = (fGetNotifierVersion) GetProcAddress(hinstLib, "GetNotifierVersion");
              procHS_Notify = (fHS_Notify) GetProcAddress(hinstLib, "HS_Notify");
         }
         case DLL_THREAD_ATTACH:
         case DLL_THREAD_DETACH:
         case DLL_PROCESS_DETACH:
              break;
   }
   return TRUE;
}

ALARMNOTIFY_API DWORD GetNotifierVersion ()
{
    DWORD result = procGetNotifierVersion();
    // Log result or something
    return result;
}
ALARMNOTIFY_API BOOL HS_Notify (int nCode, int nUserId)
{
    BOOL result = procHS_Notify(nCode,nUserId);
    // Log result or something
    return result;
}

I change the my project settings to create the dll in the C:\Palm directory, and I compile, and then debug by running HOTSYNC.EXE.  When HOTSYNC loads AlarmNotify.dll, I in turn load RealAlarmNotify.  I can set break points and set the in and out params of the functions.

There are probably easier ways of doing this.  This is the way I know how.  Hope it helps.
Comment from brianegge 02/21/2003 10:58AM PST
CampId, did this give you an idea of what you need to do?
Comment from campid 03/07/2003 01:19PM PST
great!! many thanks.