Revision: 9136 https://osdn.net/projects/ttssh2/scm/svn/commits/9136 Author: zmatsuo Date: 2021-01-27 23:40:25 +0900 (Wed, 27 Jan 2021) Log Message: ----------- MinGW による Windows 95 サポート Modified Paths: -------------- trunk/CMakeLists.txt trunk/TTProxy/CMakeLists.txt trunk/TTXKanjiMenu/CMakeLists.txt trunk/TTXSamples/TTXAdditionalTitle/CMakeLists.txt trunk/TTXSamples/TTXAlwaysOnTop/CMakeLists.txt trunk/TTXSamples/TTXCallSysMenu/CMakeLists.txt trunk/TTXSamples/TTXCheckUpdate/CMakeLists.txt trunk/TTXSamples/TTXCommandLineOpt/CMakeLists.txt trunk/TTXSamples/TTXCopyIniFile/CMakeLists.txt trunk/TTXSamples/TTXFixedWinSize/CMakeLists.txt trunk/TTXSamples/TTXKcodeChange/CMakeLists.txt trunk/TTXSamples/TTXOutputBuffering/CMakeLists.txt trunk/TTXSamples/TTXRecurringCommand/CMakeLists.txt trunk/TTXSamples/TTXResizeMenu/CMakeLists.txt trunk/TTXSamples/TTXResizeWin/CMakeLists.txt trunk/TTXSamples/TTXShowCommandLine/CMakeLists.txt trunk/TTXSamples/TTXViewMode/CMakeLists.txt trunk/TTXSamples/TTXttyrec/CMakeLists.txt trunk/TTXSamples/ttxtest/CMakeLists.txt trunk/installer/cygtool/CMakeLists.txt trunk/teraterm/CMakeLists.txt trunk/teraterm/teraterm/CMakeLists.txt trunk/teraterm/ttpcmn/CMakeLists.txt trunk/teraterm/ttpset/CMakeLists.txt trunk/teraterm/ttptek/CMakeLists.txt trunk/tools/ttbroadcast/CMakeLists.txt trunk/ttssh2/ttxssh/CMakeLists.txt Added Paths: ----------- trunk/teraterm/libmingw/ trunk/teraterm/libmingw/CMakeLists.txt trunk/teraterm/libmingw/README.md trunk/teraterm/libmingw/README_w95.md trunk/teraterm/libmingw/msvcrt_wrapper.c trunk/teraterm/libmingw/test/ trunk/teraterm/libmingw/test/CMakeLists.txt trunk/teraterm/libmingw/test/is.c trunk/teraterm/libmingw/test/main.c trunk/teraterm/libmingw/test/outputdebugprintf.cpp trunk/teraterm/libmingw/tlssup.c -------------- next part -------------- Modified: trunk/CMakeLists.txt =================================================================== --- trunk/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -59,6 +59,8 @@ elseif(MINGW) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WIN32_WINNT=${_WIN32_WINNT}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WIN32_WINNT=${_WIN32_WINNT}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__USE_MINGW_ANSI_STDIO=0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__USE_MINGW_ANSI_STDIO=0") set(CMAKE_C_CXX_WARNING_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-sign-compare") set(CMAKE_C_WARNING_FLAGS "${CMAKE_C_CXX_WARNING_FLAGS} -Wno-pointer-sign") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_WARNING_FLAGS} -static -ffunction-sections -fdata-sections ${C_ONLY_FLAGS}") Modified: trunk/TTProxy/CMakeLists.txt =================================================================== --- trunk/TTProxy/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTProxy/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -28,6 +28,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_sources( Modified: trunk/TTXKanjiMenu/CMakeLists.txt =================================================================== --- trunk/TTXKanjiMenu/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXKanjiMenu/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXAdditionalTitle/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXAdditionalTitle/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXAdditionalTitle/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXAlwaysOnTop/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXAlwaysOnTop/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXAlwaysOnTop/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXCallSysMenu/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXCallSysMenu/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXCallSysMenu/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXCheckUpdate/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXCheckUpdate/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXCheckUpdate/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -27,7 +27,21 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() +endif(SUPPORT_OLD_WINDOWS) source_group( "common" Modified: trunk/TTXSamples/TTXCommandLineOpt/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXCommandLineOpt/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXCommandLineOpt/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXCopyIniFile/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXCopyIniFile/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXCopyIniFile/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXFixedWinSize/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXFixedWinSize/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXFixedWinSize/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXKcodeChange/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXKcodeChange/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXKcodeChange/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXOutputBuffering/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXOutputBuffering/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXOutputBuffering/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,7 +17,14 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() +endif(SUPPORT_OLD_WINDOWS) set_target_properties( ${PACKAGE_NAME} Modified: trunk/TTXSamples/TTXRecurringCommand/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXRecurringCommand/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXRecurringCommand/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -19,7 +19,21 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() -endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() +endif(SUPPORT_OLD_WINDOWS) source_group( "common" Modified: trunk/TTXSamples/TTXResizeMenu/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXResizeMenu/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXResizeMenu/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,6 +17,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) if (MSVC) Modified: trunk/TTXSamples/TTXResizeWin/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXResizeWin/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXResizeWin/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,6 +17,13 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() endif(SUPPORT_OLD_WINDOWS) set_target_properties( Modified: trunk/TTXSamples/TTXShowCommandLine/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXShowCommandLine/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXShowCommandLine/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,6 +17,13 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() endif(SUPPORT_OLD_WINDOWS) set_target_properties( Modified: trunk/TTXSamples/TTXViewMode/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXViewMode/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXViewMode/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -21,6 +21,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) source_group( Modified: trunk/TTXSamples/TTXttyrec/CMakeLists.txt =================================================================== --- trunk/TTXSamples/TTXttyrec/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/TTXttyrec/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,6 +17,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + TTXttyplay + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + TTXttyplay + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_include_directories( @@ -51,6 +65,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + TTXttyrec + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + TTXttyrec + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_include_directories( Modified: trunk/TTXSamples/ttxtest/CMakeLists.txt =================================================================== --- trunk/TTXSamples/ttxtest/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/TTXSamples/ttxtest/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -15,6 +15,13 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() endif(SUPPORT_OLD_WINDOWS) set_target_properties( Modified: trunk/installer/cygtool/CMakeLists.txt =================================================================== --- trunk/installer/cygtool/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/installer/cygtool/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -14,6 +14,13 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_link_libraries( Modified: trunk/teraterm/CMakeLists.txt =================================================================== --- trunk/teraterm/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/teraterm/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -33,3 +33,10 @@ set_target_properties( common_static PROPERTIES FOLDER teraterm) + +if(SUPPORT_OLD_WINDOWS AND MINGW) + add_subdirectory(libmingw) + set_target_properties( + mingw_msvcrt + PROPERTIES FOLDER teraterm) +endif() Added: trunk/teraterm/libmingw/CMakeLists.txt =================================================================== --- trunk/teraterm/libmingw/CMakeLists.txt (rev 0) +++ trunk/teraterm/libmingw/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,9 @@ +set(PACKAGE_NAME "mingw_msvcrt") + +project(${PACKAGE_NAME}) + +add_library( + ${PACKAGE_NAME} + STATIC + msvcrt_wrapper.c + ) Added: trunk/teraterm/libmingw/README.md =================================================================== --- trunk/teraterm/libmingw/README.md (rev 0) +++ trunk/teraterm/libmingw/README.md 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,31 @@ +build with MinGW +================ + +## MinGW + +- [MinGW(Wikipedia)](https://ja.wikipedia.org/wiki/MinGW) +- いくつかの派生プロジェクトが存在する +- プロジェクトによっていくつかの選択がある + - GCC(clang)のバージョン + - ライブラリのバージョン + - ターゲット(i686(32bit)/x86_64(64bit)) + - Thread model (win32/posix) + - 例外 (sjlj/dwarf) +- 比較的新しいOSでTera Termを動作させるならどれでもokと思われる + +## printf()系の動作を Visual Studio と同じにする + +- MinGW は C99,C11 などの仕様に準拠しようとしている +- 古い Visual Studio は仕様策定前の実装 + - "%zd" など新しいフォーマット指定子 + - 古い Visual Studio(msvcrt.dll) の printf()系ではサポートしていない + - L"%s" と "%s" の動作の違い + - msvcrtでは %s は char, L"%s" は wchar_t +- 特に指定していないと MinGW の printf()系(stdio)を使用する +- このため Visual Studio と動作が異なってしまう +- `__USE_MINGW_ANSI_STDIO` マクロので切り替えることができる + - 1 のとき mingw の stdio (デフォルト) + - 0 のとき msvcrt +- 参考URL + - [printf の %lf について](https://ja.stackoverflow.com/questions/34013/printf-%E3%81%AE-lf-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6) + Added: trunk/teraterm/libmingw/README_w95.md =================================================================== --- trunk/teraterm/libmingw/README_w95.md (rev 0) +++ trunk/teraterm/libmingw/README_w95.md 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,174 @@ + + +## MinGW で古いOS(Windows95)をサポートする + +ポイント + +- ランタイム(msvcrt.dll)の違いの吸収 +- dllのロード(loadlibrary()) +- pthreadを使用しない + +## ランタイム(msvcrt.dll)の違いの吸収 + +- MinGW は C runtime として msvcrt.dll (Visual Studioのランタイムdll)を使用する +- WindowsのバージョンによってインストールされているランタイムDLL のバージョンが異なる +- 使用可能な関数が異なっている + - [msvcrt-xref.pdf](https://sourceforge.net/projects/mingw/files/MinGW/Base/mingwrt/msvcrt-xref/) + +- CランタイムDLLのバージョンを吸収するためのwrapperを作成 + - msvcrt_wrapper.c を作成 + +### 未解決シンボルの追加について + +vsnprintf_s() 場合の例 + +- msvcrt-os.a を nm で調べる +- 1つのオブジェクトファイルに次の2つのシンボルがあることがわかる + - __imp__vsnprintf_s + - _vsnprintf_s +- `__declspec(dllimport)` 属性の関数の場合 + - 関数へのポインタが `__imp_<関数名>` に収納される +- 2つのシンボルを解決できるようファイルに追加 + + +``` +libmsvcrt-oss01204.o: +00000000 b .bss +00000000 d .data +00000000 i .idata$4 +00000000 i .idata$5 +00000000 i .idata$6 +00000000 i .idata$7 +00000000 t .text + U __head_lib32_libmsvcrt_os_a +00000000 I __imp__vsnprintf_s +00000000 T _vsnprintf_s +``` + +## dllをロードできるようにする + +- プラグイン(dll)がロードできなくなる +- 原因は TLS(Thread Local Storage,スレッド毎の記憶領域) +- TLSを使用しないようにする +- MinGWのCランタイムスタートアップの一部を置き換える + - tlssup.c + +### TLSについて + +- OSにはTLS(Thread Local Storage,スレッド毎の記憶領域)サポートが有る +- 新しいC,C++の仕様ではスレッドローカル変数が使用できる + - C++11 では thread_local + - C11 では _Thread_local +- Visual Studio では __declspec(thread) で使用できる + - GCC では __thread +- LoadLibrary()で使用するdll(Tera Termの場合、プラグイン)では利用で問題があった + - exe と同時にロードするdllはok + - Windows 7以降からok + - [スレッド固有記憶領域を持つ DLLを LoadLibrary すると異常動作する問題](http://seclan.dll.jp/dtdiary/2011/dt20110818.htm) +- Windowsではexe(PE32)内.tlsセクションを利用して、スレッドローカル変数の処理を行う + - スレッドコールバックテーブル +- Tera Termではスレッドローカル変数を使用していない +- MinGWのCランタイムスタートアップの一部を置き換えてtlsセクションを生成しないようにした + +## Windows 95向けビルドで使える MinGW + +Windows 95で動作させるため、 +Thread model が win32となっていることを確認する。 +posix (pthread)を使用すると95に実装されていない Win32 APIを使用する +バイナリが生成される。 + +NGな例 (msys2) +``` +$ gcc -v +Using built-in specs. +COLLECT_GCC=C:\msys64\mingw32\bin\gcc.exe +COLLECT_LTO_WRAPPER=C:/msys64/mingw32/bin/../lib/gcc/i686-w64-mingw32/10.2.0/lto-wrapper.exe +Target: i686-w64-mingw32 +Configured with: ../gcc- .... +: +: +Thread model: posix +Supported LTO compression algorithms: zlib zstd +gcc version 10.2.0 (Rev5, Built by MSYS2 project) +``` +cygwinも同様にNG + +OKな例 (debian gcc-mingw-w64-i686-win32 package) +``` +$ i686-w64-mingw32-gcc-win32 -v +Using built-in specs. +COLLECT_GCC=i686-w64-mingw32-gcc +COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-w64-mingw32/10-win32/lto-wrapper +Target: i686-w64-mingw32 +Configured with: ../../src/configure --build=x86_64-lin.... +: +: +Thread model: win32 +Supported LTO compression algorithms: zlib +gcc version 10-win32 20200525 (GCC) +``` + +OKな例 (MinGW-W64) +``` +>gcc -v +Using built-in specs. +COLLECT_GCC=gcc +COLLECT_LTO_WRAPPER=C:/Program\ Files\ (x86)/mingw-w64/i686-8.1.0-win32-sjlj-rt_v6-rev0/mingw32/bin/../libexec/gcc/i686-w64-mingw32/8.1.0/lto-wrapper.exe +Target: i686-w64-mingw32 +Configured with: ../../../src/gcc-8.1.0/configure --host=i68... +: +: +Thread model: win32 +gcc version 8.1.0 (i686-win32-sjlj-rev0, Built by MinGW-W64 project) +``` + +### ビルド例 (debian gcc-mingw-w64-i686-win32 package) + +Tera Term を Windows 95 で動作させるためのビルド + +次のパッケージをインストールしておく +``` +sudo apt-get install gcc-mingw-w64-i686-win32 g++-mingw-w64-i686-win32 +``` + +thread model win32版が動作するか次のコマンドなどでチェックしておく +``` +i686-w64-mingw32-gcc -v +i686-w64-mingw32-g++ -v +update-alternatives --display i686-w64-mingw32-gcc +update-alternatives --display i686-w64-mingw32-g++ +``` + +ビルド例 +``` +cd [Tera Term source dir] +mkdir build +cd build +cmake .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../mingw.toolchain.cmake -DSUPPORT_OLD_WINDOWS=ON -DCMAKE_BUILD_TYPE=Release +make -j +make -j install +make -j zip +``` + +### ビルド例 (MinGW-W64) + +create_locale()がうまく解決できないため今のところ使えない + +- [MinGW-W64](http://mingw-w64.org/doku.php/download/mingw-builds) +- Version 8.1.0 +- Architecture i686 +- Thread win32 +- Exception sjlj +- Build revision 0 + +例 + +``` +cd [Tera Term source dir] +mkdir build_mingw-w64 +cd build_mingw-w64 +cmake .. -G "MinGW Makefiles" +mingw32-make -j +mingw32-make -j install +``` + Added: trunk/teraterm/libmingw/msvcrt_wrapper.c =================================================================== --- trunk/teraterm/libmingw/msvcrt_wrapper.c (rev 0) +++ trunk/teraterm/libmingw/msvcrt_wrapper.c 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2020- TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#include <wchar.h> +#include <locale.h> +#include <windows.h> +#include <stdbool.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "../common/compat_win.h" + +// 9x\x8Cn\x82Ȃǂ̌Â\xA2msvcrt\x82\xAA\x8Eg\x82\xA6\x82\xE9\x82悤\x82ɂ\xB7\x82\xE9 +// - _s() \x8Cn\x82̓Z\x83L\x83\x85\x83\x8A\x83e\x83B\x81[\x82̒Ⴂ\x8A\x94\x82\xF0\x8CĂяo\x82\xB7 +// - W() \x8Cn\x8A\x94\x82\xCD ANSI\x95\xB6\x8E\x9A\x94ł\xF0\x8CĂяo\x82\xB7 +// - \x82\xB1\x82̃t\x83@\x83C\x83\x8B\x82\xF0\x83\x8A\x83\x93\x83N\x82\xB7\x82\xE9\x82ƕK\x82\xB8\x92u\x82\xAB\x8A\xB7\x82\xA6\x82\xE7\x82\xEA\x82\xE9 +// TODO: msvcrt\x82ɑ\xB6\x8D݂\xB7\x82邩\x83`\x83F\x83b\x83N\x82\xB5\x82āA\x82\xA0\x82\xEA\x82\xCEdll\x93\xE0\x82̊\x94\x82\xF0\x8Eg\x97p\x82\xB7\x82\xE9 + +int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list ap) +{ + int truncate = count == _TRUNCATE ? 1 : 0; + if (truncate) { + count = sizeOfBuffer -1; + } + else if (count < sizeOfBuffer) { + count = sizeOfBuffer; + } + int r = vsnprintf(buffer, count, format, ap); + if (truncate && r == sizeOfBuffer) { + buffer[sizeOfBuffer - 1] = 0; + r = -1; + } + return r; +} + +static int inner_vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list ap) +{ + return vsnprintf_s(buffer, sizeOfBuffer, count, format, ap); +} + +int snprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = vsnprintf_s(buffer, sizeOfBuffer, count, format, ap); + va_end(ap); + return r; +} + +static int inner_snprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = vsnprintf_s(buffer, sizeOfBuffer, count, format, ap); + va_end(ap); + return r; +} + +/** + * TODO: locale\x96\xB3\x8E\x8B + */ +static int inner_snprintf_s_l(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, _locale_t locale, ...) +{ + int r; + va_list ap; + va_start(ap, locale); + r = inner_vsnprintf_s(buffer, sizeOfBuffer, count, format, ap); + va_end(ap); + return r; +} + +static int inner_vsnwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, va_list ap) +{ + bool truncate = false; + if (count == _TRUNCATE) { + truncate = true; + count = sizeOfBuffer; + } + else if (count < sizeOfBuffer) { + count = sizeOfBuffer; + } + int r = _vsnwprintf(buffer, count, format, ap); + if (r == -1) { + // error or \x90\xE8\x8Ê\xC4 + if (truncate) { + buffer[sizeOfBuffer - 1] = 0; + } + r = -1; + } + else { + // \x82\xA4\x82܂\xAD\x8F\x91\x82\xAB\x8D\x9E\x82܂ꂽ + } + return r; +} + +static int inner_snwprintf_s(wchar_t *buffer, size_t sizeOfBuffer, size_t count, const wchar_t *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = inner_vsnwprintf_s(buffer, sizeOfBuffer, count, format, ap); + va_end(ap); + return r; +} + +int swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = inner_vsnwprintf_s(buffer, sizeOfBuffer, 1, format, ap); + va_end(ap); + return r; +} + +static int inner_swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = inner_vsnwprintf_s(buffer, sizeOfBuffer, 1, format, ap); + va_end(ap); + return r; +} + +__declspec(dllimport) int _vscprintf(const char *format, va_list ap) +{ + int r = vsnprintf(NULL, 0, format, ap); + return r; +} + +static int inner_vscprintf(const char *format, va_list ap) +{ + int r = vsnprintf(NULL, 0, format, ap); + return r; +} + +static errno_t inner_sscanf_s(const char *buffer, const char *format, ...) +{ + int r; + va_list ap; + va_start(ap, format); + r = vsscanf(buffer, format, ap); + va_end(ap); + return r; +} + +static errno_t inner_strcat_s(char *strDestination, size_t numberOfElements, const char *strSource) +{ + size_t dest_len = strlen(strDestination); + size_t src_len = strlen(strSource); + + if(dest_len + src_len + 1 > numberOfElements) { + return EINVAL; + } + strcat(strDestination, strSource); + return 0; +} + +static errno_t inner_wcscat_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource) +{ + size_t dest_len = wcslen(strDestination); + size_t src_len = wcslen(strSource); + + if(dest_len + src_len + 1 > numberOfElements) { + return EINVAL; + } + wcscat(strDestination, strSource); + return 0; +} + +static errno_t inner_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource) +{ + size_t src_len = strlen(strSource); + + if(src_len + 1 > numberOfElements) { + return EINVAL; + } + strcpy(strDestination, strSource); + return 0; +} + +static errno_t inner_wcscpy_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource) +{ + size_t src_len = wcslen(strSource); + + if(src_len + 1 > numberOfElements) { + return EINVAL; + } + wcscpy(strDestination, strSource); + return 0; +} + +static errno_t inner_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count) +{ + size_t src_len = strlen(strSource); + + if (count == _TRUNCATE) { + size_t copy_len = numberOfElements - 1 < src_len ? numberOfElements - 1 : src_len; + memcpy(strDestination, strSource, copy_len); + strDestination[copy_len] = '\0'; + } + else { + if (numberOfElements - 1 < src_len) { + size_t copy_len = numberOfElements - 1; + memcpy(strDestination, strSource, copy_len); + strDestination[copy_len] = '\0'; + } + else { + strcpy(strDestination, strSource); + } + } + return 0; +} + +static errno_t inner_wcsncpy_s(wchar_t *strDestination, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + size_t src_len = wcslen(strSource); + + if (count == _TRUNCATE) { + size_t copy_len = numberOfElements - 1 < src_len ? numberOfElements - 1 : src_len; + wmemcpy(strDestination, strSource, copy_len); + strDestination[copy_len] = '\0'; + } + else { + if (numberOfElements - 1 < src_len) { + size_t copy_len = numberOfElements - 1; + wmemcpy(strDestination, strSource, copy_len); + strDestination[copy_len] = '\0'; + } + else { + wcscpy(strDestination, strSource); + } + } + return 0; +} + +static errno_t inner_strncat_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) +{ + size_t dest_len = strlen(strDest); + size_t left_len = numberOfElements - dest_len; + + char *d = strDest + dest_len; + return inner_strncpy_s(d, left_len, strSource, count); +} + +static errno_t inner_wcsncat_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + size_t dest_len = wcslen(strDest); + size_t left_len = numberOfElements - dest_len; + + wchar_t *d = strDest + dest_len; + return inner_wcsncpy_s(d, left_len, strSource, count); +} + +static size_t inner_strnlen(const char *s, size_t maxlen) +{ + size_t len = 0; + while(*s != 0 && maxlen != 0) { + s++; + maxlen--; + len++; + } + return len; +} + +static size_t inner_wcsnlen(const wchar_t *s, size_t maxlen) +{ + size_t len = 0; + while(*s != 0 && maxlen != 0) { + s++; + maxlen--; + len++; + } + return len; +} + + +static errno_t inner_fopen_s(FILE **f, const char *name, const char *mode) +{ + *f = fopen(name, mode); + return errno; +} + +static errno_t inner_freopen_s(FILE **f, const char *name, const char *mode) +{ + *f = freopen(name, mode, *f); + return errno; +} + +static errno_t inner__wfopen_s(FILE **f, const wchar_t *name, const char *mode) +{ + *f = fopen((char *)name, mode); // TODO + return errno; +} + +static char *inner_strtok_s(char* str, const char* delimiters, char** context) +{ + (void)context; + char *r = strtok(str, delimiters); + return r; +} + +static int inner__wstat64(const wchar_t *pathW, struct __stat64 *st) +{ + struct _stati64 st32; + int r = _wstati64(pathW, &st32); + if (r != 0) { + char pathA[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, pathW, -1, pathA, sizeof(pathA)-1, NULL, NULL); + r = _stati64(pathA, &st32); + } + if (r == 0) { + st->st_gid = st32.st_gid; + st->st_atime = st32.st_atime; + st->st_ctime = st32.st_ctime; + st->st_dev = st32.st_dev; + st->st_ino = st32.st_ino; + st->st_mode = st32.st_mode; + st->st_mtime = st32.st_mtime; + st->st_nlink = st32.st_nlink; + st->st_rdev = st32.st_rdev; + st->st_size = st32.st_size; + st->st_uid = st32.st_uid; + } + return r; +} + +static errno_t inner_tmpnam_s(char * str, size_t sizeInChars) +{ + (void)sizeInChars; + tmpnam(str); + return 0; +} + +static errno_t inner_itoa_s(int value, char * buffer, size_t size, int radix ) +{ + (void)size; + itoa(value, buffer, radix); + return 0; +} + +// \x83e\x83X\x83g\x97p\x8A\x94 +#if 0 +static void not_implemented(void) +{ + MessageBox(NULL, "not_implemented", "tera trem msvcrt_wrapper", MB_OK | MB_ICONEXCLAMATION); +} +void *_imp___itoa_s = (void *)not_implemented; +#endif + +void *_imp___vsnprintf_s = (void *)inner_vsnprintf_s; +void *_imp___snprintf_s = (void *)inner_snprintf_s; +void *_imp___snprintf_s_l = (void *)inner_snprintf_s_l; +void *_imp___vsnwprintf_s = (void *)inner_vsnwprintf_s; +void *_imp___snwprintf_s = (void *)inner_snwprintf_s; +void *_imp__swprintf_s = (void *)inner_swprintf_s; +void *_imp___vscprintf = (void *)inner_vscprintf; +void *_imp__sscanf_s = (void *)inner_sscanf_s; + +void *_imp__strcat_s = (void *)inner_strcat_s; +void *_imp__wcscat_s = (void *)inner_wcscat_s; +void *_imp__strcpy_s = (void *)inner_strcpy_s; +void *_imp__wcscpy_s = (void *)inner_wcscpy_s; +void *_imp__strncat_s = (void *)inner_strncat_s; +void *_imp__wcsncat_s = (void *)inner_wcsncat_s; +void *_imp__strncpy_s = (void *)inner_strncpy_s; +void *_imp__wcsncpy_s = (void *)inner_wcsncpy_s; +void *_imp__strnlen = (void *)inner_strnlen; +void *_imp__wcsnlen = (void *)inner_wcsnlen; +void *_imp__strtok_s = (void *)inner_strtok_s; + +void *_imp__fopen_s = (void *)inner_fopen_s; +void *_imp__freopen_s = (void *)inner_freopen_s; +void *_imp___wfopen_s = (void *)inner__wfopen_s; +void *_imp___wstat64 = (void *)inner__wstat64; +void *_imp__tmpnam_s = (void *)inner_tmpnam_s; + +void *_imp___itoa_s = (void *)inner_itoa_s; Added: trunk/teraterm/libmingw/test/CMakeLists.txt =================================================================== --- trunk/teraterm/libmingw/test/CMakeLists.txt (rev 0) +++ trunk/teraterm/libmingw/test/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,83 @@ +#cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.11) + +set(PACKAGE_NAME "msvcrt") + +project(${PACKAGE_NAME}) + +if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /ZI") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /ZI") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO") +elseif(MINGW) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__USE_MINGW_ANSI_STDIO=0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__USE_MINGW_ANSI_STDIO=0") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_WARNING_FLAGS} -g -static -ffunction-sections -fdata-sections ${C_ONLY_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_CXX_WARNING_FLAGS} -g -static -ffunction-sections -fdata-sections") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc -static-libstdc++") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + endif() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -g") +endif() + +add_executable( + ${PACKAGE_NAME} + main.c + outputdebugprintf.cpp + is.c + ../../common/asprintf.cpp + ../../common/compat_win.cpp + ../../common/layer_for_unicode.cpp + ../../common/codeconv.cpp + ../../common/dllutil.cpp + ) + +if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../msvcrt_wrapper.c + ) +endif() + +target_include_directories( + ${PACKAGE_NAME} + PRIVATE + . + ../../common + ) + +if(MINGW) + target_compile_options( + ${PACKAGE_NAME} + PUBLIC -Wall + ) +endif() + +target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + gdi32 + ) + + +#target_link_libraries( +# msvcr70 +# PRIVATE +# mingw_msvcrt +# ) + +if(false) +add_executable( + crt_snprintf_s + crt_snprintf_s.cpp + ) + +target_compile_options( + crt_snprintf_s + PUBLIC -Wall + ) +endif() Added: trunk/teraterm/libmingw/test/is.c =================================================================== --- trunk/teraterm/libmingw/test/is.c (rev 0) +++ trunk/teraterm/libmingw/test/is.c 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,216 @@ + +#include <windows.h> +#include "ttlib.h" + +#if (_MSC_VER < 1800) +BOOL vercmp( + DWORD cond_val, + DWORD act_val, + DWORD dwTypeMask) +{ + switch (dwTypeMask) { + case VER_EQUAL: + if (act_val == cond_val) { + return TRUE; + } + break; + case VER_GREATER: + if (act_val > cond_val) { + return TRUE; + } + break; + case VER_GREATER_EQUAL: + if (act_val >= cond_val) { + return TRUE; + } + break; + case VER_LESS: + if (act_val < cond_val) { + return TRUE; + } + break; + case VER_LESS_EQUAL: + if (act_val <= cond_val) { + return TRUE; + } + break; + } + return FALSE; +} + +#endif + +BOOL _myVerifyVersionInfo( + LPOSVERSIONINFOEX lpVersionInformation, + DWORD dwTypeMask, + DWORDLONG dwlConditionMask) +{ + OSVERSIONINFO osvi; + WORD cond; + BOOL ret, check_next; + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + if (dwTypeMask & VER_BUILDNUMBER) { + cond = (WORD)((dwlConditionMask >> (2*3)) & 0x07); + if (!vercmp(lpVersionInformation->dwBuildNumber, osvi.dwBuildNumber, cond)) { + return FALSE; + } + } + if (dwTypeMask & VER_PLATFORMID) { + cond = (WORD)((dwlConditionMask >> (3*3)) & 0x07); + if (!vercmp(lpVersionInformation->dwPlatformId, osvi.dwPlatformId, cond)) { + return FALSE; + } + } + ret = TRUE; + if (dwTypeMask & (VER_MAJORVERSION | VER_MINORVERSION)) { + check_next = TRUE; + if (dwTypeMask & VER_MAJORVERSION) { + cond = (WORD)((dwlConditionMask >> (1*3)) & 0x07); + if (cond == VER_EQUAL) { + if (!vercmp(lpVersionInformation->dwMajorVersion, osvi.dwMajorVersion, cond)) { + return FALSE; + } + } + else { + ret = vercmp(lpVersionInformation->dwMajorVersion, osvi.dwMajorVersion, cond); + // ret: result of major version + if (!vercmp(lpVersionInformation->dwMajorVersion, osvi.dwMajorVersion, VER_EQUAL)) { + // !vercmp(...: result of GRATOR/LESS than (not "GRATOR/LESS than or equal to") of major version + // e.g. + // lpvi:5.1 actual:5.0 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:5.1 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:5.2 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:6.0 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:TRUE must not check minor + // lpvi:5.1 actual:6.1 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:TRUE must not check minor + // lpvi:5.1 actual:6.2 cond:VER_GREATER_EQUAL ret:TRUE !vercmp(...:TRUE must not check minor + // lpvi:5.1 actual:5.0 cond:VER_GREATER ret:FALSE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:5.1 cond:VER_GREATER ret:FALSE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:5.2 cond:VER_GREATER ret:FALSE !vercmp(...:FALSE must check minor + // lpvi:5.1 actual:6.0 cond:VER_GREATER ret:TRUE !vercmp(...:TRUE must not check minor + // lpvi:5.1 actual:6.1 cond:VER_GREATER ret:TRUE !vercmp(...:TRUE must not check minor + // lpvi:5.1 actual:6.2 cond:VER_GREATER ret:TRUE !vercmp(...:TRUE must not check minor + check_next = FALSE; + } + } + } + if (check_next && (dwTypeMask & VER_MINORVERSION)) { + cond = (WORD)((dwlConditionMask >> (0*3)) & 0x07); + if (cond == VER_EQUAL) { + if (!vercmp(lpVersionInformation->dwMinorVersion, osvi.dwMinorVersion, cond)) { + return FALSE; + } + } + else { + ret = vercmp(lpVersionInformation->dwMinorVersion, osvi.dwMinorVersion, cond); + } + } + } + return ret; +} + +ULONGLONG _myVerSetConditionMask(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask) +{ + ULONGLONG result, mask; + BYTE op = dwConditionMask & 0x07; + + switch (dwTypeBitMask) { + case VER_MINORVERSION: + mask = 0x07 << (0 * 3); + result = dwlConditionMask & ~mask; + result |= op << (0 * 3); + break; + case VER_MAJORVERSION: + mask = 0x07 << (1 * 3); + result = dwlConditionMask & ~mask; + result |= op << (1 * 3); + break; + case VER_BUILDNUMBER: + mask = 0x07 << (2 * 3); + result = dwlConditionMask & ~mask; + result |= op << (2 * 3); + break; + case VER_PLATFORMID: + mask = 0x07 << (3 * 3); + result = dwlConditionMask & ~mask; + result |= op << (3 * 3); + break; + case VER_SERVICEPACKMINOR: + mask = 0x07 << (4 * 3); + result = dwlConditionMask & ~mask; + result |= op << (4 * 3); + break; + case VER_SERVICEPACKMAJOR: + mask = 0x07 << (5 * 3); + result = dwlConditionMask & ~mask; + result |= op << (5 * 3); + break; + case VER_SUITENAME: + mask = 0x07 << (6 * 3); + result = dwlConditionMask & ~mask; + result |= op << (6 * 3); + break; + case VER_PRODUCT_TYPE: + mask = 0x07 << (7 * 3); + result = dwlConditionMask & ~mask; + result |= op << (7 * 3); + break; + default: + result = 0; + break; + } + + return result; +} + +ULONGLONG myVerSetConditionMask(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask) +{ + typedef ULONGLONG(WINAPI *func)(ULONGLONG, DWORD, BYTE); + static HMODULE hmodKernel32 = NULL; + static func pVerSetConditionMask = NULL; + char kernel32_dll[MAX_PATH]; + + GetSystemDirectory(kernel32_dll, sizeof(kernel32_dll)); + strncat_s(kernel32_dll, sizeof(kernel32_dll), "\\kernel32.dll", _TRUNCATE); + if (hmodKernel32 == NULL) { + hmodKernel32 = LoadLibrary(kernel32_dll); + if (hmodKernel32 != NULL) { + pVerSetConditionMask = (func)GetProcAddress(hmodKernel32, "VerSetConditionMask"); + } + } + + if (pVerSetConditionMask == NULL) { + return _myVerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask); + } + + return pVerSetConditionMask(dwlConditionMask, dwTypeBitMask, dwConditionMask); +} + +BOOL myVerifyVersionInfo( + LPOSVERSIONINFOEX lpVersionInformation, + DWORD dwTypeMask, + DWORDLONG dwlConditionMask) +{ +#if (_MSC_VER >= 1800) + return VerifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask); +#else + return _myVerifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask); +#endif +} + +BOOL IsWindowsNTKernel() +{ + OSVERSIONINFOEX osvi; + DWORDLONG dwlConditionMask = 0; + int op = VER_EQUAL; + BOOL ret; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwPlatformId = VER_PLATFORM_WIN32_NT; + dwlConditionMask = myVerSetConditionMask(dwlConditionMask, VER_PLATFORMID, op); + ret = myVerifyVersionInfo(&osvi, VER_PLATFORMID, dwlConditionMask); + return (ret); +} Added: trunk/teraterm/libmingw/test/main.c =================================================================== --- trunk/teraterm/libmingw/test/main.c (rev 0) +++ trunk/teraterm/libmingw/test/main.c 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,45 @@ +//gcc -g -o test main.c -Wall -Wl,-wrap=_imp__fopen_s -Wl,-Map=test.map +//gcc -g -o test main.c -Wall -Wl,-Map=test.map,--allow-multiple-definition + +//#define __USE_MINGW_ANSI_STDIO 0 +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <wchar.h> +#include <windows.h> +#include <locale.h> + +#include "../../common/ttlib.h" +#include "../../common/asprintf.h" + +int vaswprintf_test(const wchar_t *fmt, ...) +{ + wchar_t *message; + va_list ap; + va_start(ap, fmt); + vaswprintf(&message, fmt, ap); + wprintf(L"message='%ls'\n", message); + wprintf(L"message='%s'\n", message); + free(message); + return 0; +} + +int main(int argc, char *argv[]) +{ + FILE *fp; + printf("1\n"); + fopen_s(&fp, "test.txt", "w"); + fclose(fp); + printf("2\n"); + + vaswprintf_test(L"test %s %ls %hs", L"wide", L"wide", "narrow"); + + { + wchar_t buf[128]; + swprintf(buf, _countof(buf), L"test %s %ls %hs", L"wide", L"wide", "narrow"); + wprintf(L"buf='%s'\n", buf); + __ms_wprintf(L"buf='%s'\n", buf); + } + + return 0; +} Added: trunk/teraterm/libmingw/test/outputdebugprintf.cpp =================================================================== --- trunk/teraterm/libmingw/test/outputdebugprintf.cpp (rev 0) +++ trunk/teraterm/libmingw/test/outputdebugprintf.cpp 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,27 @@ + +#include <stdio.h> +#include <windows.h> + +#include "ttlib.h" +#include "layer_for_unicode.h" +#include "compat_win.h" + +void OutputDebugPrintf(const char *fmt, ...) +{ + char tmp[1024]; + va_list arg; + va_start(arg, fmt); + _vsnprintf_s(tmp, sizeof(tmp), _TRUNCATE, fmt, arg); + va_end(arg); + OutputDebugStringA(tmp); +} + +void OutputDebugPrintfW(const wchar_t *fmt, ...) +{ + wchar_t tmp[1024]; + va_list arg; + va_start(arg, fmt); + _vsnwprintf_s(tmp, _countof(tmp), _TRUNCATE, fmt, arg); + va_end(arg); + _OutputDebugStringW(tmp); +} Added: trunk/teraterm/libmingw/tlssup.c =================================================================== --- trunk/teraterm/libmingw/tlssup.c (rev 0) +++ trunk/teraterm/libmingw/tlssup.c 2021-01-27 14:40:25 UTC (rev 9136) @@ -0,0 +1,186 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + * + * Written by Kai Tietz <kai.t****@onevi*****> + */ + +#ifdef CRTDLL +#undef CRTDLL +#endif + +#include <windows.h> +#include <stdio.h> +#include <memory.h> +#include <malloc.h> + +#ifndef _CRTALLOC +#define _CRTALLOC(x) __attribute__ ((section (x) )) +#endif + +#ifndef __INTERNAL_FUNC_DEFINED +#define __INTERNAL_FUNC_DEFINED + typedef void (__cdecl *_PVFV)(void); + typedef int (__cdecl *_PIFV)(void); + typedef void (__cdecl *_PVFI)(int); +#endif + +extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved); + +#define FUNCS_PER_NODE 30 + +typedef struct TlsDtorNode { + int count; + struct TlsDtorNode *next; + _PVFV funcs[FUNCS_PER_NODE]; +} TlsDtorNode; + +ULONG _tls_index = 0; + +/* TLS raw template data start and end. */ +_CRTALLOC(".tls$AAA") char _tls_start = 0; +_CRTALLOC(".tls$ZZZ") char _tls_end = 0; + +_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0; +_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0; + +#if 0 +#ifdef _WIN64 +_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = { + (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index, + (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0 +}; +#else +_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = { + (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end, + (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1), + (ULONG) 0, (ULONG) 0 +}; +#endif +#endif + +#ifndef __CRT_THREAD +#ifdef HAVE_ATTRIBUTE_THREAD +#define __CRT_THREAD __declspec(thread) +#else +#define __CRT_THREAD __thread +#endif +#endif + +#define DISABLE_MS_TLS 1 + +static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0; +static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0; + +#if !defined (DISABLE_MS_TLS) +static __CRT_THREAD TlsDtorNode *dtor_list; +static __CRT_THREAD TlsDtorNode dtor_list_head; +#endif + +extern int _CRT_MT; + +BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID); + +BOOL WINAPI +__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) +{ + _PVFV *pfunc; + int nfuncs, ifunc; + + /* We don't let us trick here. */ + if (_CRT_MT != 2) + _CRT_MT = 2; + + if (dwReason != DLL_THREAD_ATTACH) + { + if (dwReason == DLL_PROCESS_ATTACH) + __mingw_TLScallback (hDllHandle, dwReason, lpreserved); + return TRUE; + } + + /* Use the nfuncs variable to iterate the TLS functions instead of pfunc to + avoid nasty compiler optimizations when comparing two global pointers. */ + nfuncs = &__xd_z - (&__xd_a + 1); + for (ifunc=0; ifunc < nfuncs; ++ifunc) + { + pfunc = (&__xd_a + 1) + ifunc; + if (*pfunc != NULL) + (*pfunc)(); + } + return TRUE; +} + +const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init; +_CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init; + +int __cdecl __tlregdtor (_PVFV); + +int __cdecl +__tlregdtor (_PVFV func) +{ + if (!func) + return 0; +#if !defined (DISABLE_MS_TLS) + if (dtor_list == NULL) + { + dtor_list = &dtor_list_head; + dtor_list_head.count = 0; + } + else if (dtor_list->count == FUNCS_PER_NODE) + { + TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode)); + if (pnode == NULL) + return -1; + pnode->count = 0; + pnode->next = dtor_list; + dtor_list = pnode; + + dtor_list->count = 0; + } + dtor_list->funcs[dtor_list->count++] = func; +#endif + return 0; +} + +static BOOL WINAPI +__dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) +{ +#if !defined (DISABLE_MS_TLS) + TlsDtorNode *pnode, *pnext; + int i; +#endif + + if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH) + return TRUE; + /* As TLS variables are detroyed already by DLL_THREAD_DETACH + call, we have to avoid access on the possible DLL_PROCESS_DETACH + call the already destroyed TLS vars. + TODO: The used local thread based variables have to be handled + manually, so that we can control their lifetime here. */ +#if !defined (DISABLE_MS_TLS) + if (dwReason != DLL_PROCESS_DETACH) + { + for (pnode = dtor_list; pnode != NULL; pnode = pnext) + { + for (i = pnode->count - 1; i >= 0; --i) + { + if (pnode->funcs[i] != NULL) + (*pnode->funcs[i])(); + } + pnext = pnode->next; + if (pnext != NULL) + free ((void *) pnode); + } + } +#endif + __mingw_TLScallback (hDllHandle, dwReason, lpreserved); + return TRUE; +} + +_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor; + + +int mingw_initltsdrot_force = 0; +int mingw_initltsdyn_force=0; +int mingw_initltssuo_force = 0; Modified: trunk/teraterm/teraterm/CMakeLists.txt =================================================================== --- trunk/teraterm/teraterm/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/teraterm/teraterm/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -212,6 +212,15 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) if (MSVC) Modified: trunk/teraterm/ttpcmn/CMakeLists.txt =================================================================== --- trunk/teraterm/ttpcmn/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/teraterm/ttpcmn/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -26,6 +26,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_sources( Modified: trunk/teraterm/ttpset/CMakeLists.txt =================================================================== --- trunk/teraterm/ttpset/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/teraterm/ttpset/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -17,6 +17,15 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_sources( Modified: trunk/teraterm/ttptek/CMakeLists.txt =================================================================== --- trunk/teraterm/ttptek/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/teraterm/ttptek/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -20,6 +20,13 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_sources( Modified: trunk/tools/ttbroadcast/CMakeLists.txt =================================================================== --- trunk/tools/ttbroadcast/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/tools/ttbroadcast/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -28,6 +28,7 @@ target_link_libraries( ttbroadcast PRIVATE + ttpcmn common_static ) Modified: trunk/ttssh2/ttxssh/CMakeLists.txt =================================================================== --- trunk/ttssh2/ttxssh/CMakeLists.txt 2021-01-22 15:00:58 UTC (rev 9135) +++ trunk/ttssh2/ttxssh/CMakeLists.txt 2021-01-27 14:40:25 UTC (rev 9136) @@ -111,6 +111,20 @@ ../../teraterm/common/compat_w95_vs2005.c ) endif() + if(MINGW) + target_sources( + ${PACKAGE_NAME} + PRIVATE + ../../teraterm/libmingw/tlssup.c + ) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + -Wl,--whole-archive + mingw_msvcrt + -Wl,--no-whole-archive + ) + endif() endif(SUPPORT_OLD_WINDOWS) target_include_directories(