312 lines
6.9 KiB
C
312 lines
6.9 KiB
C
/*
|
||
* tclWin32Dll.c --
|
||
*
|
||
* This file contains the DLL entry point which sets up the 32-to-16-bit
|
||
* thunking code for SynchSpawn if the library is running under Win32s.
|
||
*
|
||
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
* SCCS: @(#) tclWin32Dll.c 1.15 96/09/12 15:10:59
|
||
*/
|
||
|
||
#include <windows.h>
|
||
#include "tcl.h"
|
||
#include "tclPort.h"
|
||
#include "tclWinInt.h"
|
||
|
||
typedef DWORD (WINAPI * UT32PROC)(LPVOID lpBuff, DWORD dwUserDefined,
|
||
LPVOID *lpTranslationList);
|
||
|
||
typedef BOOL (WINAPI * PUTREGISTER)(HANDLE hModule, LPCSTR SixteenBitDLL,
|
||
LPCSTR InitName, LPCSTR ProcName, UT32PROC* ThirtyTwoBitThunk,
|
||
FARPROC UT32Callback, LPVOID Buff);
|
||
|
||
typedef VOID (WINAPI * PUTUNREGISTER)(HANDLE hModule);
|
||
|
||
static PUTUNREGISTER UTUnRegister = NULL;
|
||
static int tclProcessesAttached = 0;
|
||
|
||
/*
|
||
* The following data structure is used to keep track of all of the DLL's
|
||
* opened by Tcl so that they can be freed with the Tcl.dll is unloaded.
|
||
*/
|
||
|
||
typedef struct LibraryList {
|
||
HINSTANCE handle;
|
||
struct LibraryList *nextPtr;
|
||
} LibraryList;
|
||
|
||
static LibraryList *libraryList = NULL; /* List of currently loaded DLL's. */
|
||
|
||
static HINSTANCE tclInstance; /* Global library instance handle. */
|
||
|
||
/*
|
||
* Declarations for functions that are only used in this file.
|
||
*/
|
||
|
||
static void UnloadLibraries _ANSI_ARGS_((void));
|
||
|
||
/*
|
||
* The following declaration is for the VC++ DLL entry point.
|
||
*/
|
||
|
||
BOOL APIENTRY DllMain _ANSI_ARGS_((HINSTANCE hInst,
|
||
DWORD reason, LPVOID reserved));
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* DllEntryPoint --
|
||
*
|
||
* This wrapper function is used by Borland to invoke the
|
||
* initialization code for Tcl. It simply calls the DllMain
|
||
* routine.
|
||
*
|
||
* Results:
|
||
* See DllMain.
|
||
*
|
||
* Side effects:
|
||
* See DllMain.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
BOOL APIENTRY
|
||
DllEntryPoint(hInst, reason, reserved)
|
||
HINSTANCE hInst; /* Library instance handle. */
|
||
DWORD reason; /* Reason this function is being called. */
|
||
LPVOID reserved; /* Not used. */
|
||
{
|
||
return DllMain(hInst, reason, reserved);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* DllMain --
|
||
*
|
||
* This routine is called by the VC++ C run time library init
|
||
* code, or the DllEntryPoint routine. It is responsible for
|
||
* initializing various dynamically loaded libraries.
|
||
*
|
||
* Results:
|
||
* TRUE on sucess, FALSE on failure.
|
||
*
|
||
* Side effects:
|
||
* Establishes 32-to-16 bit thunk and initializes sockets library.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
BOOL APIENTRY
|
||
DllMain(hInst, reason, reserved)
|
||
HINSTANCE hInst; /* Library instance handle. */
|
||
DWORD reason; /* Reason this function is being called. */
|
||
LPVOID reserved; /* Not used. */
|
||
{
|
||
switch (reason) {
|
||
case DLL_PROCESS_ATTACH:
|
||
|
||
/*
|
||
* Registration of UT need to be done only once for first
|
||
* attaching process. At that time set the tclWin32s flag
|
||
* to indicate if the DLL is executing under Win32s or not.
|
||
*/
|
||
|
||
if (tclProcessesAttached++) {
|
||
return FALSE; /* Not the first initialization. */
|
||
}
|
||
|
||
tclInstance = hInst;
|
||
return TRUE;
|
||
|
||
case DLL_PROCESS_DETACH:
|
||
|
||
tclProcessesAttached--;
|
||
if (tclProcessesAttached == 0) {
|
||
|
||
/*
|
||
* Unregister the Tcl thunk.
|
||
*/
|
||
|
||
if (UTUnRegister != NULL) {
|
||
UTUnRegister(hInst);
|
||
}
|
||
|
||
/*
|
||
* Cleanup any dynamically loaded libraries.
|
||
*/
|
||
|
||
UnloadLibraries();
|
||
}
|
||
break;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TclWinLoadLibrary --
|
||
*
|
||
* This function is a wrapper for the system LoadLibrary. It is
|
||
* responsible for adding library handles to the library list so
|
||
* the libraries can be freed when tcl.dll is unloaded.
|
||
*
|
||
* Results:
|
||
* Returns the handle of the newly loaded library, or NULL on
|
||
* failure.
|
||
*
|
||
* Side effects:
|
||
* Loads the specified library into the process.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
HINSTANCE
|
||
TclWinLoadLibrary(name)
|
||
char *name; /* Library file to load. */
|
||
{
|
||
HINSTANCE handle;
|
||
LibraryList *ptr;
|
||
|
||
handle = LoadLibrary(name);
|
||
if (handle != NULL) {
|
||
ptr = (LibraryList*) ckalloc(sizeof(LibraryList));
|
||
ptr->handle = handle;
|
||
ptr->nextPtr = libraryList;
|
||
libraryList = ptr;
|
||
} else {
|
||
TclWinConvertError(GetLastError());
|
||
}
|
||
return handle;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* UnloadLibraries --
|
||
*
|
||
* Frees any dynamically allocated libraries loaded by Tcl.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Frees the libraries on the library list as well as the list.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
UnloadLibraries()
|
||
{
|
||
LibraryList *ptr;
|
||
|
||
while (libraryList != NULL) {
|
||
FreeLibrary(libraryList->handle);
|
||
ptr = libraryList->nextPtr;
|
||
ckfree(libraryList);
|
||
libraryList = ptr;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TclSynchSpawn --
|
||
*
|
||
* 32-bit entry point to the 16-bit SynchSpawn code.
|
||
*
|
||
* Results:
|
||
* 1 on success, 0 on failure.
|
||
*
|
||
* Side effects:
|
||
* Spawns a command and waits for it to complete.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
int
|
||
TclSynchSpawn(void *args, int type, void **trans, int *pidPtr)
|
||
{
|
||
static UT32PROC UTProc = NULL;
|
||
static int utErrorCode;
|
||
|
||
if (UTUnRegister == NULL) {
|
||
/*
|
||
* Load the Universal Thunking routines from kernel32.dll.
|
||
*/
|
||
|
||
HINSTANCE hKernel;
|
||
PUTREGISTER UTRegister;
|
||
char buffer[] = "TCL16xx.DLL";
|
||
|
||
hKernel = TclWinLoadLibrary("Kernel32.Dll");
|
||
if (hKernel == NULL) {
|
||
return 0;
|
||
}
|
||
|
||
UTRegister = (PUTREGISTER) GetProcAddress(hKernel, "UTRegister");
|
||
UTUnRegister = (PUTUNREGISTER) GetProcAddress(hKernel, "UTUnRegister");
|
||
if (!UTRegister || !UTUnRegister) {
|
||
UnloadLibraries();
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* Construct the complete name of tcl16xx.dll.
|
||
*/
|
||
|
||
buffer[5] = '0' + TCL_MAJOR_VERSION;
|
||
buffer[6] = '0' + TCL_MINOR_VERSION;
|
||
|
||
/*
|
||
* Register the Tcl thunk.
|
||
*/
|
||
|
||
if (UTRegister(tclInstance, buffer, NULL, "UTProc", &UTProc, NULL,
|
||
NULL) == FALSE) {
|
||
utErrorCode = GetLastError();
|
||
}
|
||
}
|
||
|
||
if (UTProc == NULL) {
|
||
/*
|
||
* The 16-bit thunking DLL wasn't found. Return error code that
|
||
* indicates this problem.
|
||
*/
|
||
|
||
SetLastError(utErrorCode);
|
||
return 0;
|
||
}
|
||
|
||
UTProc(args, type, trans);
|
||
*pidPtr = 0;
|
||
return 1;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TclWinGetTclInstance --
|
||
*
|
||
* Retrieves the global library instance handle.
|
||
*
|
||
* Results:
|
||
* Returns the global library instance handle.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
HINSTANCE
|
||
TclWinGetTclInstance()
|
||
{
|
||
return tclInstance;
|
||
}
|