archie/tcl7.6/win/tclWin32Dll.c

312 lines
6.9 KiB
C
Raw Normal View History

2024-05-27 16:40:40 +02:00
/*
* 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;
}