Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
22
third_party/FreeRDP/winpr/libwinpr/environment/CMakeLists.txt
vendored
Normal file
22
third_party/FreeRDP/winpr/libwinpr/environment/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-environment cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
winpr_module_add(environment.c)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
9
third_party/FreeRDP/winpr/libwinpr/environment/ModuleOptions.cmake
vendored
Normal file
9
third_party/FreeRDP/winpr/libwinpr/environment/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "2")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "processenvironment")
|
||||
set(MINWIN_LONG_NAME "Process Environment Functions")
|
||||
set(MODULE_LIBRARY_NAME
|
||||
"api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}"
|
||||
)
|
||||
760
third_party/FreeRDP/winpr/libwinpr/environment/environment.c
vendored
Normal file
760
third_party/FreeRDP/winpr/libwinpr/environment/environment.c
vendored
Normal file
@@ -0,0 +1,760 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Process Environment Functions
|
||||
*
|
||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Thincast Technologies GmbH
|
||||
* Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <winpr/environment.h>
|
||||
|
||||
#include "../log.h"
|
||||
|
||||
#define TAG WINPR_TAG("environment")
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WINPR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__IOS__)
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
#include <crt_externs.h>
|
||||
#define environ (*_NSGetEnviron())
|
||||
#endif
|
||||
|
||||
DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer)
|
||||
{
|
||||
size_t length = 0;
|
||||
char* cwd = nullptr;
|
||||
char* ccwd = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
length += MAX_PATH;
|
||||
char* tmp = realloc(cwd, length);
|
||||
if (!tmp)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
cwd = tmp;
|
||||
|
||||
ccwd = getcwd(cwd, length);
|
||||
} while (!ccwd && (errno == ERANGE));
|
||||
|
||||
if (!ccwd)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = strnlen(cwd, length);
|
||||
|
||||
if ((nBufferLength == 0) && (lpBuffer == nullptr))
|
||||
{
|
||||
free(cwd);
|
||||
return (DWORD)length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpBuffer == nullptr)
|
||||
{
|
||||
free(cwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((length + 1) > nBufferLength)
|
||||
{
|
||||
free(cwd);
|
||||
return (DWORD)(length + 1);
|
||||
}
|
||||
|
||||
memcpy(lpBuffer, cwd, length + 1);
|
||||
free(cwd);
|
||||
return (DWORD)length;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetCurrentDirectoryW(WINPR_ATTR_UNUSED DWORD nBufferLength, WINPR_ATTR_UNUSED LPWSTR lpBuffer)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SetCurrentDirectoryA(WINPR_ATTR_UNUSED LPCSTR lpPathName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetCurrentDirectoryW(WINPR_ATTR_UNUSED LPCWSTR lpPathName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD SearchPathA(WINPR_ATTR_UNUSED LPCSTR lpPath, WINPR_ATTR_UNUSED LPCSTR lpFileName,
|
||||
WINPR_ATTR_UNUSED LPCSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
|
||||
WINPR_ATTR_UNUSED LPSTR lpBuffer, WINPR_ATTR_UNUSED LPSTR* lpFilePart)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD SearchPathW(WINPR_ATTR_UNUSED LPCWSTR lpPath, WINPR_ATTR_UNUSED LPCWSTR lpFileName,
|
||||
WINPR_ATTR_UNUSED LPCWSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
|
||||
WINPR_ATTR_UNUSED LPWSTR lpBuffer, WINPR_ATTR_UNUSED LPWSTR* lpFilePart)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPSTR GetCommandLineA(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LPWSTR GetCommandLineW(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL NeedCurrentDirectoryForExePathA(WINPR_ATTR_UNUSED LPCSTR ExeName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL NeedCurrentDirectoryForExePathW(WINPR_ATTR_UNUSED LPCWSTR ExeName)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
size_t length = 0;
|
||||
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
char* env = getenv(lpName);
|
||||
|
||||
if (!env)
|
||||
{
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = strlen(env);
|
||||
|
||||
if ((length + 1 > nSize) || (!lpBuffer))
|
||||
return (DWORD)length + 1;
|
||||
|
||||
CopyMemory(lpBuffer, env, length);
|
||||
lpBuffer[length] = '\0';
|
||||
|
||||
return (DWORD)length;
|
||||
#else
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
DWORD GetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPWSTR lpBuffer,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
SetLastError(ERROR_ENVVAR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
if (!lpName)
|
||||
return FALSE;
|
||||
|
||||
if (lpValue)
|
||||
{
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (0 != setenv(lpName, lpValue, 1))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (0 != unsetenv(lpName))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPCWSTR lpValue)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetEnvironmentStrings function:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms683187/
|
||||
*
|
||||
* The GetEnvironmentStrings function returns a pointer to a block of memory
|
||||
* that contains the environment variables of the calling process (both the
|
||||
* system and the user environment variables). Each environment block contains
|
||||
* the environment variables in the following format:
|
||||
*
|
||||
* Var1=Value1\0
|
||||
* Var2=Value2\0
|
||||
* Var3=Value3\0
|
||||
* ...
|
||||
* VarN=ValueN\0\0
|
||||
*/
|
||||
|
||||
extern char** environ;
|
||||
|
||||
LPCH GetEnvironmentStringsA(VOID)
|
||||
{
|
||||
#if !defined(_UWP)
|
||||
size_t offset = 0;
|
||||
char** envp = environ;
|
||||
const size_t blocksize = 128;
|
||||
size_t cchEnvironmentBlock = blocksize;
|
||||
LPCH lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
|
||||
|
||||
if (!lpszEnvironmentBlock)
|
||||
return nullptr;
|
||||
|
||||
while (*envp)
|
||||
{
|
||||
const size_t length = strlen(*envp);
|
||||
const size_t required = offset + length + 8ull;
|
||||
if (required > UINT32_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "Environment block too large: %" PRIuz, required);
|
||||
|
||||
free(lpszEnvironmentBlock);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (required > cchEnvironmentBlock)
|
||||
{
|
||||
size_t new_size = cchEnvironmentBlock;
|
||||
do
|
||||
{
|
||||
new_size += blocksize;
|
||||
} while (new_size <= required);
|
||||
LPCH new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size * sizeof(CHAR));
|
||||
if (!new_blk)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock = new_blk;
|
||||
cchEnvironmentBlock = new_size;
|
||||
}
|
||||
|
||||
char* p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
CopyMemory(p, *envp, length * sizeof(CHAR));
|
||||
p[length] = '\0';
|
||||
|
||||
offset += (length + 1ull);
|
||||
envp++;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock[offset] = '\0';
|
||||
|
||||
return lpszEnvironmentBlock;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
LPWCH GetEnvironmentStringsW(VOID)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentStringsA(WINPR_ATTR_UNUSED LPCH NewEnvironment)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentStringsW(WINPR_ATTR_UNUSED LPWCH NewEnvironment)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD ExpandEnvironmentStringsA(WINPR_ATTR_UNUSED LPCSTR lpSrc, WINPR_ATTR_UNUSED LPSTR lpDst,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD ExpandEnvironmentStringsW(WINPR_ATTR_UNUSED LPCWSTR lpSrc, WINPR_ATTR_UNUSED LPWSTR lpDst,
|
||||
WINPR_ATTR_UNUSED DWORD nSize)
|
||||
{
|
||||
WLog_ERR(TAG, "TODO: not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock)
|
||||
{
|
||||
free(lpszEnvironmentBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
|
||||
{
|
||||
const char* cp = nullptr;
|
||||
char* p = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t length = 0;
|
||||
const char* envp = nullptr;
|
||||
DWORD cchEnvironmentBlock = 0;
|
||||
LPCH lpszEnvironmentBlock = nullptr;
|
||||
const char** mergeStrings = nullptr;
|
||||
size_t mergeStringLength = 0;
|
||||
size_t mergeArraySize = 128;
|
||||
size_t mergeLength = 0;
|
||||
size_t foundMerge = 0;
|
||||
char* foundEquals = nullptr;
|
||||
|
||||
mergeStrings = (LPCSTR*)calloc(mergeArraySize, sizeof(char*));
|
||||
|
||||
if (!mergeStrings)
|
||||
return nullptr;
|
||||
|
||||
mergeStringLength = 0;
|
||||
|
||||
cp = merge;
|
||||
|
||||
while (*cp && *(cp + 1))
|
||||
{
|
||||
length = strlen(cp);
|
||||
|
||||
if (mergeStringLength == mergeArraySize)
|
||||
{
|
||||
const char** new_str = nullptr;
|
||||
|
||||
mergeArraySize += 128;
|
||||
new_str = (const char**)realloc((void*)mergeStrings, mergeArraySize * sizeof(char*));
|
||||
|
||||
if (!new_str)
|
||||
{
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
mergeStrings = new_str;
|
||||
}
|
||||
|
||||
mergeStrings[mergeStringLength] = cp;
|
||||
cp += length + 1;
|
||||
mergeStringLength++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
|
||||
cchEnvironmentBlock = 128;
|
||||
lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
|
||||
|
||||
if (!lpszEnvironmentBlock)
|
||||
{
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
envp = original;
|
||||
|
||||
while ((original != nullptr) && (*envp && *(envp + 1)))
|
||||
{
|
||||
size_t old_offset = offset;
|
||||
length = strlen(envp);
|
||||
|
||||
while ((offset + length + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
lpszEnvironmentBlock = tmp;
|
||||
}
|
||||
|
||||
p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
// check if this value is in the mergeStrings
|
||||
foundMerge = 0;
|
||||
for (size_t run = 0; run < mergeStringLength; run++)
|
||||
{
|
||||
if (!mergeStrings[run])
|
||||
continue;
|
||||
|
||||
mergeLength = strlen(mergeStrings[run]);
|
||||
foundEquals = strstr(mergeStrings[run], "=");
|
||||
|
||||
if (!foundEquals)
|
||||
continue;
|
||||
|
||||
const intptr_t len = foundEquals - mergeStrings[run] + 1;
|
||||
if (strncmp(envp, mergeStrings[run], WINPR_ASSERTING_INT_CAST(size_t, len)) == 0)
|
||||
{
|
||||
// found variable in merge list ... use this ....
|
||||
if (*(foundEquals + 1) == '\0')
|
||||
{
|
||||
// check if the argument is set ... if not remove variable ...
|
||||
foundMerge = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((offset + mergeLength + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp =
|
||||
(LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
lpszEnvironmentBlock = tmp;
|
||||
p = &(lpszEnvironmentBlock[old_offset]);
|
||||
}
|
||||
|
||||
foundMerge = 1;
|
||||
CopyMemory(p, mergeStrings[run], mergeLength);
|
||||
mergeStrings[run] = nullptr;
|
||||
p[mergeLength] = '\0';
|
||||
offset += (mergeLength + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundMerge == 0)
|
||||
{
|
||||
CopyMemory(p, envp, length * sizeof(CHAR));
|
||||
p[length] = '\0';
|
||||
offset += (length + 1);
|
||||
}
|
||||
|
||||
envp += (length + 1);
|
||||
}
|
||||
|
||||
// now merge the not already merged env
|
||||
for (size_t run = 0; run < mergeStringLength; run++)
|
||||
{
|
||||
if (!mergeStrings[run])
|
||||
continue;
|
||||
|
||||
mergeLength = strlen(mergeStrings[run]);
|
||||
|
||||
while ((offset + mergeLength + 8) > cchEnvironmentBlock)
|
||||
{
|
||||
cchEnvironmentBlock *= 2;
|
||||
LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
free((void*)lpszEnvironmentBlock);
|
||||
free((void*)mergeStrings);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock = tmp;
|
||||
}
|
||||
|
||||
p = &(lpszEnvironmentBlock[offset]);
|
||||
|
||||
CopyMemory(p, mergeStrings[run], mergeLength);
|
||||
mergeStrings[run] = nullptr;
|
||||
p[mergeLength] = '\0';
|
||||
offset += (mergeLength + 1);
|
||||
}
|
||||
|
||||
lpszEnvironmentBlock[offset] = '\0';
|
||||
|
||||
free((void*)mergeStrings);
|
||||
|
||||
return lpszEnvironmentBlock;
|
||||
}
|
||||
|
||||
DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||
{
|
||||
size_t vLength = 0;
|
||||
char* env = nullptr;
|
||||
char* foundEquals = nullptr;
|
||||
const char* penvb = envBlock;
|
||||
size_t nLength = 0;
|
||||
size_t fLength = 0;
|
||||
size_t lpNameLength = 0;
|
||||
|
||||
if (!lpName || nullptr == envBlock)
|
||||
return 0;
|
||||
|
||||
lpNameLength = strlen(lpName);
|
||||
|
||||
if (lpNameLength < 1)
|
||||
return 0;
|
||||
|
||||
while (*penvb && *(penvb + 1))
|
||||
{
|
||||
fLength = strlen(penvb);
|
||||
foundEquals = strstr(penvb, "=");
|
||||
|
||||
if (!foundEquals)
|
||||
{
|
||||
/* if no = sign is found the envBlock is broken */
|
||||
return 0;
|
||||
}
|
||||
|
||||
nLength = WINPR_ASSERTING_INT_CAST(size_t, (foundEquals - penvb));
|
||||
|
||||
if (nLength != lpNameLength)
|
||||
{
|
||||
penvb += (fLength + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(penvb, lpName, nLength) == 0)
|
||||
{
|
||||
env = foundEquals + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
penvb += (fLength + 1);
|
||||
}
|
||||
|
||||
if (!env)
|
||||
return 0;
|
||||
|
||||
vLength = strlen(env);
|
||||
if (vLength >= UINT32_MAX)
|
||||
return 0;
|
||||
|
||||
if ((vLength + 1 > nSize) || (!lpBuffer))
|
||||
return (DWORD)vLength + 1;
|
||||
|
||||
CopyMemory(lpBuffer, env, vLength + 1);
|
||||
|
||||
return (DWORD)vLength;
|
||||
}
|
||||
|
||||
BOOL SetEnvironmentVariableEBA(LPSTR* envBlock, LPCSTR lpName, LPCSTR lpValue)
|
||||
{
|
||||
size_t length = 0;
|
||||
char* envstr = nullptr;
|
||||
char* newEB = nullptr;
|
||||
|
||||
if (!lpName)
|
||||
return FALSE;
|
||||
|
||||
if (lpValue)
|
||||
{
|
||||
length = (strlen(lpName) + strlen(lpValue) + 2); /* +2 because of = and \0 */
|
||||
envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
|
||||
|
||||
if (!envstr)
|
||||
return FALSE;
|
||||
|
||||
(void)sprintf_s(envstr, length, "%s=%s", lpName, lpValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = strlen(lpName) + 2; /* +2 because of = and \0 */
|
||||
envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
|
||||
|
||||
if (!envstr)
|
||||
return FALSE;
|
||||
|
||||
(void)sprintf_s(envstr, length, "%s=", lpName);
|
||||
}
|
||||
|
||||
envstr[length] = '\0';
|
||||
|
||||
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock, envstr);
|
||||
|
||||
free(envstr);
|
||||
free(*envBlock);
|
||||
|
||||
*envBlock = newEB;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
|
||||
{
|
||||
char* p = nullptr;
|
||||
SSIZE_T index = 0;
|
||||
size_t count = 0;
|
||||
size_t length = 0;
|
||||
char** envp = nullptr;
|
||||
|
||||
count = 0;
|
||||
if (!lpszEnvironmentBlock)
|
||||
return nullptr;
|
||||
|
||||
p = (char*)lpszEnvironmentBlock;
|
||||
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
length = strlen(p);
|
||||
p += (length + 1);
|
||||
count++;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
p = (char*)lpszEnvironmentBlock;
|
||||
|
||||
envp = (char**)calloc(count + 1, sizeof(char*));
|
||||
if (!envp)
|
||||
return nullptr;
|
||||
envp[count] = nullptr;
|
||||
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
length = strlen(p);
|
||||
envp[index] = _strdup(p);
|
||||
if (!envp[index])
|
||||
{
|
||||
for (index -= 1; index >= 0; --index)
|
||||
{
|
||||
free(envp[index]);
|
||||
}
|
||||
free((void*)envp);
|
||||
return nullptr;
|
||||
}
|
||||
p += (length + 1);
|
||||
index++;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DWORD result = 0;
|
||||
DWORD nSizeW = 0;
|
||||
LPWSTR lpNameW = nullptr;
|
||||
LPWSTR lpBufferW = nullptr;
|
||||
LPSTR lpBufferA = lpBuffer;
|
||||
|
||||
lpNameW = ConvertUtf8ToWCharAlloc(lpName, nullptr);
|
||||
if (!lpNameW)
|
||||
goto cleanup;
|
||||
|
||||
if (!lpBuffer)
|
||||
{
|
||||
char lpBufferMaxA[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WCHAR lpBufferMaxW[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
LPSTR lpTmpBuffer = lpBufferMaxA;
|
||||
|
||||
nSizeW = ARRAYSIZE(lpBufferMaxW);
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferMaxW, nSizeW);
|
||||
|
||||
SSIZE_T rc =
|
||||
ConvertWCharNToUtf8(lpBufferMaxW, nSizeW, lpTmpBuffer, ARRAYSIZE(lpBufferMaxA));
|
||||
if ((rc < 0) || (rc >= UINT32_MAX))
|
||||
goto cleanup;
|
||||
|
||||
result = (DWORD)rc + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSizeW = nSize;
|
||||
lpBufferW = calloc(nSizeW + 1, sizeof(WCHAR));
|
||||
|
||||
if (!lpBufferW)
|
||||
goto cleanup;
|
||||
|
||||
result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
|
||||
|
||||
if (result == 0)
|
||||
goto cleanup;
|
||||
|
||||
SSIZE_T rc = ConvertWCharNToUtf8(lpBufferW, nSizeW, lpBufferA, nSize);
|
||||
if ((rc < 0) || (rc > UINT32_MAX))
|
||||
goto cleanup;
|
||||
|
||||
result = (DWORD)rc;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(lpBufferW);
|
||||
free(lpNameW);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
DWORD GetEnvironmentVariableX(const char* lpName, char* lpBuffer, DWORD nSize)
|
||||
{
|
||||
return GetEnvironmentVariableA(lpName, lpBuffer, nSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
25
third_party/FreeRDP/winpr/libwinpr/environment/test/CMakeLists.txt
vendored
Normal file
25
third_party/FreeRDP/winpr/libwinpr/environment/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
set(MODULE_NAME "TestEnvironment")
|
||||
set(MODULE_PREFIX "TEST_ENVIRONMENT")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestEnvironmentGetEnvironmentStrings.c TestEnvironmentSetEnvironmentVariable.c
|
||||
TestEnvironmentMergeEnvironmentStrings.c TestEnvironmentGetSetEB.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
41
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c
vendored
Normal file
41
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetEnvironmentStrings.c
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/environment.h>
|
||||
|
||||
int TestEnvironmentGetEnvironmentStrings(int argc, char* argv[])
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
LPTCH lpszEnvironmentBlock = GetEnvironmentStrings();
|
||||
if (!lpszEnvironmentBlock)
|
||||
goto fail;
|
||||
|
||||
TCHAR* p = lpszEnvironmentBlock;
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
const size_t max = _tcslen(p);
|
||||
const int rc = _sntprintf(nullptr, 0, _T("%s\n"), p);
|
||||
if (rc < 1)
|
||||
{
|
||||
_tprintf(_T("test failed: return %d\n"), rc);
|
||||
goto fail;
|
||||
}
|
||||
if (max != (size_t)(rc - 1))
|
||||
{
|
||||
_tprintf(_T("test failed: length %") _T(PRIuz) _T(" != %d [%s]\n"), max, rc - 1, p);
|
||||
goto fail;
|
||||
}
|
||||
p += (max + 1);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
fail:
|
||||
FreeEnvironmentStrings(lpszEnvironmentBlock);
|
||||
|
||||
return r;
|
||||
}
|
||||
138
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c
vendored
Normal file
138
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/environment.h>
|
||||
|
||||
int TestEnvironmentGetSetEB(int argc, char* argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
#ifndef _WIN32
|
||||
char test[1024];
|
||||
TCHAR* p = nullptr;
|
||||
DWORD length = 0;
|
||||
LPTCH lpszEnvironmentBlock = "SHELL=123\0test=1\0test1=2\0DISPLAY=WINPR_TEST_VALUE\0\0";
|
||||
LPTCH lpszEnvironmentBlockNew = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
rc = -1;
|
||||
/* Get length of an variable */
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "DISPLAY", nullptr, 0);
|
||||
|
||||
if (0 == length)
|
||||
return -1;
|
||||
|
||||
/* Get the variable itself */
|
||||
p = (LPSTR)malloc(length);
|
||||
|
||||
if (!p)
|
||||
goto fail;
|
||||
|
||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlock, "DISPLAY", p, length) != length - 1)
|
||||
goto fail;
|
||||
|
||||
printf("GetEnvironmentVariableA(WINPR_TEST_VARIABLE) = %s\n", p);
|
||||
|
||||
if (strcmp(p, "WINPR_TEST_VALUE") != 0)
|
||||
goto fail;
|
||||
|
||||
/* Get length of an non-existing variable */
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "BLA", nullptr, 0);
|
||||
|
||||
if (0 != length)
|
||||
{
|
||||
printf("Unset variable returned\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get length of an similar called variables */
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "XDISPLAY", nullptr, 0);
|
||||
|
||||
if (0 != length)
|
||||
{
|
||||
printf("Similar named variable returned (XDISPLAY, length %d)\n", length);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "DISPLAYX", nullptr, 0);
|
||||
|
||||
if (0 != length)
|
||||
{
|
||||
printf("Similar named variable returned (DISPLAYX, length %d)\n", length);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "DISPLA", nullptr, 0);
|
||||
|
||||
if (0 != length)
|
||||
{
|
||||
printf("Similar named variable returned (DISPLA, length %d)\n", length);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock, "ISPLAY", nullptr, 0);
|
||||
|
||||
if (0 != length)
|
||||
{
|
||||
printf("Similar named variable returned (ISPLAY, length %d)\n", length);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set variable in empty environment block */
|
||||
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5"))
|
||||
{
|
||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew, "test", test, 1023))
|
||||
{
|
||||
if (strcmp(test, "5") != 0)
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Clear variable */
|
||||
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", nullptr))
|
||||
{
|
||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew, "test", test, 1023))
|
||||
goto fail;
|
||||
else
|
||||
{
|
||||
// not found .. this is expected
|
||||
}
|
||||
}
|
||||
|
||||
free(lpszEnvironmentBlockNew);
|
||||
lpszEnvironmentBlockNew = (LPTCH)calloc(1024, sizeof(TCHAR));
|
||||
|
||||
if (!lpszEnvironmentBlockNew)
|
||||
goto fail;
|
||||
|
||||
memcpy(lpszEnvironmentBlockNew, lpszEnvironmentBlock, length);
|
||||
|
||||
/* Set variable in empty environment block */
|
||||
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5"))
|
||||
{
|
||||
if (0 != GetEnvironmentVariableEBA(lpszEnvironmentBlockNew, "testr", test, 1023))
|
||||
{
|
||||
printf("GetEnvironmentVariableEBA returned unset variable\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew, "test", test, 1023))
|
||||
{
|
||||
if (strcmp(test, "5") != 0)
|
||||
goto fail;
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(p);
|
||||
free(lpszEnvironmentBlockNew);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
34
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c
vendored
Normal file
34
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentMergeEnvironmentStrings.c
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/environment.h>
|
||||
|
||||
int TestEnvironmentMergeEnvironmentStrings(int argc, char* argv[])
|
||||
{
|
||||
#ifndef _WIN32
|
||||
TCHAR* p = nullptr;
|
||||
size_t length = 0;
|
||||
LPTCH lpszEnvironmentBlock = nullptr;
|
||||
LPTCH lpsz2Merge = "SHELL=123\0test=1\0test1=2\0DISPLAY=:77\0\0";
|
||||
LPTCH lpszMergedEnvironmentBlock = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
lpszEnvironmentBlock = GetEnvironmentStrings();
|
||||
lpszMergedEnvironmentBlock = MergeEnvironmentStrings(lpszEnvironmentBlock, lpsz2Merge);
|
||||
p = (TCHAR*)lpszMergedEnvironmentBlock;
|
||||
|
||||
while (p[0] && p[1])
|
||||
{
|
||||
printf("%s\n", p);
|
||||
length = strlen(p);
|
||||
p += (length + 1);
|
||||
}
|
||||
|
||||
FreeEnvironmentStrings(lpszMergedEnvironmentBlock);
|
||||
FreeEnvironmentStrings(lpszEnvironmentBlock);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
72
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentSetEnvironmentVariable.c
vendored
Normal file
72
third_party/FreeRDP/winpr/libwinpr/environment/test/TestEnvironmentSetEnvironmentVariable.c
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/environment.h>
|
||||
#include <winpr/error.h>
|
||||
|
||||
#define TEST_NAME "WINPR_TEST_VARIABLE"
|
||||
#define TEST_VALUE "WINPR_TEST_VALUE"
|
||||
int TestEnvironmentSetEnvironmentVariable(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
DWORD nSize = 0;
|
||||
LPSTR lpBuffer = nullptr;
|
||||
DWORD error = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
SetEnvironmentVariableA(TEST_NAME, TEST_VALUE);
|
||||
nSize = GetEnvironmentVariableA(TEST_NAME, nullptr, 0);
|
||||
|
||||
/* check if value returned is len + 1 ) */
|
||||
if (nSize != strnlen(TEST_VALUE, sizeof(TEST_VALUE)) + 1)
|
||||
{
|
||||
printf("GetEnvironmentVariableA not found error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lpBuffer = (LPSTR)malloc(nSize);
|
||||
|
||||
if (!lpBuffer)
|
||||
return -1;
|
||||
|
||||
nSize = GetEnvironmentVariableA(TEST_NAME, lpBuffer, nSize);
|
||||
|
||||
if (nSize != strnlen(TEST_VALUE, sizeof(TEST_VALUE)))
|
||||
{
|
||||
printf("GetEnvironmentVariableA wrong size returned\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (strcmp(lpBuffer, TEST_VALUE) != 0)
|
||||
{
|
||||
printf("GetEnvironmentVariableA returned value doesn't match\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nSize = GetEnvironmentVariableA("__xx__notset_", lpBuffer, nSize);
|
||||
error = GetLastError();
|
||||
|
||||
if (0 != nSize || ERROR_ENVVAR_NOT_FOUND != error)
|
||||
{
|
||||
printf("GetEnvironmentVariableA not found error\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* clear variable */
|
||||
SetEnvironmentVariableA(TEST_NAME, nullptr);
|
||||
nSize = GetEnvironmentVariableA(TEST_VALUE, nullptr, 0);
|
||||
|
||||
if (0 != nSize)
|
||||
{
|
||||
printf("SetEnvironmentVariableA failed to clear variable\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(lpBuffer);
|
||||
return rc;
|
||||
}
|
||||
Reference in New Issue
Block a user