C-Compiler Requirements for Callbacks in Microsoft Windows 3.x

When you use Microsoft 16-bit Visual C/C++ to develop your RPC application for Microsoft Windows 3.x platforms, compile with the /GA switch. The /GA switch directs the compiler to generate code that loads the DS register from the SS register on entry to a far exported function in a protected-mode application based on Windows 3.x.

For protected-mode, 16-bit Windows applications, the /GA switch allows the C compiler to generate the code for performing the housekeeping chores required when switching between tasks. This code is needed when your RPC interface contains one or more callback functions. Without this code, these callback functions can fail at run time due to an incorrect DS value.

When you use compilers other than Microsoft 16-bit Visual C/C++, use the compiler switch that is equivalent to /GA.

Previous versions of the Microsoft C compiler and 16-bit Windows used calls to the Windows 3.x function MakeProcInstance, and the /Gw switch to generate this code. The /GA switch is a more efficient way to accomplish the same tasks.

When you do not compile using the /GA switch (for example, when you are using a compiler that does not support the /GA switch), your application must:

  1. Compile using the /Gw switch (or its equivalent).
  2. Add the client stub functions to the EXPORTS section of the application's DEF file.
  3. Replace function pointers in the the client stub function dispatch table with function pointers returned by MakeProcInstance.

The function dispatch table is part of the RPC_CLIENT_INTERFACE structure defined in the RPC header file RPCDCEP.H. For example, step 3 can be implemented using the following C code:

#include "hello.h"   // generated stub file
RPC_DISPATCH_FUNCTION Old, New;
HINSTANCE hInst;
RPC_CLIENT_INTERFACE * If = Hello_ClientIfHandle;
...
    for (i = 0; i < If->DispatchTable->DispatchTableCount; i++)
    {
       Old = If->DispatchTable->DispatchTable[i];
       New = (RPC_DISPATCH_FUNCTION) MakeProcInstance(Old, hInst);
       If->DispatchTable->DispatchTable[i] = New; // overwrite
    }
...