Home | History | Annotate | Line # | Download | only in roken
      1 /*	$NetBSD: dlfcn_w32.c,v 1.2 2017/01/28 21:31:50 christos Exp $	*/
      2 
      3 /***********************************************************************
      4  * Copyright (c) 2009, Secure Endpoints Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  * - Redistributions of source code must retain the above copyright
     12  *   notice, this list of conditions and the following disclaimer.
     13  *
     14  * - Redistributions in binary form must reproduce the above copyright
     15  *   notice, this list of conditions and the following disclaimer in
     16  *   the documentation and/or other materials provided with the
     17  *   distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     30  * OF THE POSSIBILITY OF SUCH DAMAGE.
     31  *
     32  **********************************************************************/
     33 
     34 #include <config.h>
     35 #include <windows.h>
     36 #include <dlfcn.h>
     37 #include <strsafe.h>
     38 
     39 #define ERR_STR_LEN 256
     40 
     41 static volatile LONG dlfcn_tls = TLS_OUT_OF_INDEXES;
     42 
     43 static DWORD get_tl_error_slot(void)
     44 {
     45     if (dlfcn_tls == TLS_OUT_OF_INDEXES) {
     46         DWORD slot = TlsAlloc();
     47         DWORD old_slot;
     48 
     49         if (slot == TLS_OUT_OF_INDEXES)
     50             return dlfcn_tls;
     51 
     52         if ((old_slot = InterlockedCompareExchange(&dlfcn_tls, slot,
     53                                                    TLS_OUT_OF_INDEXES)) !=
     54             TLS_OUT_OF_INDEXES) {
     55 
     56             /* Lost a race */
     57             TlsFree(slot);
     58             return old_slot;
     59         } else {
     60             return slot;
     61         }
     62     }
     63 
     64     return dlfcn_tls;
     65 }
     66 
     67 static void set_error(const char * e)
     68 {
     69     char * s;
     70     char * old_s;
     71     size_t len;
     72 
     73     DWORD slot = get_tl_error_slot();
     74 
     75     if (slot == TLS_OUT_OF_INDEXES)
     76         return;
     77 
     78     len = strlen(e) * sizeof(char) + sizeof(char);
     79     s = LocalAlloc(LMEM_FIXED, len);
     80     if (s == NULL)
     81         return;
     82 
     83     old_s = (char *) TlsGetValue(slot);
     84     TlsSetValue(slot, (LPVOID) s);
     85 
     86     if (old_s != NULL)
     87         LocalFree(old_s);
     88 }
     89 
     90 static void set_error_from_last(void) {
     91     DWORD slot = get_tl_error_slot();
     92     char * s = NULL;
     93     char * old_s;
     94 
     95     if (slot == TLS_OUT_OF_INDEXES)
     96         return;
     97 
     98     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
     99 		  0, GetLastError(), 0,
    100 		  (LPTSTR) &s, 0,
    101 		  NULL);
    102     if (s == NULL)
    103         return;
    104 
    105     old_s = (char *) TlsGetValue(slot);
    106     TlsSetValue(slot, (LPVOID) s);
    107 
    108     if (old_s != NULL)
    109         LocalFree(old_s);
    110 }
    111 
    112 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
    113 dlclose(void * vhm)
    114 {
    115     BOOL brv;
    116 
    117     brv = FreeLibrary((HMODULE) vhm);
    118     if (!brv) {
    119 	set_error_from_last();
    120     }
    121     return !brv;
    122 }
    123 
    124 ROKEN_LIB_FUNCTION char  * ROKEN_LIB_CALL
    125 dlerror(void)
    126 {
    127     DWORD slot = get_tl_error_slot();
    128 
    129     if (slot == TLS_OUT_OF_INDEXES)
    130         return NULL;
    131 
    132     return (char *) TlsGetValue(slot);
    133 }
    134 
    135 ROKEN_LIB_FUNCTION void  * ROKEN_LIB_CALL
    136 dlopen(const char *fn, int flags)
    137 {
    138     HMODULE hm;
    139     UINT    old_error_mode;
    140 
    141     /* We don't support dlopen(0, ...) on Windows.*/
    142     if ( fn == NULL ) {
    143 	set_error("Not implemented");
    144 	return NULL;
    145     }
    146 
    147     old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
    148 
    149     hm = LoadLibraryEx(fn, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
    150 
    151     if (hm == NULL) {
    152 	set_error_from_last();
    153     }
    154 
    155     SetErrorMode(old_error_mode);
    156 
    157     return (void *) hm;
    158 }
    159 
    160 ROKEN_LIB_FUNCTION DLSYM_RET_TYPE ROKEN_LIB_CALL
    161 dlsym(void * vhm, const char * func_name)
    162 {
    163     HMODULE hm = (HMODULE) vhm;
    164 
    165     return (DLSYM_RET_TYPE)(ULONG_PTR)GetProcAddress(hm, func_name);
    166 }
    167 
    168 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
    169 dladdr(void *addr, Dl_info *dli)
    170 {
    171     HMODULE hm;
    172     DWORD nsize;
    173 
    174     memset(dli, 0, sizeof(*dli));
    175     dli->dli_fname = dli->_dli_buf;
    176 
    177     if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
    178                            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    179 			   (LPCTSTR)(ULONG_PTR)addr, &hm))
    180         return 0;
    181 
    182     nsize = GetModuleFileName(hm, dli->_dli_buf, sizeof(dli->_dli_buf));
    183     dli->_dli_buf[sizeof(dli->_dli_buf) - 1] = '\0';
    184     if (nsize >= sizeof(dli->_dli_buf))
    185         return 0; /* truncated? can't be... */
    186     return 1;
    187 }
    188