summaryrefslogtreecommitdiffstats
path: root/win/tclWin32Dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWin32Dll.c')
-rw-r--r--win/tclWin32Dll.c776
1 files changed, 175 insertions, 601 deletions
diff --git a/win/tclWin32Dll.c b/win/tclWin32Dll.c
index ce54eee..688fa8d 100644
--- a/win/tclWin32Dll.c
+++ b/win/tclWin32Dll.c
@@ -1,4 +1,4 @@
-/*
+/*
* tclWin32Dll.c --
*
* This file contains the DLL entry point and other low-level bit bashing
@@ -9,27 +9,14 @@
*
* 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.46 2005/07/24 22:56:46 dkf Exp $
*/
#include "tclWinInt.h"
+#if defined(HAVE_INTRIN_H)
+# include <intrin.h>
+#endif
/*
- * 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 UTREGISTER)(HANDLE hModule, LPCSTR SixteenBitDLL,
- LPCSTR InitName, LPCSTR ProcName, UT32PROC **ThirtyTwoBitThunk,
- FARPROC UT32Callback, LPVOID Buff);
-
-typedef VOID (WINAPI UTUNREGISTER)(HANDLE hModule);
-
-/*
* 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.
@@ -38,23 +25,6 @@ typedef VOID (WINAPI UTUNREGISTER)(HANDLE hModule);
static HINSTANCE hInstance; /* HINSTANCE of this DLL. */
static int platformId; /* Running under NT, or 95/98? */
-#ifdef HAVE_NO_SEH
-/*
- * Unlike Borland and Microsoft, we don't register exception handlers by
- * pushing registration records onto the runtime stack. Instead, we register
- * them by creating an EXCEPTION_REGISTRATION within the activation record.
- */
-
-typedef struct EXCEPTION_REGISTRATION {
- struct EXCEPTION_REGISTRATION *link;
- EXCEPTION_DISPOSITION (*handler)(
- struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
- void *ebp;
- void *esp;
- int status;
-} EXCEPTION_REGISTRATION;
-#endif
-
/*
* VC++ 5.x has no 'cpuid' assembler instruction, so we must emulate it
*/
@@ -63,138 +33,14 @@ typedef struct EXCEPTION_REGISTRATION {
#define cpuid __asm __emit 0fh __asm __emit 0a2h
#endif
-/*
- * 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 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,
-
- /*
- * The three NULL function pointers will only be set when
- * Tcl_FindExecutable is called. If you don't ever call that function, the
- * application will crash whenever WinTcl tries to call functions through
- * these null pointers. That is not a bug in Tcl - Tcl_FindExecutable is
- * mandatory in recent Tcl releases.
- */
-
- NULL,
- NULL,
- /* deleted (int (__cdecl*)(CONST TCHAR *, struct _utimbuf *)) _utime, */
- NULL,
- NULL,
- /* Security SDK - not available on 95,98,ME */
- NULL, NULL, NULL, NULL, NULL, NULL
-};
-
-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,
-
- /*
- * The three NULL function pointers will only be set when
- * Tcl_FindExecutable is called. If you don't ever call that function, the
- * application will crash whenever WinTcl tries to call functions through
- * these null pointers. That is not a bug in Tcl - Tcl_FindExecutable is
- * mandatory in recent Tcl releases.
- */
+static Tcl_Encoding winTCharEncoding = NULL;
- NULL,
- NULL,
- /* deleted (int (__cdecl*)(CONST TCHAR *, struct _utimbuf *)) _wutime, */
- NULL,
- NULL,
- /* Security SDK - will be filled in on NT,XP,2000,2003 */
- NULL, NULL, NULL, NULL, NULL, NULL
-};
-
-TclWinProcs *tclWinProcs;
-static Tcl_Encoding tclWinTCharEncoding;
-
-#ifdef HAVE_NO_SEH
-/*
- * Need to add noinline flag to DllMain declaration so that gcc -O3 does not
- * inline asm code into DllEntryPoint and cause a compile time error because
- * of redefined local labels.
- */
-
-BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason,
- LPVOID reserved) __attribute__ ((noinline));
-#else
/*
* The following declaration is for the VC++ DLL entry point.
*/
-BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason,
+BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason,
LPVOID reserved);
-#endif /* HAVE_NO_SEH */
/*
* The following structure and linked list is to allow us to map between
@@ -203,15 +49,15 @@ BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason,
*/
typedef struct MountPointMap {
- CONST WCHAR *volumeName; /* Native wide string volume name. */
- char driveLetter; /* Drive letter corresponding to the volume
+ const TCHAR *volumeName; /* Native wide string volume name. */
+ TCHAR driveLetter; /* Drive letter corresponding to the volume
* name. */
struct MountPointMap *nextPtr;
/* Pointer to next structure in list, or
* NULL. */
} MountPointMap;
-/*
+/*
* This is the head of the linked list, which is protected by the mutex which
* follows, for thread-enabled builds.
*/
@@ -223,9 +69,7 @@ TCL_DECLARE_MUTEX(mountPointMap)
* We will need this below.
*/
-extern Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
-
-#ifdef __WIN32__
+#ifdef _WIN32
#ifndef STATIC_BUILD
/*
@@ -246,10 +90,10 @@ extern Tcl_FSDupInternalRepProc TclNativeDupInternalRep;
*/
BOOL APIENTRY
-DllEntryPoint(hInst, reason, reserved)
- HINSTANCE hInst; /* Library instance handle. */
- DWORD reason; /* Reason this function is being called. */
- LPVOID reserved; /* Not used. */
+DllEntryPoint(
+ HINSTANCE hInst, /* Library instance handle. */
+ DWORD reason, /* Reason this function is being called. */
+ LPVOID reserved) /* Not used. */
{
return DllMain(hInst, reason, reserved);
}
@@ -267,121 +111,33 @@ DllEntryPoint(hInst, reason, reserved)
* TRUE on sucess, FALSE on failure.
*
* Side effects:
- * Establishes 32-to-16 bit thunk and initializes sockets library. This
- * might call some sycronization functions, but MSDN documentation
- * states: "Waiting on synchronization objects in DllMain can cause a
- * deadlock."
+ * Initializes most rudimentary Windows bits.
*
*----------------------------------------------------------------------
*/
BOOL APIENTRY
-DllMain(hInst, reason, reserved)
- HINSTANCE hInst; /* Library instance handle. */
- DWORD reason; /* Reason this function is being called. */
- LPVOID reserved; /* Not used. */
+DllMain(
+ HINSTANCE hInst, /* Library instance handle. */
+ DWORD reason, /* Reason this function is being called. */
+ LPVOID reserved) /* Not used. */
{
-#ifdef HAVE_NO_SEH
- EXCEPTION_REGISTRATION registration;
-#endif
-
switch (reason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInst);
TclWinInit(hInst);
return TRUE;
- case DLL_PROCESS_DETACH:
/*
- * Protect the call to Tcl_Finalize. The OS could be unloading us from
- * an exception handler and the state of the stack might be unstable.
+ * DLL_PROCESS_DETACH is unnecessary as the user should call
+ * Tcl_Finalize explicitly before unloading Tcl.
*/
-
-#ifdef HAVE_NO_SEH
- __asm__ __volatile__ (
-
- /*
- * Construct an EXCEPTION_REGISTRATION to protect the call to
- * Tcl_Finalize
- */
-
- "leal %[registration], %%edx" "\n\t"
- "movl %%fs:0, %%eax" "\n\t"
- "movl %%eax, 0x0(%%edx)" "\n\t" /* link */
- "leal 1f, %%eax" "\n\t"
- "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */
- "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */
- "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */
- "movl %[error], 0x10(%%edx)" "\n\t" /* status */
-
- /*
- * Link the EXCEPTION_REGISTRATION on the chain
- */
-
- "movl %%edx, %%fs:0" "\n\t"
-
- /*
- * Call Tcl_Finalize
- */
-
- "call _Tcl_Finalize" "\n\t"
-
- /*
- * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION
- * and store a TCL_OK status
- */
-
- "movl %%fs:0, %%edx" "\n\t"
- "movl %[ok], %%eax" "\n\t"
- "movl %%eax, 0x10(%%edx)" "\n\t"
- "jmp 2f" "\n"
-
- /*
- * Come here on an exception. Get the EXCEPTION_REGISTRATION that
- * we previously put on the chain.
- */
-
- "1:" "\t"
- "movl %%fs:0, %%edx" "\n\t"
- "movl 0x8(%%edx), %%edx" "\n"
-
-
- /*
- * Come here however we exited. Restore context from the
- * EXCEPTION_REGISTRATION in case the stack is unbalanced.
- */
-
- "2:" "\t"
- "movl 0xc(%%edx), %%esp" "\n\t"
- "movl 0x8(%%edx), %%ebp" "\n\t"
- "movl 0x0(%%edx), %%eax" "\n\t"
- "movl %%eax, %%fs:0" "\n\t"
-
- :
- /* No outputs */
- :
- [registration] "m" (registration),
- [ok] "i" (TCL_OK),
- [error] "i" (TCL_ERROR)
- :
- "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
- );
-
-#else /* HAVE_NO_SEH */
- __try {
- Tcl_Finalize();
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- /* empty handler body. */
- }
-#endif
-
- break;
}
- return TRUE;
+ return TRUE;
}
#endif /* !STATIC_BUILD */
-#endif /* __WIN32__ */
+#endif /* _WIN32 */
/*
*----------------------------------------------------------------------
@@ -400,7 +156,7 @@ DllMain(hInst, reason, reserved)
*/
HINSTANCE
-TclWinGetTclInstance()
+TclWinGetTclInstance(void)
{
return hInstance;
}
@@ -422,26 +178,29 @@ TclWinGetTclInstance()
*/
void
-TclWinInit(hInst)
- HINSTANCE hInst; /* Library instance handle. */
+TclWinInit(
+ HINSTANCE hInst) /* Library instance handle. */
{
- OSVERSIONINFO os;
+ OSVERSIONINFOW os;
hInstance = hInst;
- os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&os);
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+ GetVersionExW(&os);
platformId = os.dwPlatformId;
/*
- * We no longer support Win32s, so just in case someone manages to get a
- * runtime there, make sure they know that.
+ * We no longer support Win32s or Win9x, so just in case someone manages
+ * to get a runtime there, make sure they know that.
*/
if (platformId == VER_PLATFORM_WIN32s) {
- Tcl_Panic("Win32s is not a supported platform");
+ Tcl_Panic("Win32s is not a supported platform");
+ }
+ if (platformId == VER_PLATFORM_WIN32_WINDOWS) {
+ Tcl_Panic("Windows 9x is not a supported platform");
}
- tclWinProcs = &asciiProcs;
+ TclWinResetInterfaces();
}
/*
@@ -454,9 +213,10 @@ TclWinInit(hInst)
*
* Results:
* The return value is one of:
- * VER_PLATFORM_WIN32s Win32s on Windows 3.1. (not supported)
- * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME.
- * VER_PLATFORM_WIN32_NT Win32 on Windows NT, 2000, XP
+ * VER_PLATFORM_WIN32s Win32s on Windows 3.1 (not supported)
+ * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME (not supported)
+ * VER_PLATFORM_WIN32_NT Win32 on Windows NT, 2000, XP
+ * VER_PLATFORM_WIN32_CE Win32 on Windows CE
*
* Side effects:
* None.
@@ -464,8 +224,8 @@ TclWinInit(hInst)
*----------------------------------------------------------------------
*/
-int
-TclWinGetPlatformId()
+int
+TclWinGetPlatformId(void)
{
return platformId;
}
@@ -502,143 +262,11 @@ TclWinNoBackslash(
}
/*
- *----------------------------------------------------------------------
- *
- * TclpCheckStackSpace --
- *
- * Detect if we are about to blow the stack. Called before an evaluation
- * can happen when nesting depth is checked.
- *
- * Results:
- * 1 if there is enough stack space to continue; 0 if not.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclpCheckStackSpace()
-{
-
-#ifdef HAVE_NO_SEH
- EXCEPTION_REGISTRATION registration;
-#endif
- int retval = 0;
-
- /*
- * We can recurse only if there is at least TCL_WIN_STACK_THRESHOLD bytes
- * of stack space left. alloca() is cheap on windows; basically it just
- * subtracts from the stack pointer causing the OS to throw an exception
- * if the stack pointer is set below the bottom of the stack.
- */
-
-#ifdef HAVE_NO_SEH
- __asm__ __volatile__ (
-
- /*
- * Construct an EXCEPTION_REGISTRATION to protect the call to __alloca
- */
-
- "leal %[registration], %%edx" "\n\t"
- "movl %%fs:0, %%eax" "\n\t"
- "movl %%eax, 0x0(%%edx)" "\n\t" /* link */
- "leal 1f, %%eax" "\n\t"
- "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */
- "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */
- "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */
- "movl %[error], 0x10(%%edx)" "\n\t" /* status */
-
- /*
- * Link the EXCEPTION_REGISTRATION on the chain
- */
-
- "movl %%edx, %%fs:0" "\n\t"
-
- /*
- * Attempt a call to __alloca, to determine whether there's sufficient
- * memory to be had.
- */
-
- "movl %[size], %%eax" "\n\t"
- "pushl %%eax" "\n\t"
- "call __alloca" "\n\t"
-
- /*
- * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION and
- * store a TCL_OK status
- */
-
- "movl %%fs:0, %%edx" "\n\t"
- "movl %[ok], %%eax" "\n\t"
- "movl %%eax, 0x10(%%edx)" "\n\t"
- "jmp 2f" "\n"
-
- /*
- * Come here on an exception. Get the EXCEPTION_REGISTRATION that we
- * previously put on the chain.
- */
-
- "1:" "\t"
- "movl %%fs:0, %%edx" "\n\t"
- "movl 0x8(%%edx), %%edx" "\n\t"
-
- /*
- * Come here however we exited. Restore context from the
- * EXCEPTION_REGISTRATION in case the stack is unbalanced.
- */
-
- "2:" "\t"
- "movl 0xc(%%edx), %%esp" "\n\t"
- "movl 0x8(%%edx), %%ebp" "\n\t"
- "movl 0x0(%%edx), %%eax" "\n\t"
- "movl %%eax, %%fs:0" "\n\t"
-
- :
- /* No outputs */
- :
- [registration] "m" (registration),
- [ok] "i" (TCL_OK),
- [error] "i" (TCL_ERROR),
- [size] "i" (TCL_WIN_STACK_THRESHOLD)
- :
- "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"
- );
- retval = (registration.status == TCL_OK);
-
-#else /* !HAVE_NO_SEH */
- __try {
-#ifdef HAVE_ALLOCA_GCC_INLINE
- __asm__ __volatile__ (
- "movl %0, %%eax" "\n\t"
- "call __alloca" "\n\t"
- :
- : "i"(TCL_WIN_STACK_THRESHOLD)
- : "%eax");
-#else
- alloca(TCL_WIN_STACK_THRESHOLD);
-#endif /* HAVE_ALLOCA_GCC_INLINE */
- retval = 1;
- } __except (EXCEPTION_EXECUTE_HANDLER) {}
-#endif /* HAVE_NO_SEH */
-
- return retval;
-}
-
-/*
*---------------------------------------------------------------------------
*
- * TclWinSetInterfaces --
+ * TclpSetInterfaces --
*
- * 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.
- *
- * As well as this, we can also try to load in some additional procs
- * which may/may not be present depending on the current Windows version
- * (e.g. Win95 will not have the procs below).
+ * A helper proc that initializes winTCharEncoding.
*
* Results:
* None.
@@ -650,120 +278,23 @@ TclpCheckStackSpace()
*/
void
-TclWinSetInterfaces(
- int wide) /* Non-zero to use wide interfaces, 0
- * otherwise. */
+TclpSetInterfaces(void)
{
- Tcl_FreeEncoding(tclWinTCharEncoding);
-
- if (wide) {
- tclWinProcs = &unicodeProcs;
- tclWinTCharEncoding = Tcl_GetEncoding(NULL, "unicode");
- if (tclWinProcs->getFileAttributesExProc == NULL) {
- HINSTANCE hInstance = LoadLibraryA("kernel32");
- if (hInstance != NULL) {
- tclWinProcs->getFileAttributesExProc =
- (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS,
- LPVOID)) GetProcAddress(hInstance,
- "GetFileAttributesExW");
- tclWinProcs->createHardLinkProc =
- (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*,
- LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance,
- "CreateHardLinkW");
- tclWinProcs->findFirstFileExProc =
- (HANDLE (WINAPI *)(CONST TCHAR*, UINT, LPVOID, UINT,
- LPVOID, DWORD)) GetProcAddress(hInstance,
- "FindFirstFileExW");
- tclWinProcs->getVolumeNameForVMPProc =
- (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*,
- DWORD)) GetProcAddress(hInstance,
- "GetVolumeNameForVolumeMountPointW");
- tclWinProcs->getLongPathNameProc =
- (DWORD (WINAPI *)(CONST TCHAR*, TCHAR*,
- DWORD)) GetProcAddress(hInstance, "GetLongPathNameW");
- FreeLibrary(hInstance);
- }
- hInstance = LoadLibraryA("advapi32");
- if (hInstance != NULL) {
- tclWinProcs->getFileSecurityProc = (BOOL (WINAPI *)(
- LPCTSTR lpFileName,
- SECURITY_INFORMATION RequestedInformation,
- PSECURITY_DESCRIPTOR pSecurityDescriptor,
- DWORD nLength, LPDWORD lpnLengthNeeded))
- GetProcAddress(hInstance, "GetFileSecurityW");
- tclWinProcs->impersonateSelfProc = (BOOL (WINAPI *) (
- SECURITY_IMPERSONATION_LEVEL ImpersonationLevel))
- GetProcAddress(hInstance, "ImpersonateSelf");
- tclWinProcs->openThreadTokenProc = (BOOL (WINAPI *) (
- HANDLE ThreadHandle, DWORD DesiredAccess,
- BOOL OpenAsSelf, PHANDLE TokenHandle))
- GetProcAddress(hInstance, "OpenThreadToken");
- tclWinProcs->revertToSelfProc = (BOOL (WINAPI *) (void))
- GetProcAddress(hInstance, "RevertToSelf");
- tclWinProcs->mapGenericMaskProc = (VOID (WINAPI *) (
- PDWORD AccessMask, PGENERIC_MAPPING GenericMapping))
- GetProcAddress(hInstance, "MapGenericMask");
- tclWinProcs->accessCheckProc = (BOOL (WINAPI *)(
- PSECURITY_DESCRIPTOR pSecurityDescriptor,
- HANDLE ClientToken, DWORD DesiredAccess,
- PGENERIC_MAPPING GenericMapping,
- PPRIVILEGE_SET PrivilegeSet,
- LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess,
- LPBOOL AccessStatus)) GetProcAddress(hInstance,
- "AccessCheck");
- FreeLibrary(hInstance);
- }
- }
- } else {
- tclWinProcs = &asciiProcs;
- tclWinTCharEncoding = NULL;
- if (tclWinProcs->getFileAttributesExProc == NULL) {
- HINSTANCE hInstance = LoadLibraryA("kernel32");
- if (hInstance != NULL) {
- tclWinProcs->getFileAttributesExProc =
- (BOOL (WINAPI *)(CONST TCHAR *, GET_FILEEX_INFO_LEVELS,
- LPVOID)) GetProcAddress(hInstance,
- "GetFileAttributesExA");
- tclWinProcs->createHardLinkProc =
- (BOOL (WINAPI *)(CONST TCHAR *, CONST TCHAR*,
- LPSECURITY_ATTRIBUTES)) GetProcAddress(hInstance,
- "CreateHardLinkA");
- tclWinProcs->findFirstFileExProc = NULL;
- tclWinProcs->getLongPathNameProc = NULL;
- /*
- * The 'findFirstFileExProc' function exists on some of
- * 95/98/ME, but it seems not to work as anticipated.
- * Therefore we don't set this function pointer. The relevant
- * code will fall back on a slower approach using the normal
- * findFirstFileProc.
- *
- * (HANDLE (WINAPI *)(CONST TCHAR*, UINT,
- * LPVOID, UINT, LPVOID, DWORD)) GetProcAddress(hInstance,
- * "FindFirstFileExA");
- */
- tclWinProcs->getVolumeNameForVMPProc =
- (BOOL (WINAPI *)(CONST TCHAR*, TCHAR*,
- DWORD)) GetProcAddress(hInstance,
- "GetVolumeNameForVolumeMountPointA");
- FreeLibrary(hInstance);
- }
- }
- }
+ TclWinResetInterfaces();
+ winTCharEncoding = Tcl_GetEncoding(NULL, "unicode");
}
/*
*---------------------------------------------------------------------------
*
- * TclWinResetInterfaceEncodings --
+ * TclWinEncodingsCleanup --
*
- * Called during finalization to free up any encodings we use. The
- * tclWinProcs-> look up table is still ok to use after this call,
- * provided no encoding conversion is required.
+ * Called during finalization to free up any encodings we use.
*
* We also clean up any memory allocated in our mount point map which is
* used to follow certain kinds of symlinks. That code should never be
* used once encodings are taken down.
- *
+ *
* Results:
* None.
*
@@ -774,24 +305,22 @@ TclWinSetInterfaces(
*/
void
-TclWinResetInterfaceEncodings()
+TclWinEncodingsCleanup(void)
{
MountPointMap *dlIter, *dlIter2;
- if (tclWinTCharEncoding != NULL) {
- Tcl_FreeEncoding(tclWinTCharEncoding);
- tclWinTCharEncoding = NULL;
- }
+
+ TclWinResetInterfaces();
/*
* Clean up the mount point map.
*/
Tcl_MutexLock(&mountPointMap);
- dlIter = driveLetterLookup;
+ dlIter = driveLetterLookup;
while (dlIter != NULL) {
dlIter2 = dlIter->nextPtr;
- ckfree((char*)dlIter->volumeName);
- ckfree((char*)dlIter);
+ ckfree(dlIter->volumeName);
+ ckfree(dlIter);
dlIter = dlIter2;
}
Tcl_MutexUnlock(&mountPointMap);
@@ -803,8 +332,6 @@ TclWinResetInterfaceEncodings()
* TclWinResetInterfaces --
*
* Called during finalization to reset us to a safe state for reuse.
- * After this call, it is best not to use the tclWinProcs-> look up table
- * since it is likely to be different to what is expected.
*
* Results:
* None.
@@ -815,9 +342,12 @@ TclWinResetInterfaceEncodings()
*---------------------------------------------------------------------------
*/
void
-TclWinResetInterfaces()
+TclWinResetInterfaces(void)
{
- tclWinProcs = &asciiProcs;
+ if (winTCharEncoding != NULL) {
+ Tcl_FreeEncoding(winTCharEncoding);
+ winTCharEncoding = NULL;
+ }
}
/*
@@ -830,60 +360,61 @@ TclWinResetInterfaces()
* understand paths correctly. So, we have to build an associated array
* to find these correctly, and allow quick and easy lookup from volume
* mount points to drive letters.
- *
+ *
* We assume here that we are running on a system for which the wide
* character interfaces are used, which is valid for Win 2000 and WinXP
* which are the only systems on which this function will ever be called.
- *
+ *
* Result:
* The drive letter, or -1 if no drive letter corresponds to the given
* mount point.
- *
+ *
*--------------------------------------------------------------------
*/
-char
-TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
+char
+TclWinDriveLetterForVolMountPoint(
+ const TCHAR *mountPoint)
{
MountPointMap *dlIter, *dlPtr2;
- WCHAR Target[55]; /* Target of mount at mount point */
- WCHAR drive[4] = { L'A', L':', L'\\', L'\0' };
-
- /*
+ TCHAR Target[55]; /* Target of mount at mount point */
+ TCHAR drive[4] = TEXT("A:\\");
+
+ /*
* Detect the volume mounted there. Unfortunately, there is no simple way
* to map a unique volume name to a DOS drive letter. So, we have to build
* an associative array.
*/
-
+
Tcl_MutexLock(&mountPointMap);
- dlIter = driveLetterLookup;
+ dlIter = driveLetterLookup;
while (dlIter != NULL) {
- if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
- /*
+ if (_tcscmp(dlIter->volumeName, mountPoint) == 0) {
+ /*
* We need to check whether this information is still valid, since
* either the user or various programs could have adjusted the
* mount points on the fly.
*/
- drive[0] = L'A' + (dlIter->driveLetter - 'A');
+ drive[0] = (TCHAR) dlIter->driveLetter;
/*
* Try to read the volume mount point and see where it points.
*/
- if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive,
- (TCHAR*)Target, 55) != 0) {
- if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
+ if (GetVolumeNameForVolumeMountPoint(drive,
+ Target, 55) != 0) {
+ if (_tcscmp(dlIter->volumeName, Target) == 0) {
/*
* Nothing has changed.
*/
Tcl_MutexUnlock(&mountPointMap);
- return dlIter->driveLetter;
+ return (char) dlIter->driveLetter;
}
}
- /*
+ /*
* If we reach here, unfortunately, this mount point is no longer
* valid at all.
*/
@@ -892,7 +423,7 @@ TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
dlPtr2 = dlIter;
driveLetterLookup = dlIter->nextPtr;
} else {
- for (dlPtr2 = driveLetterLookup;
+ for (dlPtr2 = driveLetterLookup;
dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) {
if (dlPtr2->nextPtr == dlIter) {
dlPtr2->nextPtr = dlIter->nextPtr;
@@ -906,10 +437,10 @@ TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
* Now dlPtr2 points to the structure to free.
*/
- ckfree((char*)dlPtr2->volumeName);
- ckfree((char*)dlPtr2);
+ ckfree(dlPtr2->volumeName);
+ ckfree(dlPtr2);
- /*
+ /*
* Restart the loop - we could try to be clever and continue half
* way through, but the logic is a bit messy, so it's cleanest
* just to restart.
@@ -920,33 +451,33 @@ TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
}
dlIter = dlIter->nextPtr;
}
-
+
/*
* We couldn't find it, so we must iterate over the letters.
*/
-
+
for (drive[0] = L'A'; drive[0] <= L'Z'; drive[0]++) {
/*
* Try to read the volume mount point and see where it points.
*/
- if ((*tclWinProcs->getVolumeNameForVMPProc)((TCHAR*)drive,
- (TCHAR*)Target, 55) != 0) {
+ if (GetVolumeNameForVolumeMountPoint(drive,
+ Target, 55) != 0) {
int alreadyStored = 0;
- for (dlIter = driveLetterLookup; dlIter != NULL;
+ for (dlIter = driveLetterLookup; dlIter != NULL;
dlIter = dlIter->nextPtr) {
- if (wcscmp((WCHAR*)dlIter->volumeName, Target) == 0) {
+ if (_tcscmp(dlIter->volumeName, Target) == 0) {
alreadyStored = 1;
break;
}
}
if (!alreadyStored) {
- dlPtr2 = (MountPointMap *) ckalloc(sizeof(MountPointMap));
+ dlPtr2 = ckalloc(sizeof(MountPointMap));
dlPtr2->volumeName = TclNativeDupInternalRep(Target);
- dlPtr2->driveLetter = 'A' + (drive[0] - L'A');
+ dlPtr2->driveLetter = (char) drive[0];
dlPtr2->nextPtr = driveLetterLookup;
- driveLetterLookup = dlPtr2;
+ driveLetterLookup = dlPtr2;
}
}
}
@@ -955,24 +486,24 @@ TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
* Try again.
*/
- for (dlIter = driveLetterLookup; dlIter != NULL;
+ for (dlIter = driveLetterLookup; dlIter != NULL;
dlIter = dlIter->nextPtr) {
- if (wcscmp(dlIter->volumeName, mountPoint) == 0) {
+ if (_tcscmp(dlIter->volumeName, mountPoint) == 0) {
Tcl_MutexUnlock(&mountPointMap);
- return dlIter->driveLetter;
+ return (char) dlIter->driveLetter;
}
}
- /*
+ /*
* The volume doesn't appear to correspond to a drive letter - we remember
* that fact and store '-1' so we don't have to look it up each time.
*/
- dlPtr2 = (MountPointMap*) ckalloc(sizeof(MountPointMap));
- dlPtr2->volumeName = TclNativeDupInternalRep((ClientData)mountPoint);
+ dlPtr2 = ckalloc(sizeof(MountPointMap));
+ dlPtr2->volumeName = TclNativeDupInternalRep((ClientData) mountPoint);
dlPtr2->driveLetter = -1;
dlPtr2->nextPtr = driveLetterLookup;
- driveLetterLookup = dlPtr2;
+ driveLetterLookup = dlPtr2;
Tcl_MutexUnlock(&mountPointMap);
return -1;
}
@@ -1028,28 +559,28 @@ TclWinDriveLetterForVolMountPoint(CONST WCHAR *mountPoint)
*/
TCHAR *
-Tcl_WinUtfToTChar(string, len, dsPtr)
- CONST char *string; /* Source string in UTF-8. */
- int len; /* Source string length in bytes, or < 0 for
+Tcl_WinUtfToTChar(
+ 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
+ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
{
- return (TCHAR *) Tcl_UtfToExternalDString(tclWinTCharEncoding,
+ return (TCHAR *) Tcl_UtfToExternalDString(winTCharEncoding,
string, len, dsPtr);
}
char *
-Tcl_WinTCharToUtf(string, len, dsPtr)
- CONST TCHAR *string; /* Source string in Unicode when running NT,
+Tcl_WinTCharToUtf(
+ const TCHAR *string, /* Source string in Unicode when running NT,
* ANSI when running 95. */
- int len; /* Source string length in bytes, or < 0 for
+ int len, /* Source string length in bytes, or < 0 for
* platform-specific string length. */
- Tcl_DString *dsPtr; /* Uninitialized or free DString in which the
+ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the
* converted string is stored. */
{
- return Tcl_ExternalToUtfDString(tclWinTCharEncoding,
- (CONST char *) string, len, dsPtr);
+ return Tcl_ExternalToUtfDString(winTCharEncoding,
+ (const char *) string, len, dsPtr);
}
/*
@@ -1075,20 +606,55 @@ TclWinCPUID(
unsigned int index, /* Which CPUID value to retrieve. */
unsigned int *regsPtr) /* Registers after the CPUID. */
{
-#ifdef HAVE_NO_SEH
- EXCEPTION_REGISTRATION registration;
-#endif
int status = TCL_ERROR;
-#if defined(__GNUC__) && !defined(_WIN64)
- /*
+#if defined(HAVE_INTRIN_H) && defined(_WIN64)
+
+ __cpuid(regsPtr, index);
+ status = TCL_OK;
+
+#elif defined(__GNUC__)
+# if defined(_WIN64)
+ /*
* Execute the CPUID instruction with the given index, and store results
* off 'regPtr'.
*/
-
+
__asm__ __volatile__(
/*
- * Construct an EXCEPTION_REGISTRATION to protect the CPUID
+ * Do the CPUID instruction, and save the results in the 'regsPtr'
+ * area.
+ */
+
+ "movl %[rptr], %%edi" "\n\t"
+ "movl %[index], %%eax" "\n\t"
+ "cpuid" "\n\t"
+ "movl %%eax, 0x0(%%edi)" "\n\t"
+ "movl %%ebx, 0x4(%%edi)" "\n\t"
+ "movl %%ecx, 0x8(%%edi)" "\n\t"
+ "movl %%edx, 0xc(%%edi)" "\n\t"
+
+ :
+ /* No outputs */
+ :
+ [index] "m" (index),
+ [rptr] "m" (regsPtr)
+ :
+ "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+ status = TCL_OK;
+
+# else
+
+ TCLEXCEPTION_REGISTRATION registration;
+
+ /*
+ * Execute the CPUID instruction with the given index, and store results
+ * off 'regPtr'.
+ */
+
+ __asm__ __volatile__(
+ /*
+ * Construct an TCLEXCEPTION_REGISTRATION to protect the CPUID
* instruction (early 486's don't have CPUID)
*/
@@ -1100,9 +666,9 @@ TclWinCPUID(
"movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */
"movl %%esp, 0xc(%%edx)" "\n\t" /* esp */
"movl %[error], 0x10(%%edx)" "\n\t" /* status */
-
+
/*
- * Link the EXCEPTION_REGISTRATION on the chain
+ * Link the TCLEXCEPTION_REGISTRATION on the chain
*/
"movl %%edx, %%fs:0" "\n\t"
@@ -1121,7 +687,7 @@ TclWinCPUID(
"movl %%edx, 0xc(%%edi)" "\n\t"
/*
- * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION and
+ * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION and
* store a TCL_OK status.
*/
@@ -1131,28 +697,28 @@ TclWinCPUID(
"jmp 2f" "\n"
/*
- * Come here on an exception. Get the EXCEPTION_REGISTRATION that we
+ * Come here on an exception. Get the TCLEXCEPTION_REGISTRATION that we
* previously put on the chain.
*/
"1:" "\t"
"movl %%fs:0, %%edx" "\n\t"
"movl 0x8(%%edx), %%edx" "\n\t"
-
- /*
+
+ /*
* Come here however we exited. Restore context from the
- * EXCEPTION_REGISTRATION in case the stack is unbalanced.
+ * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced.
*/
-
+
"2:" "\t"
"movl 0xc(%%edx), %%esp" "\n\t"
"movl 0x8(%%edx), %%ebp" "\n\t"
"movl 0x0(%%edx), %%eax" "\n\t"
"movl %%eax, %%fs:0" "\n\t"
- :
+ :
/* No outputs */
- :
+ :
[index] "m" (index),
[rptr] "m" (regsPtr),
[registration] "m" (registration),
@@ -1162,7 +728,14 @@ TclWinCPUID(
"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
status = registration.status;
-#elif defined(_MSC_VER) && !defined(_WIN64)
+# endif /* !_WIN64 */
+#elif defined(_MSC_VER)
+# if defined(_WIN64)
+
+ __cpuid(regsPtr, index);
+ status = TCL_OK;
+
+# else
/*
* Define a structure in the stack frame to hold the registers.
*/
@@ -1174,7 +747,7 @@ TclWinCPUID(
DWORD dw3;
} regs;
regs.dw0 = index;
-
+
/*
* Execute the CPUID instruction and save regs in the stack frame.
*/
@@ -1194,7 +767,7 @@ TclWinCPUID(
pop ecx
pop ebx
}
-
+
/*
* Copy regs back out to the caller.
*/
@@ -1209,6 +782,7 @@ TclWinCPUID(
/* do nothing */
}
+# endif
#else
/*
* Don't know how to do assembly code for this compiler and/or