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.

411 lines
12 KiB

  1. /***
  2. *_file.c - Definition of _iob[], initializer and terminator.
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines _iob[], the array of stdio control structures, the initializer
  8. * and terminator routines, and the multithread locking for stdio.
  9. *
  10. *Revision History:
  11. * 04-18-84 RN initial version
  12. * ??-??-?? TC added field _bifsiz to iob2 to allow variable
  13. * length buffers
  14. * 10-02-86 SKS _NFILE_ is now different for real-mode and prot-mode
  15. * _NFILE_ must be defined by compiler -D directory
  16. * 05-27-87 JCR Protected mode now uses only 3 pre-defined file handles,
  17. * not 5. Added PM (prot mode) to conditionalize handles.
  18. * 06-24-87 SKS Make "_bufin[]" and "_bufout[]" near for Compact/Large
  19. * models (MS real-mode version only)
  20. * 07-01-87 PHG Changed PM switch to PROTMODE
  21. * 11-05-87 JCR Added _buferr and modified stderr entry
  22. * 11-09-87 SKS Removed IBMC20 switch, Changed PROTMODE to OS2
  23. * 01-04-88 JCR Moved _NFILE_ definition from command line to file
  24. * 01-11-88 JCR Merged Mthread version into standard version
  25. * 01-21-88 JCR Removed reference to internal.h and added _NEAR_
  26. * (thus, internal.h doesn't get released in startup
  27. * sources even though _file.c does).
  28. * 06-28-88 JCR Remove static stdout/stderr buffers
  29. * 07-06-88 JCR Corrected _bufin declaration so it's always in BSS
  30. * 08-24-88 GJF Added check that OS2 is defined whenever M_I386 is.
  31. * 06-08-89 GJF Propagated SKS's fix of 02-08-89, and fixed copyright.
  32. * 07-25-89 GJF Cleanup (deleted DOS specific and OS/2 286 specific
  33. * stuff). Now specific to the 386.
  34. * 01-09-90 GJF _iob[], _iob2[] merge. Also, fixed copyright
  35. * 03-16-90 GJF Added #include <cruntime.h> and removed some (now)
  36. * useless preprocessor stuff.
  37. * 03-26-90 GJF Replaced _cdecl with _VARTYPE1.
  38. * 02-14-92 GJF Replaced _NFILE_ with _NSTREAM_ for Win32, with _NFILE
  39. * for non-Win32.
  40. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  41. * 05-11-93 GJF Replaced BUFSIZ with _INTERNAL_BUFSIZ.
  42. * 04-04-94 GJF #ifndef-ed out for Win32S version of msvcrt*.dll.
  43. * Also, deleted old conditionals for non-Win32 support.
  44. * 08-18-94 GJF Moved stdio terminator stuff from fflush.c to here
  45. * and added an initializer which fixes the _file field
  46. * of _iob[0], _iob[1] and _iob[2] when the underlying
  47. * entries in _osfhnd[0], _osfhnd[1], _osfhnd[2] are
  48. * invalid (0 or -1).
  49. * 02-17-95 GJF Appended Mac version of source file (somewhat cleaned
  50. * up), with appropriate #ifdef-s.
  51. * 03-01-95 GJF Changes to manage streams via __piob[], rather than
  52. * _iob[].
  53. * 06-12-95 GJF Replaced _osfhnd[] with _osfhnd() (macro referencing
  54. * field in ioinfo struct).
  55. * 06-19-97 GJF Moved _[un]lock_file[2]() here from startup\mlock.c.
  56. * 02-13-98 GJF Changes for Win32: changed long cast to intptr_t.
  57. * 04-28-99 PML Wrap __declspec(allocate()) in _CRTALLOC macro.
  58. * 09-26-97 BWT Fix POSIX
  59. * 05-17-99 PML Remove all Macintosh support.
  60. * 01-29-01 GB Added _func function version of data variable used in msvcprt.lib
  61. * to work with STATIC_CPPLIB
  62. * 03-27-01 PML .CRT$XI routines must now return 0 or _RT_* fatal
  63. * error code (vs7#231220)
  64. *
  65. *******************************************************************************/
  66. #include <sect_attribs.h>
  67. #include <cruntime.h>
  68. #include <windows.h>
  69. #include <stdio.h>
  70. #include <file2.h>
  71. #include <internal.h>
  72. #include <malloc.h>
  73. #include <rterr.h>
  74. #include <dbgint.h>
  75. #include <mtdll.h>
  76. /*
  77. * Buffer for stdin.
  78. */
  79. char _bufin[_INTERNAL_BUFSIZ];
  80. /*
  81. * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
  82. * is not initialized)
  83. */
  84. FILE _iob[_IOB_ENTRIES] = {
  85. /* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
  86. /* stdin (_iob[0]) */
  87. { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
  88. /* stdout (_iob[1]) */
  89. { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
  90. /* stderr (_iob[3]) */
  91. { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
  92. };
  93. /* These functions are for enabling STATIC_CPPLIB functionality */
  94. _CRTIMP FILE * __cdecl __iob_func(void)
  95. {
  96. return _iob;
  97. }
  98. /*
  99. * Pointer to array of FILE * or _FILEX * structures.
  100. */
  101. void ** __piob;
  102. /*
  103. * Number of open streams (set to _NSTREAM by default)
  104. */
  105. #ifdef CRTDLL
  106. int _nstream = _NSTREAM_;
  107. #else
  108. int _nstream;
  109. #endif
  110. /*
  111. * Initializer and terminator for stdio
  112. */
  113. int __cdecl __initstdio(void);
  114. void __cdecl __endstdio(void);
  115. #ifdef _MSC_VER
  116. #pragma data_seg(".CRT$XIC")
  117. _CRTALLOC(".CRT$XIC") static _PIFV pinit = __initstdio;
  118. #pragma data_seg(".CRT$XPX")
  119. _CRTALLOC(".CRT$XPX") static _PVFV pterm = __endstdio;
  120. #pragma data_seg()
  121. #endif /* _MSC_VER */
  122. #ifndef CRTDLL
  123. /*
  124. * _cflush is a dummy variable used to pull in _endstdio() when any STDIO
  125. * routine is included in the user program.
  126. */
  127. int _cflush = 0;
  128. #endif /* CRTDLL */
  129. /***
  130. * __initstdio - Initialize the stdio system
  131. *
  132. *Purpose:
  133. * Create and initialize the __piob array.
  134. *
  135. *Entry: <void>
  136. *
  137. *Exit: Returns _RT_STDIOINIT if error encountered.
  138. *
  139. *Uses:
  140. *
  141. *Exceptions:
  142. *
  143. *******************************************************************************/
  144. int __cdecl __initstdio(void)
  145. {
  146. int i;
  147. #ifndef CRTDLL
  148. /*
  149. * If the user has not supplied a definition of _nstream, set it
  150. * to _NSTREAM_. If the user has supplied a value that is too small
  151. * set _nstream to the minimum acceptable value (_IOB_ENTRIES).
  152. */
  153. if ( _nstream == 0 )
  154. _nstream = _NSTREAM_;
  155. else if ( _nstream < _IOB_ENTRIES )
  156. _nstream = _IOB_ENTRIES;
  157. #endif
  158. /*
  159. * Allocate the __piob array. Try for _nstream entries first. If this
  160. * fails then reset _nstream to _IOB_ENTRIES and try again. If it
  161. * still fails, bail out with an RTE.
  162. */
  163. if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) ==
  164. NULL ) {
  165. _nstream = _IOB_ENTRIES;
  166. if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) ))
  167. == NULL )
  168. return _RT_STDIOINIT;
  169. }
  170. /*
  171. * Initialize the first _IOB_ENTRIES to point to the corresponding
  172. * entries in _iob[].
  173. */
  174. for ( i = 0 ; i < _IOB_ENTRIES ; i++ )
  175. __piob[i] = (void *)&_iob[i];
  176. #ifndef _POSIX_
  177. for ( i = 0 ; i < 3 ; i++ ) {
  178. if ( (_osfhnd(i) == (intptr_t)INVALID_HANDLE_VALUE) ||
  179. (_osfhnd(i) == 0) )
  180. {
  181. _iob[i]._file = -1;
  182. }
  183. }
  184. #endif
  185. return 0;
  186. }
  187. /***
  188. * __endstdio - Terminate the stdio system
  189. *
  190. *Purpose:
  191. * Terminate the stdio system
  192. *
  193. * (1) Flush all streams. (Do this even if we're going to
  194. * call fcloseall since that routine won't do anything to the
  195. * std streams.)
  196. *
  197. * (2) If returning to caller, close all streams. This is
  198. * not necessary if the exe is terminating because the OS will
  199. * close the files for us (much more efficiently, too).
  200. *
  201. *Entry: <void>
  202. *
  203. *Exit: <void>
  204. *
  205. *Uses:
  206. *
  207. *Exceptions:
  208. *
  209. *******************************************************************************/
  210. void __cdecl __endstdio(void)
  211. {
  212. /* flush all streams */
  213. _flushall();
  214. /* if in callable exit, close all streams */
  215. if (_exitflag)
  216. _fcloseall();
  217. }
  218. #ifdef _MT
  219. /***
  220. * _lock_file - Lock a FILE
  221. *
  222. *Purpose:
  223. * Assert the lock for a stdio-level file
  224. *
  225. *Entry:
  226. * pf = __piob[] entry (pointer to a FILE or _FILEX)
  227. *
  228. *Exit:
  229. *
  230. *Exceptions:
  231. *
  232. *******************************************************************************/
  233. void __cdecl _lock_file (
  234. void *pf
  235. )
  236. {
  237. /*
  238. * The way the FILE (pointed to by pf) is locked depends on whether
  239. * it is part of _iob[] or not
  240. */
  241. if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  242. /*
  243. * FILE lies in _iob[] so the lock lies in _locktable[].
  244. */
  245. _lock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
  246. else
  247. /*
  248. * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  249. * lock field of the struct is an initialized critical
  250. * section.
  251. */
  252. EnterCriticalSection( &(((_FILEX *)pf)->lock) );
  253. }
  254. /***
  255. * _lock_file2(i, s) - Lock the FILE
  256. *
  257. *Purpose:
  258. * Assert the lock for a stdio-level file given by s == __piob[i].
  259. *
  260. *Entry:
  261. * s == __piob[i]
  262. *
  263. *Exit:
  264. *
  265. *Exceptions:
  266. *
  267. *******************************************************************************/
  268. void __cdecl _lock_file2 (
  269. int i,
  270. void *s
  271. )
  272. {
  273. /*
  274. * The way the FILE is locked depends on whether it is part of _iob[]
  275. * _iob[] or not
  276. */
  277. if ( i < _IOB_ENTRIES )
  278. /*
  279. * FILE lies in _iob[] so the lock lies in _locktable[].
  280. */
  281. _lock( _STREAM_LOCKS + i );
  282. else
  283. /*
  284. * Not part of _iob[]. Therefore, *s is a _FILEX and the
  285. * lock field of the struct is an initialized critical
  286. * section.
  287. */
  288. EnterCriticalSection( &(((_FILEX *)s)->lock) );
  289. }
  290. /***
  291. * _unlock_file - Unlock a FILE
  292. *
  293. *Purpose:
  294. * Release the lock for a stdio-level file
  295. *
  296. *Entry:
  297. * pf = __piob[] entry (pointer to a FILE or _FILEX)
  298. *
  299. *Exit:
  300. *
  301. *Exceptions:
  302. *
  303. *******************************************************************************/
  304. void __cdecl _unlock_file (
  305. void *pf
  306. )
  307. {
  308. /*
  309. * The way the FILE (pointed to by pf) is unlocked depends on whether
  310. * it is part of _iob[] or not
  311. */
  312. if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  313. /*
  314. * FILE lies in _iob[] so the lock lies in _locktable[].
  315. */
  316. _unlock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
  317. else
  318. /*
  319. * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  320. * lock field of the struct is an initialized critical
  321. * section.
  322. */
  323. LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
  324. }
  325. /***
  326. * _unlock_file2(i, s) - Lock the FILE
  327. *
  328. *Purpose:
  329. * Release the lock for a stdio-level file given by s == __piob[i].
  330. *
  331. *Entry:
  332. * s == __piob[i]
  333. *
  334. *Exit:
  335. *
  336. *Exceptions:
  337. *
  338. *******************************************************************************/
  339. void __cdecl _unlock_file2 (
  340. int i,
  341. void *s
  342. )
  343. {
  344. /*
  345. * The way the FILE is locked depends on whether it is part of _iob[]
  346. * _iob[] or not
  347. */
  348. if ( i < _IOB_ENTRIES )
  349. /*
  350. * FILE lies in _iob[] so the lock lies in _locktable[].
  351. */
  352. _unlock( _STREAM_LOCKS + i );
  353. else
  354. /*
  355. * Not part of _iob[]. Therefore, *s is a _FILEX and the
  356. * lock field of the struct is an initialized critical
  357. * section.
  358. */
  359. LeaveCriticalSection( &(((_FILEX *)s)->lock) );
  360. }
  361. #endif /* _MT */