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