On Thu, 4 Dec 2025, Pali Rohár wrote:

These two 32-bit DLL libraries do not provide those wide stat and find
functions. Enable mingw-w64 emulation of them in import libraries.
For 32-bit builds these functions have also alternative names without
the "*32" suffix. Add also those symbol aliases.
---
mingw-w64-crt/Makefile.am           |  3 ++
mingw-w64-crt/stdio/_wfindfirst32.c |  6 +++
mingw-w64-crt/stdio/_wfindnext32.c  |  6 +++
mingw-w64-crt/stdio/_wstat32.c      | 58 ++++++++++++++++++++++++++++-
4 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 6f6ac57fc60d..599cf21adea2 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -893,6 +893,9 @@ src_pre_msvcrt20=\
  misc/__timezone.c \
  misc/__tzname.c \
  stdio/_telli64.c \
+  stdio/_wfindfirst32.c \
+  stdio/_wfindnext32.c \
+  stdio/_wstat32.c \
  stdio/fgetws.c \
  stdio/fputws.c \
  stdio/iob_func.c
diff --git a/mingw-w64-crt/stdio/_wfindfirst32.c 
b/mingw-w64-crt/stdio/_wfindfirst32.c
index d46f26c4d665..28443c73771a 100644
--- a/mingw-w64-crt/stdio/_wfindfirst32.c
+++ b/mingw-w64-crt/stdio/_wfindfirst32.c
@@ -17,3 +17,9 @@ intptr_t __cdecl _wfindfirst32(const wchar_t 
*_Filename,struct _wfinddata32_t *_
  return ret;
}
intptr_t (__cdecl *__MINGW_IMP_SYMBOL(_wfindfirst32))(const wchar_t *, struct 
_wfinddata32_t *) = _wfindfirst32;
+
+#ifndef _WIN64
+#undef _wfindfirst
+intptr_t __attribute__ ((alias ("_wfindfirst32"))) __cdecl _wfindfirst(const 
char *, struct _wfinddata32_t *);
+extern intptr_t __attribute__ ((alias 
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wfindfirst32))))) (__cdecl 
*__MINGW_IMP_SYMBOL(_wfindfirst))(const char *, struct _wfinddata32_t *);
+#endif
diff --git a/mingw-w64-crt/stdio/_wfindnext32.c 
b/mingw-w64-crt/stdio/_wfindnext32.c
index 1846a0f06855..d10c9f897a76 100644
--- a/mingw-w64-crt/stdio/_wfindnext32.c
+++ b/mingw-w64-crt/stdio/_wfindnext32.c
@@ -17,3 +17,9 @@ int __cdecl _wfindnext32(intptr_t _FindHandle,struct 
_wfinddata32_t *_FindData)
  return 0;
}
int (__cdecl *__MINGW_IMP_SYMBOL(_wfindnext32))(intptr_t, struct _wfinddata32_t 
*) = _wfindnext32;
+
+#ifndef _WIN64
+#undef _wfindnext
+int __attribute__ ((alias ("_wfindnext32"))) __cdecl _wfindnext(intptr_t, 
struct _wfinddata32_t *);
+extern int __attribute__ ((alias 
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wfindnext32))))) (__cdecl 
*__MINGW_IMP_SYMBOL(_wfindnext))(intptr_t, struct _wfinddata32_t *);
+#endif
diff --git a/mingw-w64-crt/stdio/_wstat32.c b/mingw-w64-crt/stdio/_wstat32.c
index 8ef681a429c1..f9be2336bdef 100644
--- a/mingw-w64-crt/stdio/_wstat32.c
+++ b/mingw-w64-crt/stdio/_wstat32.c
@@ -8,6 +8,11 @@
#include <stdint.h>
#include <errno.h>

+#ifndef _WIN64
+#include <fcntl.h>
+#include <windows.h>
+#endif
+
/* When the file time does not fit into the st_Xtime field:
 *           crtdll-msvcr71   msvcr80+
 * st_Xtime       -1             -1
@@ -20,12 +25,12 @@
 * errno       no change     no change   EOVERFLOW
 * returns         0            -1          -1
 *
- * This file is used only for 64-bit msvcrt.dll builds.
 * The stat function on 32-bit system os msvcrt.dll behaves
 * like the msvcr80/msvcr90, so use this behavior.
 */
int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 *_Stat)
{
+#ifdef _WIN64
  struct _stat64 st;
  int ret=_wstat64(_Name,&st);
  if (ret != 0)
@@ -44,5 +49,56 @@ int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 
*_Stat)
  if (_Stat->st_atime == -1 || _Stat->st_mtime == -1 || _Stat->st_ctime == -1)
    errno = EINVAL;
  return 0;
+#else
+  /* mingw-w64 _wstat64() on 32-bit systems is implemented as wrapper around 
the _wstat32().
+   * Therefore mingw-w64 _wstat32() implementation cannot call _wstat64().
+   * This _wstat32 implementation uses _fstat32() with handle obtained from 
CreateFileW().
+   * _fstat requires only FILE_READ_ATTRIBUTES access and 
FILE_FLAG_BACKUP_SEMANTICS is
+   * required for opening directory via CreateFileW().
+   * Using just FILE_READ_ATTRIBUTES access allows to open also path which is 
was denied for
+   * reading by another process. msvcrt.dll _wstat32() also allows to be 
called on such path.
+   */
+  int fd;
+  int ret;
+  int err;
+  HANDLE handle;
+  handle = CreateFileW(_Name, FILE_READ_ATTRIBUTES, FILE_SHARE_VALID_FLAGS, 
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  if (handle == INVALID_HANDLE_VALUE) {
+    switch (GetLastError()) {
+    case ERROR_PATH_NOT_FOUND:
+    case ERROR_FILE_NOT_FOUND:
+      errno = ENOENT;
+      break;
+    case ERROR_ACCESS_DENIED:
+    case ERROR_WRITE_PROTECT...ERROR_SHARING_BUFFER_EXCEEDED:

FWIW I wasn't familiar with this language extension. It's probably fine (and Clang seems to support it as well), but maybe it'd be worth pointing out that this isn't proper C in itself?

// Martin

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to