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