Special Considerations

The Windows operating system requires error and message handling for DB-Library to be installed as exported callback functions.

When the Windows operating system executes a callback function, the data segment register is not set to the application's data segment, even though the error handler is part of the application. Declare the error and message handlers using
_ _export (or declare the functions as EXPORT in the .DEF file) to cause Windows to set up the data segment register correctly so that your handlers can access the application's data.

To create an error handler or message handler, first make the function into a procedure instance. To do this, call MakeProcInstance in your initialization code or in the application's message loop. The following example shows the call in the application's message loop:

long FAR PASCAL MySqlWndProc(hWnd, message, wParam, lParam)
HWND hWnd;          // window handle 
unsigned message;   // type of message 
WORD wParam;        // additional information 
LONG lParam;        // additional information 
{
        .
        .
        .

    static FARPROC lpMyMessageHandler;  // pointer to message handler
    static FARPROC lpMyErrorHandler;    // pointer to error handler 
    int cdecl FAR MyMessageHandler(DBPROCESS *,DBINT, DBSMALLINT,
        DBSMALLINT, LPSTR, LPSTR, LPSTR, DBUSMALLINT);
    int cdecl FAR MyErrorHandler(DBPROCESS *, int, int, int, LPSTR, 
        LPSTR);

    switch (message) {
        .
        .
        .

    case WM_CREATE:    // message: window being created 
        // Make the message and error handler instances. 
        lpMyMessageHandler =
            MakeProcInstance((FARPROC)MyMessageHandler, hInst);
        lpMyErrorHandler =
            MakeProcInstance((FARPROC)MyErrorHandler, hInst);

        // Install the instances into DBLIB. 
        dbmsghandle(lpMyMessageHandler);
        dberrhandle(lpMyErrorHandler);
        .
        .
        .

Making the FARPROC variables static allows you to free them during WM_DESTROY message processing:

.
    .
    .
case WM_DESTROY:         // message: window being destroyed 
    FreeProcInstance(lpMyMessageHandler);   // release handlers 
    FreeProcInstance(lpMyErrorHandler);
    PostQuitMessage(0);
    dbwinexit(); 
    break;
    .
    .
    .

Note that callback functions in the Windows operating system are normally declared FAR PASCAL, but not with these two callback functions for DB-Library (MyErrorHandler and MyMessageHandler). DB-Library expects all function calls to be cdecl FAR. Consequently, your handlers must also be cdecl FAR, as shown in the following example:

int cdecl FAR MyErrorHandler(dbproc, severity, errno,
    oserr, dberrstr, oserrstr);

Because this function declaration type is contrary to the FARPROC declaration type in MakeProcInstance, you must cast the function name as FARPROC.

Also, you must pass the FARPROC pointers returned from MakeProcInstance to dberrhandle and dbmsghandle to install the handlers properly. Passing the addresses of the handler functions instead of the procedure instances causes unpredictable results.

Finally, you must export the functions so that the Windows environment will correctly fix the segment references. In your .DEF file, add the following lines to the EXPORTS section:

_MyMessageHandler x      ; message handler
_MyErrorHandler y    ; error handler

Note that the function names begin with an underscore ( _ ); this is because with cdecl, the compiler automatically adds the underscore to the function name. The x and y are replaced with numbers for the number of your exported functions. See the sample Windows-based application for examples of installing error and message handlers.