WINPR_API BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue);
WINPR_API BOOL SetEnvironmentVariableW(LPCWSTR lpName, LPCWSTR lpValue);
+/**
+ * A brief history of the GetEnvironmentStrings functions:
+ * http://blogs.msdn.com/b/oldnewthing/archive/2013/01/17/10385718.aspx
+ */
+
WINPR_API LPCH GetEnvironmentStrings(VOID);
WINPR_API LPWCH GetEnvironmentStringsW(VOID);
#define NeedCurrentDirectoryForExePath NeedCurrentDirectoryForExePathW
#define GetEnvironmentVariable GetEnvironmentVariableW
#define SetEnvironmentVariable SetEnvironmentVariableW
+#define GetEnvironmentStrings GetEnvironmentStringsW
#define SetEnvironmentStrings SetEnvironmentStringsW
#define ExpandEnvironmentStrings ExpandEnvironmentStringsW
#define FreeEnvironmentStrings FreeEnvironmentStringsW
#define NeedCurrentDirectoryForExePath NeedCurrentDirectoryForExePathA
#define GetEnvironmentVariable GetEnvironmentVariableA
#define SetEnvironmentVariable SetEnvironmentVariableA
+#define GetEnvironmentStringsA GetEnvironmentStrings
#define SetEnvironmentStrings SetEnvironmentStringsA
#define ExpandEnvironmentStrings ExpandEnvironmentStringsA
#define FreeEnvironmentStrings FreeEnvironmentStringsA
#endif
DECLSPEC_NORETURN WINPR_API VOID ExitProcess(UINT uExitCode);
+WINPR_API BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);
WINPR_API HANDLE _GetCurrentProcess(void);
WINPR_API DWORD GetCurrentProcessId(void);
typedef signed __int64 LONG64;
#endif
-typedef CHAR* PSTR, *LPSTR, *LPCH;
+typedef CHAR *PSTR, *LPSTR, *LPCH;
typedef const CHAR *LPCSTR,*PCSTR;
-typedef WCHAR* LPWSTR, *PWSTR, *LPWCH;
+typedef WCHAR *LPWSTR, *PWSTR, *LPWCH;
typedef const WCHAR *LPCWSTR,*PCWSTR;
typedef unsigned __int64 QWORD;
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
+
+if(BUILD_TESTING)
+ add_subdirectory(test)
+endif()
BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue)
{
+ int length;
+ char* envstr;
+
+ if (!lpName)
+ return FALSE;
+
+ if (lpValue)
+ {
+ length = strlen(lpName) + strlen(lpValue) + 1;
+ envstr = (char*) malloc(length + 1);
+ sprintf_s(envstr, length + 1, "%s=%s", lpName, lpValue);
+ envstr[length] = '\0';
+ putenv(envstr);
+ }
+ else
+ {
+ unsetenv(lpName);
+ }
+
return TRUE;
}
return TRUE;
}
+/**
+ * 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 GetEnvironmentStrings(VOID)
{
- return NULL;
+ char* p;
+ int offset;
+ int length;
+ char** envp;
+ DWORD cchEnvironmentBlock;
+ LPCH lpszEnvironmentBlock;
+
+ offset = 0;
+ envp = environ;
+
+ cchEnvironmentBlock = 128;
+ lpszEnvironmentBlock = (LPCH) malloc(cchEnvironmentBlock * sizeof(CHAR));
+
+ while (*envp)
+ {
+ length = strlen(*envp);
+
+ while ((offset + length + 8) > cchEnvironmentBlock)
+ {
+ cchEnvironmentBlock *= 2;
+ lpszEnvironmentBlock = (LPCH) realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
+ }
+
+ p = &(lpszEnvironmentBlock[offset]);
+
+ CopyMemory(p, *envp, length * sizeof(CHAR));
+ p[length] = '\0';
+
+ offset += (length + 1);
+ envp++;
+ }
+
+ lpszEnvironmentBlock[offset] = '\0';
+
+ return lpszEnvironmentBlock;
}
LPWCH GetEnvironmentStringsW(VOID)
BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
{
+ if (lpszEnvironmentBlock)
+ free(lpszEnvironmentBlock);
+
return TRUE;
}
--- /dev/null
+TestEnvironment
+TestEnvironment.c
+
--- /dev/null
+
+set(MODULE_NAME "TestEnvironment")
+set(MODULE_PREFIX "TEST_ENVIRONMENT")
+
+set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
+
+set(${MODULE_PREFIX}_TESTS
+ TestEnvironmentGetEnvironmentStrings.c
+ TestEnvironmentSetEnvironmentVariable.c)
+
+create_test_sourcelist(${MODULE_PREFIX}_SRCS
+ ${${MODULE_PREFIX}_DRIVER}
+ ${${MODULE_PREFIX}_TESTS})
+
+add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE winpr
+ MODULES winpr-environment)
+
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+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")
--- /dev/null
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/tchar.h>
+#include <winpr/environment.h>
+
+int TestEnvironmentGetEnvironmentStrings(int argc, char* argv[])
+{
+ TCHAR* p;
+ int length;
+ LPTCH lpszEnvironmentBlock;
+
+ lpszEnvironmentBlock = GetEnvironmentStrings();
+
+ p = (TCHAR*) lpszEnvironmentBlock;
+
+ while (p[0] && p[1])
+ {
+ printf("%s\n", p);
+ length = strlen(p);
+ p += (length + 1);
+ }
+
+ FreeEnvironmentStrings(lpszEnvironmentBlock);
+
+ return 0;
+}
+
--- /dev/null
+
+#include <stdio.h>
+#include <winpr/crt.h>
+#include <winpr/tchar.h>
+#include <winpr/environment.h>
+
+int TestEnvironmentSetEnvironmentVariable(int argc, char* argv[])
+{
+ DWORD nSize;
+ LPSTR lpBuffer;
+
+ SetEnvironmentVariableA("WINPR_TEST_VARIABLE", "WINPR_TEST_VALUE");
+
+ nSize = GetEnvironmentVariableA("WINPR_TEST_VARIABLE", NULL, 0);
+
+ lpBuffer = (LPSTR) malloc(nSize);
+ nSize = GetEnvironmentVariableA("WINPR_TEST_VARIABLE", lpBuffer, nSize);
+
+ printf("GetEnvironmentVariableA(WINPR_TEST_VARIABLE) = %s\n" , lpBuffer);
+
+ if (strcmp(lpBuffer, "WINPR_TEST_VALUE") != 0)
+ {
+ return -1;
+ }
+
+ free(lpBuffer);
+
+ return 0;
+}
+
{
return WAIT_FAILED;
}
+
+ process->dwExitCode = (DWORD) process->status;
}
else if (Type == HANDLE_TYPE_MUTEX)
{
#endif
#include <winpr/crt.h>
+#include <winpr/tchar.h>
+#include <winpr/environment.h>
#include <errno.h>
#include <spawn.h>
#include "../handle/handle.h"
+char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
+{
+ char* p;
+ int index;
+ int count;
+ int length;
+ char** envp = NULL;
+
+ count = 0;
+ p = (char*) lpszEnvironmentBlock;
+
+ while (p[0] && p[1])
+ {
+ length = strlen(p);
+ p += (length + 1);
+ count++;
+ }
+
+ index = 0;
+ p = (char*) lpszEnvironmentBlock;
+
+ envp = (char**) malloc(sizeof(char*) * (count + 1));
+ envp[count] = NULL;
+
+ while (p[0] && p[1])
+ {
+ length = strlen(p);
+ envp[index] = _strdup(p);
+ p += (length + 1);
+ index++;
+ }
+
+ return envp;
+}
+
BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
pid_t pid;
- char* envp;
int status;
int numArgs;
LPSTR* pArgs;
+ char** envp;
WINPR_THREAD* thread;
WINPR_PROCESS* process;
+ LPTCH lpszEnvironmentBlock;
pid = 0;
+ envp = NULL;
numArgs = 0;
+ lpszEnvironmentBlock = NULL;
pArgs = CommandLineToArgvA(lpCommandLine, &numArgs);
- envp = NULL;
+ if (lpEnvironment)
+ {
+ envp = EnvironmentBlockToEnvpA(lpEnvironment);
+ }
+ else
+ {
+ lpszEnvironmentBlock = GetEnvironmentStrings();
+ envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock);
+ }
- status = posix_spawnp(&pid, pArgs[0], NULL, NULL, pArgs, &envp);
+ status = posix_spawnp(&pid, pArgs[0], NULL, NULL, pArgs, envp);
if (status != 0)
return FALSE;
process->pid = pid;
process->status = 0;
+ process->dwExitCode = 0;
thread = (WINPR_THREAD*) malloc(sizeof(WINPR_THREAD));
}
+BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode)
+{
+ WINPR_PROCESS* process;
+
+ if (!hProcess)
+ return FALSE;
+
+ if (!lpExitCode)
+ return FALSE;
+
+ process = (WINPR_PROCESS*) hProcess;
+
+ *lpExitCode = process->dwExitCode;
+
+ return TRUE;
+}
+
HANDLE _GetCurrentProcess(VOID)
{
return NULL;
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
- MODULES winpr-thread winpr-heap)
+ MODULES winpr-thread winpr-heap winpr-environment)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
#include <winpr/tchar.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
+#include <winpr/environment.h>
int TestThreadCreateProcess(int argc, char* argv[])
{
BOOL status;
+ DWORD exitCode;
LPCTSTR lpApplicationName;
LPTSTR lpCommandLine;
LPSECURITY_ATTRIBUTES lpProcessAttributes;
LPCTSTR lpCurrentDirectory;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
+ LPTCH lpszEnvironmentBlock;
+
+ lpszEnvironmentBlock = GetEnvironmentStrings();
lpApplicationName = NULL;
- lpCommandLine = _T("ls -l /");
+ //lpCommandLine = _T("ls -l /");
+ lpCommandLine = _T("printenv");
lpProcessAttributes = NULL;
lpThreadAttributes = NULL;
bInheritHandles = FALSE;
dwCreationFlags = 0;
lpEnvironment = NULL;
+ lpEnvironment = lpszEnvironmentBlock;
lpCurrentDirectory = NULL;
ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
StartupInfo.cb = sizeof(STARTUPINFO);
&StartupInfo,
&ProcessInformation);
+ FreeEnvironmentStrings(lpszEnvironmentBlock);
+
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
+ status = GetExitCodeProcess(ProcessInformation.hProcess, &exitCode);
+
+ printf("Process exited with code: %d\n", exitCode);
+
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
pid_t pid;
int status;
+ DWORD dwExitCode;
};
typedef struct winpr_process WINPR_PROCESS;