1c7da899bSchristos /*
2*b0d17251Schristos * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
3c7da899bSchristos *
4*b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
5c7da899bSchristos * this file except in compliance with the License. You can obtain a copy
6c7da899bSchristos * in the file LICENSE in the source distribution or at
7c7da899bSchristos * https://www.openssl.org/source/license.html
8c7da899bSchristos */
9c7da899bSchristos
10a89c9211Schristos #if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE)
11a89c9211Schristos # define UNICODE
12a89c9211Schristos #endif
13a89c9211Schristos #if defined(UNICODE) && !defined(_UNICODE)
14a89c9211Schristos # define _UNICODE
15a89c9211Schristos #endif
16a89c9211Schristos #if defined(_UNICODE) && !defined(UNICODE)
17a89c9211Schristos # define UNICODE
18a89c9211Schristos #endif
19a89c9211Schristos
20a89c9211Schristos #include <windows.h>
21a89c9211Schristos #include <tchar.h>
22a89c9211Schristos #include <stdio.h>
23a89c9211Schristos #include "uplink.h"
24a89c9211Schristos void OPENSSL_showfatal(const char *, ...);
25a89c9211Schristos
26a89c9211Schristos static TCHAR msg[128];
27a89c9211Schristos
unimplemented(void)28a89c9211Schristos static void unimplemented(void)
29635165faSspz {
30635165faSspz OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg);
31b88c74d5Schristos TerminateProcess(GetCurrentProcess(), 1);
32a89c9211Schristos }
33a89c9211Schristos
OPENSSL_Uplink(volatile void ** table,int index)34a89c9211Schristos void OPENSSL_Uplink(volatile void **table, int index)
35635165faSspz {
36635165faSspz static HMODULE volatile apphandle = NULL;
37a89c9211Schristos static void **volatile applinktable = NULL;
38a89c9211Schristos int len;
39a89c9211Schristos void (*func) (void) = unimplemented;
40a89c9211Schristos HANDLE h;
41a89c9211Schristos void **p;
42a89c9211Schristos
43635165faSspz /*
44635165faSspz * Note that the below code is not MT-safe in respect to msg buffer, but
45635165faSspz * what's the worst thing that can happen? Error message might be
46635165faSspz * misleading or corrupted. As error condition is fatal and should never
47635165faSspz * be risen, I accept the risk...
48635165faSspz */
49635165faSspz /*
50635165faSspz * One can argue that I should have used InterlockedExchangePointer or
51635165faSspz * something to update static variables and table[]. Well, store
52635165faSspz * instructions are as atomic as they can get and assigned values are
53635165faSspz * effectively constant... So that volatile qualifier should be
54635165faSspz * sufficient [it prohibits compiler to reorder memory access
55635165faSspz * instructions].
56635165faSspz */
57a89c9211Schristos do {
5832daad53Schristos len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR),
5932daad53Schristos _T("OPENSSL_Uplink(%p,%02X): "), table, index);
60a89c9211Schristos _tcscpy(msg + len, _T("unimplemented function"));
61a89c9211Schristos
62635165faSspz if ((h = apphandle) == NULL) {
63635165faSspz if ((h = GetModuleHandle(NULL)) == NULL) {
64635165faSspz apphandle = (HMODULE) - 1;
65a89c9211Schristos _tcscpy(msg + len, _T("no host application"));
66a89c9211Schristos break;
67a89c9211Schristos }
68a89c9211Schristos apphandle = h;
69a89c9211Schristos }
70a89c9211Schristos if ((h = apphandle) == (HMODULE) - 1) /* revalidate */
71a89c9211Schristos break;
72a89c9211Schristos
73635165faSspz if (applinktable == NULL) {
74635165faSspz void **(*applink) ();
75a89c9211Schristos
76a89c9211Schristos applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink");
77635165faSspz if (applink == NULL) {
78635165faSspz apphandle = (HMODULE) - 1;
79a89c9211Schristos _tcscpy(msg + len, _T("no OPENSSL_Applink"));
80a89c9211Schristos break;
81a89c9211Schristos }
82a89c9211Schristos p = (*applink) ();
83635165faSspz if (p == NULL) {
84635165faSspz apphandle = (HMODULE) - 1;
85a89c9211Schristos _tcscpy(msg + len, _T("no ApplinkTable"));
86a89c9211Schristos break;
87a89c9211Schristos }
88a89c9211Schristos applinktable = p;
89635165faSspz } else
90a89c9211Schristos p = applinktable;
91a89c9211Schristos
92a89c9211Schristos if (index > (int)p[0])
93a89c9211Schristos break;
94a89c9211Schristos
95635165faSspz if (p[index])
96635165faSspz func = p[index];
97a89c9211Schristos } while (0);
98a89c9211Schristos
99a89c9211Schristos table[index] = func;
100a89c9211Schristos }
101a89c9211Schristos
102*b0d17251Schristos #if (defined(_MSC_VER) || defined(__BORLANDC__)) && defined(_M_IX86)
103*b0d17251Schristos # if defined(_MSC_VER)
104a89c9211Schristos # define LAZY(i) \
105a89c9211Schristos __declspec(naked) static void lazy##i (void) { \
106a89c9211Schristos _asm push i \
107a89c9211Schristos _asm push OFFSET OPENSSL_UplinkTable \
108a89c9211Schristos _asm call OPENSSL_Uplink \
109a89c9211Schristos _asm add esp,8 \
110a89c9211Schristos _asm jmp OPENSSL_UplinkTable+4*i }
111*b0d17251Schristos # elif defined(__BORLANDC__) && defined(__clang__)
112*b0d17251Schristos void *OPENSSL_UplinkTable[26]; /* C++Builder requires declaration before use */
113*b0d17251Schristos # define LAZY(i) \
114*b0d17251Schristos __declspec(naked) static void lazy##i (void) { \
115*b0d17251Schristos __asm__("pushl $" #i "; " \
116*b0d17251Schristos "pushl %0; " \
117*b0d17251Schristos "call %P1; " \
118*b0d17251Schristos "addl $8, %%esp; " \
119*b0d17251Schristos "jmp *%2 " \
120*b0d17251Schristos : /* no outputs */ \
121*b0d17251Schristos : "i" (OPENSSL_UplinkTable), \
122*b0d17251Schristos "i" (OPENSSL_Uplink), \
123*b0d17251Schristos "m" (OPENSSL_UplinkTable[i])); }
124*b0d17251Schristos # endif
125a89c9211Schristos
126a89c9211Schristos # if APPLINK_MAX>25
127a89c9211Schristos # error "Add more stubs..."
128a89c9211Schristos # endif
129a89c9211Schristos /* make some in advance... */
130a89c9211Schristos LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5)
131a89c9211Schristos LAZY(6) LAZY(7) LAZY(8) LAZY(9) LAZY(10)
132a89c9211Schristos LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15)
133a89c9211Schristos LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20)
134a89c9211Schristos LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25)
135a89c9211Schristos void *OPENSSL_UplinkTable[] = {
136a89c9211Schristos (void *)APPLINK_MAX,
137a89c9211Schristos lazy1, lazy2, lazy3, lazy4, lazy5,
138a89c9211Schristos lazy6, lazy7, lazy8, lazy9, lazy10,
139a89c9211Schristos lazy11, lazy12, lazy13, lazy14, lazy15,
140a89c9211Schristos lazy16, lazy17, lazy18, lazy19, lazy20,
141a89c9211Schristos lazy21, lazy22, lazy23, lazy24, lazy25,
142a89c9211Schristos };
143a89c9211Schristos #endif
144a89c9211Schristos
145a89c9211Schristos #ifdef SELFTEST
main()146635165faSspz main()
147635165faSspz {
148635165faSspz UP_fprintf(UP_stdout, "hello, world!\n");
149635165faSspz }
150a89c9211Schristos #endif
151