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 of 9 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 10 * 11 * RCS: @(#) $Id$ 12 */ 13 14#include "tkWinInt.h" 15#ifndef STATIC_BUILD 16 17#ifdef HAVE_NO_SEH 18 19/* 20 * Unlike Borland and Microsoft, we don't register exception handlers by 21 * pushing registration records onto the runtime stack. Instead, we register 22 * them by creating an EXCEPTION_REGISTRATION within the activation record. 23 */ 24 25typedef struct EXCEPTION_REGISTRATION { 26 struct EXCEPTION_REGISTRATION *link; 27 EXCEPTION_DISPOSITION (*handler)( 28 struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); 29 void *ebp; 30 void *esp; 31 int status; 32} EXCEPTION_REGISTRATION; 33 34/* 35 * Need to add noinline flag to DllMain declaration so that gcc -O3 does not 36 * inline asm code into DllEntryPoint and cause a compile time error because 37 * of redefined local labels. 38 */ 39 40BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, 41 LPVOID reserved) __attribute__ ((noinline)); 42 43#else /* !HAVE_NO_SEH */ 44 45/* 46 * The following declaration is for the VC++ DLL entry point. 47 */ 48 49BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, 50 LPVOID reserved); 51#endif /* HAVE_NO_SEH */ 52 53/* 54 *---------------------------------------------------------------------- 55 * 56 * DllEntryPoint -- 57 * 58 * This wrapper function is used by Borland to invoke the initialization 59 * code for Tk. It simply calls the DllMain routine. 60 * 61 * Results: 62 * See DllMain. 63 * 64 * Side effects: 65 * See DllMain. 66 * 67 *---------------------------------------------------------------------- 68 */ 69 70BOOL APIENTRY 71DllEntryPoint( 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 that 85 * resources are found correctly. Otherwise Tk will initialize and clean 86 * up after itself through other methods, in order to be consistent 87 * 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 documentation 94 * states: "Waiting on synchronization objects in DllMain can cause a 95 * deadlock." 96 * 97 *---------------------------------------------------------------------- 98 */ 99 100BOOL APIENTRY 101DllMain( 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 the 112 * 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 be 124 * guarenteed Tk is always being unloaded from a stable condition. 125 */ 126 127#ifdef HAVE_NO_SEH 128 __asm__ __volatile__ ( 129 130 /* 131 * Construct an EXCEPTION_REGISTRATION to protect the call to 132 * TkFinalize 133 */ 134 135 "leal %[registration], %%edx" "\n\t" 136 "movl %%fs:0, %%eax" "\n\t" 137 "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ 138 "leal 1f, %%eax" "\n\t" 139 "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ 140 "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ 141 "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ 142 "movl %[error], 0x10(%%edx)" "\n\t" /* status */ 143 144 /* 145 * Link the EXCEPTION_REGISTRATION on the chain 146 */ 147 148 "movl %%edx, %%fs:0" "\n\t" 149 150 /* 151 * Call TkFinalize 152 */ 153 154 "movl $0x0, 0x0(%%esp)" "\n\t" 155 "call _TkFinalize" "\n\t" 156 157 /* 158 * Come here on a normal exit. Recover the EXCEPTION_REGISTRATION 159 * and store a TCL_OK status 160 */ 161 162 "movl %%fs:0, %%edx" "\n\t" 163 "movl %[ok], %%eax" "\n\t" 164 "movl %%eax, 0x10(%%edx)" "\n\t" 165 "jmp 2f" "\n" 166 167 /* 168 * Come here on an exception. Get the EXCEPTION_REGISTRATION that 169 * we previously put on the chain. 170 */ 171 172 "1:" "\t" 173 "movl %%fs:0, %%edx" "\n\t" 174 "movl 0x8(%%edx), %%edx" "\n" 175 176 177 /* 178 * Come here however we exited. Restore context from the 179 * EXCEPTION_REGISTRATION in case the stack is unbalanced. 180 */ 181 182 "2:" "\t" 183 "movl 0xc(%%edx), %%esp" "\n\t" 184 "movl 0x8(%%edx), %%ebp" "\n\t" 185 "movl 0x0(%%edx), %%eax" "\n\t" 186 "movl %%eax, %%fs:0" "\n\t" 187 188 : 189 /* No outputs */ 190 : 191 [registration] "m" (registration), 192 [ok] "i" (TCL_OK), 193 [error] "i" (TCL_ERROR) 194 : 195 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" 196 ); 197 198#else /* HAVE_NO_SEH */ 199 __try { 200 /* 201 * Run and remove our exit handlers, if they haven't already been 202 * run. Just in case we are being unloaded prior to Tcl (it can 203 * happen), we won't leave any dangling pointers hanging around 204 * for when Tcl gets unloaded later. 205 */ 206 207 TkFinalize(NULL); 208 } __except (EXCEPTION_EXECUTE_HANDLER) { 209 /* empty handler body. */ 210 } 211#endif 212 213 break; 214 } 215 return TRUE; 216} 217 218#endif /* !STATIC_BUILD */ 219 220/* 221 * Local Variables: 222 * mode: c 223 * c-basic-offset: 4 224 * fill-column: 78 225 * End: 226 */ 227