Peter Dennis Bartok wrote:
This patch allows to use Wine as a shared library. It will allow the Mono project to use Wine as the backend for it's System.Windows.Forms implementation.
It looks as though Alexandre has done a good job with kernel32 and ntdll since the last time using Wine with Mono was mentioned on this list.
ChangeLog: * Alters initialization code to return control to caller instead of executing application if __wine_shared_lib flag is set.
Perhaps this could be changed to a static variable in process.c
* Adds winelib executable (wine-sharedlib) that a consumer can use
to initialize Wine as a shared library, to load Wine DLLs and to import functions from DLLs.
wine-sharedlib doesn't look very clean at the moment. Tabs are inconsistent and you forgot to change MonoWineInit to SharedWineInit in one of the comments. Why do you link to kernel32 and user32 and then use dlsym to get the function address? What is VideoDLL supposed to be for? Why does the comment for WinMain say it is never called and then have a load of junk in it?
If you can resolve these issues then we can have a single Wine for Win32 and S.W.F!
Rob
Hello!
If you can resolve these issues then we can have a single Wine for Win32 and S.W.F!
We are running some SWF applications now with Mono and this patch; And we are fairly happy, since its a small patch to maintain this time. Of course, it would be best to make it part of Wine, so the user does not need two separate Wine installations.
Miguel.
Perhaps this could be changed to a static variable in process.c
Wouldn't that make it rather hard to be set from outside process.c? I need to set it from wine-sharedlib.exe.so
If you can resolve these issues then we can have a single Wine for Win32 and S.W.F!
Well, you basically saw the hole history of the patch, it started out as a separate piece of code outside of the wine build system, and in the rush to get it out I didn't have a chance to look for the forrest, with all those trees around :-)
The attached is cleaned up. Thanks for pointing it out.
Cheers, Peter
diff -ruN wine/configure.ac wine-patched/configure.ac --- wine/configure.ac 2004-03-03 13:30:46.000000000 -0700 +++ wine-patched/configure.ac 2004-03-04 17:44:34.000000000 -0700 @@ -1670,6 +1670,7 @@ programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile +programs/wine-sharedlib/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile diff -ruN wine/dlls/kernel/process.c wine-patched/dlls/kernel/process.c --- wine/dlls/kernel/process.c 2004-02-20 13:19:24.000000000 -0700 +++ wine-patched/dlls/kernel/process.c 2004-03-04 17:44:34.000000000 -0700 @@ -756,8 +756,12 @@
SetLastError( 0 ); /* clear error code */ if (peb->BeingDebugged) DbgBreakPoint(); - ExitProcess( entry( peb ) ); + if (__wine_shared_lib==0) { + // This starts the main app and then exits wine + ExitProcess( entry( peb ) ); + } } + __EXCEPT(UnhandledExceptionFilter) { TerminateThread( GetCurrentThread(), GetExceptionCode() ); @@ -895,13 +899,20 @@ set_library_wargv( __wine_main_argv ); if (!build_command_line( __wine_main_wargv )) goto error;
- stack_size = RtlImageNtHeader(peb->ImageBaseAddress)->OptionalHeader.SizeOfStackReserve; + if (__wine_shared_lib==1) { + /* We don't want a new stack if we're going shared. Screws up our return path */ + start_process(NULL); + } else { + stack_size = RtlImageNtHeader(peb->ImageBaseAddress)->OptionalHeader.SizeOfStackReserve;
- /* allocate main thread stack */ - if (!THREAD_InitStack( NtCurrentTeb(), stack_size )) goto error; + /* allocate main thread stack */ + if (!THREAD_InitStack( NtCurrentTeb(), stack_size )) goto error; + + /* switch to the new stack */ + wine_switch_to_stack( start_process, NULL, NtCurrentTeb()->Tib.StackBase ); + } + return;
- /* switch to the new stack */ - wine_switch_to_stack( start_process, NULL, NtCurrentTeb()->Tib.StackBase );
error: ExitProcess( GetLastError() ); diff -ruN wine/dlls/ntdll/loader.c wine-patched/dlls/ntdll/loader.c --- wine/dlls/ntdll/loader.c 2004-02-23 18:25:03.000000000 -0700 +++ wine-patched/dlls/ntdll/loader.c 2004-03-04 17:44:34.000000000 -0700 @@ -1951,7 +1951,9 @@ WINE_MODREF *wm; NTSTATUS status; ANSI_STRING func_name; - void (* DECLSPEC_NORETURN init_func)(); + /* We might return for shared-lib startup */ + /* void (* DECLSPEC_NORETURN init_func)(); */ + void (* init_func)(); extern void __wine_dbg_ntdll_init(void);
thread_init(); diff -ruN wine/include/wine/library.h wine-patched/include/wine/library.h --- wine/include/wine/library.h 2004-01-02 14:08:05.000000000 -0700 +++ wine-patched/include/wine/library.h 2004-03-04 17:44:34.000000000 -0700 @@ -49,6 +49,7 @@ extern void wine_dll_unload( void *handle ); extern int wine_dll_get_owner( const char *name, char *buffer, int size, int *file_exists );
+extern int __wine_shared_lib; extern int __wine_main_argc; extern char **__wine_main_argv; extern WCHAR **__wine_main_wargv; diff -ruN wine/libs/wine/loader.c wine-patched/libs/wine/loader.c --- wine/libs/wine/loader.c 2004-01-02 14:08:05.000000000 -0700 +++ wine-patched/libs/wine/loader.c 2004-03-04 17:44:34.000000000 -0700 @@ -46,6 +46,7 @@ char **__wine_main_argv = NULL; WCHAR **__wine_main_wargv = NULL; char **__wine_main_environ = NULL; +int __wine_shared_lib = 0;
struct dll_path_context { diff -ruN wine/libs/wine/wine.def wine-patched/libs/wine/wine.def --- wine/libs/wine/wine.def 2004-02-04 19:01:35.000000000 -0700 +++ wine-patched/libs/wine/wine.def 2004-03-04 17:44:34.000000000 -0700 @@ -9,6 +9,7 @@ __wine_dbgstr_an __wine_dbgstr_wn __wine_dll_register + __wine_shared_lib __wine_main_argc __wine_main_argv __wine_main_environ diff -ruN wine/libs/wine/wine.map wine-patched/libs/wine/wine.map --- wine/libs/wine/wine.map 2004-02-12 15:54:00.000000000 -0700 +++ wine-patched/libs/wine/wine.map 2004-03-04 17:44:34.000000000 -0700 @@ -9,6 +9,7 @@ __wine_dbgstr_an; __wine_dbgstr_wn; __wine_dll_register; + __wine_shared_lib; __wine_main_argc; __wine_main_argv; __wine_main_environ; diff -ruN wine/programs/Makefile.in wine-patched/programs/Makefile.in --- wine/programs/Makefile.in 2004-01-06 13:49:59.000000000 -0700 +++ wine-patched/programs/Makefile.in 2004-03-04 17:44:34.000000000 -0700 @@ -11,6 +11,7 @@ cmdlgtst \ control \ expand \ + wine-sharedlib \ notepad \ progman \ regedit \ @@ -41,6 +42,7 @@ clock \ control \ expand \ + wine-sharedlib \ notepad \ progman \ regedit \ @@ -179,6 +181,9 @@ icinfo.exe$(DLLEXT): avitools/icinfo.exe$(DLLEXT) $(RM) $@ && $(LN_S) avitools/icinfo.exe$(DLLEXT) $@
+wine-sharedlib.exe$(DLLEXT): wine-sharedlib/wine-sharedlib.exe$(DLLEXT) + $(RM) $@ && $(LN_S) wine-sharedlib/wine-sharedlib.exe$(DLLEXT) $@ + notepad.exe$(DLLEXT): notepad/notepad.exe$(DLLEXT) $(RM) $@ && $(LN_S) notepad/notepad.exe$(DLLEXT) $@
@@ -255,6 +260,7 @@ control/control.exe$(DLLEXT): control expand/expand.exe$(DLLEXT): expand avitools/icinfo.exe$(DLLEXT): avitools +wine-sharedlib/wine-sharedlib.exe$(DLLEXT): wine-sharedlib notepad/notepad.exe$(DLLEXT): notepad progman/progman.exe$(DLLEXT): progman regedit/regedit.exe$(DLLEXT): regedit diff -ruN wine/programs/wine-sharedlib/Makefile.in wine-patched/programs/wine-sharedlib/Makefile.in --- wine/programs/wine-sharedlib/Makefile.in 1969-12-31 17:00:00.000000000 -0700 +++ wine-patched/programs/wine-sharedlib/Makefile.in 2004-03-04 17:44:34.000000000 -0700 @@ -0,0 +1,27 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = wine-sharedlib.exe +APPMODE = -mwindows +IMPORTS = kernel32 +DELAYIMPORTS = user32 +EXTRAINCL = +EXTRADEFS = -DDLLPATH="${exec_prefix}/lib/wine" -DLIBPATH="${exec_prefix}/lib" +EXTRALIBS = -ldl -lpthread +C_SRCS = \ + wine-sharedlib.c \ + ../../loader/pthread.c + +RC_SRCS = +RC_BINSRC = +RC_BINARIES = + +PLTESTS = + +EXTRASUBDIRS = + +@MAKE_PROG_RULES@ + +dlldir = ${exec_prefix}/lib +### Dependencies: diff -ruN wine/programs/wine-sharedlib/wine-sharedlib.c wine-patched/programs/wine-sharedlib/wine-sharedlib.c --- wine/programs/wine-sharedlib/wine-sharedlib.c 1969-12-31 17:00:00.000000000 -0700 +++ wine-patched/programs/wine-sharedlib/wine-sharedlib.c 2004-03-04 17:47:06.000000000 -0700 @@ -0,0 +1,81 @@ +/* + * wine-sharedlib code + * + * Copyright 2004 Novell, Inc. (http://www.novell.com/) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <wine/library.h> +#include <stdio.h> +#include <windows.h> +#include <winsock.h> +#include <dlfcn.h> + +/* + Dummy WinMain. If __wine_shared_lib is set this function is never actually called +*/ + +int WINAPI +WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + return(0); +} + +HMODULE WINAPI (*LoadLibraryF)(LPCSTR libname); +FARPROC WINAPI (*GetProcAddressF)(HMODULE hModule, LPCSTR function); + +/* + WineLoadLibrary is used by System.Windows.Forms to import the Wine dlls +*/ +void * +WineLoadLibrary(unsigned char *dll) +{ + return(LoadLibraryF(dll)); +} + +void * +WineGetProcAddress(void *handle, unsigned char *function) +{ + return(GetProcAddressF(handle, function)); +} + +/* + SharedWineInit() Must be called to initialize Wine. Sets the __wine_shared_lib flag + to make wine return after initialization instead of running WinMain +*/ + +int +SharedWineInit(void) +{ + unsigned char Error[1024]=""; + char *WineArguments[] = {"sharedapp", LIBPATH "/wine-sharedlib.exe.so", NULL}; + + __wine_shared_lib=1; + + wine_init(2, WineArguments, Error, sizeof(Error)); + if (Error[0]!='\0') { + printf("Wine initialization error:%s\n", Error); + exit(-1); + } + + putenv ("_WINE_SHAREDLIB_PATH=" DLLPATH); + + LoadLibraryF=LoadLibraryA; + GetProcAddressF=GetProcAddress; + + return(0); +} diff -ruN wine/tools/winebuild/spec32.c wine-patched/tools/winebuild/spec32.c --- wine/tools/winebuild/spec32.c 2004-02-16 13:24:32.000000000 -0700 +++ wine-patched/tools/winebuild/spec32.c 2004-03-04 17:44:34.000000000 -0700 @@ -568,6 +568,7 @@ fprintf( outfile, "extern int __wine_main_argc;\n" ); fprintf( outfile, "extern char **__wine_main_argv;\n" ); fprintf( outfile, "extern char **__wine_main_environ;\n" ); + fprintf( outfile, "extern int __wine_shared_lib;\n" ); fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" ); fprintf( outfile, "extern void _init(int, char**, char**);\n" ); fprintf( outfile, "extern void _fini();\n" );
Peter Dennis Bartok peter@novonyx.com writes:
Perhaps this could be changed to a static variable in process.c
Wouldn't that make it rather hard to be set from outside process.c? I need to set it from wine-sharedlib.exe.so
It seems to me that you could simply do a longjmp() out of your WinMain, and then you wouldn't need to modify Wine at all. It would require patching up the TEB a bit (for instance to remove the exception handler chain), but nothing really complicated.
Hello,
Perhaps this could be changed to a static variable in process.c
Wouldn't that make it rather hard to be set from outside process.c? I need to set it from wine-sharedlib.exe.so
It seems to me that you could simply do a longjmp() out of your WinMain, and then you wouldn't need to modify Wine at all. It would require patching up the TEB a bit (for instance to remove the exception handler chain), but nothing really complicated.
Well, the issue is that our WinMain is never called, and we would rather not depend on this in our patch, but instead get the small global that says `Hey Wine, just return'.
Miguel
Miguel de Icaza miguel@ximian.com writes:
Well, the issue is that our WinMain is never called, and we would rather not depend on this in our patch, but instead get the small global that says `Hey Wine, just return'.
The global variable thing is ugly; we could export a different entry point instead, but I'm not sure it's really necessary. Why doesn't your WinMain get called?
Hey,
Well, the issue is that our WinMain is never called, and we would rather not depend on this in our patch, but instead get the small global that says `Hey Wine, just return'.
The global variable thing is ugly; we could export a different entry point instead, but I'm not sure it's really necessary. Why doesn't your WinMain get called?
If you move most of the initialization code from main() to mymain() and just let main () call mymain and then jump into WinMain, basically doing the same thing the flag does, then we can just provide our own, and call the mymain() method.
Alexandre Julliard wrote:
Miguel de Icaza miguel@ximian.com writes:
Well, the issue is that our WinMain is never called, and we would rather not depend on this in our patch, but instead get the small global that says `Hey Wine, just return'.
The global variable thing is ugly; we could export a different entry point instead, but I'm not sure it's really necessary. Why doesn't your WinMain get called?
The cleanest solution would be to let WinMain get called, but if that isn't possible then we could always add an extra parameter to wine_init and pass that down to __wine_kernel_init.
Rob