On 14/02/2011 05:03, Y.Hosoi wrote:
Thank you.

However, it did not move well.

If test.dll is done in LoadLibrary, Access Violation is generated.

Are you still amused something?


[main source code]

#include "stdafx.h"
#include "windows.h"

#ifdef __cplusplus
extern "C"{
#endif

typedef int (*TFUNC)(void);

typedef void (*Tinit)(void);

int _tmain(int argc, _TCHAR* argv[])
{
        int i;

        HINSTANCE       h;
        HINSTANCE       hInstDLL;

        Tinit           init;
        TFUNC           DllFunction;
        DWORD           ErrNo;

        h = LoadLibrary( TEXT( "cygwin1.dll" ) );
        init = (Tinit)GetProcAddress( h, "cygwin_dll_init" );

        init();

        hInstDLL = LoadLibrary( TEXT( "test.dll" ) );         /* !Access 
Violation! */
        if( hInstDLL == NULL )
        {
                ErrNo = GetLastError();
                return 0;
        }
        DllFunction = (TFUNC)GetProcAddress( hInstDLL, "hello" );
        i = DllFunction();

        FreeLibrary( hInstDLL );
        FreeLibrary( h );

        return 0;
}

#ifdef __cplusplus
}
#endif


Try the following code. This was pulled from the Cygwin sources. There is a test case that does exactly this, loads cygwin1.dll dynamically. You need to make sure you allocate stack. This was compiled with MINGW. This is part of a larger program, so it might need some adjustments. The function cygloadCRTStartup() is pretty much from the sources.

Note that the entry point needs to be set with the linker option:
-Wl,-entry -Wl,_cygloadCRTStartup@0

#include <windows.h>
#include <stdio.h>
#include "getopt.h"

#define CYGHELP_SUCCESS           EXIT_SUCCESS
#define CYGHELP_ARG_ERROR         1
#define CYGHELP_DLL_NOT_FOUND     100
#define CYGHELP_DLL_NOT_SUPPORTED 101
#define CYGHELP_INTERNAL_ERROR    255

typedef void    (__cdecl cdi_t)(void);
typedef void    (__cdecl cctfwp_t)(const char *path, char *win32path);
typedef void    (__cdecl cctfpp_t)(const char *path, char *posixpath);

int mainCRTStartup ();

int __stdcall cygloadCRTStartup ()
{
        char   padding[32768];
        size_t delta;
        int    result;
        char   block[32768];
        char  *stackbase;
        char  *_stackbase;
        char  *_end;

        _end = padding + sizeof(padding);
#ifdef __GNUC__
        __asm__ (
                "movl %%fs:4, %0"
                :"=r"(stackbase)
    );
#else
        __asm {
                mov eax, fs:[4];
                mov stackbase, eax;
        }
#endif
        _stackbase = stackbase;

        // We've gotten as close as we can to the top of the stack.  Even
        // subverting the entry point, though, still doesn't get us there-- I'm
        // getting 64 bytes in use before the entry point.  So we back up the 
data
        // there and restore it when the destructor is called:
        if ((_stackbase - _end) != 0) {
                delta = (_stackbase - _end);
                memcpy (block, _end, delta);
    }
        result = mainCRTStartup ();
        memcpy(_end, block, delta);
        return result;
}

int main(int argc, char **argv)
{
        HMODULE     cygwinDll;
        DWORD       winres;
        cdi_t      *cygwin_dll_init;
        cctfwp_t   *cygwin_conv_to_full_win32_path;
        cctfpp_t   *cygwin_conv_to_full_posix_path;
        const char *dll = "cygwin1.dll";
        const char *ppath = NULL;
        const char *wpath = NULL;
        
        char        module[MAX_PATH];
        char        buff[MAX_PATH];
        int         i;
        int         c;
        
        // Get any options the user provides
        opterr = 0;
        while ((c = getopt(argc, argv, "c:p:w:")) != -1) {
                switch (c) {
                case 'c':
                        dll = optarg;
                        break;
                case 'p':
                        ppath = optarg;
                        break;
                case 'w':
                        wpath = optarg;
                        break;
                case '?':
                        if (optopt == 'c') {
fprintf(stderr, "Option -%c requires the full name for the Cygwin DLL\n", optopt);
                        } else if (optopt == 'p') {
fprintf(stderr, "Option -%c requires the Posix path to convert\n", optopt);
                        } else if (optopt == 'w') {
fprintf(stderr, "Option -%c requires the Windows path to convert\n", optopt);
                        } else {
                                fprintf(stderr, "Unknown option -%c\n", optopt);
                        }
                        return CYGHELP_ARG_ERROR;
                default:
                        fprintf(stderr, "Argument %c given, unknown handler\n", 
c);
                        return CYGHELP_INTERNAL_ERROR;
                }
        }

        // Load the library and determine the full path to the library (as
        // determined by windows)
        cygwinDll = LoadLibrary(dll);
        if (!cygwinDll) {
                fprintf(stderr, "Couldn't find %s\n", dll);
                return CYGHELP_DLL_NOT_FOUND;
        }
        winres = GetModuleFileName(cygwinDll, module, MAX_PATH);
        if (!winres) {
                winres = GetLastError();
                fprintf(stderr, "GetModuleFilename returned error %d\n", 
winres);
                return CYGHELP_DLL_NOT_SUPPORTED;
        }
        
        cygwin_dll_init = (cdi_t *)
                GetProcAddress(cygwinDll, "cygwin_dll_init");
        if (!cygwin_dll_init) {
                fprintf(stderr, "Couldn't find cygwin_dll_init\n");
                return CYGHELP_DLL_NOT_SUPPORTED;
        }
        
        cygwin_conv_to_full_win32_path = (cctfwp_t *)
                GetProcAddress(cygwinDll, "cygwin_conv_to_full_win32_path");
        if (!cygwin_conv_to_full_win32_path) {
                fprintf(stderr, "Couldn't find 
cygwin_conv_to_full_win32_path\n");
                return CYGHELP_DLL_NOT_SUPPORTED;
        }
        
        cygwin_conv_to_full_posix_path = (cctfpp_t *)
                GetProcAddress(cygwinDll, "cygwin_conv_to_full_posix_path");
        if (!cygwin_conv_to_full_posix_path) {
                fprintf(stderr, "Couldn't find 
cygwin_conv_to_full_posix_path\n");
                return CYGHELP_DLL_NOT_SUPPORTED;
        }
        
        // Initialise the library. The first line is always the name of the
        // module. Then we print the result that the user expects. This allows
        // programs to know what library is in use and to easily parse the 
output
        // for their needs
        cygwin_dll_init();
        printf("%s\n", module);
        if (ppath) {
                cygwin_conv_to_full_win32_path(ppath, buff);
                printf("%s\n", buff);
        }
        if (wpath) {
                cygwin_conv_to_full_posix_path(wpath, buff);
                printf("%s\n", buff);
        }
        
        // We've finished now, so let's exit
        FreeLibrary(cygwinDll);
        return CYGHELP_SUCCESS;
}


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to