environment.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * Process Environment Functions
  4. *
  5. * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. * Copyright 2013 Thincast Technologies GmbH
  7. * Copyright 2013 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include <winpr/crt.h>
  25. #include <winpr/platform.h>
  26. #include <winpr/error.h>
  27. #include <winpr/environment.h>
  28. #ifndef _WIN32
  29. #define stricmp strcasecmp
  30. #define strnicmp strncasecmp
  31. #include <winpr/crt.h>
  32. #include <winpr/platform.h>
  33. #ifdef HAVE_UNISTD_H
  34. #include <unistd.h>
  35. #endif
  36. #if defined(__IOS__)
  37. #elif defined(__MACOSX__)
  38. #include <crt_externs.h>
  39. #define environ (*_NSGetEnviron())
  40. #endif
  41. DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer)
  42. {
  43. char* cwd;
  44. size_t length;
  45. cwd = getcwd(NULL, 0);
  46. if (!cwd)
  47. return 0;
  48. length = strlen(cwd);
  49. if ((nBufferLength == 0) && (lpBuffer == NULL))
  50. {
  51. free(cwd);
  52. return (DWORD)length;
  53. }
  54. else
  55. {
  56. if (lpBuffer == NULL)
  57. {
  58. free(cwd);
  59. return 0;
  60. }
  61. if ((length + 1) > nBufferLength)
  62. {
  63. free(cwd);
  64. return (DWORD)(length + 1);
  65. }
  66. memcpy(lpBuffer, cwd, length + 1);
  67. free(cwd);
  68. return length;
  69. }
  70. return 0;
  71. }
  72. DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer)
  73. {
  74. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  75. return 0;
  76. }
  77. // implement it [3/18/2020 18:36 Gifur]
  78. BOOL SetCurrentDirectoryA(LPCSTR lpPathName)
  79. {
  80. if (chdir(lpPathName) == -1) {
  81. fprintf(stderr, "chdir failed: %s\n", strerror(errno));
  82. return FALSE;
  83. }
  84. return TRUE;
  85. }
  86. BOOL SetCurrentDirectoryW(LPCWSTR lpPathName)
  87. {
  88. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  89. return FALSE;
  90. }
  91. DWORD SearchPathA(LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength,
  92. LPSTR lpBuffer, LPSTR* lpFilePart)
  93. {
  94. return 0;
  95. }
  96. DWORD SearchPathW(LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength,
  97. LPWSTR lpBuffer, LPWSTR* lpFilePart)
  98. {
  99. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  100. return 0;
  101. }
  102. LPSTR GetCommandLineA(VOID)
  103. {
  104. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  105. return NULL;
  106. }
  107. LPWSTR GetCommandLineW(VOID)
  108. {
  109. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  110. return NULL;
  111. }
  112. BOOL NeedCurrentDirectoryForExePathA(LPCSTR ExeName)
  113. {
  114. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  115. return TRUE;
  116. }
  117. BOOL NeedCurrentDirectoryForExePathW(LPCWSTR ExeName)
  118. {
  119. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  120. return TRUE;
  121. }
  122. #endif
  123. #if !defined(_WIN32) || defined(_UWP)
  124. DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
  125. {
  126. #if !defined(_UWP)
  127. size_t length;
  128. char* env = NULL;
  129. env = getenv(lpName);
  130. if (!env)
  131. {
  132. SetLastError(ERROR_ENVVAR_NOT_FOUND);
  133. return 0;
  134. }
  135. length = strlen(env);
  136. if ((length + 1 > nSize) || (!lpBuffer))
  137. return length + 1;
  138. CopyMemory(lpBuffer, env, length);
  139. lpBuffer[length] = '\0';
  140. return length;
  141. #else
  142. SetLastError(ERROR_ENVVAR_NOT_FOUND);
  143. return 0;
  144. #endif
  145. }
  146. DWORD GetEnvironmentVariableW(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize)
  147. {
  148. SetLastError(ERROR_ENVVAR_NOT_FOUND);
  149. return 0;
  150. }
  151. BOOL SetEnvironmentVariableA(LPCSTR lpName, LPCSTR lpValue)
  152. {
  153. #if !defined(_UWP)
  154. if (!lpName)
  155. return FALSE;
  156. if (lpValue)
  157. {
  158. if (0 != setenv(lpName, lpValue, 1))
  159. return FALSE;
  160. }
  161. else
  162. {
  163. if (0 != unsetenv(lpName))
  164. return FALSE;
  165. }
  166. return TRUE;
  167. #else
  168. return FALSE;
  169. #endif
  170. }
  171. BOOL SetEnvironmentVariableW(LPCWSTR lpName, LPCWSTR lpValue)
  172. {
  173. return FALSE;
  174. }
  175. /**
  176. * GetEnvironmentStrings function:
  177. * http://msdn.microsoft.com/en-us/library/windows/desktop/ms683187/
  178. *
  179. * The GetEnvironmentStrings function returns a pointer to a block of memory
  180. * that contains the environment variables of the calling process (both the
  181. * system and the user environment variables). Each environment block contains
  182. * the environment variables in the following format:
  183. *
  184. * Var1=Value1\0
  185. * Var2=Value2\0
  186. * Var3=Value3\0
  187. * ...
  188. * VarN=ValueN\0\0
  189. */
  190. extern char** environ;
  191. LPCH GetEnvironmentStringsA(VOID)
  192. {
  193. #if !defined(_UWP)
  194. char* p;
  195. size_t offset;
  196. size_t length;
  197. char** envp;
  198. DWORD cchEnvironmentBlock;
  199. LPCH lpszEnvironmentBlock;
  200. offset = 0;
  201. envp = environ;
  202. cchEnvironmentBlock = 128;
  203. lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
  204. if (!lpszEnvironmentBlock)
  205. return NULL;
  206. while (*envp)
  207. {
  208. length = strlen(*envp);
  209. while ((offset + length + 8) > cchEnvironmentBlock)
  210. {
  211. DWORD new_size;
  212. LPCH new_blk;
  213. new_size = cchEnvironmentBlock * 2;
  214. new_blk = (LPCH)realloc(lpszEnvironmentBlock, new_size * sizeof(CHAR));
  215. if (!new_blk)
  216. {
  217. free(lpszEnvironmentBlock);
  218. return NULL;
  219. }
  220. lpszEnvironmentBlock = new_blk;
  221. cchEnvironmentBlock = new_size;
  222. }
  223. p = &(lpszEnvironmentBlock[offset]);
  224. CopyMemory(p, *envp, length * sizeof(CHAR));
  225. p[length] = '\0';
  226. offset += (length + 1);
  227. envp++;
  228. }
  229. lpszEnvironmentBlock[offset] = '\0';
  230. return lpszEnvironmentBlock;
  231. #else
  232. return NULL;
  233. #endif
  234. }
  235. LPWCH GetEnvironmentStringsW(VOID)
  236. {
  237. return NULL;
  238. }
  239. BOOL SetEnvironmentStringsA(LPCH NewEnvironment)
  240. {
  241. return TRUE;
  242. }
  243. BOOL SetEnvironmentStringsW(LPWCH NewEnvironment)
  244. {
  245. return TRUE;
  246. }
  247. DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize)
  248. {
  249. return 0;
  250. }
  251. DWORD ExpandEnvironmentStringsW(LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize)
  252. {
  253. return 0;
  254. }
  255. BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock)
  256. {
  257. free(lpszEnvironmentBlock);
  258. return TRUE;
  259. }
  260. BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock)
  261. {
  262. return TRUE;
  263. }
  264. #endif
  265. LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
  266. {
  267. const char* cp;
  268. char* p;
  269. size_t offset;
  270. size_t length;
  271. const char* envp;
  272. DWORD cchEnvironmentBlock;
  273. LPCH lpszEnvironmentBlock;
  274. const char** mergeStrings;
  275. size_t mergeStringLength;
  276. size_t mergeArraySize = 128;
  277. size_t run;
  278. size_t mergeLength;
  279. size_t foundMerge;
  280. char* foundEquals;
  281. mergeStrings = (LPCSTR*)calloc(mergeArraySize, sizeof(char*));
  282. if (!mergeStrings)
  283. return NULL;
  284. mergeStringLength = 0;
  285. cp = merge;
  286. while (*cp && *(cp + 1))
  287. {
  288. length = strlen(cp);
  289. if (mergeStringLength == mergeArraySize)
  290. {
  291. const char** new_str;
  292. mergeArraySize += 128;
  293. new_str = (const char**)realloc((void*)mergeStrings, mergeArraySize * sizeof(char*));
  294. if (!new_str)
  295. {
  296. free((void*)mergeStrings);
  297. return NULL;
  298. }
  299. mergeStrings = new_str;
  300. }
  301. mergeStrings[mergeStringLength] = cp;
  302. cp += length + 1;
  303. mergeStringLength++;
  304. }
  305. offset = 0;
  306. cchEnvironmentBlock = 128;
  307. lpszEnvironmentBlock = (LPCH)calloc(cchEnvironmentBlock, sizeof(CHAR));
  308. if (!lpszEnvironmentBlock)
  309. {
  310. free((void*)mergeStrings);
  311. return NULL;
  312. }
  313. envp = original;
  314. while ((original != NULL) && (*envp && *(envp + 1)))
  315. {
  316. size_t old_offset = offset;
  317. length = strlen(envp);
  318. while ((offset + length + 8) > cchEnvironmentBlock)
  319. {
  320. LPCH tmp;
  321. cchEnvironmentBlock *= 2;
  322. tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
  323. if (!tmp)
  324. {
  325. free((void*)lpszEnvironmentBlock);
  326. free((void*)mergeStrings);
  327. return NULL;
  328. }
  329. lpszEnvironmentBlock = tmp;
  330. }
  331. p = &(lpszEnvironmentBlock[offset]);
  332. // check if this value is in the mergeStrings
  333. foundMerge = 0;
  334. for (run = 0; run < mergeStringLength; run++)
  335. {
  336. if (!mergeStrings[run])
  337. continue;
  338. mergeLength = strlen(mergeStrings[run]);
  339. foundEquals = strstr(mergeStrings[run], "=");
  340. if (!foundEquals)
  341. continue;
  342. if (strncmp(envp, mergeStrings[run], foundEquals - mergeStrings[run] + 1) == 0)
  343. {
  344. // found variable in merge list ... use this ....
  345. if (*(foundEquals + 1) == '\0')
  346. {
  347. // check if the argument is set ... if not remove variable ...
  348. foundMerge = 1;
  349. }
  350. else
  351. {
  352. while ((offset + mergeLength + 8) > cchEnvironmentBlock)
  353. {
  354. LPCH tmp;
  355. cchEnvironmentBlock *= 2;
  356. tmp =
  357. (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
  358. if (!tmp)
  359. {
  360. free((void*)lpszEnvironmentBlock);
  361. free((void*)mergeStrings);
  362. return NULL;
  363. }
  364. lpszEnvironmentBlock = tmp;
  365. p = &(lpszEnvironmentBlock[old_offset]);
  366. }
  367. foundMerge = 1;
  368. CopyMemory(p, mergeStrings[run], mergeLength);
  369. mergeStrings[run] = NULL;
  370. p[mergeLength] = '\0';
  371. offset += (mergeLength + 1);
  372. }
  373. }
  374. }
  375. if (foundMerge == 0)
  376. {
  377. CopyMemory(p, envp, length * sizeof(CHAR));
  378. p[length] = '\0';
  379. offset += (length + 1);
  380. }
  381. envp += (length + 1);
  382. }
  383. // now merge the not already merged env
  384. for (run = 0; run < mergeStringLength; run++)
  385. {
  386. if (!mergeStrings[run])
  387. continue;
  388. mergeLength = strlen(mergeStrings[run]);
  389. while ((offset + mergeLength + 8) > cchEnvironmentBlock)
  390. {
  391. LPCH tmp;
  392. cchEnvironmentBlock *= 2;
  393. tmp = (LPCH)realloc(lpszEnvironmentBlock, cchEnvironmentBlock * sizeof(CHAR));
  394. if (!tmp)
  395. {
  396. free((void*)lpszEnvironmentBlock);
  397. free((void*)mergeStrings);
  398. return NULL;
  399. }
  400. lpszEnvironmentBlock = tmp;
  401. }
  402. p = &(lpszEnvironmentBlock[offset]);
  403. CopyMemory(p, mergeStrings[run], mergeLength);
  404. mergeStrings[run] = NULL;
  405. p[mergeLength] = '\0';
  406. offset += (mergeLength + 1);
  407. }
  408. lpszEnvironmentBlock[offset] = '\0';
  409. free((void*)mergeStrings);
  410. return lpszEnvironmentBlock;
  411. }
  412. DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
  413. {
  414. size_t vLength = 0;
  415. char* env = NULL;
  416. char* foundEquals;
  417. const char* penvb = envBlock;
  418. size_t nLength, fLength, lpNameLength;
  419. if (!lpName || NULL == envBlock)
  420. return 0;
  421. lpNameLength = strlen(lpName);
  422. if (lpNameLength < 1)
  423. return 0;
  424. while (*penvb && *(penvb + 1))
  425. {
  426. fLength = strlen(penvb);
  427. foundEquals = strstr(penvb, "=");
  428. if (!foundEquals)
  429. {
  430. /* if no = sign is found the envBlock is broken */
  431. return 0;
  432. }
  433. nLength = (foundEquals - penvb);
  434. if (nLength != lpNameLength)
  435. {
  436. penvb += (fLength + 1);
  437. continue;
  438. }
  439. if (strncmp(penvb, lpName, nLength) == 0)
  440. {
  441. env = foundEquals + 1;
  442. break;
  443. }
  444. penvb += (fLength + 1);
  445. }
  446. if (!env)
  447. return 0;
  448. vLength = strlen(env);
  449. if ((vLength + 1 > nSize) || (!lpBuffer))
  450. return vLength + 1;
  451. CopyMemory(lpBuffer, env, vLength + 1);
  452. return vLength;
  453. }
  454. BOOL SetEnvironmentVariableEBA(LPSTR* envBlock, LPCSTR lpName, LPCSTR lpValue)
  455. {
  456. int length;
  457. char* envstr;
  458. char* newEB;
  459. if (!lpName)
  460. return FALSE;
  461. if (lpValue)
  462. {
  463. length = (int)(strlen(lpName) + strlen(lpValue) + 2); /* +2 because of = and \0 */
  464. envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
  465. if (!envstr)
  466. return FALSE;
  467. sprintf_s(envstr, length, "%s=%s", lpName, lpValue);
  468. }
  469. else
  470. {
  471. length = (int)strlen(lpName) + 2; /* +2 because of = and \0 */
  472. envstr = (char*)malloc(length + 1); /* +1 because of closing \0 */
  473. if (!envstr)
  474. return FALSE;
  475. sprintf_s(envstr, length, "%s=", lpName);
  476. }
  477. envstr[length] = '\0';
  478. newEB = MergeEnvironmentStrings((LPCSTR)*envBlock, envstr);
  479. free(envstr);
  480. free(*envBlock);
  481. *envBlock = newEB;
  482. return TRUE;
  483. }
  484. char** EnvironmentBlockToEnvpA(LPCH lpszEnvironmentBlock)
  485. {
  486. char* p;
  487. SSIZE_T index;
  488. size_t count;
  489. size_t length;
  490. char** envp = NULL;
  491. count = 0;
  492. if (!lpszEnvironmentBlock)
  493. return NULL;
  494. p = (char*)lpszEnvironmentBlock;
  495. while (p[0] && p[1])
  496. {
  497. length = strlen(p);
  498. p += (length + 1);
  499. count++;
  500. }
  501. index = 0;
  502. p = (char*)lpszEnvironmentBlock;
  503. envp = (char**)calloc(count + 1, sizeof(char*));
  504. if (!envp)
  505. return NULL;
  506. envp[count] = NULL;
  507. while (p[0] && p[1])
  508. {
  509. length = strlen(p);
  510. envp[index] = _strdup(p);
  511. if (!envp[index])
  512. {
  513. for (index -= 1; index >= 0; --index)
  514. {
  515. free(envp[index]);
  516. }
  517. free(envp);
  518. return NULL;
  519. }
  520. p += (length + 1);
  521. index++;
  522. }
  523. return envp;
  524. }