tclWinLoad.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

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