Let's use the Win32 API more precisely
cover Let's use the Win32 API more precisely
For many Win32 functions, there actually exist two variants: one that takes const char * ("ANSI", meaning the current code page) and wchar_t * ("Unicode", i.e. UTF-16, at least for all practical matters).
These functions have "A" and "W" suffixes, respectively, e.g. GetFileAttributesW(). The symbols without this suffix are #defined to the *W() versions if the constant UNICODE is defined before including the Windows headers, and to *A() otherwise.
Let's not rely on this constant, but explicitly say what we want: we want the Unicode versions, as they seem to be used by the ANSI flavor anyway.
Johannes Schindelin (2):
mingw: get pw_name in UTF-8 format
mingw: use Unicode functions explicitly
compat/mingw.c | 12 +++++++++--- compat/poll/poll.c | 2 +- compat/winansi.c | 10 ++++++---- 3 files changed, 16 insertions(+), 8 deletions(-)
base-commit: aa25c82427ae70aebf3b8f970f2afd54e9a2a8c6
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-147%2Fdscho%2Fansi-unicode-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-147/dscho/ansi-unicode-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/147
Signature · 1 line
gitgitgadget
PATCH 1/2 mingw: get pw_name in UTF-8 format
From: Johannes Schindelin <[email protected]>
Previously, we would have obtained the user name encoded in whatever the current code page is.
Note: the "user name" here does not denote the full name but instead the short logon name.
--- compat/mingw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
compat/mingw.c +8 -2
@@ -1946,13 +1946,19 @@ struct passwd *getpwuid(int uid)static unsigned initialized;static char user_name[100 ];static struct passwd *p; +wchar_t buf[100 ];DWORD len;if (initialized)return p; - len =sizeof (user_name); -if (!GetUserName (user_name, &len)) { + len =sizeof (buf); +if (!GetUserNameW (buf, &len)) { + initialized =1 ; +return NULL ; + } + +if (xwcstoutf (user_name, buf,sizeof (user_name)) <0 ) { initialized =1 ;return NULL ; }
Signature · 1 line
gitgitgadget
Re: [PATCH 1/2] mingw: get pw_name in UTF-8 format
Quoted 20 lines · Johannes Schindelin via GitGitGadget
From: Johannes Schindelin <[email protected]>
Previously, we would have obtained the user name encoded in whatever the current code page is.
Note: the "user name" here does not denote the full name but instead the short logon name.
Signed-off-by Johannes Schindelin <[email protected]>--- compat/mingw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)compat/mingw.c +0
-0@@ -1946,13 +1946,19 @@ struct passwd *getpwuid(int uid)static unsigned initialized;static char user_name[100 ];
compat/mingw.c struct passwd *getpwuid(int uid) · line 1955
Quoted 10 lines
compat/mingw.c +2
-2static struct passwd *p; +wchar_t buf[100 ];DWORD len;if (initialized)return p; - len =sizeof (user_name); -if (!GetUserName (user_name, &len)) { + len =sizeof (buf);
I think this should be "len = sizeof(buf) / sizeof(buf[0])".
GetUserNameW() takes the number of characters, not bytes.
compat/mingw.c struct passwd *getpwuid(int uid) · line 1964
Quoted 10 lines
compat/mingw.c +6
-0+if (!GetUserNameW (buf, &len)) { + initialized =1 ; +return NULL ; + } + +if (xwcstoutf (user_name, buf,sizeof (user_name)) <0 ) { initialized =1 ;return NULL ; }
Cheers,
Beat
Re: [PATCH 1/2] mingw: get pw_name in UTF-8 format
Hi Beat,
Quoted 28 lines · Beat Bolli
Quoted 27 lines · Johannes Schindelin via GitGitGadget
From: Johannes Schindelin <[email protected]>
Previously, we would have obtained the user name encoded in whatever the current code page is.
Note: the "user name" here does not denote the full name but instead the short logon name.
Signed-off-by Johannes Schindelin <[email protected]>--- compat/mingw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)compat/mingw.c +1
-0@@ -1946,13 +1946,19 @@ struct passwd *getpwuid(int uid)static unsigned initialized;static char user_name[100 ];static struct passwd *p; +wchar_t buf[100 ];DWORD len;if (initialized)return p;
Quoted 7 lines
compat/mingw.c struct passwd *getpwuid(int uid) · line 1955
Quoted 3 lines
compat/mingw.c +1
-2- len =sizeof (user_name); -if (!GetUserName (user_name, &len)) { + len =sizeof (buf);I think this should be "len = sizeof(buf) /
sizeof(buf[0])".
GetUserNameW()takes the number of characters, not bytes.
Good catch.
How about I use ARRAY_SIZE(buf)? Since this is already in next, I will prepare a follow-up patch.
Ciao,
Dscho
Quoted 15 lines
compat/mingw.c struct passwd *getpwuid(int uid) · line 1964
Quoted 11 lines
compat/mingw.c +6
-0+if (!GetUserNameW (buf, &len)) { + initialized =1 ; +return NULL ; + } + +if (xwcstoutf (user_name, buf,sizeof (user_name)) <0 ) { initialized =1 ;return NULL ; }Cheers,
Beat
Re: [PATCH 1/2] mingw: get pw_name in UTF-8 format
Hi Dscho
Quoted 38 lines · Johannes Schindelin
Hi Beat,
Quoted 34 lines · Beat Bolli
Quoted 20 lines · Johannes Schindelin via GitGitGadget
From: Johannes Schindelin <[email protected]>
Previously, we would have obtained the user name encoded in whatever the current code page is.
Note: the "user name" here does not denote the full name but instead the short logon name.
Signed-off-by Johannes Schindelin <[email protected]>--- compat/mingw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)compat/mingw.c +0
-0@@ -1946,13 +1946,19 @@ struct passwd *getpwuid(int uid)static unsigned initialized;static char user_name[100 ];compat/mingw.c struct passwd *getpwuid(int uid) · line 1955
Quoted 10 lines
compat/mingw.c +2
-2static struct passwd *p; +wchar_t buf[100 ];DWORD len;if (initialized)return p; - len =sizeof (user_name); -if (!GetUserName (user_name, &len)) { + len =sizeof (buf);I think this should be "len = sizeof(buf) /
sizeof(buf[0])".
Quoted 6 lines
Quoted 1 line
GetUserNameW()takes the number of characters, not bytes.Good catch.
How about I use
ARRAY_SIZE(buf)? Since this is already innext, I will prepare a follow-up patch.
Of course, ARRAY_SIZE() is even better. I didn't remember it existed.
Cheers,
Beat
Quoted 19 lines
Ciao,
DschoQuoted 15 lines
compat/mingw.c struct passwd *getpwuid(int uid) · line 1964
Quoted 11 lines
compat/mingw.c +6
-0+if (!GetUserNameW (buf, &len)) { + initialized =1 ; +return NULL ; + } + +if (xwcstoutf (user_name, buf,sizeof (user_name)) <0 ) { initialized =1 ;return NULL ; }Cheers,
Beat
PATCH 2/2 mingw: use Unicode functions explicitly
In reply to Johannes Schindelin via GitGitGadgetFrom: Johannes Schindelin <[email protected]>
Many Win32 API functions actually exist in two variants: one with the A suffix that takes ANSI parameters (char * or const char *) and one with the W suffix that takes Unicode parameters (wchar_t * or const wchar_t *).
The ANSI variant assumes that the strings are encoded according to whatever is the current locale. This is not what Git wants to use on
Windows: we assume that char * variables point to strings encoded in UTF-8.
There is a pseudo UTF-8 locale on Windows, but it does not work as one might expect. In addition, if we overrode the user's locale, that would modify the behavior of programs spawned by Git (such as editors, difftools, etc), therefore we cannot use that pseudo locale.
Further, it is actually highly encouraged to use the Unicode versions instead of the ANSI versions, so let's do precisely that.
Note: when calling the Win32 API functions _without_ any suffix, it depends whether the UNICODE constant is defined before the relevant headers are #include'd. Without that constant, the ANSI variants are used. Let's be explicit and avoid that ambiguity.
--- compat/mingw.c | 2 +- compat/poll/poll.c | 2 +- compat/winansi.c | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-)
compat/mingw.c +1 -1
@@ -1407,7 +1407,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaendo_unset_environment_variables ();/* Determine whether or not we are associated to a console */ - cons =CreateFile ("CONOUT$" ,GENERIC_WRITE , + cons =CreateFileW (L"CONOUT$" ,GENERIC_WRITE ,FILE_SHARE_WRITE ,NULL ,OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL ,NULL );if (cons ==INVALID_HANDLE_VALUE ) {
compat/poll/poll.c +1 -1
@@ -150,7 +150,7 @@ win32_compute_revents (HANDLE h, int *p_sought)if (!once_only) { NtQueryInformationFile = (PNtQueryInformationFile ) -GetProcAddress (GetModuleHandle ("ntdll.dll" ), +GetProcAddress (GetModuleHandleW (L"ntdll.dll" ),"NtQueryInformationFile" ); once_only = TRUE; }
compat/winansi.c +6 -4
@@ -599,7 +599,7 @@ int winansi_isatty(int fd)void winansi_init (void ) {int con1, con2; -char name[32 ]; +wchar_t name[32 ];/* check if either stdout or stderr is a console output screen buffer */ con1 =is_console (1 );
@@ -619,13 +619,15 @@ void winansi_init(void) }/* create a named pipe to communicate with the console thread */ -xsnprintf (name,sizeof (name),"\\\\.\\pipe\\winansi%lu" ,GetCurrentProcessId ()); - hwrite =CreateNamedPipe (name,PIPE_ACCESS_OUTBOUND , +if (swprintf (name,ARRAY_SIZE (name) -1 ,L"\\\\.\\pipe\\winansi%lu" , +GetCurrentProcessId ()) <0 ) +die ("Could not initialize winansi pipe name" ); + hwrite =CreateNamedPipeW (name,PIPE_ACCESS_OUTBOUND ,PIPE_TYPE_BYTE |PIPE_WAIT ,1 ,BUFFER_SIZE ,0 ,0 ,NULL );if (hwrite ==INVALID_HANDLE_VALUE )die_lasterr ("CreateNamedPipe failed" ); - hread =CreateFile (name,GENERIC_READ ,0 ,NULL ,OPEN_EXISTING ,0 ,NULL ); + hread =CreateFileW (name,GENERIC_READ ,0 ,NULL ,OPEN_EXISTING ,0 ,NULL );if (hread ==INVALID_HANDLE_VALUE )die_lasterr ("CreateFile for named pipe failed" );
Signature · 1 line
gitgitgadget
Re: [PATCH 2/2] mingw: use Unicode functions explicitly
Quoted 5 lines · Johannes Schindelin via GitGitGadget
Many Win32 API functions actually exist in two variants: one with the
Asuffix that takes ANSI parameters (char *orconst char *) and one with theWsuffix that takes Unicode parameters (wchar_t *orconst wchar_t *).
Quoted 7 lines
The ANSI variant assumes that the strings are encoded according to whatever is the current locale. This is not what Git wants to use on
Windows: we assume thatchar *variables point to strings encoded in UTF-8.There is a pseudo UTF-8 locale on Windows, but it does not work as one might expect.
What does "does not work as one might expect" mean? The reader is left hanging, not knowing why or how the UTF-8 locale on Windows is undesirable.
Quoted 13 lines
In addition, if we overrode the user's locale, that
would modify the behavior of programs spawned by Git (such as editors, difftools, etc), therefore we cannot use that pseudo locale.Further, it is actually highly encouraged to use the Unicode versions instead of the ANSI versions, so let's do precisely that.
Note: when calling the Win32 API functions _without_ any suffix, it depends whether the
UNICODEconstant is defined before the relevant headers are #include'd. Without that constant, the ANSI variants are used. Let's be explicit and avoid that ambiguity.Signed-off-by Johannes Schindelin <[email protected]>
Re: [PATCH 2/2] mingw: use Unicode functions explicitly
Hi Eric,
Quoted 12 lines · Eric Sunshine
Quoted 10 lines · Johannes Schindelin via GitGitGadget
Many Win32 API functions actually exist in two variants: one with the
Asuffix that takes ANSI parameters (char *orconst char *) and one with theWsuffix that takes Unicode parameters (wchar_t *orconst wchar_t *).The ANSI variant assumes that the strings are encoded according to whatever is the current locale. This is not what Git wants to use on
Windows: we assume thatchar *variables point to strings encoded in UTF-8.
Quoted 6 lines
Quoted 2 lines
There is a pseudo UTF-8 locale on Windows, but it does not work as one might expect.
What does "does not work as one might expect" mean? The reader is left hanging, not knowing why or how the UTF-8 locale on Windows is undesirable.
Should I really bore the reader with half-details? At least one of those behaviors was reported as an unbootable Windows 7, but some others could not reproduce.
I really did not want to write a novel here that is 1) largely irrelevant and 2) would take way too long to write because I forgot most of the details and would have to look them up again.
Hopefully we can do without the full story here, as even one report that it does not work as expected is enough to make this an unfeasible option for us, and that's that as far as I am concerned.
Ciao,
Dscho
Quoted 15 lines
Quoted 14 lines
In addition, if we overrode the user's locale, that
would modify the behavior of programs spawned by Git (such as editors, difftools, etc), therefore we cannot use that pseudo locale.Further, it is actually highly encouraged to use the Unicode versions instead of the ANSI versions, so let's do precisely that.
Note: when calling the Win32 API functions _without_ any suffix, it depends whether the
UNICODEconstant is defined before the relevant headers are #include'd. Without that constant, the ANSI variants are used. Let's be explicit and avoid that ambiguity.Signed-off-by Johannes Schindelin <[email protected]>