Skip to content

Commit 4f46e52

Browse files
Karthik Rajagopalansteve-m-hay
Karthik Rajagopalan
authored andcommitted
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(..).
1 parent c8d84f8 commit 4f46e52

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

win32/perlhost.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,7 +2262,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
22622262
int nLength, compVal;
22632263

22642264
// get the process environment strings
2265-
lpAllocPtr = lpTmp = (LPSTR)GetEnvironmentStrings();
2265+
lpAllocPtr = lpTmp = (LPSTR)win32_getenvironmentstrings();
22662266

22672267
// step over current directory stuff
22682268
while(*lpTmp == '=')
@@ -2338,7 +2338,7 @@ CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
23382338
}
23392339

23402340
// release the process environment strings
2341-
FreeEnvironmentStrings(lpAllocPtr);
2341+
win32_freeenvironmentstrings(lpAllocPtr);
23422342

23432343
return lpPtr;
23442344
}
@@ -2375,7 +2375,7 @@ CPerlHost::Clearenv(void)
23752375
}
23762376

23772377
/* get the process environment strings */
2378-
lpStr = lpEnvPtr = (LPSTR)GetEnvironmentStrings();
2378+
lpStr = lpEnvPtr = (LPSTR)win32_getenvironmentstrings();
23792379

23802380
/* step over current directory stuff */
23812381
while(*lpStr == '=')
@@ -2394,7 +2394,7 @@ CPerlHost::Clearenv(void)
23942394
lpStr += strlen(lpStr) + 1;
23952395
}
23962396

2397-
FreeEnvironmentStrings(lpEnvPtr);
2397+
win32_freeenvironmentstrings(lpEnvPtr);
23982398
}
23992399

24002400

win32/win32.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,41 @@ win32_ansipath(const WCHAR *widename)
16491649
return name;
16501650
}
16511651

1652+
DllExport char *
1653+
win32_getenvironmentstrings(void)
1654+
{
1655+
LPWSTR lpWStr, lpWTmp;
1656+
LPSTR lpStr, lpTmp;
1657+
DWORD env_len, wenvstrings_len = 0, aenvstrings_len = 0;
1658+
1659+
/* Get the process environment strings */
1660+
lpWTmp = lpWStr = (LPWSTR) GetEnvironmentStringsW();
1661+
for(wenvstrings_len = 1; *lpWTmp != '\0'; lpWTmp += env_len + 1) {
1662+
env_len = wcslen(lpWTmp);
1663+
/* calculate the size of the environment strings */
1664+
wenvstrings_len += env_len + 1;
1665+
}
1666+
1667+
/* Get the number of bytes required to store the UTF16 encoded string */
1668+
aenvstrings_len = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
1669+
lpWStr, wenvstrings_len, NULL, 0, 0, 0);
1670+
lpTmp = lpStr = (char *)win32_calloc(aenvstrings_len, sizeof(char));
1671+
if(!lpTmp)
1672+
out_of_memory();
1673+
1674+
/* Convert the string from UTF-16 encoding to ACP encoding */
1675+
WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, lpWStr, wenvstrings_len, lpStr,
1676+
aenvstrings_len, 0, 0);
1677+
1678+
return(lpStr);
1679+
}
1680+
1681+
DllExport void
1682+
win32_freeenvironmentstrings(void* block)
1683+
{
1684+
win32_free(block);
1685+
}
1686+
16521687
DllExport char *
16531688
win32_getenv(const char *name)
16541689
{

win32/win32iop.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ DllExport void win32_rewinddir(DIR *dirp);
126126
DllExport int win32_closedir(DIR *dirp);
127127
DllExport DIR* win32_dirp_dup(DIR *const dirp, CLONE_PARAMS *const param);
128128

129+
DllExport char* win32_getenvironmentstrings(void);
130+
DllExport void win32_freeenvironmentstrings(void *block);
129131
DllExport char* win32_getenv(const char *name);
130132
DllExport int win32_putenv(const char *name);
131133

0 commit comments

Comments
 (0)