/*
* 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.
*
* RCS: @(#) $Id: tclWin32Dll.c,v 1.4 1998/09/14 18:40:19 stanton Exp $
*/
#include "tkWinInt.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. */
static int tclPlatformId; /* Running under NT, 95, or Win32s? */
/*
* 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));
#ifdef __WIN32__
#ifndef STATIC_BUILD
/*
*----------------------------------------------------------------------
*
* 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:
if (tclProcessesAttached++) {
return FALSE; /* Not the first initialization. */
}
TclWinInit(hInst);
return TRUE;
case DLL_PROCESS_DETACH:
tclProcessesAttached--;
if (tclProcessesAttached == 0) {
Tcl_Finalize();
}
break;
}
return TRUE;
}
#endif /* !STATIC_BUILD */
#endif /* __WIN32__ */
/*
*----------------------------------------------------------------------
*
* TclWinInit --
*
* This function initializes the internal state of the tcl library.
*
* Results:
* None.
*
* Side effects:
* Initializes the 16-bit thunking library, and the tclPlatformId
* variable.
*
*----------------------------------------------------------------------
*/
void
TclWinInit(hInst)
HINSTANCE hInst; /* Library instance handle. */
{
OSVERSIONINFO os;
tclInstance = hInst;
os.dwOSVersionInfoSize = sizeof(os);
GetVersionEx(&os);
tclPlatformId = os.dwPlatformId;
/*
* The following code stops Windows 3.x from automatically putting
* up Sharing Violation dialogs, e.g, when someone tries to
* access a file that is locked or a drive with no disk in it.
* Tcl already returns the appropriate error to the caller, and they
* can decide to put up their own dialog in response to that failure.
*
* Under 95 and NT, the system doesn't automatically put up dialogs
* when the above operations fail.
*/
if (tclPlatformId == VER_PLATFORM_WIN32s) {
SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS);
}
}
/*
*----------------------------------------------------------------------
*
* TclpFinalize --
*
* Clean up the Windows specific library state.
*
* Results:
* None.
*
* Side effects:
* Unloads any DLLs and cleans up the thunking library, if
* necessary.
*
*----------------------------------------------------------------------
*/
void
TclpFinalize()
{
/*
* Unregister the Tcl thunk.
*/
if (UTUnRegister != NULL) {
UTUnRegister(tclInstance);
UTUnRegister = NULL;
}
break;
}
/*
* Cleanup any dynamically loaded libraries.
*/
UnloadLibraries();
}
#if 0
/*
*----------------------------------------------------------------------
*
* 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((char*)libraryList);
libraryList = ptr;
}
}
/*
*----------------------------------------------------------------------
*
* TclWinSynchSpawn --
*
* 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
TclWinSynchSpawn(void *args, int type, void **trans, Tcl_Pid *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;
}
#endif
/*
*----------------------------------------------------------------------
*
* TclWinGetTclInstance --
*
* Retrieves the global library instance handle.
*
* Results:
* Returns the global library instance handle.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
HINSTANCE
TclWinGetTclInstance()
{
return tclInstance;
}
/*
*----------------------------------------------------------------------
*
* TclWinGetPlatformId --
*
* Determines whether running under NT, 95, or Win32s, to allow
* runtime conditional code.
*
* Results:
* The return value is one of:
* VER_PLATFORM_WIN32s Win32s on Windows 3.1.
* VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95.
* VER_PLATFORM_WIN32_NT Win32 on Windows NT
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclWinGetPlatformId()
{
return tclPlatformId;
}