os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/tclWinLoad.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* 
sl@0
     2
 * tclWinLoad.c --
sl@0
     3
 *
sl@0
     4
 *	This procedure provides a version of the TclLoadFile that
sl@0
     5
 *	works with the Windows "LoadLibrary" and "GetProcAddress"
sl@0
     6
 *	API for dynamic loading.
sl@0
     7
 *
sl@0
     8
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
sl@0
     9
 *
sl@0
    10
 * See the file "license.terms" for information on usage and redistribution
sl@0
    11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    12
 *
sl@0
    13
 * RCS: @(#) $Id: tclWinLoad.c,v 1.15 2002/10/10 12:25:53 vincentdarley Exp $
sl@0
    14
 */
sl@0
    15
sl@0
    16
#include "tclWinInt.h"
sl@0
    17
sl@0
    18

sl@0
    19
/*
sl@0
    20
 *----------------------------------------------------------------------
sl@0
    21
 *
sl@0
    22
 * TclpDlopen --
sl@0
    23
 *
sl@0
    24
 *	Dynamically loads a binary code file into memory and returns
sl@0
    25
 *	a handle to the new code.
sl@0
    26
 *
sl@0
    27
 * Results:
sl@0
    28
 *	A standard Tcl completion code.  If an error occurs, an error
sl@0
    29
 *	message is left in the interp's result.
sl@0
    30
 *
sl@0
    31
 * Side effects:
sl@0
    32
 *	New code suddenly appears in memory.
sl@0
    33
 *
sl@0
    34
 *----------------------------------------------------------------------
sl@0
    35
 */
sl@0
    36
sl@0
    37
int
sl@0
    38
TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
sl@0
    39
    Tcl_Interp *interp;		/* Used for error reporting. */
sl@0
    40
    Tcl_Obj *pathPtr;		/* Name of the file containing the desired
sl@0
    41
				 * code (UTF-8). */
sl@0
    42
    Tcl_LoadHandle *loadHandle;	/* Filled with token for dynamically loaded
sl@0
    43
				 * file which will be passed back to 
sl@0
    44
				 * (*unloadProcPtr)() to unload the file. */
sl@0
    45
    Tcl_FSUnloadFileProc **unloadProcPtr;	
sl@0
    46
				/* Filled with address of Tcl_FSUnloadFileProc
sl@0
    47
				 * function which should be used for
sl@0
    48
				 * this file. */
sl@0
    49
{
sl@0
    50
    HINSTANCE handle;
sl@0
    51
    CONST TCHAR *nativeName;
sl@0
    52
sl@0
    53
    /* 
sl@0
    54
     * First try the full path the user gave us.  This is particularly
sl@0
    55
     * important if the cwd is inside a vfs, and we are trying to load
sl@0
    56
     * using a relative path.
sl@0
    57
     */
sl@0
    58
    nativeName = Tcl_FSGetNativePath(pathPtr);
sl@0
    59
    handle = (*tclWinProcs->loadLibraryProc)(nativeName);
sl@0
    60
    if (handle == NULL) {
sl@0
    61
	/* 
sl@0
    62
	 * Let the OS loader examine the binary search path for
sl@0
    63
	 * whatever string the user gave us which hopefully refers
sl@0
    64
	 * to a file on the binary path
sl@0
    65
	 */
sl@0
    66
	Tcl_DString ds;
sl@0
    67
        char *fileName = Tcl_GetString(pathPtr);
sl@0
    68
	nativeName = Tcl_WinUtfToTChar(fileName, -1, &ds);
sl@0
    69
	handle = (*tclWinProcs->loadLibraryProc)(nativeName);
sl@0
    70
	Tcl_DStringFree(&ds);
sl@0
    71
    }
sl@0
    72
sl@0
    73
    *loadHandle = (Tcl_LoadHandle) handle;
sl@0
    74
    
sl@0
    75
    if (handle == NULL) {
sl@0
    76
	DWORD lastError = GetLastError();
sl@0
    77
#if 0
sl@0
    78
	/*
sl@0
    79
	 * It would be ideal if the FormatMessage stuff worked better,
sl@0
    80
	 * but unfortunately it doesn't seem to want to...
sl@0
    81
	 */
sl@0
    82
	LPTSTR lpMsgBuf;
sl@0
    83
	char *buf;
sl@0
    84
	int size;
sl@0
    85
	size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
sl@0
    86
		FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, lastError, 0,
sl@0
    87
		(LPTSTR) &lpMsgBuf, 0, NULL);
sl@0
    88
	buf = (char *) ckalloc((unsigned) TCL_INTEGER_SPACE + size + 1);
sl@0
    89
	sprintf(buf, "%d %s", lastError, (char *)lpMsgBuf);
sl@0
    90
#endif
sl@0
    91
	Tcl_AppendResult(interp, "couldn't load library \"",
sl@0
    92
			 Tcl_GetString(pathPtr), "\": ", (char *) NULL);
sl@0
    93
	/*
sl@0
    94
	 * Check for possible DLL errors.  This doesn't work quite right,
sl@0
    95
	 * because Windows seems to only return ERROR_MOD_NOT_FOUND for
sl@0
    96
	 * just about any problem, but it's better than nothing.  It'd be
sl@0
    97
	 * even better if there was a way to get what DLLs
sl@0
    98
	 */
sl@0
    99
	switch (lastError) {
sl@0
   100
	    case ERROR_MOD_NOT_FOUND:
sl@0
   101
	    case ERROR_DLL_NOT_FOUND:
sl@0
   102
		Tcl_AppendResult(interp, "this library or a dependent library",
sl@0
   103
			" could not be found in library path",
sl@0
   104
			(char *) NULL);
sl@0
   105
		break;
sl@0
   106
	    case ERROR_PROC_NOT_FOUND:
sl@0
   107
		Tcl_AppendResult(interp, "could not find specified procedure",
sl@0
   108
			(char *) NULL);
sl@0
   109
		break;
sl@0
   110
	    case ERROR_INVALID_DLL:
sl@0
   111
		Tcl_AppendResult(interp, "this library or a dependent library",
sl@0
   112
			" is damaged", (char *) NULL);
sl@0
   113
		break;
sl@0
   114
	    case ERROR_DLL_INIT_FAILED:
sl@0
   115
		Tcl_AppendResult(interp, "the library initialization",
sl@0
   116
			" routine failed", (char *) NULL);
sl@0
   117
		break;
sl@0
   118
	    default:
sl@0
   119
		TclWinConvertError(lastError);
sl@0
   120
		Tcl_AppendResult(interp, Tcl_PosixError(interp),
sl@0
   121
			(char *) NULL);
sl@0
   122
	}
sl@0
   123
	return TCL_ERROR;
sl@0
   124
    } else {
sl@0
   125
	*unloadProcPtr = &TclpUnloadFile;
sl@0
   126
    }
sl@0
   127
    return TCL_OK;
sl@0
   128
}
sl@0
   129

