4f480a7981712dde22e522f6d6e3890ef243d8d6
[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 #ifdef SELFTEST
94 main()
95 {
96     UP_fprintf(UP_stdout, "hello, world!\n");
97 }
98 #endif