mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
Fix Windows Unicode handling of environment variables
This commit is contained in:
committed by
akallabeth
parent
be5ace1123
commit
55be5f8bb0
@@ -134,6 +134,9 @@ extern "C"
|
||||
|
||||
WINPR_API char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock);
|
||||
|
||||
WINPR_API DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize);
|
||||
WINPR_API char* GetEnvAlloc(LPCSTR lpName);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -643,3 +643,77 @@ char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
|
||||
|
||||
return envp;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// https://devblogs.microsoft.com/oldnewthing/20100203-00/?p=15083
|
||||
#define WINPR_MAX_ENVIRONMENT_LENGTH 2048
|
||||
|
||||
DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize)
|
||||
{
|
||||
int status;
|
||||
DWORD result = 0;
|
||||
DWORD nSizeW = 0;
|
||||
LPWSTR lpNameW = NULL;
|
||||
LPWSTR lpBufferW = NULL;
|
||||
LPSTR lpBufferA = lpBuffer;
|
||||
|
||||
if (ConvertToUnicode(CP_UTF8, 0, lpName, -1, &lpNameW, 0) < 1)
|
||||
goto cleanup;
|
||||
|
||||
if (!lpBuffer)
|
||||
{
|
||||
char lpBufferMaxA[WINPR_MAX_ENVIRONMENT_LENGTH];
|
||||
WCHAR lpBufferMaxW[WINPR_MAX_ENVIRONMENT_LENGTH];
|
||||
|
||||
// calling GetEnvironmentVariableX with a NULL buffer should return the expected size
|
||||
// TODO: dynamically allocate the buffer, or use the theoretical limit of 32,768 characters
|
||||
|
||||
lpBufferA = lpBufferMaxA;
|
||||
lpBufferW = lpBufferMaxW;
|
||||
nSizeW = sizeof(lpBufferMaxW) / 2;
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, lpBufferW, -1, &lpBufferA, sizeof(lpBufferMaxA),
|
||||
NULL, NULL);
|
||||
|
||||
if (status > 0)
|
||||
result = (DWORD)status;
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSizeW = nSize + 1;
|
||||
lpBufferW = calloc(nSizeW, 2);
|
||||
|
||||
if (!lpBufferW)
|
||||
goto cleanup;
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
|
||||
|
||||
if (result == 0)
|
||||
goto cleanup;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, lpBufferW, -1, &lpBufferA, nSize, NULL, NULL);
|
||||
|
||||
if (status > 0)
|
||||
result = (DWORD)(status - 1);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(lpBufferW);
|
||||
free(lpNameW);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize)
|
||||
{
|
||||
return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -59,20 +59,24 @@ static char* GetPath_XDG_RUNTIME_DIR(void);
|
||||
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
*/
|
||||
|
||||
static char* GetEnvAlloc(LPCSTR lpName)
|
||||
char* GetEnvAlloc(LPCSTR lpName)
|
||||
{
|
||||
DWORD length;
|
||||
DWORD nSize;
|
||||
DWORD nStatus;
|
||||
char* env = NULL;
|
||||
length = GetEnvironmentVariableA(lpName, NULL, 0);
|
||||
|
||||
if (length > 0)
|
||||
nSize = GetEnvironmentVariableX(lpName, NULL, 0);
|
||||
|
||||
if (nSize > 0)
|
||||
{
|
||||
env = malloc(length);
|
||||
env = malloc(nSize);
|
||||
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
if (GetEnvironmentVariableA(lpName, env, length) != length - 1)
|
||||
nStatus = GetEnvironmentVariableX(lpName, env, nSize);
|
||||
|
||||
if (nStatus != (nSize - 1))
|
||||
{
|
||||
free(env);
|
||||
return NULL;
|
||||
@@ -376,7 +380,8 @@ char* GetEnvironmentPath(char* name)
|
||||
{
|
||||
char* env = NULL;
|
||||
DWORD nSize;
|
||||
nSize = GetEnvironmentVariableA(name, NULL, 0);
|
||||
DWORD nStatus;
|
||||
nSize = GetEnvironmentVariableX(name, NULL, 0);
|
||||
|
||||
if (nSize)
|
||||
{
|
||||
@@ -385,7 +390,9 @@ char* GetEnvironmentPath(char* name)
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
|
||||
nStatus = GetEnvironmentVariableX(name, env, nSize);
|
||||
|
||||
if (nStatus != (nSize - 1))
|
||||
{
|
||||
free(env);
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user