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.

415 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. * 11-06-01 GB To Minimize Leaks, Added free_crt(piob) in __endstdio
  65. *
  66. *******************************************************************************/
  67. #include <sect_attribs.h>
  68. #include <cruntime.h>
  69. #include <windows.h>
  70. #include <stdio.h>
  71. #include <file2.h>
  72. #include <internal.h>
  73. #include <malloc.h>
  74. #include <rterr.h>
  75. #include <dbgint.h>
  76. #include <mtdll.h>
  77. /*
  78. * Buffer for stdin.
  79. */
  80. char _bufin[_INTERNAL_BUFSIZ];
  81. /*
  82. * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
  83. * is not initialized)
  84. */
  85. FILE _iob[_IOB_ENTRIES] = {
  86. /* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
  87. /* stdin (_iob[0]) */
  88. { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
  89. /* stdout (_iob[1]) */
  90. { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
  91. /* stderr (_iob[3]) */
  92. { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
  93. };
  94. /* These functions are for enabling STATIC_CPPLIB functionality */
  95. _CRTIMP FILE * __cdecl __iob_func(void)
  96. {
  97. return _iob;
  98. }
  99. /*
  100. * Pointer to array of FILE * or _FILEX * structures.
  101. */
  102. void ** __piob;
  103. /*
  104. * Number of open streams (set to _NSTREAM by default)
  105. */
  106. #ifdef CRTDLL
  107. int _nstream = _NSTREAM_;
  108. #else
  109. int _nstream;
  110. #endif
  111. /*
  112. * Initializer and terminator for stdio
  113. */
  114. int __cdecl __initstdio(void);
  115. void __cdecl __endstdio(void);
  116. #ifdef _MSC_VER
  117. #pragma data_seg(".CRT$XIC")
  118. _CRTALLOC(".CRT$XIC") static _PIFV pinit = __initstdio;
  119. #pragma data_seg(".CRT$XPXA")
  120. _CRTALLOC(".CRT$XPXA") static _PVFV pterm = __endstdio;
  121. #pragma data_seg()
  122. #endif /* _MSC_VER */
  123. #ifndef CRTDLL
  124. /*
  125. * _cflush is a dummy variable used to pull in _endstdio() when any STDIO
  126. * routine is included in the user program.
  127. */
  128. int _cflush = 0;
  129. #endif /* CRTDLL */
  130. /***
  131. * __initstdio - Initialize the stdio system
  132. *
  133. *Purpose:
  134. * Create and initialize the __piob array.
  135. *
  136. *Entry: <void>
  137. *
  138. *Exit: Returns _RT_STDIOINIT if error encountered.
  139. *
  140. *Uses:
  141. *
  142. *Exceptions:
  143. *
  144. *******************************************************************************/
  145. int __cdecl __initstdio(void)
  146. {
  147. int i;
  148. #ifndef CRTDLL
  149. /*
  150. * If the user has not supplied a definition of _nstream, set it
  151. * to _NSTREAM_. If the user has supplied a value that is too small
  152. * set _nstream to the minimum acceptable value (_IOB_ENTRIES).
  153. */
  154. if ( _nstream == 0 )
  155. _nstream = _NSTREAM_;
  156. else if ( _nstream < _IOB_ENTRIES )
  157. _nstream = _IOB_ENTRIES;
  158. #endif
  159. /*
  160. * Allocate the __piob array. Try for _nstream entries first. If this
  161. * fails then reset _nstream to _IOB_ENTRIES and try again. If it
  162. * still fails, bail out with an RTE.
  163. */
  164. if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) ==
  165. NULL ) {
  166. _nstream = _IOB_ENTRIES;
  167. if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) ))
  168. == NULL )
  169. return _RT_STDIOINIT;
  170. }
  171. /*
  172. * Initialize the first _IOB_ENTRIES to point to the corresponding
  173. * entries in _iob[].
  174. */
  175. for ( i = 0 ; i < _IOB_ENTRIES ; i++ )
  176. __piob[i] = (void *)&_iob[i];
  177. #ifndef _POSIX_
  178. for ( i = 0 ; i < 3 ; i++ ) {
  179. if ( (_osfhnd(i) == (intptr_t)INVALID_HANDLE_VALUE) ||
  180. (_osfhnd(i) == 0) )
  181. {
  182. _iob[i]._file = -1;
  183. }
  184. }
  185. #endif
  186. return 0;
  187. }
  188. /***
  189. * __endstdio - Terminate the stdio system
  190. *
  191. *Purpose:
  192. * Terminate the stdio system
  193. *
  194. * (1) Flush all streams. (Do this even if we're going to
  195. * call fcloseall since that routine won't do anything to the
  196. * std streams.)
  197. *
  198. * (2) If returning to caller, close all streams. This is
  199. * not necessary if the exe is terminating because the OS will
  200. * close the files for us (much more efficiently, too).
  201. *
  202. *Entry: <void>
  203. *
  204. *Exit: <void>
  205. *
  206. *Uses:
  207. *
  208. *Exceptions:
  209. *
  210. *******************************************************************************/
  211. void __cdecl __endstdio(void)
  212. {
  213. /* flush all streams */
  214. _flushall();
  215. /* if in callable exit, close all streams */
  216. if (_exitflag)
  217. _fcloseall();
  218. #ifndef CRTDLL
  219. _free_crt(__piob);
  220. #endif
  221. }
  222. #ifdef _MT
  223. /***
  224. * _lock_file - Lock a FILE
  225. *
  226. *Purpose:
  227. * Assert the lock for a stdio-level file
  228. *
  229. *Entry:
  230. * pf = __piob[] entry (pointer to a FILE or _FILEX)
  231. *
  232. *Exit:
  233. *
  234. *Exceptions:
  235. *
  236. *******************************************************************************/
  237. void __cdecl _lock_file (
  238. void *pf
  239. )
  240. {
  241. /*
  242. * The way the FILE (pointed to by pf) is locked depends on whether
  243. * it is part of _iob[] or not
  244. */
  245. if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  246. /*
  247. * FILE lies in _iob[] so the lock lies in _locktable[].
  248. */
  249. _lock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
  250. else
  251. /*
  252. * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  253. * lock field of the struct is an initialized critical
  254. * section.
  255. */
  256. EnterCriticalSection( &(((_FILEX *)pf)->lock) );
  257. }
  258. /***
  259. * _lock_file2(i, s) - Lock the FILE
  260. *
  261. *Purpose:
  262. * Assert the lock for a stdio-level file given by s == __piob[i].
  263. *
  264. *Entry:
  265. * s == __piob[i]
  266. *
  267. *Exit:
  268. *
  269. *Exceptions:
  270. *
  271. *******************************************************************************/
  272. void __cdecl _lock_file2 (
  273. int i,
  274. void *s
  275. )
  276. {
  277. /*
  278. * The way the FILE is locked depends on whether it is part of _iob[]
  279. * _iob[] or not
  280. */
  281. if ( i < _IOB_ENTRIES )
  282. /*
  283. * FILE lies in _iob[] so the lock lies in _locktable[].
  284. */
  285. _lock( _STREAM_LOCKS + i );
  286. else
  287. /*
  288. * Not part of _iob[]. Therefore, *s is a _FILEX and the
  289. * lock field of the struct is an initialized critical
  290. * section.
  291. */
  292. EnterCriticalSection( &(((_FILEX *)s)->lock) );
  293. }
  294. /***
  295. * _unlock_file - Unlock a FILE
  296. *
  297. *Purpose:
  298. * Release the lock for a stdio-level file
  299. *
  300. *Entry:
  301. * pf = __piob[] entry (pointer to a FILE or _FILEX)
  302. *
  303. *Exit:
  304. *
  305. *Exceptions:
  306. *
  307. *******************************************************************************/
  308. void __cdecl _unlock_file (
  309. void *pf
  310. )
  311. {
  312. /*
  313. * The way the FILE (pointed to by pf) is unlocked depends on whether
  314. * it is part of _iob[] or not
  315. */
  316. if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
  317. /*
  318. * FILE lies in _iob[] so the lock lies in _locktable[].
  319. */
  320. _unlock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
  321. else
  322. /*
  323. * Not part of _iob[]. Therefore, *pf is a _FILEX and the
  324. * lock field of the struct is an initialized critical
  325. * section.
  326. */
  327. LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
  328. }
  329. /***
  330. * _unlock_file2(i, s) - Lock the FILE
  331. *
  332. *Purpose:
  333. * Release the lock for a stdio-level file given by s == __piob[i].
  334. *
  335. *Entry:
  336. * s == __piob[i]
  337. *
  338. *Exit:
  339. *
  340. *Exceptions:
  341. *
  342. *******************************************************************************/
  343. void __cdecl _unlock_file2 (
  344. int i,
  345. void *s
  346. )
  347. {
  348. /*
  349. * The way the FILE is locked depends on whether it is part of _iob[]
  350. * _iob[] or not
  351. */
  352. if ( i < _IOB_ENTRIES )
  353. /*
  354. * FILE lies in _iob[] so the lock lies in _locktable[].
  355. */
  356. _unlock( _STREAM_LOCKS + i );
  357. else
  358. /*
  359. * Not part of _iob[]. Therefore, *s is a _FILEX and the
  360. * lock field of the struct is an initialized critical
  361. * section.
  362. */
  363. LeaveCriticalSection( &(((_FILEX *)s)->lock) );
  364. }
  365. #endif /* _MT */