22#include <winpr/config.h>
25#include <winpr/platform.h>
26#include <winpr/error.h>
27#include <winpr/file.h>
28#include <winpr/string.h>
29#include <winpr/wlog.h>
31#include <winpr/environment.h>
35#define TAG WINPR_TAG("environment")
41#ifdef WINPR_HAVE_UNISTD_H
47#elif defined(__MACOSX__)
48#include <crt_externs.h>
49#define environ (*_NSGetEnviron())
52DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer)
61 char* tmp = realloc(cwd, length);
69 ccwd = getcwd(cwd, length);
70 }
while (!ccwd && (errno == ERANGE));
78 length = strnlen(cwd, length);
80 if ((nBufferLength == 0) && (lpBuffer ==
nullptr))
87 if (lpBuffer ==
nullptr)
93 if ((length + 1) > nBufferLength)
96 return (DWORD)(length + 1);
99 memcpy(lpBuffer, cwd, length + 1);
101 return (DWORD)length;
105DWORD GetCurrentDirectoryW(WINPR_ATTR_UNUSED DWORD nBufferLength, WINPR_ATTR_UNUSED LPWSTR lpBuffer)
107 WLog_ERR(TAG,
"TODO: not implemented");
111BOOL SetCurrentDirectoryA(WINPR_ATTR_UNUSED LPCSTR lpPathName)
113 WLog_ERR(TAG,
"TODO: not implemented");
117BOOL SetCurrentDirectoryW(WINPR_ATTR_UNUSED LPCWSTR lpPathName)
119 WLog_ERR(TAG,
"TODO: not implemented");
123DWORD SearchPathA(WINPR_ATTR_UNUSED LPCSTR lpPath, WINPR_ATTR_UNUSED LPCSTR lpFileName,
124 WINPR_ATTR_UNUSED LPCSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
125 WINPR_ATTR_UNUSED LPSTR lpBuffer, WINPR_ATTR_UNUSED LPSTR* lpFilePart)
127 WLog_ERR(TAG,
"TODO: not implemented");
131DWORD SearchPathW(WINPR_ATTR_UNUSED LPCWSTR lpPath, WINPR_ATTR_UNUSED LPCWSTR lpFileName,
132 WINPR_ATTR_UNUSED LPCWSTR lpExtension, WINPR_ATTR_UNUSED DWORD nBufferLength,
133 WINPR_ATTR_UNUSED LPWSTR lpBuffer, WINPR_ATTR_UNUSED LPWSTR* lpFilePart)
135 WLog_ERR(TAG,
"TODO: not implemented");
139LPSTR GetCommandLineA(VOID)
141 WLog_ERR(TAG,
"TODO: not implemented");
145LPWSTR GetCommandLineW(VOID)
147 WLog_ERR(TAG,
"TODO: not implemented");
151BOOL NeedCurrentDirectoryForExePathA(WINPR_ATTR_UNUSED LPCSTR ExeName)
153 WLog_ERR(TAG,
"TODO: not implemented");
157BOOL NeedCurrentDirectoryForExePathW(WINPR_ATTR_UNUSED LPCWSTR ExeName)
159 WLog_ERR(TAG,
"TODO: not implemented");
165#if !defined(_WIN32) || defined(_UWP)
167DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
173 char* env = getenv(lpName);
177 SetLastError(ERROR_ENVVAR_NOT_FOUND);
181 length = strlen(env);
183 if ((length + 1 > nSize) || (!lpBuffer))
184 return (DWORD)length + 1;
186 CopyMemory(lpBuffer, env, length);
187 lpBuffer[length] =
'\0';
189 return (DWORD)length;
191 SetLastError(ERROR_ENVVAR_NOT_FOUND);
196DWORD GetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPWSTR lpBuffer,
197 WINPR_ATTR_UNUSED DWORD nSize)
199 WLog_ERR(TAG,
"TODO: not implemented");
200 SetLastError(ERROR_ENVVAR_NOT_FOUND);
204BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue)
213 if (0 != setenv(lpName, lpValue, 1))
219 if (0 != unsetenv(lpName))
229BOOL SetEnvironmentVariableW(WINPR_ATTR_UNUSED LPCWSTR lpName, WINPR_ATTR_UNUSED LPCWSTR lpValue)
231 WLog_ERR(TAG,
"TODO: not implemented");
251extern char** environ;
253WINPR_ATTR_MALLOC(FreeEnvironmentStringsA, 1)
254static LPCH GetEnvironmentStringsAN(
size_t* pLen)
258 char** envp = environ;
259 const size_t blocksize = 128;
260 size_t cchEnvironmentBlock = blocksize;
261 LPCH lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock,
sizeof(CHAR));
266 if (!lpszEnvironmentBlock)
271 const size_t length = strlen(*envp);
272 const size_t required = offset + length + 8ull;
273 if (required > UINT32_MAX)
275 WLog_ERR(TAG,
"Environment block too large: %" PRIuz, required);
277 free(lpszEnvironmentBlock);
281 if (required > cchEnvironmentBlock)
283 size_t new_size = cchEnvironmentBlock;
286 new_size += blocksize;
287 }
while (new_size <= required);
288 LPCH new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size *
sizeof(CHAR));
291 free(lpszEnvironmentBlock);
295 const size_t diff = new_size - cchEnvironmentBlock;
296 const size_t old = cchEnvironmentBlock;
297 lpszEnvironmentBlock = new_blk;
298 cchEnvironmentBlock = new_size;
300 memset(&lpszEnvironmentBlock[old], 0, diff);
303 char* p = &(lpszEnvironmentBlock[offset]);
305 CopyMemory(p, *envp, length *
sizeof(CHAR));
308 offset += (length + 1ull);
312 lpszEnvironmentBlock[offset] =
'\0';
314 *pLen = cchEnvironmentBlock;
316 return lpszEnvironmentBlock;
324LPCH GetEnvironmentStringsA(VOID)
326 return GetEnvironmentStringsAN(
nullptr);
329LPWCH GetEnvironmentStringsW(VOID)
332 LPCH env = GetEnvironmentStringsAN(&len);
335 LPWCH envW = ConvertMszUtf8NToWCharAlloc(env, len,
nullptr);
336 FreeEnvironmentStringsA(env);
340BOOL SetEnvironmentStringsA(WINPR_ATTR_UNUSED LPCH NewEnvironment)
342 WLog_ERR(TAG,
"TODO: not implemented");
346BOOL SetEnvironmentStringsW(WINPR_ATTR_UNUSED LPWCH NewEnvironment)
348 WLog_ERR(TAG,
"TODO: not implemented");
352DWORD ExpandEnvironmentStringsA(WINPR_ATTR_UNUSED LPCSTR lpSrc, WINPR_ATTR_UNUSED LPSTR lpDst,
353 WINPR_ATTR_UNUSED DWORD nSize)
355 WLog_ERR(TAG,
"TODO: not implemented");
359DWORD ExpandEnvironmentStringsW(WINPR_ATTR_UNUSED LPCWSTR lpSrc, WINPR_ATTR_UNUSED LPWSTR lpDst,
360 WINPR_ATTR_UNUSED DWORD nSize)
362 WLog_ERR(TAG,
"TODO: not implemented");
366BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
368 free(lpszEnvironmentBlock);
373BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock)
375 free(lpszEnvironmentBlock);
382LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
384 const char* cp =
nullptr;
388 const char* envp =
nullptr;
389 DWORD cchEnvironmentBlock = 0;
390 LPCH lpszEnvironmentBlock =
nullptr;
391 const char** mergeStrings =
nullptr;
392 size_t mergeStringLength = 0;
393 size_t mergeArraySize = 128;
394 size_t mergeLength = 0;
395 size_t foundMerge = 0;
396 char* foundEquals =
nullptr;
398 mergeStrings = (LPCSTR*)calloc(mergeArraySize,
sizeof(
char*));
403 mergeStringLength = 0;
407 while (*cp && *(cp + 1))
411 if (mergeStringLength == mergeArraySize)
413 const char** new_str =
nullptr;
415 mergeArraySize += 128;
416 new_str = (
const char**)realloc((
void*)mergeStrings, mergeArraySize *
sizeof(
char*));
420 free((
void*)mergeStrings);
423 mergeStrings = new_str;
426 mergeStrings[mergeStringLength] = cp;
433 cchEnvironmentBlock = 128;
434 lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock,
sizeof(CHAR));
436 if (!lpszEnvironmentBlock)
438 free((
void*)mergeStrings);
444 while ((original !=
nullptr) && (*envp && *(envp + 1)))
446 size_t old_offset = offset;
447 length = strlen(envp);
449 while ((offset + length + 8) > cchEnvironmentBlock)
451 cchEnvironmentBlock *= 2;
452 LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
456 free((
void*)lpszEnvironmentBlock);
457 free((
void*)mergeStrings);
460 lpszEnvironmentBlock = tmp;
463 p = &(lpszEnvironmentBlock[offset]);
467 for (
size_t run = 0; run < mergeStringLength; run++)
469 if (!mergeStrings[run])
472 mergeLength = strlen(mergeStrings[run]);
473 foundEquals = strstr(mergeStrings[run],
"=");
478 const intptr_t len = foundEquals - mergeStrings[run] + 1;
479 if (strncmp(envp, mergeStrings[run], WINPR_ASSERTING_INT_CAST(
size_t, len)) == 0)
482 if (*(foundEquals + 1) ==
'\0')
489 while ((offset + mergeLength + 8) > cchEnvironmentBlock)
491 cchEnvironmentBlock *= 2;
493 (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
497 free((
void*)lpszEnvironmentBlock);
498 free((
void*)mergeStrings);
501 lpszEnvironmentBlock = tmp;
502 p = &(lpszEnvironmentBlock[old_offset]);
506 CopyMemory(p, mergeStrings[run], mergeLength);
507 mergeStrings[run] =
nullptr;
508 p[mergeLength] =
'\0';
509 offset += (mergeLength + 1);
516 CopyMemory(p, envp, length *
sizeof(CHAR));
518 offset += (length + 1);
521 envp += (length + 1);
525 for (
size_t run = 0; run < mergeStringLength; run++)
527 if (!mergeStrings[run])
530 mergeLength = strlen(mergeStrings[run]);
532 while ((offset + mergeLength + 8) > cchEnvironmentBlock)
534 cchEnvironmentBlock *= 2;
535 LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
539 free((
void*)lpszEnvironmentBlock);
540 free((
void*)mergeStrings);
544 lpszEnvironmentBlock = tmp;
547 p = &(lpszEnvironmentBlock[offset]);
549 CopyMemory(p, mergeStrings[run], mergeLength);
550 mergeStrings[run] =
nullptr;
551 p[mergeLength] =
'\0';
552 offset += (mergeLength + 1);
555 lpszEnvironmentBlock[offset] =
'\0';
557 free((
void*)mergeStrings);
559 return lpszEnvironmentBlock;
562DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
566 char* foundEquals =
nullptr;
567 const char* penvb = envBlock;
570 size_t lpNameLength = 0;
572 if (!lpName ||
nullptr == envBlock)
575 lpNameLength = strlen(lpName);
577 if (lpNameLength < 1)
580 while (*penvb && *(penvb + 1))
582 fLength = strlen(penvb);
583 foundEquals = strstr(penvb,
"=");
591 nLength = WINPR_ASSERTING_INT_CAST(
size_t, (foundEquals - penvb));
593 if (nLength != lpNameLength)
595 penvb += (fLength + 1);
599 if (strncmp(penvb, lpName, nLength) == 0)
601 env = foundEquals + 1;
605 penvb += (fLength + 1);
611 vLength = strlen(env);
612 if (vLength >= UINT32_MAX)
615 if ((vLength + 1 > nSize) || (!lpBuffer))
616 return (DWORD)vLength + 1;
618 CopyMemory(lpBuffer, env, vLength + 1);
620 return (DWORD)vLength;
623BOOL SetEnvironmentVariableEBA(LPSTR* envBlock, LPCSTR lpName, LPCSTR lpValue)
626 char* envstr =
nullptr;
627 char* newEB =
nullptr;
634 length = (strlen(lpName) + strlen(lpValue) + 2);
635 envstr = (
char*)malloc(length + 1);
640 (void)sprintf_s(envstr, length,
"%s=%s", lpName, lpValue);
644 length = strlen(lpName) + 2;
645 envstr = (
char*)malloc(length + 1);
650 (void)sprintf_s(envstr, length,
"%s=", lpName);
653 envstr[length] =
'\0';
655 newEB = MergeEnvironmentStrings((LPCSTR)*envBlock, envstr);
665char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
671 char** envp =
nullptr;
674 if (!lpszEnvironmentBlock)
677 p = (
char*)lpszEnvironmentBlock;
687 p = (
char*)lpszEnvironmentBlock;
689 envp = (
char**)calloc(count + 1,
sizeof(
char*));
692 envp[count] =
nullptr;
697 envp[index] = _strdup(p);
700 for (index -= 1; index >= 0; --index)
717#define WINPR_MAX_ENVIRONMENT_LENGTH 2048
719DWORD GetEnvironmentVariableX(
const char* lpName,
char* lpBuffer, DWORD nSize)
723 LPWSTR lpNameW =
nullptr;
724 LPWSTR lpBufferW =
nullptr;
725 LPSTR lpBufferA = lpBuffer;
727 lpNameW = ConvertUtf8ToWCharAlloc(lpName,
nullptr);
733 char lpBufferMaxA[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
734 WCHAR lpBufferMaxW[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
735 LPSTR lpTmpBuffer = lpBufferMaxA;
737 nSizeW = ARRAYSIZE(lpBufferMaxW);
739 result = GetEnvironmentVariableW(lpNameW, lpBufferMaxW, nSizeW);
742 ConvertWCharNToUtf8(lpBufferMaxW, nSizeW, lpTmpBuffer, ARRAYSIZE(lpBufferMaxA));
743 if ((rc < 0) || (rc >= UINT32_MAX))
746 result = (DWORD)rc + 1;
751 lpBufferW = calloc(nSizeW + 1,
sizeof(WCHAR));
756 result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
761 SSIZE_T rc = ConvertWCharNToUtf8(lpBufferW, nSizeW, lpBufferA, nSize);
762 if ((rc < 0) || (rc > UINT32_MAX))
777DWORD GetEnvironmentVariableX(
const char* lpName,
char* lpBuffer, DWORD nSize)
779 return GetEnvironmentVariableA(lpName, lpBuffer, nSize);