From: Jacek Caban Subject: [PATCH 4/5] msvcrt: Provide EXE entry points in importlib. Message-Id: Date: Tue, 21 Jan 2020 19:58:50 +0100 Signed-off-by: Jacek Caban --- Those are very minimalistic, but Wine is very minimalistic about used features, so it should be enough for our needs. We can extend it to support more features like DLL-aware atexit() or global constructors if needed. After experimenting, I think that crt importlib seems the best place for this and it's what MSVC does. mingw instead has separated object files with entry point implementation that are linked into modules. Both this solution and having them in winecrt0 (which would be another possibility) introduces problematic dependency on msvcrt importlib. This can be done, but leads to some unpleasant problems with supporting multiple runtimes. Having it in crt importlibs will allow easy customisations. dlls/msvcrt/Makefile.in | 5 ++++ dlls/msvcrt/crt_gccmain.c | 31 ++++++++++++++++++++ dlls/msvcrt/crt_main.c | 59 +++++++++++++++++++++++++++++++++++++ dlls/msvcrt/crt_winmain.c | 58 ++++++++++++++++++++++++++++++++++++ dlls/msvcrt/crt_wmain.c | 59 +++++++++++++++++++++++++++++++++++++ dlls/msvcrt/crt_wwinmain.c | 60 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 272 insertions(+) create mode 100644 dlls/msvcrt/crt_gccmain.c create mode 100644 dlls/msvcrt/crt_main.c create mode 100644 dlls/msvcrt/crt_winmain.c create mode 100644 dlls/msvcrt/crt_wmain.c create mode 100644 dlls/msvcrt/crt_wwinmain.c diff --git a/dlls/msvcrt/Makefile.in b/dlls/msvcrt/Makefile.in index d0237fd891..0b8fdf19c7 100644 --- a/dlls/msvcrt/Makefile.in +++ b/dlls/msvcrt/Makefile.in @@ -6,6 +6,11 @@ DELAYIMPORTS = advapi32 user32 C_SRCS = \ console.c \ cpp.c \ + crt_gccmain.c \ + crt_main.c \ + crt_winmain.c \ + crt_wmain.c \ + crt_wwinmain.c \ ctype.c \ data.c \ dir.c \ diff --git a/dlls/msvcrt/crt_gccmain.c b/dlls/msvcrt/crt_gccmain.c new file mode 100644 index 0000000000..ed25f385d1 --- /dev/null +++ b/dlls/msvcrt/crt_gccmain.c @@ -0,0 +1,31 @@ +/* + * __main entry point + * + * Copyright 2019 Jacek Caban for CodeWeavers + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __MINGW32__ + +/* mingw compilers emit call to __main() when main() function is defined. + * it's used by crt to call global constructors and register global destructors. */ +void __cdecl __main(void) {} + +#endif diff --git a/dlls/msvcrt/crt_main.c b/dlls/msvcrt/crt_main.c new file mode 100644 index 0000000000..7502f30075 --- /dev/null +++ b/dlls/msvcrt/crt_main.c @@ -0,0 +1,59 @@ +/* + * mainCRTStartup default entry point + * + * Copyright 2019 Jacek Caban for CodeWeavers + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __MINGW32__ + +#include "msvcrt.h" + +#include "windef.h" +#include "winbase.h" + +/* FIXME: Use msvcrt headers once we move to PE file */ +void __cdecl exit(int); +void __cdecl __getmainargs(int *, char ***, char ***, int, int *); +void __cdecl __set_app_type(int); + +int __cdecl main(int argc, char **argv, char **env); + +static const IMAGE_NT_HEADERS *get_nt_header( void ) +{ + extern IMAGE_DOS_HEADER __ImageBase; + return (const IMAGE_NT_HEADERS *)((char *)&__ImageBase + __ImageBase.e_lfanew); +} + +int __cdecl mainCRTStartup(void) +{ + int argc, new_mode = 0, ret; + char **argv, **env; + + __getmainargs(&argc, &argv, &env, 0, &new_mode); + __set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? 2 : 1); + + ret = main(argc, argv, env); + + exit(ret); + return ret; +} + +#endif diff --git a/dlls/msvcrt/crt_winmain.c b/dlls/msvcrt/crt_winmain.c new file mode 100644 index 0000000000..27e0283cbf --- /dev/null +++ b/dlls/msvcrt/crt_winmain.c @@ -0,0 +1,58 @@ +/* + * main default entry point for exe files + * + * Copyright 2005 Alexandre Julliard + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __MINGW32__ + +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" + +int __cdecl main( int argc, char *argv[] ) +{ + STARTUPINFOA info; + char *cmdline = GetCommandLineA(); + int bcount = 0; + BOOL in_quotes = FALSE; + + while (*cmdline) + { + if ((*cmdline == '\t' || *cmdline == ' ') && !in_quotes) break; + else if (*cmdline == '\\') bcount++; + else if (*cmdline == '\"') + { + if (!(bcount & 1)) in_quotes = !in_quotes; + bcount = 0; + } + else bcount = 0; + cmdline++; + } + while (*cmdline == '\t' || *cmdline == ' ') cmdline++; + + GetStartupInfoA( &info ); + if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL; + return WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ); +} + +#endif diff --git a/dlls/msvcrt/crt_wmain.c b/dlls/msvcrt/crt_wmain.c new file mode 100644 index 0000000000..0588d5bdce --- /dev/null +++ b/dlls/msvcrt/crt_wmain.c @@ -0,0 +1,59 @@ +/* + * wmainCRTStartup default entry point + * + * Copyright 2019 Jacek Caban for CodeWeavers + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __MINGW32__ + +#include "msvcrt.h" + +#include "windef.h" +#include "winbase.h" + +/* FIXME: Use msvcrt headers once we move to PE file */ +void __cdecl exit(int); +void __cdecl __wgetmainargs(int *, WCHAR ***, WCHAR ***, int, int *); +void __cdecl __set_app_type(int); + +int __cdecl wmain(int argc, WCHAR **argv, WCHAR **env); + +static const IMAGE_NT_HEADERS *get_nt_header( void ) +{ + extern IMAGE_DOS_HEADER __ImageBase; + return (const IMAGE_NT_HEADERS *)((char *)&__ImageBase + __ImageBase.e_lfanew); +} + +int __cdecl wmainCRTStartup(void) +{ + int argc, new_mode = 0, ret; + WCHAR **argv, **env; + + __wgetmainargs(&argc, &argv, &env, 0, &new_mode); + __set_app_type(get_nt_header()->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? 2 : 1); + + ret = wmain(argc, argv, env); + + exit(ret); + return ret; +} + +#endif diff --git a/dlls/msvcrt/crt_wwinmain.c b/dlls/msvcrt/crt_wwinmain.c new file mode 100644 index 0000000000..2c53b744b5 --- /dev/null +++ b/dlls/msvcrt/crt_wwinmain.c @@ -0,0 +1,60 @@ +/* + * main default entry point for Unicode exe files + * + * Copyright 2005 Alexandre Julliard + * + * 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 St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep implib +#endif + +#ifdef __MINGW32__ + +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" + +int WINAPI wWinMain(HINSTANCE,HINSTANCE,LPWSTR,int); + +int __cdecl wmain( int argc, WCHAR *argv[] ) +{ + STARTUPINFOW info; + WCHAR *cmdline = GetCommandLineW(); + int bcount = 0; + BOOL in_quotes = FALSE; + + while (*cmdline) + { + if ((*cmdline == '\t' || *cmdline == ' ') && !in_quotes) break; + else if (*cmdline == '\\') bcount++; + else if (*cmdline == '\"') + { + if (!(bcount & 1)) in_quotes = !in_quotes; + bcount = 0; + } + else bcount = 0; + cmdline++; + } + while (*cmdline == '\t' || *cmdline == ' ') cmdline++; + + GetStartupInfoW( &info ); + if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL; + return wWinMain( GetModuleHandleW(0), 0, cmdline, info.wShowWindow ); +} + +#endif