dynamic_link_handle dynamic_load( const wchar_t* library, const dynamic_link_descriptor descriptors[], size_t required ) {
 ::tbb::internal::suppress_unused_warning( library, descriptors, required );
 #if __TBB_DYNAMIC_LOAD_ENABLED
 #if _XBOX
     return LoadLibrary (library);
 #else /* _XBOX */
     size_t const len = PATH_MAX + 1;
     wchar_t path[ len ];
     size_t rc = abs_path( library, path, len );
     if ( 0 < rc && rc < len ) {
 #if _WIN32
         // Prevent Windows from displaying silly message boxes if it fails to load library
         // (e.g. because of MS runtime problems - one of those crazy manifest related ones)
         UINT prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
 #endif /* _WIN32 */
         dynamic_link_handle library_handle = dlopen( path, RTLD_LAZY );
 #if _WIN32
         SetErrorMode (prev_mode);
 #endif /* _WIN32 */
         if( library_handle ) {
             if( !resolve_symbols( library_handle, descriptors, required ) ) {
                 // The loaded library does not contain all the expected entry points
                 dynamic_unlink( library_handle );
                 library_handle = NULL;
             }
         } else
             DYNAMIC_LINK_WARNING( dl_lib_not_found, path, dlerror() );
         return library_handle;
     } else if ( rc>=len )
             DYNAMIC_LINK_WARNING( dl_buff_too_small );
             // rc == 0 means failing of init_ap_data so the warning has already been issued.
 #endif /* _XBOX */
 #endif /* __TBB_DYNAMIC_LOAD_ENABLED */
     return 0;
 }
Beispiel #2
0
/*
    There is a security issue on Windows: LoadLibrary() may load and execute malicious code.
    See http://www.microsoft.com/technet/security/advisory/2269637.mspx for details.
    To avoid the issue, we have to pass full path (not just library name) to LoadLibrary. This
    function constructs full path to the specified library (it is assumed the library located
    side-by-side with the tbb.dll.

    The function constructs absolute path for given relative path. Important: Base directory is not
    current one, it is the directory tbb.dll loaded from.

    Example:
        Let us assume "tbb.dll" is located in "c:\program files\common\intel\" directory, e. g.
        absolute path of tbb library is "c:\program files\common\intel\tbb.dll". Absolute path for
        "tbbmalloc.dll" would be "c:\program files\common\intel\tbbmalloc.dll". Absolute path for
        "malloc\tbbmalloc.dll" would be "c:\program files\common\intel\malloc\tbbmalloc.dll".

    Arguments:
        in  name -- Name of a file (may be with relative path; it must not be an absolute one).
        out path -- Buffer to save result (absolute path) to.
        in  len  -- Size of buffer.
        ret      -- 0         -- Error occurred.
                    > len     -- Buffer too short, required size returned.
                    otherwise -- Ok, number of characters (not counting terminating null) written to
                                 buffer.
*/
static size_t abs_path( char const * name, char * path, size_t len ) {
    // Get handle of our DLL first.
    HMODULE handle;
    BOOL brc =
        GetModuleHandleEx(
            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            (LPCSTR)( & abs_path ),
            & handle
        );
    if ( ! brc ) {    // Error occurred.
        int err = GetLastError();
        DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err );
        return 0;
    } // if

    // Now get path to our DLL.
    DWORD drc = GetModuleFileName( handle, path, static_cast< DWORD >( len ) );
    if ( drc == 0 ) {    // Error occurred.
        int err = GetLastError();
        DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err );
        return drc;
    } // if
    if ( drc >= len ) {  // Buffer too short.
        DYNAMIC_LINK_WARNING( dl_buff_too_small );
        return drc;
    } // if

    // Find the position of the last backslash.
    char * backslash = path + drc;            // backslash points behind the path.
    LIBRARY_ASSERT( * backslash == 0, NULL );
    while ( backslash > path && * backslash != '\\' ) {
        -- backslash;
    } // while
    if ( backslash <= path ) {    // Backslash not found.
        return 0;                 // Unbelievable.
    } // if

    // Now append name to construct the full path.
    LIBRARY_ASSERT( * backslash == '\\', NULL );
    size_t rc = ( backslash + 1 - path ) + strlen( name );
    if ( rc >= len ) {
        DYNAMIC_LINK_WARNING( dl_buff_too_small );
        return rc + 1;
    } // if
    strcpy( backslash + 1, name );
    LIBRARY_ASSERT( rc == strlen( path ), NULL );
    return rc;
} // abs_path
    static dynamic_link_handle pin_symbols( dynamic_link_handle library_handle, dynamic_link_descriptor desc, const dynamic_link_descriptor* descriptors, size_t required ) {
        ::tbb::internal::suppress_unused_warning( desc, descriptors, required );
#if __TBB_DYNAMIC_LOAD_ENABLED
        // It is supposed that all symbols are from the only one library
        // The library has been loaded by another module and contains at least one requested symbol.
        // But after we obtained the symbol the library can be unloaded by another thread
        // invalidating our symbol. Therefore we need to pin the library in memory.
        Dl_info info;
        // Get library's name from earlier found symbol
        if ( dladdr( (void*)*desc.handler, &info ) ) {
            // Pin the library
            library_handle = dlopen( info.dli_fname, RTLD_LAZY );
            if ( library_handle ) {
                // If original library was unloaded before we pinned it
                // and then another module loaded in its place, the earlier
                // found symbol would become invalid. So revalidate them.
                if ( !resolve_symbols( library_handle, descriptors, required ) ) {
                    // Wrong library.
                    dynamic_unlink(library_handle);
                    library_handle = 0;
                }
            } else {
                char const * err = dlerror();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, info.dli_fname, err );
            }
        }
        else {
            // The library have been unloaded by another thread
            library_handle = 0;
        }
