xref: /netbsd-src/crypto/external/bsd/openssl/dist/ms/uplink.c (revision b0d1725196a7921d003d2c66a14f186abda4176b)
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