-void OPENSSL_Uplink (void **table, int index)
-{ static HMODULE app=NULL;
- static void **applinktable=NULL;
- int len;
-
- len = _stprintf (msg,_T("OPENSSL_Uplink(%p,%02X): "),table,index);
- _tcscpy (msg+len,_T("unimplemented function"));
- table [index] = unimplemented;
-
- if (app==NULL && (app=GetModuleHandle(NULL))==NULL)
- { app=(HMODULE)-1; _tcscpy (msg+len,_T("no host application"));
- return;
- }
- else if (app==(HMODULE)-1) { return; }
-
- if (applinktable==NULL)
- { void**(*applink)();
-
- applink=(void**(*)())GetProcAddress(app,"OPENSSL_Applink");
- if (applink==NULL)
- { app=(HMODULE)-1; _tcscpy (msg+len,_T("no OPENSSL_Applink"));
- return;
- }
- applinktable = (*applink)();
- if (applinktable==NULL)
- { app=(HMODULE)-1; _tcscpy (msg+len,_T("no ApplinkTable"));
- return;
- }
- }
-
- if (index > (int)applinktable[0]) { return; }
-
- if (applinktable[index]) table[index] = applinktable[index];
-}
+void OPENSSL_Uplink(volatile void **table, int index)
+{
+ static HMODULE volatile apphandle = NULL;
+ static void **volatile applinktable = NULL;
+ int len;
+ void (*func) (void) = unimplemented;
+ HANDLE h;
+ void **p;
+
+ /*
+ * Note that the below code is not MT-safe in respect to msg buffer, but
+ * what's the worst thing that can happen? Error message might be
+ * misleading or corrupted. As error condition is fatal and should never
+ * be risen, I accept the risk...
+ */
+ /*
+ * One can argue that I should have used InterlockedExchangePointer or
+ * something to update static variables and table[]. Well, store
+ * instructions are as atomic as they can get and assigned values are
+ * effectively constant... So that volatile qualifier should be
+ * sufficient [it prohibits compiler to reorder memory access
+ * instructions].
+ */
+ do {
+ len = _sntprintf(msg, sizeof(msg) / sizeof(TCHAR),
+ _T("OPENSSL_Uplink(%p,%02X): "), table, index);
+ _tcscpy(msg + len, _T("unimplemented function"));
+
+ if ((h = apphandle) == NULL) {
+ if ((h = GetModuleHandle(NULL)) == NULL) {
+ apphandle = (HMODULE) - 1;
+ _tcscpy(msg + len, _T("no host application"));
+ break;
+ }
+ apphandle = h;
+ }
+ if ((h = apphandle) == (HMODULE) - 1) /* revalidate */
+ break;
+
+ if (applinktable == NULL) {
+ void **(*applink) ();
+
+ applink = (void **(*)())GetProcAddress(h, "OPENSSL_Applink");
+ if (applink == NULL) {
+ apphandle = (HMODULE) - 1;
+ _tcscpy(msg + len, _T("no OPENSSL_Applink"));
+ break;
+ }
+ p = (*applink) ();
+ if (p == NULL) {
+ apphandle = (HMODULE) - 1;
+ _tcscpy(msg + len, _T("no ApplinkTable"));
+ break;
+ }
+ applinktable = p;
+ } else
+ p = applinktable;
+
+ if (index > (int)p[0])
+ break;
+
+ if (p[index])
+ func = p[index];
+ } while (0);
+
+ table[index] = func;
+}