1 /* 2 * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #if (defined(_WIN64) || defined(_WIN32_WCE)) && !defined(UNICODE) 11 #define UNICODE 12 #endif 13 #if defined(UNICODE) && !defined(_UNICODE) 14 #define _UNICODE 15 #endif 16 #if defined(_UNICODE) && !defined(UNICODE) 17 #define UNICODE 18 #endif 19 20 #include <windows.h> 21 #include <tchar.h> 22 #include <stdio.h> 23 #include "uplink.h" 24 void OPENSSL_showfatal(const char *, ...); 25 26 static TCHAR msg[128]; 27 28 static void unimplemented(void) 29 { 30 OPENSSL_showfatal(sizeof(TCHAR) == sizeof(char) ? "%s\n" : "%S\n", msg); 31 TerminateProcess(GetCurrentProcess(), 1); 32 } 33 34 void OPENSSL_Uplink(volatile void **table, int index) 35 { 36 static HMODULE volatile apphandle = NULL; 37 static void **volatile applinktable = NULL; 38 int len; 39 void (*func)(void) = unimplemented; 40 HANDLE h; 41 void **p; 42 43 /* 44 * Note that the below code is not MT-safe in respect to msg buffer, but 45 * what's the worst thing that can happen? Error message might be 46 * misleading or corrupted. As error condition is fatal and should never 47 * be risen, I accept the risk... 48 */ 49 /* 50 * One can argue that I should have used InterlockedExchangePointer or 51 * something to update static variables and table[]. Well, store 52 * instructions are as atomic as they can get and assigned values are 53 * effectively constant... So that volatile qualifier should be 54 * sufficient [it prohibits compiler to reorder memory access 55 * instructions]. 56 */ 57 do { 58 len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR), 59 _T("OPENSSL_Uplink(%p,%02X): "), table, index); 60 _tcscpy(msg + len, _T("unimplemented function")); 61 62 if ((h = apphandle) == NULL) { 63 if ((h = GetModuleHandle(NULL)) == NULL) { 64 apphandle = (HMODULE)-1; 65 _tcscpy(msg + len, _T("no host application")); 66 break; 67 } 68 apphandle = h; 69 } 70 if ((h = apphandle) == (HMODULE)-1) /* revalidate */ 71 break; 72 73 if (applinktable == NULL) { 74 void **(*applink)(); 75 76 applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink"); 77 if (applink == NULL) { 78 apphandle = (HMODULE)-1; 79 _tcscpy(msg + len, _T("no OPENSSL_Applink")); 80 break; 81 } 82 p = (*applink)(); 83 if (p == NULL) { 84 apphandle = (HMODULE)-1; 85 _tcscpy(msg + len, _T("no ApplinkTable")); 86 break; 87 } 88 applinktable = p; 89 } else 90 p = applinktable; 91 92 if (index > (int)p[0]) 93 break; 94 95 if (p[index]) 96 func = p[index]; 97 } while (0); 98 99 table[index] = func; 100 } 101 102 #if (defined(_MSC_VER) || defined(__BORLANDC__)) && defined(_M_IX86) 103 #if defined(_MSC_VER) 104 #define LAZY(i) \ 105 __declspec(naked) static void lazy##i(void) \ 106 { \ 107 _asm push i _asm push OFFSET OPENSSL_UplinkTable _asm call OPENSSL_Uplink _asm add esp, 8 _asm jmp OPENSSL_UplinkTable + 4 * i \ 108 } 109 #elif defined(__BORLANDC__) && defined(__clang__) 110 void *OPENSSL_UplinkTable[26]; /* C++Builder requires declaration before use */ 111 #define LAZY(i) \ 112 __declspec(naked) static void lazy##i(void) \ 113 { \ 114 __asm__("pushl $" #i "; " \ 115 "pushl %0; " \ 116 "call %P1; " \ 117 "addl $8, %%esp; " \ 118 "jmp *%2 " \ 119 : /* no outputs */ \ 120 : "i"(OPENSSL_UplinkTable), \ 121 "i"(OPENSSL_Uplink), \ 122 "m"(OPENSSL_UplinkTable[i])); \ 123 } 124 #endif 125 126 #if APPLINK_MAX > 25 127 #error "Add more stubs..." 128 #endif 129 /* make some in advance... */ 130 LAZY(1) 131 LAZY(2) 132 LAZY(3) 133 LAZY(4) 134 LAZY(5) 135 LAZY(6) 136 LAZY(7) 137 LAZY(8) 138 LAZY(9) 139 LAZY(10) 140 LAZY(11) 141 LAZY(12) 142 LAZY(13) 143 LAZY(14) 144 LAZY(15) 145 LAZY(16) 146 LAZY(17) 147 LAZY(18) 148 LAZY(19) 149 LAZY(20) 150 LAZY(21) 151 LAZY(22) 152 LAZY(23) 153 LAZY(24) 154 LAZY(25) 155 void *OPENSSL_UplinkTable[] = { 156 (void *)APPLINK_MAX, 157 lazy1, 158 lazy2, 159 lazy3, 160 lazy4, 161 lazy5, 162 lazy6, 163 lazy7, 164 lazy8, 165 lazy9, 166 lazy10, 167 lazy11, 168 lazy12, 169 lazy13, 170 lazy14, 171 lazy15, 172 lazy16, 173 lazy17, 174 lazy18, 175 lazy19, 176 lazy20, 177 lazy21, 178 lazy22, 179 lazy23, 180 lazy24, 181 lazy25, 182 }; 183 #endif 184 185 #ifdef SELFTEST 186 main() 187 { 188 UP_fprintf(UP_stdout, "hello, world!\n"); 189 } 190 #endif 191