Home | History | Annotate | Line # | Download | only in ms
      1 /*
      2  * Copyright 2004-2019 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     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(_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