1ebfedea0SLionel Sambuc #if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE)
2ebfedea0SLionel Sambuc # define UNICODE
3ebfedea0SLionel Sambuc #endif
4ebfedea0SLionel Sambuc #if defined(UNICODE) && !defined(_UNICODE)
5ebfedea0SLionel Sambuc # define _UNICODE
6ebfedea0SLionel Sambuc #endif
7ebfedea0SLionel Sambuc #if defined(_UNICODE) && !defined(UNICODE)
8ebfedea0SLionel Sambuc # define UNICODE
9ebfedea0SLionel Sambuc #endif
10ebfedea0SLionel Sambuc
11ebfedea0SLionel Sambuc #include <windows.h>
12ebfedea0SLionel Sambuc #include <tchar.h>
13ebfedea0SLionel Sambuc #include <stdio.h>
14ebfedea0SLionel Sambuc #include "uplink.h"
15ebfedea0SLionel Sambuc void OPENSSL_showfatal(const char *, ...);
16ebfedea0SLionel Sambuc
17ebfedea0SLionel Sambuc static TCHAR msg[128];
18ebfedea0SLionel Sambuc
unimplemented(void)19ebfedea0SLionel Sambuc static void unimplemented(void)
20*0a6a1f1dSLionel Sambuc {
21*0a6a1f1dSLionel Sambuc OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg);
22ebfedea0SLionel Sambuc ExitProcess(1);
23ebfedea0SLionel Sambuc }
24ebfedea0SLionel Sambuc
OPENSSL_Uplink(volatile void ** table,int index)25ebfedea0SLionel Sambuc void OPENSSL_Uplink(volatile void **table, int index)
26*0a6a1f1dSLionel Sambuc {
27*0a6a1f1dSLionel Sambuc static HMODULE volatile apphandle = NULL;
28ebfedea0SLionel Sambuc static void **volatile applinktable = NULL;
29ebfedea0SLionel Sambuc int len;
30ebfedea0SLionel Sambuc void (*func) (void) = unimplemented;
31ebfedea0SLionel Sambuc HANDLE h;
32ebfedea0SLionel Sambuc void **p;
33ebfedea0SLionel Sambuc
34*0a6a1f1dSLionel Sambuc /*
35*0a6a1f1dSLionel Sambuc * Note that the below code is not MT-safe in respect to msg buffer, but
36*0a6a1f1dSLionel Sambuc * what's the worst thing that can happen? Error message might be
37*0a6a1f1dSLionel Sambuc * misleading or corrupted. As error condition is fatal and should never
38*0a6a1f1dSLionel Sambuc * be risen, I accept the risk...
39*0a6a1f1dSLionel Sambuc */
40*0a6a1f1dSLionel Sambuc /*
41*0a6a1f1dSLionel Sambuc * One can argue that I should have used InterlockedExchangePointer or
42*0a6a1f1dSLionel Sambuc * something to update static variables and table[]. Well, store
43*0a6a1f1dSLionel Sambuc * instructions are as atomic as they can get and assigned values are
44*0a6a1f1dSLionel Sambuc * effectively constant... So that volatile qualifier should be
45*0a6a1f1dSLionel Sambuc * sufficient [it prohibits compiler to reorder memory access
46*0a6a1f1dSLionel Sambuc * instructions].
47*0a6a1f1dSLionel Sambuc */
48ebfedea0SLionel Sambuc do {
49ebfedea0SLionel Sambuc len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR),
50ebfedea0SLionel Sambuc _T("OPENSSL_Uplink(%p,%02X): "), table, index);
51ebfedea0SLionel Sambuc _tcscpy(msg + len, _T("unimplemented function"));
52ebfedea0SLionel Sambuc
53*0a6a1f1dSLionel Sambuc if ((h = apphandle) == NULL) {
54*0a6a1f1dSLionel Sambuc if ((h = GetModuleHandle(NULL)) == NULL) {
55*0a6a1f1dSLionel Sambuc apphandle = (HMODULE) - 1;
56ebfedea0SLionel Sambuc _tcscpy(msg + len, _T("no host application"));
57ebfedea0SLionel Sambuc break;
58ebfedea0SLionel Sambuc }
59ebfedea0SLionel Sambuc apphandle = h;
60ebfedea0SLionel Sambuc }
61ebfedea0SLionel Sambuc if ((h = apphandle) == (HMODULE) - 1) /* revalidate */
62ebfedea0SLionel Sambuc break;
63ebfedea0SLionel Sambuc
64*0a6a1f1dSLionel Sambuc if (applinktable == NULL) {
65*0a6a1f1dSLionel Sambuc void **(*applink) ();
66ebfedea0SLionel Sambuc
67ebfedea0SLionel Sambuc applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink");
68*0a6a1f1dSLionel Sambuc if (applink == NULL) {
69*0a6a1f1dSLionel Sambuc apphandle = (HMODULE) - 1;
70ebfedea0SLionel Sambuc _tcscpy(msg + len, _T("no OPENSSL_Applink"));
71ebfedea0SLionel Sambuc break;
72ebfedea0SLionel Sambuc }
73ebfedea0SLionel Sambuc p = (*applink) ();
74*0a6a1f1dSLionel Sambuc if (p == NULL) {
75*0a6a1f1dSLionel Sambuc apphandle = (HMODULE) - 1;
76ebfedea0SLionel Sambuc _tcscpy(msg + len, _T("no ApplinkTable"));
77ebfedea0SLionel Sambuc break;
78ebfedea0SLionel Sambuc }
79ebfedea0SLionel Sambuc applinktable = p;
80*0a6a1f1dSLionel Sambuc } else
81ebfedea0SLionel Sambuc p = applinktable;
82ebfedea0SLionel Sambuc
83ebfedea0SLionel Sambuc if (index > (int)p[0])
84ebfedea0SLionel Sambuc break;
85ebfedea0SLionel Sambuc
86*0a6a1f1dSLionel Sambuc if (p[index])
87*0a6a1f1dSLionel Sambuc func = p[index];
88ebfedea0SLionel Sambuc } while (0);
89ebfedea0SLionel Sambuc
90ebfedea0SLionel Sambuc table[index] = func;
91ebfedea0SLionel Sambuc }
92ebfedea0SLionel Sambuc
93ebfedea0SLionel Sambuc #if defined(_MSC_VER) && defined(_M_IX86) && !defined(OPENSSL_NO_INLINE_ASM)
94ebfedea0SLionel Sambuc # define LAZY(i) \
95ebfedea0SLionel Sambuc __declspec(naked) static void lazy##i (void) { \
96ebfedea0SLionel Sambuc _asm push i \
97ebfedea0SLionel Sambuc _asm push OFFSET OPENSSL_UplinkTable \
98ebfedea0SLionel Sambuc _asm call OPENSSL_Uplink \
99ebfedea0SLionel Sambuc _asm add esp,8 \
100ebfedea0SLionel Sambuc _asm jmp OPENSSL_UplinkTable+4*i }
101ebfedea0SLionel Sambuc
102ebfedea0SLionel Sambuc # if APPLINK_MAX>25
103ebfedea0SLionel Sambuc # error "Add more stubs..."
104ebfedea0SLionel Sambuc # endif
105ebfedea0SLionel Sambuc /* make some in advance... */
106ebfedea0SLionel Sambuc LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5)
107ebfedea0SLionel Sambuc LAZY(6) LAZY(7) LAZY(8) LAZY(9) LAZY(10)
108ebfedea0SLionel Sambuc LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15)
109ebfedea0SLionel Sambuc LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20)
110ebfedea0SLionel Sambuc LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25)
111ebfedea0SLionel Sambuc void *OPENSSL_UplinkTable[] = {
112ebfedea0SLionel Sambuc (void *)APPLINK_MAX,
113ebfedea0SLionel Sambuc lazy1, lazy2, lazy3, lazy4, lazy5,
114ebfedea0SLionel Sambuc lazy6, lazy7, lazy8, lazy9, lazy10,
115ebfedea0SLionel Sambuc lazy11, lazy12, lazy13, lazy14, lazy15,
116ebfedea0SLionel Sambuc lazy16, lazy17, lazy18, lazy19, lazy20,
117ebfedea0SLionel Sambuc lazy21, lazy22, lazy23, lazy24, lazy25,
118ebfedea0SLionel Sambuc };
119ebfedea0SLionel Sambuc #endif
120ebfedea0SLionel Sambuc
121ebfedea0SLionel Sambuc #ifdef SELFTEST
main()122*0a6a1f1dSLionel Sambuc main()
123*0a6a1f1dSLionel Sambuc {
124*0a6a1f1dSLionel Sambuc UP_fprintf(UP_stdout, "hello, world!\n");
125*0a6a1f1dSLionel Sambuc }
126ebfedea0SLionel Sambuc #endif
127