#endif /* __TBB_DYNAMIC_LOAD_ENABLED */
        return library_handle;
    }
Beispiel #4
0
 _abs_path() {
     if ( getcwd( _path, PATH_MAX+1 ) ) {
         _state = ap_only_cwd;
         _len = strlen( _path );
         _path[_len++]='/';
     } else {
         DYNAMIC_LINK_WARNING( dl_buff_too_small );
         _state = ap_invalid;
     }
 }
Beispiel #5
0
bool dynamic_link( dynamic_link_handle module, const dynamic_link_descriptor descriptors[], size_t n, size_t required )
{
    LIBRARY_ASSERT( module != NULL, "Module handle is NULL" );
    if ( module == NULL ) {
        return false;
    } // if
    pointer_to_handler *h = (pointer_to_handler*)alloca(n * sizeof(pointer_to_handler));
    if ( required == ~(size_t)0 )
        required = n;
    LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" );
    size_t k = 0;
    for ( ; k < n; ++k ) {
        dynamic_link_descriptor const & desc = descriptors[k];
#if _WIN32||_WIN64
        FARPROC addr = GetProcAddress( module, desc.name );
        if ( addr == NULL ) {
            int err = GetLastError();
            DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err );
        } // if
        h[k] = pointer_to_handler( addr );
#else /* !WIN */
        void * addr = dlsym( module, desc.name );
        if ( addr == NULL ) {
            char const * err = dlerror();
            DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err );
        } // if
        // Lvalue casting is used; this way icc -strict-ansi does not warn about nonstandard pointer conversion
        (void *&)h[k] = addr;
