1 /* 2 * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (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 ExitProcess(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(_M_IX86) 103 # define LAZY(i) \ 104 __declspec(naked) static void lazy##i (void) { \ 105 _asm push i \ 106 _asm push OFFSET OPENSSL_UplinkTable \ 107 _asm call OPENSSL_Uplink \ 108 _asm add esp,8 \ 109 _asm jmp OPENSSL_UplinkTable+4*i } 110 111 # if APPLINK_MAX>25 112 # error "Add more stubs..." 113 # endif 114 /* make some in advance... */ 115 LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5) 116 LAZY(6) LAZY(7) LAZY(8) LAZY(9) LAZY(10) 117 LAZY(11) LAZY(12) LAZY(13) LAZY(14) LAZY(15) 118 LAZY(16) LAZY(17) LAZY(18) LAZY(19) LAZY(20) 119 LAZY(21) LAZY(22) LAZY(23) LAZY(24) LAZY(25) 120 void *OPENSSL_UplinkTable[] = { 121 (void *)APPLINK_MAX, 122 lazy1, lazy2, lazy3, lazy4, lazy5, 123 lazy6, lazy7, lazy8, lazy9, lazy10, 124 lazy11, lazy12, lazy13, lazy14, lazy15, 125 lazy16, lazy17, lazy18, lazy19, lazy20, 126 lazy21, lazy22, lazy23, lazy24, lazy25, 127 }; 128 #endif 129 130 #ifdef SELFTEST 131 main() 132 { 133 UP_fprintf(UP_stdout, "hello, world!\n"); 134 } 135 #endif 136