Source code of Windows XP (NT5)
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.

399 lines
14 KiB

  1. /***
  2. *ioinit.c - Initialization for lowio functions
  3. *
  4. * Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Contains initialization and termination routines for lowio.
  8. * Currently, this includes:
  9. * 1. Initial allocation of array(s) of ioinfo structs.
  10. * 2. Processing of inherited file info from parent process.
  11. * 3. Special case initialization of the first three ioinfo structs,
  12. * the ones that correspond to handles 0, 1 and 2.
  13. *
  14. *Revision History:
  15. * 02-14-92 GJF Module created.
  16. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  17. * 03-28-94 GJF Made definitions of:
  18. * _osfhnd[]
  19. * _osfile[]
  20. * _pipech[]
  21. * conditional on ndef DLL_FOR_WIN32S. Also replaced
  22. * MTHREAD with _MT.
  23. * 02-02-95 BWT Check cbReserved2 before copying inherited handles.
  24. * Current NT doesn't always set lpReserved2 to NULL.
  25. * 06-01-95 GJF Always mark handles 0 - 2 as open. Further, if an
  26. * underlying HANDLE-s is invalid or of unknown type,
  27. * mark the corresponding handle as a device (handles
  28. * 0 - 2 only).
  29. * 06-08-95 GJF Completely revised to use arrays of ioinfo structs.
  30. * 07-07-95 GJF Fixed the loop in _ioterm so it didn't iterate off
  31. * the end of the universe.
  32. * 07-11-95 GJF Use UNALIGNED int and long pointers to avoid choking
  33. * RISC platforms.
  34. * 07-28-95 GJF Added __badioinfo.
  35. * 04-12-96 SKS __badioinfo and __pioinfo must be exported for the
  36. * Old Iostreams DLLs (msvcirt.dll and msvcirtd.dll).
  37. * 05-16-96 GJF Don't call GetFileType for inherited pipe handles.
  38. * This avoids a major problem in NT - GetFileType will
  39. * 'hang' if there is a "blocking read" pending on the
  40. * pipe in the parent.
  41. * 07-08-96 GJF Deleted DLL_FOR_WIN32S. Also, detab-ed.
  42. * 07-09-96 GJF Replaced __pioinfo[i] == NULL; with __pioinfo[i] =
  43. * NULL in _ioterm().
  44. * 02-10-98 GJF Changes for Win64: use intptr_t for anything holding
  45. * HANDLE values.
  46. * 10-19-00 PML Force text mode in __badioinfo to avoid alignment
  47. * fault (vs7#176001).
  48. * 02-20-01 PML vs7#172586 Avoid _RT_LOCK by preallocating all locks
  49. * that will be required, and returning failure back on
  50. * inability to allocate a lock.
  51. * 03-27-01 PML Return -1 on fatal error instead of calling
  52. * _amsg_exit (vs7#231220)
  53. *
  54. *******************************************************************************/
  55. #include <cruntime.h>
  56. #include <windows.h>
  57. #include <internal.h>
  58. #include <malloc.h>
  59. #include <msdos.h>
  60. #include <rterr.h>
  61. #include <stddef.h>
  62. #include <stdlib.h>
  63. #include <dbgint.h>
  64. /*
  65. * Special static ioinfo structure. This is referred to only by the
  66. * _pioinfo_safe() macro, and its derivatives, in internal.h. These, in turn
  67. * are used in certain stdio-level functions to more gracefully handle a FILE
  68. * with -1 in the _file field.
  69. */
  70. _CRTIMP ioinfo __badioinfo = {
  71. (intptr_t)(-1), /* osfhnd */
  72. FTEXT, /* osfile */
  73. #ifdef _MT
  74. 10, /* pipech */
  75. 0 /* lockinitflag */
  76. #else
  77. 10
  78. #endif
  79. };
  80. /*
  81. * Number of ioinfo structs allocated at any given time. This number ranges
  82. * from a minimum of IOINFO_ARRAY_ELTS to a maximum of _NHANDLE_ (==
  83. * IOINFO_ARRAY_ELTS * IOINFO_ARRAYS) in steps of IOINFO_ARRAY_ELTS.
  84. */
  85. int _nhandle;
  86. /*
  87. * Array of pointers to arrays of ioinfo structs.
  88. */
  89. _CRTIMP ioinfo * __pioinfo[IOINFO_ARRAYS];
  90. /*
  91. * macro used to map 0, 1 and 2 to right value for call to GetStdHandle
  92. */
  93. #define stdhndl(fh) ( (fh == 0) ? STD_INPUT_HANDLE : ((fh == 1) ? \
  94. STD_OUTPUT_HANDLE : STD_ERROR_HANDLE) )
  95. /***
  96. *_ioinit() -
  97. *
  98. *Purpose:
  99. * Allocates and initializes initial array(s) of ioinfo structs. Then,
  100. * obtains and processes information on inherited file handles from the
  101. * parent process (e.g., cmd.exe).
  102. *
  103. * Obtains the StartupInfo structure from the OS. The inherited file
  104. * handle information is pointed to by the lpReserved2 field. The format
  105. * of the information is as follows:
  106. *
  107. * bytes 0 thru 3 - integer value, say N, which is the
  108. * number of handles information is passed
  109. * about
  110. *
  111. * bytes 4 thru N+3 - the N values for osfile
  112. *
  113. * bytes N+4 thru 5*N+3 - N double-words, the N OS HANDLE values
  114. * being passed
  115. *
  116. * Next, osfhnd and osfile for the first three ioinfo structs,
  117. * corrsponding to handles 0, 1 and 2, are initialized as follows:
  118. *
  119. * If the value in osfhnd is INVALID_HANDLE_VALUE, then try to
  120. * obtain a HANDLE by calling GetStdHandle, and call GetFileType to
  121. * help set osfile. Otherwise, assume _osfhndl and _osfile are
  122. * valid, but force it to text mode (standard input/output/error
  123. * are to always start out in text mode).
  124. *
  125. * Notes:
  126. * 1. In general, not all of the passed info from the parent process
  127. * will describe open handles! If, for example, only C handle 1
  128. * (STDOUT) and C handle 6 are open in the parent, info for C
  129. * handles 0 thru 6 is passed to the the child.
  130. *
  131. * 2. Care is taken not to 'overflow' the arrays of ioinfo structs.
  132. *
  133. * 3. See exec\dospawn.c for the encoding of the file handle info
  134. * to be passed to a child process.
  135. *
  136. *Entry:
  137. * No parameters: reads the STARTUPINFO structure.
  138. *
  139. *Exit:
  140. * 0 on success, -1 if error encountered
  141. *
  142. *Exceptions:
  143. *
  144. *******************************************************************************/
  145. int __cdecl _ioinit (
  146. void
  147. )
  148. {
  149. STARTUPINFO StartupInfo;
  150. int cfi_len;
  151. int fh;
  152. int i;
  153. ioinfo *pio;
  154. char *posfile;
  155. UNALIGNED intptr_t *posfhnd;
  156. intptr_t stdfh;
  157. DWORD htype;
  158. /*
  159. * Allocate and initialize the first array of ioinfo structs. This
  160. * array is pointed to by __pioinfo[0]
  161. */
  162. if ( (pio = _malloc_crt( IOINFO_ARRAY_ELTS * sizeof(ioinfo) ))
  163. == NULL )
  164. {
  165. return -1;
  166. }
  167. __pioinfo[0] = pio;
  168. _nhandle = IOINFO_ARRAY_ELTS;
  169. for ( ; pio < __pioinfo[0] + IOINFO_ARRAY_ELTS ; pio++ ) {
  170. pio->osfile = 0;
  171. pio->osfhnd = (intptr_t)INVALID_HANDLE_VALUE;
  172. pio->pipech = 10; /* linefeed/newline char */
  173. #ifdef _MT
  174. pio->lockinitflag = 0; /* uninitialized lock */
  175. #endif
  176. }
  177. /*
  178. * Process inherited file handle information, if any
  179. */
  180. GetStartupInfo( &StartupInfo );
  181. if ( (StartupInfo.cbReserved2 != 0) &&
  182. (StartupInfo.lpReserved2 != NULL) )
  183. {
  184. /*
  185. * Get the number of handles inherited.
  186. */
  187. cfi_len = *(UNALIGNED int *)(StartupInfo.lpReserved2);
  188. /*
  189. * Set pointers to the start of the passed file info and OS
  190. * HANDLE values.
  191. */
  192. posfile = (char *)(StartupInfo.lpReserved2) + sizeof( int );
  193. posfhnd = (UNALIGNED intptr_t *)(posfile + cfi_len);
  194. /*
  195. * Ensure cfi_len does not exceed the number of supported
  196. * handles!
  197. */
  198. cfi_len = __min( cfi_len, _NHANDLE_ );
  199. /*
  200. * Allocate sufficient arrays of ioinfo structs to hold inherited
  201. * file information.
  202. */
  203. for ( i = 1 ; _nhandle < cfi_len ; i++ ) {
  204. /*
  205. * Allocate another array of ioinfo structs
  206. */
  207. if ( (pio = _malloc_crt( IOINFO_ARRAY_ELTS * sizeof(ioinfo) ))
  208. == NULL )
  209. {
  210. /*
  211. * No room for another array of ioinfo structs, reduce
  212. * the number of inherited handles we process.
  213. */
  214. cfi_len = _nhandle;
  215. break;
  216. }
  217. /*
  218. * Update __pioinfo[] and _nhandle
  219. */
  220. __pioinfo[i] = pio;
  221. _nhandle += IOINFO_ARRAY_ELTS;
  222. for ( ; pio < __pioinfo[i] + IOINFO_ARRAY_ELTS ; pio++ ) {
  223. pio->osfile = 0;
  224. pio->osfhnd = (intptr_t)INVALID_HANDLE_VALUE;
  225. pio->pipech = 10;
  226. #ifdef _MT
  227. pio->lockinitflag = 0;
  228. #endif
  229. }
  230. }
  231. /*
  232. * Validate and copy the passed file information
  233. */
  234. for ( fh = 0 ; fh < cfi_len ; fh++, posfile++, posfhnd++ ) {
  235. /*
  236. * Copy the passed file info iff it appears to describe
  237. * an open, valid file or device.
  238. *
  239. * Note that GetFileType cannot be called for pipe handles
  240. * since it may 'hang' if there is blocked read pending on
  241. * the pipe in the parent.
  242. */
  243. if ( (*posfhnd != (intptr_t)INVALID_HANDLE_VALUE) &&
  244. (*posfile & FOPEN) &&
  245. ((*posfile & FPIPE) ||
  246. (GetFileType( (HANDLE)*posfhnd ) != FILE_TYPE_UNKNOWN)) )
  247. {
  248. pio = _pioinfo( fh );
  249. pio->osfhnd = *posfhnd;
  250. pio->osfile = *posfile;
  251. #ifdef _MT
  252. /* Allocate the lock for this handle. */
  253. if ( !__crtInitCritSecAndSpinCount( &pio->lock,
  254. _CRT_SPINCOUNT ))
  255. return -1;
  256. pio->lockinitflag++;
  257. #endif
  258. }
  259. }
  260. }
  261. /*
  262. * If valid HANDLE-s for standard input, output and error were not
  263. * inherited, try to obtain them directly from the OS. Also, set the
  264. * appropriate bits in the osfile fields.
  265. */
  266. for ( fh = 0 ; fh < 3 ; fh++ ) {
  267. pio = __pioinfo[0] + fh;
  268. if ( pio->osfhnd == (intptr_t)INVALID_HANDLE_VALUE ) {
  269. /*
  270. * mark the handle as open in text mode.
  271. */
  272. pio->osfile = (char)(FOPEN | FTEXT);
  273. if ( ((stdfh = (intptr_t)GetStdHandle( stdhndl(fh) ))
  274. != (intptr_t)INVALID_HANDLE_VALUE) && ((htype =
  275. GetFileType( (HANDLE)stdfh )) != FILE_TYPE_UNKNOWN) )
  276. {
  277. /*
  278. * obtained a valid HANDLE from GetStdHandle
  279. */
  280. pio->osfhnd = stdfh;
  281. /*
  282. * finish setting osfile: determine if it is a character
  283. * device or pipe.
  284. */
  285. if ( (htype & 0xFF) == FILE_TYPE_CHAR )
  286. pio->osfile |= FDEV;
  287. else if ( (htype & 0xFF) == FILE_TYPE_PIPE )
  288. pio->osfile |= FPIPE;
  289. #ifdef _MT
  290. /* Allocate the lock for this handle. */
  291. if ( !__crtInitCritSecAndSpinCount( &pio->lock,
  292. _CRT_SPINCOUNT ))
  293. return -1;
  294. pio->lockinitflag++;
  295. #endif
  296. }
  297. else {
  298. /*
  299. * if there is no valid HANDLE, treat the CRT handle as
  300. * being open in text mode on a device (with
  301. * INVALID_HANDLE_VALUE underlying it).
  302. */
  303. pio->osfile |= FDEV;
  304. }
  305. }
  306. else {
  307. /*
  308. * handle was passed to us by parent process. make
  309. * sure it is text mode.
  310. */
  311. pio->osfile |= FTEXT;
  312. }
  313. }
  314. /*
  315. * Set the number of supported HANDLE-s to _nhandle
  316. */
  317. (void)SetHandleCount( (unsigned)_nhandle );
  318. return 0;
  319. }
  320. /***
  321. *_ioterm() -
  322. *
  323. *Purpose:
  324. * Free the memory holding the ioinfo arrays.
  325. *
  326. * In the multi-thread case, first walk each array of ioinfo structs and
  327. * delete any all initialized critical sections (locks).
  328. *
  329. *Entry:
  330. * No parameters.
  331. *
  332. *Exit:
  333. * No return value.
  334. *
  335. *Exceptions:
  336. *
  337. *******************************************************************************/
  338. void __cdecl _ioterm (
  339. void
  340. )
  341. {
  342. int i;
  343. #ifdef _MT
  344. ioinfo *pio;
  345. #endif
  346. for ( i = 0 ; i < IOINFO_ARRAYS ; i++ ) {
  347. if ( __pioinfo[i] != NULL ) {
  348. #ifdef _MT
  349. /*
  350. * Delete any initialized critical sections.
  351. */
  352. for ( pio = __pioinfo[i] ;
  353. pio < __pioinfo[i] + IOINFO_ARRAY_ELTS ;
  354. pio++ )
  355. {
  356. if ( pio->lockinitflag )
  357. DeleteCriticalSection( &(pio->lock) );
  358. }
  359. #endif
  360. /*
  361. * Free the memory which held the ioinfo array.
  362. */
  363. _free_crt( __pioinfo[i] );
  364. __pioinfo[i] = NULL;
  365. }
  366. }
  367. }