diff options
author | stanton <stanton> | 1999-04-16 00:46:29 (GMT) |
---|---|---|
committer | stanton <stanton> | 1999-04-16 00:46:29 (GMT) |
commit | 97464e6cba8eb0008cf2727c15718671992b913f (patch) | |
tree | ce9959f2747257d98d52ec8d18bf3b0de99b9535 /win/tclWin32Dll.c | |
parent | a8c96ddb94d1483a9de5e340b740cb74ef6cafa7 (diff) | |
download | tcl-97464e6cba8eb0008cf2727c15718671992b913f.zip tcl-97464e6cba8eb0008cf2727c15718671992b913f.tar.gz tcl-97464e6cba8eb0008cf2727c15718671992b913f.tar.bz2 |
merged tcl 8.1 branch back into the main trunk
Diffstat (limited to 'win/tclWin32Dll.c')
-rw-r--r-- | win/tclWin32Dll.c | 543 |
1 files changed, 349 insertions, 194 deletions
diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c index 16c47c1..5a90b77 100644 --- a/win/tclWin32Dll.c +++ b/win/tclWin32Dll.c @@ -1,4 +1,5 @@ /* + * tclWin32Dll.c -- * * This file contains the DLL entry point which sets up the 32-to-16-bit @@ -9,50 +10,124 @@ * 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.5 1999/03/10 05:52:53 stanton Exp $ + * RCS: @(#) $Id: tclWin32Dll.c,v 1.6 1999/04/16 00:48:07 stanton Exp $ */ #include "tclWinInt.h" -typedef DWORD (WINAPI * UT32PROC)(LPVOID lpBuff, DWORD dwUserDefined, +/* + * The following data structures are used when loading the thunking + * library for execing child processes under Win32s. + */ + +typedef DWORD (WINAPI UT32PROC)(LPVOID lpBuff, DWORD dwUserDefined, LPVOID *lpTranslationList); -typedef BOOL (WINAPI * PUTREGISTER)(HANDLE hModule, LPCSTR SixteenBitDLL, - LPCSTR InitName, LPCSTR ProcName, UT32PROC* ThirtyTwoBitThunk, +typedef BOOL (WINAPI UTREGISTER)(HANDLE hModule, LPCSTR SixteenBitDLL, + LPCSTR InitName, LPCSTR ProcName, UT32PROC **ThirtyTwoBitThunk, FARPROC UT32Callback, LPVOID Buff); -typedef VOID (WINAPI * PUTUNREGISTER)(HANDLE hModule); +typedef VOID (WINAPI UTUNREGISTER)(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. +/* + * The following variables keep track of information about this DLL + * on a per-instance basis. Each time this DLL is loaded, it gets its own + * new data segment with its own copy of all static and global information. */ -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? */ +static HINSTANCE hInstance; /* HINSTANCE of this DLL. */ +static int platformId; /* Running under NT, 95, or Win32s? */ /* - * Declarations for functions that are only used in this file. + * The following function tables are used to dispatch to either the + * wide-character or multi-byte versions of the operating system calls, + * depending on whether the Unicode calls are available. */ -static void UnloadLibraries _ANSI_ARGS_((void)); +static TclWinProcs asciiProcs = { + 0, + + (BOOL (WINAPI *)(CONST TCHAR *, LPDCB)) BuildCommDCBA, + (TCHAR *(WINAPI *)(TCHAR *)) CharLowerA, + (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *, BOOL)) CopyFileA, + (BOOL (WINAPI *)(CONST TCHAR *, LPSECURITY_ATTRIBUTES)) CreateDirectoryA, + (HANDLE (WINAPI *)(CONST TCHAR *, DWORD, DWORD, SECURITY_ATTRIBUTES *, + DWORD, DWORD, HANDLE)) CreateFileA, + (BOOL (WINAPI *)(CONST TCHAR *, TCHAR *, LPSECURITY_ATTRIBUTES, + LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, CONST TCHAR *, + LPSTARTUPINFOA, LPPROCESS_INFORMATION)) CreateProcessA, + (BOOL (WINAPI *)(CONST TCHAR *)) DeleteFileA, + (HANDLE (WINAPI *)(CONST TCHAR *, WIN32_FIND_DATAT *)) FindFirstFileA, + (BOOL (WINAPI *)(HANDLE, WIN32_FIND_DATAT *)) FindNextFileA, + (BOOL (WINAPI *)(WCHAR *, LPDWORD)) GetComputerNameA, + (DWORD (WINAPI *)(DWORD, WCHAR *)) GetCurrentDirectoryA, + (DWORD (WINAPI *)(CONST TCHAR *)) GetFileAttributesA, + (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, + TCHAR **)) GetFullPathNameA, + (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameA, + (DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameA, + (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, + WCHAR *)) GetTempFileNameA, + (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathA, + (BOOL (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD, LPDWORD, LPDWORD, LPDWORD, + WCHAR *, DWORD)) GetVolumeInformationA, + (HINSTANCE (WINAPI *)(CONST TCHAR *)) LoadLibraryA, + (TCHAR (WINAPI *)(WCHAR *, CONST TCHAR *)) lstrcpyA, + (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileA, + (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryA, + (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, + WCHAR *, TCHAR **)) SearchPathA, + (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryA, + (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesA, +}; + +static TclWinProcs unicodeProcs = { + 1, + + (BOOL (WINAPI *)(CONST TCHAR *, LPDCB)) BuildCommDCBW, + (TCHAR *(WINAPI *)(TCHAR *)) CharLowerW, + (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *, BOOL)) CopyFileW, + (BOOL (WINAPI *)(CONST TCHAR *, LPSECURITY_ATTRIBUTES)) CreateDirectoryW, + (HANDLE (WINAPI *)(CONST TCHAR *, DWORD, DWORD, SECURITY_ATTRIBUTES *, + DWORD, DWORD, HANDLE)) CreateFileW, + (BOOL (WINAPI *)(CONST TCHAR *, TCHAR *, LPSECURITY_ATTRIBUTES, + LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, CONST TCHAR *, + LPSTARTUPINFOA, LPPROCESS_INFORMATION)) CreateProcessW, + (BOOL (WINAPI *)(CONST TCHAR *)) DeleteFileW, + (HANDLE (WINAPI *)(CONST TCHAR *, WIN32_FIND_DATAT *)) FindFirstFileW, + (BOOL (WINAPI *)(HANDLE, WIN32_FIND_DATAT *)) FindNextFileW, + (BOOL (WINAPI *)(WCHAR *, LPDWORD)) GetComputerNameW, + (DWORD (WINAPI *)(DWORD, WCHAR *)) GetCurrentDirectoryW, + (DWORD (WINAPI *)(CONST TCHAR *)) GetFileAttributesW, + (DWORD (WINAPI *)(CONST TCHAR *, DWORD nBufferLength, WCHAR *, + TCHAR **)) GetFullPathNameW, + (DWORD (WINAPI *)(HMODULE, WCHAR *, int)) GetModuleFileNameW, + (DWORD (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD)) GetShortPathNameW, + (UINT (WINAPI *)(CONST TCHAR *, CONST TCHAR *, UINT uUnique, + WCHAR *)) GetTempFileNameW, + (DWORD (WINAPI *)(DWORD, WCHAR *)) GetTempPathW, + (BOOL (WINAPI *)(CONST TCHAR *, WCHAR *, DWORD, LPDWORD, LPDWORD, LPDWORD, + WCHAR *, DWORD)) GetVolumeInformationW, + (HINSTANCE (WINAPI *)(CONST TCHAR *)) LoadLibraryW, + (TCHAR (WINAPI *)(WCHAR *, CONST TCHAR *)) lstrcpyW, + (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR *)) MoveFileW, + (BOOL (WINAPI *)(CONST TCHAR *)) RemoveDirectoryW, + (DWORD (WINAPI *)(CONST TCHAR *, CONST TCHAR *, CONST TCHAR *, DWORD, + WCHAR *, TCHAR **)) SearchPathW, + (BOOL (WINAPI *)(CONST TCHAR *)) SetCurrentDirectoryW, + (BOOL (WINAPI *)(CONST TCHAR *, DWORD)) SetFileAttributesW, +}; + +TclWinProcs *tclWinProcs; +static Tcl_Encoding tclWinTCharEncoding; /* * The following declaration is for the VC++ DLL entry point. */ -BOOL APIENTRY DllMain _ANSI_ARGS_((HINSTANCE hInst, - DWORD reason, LPVOID reserved)); +BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, + LPVOID reserved); + #ifdef __WIN32__ #ifndef STATIC_BUILD @@ -110,18 +185,24 @@ DllMain(hInst, reason, reserved) { switch (reason) { case DLL_PROCESS_ATTACH: - if (tclProcessesAttached++) { - return FALSE; /* Not the first initialization. */ + if (hInstance != NULL) { + /* + * Prevents DLL from being loaded multiple times under Win32s, + * since all copies of the DLL share the same data segment and + * Tcl isn't set up to handle that. Under NT or 95, each time + * the DLL is loaded, it gets its own private copy of the data + * segment. + */ + + return FALSE; } TclWinInit(hInst); return TRUE; case DLL_PROCESS_DETACH: - - tclProcessesAttached--; - if (tclProcessesAttached == 0) { - Tcl_Finalize(); + if (hInst == hInstance) { + Tcl_Finalize(); } break; } @@ -135,244 +216,206 @@ DllMain(hInst, reason, reserved) /* *---------------------------------------------------------------------- * - * TclWinInit -- + * TclWinSynchSpawn -- * - * This function initializes the internal state of the tcl library. + * 32-bit entry point to the 16-bit SynchSpawn code. * * Results: - * None. + * 1 on success, 0 on failure. * * Side effects: - * Initializes the 16-bit thunking library, and the tclPlatformId - * variable. + * Spawns a command and waits for it to complete. * *---------------------------------------------------------------------- */ - -void -TclWinInit(hInst) - HINSTANCE hInst; /* Library instance handle. */ +int +TclWinSynchSpawn(void *args, int type, void **trans, Tcl_Pid *pidPtr) { - OSVERSIONINFO os; - - tclInstance = hInst; - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx(&os); - tclPlatformId = os.dwPlatformId; + HINSTANCE hKernel; + UTREGISTER *utRegisterProc; + UTUNREGISTER *utUnRegisterProc; + UT32PROC *ut32Proc; + char buffer[] = "TCL16xx.DLL"; + int result; + + hKernel = LoadLibraryA("kernel32.dll"); + if (hKernel == NULL) { + return 0; + } /* - * 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. + * Load the Universal Thunking routines from kernel32.dll. */ - if (tclPlatformId == VER_PLATFORM_WIN32s) { - SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS); + utRegisterProc = (UTREGISTER *) GetProcAddress(hKernel, "UTRegister"); + utUnRegisterProc = (UTUNREGISTER *) GetProcAddress(hKernel, "UTUnRegister"); + if ((utRegisterProc == NULL) || (utUnRegisterProc == NULL)) { + result = 0; + goto done; } -} - -/* - *---------------------------------------------------------------------- - * - * 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. + * Construct the complete name of tcl16xx.dll. */ - if (UTUnRegister != NULL) { - UTUnRegister(tclInstance); - UTUnRegister = NULL; - } + buffer[5] = '0' + TCL_MAJOR_VERSION; + buffer[6] = '0' + TCL_MINOR_VERSION; /* - * Cleanup any dynamically loaded libraries. + * Register the Tcl thunk. */ - UnloadLibraries(); + if ((*utRegisterProc)(hInstance, buffer, NULL, "UTProc", &ut32Proc, + NULL, NULL) == FALSE) { + result = 0; + goto done; + } + if (ut32Proc != NULL) { + /* + * Invoke the thunk. + */ + + *pidPtr = 0; + (*ut32Proc)(args, type, trans); + result = 1; + } else { + /* + * The 16-bit thunking DLL wasn't found. Return error code that + * indicates this problem. + */ + + result = 0; + } + (*utUnRegisterProc)(hInstance); + + done: + FreeLibrary(hKernel); + return result; } /* *---------------------------------------------------------------------- * - * TclWinLoadLibrary -- + * TclWinGetTclInstance -- * - * 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. + * Retrieves the global library instance handle. * * Results: - * Returns the handle of the newly loaded library, or NULL on - * failure. + * Returns the global library instance handle. * * Side effects: - * Loads the specified library into the process. + * None. * *---------------------------------------------------------------------- */ HINSTANCE -TclWinLoadLibrary(name) - char *name; /* Library file to load. */ +TclWinGetTclInstance() { - 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; + return hInstance; } /* *---------------------------------------------------------------------- * - * UnloadLibraries -- + * TclWinInit -- * - * Frees any dynamically allocated libraries loaded by Tcl. + * This function initializes the internal state of the tcl library. * * Results: * None. * * Side effects: - * Frees the libraries on the library list as well as the list. + * Initializes the 16-bit thunking library, and the tclPlatformId + * variable. * *---------------------------------------------------------------------- */ -static void -UnloadLibraries() +void +TclWinInit(hInst) + HINSTANCE hInst; /* Library instance handle. */ { - LibraryList *ptr; + OSVERSIONINFO os; + + hInstance = hInst; + os.dwOSVersionInfoSize = sizeof(os); + GetVersionEx(&os); + platformId = os.dwPlatformId; - while (libraryList != NULL) { - FreeLibrary(libraryList->handle); - ptr = libraryList->nextPtr; - ckfree((char*)libraryList); - libraryList = ptr; + /* + * 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 (platformId == VER_PLATFORM_WIN32s) { + SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS); } + + tclWinProcs = &asciiProcs; } /* *---------------------------------------------------------------------- * - * TclWinSynchSpawn -- + * TclWinGetPlatformId -- * - * 32-bit entry point to the 16-bit SynchSpawn code. + * Determines whether running under NT, 95, or Win32s, to allow + * runtime conditional code. * * Results: - * 1 on success, 0 on failure. + * 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: - * Spawns a command and waits for it to complete. + * None. * *---------------------------------------------------------------------- */ -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; +int +TclWinGetPlatformId() +{ + return platformId; } /* - *---------------------------------------------------------------------- + *------------------------------------------------------------------------- * - * TclWinGetTclInstance -- + * TclWinNoBackslash -- * - * Retrieves the global library instance handle. + * We're always iterating through a string in Windows, changing the + * backslashes to slashes for use in Tcl. * * Results: - * Returns the global library instance handle. + * All backslashes in given string are changed to slashes. * * Side effects: * None. * - *---------------------------------------------------------------------- + *------------------------------------------------------------------------- */ -HINSTANCE -TclWinGetTclInstance() +char * +TclWinNoBackslash( + char *path) /* String to change. */ { - return tclInstance; + char *p; + + for (p = path; *p != '\0'; p++) { + if (*p == '\\') { + *p = '/'; + } + } + return path; } /* @@ -409,20 +452,18 @@ TclpCheckStackSpace() return 0; } + /* *---------------------------------------------------------------------- * - * TclWinGetPlatformId -- + * TclWinGetPlatform -- * - * Determines whether running under NT, 95, or Win32s, to allow - * runtime conditional code. + * This is a kludge that allows the test library to get access + * the internal tclPlatform variable. * * 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 + * Returns a pointer to the tclPlatform variable. * * Side effects: * None. @@ -430,8 +471,122 @@ TclpCheckStackSpace() *---------------------------------------------------------------------- */ -int -TclWinGetPlatformId() +TclPlatformType * +TclWinGetPlatform() +{ + return &tclPlatform; +} + +/* + *--------------------------------------------------------------------------- + * + * TclWinSetInterfaces -- + * + * A helper proc that allows the test library to change the + * tclWinProcs structure to dispatch to either the wide-character + * or multi-byte versions of the operating system calls, depending + * on whether Unicode is the system encoding. + * + * Results: + * None. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +void +TclWinSetInterfaces( + int wide) /* Non-zero to use wide interfaces, 0 + * otherwise. */ +{ + Tcl_FreeEncoding(tclWinTCharEncoding); + + if (wide) { + tclWinProcs = &unicodeProcs; + tclWinTCharEncoding = Tcl_GetEncoding(NULL, "unicode"); + } else { + tclWinProcs = &asciiProcs; + tclWinTCharEncoding = NULL; + } +} + +/* + *--------------------------------------------------------------------------- + * + * Tcl_WinUtfToTChar, Tcl_WinTCharToUtf -- + * + * Convert between UTF-8 and Unicode when running Windows NT or + * the current ANSI code page when running Windows 95. + * + * On Mac, Unix, and Windows 95, all strings exchanged between Tcl + * and the OS are "char" oriented. We need only one Tcl_Encoding to + * convert between UTF-8 and the system's native encoding. We use + * NULL to represent that encoding. + * + * On NT, some strings exchanged between Tcl and the OS are "char" + * oriented, while others are in Unicode. We need two Tcl_Encoding + * APIs depending on whether we are targeting a "char" or Unicode + * interface. + * + * Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an + * encoding of NULL should always used to convert between UTF-8 + * and the system's "char" oriented encoding. The following two + * functions are used in Windows-specific code to convert between + * UTF-8 and Unicode strings (NT) or "char" strings(95). This saves + * you the trouble of writing the following type of fragment over and + * over: + * + * if (running NT) { + * encoding <- Tcl_GetEncoding("unicode"); + * nativeBuffer <- UtfToExternal(encoding, utfBuffer); + * Tcl_FreeEncoding(encoding); + * } else { + * nativeBuffer <- UtfToExternal(NULL, utfBuffer); + * } + * + * By convention, in Windows a TCHAR is a character in the ANSI code + * page on Windows 95, a Unicode character on Windows NT. If you + * plan on targeting a Unicode interfaces when running on NT and a + * "char" oriented interface while running on 95, these functions + * should be used. If you plan on targetting the same "char" + * oriented function on both 95 and NT, use Tcl_UtfToExternal() + * with an encoding of NULL. + * + * Results: + * The result is a pointer to the string in the desired target + * encoding. Storage for the result string is allocated in + * dsPtr; the caller must call Tcl_DStringFree() when the result + * is no longer needed. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +TCHAR * +Tcl_WinUtfToTChar(string, len, dsPtr) + CONST char *string; /* Source string in UTF-8. */ + int len; /* Source string length in bytes, or < 0 for + * strlen(). */ + Tcl_DString *dsPtr; /* Uninitialized or free DString in which + * the converted string is stored. */ +{ + return (TCHAR *) Tcl_UtfToExternalDString(tclWinTCharEncoding, + string, len, dsPtr); +} + +char * +Tcl_WinTCharToUtf(string, len, dsPtr) + CONST TCHAR *string; /* Source string in Unicode when running + * NT, ANSI when running 95. */ + int len; /* Source string length in bytes, or < 0 for + * platform-specific string length. */ + Tcl_DString *dsPtr; /* Uninitialized or free DString in which + * the converted string is stored. */ { - return tclPlatformId; + return Tcl_ExternalToUtfDString(tclWinTCharEncoding, + (CONST char *) string, len, dsPtr); } |