1/* 2 * tkWin32Dll.c -- 3 * 4 * This file contains a stub dll entry point. 5 * 6 * Copyright (c) 1995 Sun Microsystems, Inc. 7 * 8 * See the file "license.terms" for information on usage and redistribution 9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 10 * 11 * RCS: @(#) $Id: tkWin32Dll.c,v 1.6.2.3 2005/08/23 18:34:49 mdejong Exp $ 12 */ 13 14#include "tkWinInt.h" 15#ifndef STATIC_BUILD 16 17#ifdef HAVE_NO_SEH 18/* 19 * Unlike Borland and Microsoft, we don't register exception handlers by 20 * pushing registration records onto the runtime stack. Instead, we register 21 * them by creating an EXCEPTION_REGISTRATION within the activation record. 22 */ 23 24typedef struct EXCEPTION_REGISTRATION { 25 struct EXCEPTION_REGISTRATION *link; 26 EXCEPTION_DISPOSITION (*handler)( 27 struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); 28 void *ebp; 29 void *esp; 30 int status; 31} EXCEPTION_REGISTRATION; 32 33/* Need to add noinline flag to DllMain declaration so that gcc -O3 34 * does not inline asm code into DllEntryPoint and cause a 35 * compile time error because of redefined local labels. 36 */ 37 38BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, 39 LPVOID reserved) 40 __attribute__ ((noinline)); 41 42#else 43 44/* 45 * The following declaration is for the VC++ DLL entry point. 46 */ 47 48BOOL WINAPI DllMain _ANSI_ARGS_((HINSTANCE hInst, 49 DWORD reason, LPVOID reserved)); 50#endif /* HAVE_NO_SEH */ 51 52/* 53 *---------------------------------------------------------------------- 54 * 55 * DllEntryPoint -- 56 * 57 * This wrapper function is used by Borland to invoke the 58 * initialization code for Tk. It simply calls the DllMain 59 * routine. 60 * 61 * Results: 62 * See DllMain. 63 * 64 * Side effects: 65 * See DllMain. 66 * 67 *---------------------------------------------------------------------- 68 */ 69 70BOOL WINAPI 71DllEntryPoint(hInst, reason, reserved) 72 HINSTANCE hInst; /* Library instance handle. */ 73 DWORD reason; /* Reason this function is being called. */ 74 LPVOID reserved; /* Not used. */ 75{ 76 return DllMain(hInst, reason, reserved); 77} 78 79/* 80 *---------------------------------------------------------------------- 81 * 82 * DllMain -- 83 * 84 * DLL entry point. It is only necessary to specify our dll here so 85 * that resources are found correctly. Otherwise Tk will initialize 86 * and clean up after itself through other methods, in order to be 87 * consistent whether the build is static or dynamic. 88 * 89 * Results: 90 * Always TRUE. 91 * 92 * Side effects: 93 * This might call some sycronization functions, but MSDN 94 * documentation states: "Waiting on synchronization objects in 95 * DllMain can cause a deadlock." 96 * 97 *---------------------------------------------------------------------- 98 */ 99 100BOOL WINAPI 101DllMain(hInstance, reason, reserved) 102 HINSTANCE hInstance; 103 DWORD reason; 104 LPVOID reserved; 105{ 106#ifdef HAVE_NO_SEH 107 EXCEPTION_REGISTRATION registration; 108#endif 109 110 /* 111 * If we are attaching to the DLL from a new process, tell Tk about 112 * the hInstance to use. 113 */ 114 115 switch (reason) { 116 case DLL_PROCESS_ATTACH: 117 DisableThreadLibraryCalls(hInstance); 118 TkWinSetHINSTANCE(hInstance); 119 break; 120 121 case DLL_PROCESS_DETACH: 122 /* 123 * Protect the call to TkFinalize in an SEH block. We can't 124 * be guarenteed Tk is always being unloaded from a stable 125 * condition. 126 */ 127 128#ifdef HAVE_NO_SEH 129 __asm__ __volatile__ ( 130 131 /* 132 * Construct an EXCEPTION_REGISTRATION to protect the call to 133 * TkFinalize 134 */ 135 136 "leal %[registration], %%edx" "\n\t" 137 "movl %%fs:0, %%eax" "\n\t" 138 "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ 139 "leal 1f, %%eax" "\n\t" 140 "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ 141 "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ 142 "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ 143 "movl %[error], 0x10(%%edx)" "\n\t" /* status */ 144 145 /* 146 * Link the EXCEPTION_REGISTRATION on the chain 147 */ 148 149 "movl %%edx, %%fs:0" "\n\t" 150 151 /* 152 * Call TkFinalize 153 */ 154 155 "movl $0x0, 0x0(%%esp)" "\n\t" 156 "call _TkFinalize" "\n\t" 157 158 /* 159 * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION 160 * and store a TCL_OK status 161 */ 162 163 "movl %%fs:0, %%edx" "\n\t" 164 "movl %[ok], %%eax" "\n\t" 165 "movl %%eax, 0x10(%%edx)" "\n\t" 166 "jmp 2f" "\n" 167 168 /* 169 * Come here on an exception. Get the EXCEPTION_REGISTRATION that 170 * we previously put on the chain. 171 */ 172 173 "1:" "\t" 174 "movl %%fs:0, %%edx" "\n\t" 175 "movl 0x8(%%edx), %%edx" "\n" 176 177 178 /* 179 * Come here however we exited. Restore context from the 180 * EXCEPTION_REGISTRATION in case the stack is unbalanced. 181 */ 182 183 "2:" "\t" 184 "movl 0xc(%%edx), %%esp" "\n\t" 185 "movl 0x8(%%edx), %%ebp" "\n\t" 186 "movl 0x0(%%edx), %%eax" "\n\t" 187 "movl %%eax, %%fs:0" "\n\t" 188 189 : 190 /* No outputs */ 191 : 192 [registration] "m" (registration), 193 [ok] "i" (TCL_OK), 194 [error] "i" (TCL_ERROR) 195 : 196 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" 197 ); 198 199#else /* HAVE_NO_SEH */ 200 __try { 201 /* 202 * Run and remove our exit handlers, if they haven't already 203 * been run. Just in case we are being unloaded prior to 204 * Tcl (it can happen), we won't leave any dangling pointers 205 * hanging around for when Tcl gets unloaded later. 206 */ 207 208 TkFinalize(NULL); 209 } __except (EXCEPTION_EXECUTE_HANDLER) { 210 /* empty handler body. */ 211 } 212#endif 213 214 break; 215 } 216 return TRUE; 217} 218 219#endif /* !STATIC_BUILD */ 220