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