Home | History | Annotate | Line # | Download | only in ms
      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