#endif /* !WIN */
        if ( !h[k] && k < required )
            return false;
    }
    LIBRARY_ASSERT( k == n, "if required entries are initialized, all entries are expected to be walked");
    // Commit the entry points.
    // Cannot use memset here, because the writes must be atomic.
    for( k = 0; k < n; ++k )
        *descriptors[k].handler = h[k];
    return true;
}
Beispiel #6
0
        bool prepare_full_path() {
            LIBRARY_ASSERT( _state==ap_only_cwd, NULL );

            Dl_info dlinfo;
            int res = dladdr( (void*)&dynamic_unlink, &dlinfo );
            if ( !res ) {
                char const * err = dlerror();
                DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );
                return false;
            }

            size_t fname_len = strlen( dlinfo.dli_fname );
            // Find the position of the last backslash.
            while ( fname_len>0 && dlinfo.dli_fname[fname_len-1]!='/' ) fname_len-=1;

            size_t rc;

            if ( dlinfo.dli_fname[0]=='/' ) {
                rc = 0;
                _len = fname_len;
            } else {
                rc = _len;
                _len += fname_len;
            }

            if ( fname_len>0 ) {
                if ( _len>PATH_MAX ) {
                    DYNAMIC_LINK_WARNING( dl_buff_too_small );
                    return false;
                }
                memcpy( _path+rc, dlinfo.dli_fname, fname_len*sizeof(char) );
                _path[_len]=0;
            }

            return true;
        }
    static void init_ap_data() {
    #if _WIN32
        // Get handle of our DLL first.
        HMODULE handle;
        BOOL brc = GetModuleHandleEx(
            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            (PCWSTR)( & dynamic_link ), // any function inside the library can be used for the address
            & handle
            );
        if ( !brc ) { // Error occurred.
            int err = GetLastError();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err );
            return;
        }
        // Now get path to our DLL.
        DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) );
        if ( drc == 0 ) { // Error occurred.
            int err = GetLastError();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err );
            return;
        }
        if ( drc >= PATH_MAX ) { // Buffer too short.
            DYNAMIC_LINK_WARNING( dl_buff_too_small );
            return;
        }
        // Find the position of the last backslash.
        wchar_t *backslash = wcsrchr( ap_data._path, '\\' );

        if ( !backslash ) {    // Backslash not found.
            LIBRARY_ASSERT( backslash!=NULL, "Unbelievable.");
            return;
        }
        LIBRARY_ASSERT( backslash >= ap_data._path, "Unbelievable.");
        ap_data._len = (size_t)(backslash - ap_data._path) + 1;
        *(backslash+1) = 0;
    #else
        // Get the library path
        Dl_info dlinfo;
        int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address
        if ( !res ) {
            char const * err = dlerror();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );
            return;
        } else {
            LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." );
        }

        char const *slash = strrchr( dlinfo.dli_fname, '/' );
        size_t fname_len=0;
        if ( slash ) {
            LIBRARY_ASSERT( slash >= dlinfo.dli_fname, "Unbelievable.");
            fname_len = (size_t)(slash - dlinfo.dli_fname) + 1;
        }

        size_t rc;
        if ( dlinfo.dli_fname[0]=='/' ) {
            // The library path is absolute
            rc = 0;
            ap_data._len = 0;
        } else {
            // The library path is relative so get the current working directory
            if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) {
                DYNAMIC_LINK_WARNING( dl_buff_too_small );
                return;
            }
            ap_data._len = strlen( ap_data._path );
            ap_data._path[ap_data._len++]='/';
            rc = ap_data._len;
        }

        if ( fname_len>0 ) {
            if ( ap_data._len>PATH_MAX ) {
                DYNAMIC_LINK_WARNING( dl_buff_too_small );
                ap_data._len=0;
                return;
            }
            strncpy( ap_data._path+rc, dlinfo.dli_fname, fname_len );
            ap_data._len += fname_len;
            ap_data._path[ap_data._len]=0;
        }
    #endif /* _WIN32 */
    }
Beispiel #8
0
bool dynamic_link( const char* library, const dynamic_link_descriptor descriptors[], size_t n, size_t required, dynamic_link_handle *handle ) {
    // Get library handle in case it is already loaded into the current process
#if ! __TBB_DYNAMIC_LOAD_ENABLED
    dynamic_link_handle library_handle = NULL;
#ifndef __TBB_ASSERT_EX
#define __TBB_ASSERT_EX LIBRARY_ASSERT 
#endif 
    __TBB_ASSERT_EX( library, "library name must be provided");
#elif _WIN32||_WIN64
    dynamic_link_handle library_handle = GetModuleHandle( library );
#else
    dynamic_link_handle library_handle = dlopen( NULL, RTLD_LAZY );
#endif /* _WIN32||_WIN64 */

    // Get descriptors from the library
    if ( library_handle && dynamic_link( library_handle, descriptors, n, required ) ) {
#if !__TBB_DYNAMIC_LOAD_ENABLED
        return true;
#else
        // The library has been loaded by another module and contains requested symbols.
        // But after we obtained the library's handle it can be unloaded by another thread
        // invalidating our handle copy. Therefore we need to pin the library in memory.
#if _WIN32||_WIN64
        char library_full_name[ MAX_PATH+1 ];
        // Get library's name from earlier found handle
        if ( GetModuleFileName( library_handle, library_full_name, MAX_PATH+1 ) ) {
            // Pin the library
            library_handle = LoadLibrary( library_full_name );
            if ( library_handle == NULL ) {
                int err = GetLastError();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, library_full_name, err );
            } // if
        } // if
#else /* !WIN */
        Dl_info info;
        // Get library's name from earlier found symbol
        if ( dladdr( (void*)*descriptors[0].handler, &info ) ) {
            // Pin the library
            library_handle = dlopen( info.dli_fname, RTLD_LAZY );
            if ( library_handle == NULL ) {
                char const * err = dlerror();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, info.dli_fname, err );
            } // if
        } // if
