Microsoft KB Archive/105346
Article ID: 105346
Article Last Modified on 2/22/2005
- Microsoft SQL Server 4.21a Standard Edition
- Microsoft SQL Server 6.5 Standard Edition
This article was previously published under Q105346
Writing a user-defined dynamic link library (DLL) for Windows to access DB-Library functions requires special considerations. One consideration that is specific to DB-Library is that a DLL cannot share DBPROCESS connections or error and message handlers between applications. This is because a DLL can be called from many different concurrently running applications.
A DLL runs under the context of the program that called it. This is important because DB-Library tracks data for each active application separately. This per-process data includes DBPROCESS connections and pointers to the error and message handlers. DB-Library does this by registering the calling application's Windows task handle when dbinit() is called, and uses that to identify all of the DB-Library data associated with that application. The dbwinexit() function "unregisters" the application, and de-allocates the data associated with the process.
In addition, DB-Library for Windows validates each DBPROCESS connection before using it, using the Windows task handle of the calling application.
If you try to share a DBPROCESS between multiple applications, the following occurs:
- Suppose application APPONE calls your DLL. You do a dbinit(), use dbopen() to get a DBPROCESS connection, and start accessing SQL Server.
- Now suppose application APPTWO calls your DLL, and your DLL attempts to use the same DBPROCESS (the one your DLL got while running under APPONE) in a call to dbcmd() or any other DB-Library function.
- Since your DLL is running under APPTWO's context, DB-Library will search for the registration of APPTWO, and not finding it will return FAIL.
There are many approaches to handling DB-Library calls in a DLL. Some of the most common are covered below:
One way is to have each application do its own dbinit() and dbopen(), register its own error and message handlers, and pass the DBPROCESS pointer as a parameter to the DLL functions. When the application is done, it will call dbwinexit().
A second option is to have each of your DLL's functions call dbinit(), register the error and message handlers, call dbopen(), use the DBPROCESS, then call dbwinexit().
Another option is for your DLL to provide a dll_init() and dll_exit() function, which are called by each application that wants to use your DLL. The dll_init() function would call dbinit() and dbopen(), install the error and message handlers, and return the dbproc to the calling routine. Then the dll_exit() function would call dbwinexit(). The calling application would pass back the dbproc on each call to your DLL.
Additional query words: DB-Library dblib Dynamic Link Library
Keywords: kbinfo kbprogramming KB105346