- From f8a53c192eb697b88c5d7dcd29834129c7c0e842 Mon Sep 17 00:00:00 2001
- From: Lionel Cons <lionelcons1972@gmail.com>
- Date: Fri, 13 Jun 2025 14:58:14 +0200
- Subject: [PATCH 1/6] tests: Fix tests/winclonefile/winclonefile.c build
- failure with newer MinGW headers
- Fix tests/winclonefile/winclonefile.c build failure with newer MinGW headers.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- tests/winclonefile/winclonefile.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
- diff --git a/tests/winclonefile/winclonefile.c b/tests/winclonefile/winclonefile.c
- index 39b019b..c79672d 100644
- --- a/tests/winclonefile/winclonefile.c
- +++ b/tests/winclonefile/winclonefile.c
- @@ -37,7 +37,17 @@
- #define EXIT_USAGE (2)
- -#if 1
- +#ifdef DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC
- +/*
- + * MinGW commit
- + * https://github.com/mingw-w64/mingw-w64/commit/dd725c39e8eace4bfaa76e30e648b2bf7e7541e3
- + * added |DUPLICATE_EXTENTS_DATA| and |DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC|
- + */
- +#define WIN32_HEADERS_HAVE_DUPLICATE_EXTENTS_DATA 1
- +#endif /* WIN32_HEADERS_HAVE_DUPLICATE_EXTENTS_DATA */
- +
- +
- +#ifndef WIN32_HEADERS_HAVE_DUPLICATE_EXTENTS_DATA
- /*
- * MinGW include do not define |DUPLICATE_EXTENTS_DATA| yet, see
- * https://github.com/mingw-w64/mingw-w64/issues/90 ("[mingw-w64/mingw-w64]
- @@ -49,7 +59,7 @@ typedef struct _DUPLICATE_EXTENTS_DATA {
- LARGE_INTEGER TargetFileOffset;
- LARGE_INTEGER ByteCount;
- } DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
- -#endif
- +#endif /* WIN32_HEADERS_HAVE_DUPLICATE_EXTENTS_DATA */
- void
- --
- 2.45.1
- From 3c83bad5284c8d9c88ff8a5f7fad81487e1b976f Mon Sep 17 00:00:00 2001
- From: Lionel Cons <lionelcons1972@gmail.com>
- Date: Fri, 13 Jun 2025 15:01:23 +0200
- Subject: [PATCH 2/6] tests: Fix bogus trailing backslash in tests/*/Makefiles
- Fix bogus trailing backslash in tests/*/Makefiles.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- tests/ea/Makefile | 2 +-
- tests/lssparse/Makefile | 2 +-
- tests/winclonefile/Makefile | 2 +-
- tests/winfsinfo1/Makefile | 2 +-
- tests/winsg/Makefile | 2 +-
- 5 files changed, 5 insertions(+), 5 deletions(-)
- diff --git a/tests/ea/Makefile b/tests/ea/Makefile
- index 65e58a3..4e49afd 100644
- --- a/tests/ea/Makefile
- +++ b/tests/ea/Makefile
- @@ -20,5 +20,5 @@ clean:
- rm -fv \
- nfs_ea.i686.exe \
- nfs_ea.x86_64.exe \
- - nfs_ea.exe \
- + nfs_ea.exe
- # EOF.
- diff --git a/tests/lssparse/Makefile b/tests/lssparse/Makefile
- index 4f92fc1..6b591ac 100644
- --- a/tests/lssparse/Makefile
- +++ b/tests/lssparse/Makefile
- @@ -19,5 +19,5 @@ lssparse.exe: lssparse.x86_64.exe
- clean:
- rm -fv \
- lssparse.x86_64.exe \
- - lssparse.exe \
- + lssparse.exe
- # EOF.
- diff --git a/tests/winclonefile/Makefile b/tests/winclonefile/Makefile
- index bf548b7..f541936 100644
- --- a/tests/winclonefile/Makefile
- +++ b/tests/winclonefile/Makefile
- @@ -19,5 +19,5 @@ clean:
- rm -fv \
- winclonefile.i686.exe \
- winclonefile.x86_64.exe \
- - winclonefile.exe \
- + winclonefile.exe
- # EOF.
- diff --git a/tests/winfsinfo1/Makefile b/tests/winfsinfo1/Makefile
- index 6ef7039..7a529a6 100644
- --- a/tests/winfsinfo1/Makefile
- +++ b/tests/winfsinfo1/Makefile
- @@ -19,5 +19,5 @@ clean:
- rm -fv \
- winfsinfo.i686.exe \
- winfsinfo.x86_64.exe \
- - winfsinfo.exe \
- + winfsinfo.exe
- # EOF.
- diff --git a/tests/winsg/Makefile b/tests/winsg/Makefile
- index 19f96db..6c548ca 100644
- --- a/tests/winsg/Makefile
- +++ b/tests/winsg/Makefile
- @@ -19,5 +19,5 @@ clean:
- rm -fv \
- winsg.i686.exe \
- winsg.x86_64.exe \
- - winsg.exe \
- + winsg.exe
- # EOF.
- --
- 2.45.1
- From 4501f442aed934d4c7e39ffb5548266ff574b4a0 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Fri, 13 Jun 2025 15:05:17 +0200
- Subject: [PATCH 3/6] tests: Add test entry for directory ACL "X" flag
- Add test entry for directory ACL "X" flag.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- tests/manual_testing.txt | 11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
- diff --git a/tests/manual_testing.txt b/tests/manual_testing.txt
- index 29691e4..ea82965 100644
- --- a/tests/manual_testing.txt
- +++ b/tests/manual_testing.txt
- @@ -377,11 +377,18 @@ ksh93 -c 'rm -f test1.txt test2.txt aclspec.icacls aclspec2.icacls ; touch test1
- -------- snip --------
- #
- -# Test for "Generic Write" ACL:
- +# Test for file "Generic Write" ACL:
- #
- $ ksh93 -c 'set -o xtrace ; rm -f test1.txt ; touch test1.txt ; icacls test1.txt /grant "siegfried_wulsch:(GW)" ; icacls test1.txt | grep --colour -E "siegfried_wulsch.+GW"'
- # Expectation:
- -The ACL entry for user "siegfried_wulsch" should have the "GW" flag set
- +# The ACL entry for user "siegfried_wulsch" should have the "GW" flag set
- +
- +#
- +# Test for directory "X" ACL:
- +#
- +$ ksh93 -c 'set -o xtrace ; rm -rf test1.dir ; mkdir test1.dir ; icacls test1.dir /grant "siegfried_wulsch:(W,X)" ; icacls test1.dir | grep --colour -E "siegfried_wulsch.+X"'
- +# Expectation:
- +# The ACL entry for user "siegfried_wulsch" should have the "X" flag set
- #
- # Test for default (inheritance) ACLs:
- --
- 2.45.1
- From f71e60aa629ca308d286d03e978a4f4d1d4e5574 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Fri, 13 Jun 2025 16:08:45 +0200
- Subject: [PATCH 4/6] cygwin_idmapper.ksh: printf %q does not need to be in
- quotes
- printf %q does not need to be in quotes, because ksh93 printf %q
- already does quoting itself.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin_idmapper.ksh | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
- diff --git a/cygwin_idmapper.ksh b/cygwin_idmapper.ksh
- index 84686c2..e55fe96 100644
- --- a/cygwin_idmapper.ksh
- +++ b/cygwin_idmapper.ksh
- @@ -46,7 +46,7 @@ typeset -A c.localised_groupnames
- # versions use different values
- typeset machine_sid="$(mkgroup -l | sed -n 's/[^:]*:\(S-[-0-9]*\)-513:.*$/\1/p')"
- if [[ "$machine_sid" != ~(El)S-1-5-21- ]] ; then
- - print -u2 -f "%s: Unexpected machine SID '%q'\n" \
- + print -u2 -f "%s: Unexpected machine SID %q\n" \
- "$0" "$machine_sid"
- exit 1
- fi
- @@ -302,7 +302,7 @@ case "${c.mode}" in
- fi
- fi
- - print -u2 -f "cygwin_idmapper.ksh: Account '%q' not found.\n" "${c.name}"
- + print -u2 -f "cygwin_idmapper.ksh: Account %q not found.\n" "${c.name}"
- exit 1
- ;;
- 'nfsserver_owner_group2localgroup')
- @@ -341,7 +341,7 @@ case "${c.mode}" in
- fi
- fi
- - print -u2 -f "cygwin_idmapper.ksh: Group '%q' not found.\n" "${c.name}"
- + print -u2 -f "cygwin_idmapper.ksh: Group %q not found.\n" "${c.name}"
- exit 1
- ;;
- *)
- --
- 2.45.1
- From af233024aee6a489ab489b6bf83fe7b50f579168 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Fri, 13 Jun 2025 17:20:35 +0200
- Subject: [PATCH 5/6] daemon: |subcmd_popen()| should be able to pass arguments
- with non-ASCII characters to child processes
- |subcmd_popen()| should be able to pass arguments with non-ASCII characters
- to child processes.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/util.c | 22 +++++++++++++++++++---
- 1 file changed, 19 insertions(+), 3 deletions(-)
- diff --git a/daemon/util.c b/daemon/util.c
- index aa3883f..1317fbe 100644
- --- a/daemon/util.c
- +++ b/daemon/util.c
- @@ -424,7 +424,7 @@ out:
- subcmd_popen_context *subcmd_popen(const char *command)
- {
- subcmd_popen_context *pinfo;
- - STARTUPINFOA si;
- + STARTUPINFOW si;
- SECURITY_ATTRIBUTES sa = { 0 };
- if (!command) {
- @@ -483,8 +483,24 @@ subcmd_popen_context *subcmd_popen(const char *command)
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- si.dwFlags |= STARTF_USESTDHANDLES;
- - if (!CreateProcessA(NULL,
- - (LPSTR)command, NULL, NULL, TRUE, 0, NULL, NULL, &si,
- + size_t commandWSize = strlen(command)+1;
- + wchar_t *commandW = _alloca(commandWSize * sizeof(wchar_t));
- +
- + if (MultiByteToWideChar(CP_UTF8,
- + 0,
- + command,
- + -1,
- + commandW,
- + (int)commandWSize) == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + DPRINTF(0, ("subcmd_popen: cannot convert cmdline to widechar\n"));
- + goto fail;
- + }
- +
- + if (!CreateProcessW(NULL,
- + commandW, NULL, NULL, TRUE, 0, NULL, NULL, &si,
- &pinfo->pi)) {
- DPRINTF(0, ("subcmd_popen: cannot create process\n"));
- goto fail;
- --
- 2.45.1
- From fa71019ba355e9c604293f715248a5018bd2a2b1 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Fri, 13 Jun 2025 17:23:41 +0200
- Subject: [PATCH 6/6] daemon: Allow non-ASCII characters in Win32 user+group
- names
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Allow non-ASCII characters in Win32 user+group names, by converting
- the NFSv4 { owner, owner_group, ACL } UTF-8 strings from/to
- Win32 |wchar_t| strings, and use |LookupAccountSidW()| and
- |LookupAccountNameW()| instead of the Win32 codepage-specific
- |LookupAccountSidA()| and |LookupAccountNameA()|.
- Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
- Reported-by: Horacio Campoy Vidaña <horacio.campoy-vidana@rovema.de>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/accesstoken.c | 18 ++-
- daemon/acl.c | 16 +-
- daemon/nfs41_daemon.c | 4 +
- daemon/sid.c | 356 +++++++++++++++++++++++++++++++++++++++++-
- daemon/sid.h | 22 ++-
- 5 files changed, 393 insertions(+), 23 deletions(-)
- diff --git a/daemon/accesstoken.c b/daemon/accesstoken.c
- index 6432bdb..eae34c6 100644
- --- a/daemon/accesstoken.c
- +++ b/daemon/accesstoken.c
- @@ -72,10 +72,10 @@ bool get_token_user_name(HANDLE tok, char *out_buffer)
- }
- #endif /* NFS41_DRIVER_SID_CACHE */
- - if (!LookupAccountSidA(NULL, pusid, out_buffer, &namesize,
- + if (!lookupaccountsidutf8(NULL, pusid, out_buffer, &namesize,
- domainbuffer, &domainbuffer_size, &name_use)) {
- eprintf("get_token_user_name: "
- - "LookupAccountSidA() failed, status=%d\n",
- + "lookupaccountsidutf8() failed, status=%d\n",
- (int)GetLastError());
- return false;
- }
- @@ -116,10 +116,10 @@ bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
- }
- #endif /* NFS41_DRIVER_SID_CACHE */
- - if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
- + if (!lookupaccountsidutf8(NULL, pgsid, out_buffer, &namesize,
- domainbuffer, &domainbuffer_size, &name_use)) {
- eprintf("get_token_primarygroup_name: "
- - "LookupAccountSidA() failed, status=%d\n",
- + "lookupaccountsidutf8() failed, status=%d\n",
- (int)GetLastError());
- return false;
- }
- @@ -241,10 +241,14 @@ bool get_token_groups_names(HANDLE tok,
- namesize = sizeof(namebuffer)-1;
- domainbuffer_size = sizeof(domainbuffer)-1;
- - if (!LookupAccountSidA(NULL, ptgroups->Groups[i].Sid,
- - namebuffer, &namesize, domainbuffer, &domainbuffer_size, &name_use)) {
- + if (!lookupaccountsidutf8(NULL, ptgroups->Groups[i].Sid,
- + namebuffer,
- + &namesize,
- + domainbuffer,
- + &domainbuffer_size,
- + &name_use)) {
- DPRINTF(0, ("get_token_groups_names: "
- - "LookupAccountSidA() failed, status=%d.\n",
- + "lookupaccountsidutf8() failed, status=%d.\n",
- (int)GetLastError()));
- continue;
- }
- diff --git a/daemon/acl.c b/daemon/acl.c
- index ecf6156..45dda26 100644
- --- a/daemon/acl.c
- +++ b/daemon/acl.c
- @@ -1,5 +1,6 @@
- /* NFSv4.1 client for Windows
- - * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -987,8 +988,8 @@ int map_sid2nfs4ace_who(PSID sid, PSID owner_sid, PSID group_sid,
- goto out;
- }
- - status = LookupAccountSidA(NULL, sid, who_buf, &who_size, domain_buf,
- - &domain_size, &sid_type);
- + status = lookupaccountsidutf8(NULL, sid, who_buf, &who_size, domain_buf,
- + &domain_size, &sid_type);
- lasterr = GetLastError();
- if (status) {
- @@ -1074,14 +1075,15 @@ int map_sid2nfs4ace_who(PSID sid, PSID owner_sid, PSID group_sid,
- goto err_none_mapped;
- }
- - eprintf("map_sid2nfs4ace_who: LookupAccountSidA() "
- + eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
- "returned ERROR_NONE_MAPPED+no "
- "Unix_@(User|Group)+ mapping for sidstr='%s'\n",
- sidstr);
- err_none_mapped:
- status = ERROR_NONE_MAPPED;
- #else
- - DPRINTF(ACLLVL2, ("map_sid2nfs4ace_who: LookupAccountSidA() "
- + DPRINTF(ACLLVL2,
- + ("map_sid2nfs4ace_who: lookupaccountsidutf8() "
- "returned ERROR_NONE_MAPPED for sidstr='%s'\n",
- sidstr));
- status = lasterr;
- @@ -1091,7 +1093,7 @@ err_none_mapped:
- /* Catch other cases */
- case ERROR_NO_SUCH_USER:
- case ERROR_NO_SUCH_GROUP:
- - eprintf("map_sid2nfs4ace_who: LookupAccountSidA() "
- + eprintf("map_sid2nfs4ace_who: lookupaccountsidutf8() "
- "returned ERROR_NO_SUCH_@(USER|GROUP) for "
- "sidstr='%s'\n",
- sidstr);
- @@ -1099,7 +1101,7 @@ err_none_mapped:
- goto out;
- default:
- eprintf("map_sid2nfs4ace_who: Internal error, "
- - "LookupAccountSidA() returned unexpected ERROR_%d "
- + "lookupaccountsidutf8() returned unexpected ERROR_%d "
- "for sidstr='%s'\n",
- status, sidstr);
- status = ERROR_INTERNAL_ERROR;
- diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
- index 93d66b2..0fd2255 100644
- --- a/daemon/nfs41_daemon.c
- +++ b/daemon/nfs41_daemon.c
- @@ -792,6 +792,10 @@ VOID ServiceStart(DWORD argc, LPTSTR *argv)
- DPRINTF(0, ("SID cache disabled\n"));
- #endif /* NFS41_DRIVER_SID_CACHE */
- +#if 1
- + DPRINTF(0, ("wmain: GetACP()=%d\n", (int)GetACP()));
- +#endif
- +
- #ifdef _DEBUG
- logprintf("NFS client daemon (DEBUG build) %s starting...\n",
- GIT_COMMIT_ID);
- diff --git a/daemon/sid.c b/daemon/sid.c
- index 0ea20ee..0ce84f8 100644
- --- a/daemon/sid.c
- +++ b/daemon/sid.c
- @@ -1,5 +1,6 @@
- /* NFSv4.1 client for Windows
- - * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -327,7 +328,8 @@ void sidcache_addwithalias(sidcache *cache, const char *win32name, const char *a
- /* Replace the cache entry */
- sidcache_entry *e = &cache->entries[freeEntryIndex];
- DWORD sid_len = GetLengthSid(value);
- - EASSERT(sid_len <= SECURITY_MAX_SID_SIZE);
- + EASSERT_MSG((sid_len <= SECURITY_MAX_SID_SIZE),
- + ("sid_len=%ld\n", (long)sid_len));
- e->sid = (PSID)e->sid_buffer;
- if (!CopySid(sid_len, e->sid, value)) {
- e->sid = NULL;
- @@ -506,15 +508,15 @@ int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *si
- *sid_len = SECURITY_MAX_SID_SIZE;
- domain_len = sizeof(domain_buff);
- - status = LookupAccountNameA(NULL, nfsname, *sid, sid_len,
- + status = lookupaccountnameutf8(NULL, nfsname, *sid, sid_len,
- domain_buff, &domain_len, &sid_type);
- if (status) {
- - /* |LookupAccountNameA()| success */
- + /* |lookupaccountnameutf8()| success */
- DPRINTF(ACLLVL,
- ("map_nfs4servername_2_sid(query=0x%x,nfsname='%s'): "
- - "LookupAccountNameA() returned status=%d "
- + "lookupaccountnameutf8() returned status=%d "
- "GetLastError=%d *sid_len=%d domain_buff='%s' domain_len=%d\n",
- query, nfsname, status, GetLastError(), *sid_len, domain_buff,
- domain_len));
- @@ -524,10 +526,10 @@ int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *si
- goto out_cache;
- }
- - /* |LookupAccountNameA()| failed... */
- + /* |lookupaccountnameutf8()| failed... */
- DPRINTF(ACLLVL,
- ("map_nfs4servername_2_sid(query=0x%x,nfsname='%s'): "
- - "LookupAccountNameA() returned status=%d "
- + "lookupaccountnameutf8() returned status=%d "
- "GetLastError=%d\n",
- query, nfsname, status, GetLastError()));
- @@ -648,7 +650,7 @@ out_cache:
- /*
- * Treat |SidTypeAlias| as (local) group
- *
- - * It seems that |LookupAccountNameA()| will always return
- + * It seems that |lookupaccountnameutf8()| will always return
- * |SidTypeAlias| for local groups created with
- * $ net localgroup cygwingrp1 /add #
- *
- @@ -743,3 +745,341 @@ out_free_sid:
- *sid = NULL;
- goto out;
- }
- +
- +
- +/* Maximum number of bytes required to store one |wchar_t| as UTF-8 */
- +#define MAX_UTF8_BYTES_PER_WCHAR_T (5)
- +
- +/*
- + * |lookupaccountnameutf8()| - UTF-8 version of |LookupAccountNameA()|
- + *
- + * We need this because Windows user+group names can contain Unicode
- + * characters, and |*A()| functions depend on the current code page,
- + * which might not cover all code points needed
- + */
- +BOOL lookupaccountnameutf8(
- + const char *restrict pSystemNameUTF8,
- + const char *restrict pAccountNameUTF8,
- + PSID restrict pSid,
- + LPDWORD restrict pSidSize,
- + char *restrict pReferencedDomainNameUTF8,
- + LPDWORD restrict pReferencedDomainNameUTF8size,
- + PSID_NAME_USE restrict peUse)
- +{
- +#ifdef NO_UTF8_ACCOUNT_CONV
- + return LookupAccountNameA(
- + pSystemNameUTF8,
- + pAccountNameUTF8,
- + pSid,
- + pSidSize,
- + pReferencedDomainNameUTF8,
- + pReferencedDomainNameUTF8size,
- + peUse);
- +#else
- + if ((pAccountNameUTF8 == NULL) ||
- + (pReferencedDomainNameUTF8size == NULL) ||
- + (pSidSize == NULL) || (peUse == NULL)) {
- + SetLastError(ERROR_INVALID_PARAMETER);
- + return FALSE;
- + }
- +
- + LPWSTR pSystemNameW;
- +
- + if (pSystemNameUTF8) {
- + DWORD systemNameWsize;
- +
- + /*
- + * Use |strlen()| here as optimisation, saving one around of
- + * |MultiByteToWideChar()|
- + */
- + systemNameWsize = (DWORD)strlen(pSystemNameUTF8)+1;
- + pSystemNameW = (LPWSTR)_alloca(systemNameWsize * sizeof(wchar_t));
- +
- + if (MultiByteToWideChar(CP_UTF8,
- + 0,
- + pSystemNameUTF8,
- + -1,
- + pSystemNameW,
- + systemNameWsize) == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- + }
- + else {
- + pSystemNameW = NULL;
- + }
- +
- + LPWSTR pAccountNameW;
- + DWORD accountNameWsize;
- +
- + /*
- + * Use |strlen()| here as optimisation, saving one around of
- + * |MultiByteToWideChar()|
- + */
- + accountNameWsize = (DWORD)strlen(pAccountNameUTF8)+1;
- + pAccountNameW = (LPWSTR)_alloca(accountNameWsize * sizeof(wchar_t));
- +
- + if (MultiByteToWideChar(CP_UTF8,
- + 0,
- + pAccountNameUTF8,
- + -1,
- + pAccountNameW,
- + accountNameWsize) == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + DWORD referencedDomainNameWsize =
- + (DWORD)*pReferencedDomainNameUTF8size / sizeof(wchar_t);
- + LPWSTR pReferencedDomainNameW = NULL;
- +
- + if ((pReferencedDomainNameUTF8 == NULL) ||
- + (*pReferencedDomainNameUTF8size == 0)) {
- + referencedDomainNameWsize = 256;
- + }
- +
- + pReferencedDomainNameW =
- + (LPWSTR)_alloca(referencedDomainNameWsize * sizeof(wchar_t));
- +
- + BOOL success = LookupAccountNameW(
- + pSystemNameW,
- + pAccountNameW,
- + pSid,
- + pSidSize,
- + pReferencedDomainNameW,
- + &referencedDomainNameWsize,
- + peUse);
- +
- + if (!success) {
- + DWORD lastError = GetLastError();
- +
- + if (lastError == ERROR_INSUFFICIENT_BUFFER) {
- + int requiredDomainNameUTF8Size = WideCharToMultiByte(CP_UTF8,
- + 0,
- + pReferencedDomainNameW,
- + referencedDomainNameWsize+1,
- + NULL,
- + 0,
- + NULL,
- + NULL);
- + if (requiredDomainNameUTF8Size == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + *pReferencedDomainNameUTF8size =
- + (size_t)requiredDomainNameUTF8Size+1;
- + } else if (lastError == ERROR_NONE_MAPPED) {
- + *pReferencedDomainNameUTF8size = 0;
- + *pSidSize = 0;
- + *peUse = SidTypeUnknown;
- + } else {
- + *pReferencedDomainNameUTF8size = 0;
- + *pSidSize = 0;
- + *peUse = SidTypeUnknown;
- + }
- +
- + return FALSE;
- + }
- +
- + int domainNameUTF8size = WideCharToMultiByte(CP_UTF8,
- + 0,
- + pReferencedDomainNameW,
- + referencedDomainNameWsize+1,
- + NULL,
- + 0,
- + NULL,
- + NULL);
- + if (domainNameUTF8size == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + if (*pReferencedDomainNameUTF8size < (size_t)domainNameUTF8size) {
- + *pReferencedDomainNameUTF8size = (size_t)domainNameUTF8size;
- + SetLastError(ERROR_INSUFFICIENT_BUFFER);
- + return FALSE;
- + }
- +
- + (void)WideCharToMultiByte(CP_UTF8,
- + 0,
- + pReferencedDomainNameW,
- + referencedDomainNameWsize+1,
- + pReferencedDomainNameUTF8,
- + domainNameUTF8size,
- + NULL,
- + NULL);
- + *pReferencedDomainNameUTF8size = (size_t)domainNameUTF8size-1;
- +
- + SetLastError(ERROR_SUCCESS);
- + return TRUE;
- +#endif /* NO_UTF8_ACCOUNT_CONV */
- +}
- +
- +
- +/*
- + * |lookupaccountsidutf8()| - UTF-8 version of |LookupAccountSidA()|
- + *
- + * We need this because Windows user+group names can contain Unicode
- + * characters, and |*A()| functions depend on the current code page,
- + * which might not cover all code points needed
- + */
- +BOOL lookupaccountsidutf8(
- + const char *restrict pSystemNameUTF8,
- + PSID restrict Sid,
- + char *restrict pNameUTF8,
- + LPDWORD restrict pNameSize,
- + char *restrict pReferencedDomainNameUTF8,
- + LPDWORD restrict pReferencedDomainNameUTF8Size,
- + PSID_NAME_USE restrict peUse)
- +{
- +#ifdef NO_UTF8_ACCOUNT_CONV
- + return LookupAccountSidA(pSystemNameUTF8,
- + Sid, pNameUTF8, pNameSize,
- + pReferencedDomainNameUTF8, pReferencedDomainNameUTF8Size,
- + peUse);
- +#else
- + if ((Sid == NULL) ||
- + (pNameUTF8 == NULL) ||
- + (pNameSize == NULL) ||
- + (pReferencedDomainNameUTF8 == NULL) ||
- + (pReferencedDomainNameUTF8Size == NULL) ||
- + (peUse == NULL)) {
- + SetLastError(ERROR_INVALID_PARAMETER);
- + return FALSE;
- + }
- +
- + wchar_t *systemNameW;
- + wchar_t *nameW;
- + wchar_t *referencedDomainNameW;
- +
- + if (pSystemNameUTF8) {
- + DWORD wide_len = (DWORD)strlen(pSystemNameUTF8)+1;
- +
- + systemNameW = (wchar_t *)_alloca(wide_len * sizeof(wchar_t));
- +
- + if (MultiByteToWideChar(CP_UTF8,
- + 0,
- + pSystemNameUTF8,
- + -1,
- + systemNameW,
- + wide_len) == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- + }
- + else {
- + systemNameW = NULL;
- + }
- +
- + nameW = (wchar_t *)_alloca(((size_t)*pNameSize+1) * sizeof(wchar_t));
- + referencedDomainNameW =
- + (wchar_t *)_alloca(((size_t)*pReferencedDomainNameUTF8Size+1) *
- + sizeof(wchar_t));
- +
- + DWORD nameSizeW = *pNameSize;
- + DWORD referencedDomainNameSizeW =
- + *pReferencedDomainNameUTF8Size;
- +
- + if (!LookupAccountSidW(
- + systemNameW,
- + Sid,
- + nameW,
- + &nameSizeW,
- + referencedDomainNameW,
- + &referencedDomainNameSizeW,
- + peUse))
- + {
- + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- + /* Assume that each |wchar_t| needs a maximum of 5 bytes */
- + *pNameSize = nameSizeW * MAX_UTF8_BYTES_PER_WCHAR_T;
- + *pReferencedDomainNameUTF8Size =
- + referencedDomainNameSizeW * MAX_UTF8_BYTES_PER_WCHAR_T;
- + }
- + return FALSE;
- + }
- +
- + int required_name_utf8_bytes = WideCharToMultiByte(CP_UTF8,
- + 0,
- + nameW,
- + nameSizeW+1,
- + NULL,
- + 0,
- + NULL,
- + NULL);
- + if (required_name_utf8_bytes == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + int required_domain_utf8_bytes = WideCharToMultiByte(CP_UTF8,
- + 0,
- + referencedDomainNameW,
- + referencedDomainNameSizeW+1,
- + NULL,
- + 0,
- + NULL,
- + NULL);
- + if (required_domain_utf8_bytes == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + if ((*pNameSize < (DWORD)required_name_utf8_bytes) ||
- + (*pReferencedDomainNameUTF8Size < (DWORD)required_domain_utf8_bytes)) {
- + *pNameSize = (DWORD)required_name_utf8_bytes;
- + *pReferencedDomainNameUTF8Size = (DWORD)required_domain_utf8_bytes;
- + SetLastError(ERROR_INSUFFICIENT_BUFFER);
- + return FALSE;
- + }
- +
- + int bytes_written_name = WideCharToMultiByte(CP_UTF8,
- + 0,
- + nameW,
- + nameSizeW+1,
- + pNameUTF8,
- + *pNameSize,
- + NULL,
- + NULL);
- + if (bytes_written_name == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + int bytes_written_domain = WideCharToMultiByte(CP_UTF8,
- + 0,
- + referencedDomainNameW,
- + referencedDomainNameSizeW+1,
- + pReferencedDomainNameUTF8,
- + *pReferencedDomainNameUTF8Size,
- + NULL,
- + NULL);
- + if (bytes_written_domain == 0) {
- + if (GetLastError() == ERROR_SUCCESS) {
- + SetLastError(ERROR_INVALID_DATA);
- + }
- + return FALSE;
- + }
- +
- + *pReferencedDomainNameUTF8Size = (DWORD)bytes_written_domain-1;
- + *pNameSize = (DWORD)bytes_written_name-1;
- +
- + return TRUE;
- +#endif /* NO_UTF8_ACCOUNT_CONV */
- +}
- diff --git a/daemon/sid.h b/daemon/sid.h
- index 70fc910..c19b3d9 100644
- --- a/daemon/sid.h
- +++ b/daemon/sid.h
- @@ -1,6 +1,7 @@
- /* NFSv4.1 client for Windows
- - * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -64,4 +65,23 @@ bool sidcache_getcached_bysid(sidcache *cache, PSID sid, char *out_win32name);
- int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *sid_len, PSID *sid, LPCSTR name);
- +/* UTF-8 version of |LookupAccountNameA()| */
- +BOOL lookupaccountnameutf8(
- + const char *restrict pSystemNameUTF8,
- + const char *restrict pAccountNameUTF8,
- + PSID restrict pSid,
- + LPDWORD restrict pSidSize,
- + char *restrict pReferencedDomainNameUTF8,
- + LPDWORD restrict pReferencedDomainNameUTF8size,
- + PSID_NAME_USE restrict peUse);
- +/* UTF-8 version of |LookupAccountSidA()| */
- +BOOL lookupaccountsidutf8(
- + const char *restrict pSystemNameUTF8,
- + PSID restrict Sid,
- + char *restrict pNameUTF8,
- + LPDWORD restrict pNameSize,
- + char *restrict pReferencedDomainNameUTF8,
- + LPDWORD restrict pReferencedDomainNameSize,
- + PSID_NAME_USE restrict peUse);
- +
- #endif /* !__NFS41_DAEMON_SID_H */
- --
- 2.45.1
msnfs41client: Patch for non-ASCII characters in Win32 user+group names+misc, 2025-06-13
Posted by Anonymous on Fri 13th Jun 2025 16:41
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.