#endif /* !WIN */
        else {
            // The library have been unloaded by another thread
            library_handle = 0;
        }
        if ( library_handle ) {
            // If original library was unloaded before we pinned it
            // and then another module loaded in its place, the earlier
            // found symbols would become invalid. So revalidate them.
            if ( !dynamic_link( library_handle, descriptors, n, required ) ) {
                // Wrong library.
                dynamic_unlink(library_handle);
                library_handle = 0;
            }
        }
        if ( !library_handle ) {
            // Failed to pin the library, so clear the descriptors too.
            for( size_t i=0; i<n; ++i )
                *descriptors[i].handler = 0;
        }
#endif /* __TBB_DYNAMIC_LOAD_ENABLED */
    } else {
        library_handle = 0;
    }

#if __TBB_DYNAMIC_LOAD_ENABLED
    if ( !library_handle ) {
#if _WIN32||_WIN64
#if _XBOX
        library_handle = LoadLibrary (library);
#else
        library_handle = NULL;
        // Construct absolute path to the library to avoid security issue.
        size_t const len = MAX_PATH + 1;
        char path[ len ];
        size_t rc = abs_path( library, path, len );
        if ( 0 < rc && rc < len ) {
            // Prevent Windows from displaying silly message boxes if it fails to load library
            // (e.g. because of MS runtime problems - one of those crazy manifest related ones)
            UINT prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS);
            library_handle = LoadLibrary (path);
            SetErrorMode (prev_mode);
            if ( library_handle == NULL ) {
                int err = GetLastError();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, path, err );
            } // if
        } // if
#endif /* !_XBOX */
#else /* !WIN */
        library_handle = NULL;
        // Construct absolute path to the library.
        size_t const len = PATH_MAX + 1;
        char path[ len ];
        size_t rc = abs_path( library, path, len );
        if ( 0 < rc && rc < len ) {
            library_handle = dlopen( path, RTLD_LAZY );
            if ( library_handle == NULL ) {
                char const * err = dlerror();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, library, err );
            } // if
        } // if
#endif /* !WIN */
        if( library_handle ) {
            if( !dynamic_link( library_handle, descriptors, n, required ) ) {
                // The loaded library does not contain all the expected entry points
                dynamic_unlink( library_handle );
                library_handle = NULL;
            }
        }
    }
#endif /* __TBB_DYNAMIC_LOAD_ENABLED */

    if ( library_handle ) {
        if ( handle )
            *handle = library_handle;
#if __TBB_BUILD
        else
            handles.add_handle( library_handle );
#endif /* __TBB_BUILD */
        return true;
    }
    return false;
}
Beispiel #9
0
    static dynamic_link_handle pin_symbols( dynamic_link_handle library_handle, dynamic_link_descriptor desc, const dynamic_link_descriptor* descriptors, size_t required ) {
        ::tbb::internal::suppress_unused_warning( desc, descriptors, required );
#if __TBB_DYNAMIC_LOAD_ENABLED
        // It is supposed that all symbols are from the only one library
        // The library has been loaded by another module and contains at least one requested symbol.
        // But after we obtained the symbol the library can be unloaded by another thread
        // invalidating our symbol. Therefore we need to pin the library in memory.
        const char * dli_fname;
    #ifdef __CYGWIN__
        MEMORY_BASIC_INFORMATION mbi;
        char path[MAX_PATH];
        VirtualQuery((void*)&dynamic_link, &mbi, sizeof(mbi));
        if(GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH)) {
        char posix_path[MAX_PATH];
        cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, path, posix_path, MAX_PATH);
        dli_fname = posix_path;

    #else
        Dl_info info;
        // Get library's name from earlier found symbol
        if ( dladdr( (void*)*desc.handler, &info ) ) {
            dli_fname = info.dli_fname;
    #endif
            // Pin the library
            library_handle = dlopen( dli_fname, RTLD_LAZY );
            if ( library_handle ) {
                // If original library was unloaded before we pinned it
                // and then another module loaded in its place, the earlier
                // found symbol would become invalid. So revalidate them.
                if ( !resolve_symbols( library_handle, descriptors, required ) ) {
                    // Wrong library.
                    dynamic_unlink(library_handle);
                    library_handle = 0;
                }
            } else {
                char const * err = dlerror();
                DYNAMIC_LINK_WARNING( dl_lib_not_found, dli_fname, err );
            }
        }
        else {
            // The library have been unloaded by another thread
            library_handle = 0;
        }
#endif /* __TBB_DYNAMIC_LOAD_ENABLED */
        return library_handle;
    }
