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;
253LPCH GetEnvironmentStringsA(VOID)
257 char** envp = environ;
258 const size_t blocksize = 128;
259 size_t cchEnvironmentBlock = blocksize;
260 LPCH lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock,
sizeof(CHAR));
262 if (!lpszEnvironmentBlock)
267 const size_t length = strlen(*envp);
268 const size_t required = offset + length + 8ull;
269 if (required > UINT32_MAX)
271 WLog_ERR(TAG,
"Environment block too large: %" PRIuz, required);
273 free(lpszEnvironmentBlock);
277 if (required > cchEnvironmentBlock)
279 size_t new_size = cchEnvironmentBlock;
282 new_size += blocksize;
283 }
while (new_size <= required);
284 LPCH new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size *
sizeof(CHAR));
287 free(lpszEnvironmentBlock);
291 lpszEnvironmentBlock = new_blk;
292 cchEnvironmentBlock = new_size;
295 char* p = &(lpszEnvironmentBlock[offset]);
297 CopyMemory(p, *envp, length *
sizeof(CHAR));
300 offset += (length + 1ull);
304 lpszEnvironmentBlock[offset] =
'\0';
306 return lpszEnvironmentBlock;
312LPWCH GetEnvironmentStringsW(VOID)
314 WLog_ERR(TAG,
"TODO: not implemented");
318BOOL SetEnvironmentStringsA(WINPR_ATTR_UNUSED LPCH NewEnvironment)
320 WLog_ERR(TAG,
"TODO: not implemented");
324BOOL SetEnvironmentStringsW(WINPR_ATTR_UNUSED LPWCH NewEnvironment)
326 WLog_ERR(TAG,
"TODO: not implemented");
330DWORD ExpandEnvironmentStringsA(WINPR_ATTR_UNUSED LPCSTR lpSrc, WINPR_ATTR_UNUSED LPSTR lpDst,
331 WINPR_ATTR_UNUSED DWORD nSize)
333 WLog_ERR(TAG,
"TODO: not implemented");
337DWORD ExpandEnvironmentStringsW(WINPR_ATTR_UNUSED LPCWSTR lpSrc, WINPR_ATTR_UNUSED LPWSTR lpDst,
338 WINPR_ATTR_UNUSED DWORD nSize)
340 WLog_ERR(TAG,
"TODO: not implemented");
344BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
346 free(lpszEnvironmentBlock);
351BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock)
353 free(lpszEnvironmentBlock);
360LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
362 const char* cp =
nullptr;
366 const char* envp =
nullptr;
367 DWORD cchEnvironmentBlock = 0;
368 LPCH lpszEnvironmentBlock =
nullptr;
369 const char** mergeStrings =
nullptr;
370 size_t mergeStringLength = 0;
371 size_t mergeArraySize = 128;
372 size_t mergeLength = 0;
373 size_t foundMerge = 0;
374 char* foundEquals =
nullptr;
376 mergeStrings = (LPCSTR*)calloc(mergeArraySize,
sizeof(
char*));
381 mergeStringLength = 0;
385 while (*cp && *(cp + 1))
389 if (mergeStringLength == mergeArraySize)
391 const char** new_str =
nullptr;
393 mergeArraySize += 128;
394 new_str = (
const char**)realloc((
void*)mergeStrings, mergeArraySize *
sizeof(
char*));
398 free((
void*)mergeStrings);
401 mergeStrings = new_str;
404 mergeStrings[mergeStringLength] = cp;
411 cchEnvironmentBlock = 128;
412 lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock,
sizeof(CHAR));
414 if (!lpszEnvironmentBlock)
416 free((
void*)mergeStrings);
422 while ((original !=
nullptr) && (*envp && *(envp + 1)))
424 size_t old_offset = offset;
425 length = strlen(envp);
427 while ((offset + length + 8) > cchEnvironmentBlock)
429 cchEnvironmentBlock *= 2;
430 LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
434 free((
void*)lpszEnvironmentBlock);
435 free((
void*)mergeStrings);
438 lpszEnvironmentBlock = tmp;
441 p = &(lpszEnvironmentBlock[offset]);
445 for (
size_t run = 0; run < mergeStringLength; run++)
447 if (!mergeStrings[run])
450 mergeLength = strlen(mergeStrings[run]);
451 foundEquals = strstr(mergeStrings[run],
"=");
456 const intptr_t len = foundEquals - mergeStrings[run] + 1;
457 if (strncmp(envp, mergeStrings[run], WINPR_ASSERTING_INT_CAST(
size_t, len)) == 0)
460 if (*(foundEquals + 1) ==
'\0')
467 while ((offset + mergeLength + 8) > cchEnvironmentBlock)
469 cchEnvironmentBlock *= 2;
471 (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
475 free((
void*)lpszEnvironmentBlock);
476 free((
void*)mergeStrings);
479 lpszEnvironmentBlock = tmp;
480 p = &(lpszEnvironmentBlock[old_offset]);
484 CopyMemory(p, mergeStrings[run], mergeLength);
485 mergeStrings[run] =
nullptr;
486 p[mergeLength] =
'\0';
487 offset += (mergeLength + 1);
494 CopyMemory(p, envp, length *
sizeof(CHAR));
496 offset += (length + 1);
499 envp += (length + 1);
503 for (
size_t run = 0; run < mergeStringLength; run++)
505 if (!mergeStrings[run])
508 mergeLength = strlen(mergeStrings[run]);
510 while ((offset + mergeLength + 8) > cchEnvironmentBlock)
512 cchEnvironmentBlock *= 2;
513 LPCH tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock *
sizeof(CHAR));
517 free((
void*)lpszEnvironmentBlock);
518 free((
void*)mergeStrings);
522 lpszEnvironmentBlock = tmp;
525 p = &(lpszEnvironmentBlock[offset]);
527 CopyMemory(p, mergeStrings[run], mergeLength);
528 mergeStrings[run] =
nullptr;
529 p[mergeLength] =
'\0';
530 offset += (mergeLength + 1);
533 lpszEnvironmentBlock[offset] =
'\0';
535 free((
void*)mergeStrings);
537 return lpszEnvironmentBlock;
540DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
544 char* foundEquals =
nullptr;
545 const char* penvb = envBlock;
548 size_t lpNameLength = 0;
550 if (!lpName ||
nullptr == envBlock)
553 lpNameLength = strlen(lpName);
555 if (lpNameLength < 1)
558 while (*penvb && *(penvb + 1))
560 fLength = strlen(penvb);
561 foundEquals = strstr(penvb,
"=");
569 nLength = WINPR_ASSERTING_INT_CAST(
size_t, (foundEquals - penvb));
571 if (nLength != lpNameLength)
573 penvb += (fLength + 1);
577 if (strncmp(penvb, lpName, nLength) == 0)
579 env = foundEquals + 1;
583 penvb += (fLength + 1);
589 vLength = strlen(env);
590 if (vLength >= UINT32_MAX)
593 if ((vLength + 1 > nSize) || (!lpBuffer))
594 return (DWORD)vLength + 1;
596 CopyMemory(lpBuffer, env, vLength + 1);
598 return (DWORD)vLength;
601BOOL SetEnvironmentVariableEBA(LPSTR* envBlock, LPCSTR lpName, LPCSTR lpValue)
604 char* envstr =
nullptr;
605 char* newEB =
nullptr;
612 length = (strlen(lpName) + strlen(lpValue) + 2);
613 envstr = (
char*)malloc(length + 1);
618 (void)sprintf_s(envstr, length,
"%s=%s", lpName, lpValue);
622 length = strlen(lpName) + 2;
623 envstr = (
char*)malloc(length + 1);
628 (void)sprintf_s(envstr, length,
"%s=", lpName);
631 envstr[length] =
'\0';
633 newEB = MergeEnvironmentStrings((LPCSTR)*envBlock, envstr);
643char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
649 char** envp =
nullptr;
652 if (!lpszEnvironmentBlock)
655 p = (
char*)lpszEnvironmentBlock;
665 p = (
char*)lpszEnvironmentBlock;
667 envp = (
char**)calloc(count + 1,
sizeof(
char*));
670 envp[count] =
nullptr;
675 envp[index] = _strdup(p);
678 for (index -= 1; index >= 0; --index)
695#define WINPR_MAX_ENVIRONMENT_LENGTH 2048
697DWORD GetEnvironmentVariableX(
const char* lpName,
char* lpBuffer, DWORD nSize)
701 LPWSTR lpNameW =
nullptr;
702 LPWSTR lpBufferW =
nullptr;
703 LPSTR lpBufferA = lpBuffer;
705 lpNameW = ConvertUtf8ToWCharAlloc(lpName,
nullptr);
711 char lpBufferMaxA[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
712 WCHAR lpBufferMaxW[WINPR_MAX_ENVIRONMENT_LENGTH] = WINPR_C_ARRAY_INIT;
713 LPSTR lpTmpBuffer = lpBufferMaxA;
715 nSizeW = ARRAYSIZE(lpBufferMaxW);
717 result = GetEnvironmentVariableW(lpNameW, lpBufferMaxW, nSizeW);
720 ConvertWCharNToUtf8(lpBufferMaxW, nSizeW, lpTmpBuffer, ARRAYSIZE(lpBufferMaxA));
721 if ((rc < 0) || (rc >= UINT32_MAX))
724 result = (DWORD)rc + 1;
729 lpBufferW = calloc(nSizeW + 1,
sizeof(WCHAR));
734 result = GetEnvironmentVariableW(lpNameW, lpBufferW, nSizeW);
739 SSIZE_T rc = ConvertWCharNToUtf8(lpBufferW, nSizeW, lpBufferA, nSize);
740 if ((rc < 0) || (rc > UINT32_MAX))
755DWORD GetEnvironmentVariableX(
const char* lpName,
char* lpBuffer, DWORD nSize)
757 return GetEnvironmentVariableA(lpName, lpBuffer, nSize);