summaryrefslogtreecommitdiffstats
path: root/win/tclWin32Dll.c
diff options
context:
space:
mode:
authorstanton <stanton>1999-04-16 00:46:29 (GMT)
committerstanton <stanton>1999-04-16 00:46:29 (GMT)
commit97464e6cba8eb0008cf2727c15718671992b913f (patch)
treece9959f2747257d98d52ec8d18bf3b0de99b9535 /win/tclWin32Dll.c
parenta8c96ddb94d1483a9de5e340b740cb74ef6cafa7 (diff)
downloadtcl-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.c543
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);
}