#endif /* !_WIN32 */

    static dynamic_link_handle global_symbols_link( const char* library, const dynamic_link_descriptor descriptors[], size_t required ) {
        ::tbb::internal::suppress_unused_warning( library );
        dynamic_link_handle library_handle;
#if _WIN32
        if ( GetModuleHandleEx( 0, library, &library_handle ) ) {
            if ( resolve_symbols( library_handle, descriptors, required ) )
                return library_handle;
            else
                FreeLibrary( library_handle );
        }
#else /* _WIN32 */
    #if !__TBB_DYNAMIC_LOAD_ENABLED /* only __TBB_WEAK_SYMBOLS_PRESENT is defined */
        if ( !dlopen ) return 0;
    #endif /* !__TBB_DYNAMIC_LOAD_ENABLED */
        library_handle = dlopen( NULL, RTLD_LAZY );
    #if !__ANDROID__
        // On Android dlopen( NULL ) returns NULL if it is called during dynamic module initialization.
        LIBRARY_ASSERT( library_handle, "The handle for the main program is NULL" );
    #endif
        // Check existence of the first symbol only, then use it to find the library and load all necessary symbols.
        pointer_to_handler handler;
        dynamic_link_descriptor desc;
        desc.name = descriptors[0].name;
        desc.handler = &handler;
        if ( resolve_symbols( library_handle, &desc, 1 ) )
            return pin_symbols( library_handle, desc, descriptors, required );
#endif /* _WIN32 */
        return 0;
    }
Beispiel #10
0
    static void init_ap_data() {
    #if _WIN32
        // Get handle of our DLL first.
        HMODULE handle;
        BOOL brc = GetModuleHandleEx(
            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
            (LPCSTR)( & dynamic_link ), // any function inside the library can be used for the address
            & handle
            );
        if ( !brc ) { // Error occurred.
            int err = GetLastError();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err );
            return;
        }
        // Now get path to our DLL.
        DWORD drc = GetModuleFileName( handle, ap_data._path, static_cast< DWORD >( PATH_MAX ) );
        if ( drc == 0 ) { // Error occurred.
            int err = GetLastError();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err );
            return;
        }
        if ( drc >= PATH_MAX ) { // Buffer too short.
            DYNAMIC_LINK_WARNING( dl_buff_too_small );
            return;
        }
        // Find the position of the last backslash.
        char *backslash = strrchr( ap_data._path, '\\' );

        if ( !backslash ) {    // Backslash not found.
            LIBRARY_ASSERT( backslash!=NULL, "Unbelievable.");
            return;
        }
        LIBRARY_ASSERT( backslash >= ap_data._path, "Unbelievable.");
        ap_data._len = (size_t)(backslash - ap_data._path) + 1;
        *(backslash+1) = 0;
    #else
        // Get the library path
        /*Dl_info dlinfo;
        int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address
        if ( !res ) {
            char const * err = dlerror();
            DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );
            return;
        } else {
            LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." );
        }*/
		const char *dli_fname;

		#ifdef __CYGWIN__
			MEMORY_BASIC_INFORMATION mbi;
			char path[MAX_PATH];
			VirtualQuery((void*)&dynamic_link, &mbi,
                sizeof(mbi));
			GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);

			char posix_path[MAX_PATH];
			cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, path, posix_path, MAX_PATH);
			dli_fname = posix_path;

		#else
			Dl_info dlinfo;
			int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address
			if ( !res ) {
				char const * err = dlerror();
				DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );
				return;
			} else {
				LIBRARY_ASSERT( dlinfo.dli_fname!=NULL, "Unbelievable." );
			}
			dli_fname = dlinfo.dli_fname;
		#endif

        char const *slash = strrchr( dli_fname, '/' );
        size_t fname_len=0;
        if ( slash ) {
            LIBRARY_ASSERT( slash >= dli_fname, "Unbelievable.");
            fname_len = (size_t)(slash - dli_fname) + 1;
        }

        size_t rc;
        if ( dli_fname[0]=='/' ) {
            // The library path is absolute
            rc = 0;
            ap_data._len = 0;
        } else {
            // The library path is relative so get the current working directory
            if ( !getcwd( ap_data._path, sizeof(ap_data._path)/sizeof(ap_data._path[0]) ) ) {
                DYNAMIC_LINK_WARNING( dl_buff_too_small );
                return;
            }
            ap_data._len = strlen( ap_data._path );
            ap_data._path[ap_data._len++]='/';
            rc = ap_data._len;
        }

        if ( fname_len>0 ) {
            if ( ap_data._len>PATH_MAX ) {
                DYNAMIC_LINK_WARNING( dl_buff_too_small );
                ap_data._len=0;
                return;
            }
            strncpy( ap_data._path+rc, dli_fname, fname_len );
            ap_data._len += fname_len;
            ap_data._path[ap_data._len]=0;
        }
    #endif /* _WIN32 */
    }