Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Unified Diff: third_party/dlfcn-win32/dlfcn.c

Issue 137143003: Add dlfcn-win32 to third_party (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/deps/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/dlfcn-win32/dlfcn.h ('k') | third_party/dlfcn-win32/test.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/dlfcn-win32/dlfcn.c
===================================================================
--- third_party/dlfcn-win32/dlfcn.c (revision 0)
+++ third_party/dlfcn-win32/dlfcn.c (revision 0)
@@ -0,0 +1,312 @@
+/*
+ * dlfcn-win32
+ * Copyright (c) 2007 Ramiro Polla
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "dlfcn.h"
+
+/* Note:
+ * MSDN says these functions are not thread-safe. We make no efforts to have
+ * any kind of thread safety.
+ */
+
+typedef struct global_object {
+ HMODULE hModule;
+ struct global_object *previous;
+ struct global_object *next;
+} global_object;
+
+static global_object first_object;
+
+/* These functions implement a double linked list for the global objects. */
+static global_object *global_search( HMODULE hModule )
+{
+ global_object *pobject;
+
+ if( hModule == NULL )
+ return NULL;
+
+ for( pobject = &first_object; pobject ; pobject = pobject->next )
+ if( pobject->hModule == hModule )
+ return pobject;
+
+ return NULL;
+}
+
+static void global_add( HMODULE hModule )
+{
+ global_object *pobject;
+ global_object *nobject;
+
+ if( hModule == NULL )
+ return;
+
+ pobject = global_search( hModule );
+
+ /* Do not add object again if it's already on the list */
+ if( pobject )
+ return;
+
+ for( pobject = &first_object; pobject->next ; pobject = pobject->next );
+
+ nobject = malloc( sizeof(global_object) );
+
+ /* Should this be enough to fail global_add, and therefore also fail
+ * dlopen?
+ */
+ if( !nobject )
+ return;
+
+ pobject->next = nobject;
+ nobject->next = NULL;
+ nobject->previous = pobject;
+ nobject->hModule = hModule;
+}
+
+static void global_rem( HMODULE hModule )
+{
+ global_object *pobject;
+
+ if( hModule == NULL )
+ return;
+
+ pobject = global_search( hModule );
+
+ if( !pobject )
+ return;
+
+ if( pobject->next )
+ pobject->next->previous = pobject->previous;
+ if( pobject->previous )
+ pobject->previous->next = pobject->next;
+
+ free( pobject );
+}
+
+/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one
+ * static buffer.
+ * MSDN says the buffer cannot be larger than 64K bytes, so we set it to
+ * the limit.
+ */
+static char error_buffer[65535];
+static char *current_error;
+
+static int copy_string( char *dest, int dest_size, const char *src )
+{
+ int i = 0;
+
+ /* gcc should optimize this out */
+ if( !src || !dest )
+ return 0;
+
+ for( i = 0 ; i < dest_size-1 ; i++ )
+ {
+ if( !src[i] )
+ break;
+ else
+ dest[i] = src[i];
+ }
+ dest[i] = '\0';
+
+ return i;
+}
+
+static void save_err_str( const char *str )
+{
+ DWORD dwMessageId;
+ DWORD pos;
+
+ dwMessageId = GetLastError( );
+
+ if( dwMessageId == 0 )
+ return;
+
+ /* Format error message to:
+ * "<argument to function that failed>": <Windows localized error message>
+ */
+ pos = copy_string( error_buffer, sizeof(error_buffer), "\"" );
+ pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str );
+ pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " );
+ pos += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId,
+ MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
+ error_buffer+pos, sizeof(error_buffer)-pos, NULL );
+
+ if( pos > 1 )
+ {
+ /* POSIX says the string must not have trailing <newline> */
+ if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' )
+ error_buffer[pos-2] = '\0';
+ }
+
+ current_error = error_buffer;
+}
+
+static void save_err_ptr_str( const void *ptr )
+{
+ char ptr_buf[19]; /* 0x<pointer> up to 64 bits. */
+
+ sprintf( ptr_buf, "0x%p", ptr );
+
+ save_err_str( ptr_buf );
+}
+
+void *dlopen( const char *file, int mode )
+{
+ HMODULE hModule;
+ UINT uMode;
+
+ current_error = NULL;
+
+ /* Do not let Windows display the critical-error-handler message box */
+ uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
+
+ if( file == 0 )
+ {
+ /* POSIX says that if the value of file is 0, a handle on a global
+ * symbol object must be provided. That object must be able to access
+ * all symbols from the original program file, and any objects loaded
+ * with the RTLD_GLOBAL flag.
+ * The return value from GetModuleHandle( ) allows us to retrieve
+ * symbols only from the original program file. For objects loaded with
+ * the RTLD_GLOBAL flag, we create our own list later on.
+ */
+ hModule = GetModuleHandle( NULL );
+
+ if( !hModule )
+ save_err_ptr_str( file );
+ }
+ else
+ {
+ char lpFileName[MAX_PATH];
+ int i;
+
+ /* MSDN says backslashes *must* be used instead of forward slashes. */
+ for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ )
+ {
+ if( !file[i] )
+ break;
+ else if( file[i] == '/' )
+ lpFileName[i] = '\\';
+ else
+ lpFileName[i] = file[i];
+ }
+ lpFileName[i] = '\0';
+
+ /* POSIX says the search path is implementation-defined.
+ * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely
+ * to UNIX's search paths (start with system folders instead of current
+ * folder).
+ */
+ hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH );
+
+ /* If the object was loaded with RTLD_GLOBAL, add it to list of global
+ * objects, so that its symbols may be retrieved even if the handle for
+ * the original program file is passed. POSIX says that if the same
+ * file is specified in multiple invocations, and any of them are
+ * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the
+ * symbols will remain global.
+ */
+ if( !hModule )
+ save_err_str( lpFileName );
+ else if( (mode & RTLD_GLOBAL) )
+ global_add( hModule );
+ }
+
+ /* Return to previous state of the error-mode bit flags. */
+ SetErrorMode( uMode );
+
+ return (void *) hModule;
+}
+
+int dlclose( void *handle )
+{
+ HMODULE hModule = (HMODULE) handle;
+ BOOL ret;
+
+ current_error = NULL;
+
+ ret = FreeLibrary( hModule );
+
+ /* If the object was loaded with RTLD_GLOBAL, remove it from list of global
+ * objects.
+ */
+ if( ret )
+ global_rem( hModule );
+ else
+ save_err_ptr_str( handle );
+
+ /* dlclose's return value in inverted in relation to FreeLibrary's. */
+ ret = !ret;
+
+ return (int) ret;
+}
+
+void *dlsym( void *handle, const char *name )
+{
+ FARPROC symbol;
+
+ current_error = NULL;
+
+ symbol = GetProcAddress( handle, name );
+
+ if( symbol == NULL )
+ {
+ HMODULE hModule;
+
+ /* If the handle for the original program file is passed, also search
+ * in all globally loaded objects.
+ */
+
+ hModule = GetModuleHandle( NULL );
+
+ if( hModule == handle )
+ {
+ global_object *pobject;
+
+ for( pobject = &first_object; pobject ; pobject = pobject->next )
+ {
+ if( pobject->hModule )
+ {
+ symbol = GetProcAddress( pobject->hModule, name );
+ if( symbol != NULL )
+ break;
+ }
+ }
+ }
+ }
+
+ if( symbol == NULL )
+ save_err_str( name );
+
+ return (void*) symbol;
+}
+
+char *dlerror( void )
+{
+ char *error_pointer = current_error;
+
+ /* POSIX says that invoking dlerror( ) a second time, immediately following
+ * a prior invocation, shall result in NULL being returned.
+ */
+ current_error = NULL;
+
+ return error_pointer;
+}
Property changes on: third_party/dlfcn-win32/dlfcn.c
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « third_party/dlfcn-win32/dlfcn.h ('k') | third_party/dlfcn-win32/test.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698