-
Notifications
You must be signed in to change notification settings - Fork 560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetEnvironmentStrings() mess up the values for non-ascii strings #12161
Comments
From karthik.rajagopalan@schrodinger.comHi, Before launching a sub-process using win32_spawnvp of win32.c, we try You will observe this issue in all versions of perl including 5.17 of To reproduce the issue, following the below recipe - 0) Create a user account in windows with non-ascii character, say bærbar The program should successfully launch test1.exe and get the The ANSI code page of my system while doing this test is My System Details Flags: Site configuration information for perl 5.14.2: Configured by rajagopa at Wed May 23 12:48:29 2012. Summary of my perl5 (revision 5 version 14 subversion 2) configuration: Platform: Locally applied patches: @INC for perl 5.14.2: Environment for perl 5.14.2: |
From karthik.rajagopalan@schrodinger.comcl.exe /c /MD test1.c |
From karthik.rajagopalan@schrodinger.com#include <stdio.h>
#include <Shlobj.h>
#include <windows.h>
int main()
{
char local_appdata_path[1024];
printf("ACP %d\n", GetACP());
printf("OEMCP %d\n", GetOEMCP());
if( SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL,
SHGFP_TYPE_CURRENT, local_appdata_path) < 0 )
{
puts("Failed to get CSIDL_LOCAL_APPDATA of user");
}
else {
puts("success in getting CSIDL_LOCAL_APPDATA of user");
}
} |
From karthik.rajagopalan@schrodinger.com0001-Use-GetEnvironmentStringsW-.-instead-of-GetEnvironme.patchFrom 011f192c113c53705f2bab641e12e37c747a8146 Mon Sep 17 00:00:00 2001
From: Karthik Rajagopalan <rajagopa@schrodinger.com>
Date: Wed, 6 Jun 2012 17:05:11 -0400
Subject: [PATCH] Use GetEnvironmentStringsW(..) instead of
GetEnvironmentStringsA(..)
GetEnvironmentStringsA(..) return strings in the OEM code page. This
can actually mangle the environment strings if if contain special characters.
A better approach would be to get the utf-16 strings through GetEnvironmentStringsW(..)
and convert them to ANSI code page.
---
win32/perlhost.h | 45 ++++++++++++++++++++++++++++++++++++++-------
1 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/win32/perlhost.h b/win32/perlhost.h
index e8f5fb4..244c4ac 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -2258,11 +2258,26 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
{
dTHX;
LPSTR lpStr, lpPtr, lpEnvPtr, lpTmp, lpLocalEnv, lpAllocPtr;
- DWORD dwSize, dwEnvIndex;
+ LPWSTR lpWAllocPtr, lpWTmp;
+ DWORD dwSize, dwEnvIndex, ansienv_size;
int nLength, compVal;
- // get the process environment strings
- lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings();
+ // Get the process environment strings
+ lpWAllocPtr = lpWTmp = (LPWSTR) GetEnvironmentStringsW();
+ for(dwSize = 1; *lpWTmp != '\0'; lpWTmp += wcslen(lpWTmp) + 1) {
+ // calculate the size of the environment strings
+ dwSize += wcslen(lpWTmp) + 1;
+ }
+
+ /* Get the number of bytes required to store the UTF16 encoded string */
+ ansienv_size = WideCharToMultiByte(CP_ACP, 0, lpWAllocPtr, dwSize, NULL, 0, 0, 0);
+ lpAllocPtr = lpTmp = (char *)calloc(ansienv_size, sizeof(char));
+
+ /* Convert the string from UTF-16 encoding to ANSI encoding */
+ WideCharToMultiByte(CP_ACP, 0, lpWAllocPtr, dwSize, lpTmp, ansienv_size, 0, 0);
+
+ // release the process environment strings
+ FreeEnvironmentStringsW(lpWAllocPtr);
// step over current directory stuff
while(*lpTmp == '=')
@@ -2337,8 +2352,6 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
*lpStr = '\0';
}
- // release the process environment strings
- FreeEnvironmentStrings(lpAllocPtr);
return lpPtr;
}
@@ -2364,6 +2377,10 @@ CPerlHost::Clearenv(void)
dTHX;
char ch;
LPSTR lpPtr, lpStr, lpEnvPtr;
+ LPWSTR lpWStr, lpWEnvPtr;
+ DWORD ansienv_size = 0;
+ DWORD dwSize = 0;
+
if (m_lppEnvList != NULL) {
/* set every entry to an empty string */
for(DWORD index = 0; index < m_dwEnvCount; ++index) {
@@ -2374,8 +2391,22 @@ CPerlHost::Clearenv(void)
}
}
- /* get the process environment strings */
- lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings();
+ /* Get the process environment strings */
+ lpWStr = lpWEnvPtr = (LPWSTR) GetEnvironmentStringsW();
+ for(dwSize = 1; *lpWEnvPtr != '\0'; lpWEnvPtr += wcslen(lpWEnvPtr) + 1) {
+ // calculate the size of the environment strings
+ dwSize += wcslen(lpWEnvPtr) + 1;
+ }
+
+ /* Get the number of bytes required to store the UTF16 encoded string */
+ ansienv_size = WideCharToMultiByte(CP_ACP, 0, lpWStr, dwSize, NULL, 0, 0, 0);
+ lpStr = lpEnvPtr = (char *)calloc(ansienv_size, sizeof(char));
+
+ /* Convert the string from UTF-16 encoding to ANSI encoding */
+ WideCharToMultiByte(CP_ACP, 0, lpWStr, dwSize, lpStr, ansienv_size, 0, 0);
+
+ /* Free environment strings */
+ FreeEnvironmentStringsW(lpWStr);
/* step over current directory stuff */
while(*lpStr == '=')
--
1.7.7.1
|
From @bulk88First issue, why are there 2 wcslens for the same data in the loop? Second issue, I'm not sure what the Perl Interp's standards are for the |
The RT System itself - Status changed from 'new' to 'open' |
From karthik.rajagopalan@schrodinger.comOn Thu Jun 07 08:41:48 2012, bulk88. wrote:
I just maintained the same way it was handled earlier for
That would require a huge change in other functions AFAIK. This is the -Karthik |
From karthik.rajagopalan@schrodinger.comBTW, I need free ascii encdoing strings once they are processed. Once I -Karthik On Thu Jun 07 08:49:05 2012, kartlee05 wrote:
|
From @steve-m-hayOn 6 June 2012 22:59, Karthik Rajagopalan <perlbug-followup@perl.org> wrote:
Thanks for the report. I have reproduced this with bleadperl and am - You've added a large duplicated block of code in place of what was - Where do you free() the memory that was calloc()ed? If you factor - Is calloc() definitely the right thing to call? I'm wondering if it - Perhaps your WideCharToMultiByte() calls should make use of the |
From karthik.rajagopalan@schrodinger.comHi Steve,
Sounds good.
Just before the function CreateLocalEnvironmentStrings(..) and // release the ANSI encoding process environment strings // for Clearenv(..) You suggestion of moving to a separate function for caller to use,
win32_calloc(..) in turn call calloc(..) ( see win32.c ). I can make use
Since we are not going to deal just with PATH in environment strings, do I will submit a patch based on your suggestion by today. BTW, did you get a chance to try with my patch? Did it solve the issue? -Karthik |
From @steve-m-hayOn 7 June 2012 23:20, Karthik Rajagopalan via RT
I was thinking about things in the environment (like usernames!...)
Yes, your patch fixed the problem for me. Looking forward to a revised |
From karthik.rajagopalan@schrodinger.comHi Shay, On Fri Jun 08 13:17:34 2012, shay wrote:
I was thinking for env other than username. This could have been taken by
I now have your comments incorporated in my attached patch. Please go- -Karthik |
From karthik.rajagopalan@schrodinger.com0001-Use-GetEnvironmentStringsW-.-instead-of-GetEnvironme.patchFrom bb7c5e61c26c2634be8e508bf0514f48056b54a9 Mon Sep 17 00:00:00 2001
From: Karthik Rajagopalan <rajagopa@schrodinger.com>
Date: Mon, 11 Jun 2012 15:50:34 -0400
Subject: [PATCH] Use GetEnvironmentStringsW(..) instead of
GetEnvironmentStringsA(..).
GetEnvironmentStringsA(..) return strings in the OEM code page. This
can actually mangle the environment strings if it contain special characters.
A better approach would be to get the utf-16 strings through GetEnvironmentStringsW(..)
and convert them to ANSI code page. This is now done by win32_getenvironmentstrings(..).
To free the block, you can use win32_freeenvironmentstrings(..).
---
win32/perlhost.h | 8 ++++----
win32/win32.c | 34 ++++++++++++++++++++++++++++++++++
win32/win32iop.h | 2 ++
3 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/win32/perlhost.h b/win32/perlhost.h
index e8f5fb4..ae422ef 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -2262,7 +2262,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
int nLength, compVal;
// get the process environment strings
- lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings();
+ lpAllocPtr = lpTmp = (LPSTR)win32_getenvironmentstrings();
// step over current directory stuff
while(*lpTmp == '=')
@@ -2338,7 +2338,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
}
// release the process environment strings
- FreeEnvironmentStrings(lpAllocPtr);
+ win32_freeenvironmentstrings(lpAllocPtr);
return lpPtr;
}
@@ -2375,7 +2375,7 @@ CPerlHost::Clearenv(void)
}
/* get the process environment strings */
- lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings();
+ lpStr = lpEnvPtr = (LPSTR)win32_getenvironmentstrings();
/* step over current directory stuff */
while(*lpStr == '=')
@@ -2394,7 +2394,7 @@ CPerlHost::Clearenv(void)
lpStr += strlen(lpStr) + 1;
}
- FreeEnvironmentStrings(lpEnvPtr);
+ win32_freeenvironmentstrings(lpEnvPtr);
}
diff --git a/win32/win32.c b/win32/win32.c
index 7f2444b..1c4c05c 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1650,6 +1650,40 @@ win32_ansipath(const WCHAR *widename)
}
DllExport char *
+win32_getenvironmentstrings(void)
+{
+ LPWSTR lpWStr, lpWTmp;
+ LPSTR lpStr, lpTmp;
+ DWORD size, env_len, wenvstrings_len = 0, aenvstrings_len = 0;
+
+ // Get the process environment strings
+ lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
+ for(size = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
+ env_len = wcslen(lpWTmp);
+ // calculate the size of the environment strings
+ wenvstrings_len += env_len + 1;
+ }
+
+ /* Get the number of bytes required to store the UTF16 encoded string */
+ aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
+ lpWStr, wenvstrings_len, NULL, 0, 0, 0);
+ lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
+ if(!lpTmp)
+ out_of_memory();
+
+ /* Convert the string from UTF-16 encoding to UTF-8 encoding */
+ WideCharToMultiByte(CP_ACP, 0, lpWStr, wenvstrings_len, lpStr, aenvstrings_len, 0, 0);
+
+ return(lpStr);
+}
+
+DllExport void
+win32_freeenvironmentstrings(void* block)
+{
+ win32_free(block);
+}
+
+DllExport char *
win32_getenv(const char *name)
{
dTHX;
diff --git a/win32/win32iop.h b/win32/win32iop.h
index 373e3e3..cbc9716 100644
--- a/win32/win32iop.h
+++ b/win32/win32iop.h
@@ -126,6 +126,8 @@ DllExport void win32_rewinddir(DIR *dirp);
DllExport int win32_closedir(DIR *dirp);
DllExport DIR* win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param);
+DllExport char* win32_getenvironmentstrings(void);
+DllExport void win32_freeenvironmentstrings(void *block);
DllExport char* win32_getenv(const char *name);
DllExport int win32_putenv(const char *name);
--
1.7.7.1
|
From [Unknown Contact. See original ticket]Hi Shay, On Fri Jun 08 13:17:34 2012, shay wrote:
I was thinking for env other than username. This could have been taken by
I now have your comments incorporated in my attached patch. Please go- -Karthik |
From @bulk88On Mon Jun 11 12:57:53 2012, kartlee05 wrote:
__________________________ ________________________________ len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wstr, wlen, |
From karthik.rajagopalan@schrodinger.comHi, On Tue Jun 12 08:13:09 2012, bulk88. wrote:
That was mistake on my part not to pass WC_NO_BEST_FIT_CHARS in acutal BTW, I don't think the win32 code would really work if UTF-8 is -Karthik
wlen,
|
From karthik.rajagopalan@schrodinger.com
I now fixed the patch to use WC_NO_BEST_FIT_CHARS in the actual -Karthik |
From karthik.rajagopalan@schrodinger.com0001-Use-GetEnvironmentStringsW-.-instead-of-GetEnvironme.patchFrom b77244181d5feea493dfc861434ea27a7b4825ef Mon Sep 17 00:00:00 2001
From: Karthik Rajagopalan <rajagopa@schrodinger.com>
Date: Tue, 12 Jun 2012 11:37:29 -0400
Subject: [PATCH] Use GetEnvironmentStringsW(..) instead of
GetEnvironmentStringsA(..).
GetEnvironmentStringsA(..) return strings in the OEM code page. This
can actually mangle the environment strings if it contain special characters.
A better approach would be to get the utf-16 strings through GetEnvironmentStringsW(..)
and convert them to ANSI code page. This is now done by win32_getenvironmentstrings(..).
To free the block, you can use win32_freeenvironmentstrings(..).
---
win32/perlhost.h | 8 ++++----
win32/win32.c | 35 +++++++++++++++++++++++++++++++++++
win32/win32iop.h | 2 ++
3 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/win32/perlhost.h b/win32/perlhost.h
index e8f5fb4..ae422ef 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -2262,7 +2262,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
int nLength, compVal;
// get the process environment strings
- lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings();
+ lpAllocPtr = lpTmp = (LPSTR)win32_getenvironmentstrings();
// step over current directory stuff
while(*lpTmp == '=')
@@ -2338,7 +2338,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
}
// release the process environment strings
- FreeEnvironmentStrings(lpAllocPtr);
+ win32_freeenvironmentstrings(lpAllocPtr);
return lpPtr;
}
@@ -2375,7 +2375,7 @@ CPerlHost::Clearenv(void)
}
/* get the process environment strings */
- lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings();
+ lpStr = lpEnvPtr = (LPSTR)win32_getenvironmentstrings();
/* step over current directory stuff */
while(*lpStr == '=')
@@ -2394,7 +2394,7 @@ CPerlHost::Clearenv(void)
lpStr += strlen(lpStr) + 1;
}
- FreeEnvironmentStrings(lpEnvPtr);
+ win32_freeenvironmentstrings(lpEnvPtr);
}
diff --git a/win32/win32.c b/win32/win32.c
index 7f2444b..de7b9aa 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1650,6 +1650,41 @@ win32_ansipath(const WCHAR *widename)
}
DllExport char *
+win32_getenvironmentstrings(void)
+{
+ LPWSTR lpWStr, lpWTmp;
+ LPSTR lpStr, lpTmp;
+ DWORD size, env_len, wenvstrings_len = 0, aenvstrings_len = 0;
+
+ // Get the process environment strings
+ lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
+ for(size = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
+ env_len = wcslen(lpWTmp);
+ // calculate the size of the environment strings
+ wenvstrings_len += env_len + 1;
+ }
+
+ /* Get the number of bytes required to store the UTF16 encoded string */
+ aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
+ lpWStr, wenvstrings_len, NULL, 0, 0, 0);
+ lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
+ if(!lpTmp)
+ out_of_memory();
+
+ /* Convert the string from UTF-16 encoding to UTF-8 encoding */
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
+ aenvstrings_len, 0, 0);
+
+ return(lpStr);
+}
+
+DllExport void
+win32_freeenvironmentstrings(void* block)
+{
+ win32_free(block);
+}
+
+DllExport char *
win32_getenv(const char *name)
{
dTHX;
diff --git a/win32/win32iop.h b/win32/win32iop.h
index 373e3e3..cbc9716 100644
--- a/win32/win32iop.h
+++ b/win32/win32iop.h
@@ -126,6 +126,8 @@ DllExport void win32_rewinddir(DIR *dirp);
DllExport int win32_closedir(DIR *dirp);
DllExport DIR* win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param);
+DllExport char* win32_getenvironmentstrings(void);
+DllExport void win32_freeenvironmentstrings(void *block);
DllExport char* win32_getenv(const char *name);
DllExport int win32_putenv(const char *name);
--
1.7.7.1
|
From @bulk88I've got a problem. I think your patch's code is unreachable. I compiled |
From @bulk88On Tue Jun 12 16:48:28 2012, bulk88. wrote:
Platform: Characteristics of this binary (from libperl): C:\p517\perl\win32> |
From @bulk88disregard the last 2 posts, i found the place where its called |
From @bulk88You can't use CP_ACP unless your intending for your patch to only work From lpWStr After conversion WideCharToMultiByte The unicode does NOT pass through to the child process for me. I'll try |
From @bulk88The attachment is a accidentally posted work in progress debugging |
From @bulk88On Tue Jun 12 22:57:14 2012, bulk88. wrote:
|
From @steve-m-hayOn Tue Jun 12 08:41:15 2012, kartlee05 wrote:
I think there is a bug in this and the previous patch (but not your After changing for(size = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) { to for(wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) { the patch looks good to me code-wise, but I will await any further input Could you also fix up a couple of the comments, though, please? The |
From @bulk88Okay, here is the problem with the patch, the env var is NOT corrupted, I decided NOT to study how %ENV works just to post this. I |
From @bulk88Active code page: 65001 perl ver parent v5.17.0 NEW PROCESS in ENVREAD.PL |
From @bulk88Active code page: 65001 perl ver parent v5.17.0 NEW PROCESS in ENVREAD.PL |
From @bulk88Active code page: 65001 perl ver parent v5.12.2 NEW PROCESS in ENVREAD.PL |
From @bulk88 |
From @bulk88Active code page: 65001 perl ver parent v5.12.2 NEW PROCESS in ENVREAD.PL |
From @steve-m-haybulk88 via RT wrote on 2012-06-13:
Thanks for the sample programs. I intend to have a look through them when I have more time, but if I understand you correctly the problem here is only that things are still not working if the environment contains characters which cannot be represented in the current ANSI codepage? That is to be expected, given the widechar (UTF-16) -> ANSI codepage conversion being done, and the ? character, of course, comes from the WideCharToMultiByte() calls when they fail to map a unicode character to the target encoding. On pre-patch perls something different happens because GetEnvironmentStringsA() was being used which returns things in the OEM codepage and must presumably have some algorithm of its own for handling unicode characters that cannot be mapped to that encoding, hence different characters (but still the wrong ones!) appearing instead of ?. I still think the patch is worthwhile (with the fix I posted previously) because it fixes things for the common case where the environment contains characters which *are* in the current ANSI codepage but either not in the current OEM codepage (because the GetEnvironmentStringsA() conversion from unicode to OEM would have failed) or else (more commonly) in the OEM codepage but at a different byte position (because perl then treated the OEM bytes as if they were the ANSI bytes which are normally used). So the only problem remaining is what happens in the case when characters outside of the current ANSI codepage appear in the environment, and that would be worth logging as a separate bug. It isn't such a common case, and there are likely to be problems in other areas of the code in that case anyway, e.g. you can't open a file whose name contains characters outside of the ANSI codepage without jumping through some hoops rather than using the built-in open() function. If you agree and have no other issues with the patch then I'll apply it and raise the non-ANSI characters problem as a separate bug (and attach your scripts etc). |
From @bulk88On Thu Jun 14 00:56:57 2012, Steve.Hay@verosoftware.com wrote:
I agree. You can apply the patch. Ultimately one day all of %INC support |
From karthik.rajagopalan@schrodinger.comOn Wed Jun 13 00:22:43 2012, shay wrote:
I fixed the bug in my patch which failed to account for last '\0' char
This is also fixed now. The revised patch is attached now. Please take a look. -Karthik |
From karthik.rajagopalan@schrodinger.com0001-Use-GetEnvironmentStringsW-.-instead-of-GetEnvironme.patchFrom f5bbd57635ff725971d736aed43832a57845491b Mon Sep 17 00:00:00 2001
From: Karthik Rajagopalan <rajagopa@schrodinger.com>
Date: Thu, 14 Jun 2012 12:16:15 -0400
Subject: [PATCH] Use GetEnvironmentStringsW(..) instead of
GetEnvironmentStringsA(..).
GetEnvironmentStringsA(..) return strings in the OEM code page. This
can actually mangle the environment strings if it contain special characters.
A better approach would be to get the utf-16 strings through GetEnvironmentStringsW(..)
and convert them to ANSI code page. This is now done by win32_getenvironmentstrings(..).
To free the block, you can use win32_freeenvironmentstrings(..).
---
win32/perlhost.h | 8 ++++----
win32/win32.c | 35 +++++++++++++++++++++++++++++++++++
win32/win32iop.h | 2 ++
3 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/win32/perlhost.h b/win32/perlhost.h
index e8f5fb4..ae422ef 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -2262,7 +2262,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
int nLength, compVal;
// get the process environment strings
- lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings();
+ lpAllocPtr = lpTmp = (LPSTR)win32_getenvironmentstrings();
// step over current directory stuff
while(*lpTmp == '=')
@@ -2338,7 +2338,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
}
// release the process environment strings
- FreeEnvironmentStrings(lpAllocPtr);
+ win32_freeenvironmentstrings(lpAllocPtr);
return lpPtr;
}
@@ -2375,7 +2375,7 @@ CPerlHost::Clearenv(void)
}
/* get the process environment strings */
- lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings();
+ lpStr = lpEnvPtr = (LPSTR)win32_getenvironmentstrings();
/* step over current directory stuff */
while(*lpStr == '=')
@@ -2394,7 +2394,7 @@ CPerlHost::Clearenv(void)
lpStr += strlen(lpStr) + 1;
}
- FreeEnvironmentStrings(lpEnvPtr);
+ win32_freeenvironmentstrings(lpEnvPtr);
}
diff --git a/win32/win32.c b/win32/win32.c
index 7f2444b..e496837 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1650,6 +1650,41 @@ win32_ansipath(const WCHAR *widename)
}
DllExport char *
+win32_getenvironmentstrings(void)
+{
+ LPWSTR lpWStr, lpWTmp;
+ LPSTR lpStr, lpTmp;
+ DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
+
+ /* Get the process environment strings */
+ lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
+ for(wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
+ env_len = wcslen(lpWTmp);
+ /* calculate the size of the environment strings */
+ wenvstrings_len += env_len + 1;
+ }
+
+ /* Get the number of bytes required to store the UTF16 encoded string */
+ aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
+ lpWStr, wenvstrings_len, NULL, 0, 0, 0);
+ lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
+ if(!lpTmp)
+ out_of_memory();
+
+ /* Convert the string from UTF-16 encoding to ACP encoding */
+ WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
+ aenvstrings_len, 0, 0);
+
+ return(lpStr);
+}
+
+DllExport void
+win32_freeenvironmentstrings(void* block)
+{
+ win32_free(block);
+}
+
+DllExport char *
win32_getenv(const char *name)
{
dTHX;
diff --git a/win32/win32iop.h b/win32/win32iop.h
index 373e3e3..cbc9716 100644
--- a/win32/win32iop.h
+++ b/win32/win32iop.h
@@ -126,6 +126,8 @@ DllExport void win32_rewinddir(DIR *dirp);
DllExport int win32_closedir(DIR *dirp);
DllExport DIR* win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param);
+DllExport char* win32_getenvironmentstrings(void);
+DllExport void win32_freeenvironmentstrings(void *block);
DllExport char* win32_getenv(const char *name);
DllExport int win32_putenv(const char *name);
--
1.7.7.1
|
From karthik.rajagopalan@schrodinger.comOn Tue Jun 12 22:54:32 2012, bulk88. wrote:
Yes, there are lot of places in win32 which still depend on ACP calls. So -Karthik |
From @steve-m-hayOn Thu Jun 14 09:02:31 2012, bulk88. wrote:
I added a note to perltodo.pod in commit 799c141 referring to this |
From @steve-m-hayOn Thu Jun 14 09:20:33 2012, kartlee05 wrote:
Thanks, your patch is now applied as commit 4f46e52. |
@steve-m-hay - Status changed from 'open' to 'resolved' |
From karthik.rajagopalan@schrodinger.comHi Steve, On Fri Jun 15 00:57:16 2012, shay wrote:
Thanks for applying this change. Will this be in 5.17? BTW, do you want -Karthik |
From karthik.rajagopalan@schrodinger.comOn Fri Jun 15 07:13:34 2012, kartlee05 wrote:
I meant in next minor version for it?
|
From [Unknown Contact. See original ticket]On Fri Jun 15 07:13:34 2012, kartlee05 wrote:
I meant in next minor version for it?
|
From karthik.rajagopalan@schrodinger.comSent from my iPhone On Jun 13, 2012, at 3:22 AM, "Steve Hay via RT" <perlbug-followup@perl.org> wrote:
I agree. I have not taken care for the additional null char to indicate the end of environment strings in my last two patches. I will add this now and resend.
Sure, I will do that and send you in an hour. -Karthik |
From @steve-m-hayOn Fri Jun 15 07:13:34 2012, kartlee05 wrote:
The change will indeed be in 5.17.1, due out in a couple of days. Support for wide api calls on Win32 was actually removed some time ago For sure, the solution on Windows must involve the wide apis, but what |
From @bulk88On Mon Jun 18 00:26:30 2012, shay wrote:
This ticket probably caused the leak reported at https://rt-archive.perl.org/perl5/Ticket/Display.html?id=121676 -- |
Migrated from rt.perl.org#113536 (status was 'resolved')
Searchable as RT113536$
The text was updated successfully, but these errors were encountered: