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

  1. /***
  2. *osfinfo.c - Win32 _osfhnd[] support routines
  3. *
  4. *       Copyright (c) 1990-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Defines the internally used routine _alloc_osfhnd()
  8. *       and the user visible routine _get_osfhandle().
  9. *
  10. *******************************************************************************/
  11.  
  12. #ifndef _MAC
  13.  
  14.  
  15. #include <cruntime.h>
  16. #include <oscalls.h>
  17. #include <errno.h>
  18. #include <internal.h>
  19. #include <fcntl.h>
  20. #include <malloc.h>
  21. #include <msdos.h>
  22. #include <mtdll.h>
  23. #include <stdlib.h>
  24. #include <dbgint.h>
  25.  
  26.  
  27. /***
  28. *int _alloc_osfhnd() - get free _ioinfo struct
  29. *
  30. *Purpose:
  31. *       Finds the first free entry in the arrays of ioinfo structs and
  32. *       returns the index of that entry (which is the CRT file handle to the
  33. *       caller) to the caller.
  34. *
  35. *Entry:
  36. *       none
  37. *
  38. *Exit:
  39. *       returns index of the entry, if successful
  40. *       return -1, if no free entry is available
  41. *
  42. *       MULTITHREAD NOTE: IF SUCCESSFUL, THE HANDLE IS LOCKED WHEN IT IS
  43. *       RETURNED TO THE CALLER!
  44. *
  45. *Exceptions:
  46. *
  47. *******************************************************************************/
  48.  
  49. int __cdecl _alloc_osfhnd(
  50.         void
  51.         )
  52. {
  53.         int fh = -1;    /* file handle */
  54.         int i;
  55.         ioinfo *pio;
  56.  
  57.         _mlock(_OSFHND_LOCK);   /* lock the __pioinfo[] array */
  58.  
  59.         /*
  60.          * Search the arrays of ioinfo structs, in order, looking for the
  61.          * first free entry. The compound index of this free entry is the
  62.          * return value. Here, the compound index of the ioinfo struct
  63.          * *(__pioinfo[i] + j) is k = i * IOINFO_ARRAY_ELTS + j, and k = 0,
  64.          * 1, 2,... is the order of the search.
  65.          */
  66.         for ( i = 0 ; i < IOINFO_ARRAYS ; i++ ) {
  67.             /*
  68.              * If __pioinfo[i] is non-empty array, search it looking for
  69.              * the first free entry. Otherwise, allocate a new array and use
  70.              * its first entry.
  71.              */
  72.             if ( __pioinfo[i] != NULL ) {
  73.                 /*
  74.                  * Search for an available entry.
  75.                  */
  76.                 for ( pio = __pioinfo[i] ;
  77.                       pio < __pioinfo[i] + IOINFO_ARRAY_ELTS ;
  78.                       pio++ )
  79.                 {
  80.                     if ( (pio->osfile & FOPEN) == 0 ) {
  81. #ifdef _MT
  82.                         /*
  83.                          * Make sure the lock is initialized.
  84.                          */
  85.                         if ( pio->lockinitflag == 0 ) {
  86.                             _mlock( _LOCKTAB_LOCK );
  87.                             if ( pio->lockinitflag == 0 ) {
  88.                                 InitializeCriticalSection( &(pio->lock) );
  89.                                 pio->lockinitflag++;
  90.                             }
  91.                             _munlock( _LOCKTAB_LOCK );
  92.                         }
  93.  
  94.                         EnterCriticalSection( &(pio->lock) );
  95.  
  96.                         /*
  97.                          * Check for the case where another thread has
  98.                          * managed to grab the handle out from under us.
  99.                          */
  100.                         if ( (pio->osfile & FOPEN) != 0 ) {
  101.                             LeaveCriticalSection( &(pio->lock) );
  102.                             continue;
  103.                         }
  104. #endif  /* _MT */
  105.                         pio->osfhnd = (long)INVALID_HANDLE_VALUE;
  106.                         fh = i * IOINFO_ARRAY_ELTS + (pio - __pioinfo[i]);
  107.                         break;
  108.                     }
  109.                 }
  110.  
  111.                 /*
  112.                  * Check if a free entry has been found.
  113.                  */
  114.                 if ( fh != -1 )
  115.                     break;
  116.             }
  117.             else {
  118.             /*
  119.              * Allocate and initialize another array of ioinfo structs.
  120.              */
  121.             if ( (pio = _malloc_crt( IOINFO_ARRAY_ELTS * sizeof(ioinfo) ))
  122.                 != NULL )
  123.             {
  124.  
  125.                 /*
  126.                  * Update __pioinfo[] and _nhandle
  127.                  */
  128.                 __pioinfo[i] = pio;
  129.                 _nhandle += IOINFO_ARRAY_ELTS;
  130.  
  131.                 for ( ; pio < __pioinfo[i] + IOINFO_ARRAY_ELTS ; pio++ ) {
  132.                     pio->osfile = 0;
  133.                     pio->osfhnd = (long)INVALID_HANDLE_VALUE;
  134.                     pio->pipech = 10;
  135. #ifdef _MT
  136.                     pio->lockinitflag = 0;
  137. #endif  /* _MT */
  138.                 }
  139.  
  140.                 /*
  141.                  * The first element of the newly allocated array of ioinfo
  142.                  * structs, *(__pioinfo[i]), is our first free entry.
  143.                  */
  144.                 fh = i * IOINFO_ARRAY_ELTS;
  145. #ifdef _MT
  146.                     _lock_fhandle( fh );
  147. #endif  /* _MT */
  148.             }
  149.  
  150.             break;
  151.             }
  152.         }
  153.  
  154.         _munlock(_OSFHND_LOCK); /* unlock the __pioinfo[] table */
  155.  
  156.  
  157.         /*
  158.          * return the index of the previously free table entry, if one was
  159.          * found. return -1 otherwise.
  160.          */
  161.         return( fh );
  162. }
  163.  
  164.  
  165. /***
  166. *int _set_osfhnd(int fh, long value) - set Win32 HANDLE value
  167. *
  168. *Purpose:
  169. *       If fh is in range and if _osfhnd(fh) is marked with
  170. *       INVALID_HANDLE_VALUE then set _osfhnd(fh) to the passed value.
  171. *
  172. *Entry:
  173. *       int fh      - CRT file handle
  174. *       long value  - new Win32 HANDLE value for this handle
  175. *
  176. *Exit:
  177. *       Returns zero if successful.
  178. *       Returns -1 and sets errno to EBADF otherwise.
  179. *
  180. *Exceptions:
  181. *
  182. *******************************************************************************/
  183.  
  184. int __cdecl _set_osfhnd (
  185.         int fh,
  186.         long value
  187.         )
  188. {
  189.         if ( ((unsigned)fh < (unsigned)_nhandle) &&
  190.              (_osfhnd(fh) == (long)INVALID_HANDLE_VALUE)
  191.            ) {
  192.             if ( __app_type == _CONSOLE_APP ) {
  193.                 switch (fh) {
  194.                 case 0:
  195.                     SetStdHandle( STD_INPUT_HANDLE, (HANDLE)value );
  196.                     break;
  197.                 case 1:
  198.                     SetStdHandle( STD_OUTPUT_HANDLE, (HANDLE)value );
  199.                     break;
  200.                 case 2:
  201.                     SetStdHandle( STD_ERROR_HANDLE, (HANDLE)value );
  202.                     break;
  203.                 }
  204.             }
  205.  
  206.             _osfhnd(fh) = value;
  207.             return(0);
  208.         } else {
  209.             errno = EBADF;      /* bad handle */
  210.             _doserrno = 0L;     /* not an OS error */
  211.             return -1;
  212.         }
  213. }
  214.  
  215.  
  216. /***
  217. *int _free_osfhnd(int fh) - mark osfhnd field of ioinfo struct as free
  218. *
  219. *Purpose:
  220. *       If fh is in range, the corrsponding ioinfo struct is marked as
  221. *       being open, and the osfhnd field is NOT set to INVALID_HANDLE_VALUE,
  222. *       then mark it with INVALID_HANDLE_VALUE.
  223. *
  224. *Entry:
  225. *       int fh -    CRT file handle
  226. *
  227. *Exit:
  228. *       Returns zero if successful.
  229. *       Returns -1 and sets errno to EBADF otherwise.
  230. *
  231. *Exceptions:
  232. *
  233. *******************************************************************************/
  234.  
  235. int __cdecl _free_osfhnd (
  236.         int fh      /* user's file handle */
  237.         )
  238. {
  239.         if ( ((unsigned)fh < (unsigned)_nhandle) &&
  240.              (_osfile(fh) & FOPEN) &&
  241.              (_osfhnd(fh) != (long)INVALID_HANDLE_VALUE) )
  242.         {
  243.             if ( __app_type == _CONSOLE_APP ) {
  244.                 switch (fh) {
  245.                 case 0:
  246.                     SetStdHandle( STD_INPUT_HANDLE, NULL );
  247.                     break;
  248.                 case 1:
  249.                     SetStdHandle( STD_OUTPUT_HANDLE, NULL );
  250.                     break;
  251.                 case 2:
  252.                     SetStdHandle( STD_ERROR_HANDLE, NULL );
  253.                     break;
  254.                 }
  255.             }
  256.  
  257.             _osfhnd(fh) = (long)INVALID_HANDLE_VALUE;
  258.             return(0);
  259.         } else {
  260.             errno = EBADF;      /* bad handle */
  261.             _doserrno = 0L;     /* not an OS error */
  262.             return -1;
  263.         }
  264. }
  265.  
  266.  
  267. /***
  268. *long _get_osfhandle(int fh) - get Win32 HANDLE value
  269. *
  270. *Purpose:
  271. *       If fh is in range and marked open, return _osfhnd(fh).
  272. *
  273. *Entry:
  274. *       int fh  - CRT file handle
  275. *
  276. *Exit:
  277. *       Returns the Win32 HANDLE successful.
  278. *       Returns -1 and sets errno to EBADF otherwise.
  279. *
  280. *Exceptions:
  281. *
  282. *******************************************************************************/
  283.  
  284. long __cdecl _get_osfhandle (
  285.         int fh      /* user's file handle */
  286.         )
  287. {
  288.         if ( ((unsigned)fh < (unsigned)_nhandle) && (_osfile(fh) & FOPEN) )
  289.             return( _osfhnd(fh) );
  290.         else {
  291.             errno = EBADF;      /* bad handle */
  292.             _doserrno = 0L;     /* not an OS error */
  293.             return -1;
  294.         }
  295. }
  296.  
  297. /***
  298. *int _open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
  299. *
  300. *Purpose:
  301. *       This function allocates a free C Runtime file handle and associates
  302. *       it with the Win32 HANDLE specified by the first parameter.
  303. *
  304. *Entry:
  305. *       long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
  306. *       int flags      - flags to associate with C Runtime file handle.
  307. *
  308. *Exit:
  309. *       returns index of entry in fh, if successful
  310. *       return -1, if no free entry is found
  311. *
  312. *Exceptions:
  313. *
  314. *******************************************************************************/
  315.  
  316. int __cdecl _open_osfhandle(
  317.         long osfhandle,
  318.         int flags
  319.         )
  320. {
  321.         int fh;
  322.         char fileflags;         /* _osfile flags */
  323.         DWORD isdev;            /* device indicator in low byte */
  324.  
  325.         /* copy relevant flags from second parameter */
  326.  
  327.         fileflags = 0;
  328.  
  329.         if ( flags & _O_APPEND )
  330.             fileflags |= FAPPEND;
  331.  
  332.         if ( flags & _O_TEXT )
  333.             fileflags |= FTEXT;
  334.  
  335.         if ( flags & _O_NOINHERIT )
  336.             fileflags |= FNOINHERIT;
  337.  
  338.         /* find out what type of file (file/device/pipe) */
  339.  
  340.         isdev = GetFileType((HANDLE)osfhandle);
  341.         if (isdev == FILE_TYPE_UNKNOWN) {
  342.             /* OS error */
  343.             _dosmaperr( GetLastError() );   /* map error */
  344.             return -1;
  345.         }
  346.  
  347.         /* is isdev value to set flags */
  348.         if (isdev == FILE_TYPE_CHAR)
  349.             fileflags |= FDEV;
  350.         else if (isdev == FILE_TYPE_PIPE)
  351.             fileflags |= FPIPE;
  352.  
  353.  
  354.         /* attempt to allocate a C Runtime file handle */
  355.  
  356.         if ( (fh = _alloc_osfhnd()) == -1 ) {
  357.             errno = EMFILE;         /* too many open files */
  358.             _doserrno = 0L;         /* not an OS error */
  359.             return -1;              /* return error to caller */
  360.         }
  361.  
  362.         /*
  363.          * the file is open. now, set the info in _osfhnd array
  364.          */
  365.  
  366.         _set_osfhnd(fh, osfhandle);
  367.  
  368.         fileflags |= FOPEN;     /* mark as open */
  369.  
  370.         _osfile(fh) = fileflags;    /* set osfile entry */
  371.  
  372.         _unlock_fh(fh);         /* unlock handle */
  373.  
  374.         return fh;          /* return handle */
  375. }
  376.  
  377.  
  378. #ifdef _MT
  379.  
  380. /***
  381. *void _lock_fhandle(int fh) - lock file handle
  382. *
  383. *Purpose:
  384. *       Assert the lock associated with the passed file handle.
  385. *
  386. *Entry:
  387. *       int fh  - CRT file handle
  388. *
  389. *Exit:
  390. *
  391. *Exceptions:
  392. *
  393. *******************************************************************************/
  394.  
  395. void __cdecl _lock_fhandle (
  396.         int fh
  397.         )
  398. {
  399.         ioinfo *pio = _pioinfo(fh);
  400.  
  401.         /*
  402.          * Make sure the lock has been initialized.
  403.          */
  404.         if ( pio->lockinitflag == 0 ) {
  405.  
  406.             _mlock( _LOCKTAB_LOCK );
  407.  
  408.             if ( pio->lockinitflag == 0 ) {
  409.                 InitializeCriticalSection( &(pio->lock) );
  410.                 pio->lockinitflag++;
  411.             }
  412.  
  413.             _munlock( _LOCKTAB_LOCK);
  414.         }
  415.  
  416.         EnterCriticalSection( &(_pioinfo(fh)->lock) );
  417. }
  418.  
  419.  
  420. /***
  421. *void _unlock_fhandle(int fh) - unlock file handle
  422. *
  423. *Purpose:
  424. *       Release the lock associated with passed file handle.
  425. *
  426. *Entry:
  427. *       int fh  - CRT file handle
  428. *
  429. *Exit:
  430. *
  431. *Exceptions:
  432. *
  433. *******************************************************************************/
  434.  
  435. void __cdecl _unlock_fhandle (
  436.         int fh
  437.         )
  438. {
  439.         LeaveCriticalSection( &(_pioinfo(fh)->lock) );
  440. }
  441.  
  442. #endif  /* _MT */
  443.  
  444.  
  445. #else  /* _MAC */
  446.  
  447.  
  448. #include <cruntime.h>
  449. #include <errno.h>
  450. #include <internal.h>
  451. #include <fcntl.h>
  452. #include <msdos.h>
  453. #include <stdlib.h>
  454.  
  455. /***
  456. *int _alloc_osfhnd() - get free _osfhnd[] entry
  457. *
  458. *Purpose:
  459. *       Finds the first free entry in _osfhnd[], mark it in use and return
  460. *       the index of the entry to the caller.
  461. *
  462. *Entry:
  463. *       none
  464. *
  465. *Exit:
  466. *       returns index of entry in fh, if successful
  467. *       return -1, if no free entry is found in _osfhnd[].
  468. *
  469. *Exceptions:
  470. *
  471. *******************************************************************************/
  472.  
  473. int __cdecl _alloc_osfhnd(
  474.         void
  475.         )
  476. {
  477.         int fh;         /* _osfhnd[] index */
  478.  
  479.         /*
  480.          * search _osfhnd[] for an entry that is not currently being used.
  481.          * if one is found, mark it in use and set the _osfhandle field to
  482.          * 0xffffffff.
  483.          */
  484.         for ( fh = 0 ; fh < _nfile ; fh++ ) {
  485.             if ( (_osfile[fh] & FOPEN) == 0 ) {
  486.                 /*
  487.                  * free entry found! initialize it and
  488.                  * break out of the loop
  489.                  */
  490.                 _osfhnd[fh] = (long)0xffffffff;
  491.                 break;
  492.             }
  493.         }
  494.  
  495.         /*
  496.          * return the index of the previously free table entry, if one was
  497.          * found. return -1 otherwise.
  498.          */
  499.         return( (fh >= _nfile) ? -1 : fh );
  500. }
  501.  
  502.  
  503. /***
  504. *int _set_osfhnd(int fh) - set OS file handle table value
  505. *
  506. *Purpose:
  507. *       If fh is in range and if _osfhnd[fh] is marked with 0xfffffff
  508. *       then set _osfhnd[fh] to the passed value.
  509. *
  510. *Entry:
  511. *       int fh -    index of _osfhnd[] entry
  512. *       long fh     -   new value of this handle entry
  513. *
  514. *Exit:
  515. *       Returns zero if successful.
  516. *       Returns -1 and sets errno to EBADF otherwise.
  517. *
  518. *Exceptions:
  519. *
  520. *******************************************************************************/
  521.  
  522. int __cdecl _set_osfhnd (
  523.         int fh,     /* index into _osfhnd[] (user's file handle) */
  524.         long value
  525.         )
  526. {
  527.         if ( ((unsigned)fh < (unsigned)_nfile) &&
  528.              _osfhnd[fh] == (long)0xffffffff
  529.            ) {
  530.             _osfhnd[fh] = value;
  531.             return(0);
  532.         } else {
  533.             errno = EBADF;      /* bad handle */
  534.             _macerrno = 0L;     /* not an OS error */
  535.             return -1;
  536.         }
  537. }
  538.  
  539.  
  540. /***
  541. *int _free_osfhnd(int fh) - free OS file handle table entry
  542. *
  543. *Purpose:
  544. *       If fh is in range and if _osfhnd[fh] is in use and NOT marked
  545. *       with 0xfffffff
  546. *
  547. *Entry:
  548. *       int fh -    index of _osfhnd[] entry
  549. *
  550. *Exit:
  551. *       Returns zero if successful.
  552. *       Returns -1 and sets errno to EBADF otherwise.
  553. *
  554. *Exceptions:
  555. *
  556. *******************************************************************************/
  557.  
  558. int __cdecl _free_osfhnd (
  559.         int fh      /* index into _osfhnd[] (user's file handle) */
  560.         )
  561. {
  562.         if ( ((unsigned)fh < (unsigned)_nfile) &&
  563.              (_osfile[fh] & FOPEN) &&
  564.              _osfhnd[fh] != (long)0xffffffff
  565.            ) {
  566.             _osfhnd[fh] = (long)0xffffffff;
  567.             return(0);
  568.         } else {
  569.             errno = EBADF;      /* bad handle */
  570.             _macerrno = 0L;     /* not an OS error */
  571.             return -1;
  572.         }
  573. }
  574.  
  575.  
  576. /***
  577. *long _get_osfhandle(int fh) - get OS file handle
  578. *
  579. *Purpose:
  580. *       If fh is in range and if _osfhnd[fh] is marked free, return
  581. *       _osfhnd[fh]
  582. *
  583. *Entry:
  584. *       int fh -    index of _osfhnd[] entry
  585. *
  586. *Exit:
  587. *       Returns the OS file handle if successful.
  588. *       Returns -1 and sets errno to EBADF otherwise.
  589. *
  590. *Exceptions:
  591. *
  592. *******************************************************************************/
  593.  
  594. long __cdecl _get_osfhandle (
  595.         int fh      /* index into _osfhnd[] (user's file handle) */
  596.         )
  597. {
  598.         if ( ((unsigned)fh < (unsigned)_nfile) && (_osfile[fh] & FOPEN))
  599.             return(_osfhnd[fh]);
  600.         else {
  601.             errno = EBADF;      /* bad handle */
  602.             _macerrno = 0L;     /* not an OS error */
  603.             return -1;
  604.         }
  605. }
  606.  
  607. /***
  608. *int _open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
  609. *
  610. *Purpose:
  611. *       This function allocates a free C Runtime file handle and sets it
  612. *       to point to the Win32 file handle specified by the first parameter.
  613. *
  614. *Entry:
  615. *       long osfhandle -Win32 file handle to associate with C Runtime file handle.
  616. *       int flags -     flags to associate with C Runtime file handle.
  617. *
  618. *Exit:
  619. *       returns index of entry in fh, if successful
  620. *       return -1, if no free entry is found in _osfhnd[].
  621. *
  622. *Exceptions:
  623. *
  624. *******************************************************************************/
  625.  
  626. int __cdecl _open_osfhandle(
  627.         long osfhandle,
  628.         int flags
  629.         )
  630. {
  631.         int fh;
  632.         char fileflags;         /* _osfile flags */
  633.  
  634.         /* copy relavent flags from second parameter */
  635.  
  636.         fileflags = 0;
  637.         if ( flags & _O_RDONLY )
  638.             fileflags |= FRDONLY;
  639.         else if ( flags & _O_APPEND )
  640.                 fileflags |= FAPPEND;
  641.         else if ( flags & _O_TEXT )
  642.                 fileflags |= FTEXT;
  643.  
  644.         /* attempt to allocate a C Runtime file handle */
  645.  
  646.         if ( (fh = _alloc_osfhnd()) == -1 ) {
  647.             errno = EMFILE;     /* too many open files */
  648.             _macerrno = 0L;         /* not an OS error */
  649.             return -1;      /* return error to caller */
  650.         }
  651.  
  652.         /*
  653.          * the file is open. now, set the info in _osfhnd array
  654.          */
  655.  
  656.         _set_osfhnd(fh, osfhandle);
  657.  
  658.         fileflags |= FOPEN;     /* mark as open */
  659.  
  660.         _osfile[fh] = fileflags;    /* set osfile entry */
  661.  
  662.         return fh;          /* return handle */
  663. }
  664.  
  665.  
  666. #endif  /* _MAC */
  667.