home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / ioinit.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  11KB  |  342 lines

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