env.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. env.c
  5. Abstract:
  6. This module implements environment support for user mode programs.
  7. Author:
  8. Evan Green 7-Mar-2013
  9. Environment:
  10. User Mode
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "osbasep.h"
  16. //
  17. // ---------------------------------------------------------------- Definitions
  18. //
  19. #define ENVIRONMENT_ALLOCATION_TAG 0x21766E45
  20. //
  21. // ------------------------------------------------------ Data Type Definitions
  22. //
  23. //
  24. // ----------------------------------------------- Internal Function Prototypes
  25. //
  26. //
  27. // -------------------------------------------------------------------- Globals
  28. //
  29. //
  30. // Store a pointer to the environment.
  31. //
  32. PPROCESS_ENVIRONMENT OsEnvironment = NULL;
  33. //
  34. // ------------------------------------------------------------------ Functions
  35. //
  36. OS_API
  37. PPROCESS_ENVIRONMENT
  38. OsCreateEnvironment (
  39. PSTR ImagePath,
  40. ULONG ImagePathLength,
  41. PSTR *ArgumentValues,
  42. ULONG ArgumentValuesTotalLength,
  43. ULONG ArgumentCount,
  44. PSTR *EnvironmentValues,
  45. ULONG EnvironmentValuesTotalLength,
  46. ULONG EnvironmentCount
  47. )
  48. /*++
  49. Routine Description:
  50. This routine creates an environment that can be passed to the kernel for
  51. execution of an image. This routine will use the heap.
  52. Arguments:
  53. ImagePath - Supplies a pointer to the name of the image that will be
  54. executed.
  55. ImagePathLength - Supplies the length of the image path buffer in bytes,
  56. including the null terminator.
  57. ArgumentValues - Supplies an array of pointers to arguments to pass to the
  58. image.
  59. ArgumentValuesTotalLength - Supplies the total length of all arguments, in
  60. bytes, including their null terminators.
  61. ArgumentCount - Supplies the number of arguments in the argument values
  62. array.
  63. EnvironmentValues - Supplies an array of pointers to environment variables
  64. to set in the new environment. Environment variables take the form
  65. "name=value".
  66. EnvironmentValuesTotalLength - Supplies the total length of all environment
  67. variables, in bytes, including their null terminators.
  68. EnvironmentCount - Supplies the number of environment variable strings
  69. present in the environment values array. This should not include any
  70. null terminating entry in the array.
  71. Return Value:
  72. Returns a pointer to a heap allocated environment, suitable for sending to
  73. the execute image system call.
  74. NULL on failure.
  75. --*/
  76. {
  77. ULONG AllocationSize;
  78. ULONG BufferSize;
  79. PSTR CurrentBuffer;
  80. ULONG ElementIndex;
  81. PPROCESS_ENVIRONMENT Environment;
  82. BOOL Result;
  83. ULONG StringSize;
  84. ULONG TerminatedEnvironmentCount;
  85. Result = FALSE;
  86. TerminatedEnvironmentCount = EnvironmentCount;
  87. if ((EnvironmentCount == 0) ||
  88. (EnvironmentValues[EnvironmentCount - 1] != NULL)) {
  89. TerminatedEnvironmentCount += 1;
  90. }
  91. //
  92. // Allocate the beast. There's a null pointer at the end of the list too
  93. // (hence the argument count plus one).
  94. //
  95. AllocationSize = sizeof(PROCESS_ENVIRONMENT) +
  96. ALIGN_RANGE_UP(ImagePathLength, sizeof(PVOID)) +
  97. ((ArgumentCount + 1) * sizeof(PSTR)) +
  98. ALIGN_RANGE_UP(ArgumentValuesTotalLength, sizeof(PVOID)) +
  99. (TerminatedEnvironmentCount * sizeof(PSTR)) +
  100. EnvironmentValuesTotalLength;
  101. Environment = OsHeapAllocate(AllocationSize, ENVIRONMENT_ALLOCATION_TAG);
  102. if (Environment == NULL) {
  103. return NULL;
  104. }
  105. RtlZeroMemory(Environment, sizeof(PROCESS_ENVIRONMENT));
  106. //
  107. // Copy the image path.
  108. //
  109. Environment->ImageName = (PSTR)(Environment + 1);
  110. RtlStringCopy(Environment->ImageName, ImagePath, ImagePathLength);
  111. Environment->ImageNameLength = ImagePathLength;
  112. //
  113. // Make room for the arguments and its buffer.
  114. //
  115. Environment->Arguments =
  116. (PSTR *)((PVOID)Environment->ImageName +
  117. ALIGN_RANGE_UP(ImagePathLength, sizeof(PVOID)));
  118. Environment->ArgumentCount = ArgumentCount;
  119. Environment->ArgumentsBuffer = (PVOID)Environment->Arguments +
  120. ((ArgumentCount + 1) * sizeof(PSTR));
  121. Environment->ArgumentsBufferLength = ArgumentValuesTotalLength;
  122. //
  123. // Make room for the environment and its buffer.
  124. //
  125. Environment->Environment =
  126. (PSTR *)(Environment->ArgumentsBuffer +
  127. ALIGN_RANGE_UP(ArgumentValuesTotalLength, sizeof(PVOID)));
  128. Environment->EnvironmentCount = EnvironmentCount;
  129. Environment->EnvironmentBuffer =
  130. (PVOID)Environment->Environment +
  131. (TerminatedEnvironmentCount * sizeof(PSTR));
  132. Environment->EnvironmentBufferLength = EnvironmentValuesTotalLength;
  133. //
  134. // Copy over each argument. The first is always the image name.
  135. //
  136. BufferSize = ArgumentValuesTotalLength;
  137. CurrentBuffer = Environment->ArgumentsBuffer;
  138. for (ElementIndex = 0; ElementIndex < ArgumentCount; ElementIndex += 1) {
  139. StringSize = RtlStringCopy(CurrentBuffer,
  140. ArgumentValues[ElementIndex],
  141. BufferSize);
  142. if (StringSize == 0) {
  143. goto CreateEnvironmentEnd;
  144. }
  145. Environment->Arguments[ElementIndex] = CurrentBuffer;
  146. CurrentBuffer += StringSize;
  147. BufferSize -= StringSize;
  148. }
  149. //
  150. // Copy over each environment variable.
  151. //
  152. BufferSize = EnvironmentValuesTotalLength;
  153. CurrentBuffer = Environment->EnvironmentBuffer;
  154. for (ElementIndex = 0; ElementIndex < EnvironmentCount; ElementIndex += 1) {
  155. //
  156. // Protect against a supplied environment that was null-terminated.
  157. //
  158. if ((ElementIndex == (EnvironmentCount - 1)) &&
  159. (EnvironmentValues[ElementIndex] == NULL)) {
  160. break;
  161. }
  162. StringSize = RtlStringCopy(CurrentBuffer,
  163. EnvironmentValues[ElementIndex],
  164. BufferSize);
  165. if (StringSize == 0) {
  166. goto CreateEnvironmentEnd;
  167. }
  168. Environment->Environment[ElementIndex] = CurrentBuffer;
  169. CurrentBuffer += StringSize;
  170. BufferSize -= StringSize;
  171. }
  172. //
  173. // NULL out the last one.
  174. //
  175. ASSERT(ElementIndex == TerminatedEnvironmentCount - 1);
  176. Environment->Environment[ElementIndex] = NULL;
  177. Result = TRUE;
  178. CreateEnvironmentEnd:
  179. if (Result == FALSE) {
  180. if (Environment != NULL) {
  181. OsHeapFree(Environment);
  182. Environment = NULL;
  183. }
  184. }
  185. return Environment;
  186. }
  187. OS_API
  188. VOID
  189. OsDestroyEnvironment (
  190. PPROCESS_ENVIRONMENT Environment
  191. )
  192. /*++
  193. Routine Description:
  194. This routine destroys an environment created with the create environment
  195. function.
  196. Arguments:
  197. Environment - Supplies a pointer to the environment to destroy.
  198. Return Value:
  199. None.
  200. --*/
  201. {
  202. OsHeapFree(Environment);
  203. return;
  204. }
  205. OS_API
  206. PPROCESS_ENVIRONMENT
  207. OsGetCurrentEnvironment (
  208. VOID
  209. )
  210. /*++
  211. Routine Description:
  212. This routine gets the environment for the current process.
  213. Arguments:
  214. None.
  215. Return Value:
  216. Returns a pointer to the current environment. This is shared memory, and
  217. should not be altered by the caller.
  218. --*/
  219. {
  220. return OsEnvironment;
  221. }
  222. //
  223. // --------------------------------------------------------- Internal Functions
  224. //