On Saturday 13 December 2025 00:31:22 Martin Storsjö wrote:
> 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
I used this syntax so many times without spotting any problem and I did
not know that this is not proper C, but rather gcc extension. I will add
a comment for it.
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public