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