sl@0
   130
/*
sl@0
   131
 *----------------------------------------------------------------------
sl@0
   132
 *
sl@0
   133
 * TclpFindSymbol --
sl@0
   134
 *
sl@0
   135
 *	Looks up a symbol, by name, through a handle associated with
sl@0
   136
 *	a previously loaded piece of code (shared library).
sl@0
   137
 *
sl@0
   138
 * Results:
sl@0
   139
 *	Returns a pointer to the function associated with 'symbol' if
sl@0
   140
 *	it is found.  Otherwise returns NULL and may leave an error
sl@0
   141
 *	message in the interp's result.
sl@0
   142
 *
sl@0
   143
 *----------------------------------------------------------------------
sl@0
   144
 */
sl@0
   145
Tcl_PackageInitProc*
sl@0
   146
TclpFindSymbol(interp, loadHandle, symbol) 
sl@0
   147
    Tcl_Interp *interp;
sl@0
   148
    Tcl_LoadHandle loadHandle;
sl@0
   149
    CONST char *symbol;
sl@0
   150
{
sl@0
   151
    Tcl_PackageInitProc *proc = NULL;
sl@0
   152
    HINSTANCE handle = (HINSTANCE)loadHandle;
sl@0
   153
sl@0
   154
    /*
sl@0
   155
     * For each symbol, check for both Symbol and _Symbol, since Borland
sl@0
   156
     * generates C symbols with a leading '_' by default.
sl@0
   157
     */
sl@0
   158
sl@0
   159
    proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
sl@0
   160
    if (proc == NULL) {
sl@0
   161
	Tcl_DString ds;
sl@0
   162
	Tcl_DStringInit(&ds);
sl@0
   163
	Tcl_DStringAppend(&ds, "_", 1);
sl@0
   164
	symbol = Tcl_DStringAppend(&ds, symbol, -1);
sl@0
   165
	proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
sl@0
   166
	Tcl_DStringFree(&ds);
sl@0
   167
    }
sl@0
   168
    return proc;
sl@0
   169
}
sl@0
   170

