Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
12 KiB

  1. /***
  2. *cenvarg.c - set up environment, command line blocks
  3. *
  4. * Copyright (c) 1986-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _cenvarg() - setup environment/command line blocks
  8. *
  9. *Revision History:
  10. * 05-20-86 SKS Module created
  11. * 10-03-86 SKS Wasn't clearing final null byte in environment block
  12. * 10-13-86 SKS Check for environment segment > 32 KB (esp. > 64 KB)
  13. * 10-23-86 SKS New format for C_FILE_INFO for Prot-Mode execution
  14. * 12-17-86 SKS Support for new command line format
  15. * 01-21-87 BCM Removed DCR475 switch, new command line format official
  16. * 07-07-87 JCR Corrected bug in ENV_MAX check
  17. * 05-24-88 SJM Removed support for ;C_FILE_INFO for Real-Mode execution
  18. * 06-01-88 SJM Added support for .cmd files via comname/cmdname
  19. * 12-27-88 JCR Added support for _fileinfo option
  20. * 03-08-90 GJF Made calling type _CALLTYPE1, added #include
  21. * <cruntime.h>, removed #include <register.h> and fixed
  22. * the copyright. Also, cleaned up the formatting a bit.
  23. * 04-02-90 GJF Added const to arg types.
  24. * 08-10-90 SBM Compiles cleanly with -W3
  25. * 09-27-90 GJF New-style function declarator.
  26. * 12-06-90 GJF Added Win32 support. That is, support for encoding
  27. * _osfinfo[] data into _C_FILE_INFO environment variable.
  28. * 01-18-91 GJF ANSI naming.
  29. * 02-05-91 SRW Removed usage of _C_FILE_INFO to pass binary data
  30. * to child process. [_WIN32_]
  31. * 05-07-92 SKS Remove code which stripped the extension from a batch
  32. * file while building arguments to CMD.EXE. This was
  33. * done long ago (1988) for DOS 3.X, I think.
  34. * 10-24-92 SKS Remove special code for batch files - not needed on NT
  35. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  36. * 07-15-93 SRW Added _capture_argv function
  37. * 08-31-93 GJF Merged NT SDK and Cuda version. Also cleaned up the
  38. * formating and removed (obsolete) Cruiser support.
  39. * 12-07-93 CFW Wide char enable.
  40. * 12-08-94 CFW Get wide environment if needed.
  41. * 01-10-95 CFW Debug CRT allocs.
  42. * 03-13-96 JWM Get all environments as needed; free buffers on exit.
  43. * 08-15-96 JWM Remove all 32K limitations on spawned processes.
  44. * 12-15-98 GJF Changes for 64-bit size_t.
  45. *
  46. *******************************************************************************/
  47. #include <cruntime.h>
  48. #include <stdio.h>
  49. #include <errno.h>
  50. #include <msdos.h>
  51. #include <stdlib.h>
  52. #include <stdarg.h>
  53. #include <internal.h>
  54. #include <string.h>
  55. #include <awint.h>
  56. #include <tchar.h>
  57. #include <dbgint.h>
  58. #define ENV_MAX 32767
  59. /* local tchar */
  60. #ifdef WPRFLAG
  61. #define _tenvptr _wenvptr
  62. #else
  63. #define _tenvptr _aenvptr
  64. #endif
  65. /***
  66. *int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ
  67. *
  68. *Purpose:
  69. * Set up the block forms of the environment and the command line.
  70. * If "envp" is null, "_environ" is used instead.
  71. * File handle info is passed in the environment if _fileinfo is !0.
  72. *
  73. *Entry:
  74. * _TSCHAR **argv - argument vector
  75. * _TSCHAR **envp - environment vector
  76. * _TSCHAR **argblk - pointer to pointer set to malloc'ed space for args
  77. * _TSCHAR **envblk - pointer to pointer set to malloc'ed space for env
  78. * _TSCHAR *name - name of program being invoked
  79. *
  80. *Exit:
  81. * returns 0 if ok, -1 if fails
  82. * stores through argblk and envblk
  83. * (calls malloc)
  84. *
  85. *Exceptions:
  86. *
  87. *******************************************************************************/
  88. #ifdef WPRFLAG
  89. int __cdecl _wcenvarg (
  90. #else
  91. int __cdecl _cenvarg (
  92. #endif
  93. const _TSCHAR * const *argv,
  94. const _TSCHAR * const *envp,
  95. _TSCHAR **argblk,
  96. _TSCHAR **envblk,
  97. const _TSCHAR *name
  98. )
  99. {
  100. REG1 const _TSCHAR * const *vp;
  101. REG2 unsigned tmp;
  102. REG3 _TSCHAR *cptr;
  103. unsigned arg_len;
  104. int cfi_len; /* counts the number of file handles in CFI */
  105. /*
  106. * Null environment pointer "envp" means use global variable,
  107. * "_environ"
  108. */
  109. int cwd_start;
  110. int cwd_end; /* length of "cwd" strings in environment */
  111. /*
  112. * Allocate space for command line string
  113. * tmp counts the number of bytes in the command line string
  114. * including spaces between arguments
  115. * An empty string is special -- 2 bytes
  116. */
  117. for (vp = argv, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;
  118. arg_len = tmp;
  119. /*
  120. * Allocate space for the command line plus 2 null bytes
  121. */
  122. if ( (*argblk = _malloc_crt(tmp * sizeof(_TSCHAR))) == NULL)
  123. {
  124. *envblk = NULL;
  125. errno = ENOMEM;
  126. _doserrno = E_nomem;
  127. return(-1);
  128. }
  129. /*
  130. * Allocate space for environment strings
  131. * tmp counts the number of bytes in the environment strings
  132. * including nulls between strings
  133. * Also add "_C_FILE_INFO=" string
  134. */
  135. if (envp)
  136. for (vp = envp, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;
  137. /*
  138. * The _osfile and _osfhnd arrays are passed as binary data in
  139. * dospawn.c
  140. */
  141. cfi_len = 0; /* no _C_FILE_INFO */
  142. if (!envp)
  143. *envblk = NULL;
  144. else {
  145. /*
  146. * Now that we've decided to pass our own environment block,
  147. * compute the size of the "current directory" strings to
  148. * propagate to the new environment.
  149. */
  150. #ifdef WPRFLAG
  151. /*
  152. * Make sure wide environment exists.
  153. */
  154. if (!_wenvptr)
  155. {
  156. if ((_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW()) == NULL)
  157. return -1;
  158. }
  159. #else
  160. if (!_aenvptr)
  161. {
  162. if ((_aenvptr = (char *)__crtGetEnvironmentStringsA()) == NULL)
  163. return -1;
  164. }
  165. #endif
  166. /*
  167. * search for the first one
  168. */
  169. for (cwd_start = 0;
  170. _tenvptr[cwd_start] != _T('\0') &&
  171. _tenvptr[cwd_start] != _T('=');
  172. cwd_start += (int)_tcslen(&_tenvptr[cwd_start]) + 1)
  173. {
  174. }
  175. /* find the total size of all contiguous ones */
  176. cwd_end = cwd_start;
  177. while (_tenvptr[cwd_end+0] == _T('=') &&
  178. _tenvptr[cwd_end+1] != _T('\0') &&
  179. _tenvptr[cwd_end+2] == _T(':') &&
  180. _tenvptr[cwd_end+3] == _T('='))
  181. {
  182. cwd_end += 4 + (int)_tcslen(&_tenvptr[cwd_end+4]) + 1;
  183. }
  184. tmp += cwd_end - cwd_start;
  185. /*
  186. * Allocate space for the environment strings plus extra null byte
  187. */
  188. if( !(*envblk = _malloc_crt(tmp * sizeof(_TSCHAR))) )
  189. {
  190. _free_crt(*argblk);
  191. *argblk = NULL;
  192. errno = ENOMEM;
  193. _doserrno = E_nomem;
  194. return(-1);
  195. }
  196. }
  197. /*
  198. * Build the command line by concatenating the argument strings
  199. * with spaces between, and two null bytes at the end.
  200. * NOTE: The argv[0] argument is followed by a null.
  201. */
  202. cptr = *argblk;
  203. vp = argv;
  204. if (!*vp) /* Empty argument list ? */
  205. ++cptr; /* just two null bytes */
  206. else { /* argv[0] must be followed by a null */
  207. _tcscpy(cptr, *vp);
  208. cptr += (int)_tcslen(*vp++) + 1;
  209. }
  210. while( *vp ) {
  211. _tcscpy(cptr, *vp);
  212. cptr += (int)_tcslen(*vp++);
  213. *cptr++ = ' ';
  214. }
  215. *cptr = cptr[ -1 ] = _T('\0'); /* remove extra blank, add double null */
  216. /*
  217. * Build the environment block by concatenating the environment
  218. * strings with nulls between and two null bytes at the end
  219. */
  220. cptr = *envblk;
  221. if (envp != NULL) {
  222. /*
  223. * Copy the "cwd" strings to the new environment.
  224. */
  225. memcpy(cptr, &_tenvptr[cwd_start], (cwd_end - cwd_start) * sizeof(_TSCHAR));
  226. cptr += cwd_end - cwd_start;
  227. /*
  228. * Copy the environment strings from "envp".
  229. */
  230. vp = envp;
  231. while( *vp ) {
  232. _tcscpy(cptr, *vp);
  233. cptr += 1 + (int)_tcslen(*vp++);
  234. }
  235. }
  236. if (cptr != NULL) {
  237. if (cptr == *envblk) {
  238. /*
  239. * Empty environment block ... this requires two
  240. * nulls.
  241. */
  242. *cptr++ = _T('\0');
  243. }
  244. /*
  245. * Extra null terminates the segment
  246. */
  247. *cptr = _T('\0');
  248. }
  249. #ifdef WPRFLAG
  250. _free_crt(_wenvptr);
  251. _wenvptr = NULL;
  252. #else
  253. _free_crt(_aenvptr);
  254. _aenvptr = NULL;
  255. #endif
  256. return(0);
  257. }
  258. #ifndef _M_IX86
  259. /***
  260. *int _capture_argv(arglist, static_argv, max_static_entries) - set up argv array
  261. * for exec?? functions
  262. *
  263. *Purpose:
  264. * Set up the argv array for the exec?? functions by captures the
  265. * arguments from the passed va_list into the static_argv array. If the
  266. * size of the static_argv array as specified by the max_static_entries
  267. * parameter is not large enough, then allocates a dynamic array to hold
  268. * the arguments. Return the address of the final argv array. If NULL
  269. * then not enough memory to hold argument array. If different from
  270. * static_argv parameter then call must free the return argv array when
  271. * done with it.
  272. *
  273. * The scan of the arglist is terminated when a NULL argument is
  274. * reached. The terminating NULL parameter is stored in the resulting
  275. * argv array.
  276. *
  277. *Entry:
  278. * va_list *arglist - pointer to variable length argument list.
  279. * _TSCHAR *firstarg - first argument to store in array
  280. * _TSCHAR **static_argv - pointer to static argv to use.
  281. * size_t max_static_entries - maximum number of entries that can be
  282. * placed in static_argv array.
  283. *
  284. *Exit:
  285. * returns NULL if no memory.
  286. * Otherwise returns pointer to argv array.
  287. * (sometimes calls malloc)
  288. *
  289. *Exceptions:
  290. *
  291. *******************************************************************************/
  292. #ifdef WPRFLAG
  293. _TSCHAR ** __cdecl _wcapture_argv(
  294. #else
  295. _TSCHAR ** __cdecl _capture_argv(
  296. #endif
  297. va_list *arglist,
  298. const _TSCHAR *firstarg,
  299. _TSCHAR **static_argv,
  300. size_t max_static_entries
  301. )
  302. {
  303. _TSCHAR ** argv;
  304. _TSCHAR * nextarg;
  305. size_t i;
  306. size_t max_entries;
  307. nextarg = (_TSCHAR *)firstarg;
  308. argv = static_argv;
  309. max_entries = max_static_entries;
  310. i = 0;
  311. for (;;) {
  312. if (i >= max_entries) {
  313. if (argv == static_argv)
  314. argv = _malloc_crt((max_entries * 2) * sizeof(_TSCHAR *));
  315. else
  316. argv = _realloc_crt(argv, (max_entries * 2) * sizeof(_TSCHAR *));
  317. if (argv == NULL) break;
  318. max_entries += max_entries;
  319. }
  320. argv[ i++ ] = nextarg;
  321. if (nextarg == NULL) break;
  322. nextarg = va_arg(*arglist, _TSCHAR *);
  323. }
  324. return argv;
  325. }
  326. #endif /* _M_IX86 */