sl@0
   171
/*
sl@0
   172
 *----------------------------------------------------------------------
sl@0
   173
 *
sl@0
   174
 * TclpUnloadFile --
sl@0
   175
 *
sl@0
   176
 *	Unloads a dynamically loaded binary code file from memory.
sl@0
   177
 *	Code pointers in the formerly loaded file are no longer valid
sl@0
   178
 *	after calling this function.
sl@0
   179
 *
sl@0
   180
 * Results:
sl@0
   181
 *	None.
sl@0
   182
 *
sl@0
   183
 * Side effects:
sl@0
   184
 *	Code removed from memory.
sl@0
   185
 *
sl@0
   186
 *----------------------------------------------------------------------
sl@0
   187
 */
sl@0
   188
sl@0
   189
void
sl@0
   190
TclpUnloadFile(loadHandle)
sl@0
   191
    Tcl_LoadHandle loadHandle;	/* loadHandle returned by a previous call
sl@0
   192
				 * to TclpDlopen().  The loadHandle is 
sl@0
   193
				 * a token that represents the loaded 
sl@0
   194
				 * file. */
sl@0
   195
{
sl@0
   196
    HINSTANCE handle;
sl@0
   197
sl@0
   198
    handle = (HINSTANCE) loadHandle;
sl@0
   199
    FreeLibrary(handle);
sl@0
   200
}
sl@0
   201

sl@0
   202
/*
sl@0
   203
 *----------------------------------------------------------------------
sl@0
   204
 *
sl@0
   205
 * TclGuessPackageName --
sl@0
   206
 *
sl@0
   207
 *	If the "load" command is invoked without providing a package
sl@0
   208
 *	name, this procedure is invoked to try to figure it out.
sl@0
   209
 *
sl@0
   210
 * Results:
sl@0
   211
 *	Always returns 0 to indicate that we couldn't figure out a
sl@0
   212
 *	package name;  generic code will then try to guess the package
sl@0
   213
 *	from the file name.  A return value of 1 would have meant that
sl@0
   214
 *	we figured out the package name and put it in bufPtr.
sl@0
   215
 *
sl@0
   216
 * Side effects:
sl@0
   217
 *	None.
sl@0
   218
 *
sl@0
   219
 *----------------------------------------------------------------------
sl@0
   220
 */
sl@0
   221
sl@0
   222
int
sl@0
   223
TclGuessPackageName(fileName, bufPtr)
sl@0
   224
    CONST char *fileName;	/* Name of file containing package (already
sl@0
   225
				 * translated to local form if needed). */
sl@0
   226
    Tcl_DString *bufPtr;	/* Initialized empty dstring.  Append
sl@0
   227
				 * package name to this if possible. */
sl@0
   228
{
sl@0
   229
    return 0;
sl@0
   230
}