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

  1. /***
  2. *close.c - close file handle for Windows NT
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _close() - close a file handle
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <oscalls.h>
  16. #include <io.h>
  17. #include <mtdll.h>
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include <msdos.h>
  21. #include <internal.h>
  22.  
  23. /***
  24. *int _close(fh) - close a file handle
  25. *
  26. *Purpose:
  27. *       Closes the file associated with the file handle fh.
  28. *
  29. *Entry:
  30. *       int fh - file handle to close
  31. *
  32. *Exit:
  33. *       returns 0 if successful, -1 (and sets errno) if fails
  34. *
  35. *Exceptions:
  36. *
  37. *******************************************************************************/
  38.  
  39. #ifdef _MT
  40.  
  41. /* define normal version that locks/unlocks, validates fh */
  42.  
  43. int __cdecl _close (
  44.         int fh
  45.         )
  46. {
  47.         int r;                          /* return value */
  48.  
  49.         /* validate file handle */
  50.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  51.              !(_osfile(fh) & FOPEN) )
  52.          {
  53.                 /* bad file handle, set errno and abort */
  54.                 errno = EBADF;
  55.                 _doserrno = 0;
  56.                 return -1;
  57.         }
  58.  
  59.         _lock_fh(fh);                   /* lock file */
  60.         r = _close_lk(fh);
  61.         _unlock_fh(fh);                 /* unlock the file */
  62.  
  63.         return r;
  64. }
  65.  
  66. /* now define version that doesn't lock/unlock, validate fh */
  67. int __cdecl _close_lk (
  68.         int fh
  69.         )
  70. {
  71.         DWORD dosretval;
  72.  
  73. #else  /* _MT */
  74.  
  75. /* now define normal version */
  76. int __cdecl _close (
  77.         int fh
  78.         )
  79. {
  80.         DWORD dosretval;
  81.  
  82.         /* validate file handle */
  83.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  84.              !(_osfile(fh) & FOPEN) )
  85.         {
  86.                 /* bad file handle, set errno and abort */
  87.                 errno = EBADF;
  88.                 _doserrno = 0;  /* no o.s. error */
  89.                 return -1;
  90.         }
  91. #endif  /* _MT */
  92.         /*
  93.          * Close the underlying OS file handle. Special cases:
  94.          *      1. If _get_osfhandle(fh) is INVALID_HANDLE_VALUE, don't try
  95.          *         to actually close it. Just reset the lowio info so the
  96.          *         handle can be reused. The standard handles are setup like
  97.          *         this in Windows app, or a background app.
  98.          *      2. If fh is STDOUT or STDERR, and if STDOUT and STDERR are
  99.          *         mapped to the same OS file handle, skip the CloseHandle
  100.          *         is skipped (without error). STDOUT and STDERR are the only
  101.          *         handles for which this support is provided. Other handles
  102.          *         are mapped to the same OS file handle only at the
  103.          *         programmer's risk.
  104.          */
  105.         if ( (_get_osfhandle(fh) == (long)INVALID_HANDLE_VALUE) ||
  106.              ( ((fh == 1) || (fh == 2)) &&
  107.                (_get_osfhandle(1) == _get_osfhandle(2)) ) ||
  108.              CloseHandle( (HANDLE)_get_osfhandle(fh) ) )
  109.         {
  110.  
  111.                 dosretval = 0L;
  112.         }
  113.         else
  114.                 dosretval = GetLastError();
  115.  
  116.         _free_osfhnd(fh);
  117.  
  118.         _osfile(fh) = 0;                /* clear file flags */
  119.  
  120.         if (dosretval) {
  121.                 /* OS error */
  122.                 _dosmaperr(dosretval);
  123.                 return -1;
  124.         }
  125.  
  126.         return 0;                       /* good return */
  127. }
  128.  
  129.  
  130. #else  /* _MAC */
  131.  
  132. #include <cruntime.h>
  133. #include <msdos.h>
  134. #include <memory.h>
  135. #include <errno.h>
  136. #include <stdlib.h>
  137. #include <internal.h>
  138. #include <macos\files.h>
  139. #include <macos\errors.h>
  140.  
  141. /***
  142. *int _close(fh) - close a file handle
  143. *
  144. *Purpose:
  145. *       Closes the file associated with the file handle fh.
  146. *
  147. *Entry:
  148. *       int fh - file handle to close
  149. *
  150. *Exit:
  151. *       returns 0 if successful, -1 (and sets errno) if fails
  152. *
  153. *Exceptions:
  154. *
  155. *******************************************************************************/
  156.  
  157. /* now define normal version */
  158. int __cdecl _close (
  159.         int fh
  160.         )
  161. {
  162.         ParamBlockRec parm;
  163.         OSErr osErr = 0;
  164.  
  165.         FCBPBRec fcbparm;
  166.         HParamBlockRec hparm;
  167.         OSErr osErrFCB = 0;
  168.         unsigned char strFilename[32];
  169.  
  170.         /* validate file handle */
  171.         if ((unsigned)fh >= (unsigned)_nfile || !(_osfile[fh] & FOPEN))
  172.         {
  173.                 /* bad file handle, set errno and abort */
  174.                 errno = EBADF;
  175.                 _macerrno = 0;
  176.                 return -1;
  177.         }
  178.  
  179.  
  180.         if (!(_osfile[fh] & FDEV))          /* no need to close console */
  181.         {
  182.                 if (_osfhnd[fh] == -1 )
  183.                 {
  184.                         /* an open file with a -1 handle indicates a pseudo open
  185.                            for stdin, stdout, or stderr -- close with no error */
  186.  
  187.                         _osfhnd[fh] = 0;    /* only allowed to close once */
  188.                 }
  189.                 else
  190.                 {
  191.                         /* if file is temporary, use the file FCB to get the
  192.                            volume, filename, and parent directory for deletion */
  193.  
  194.                         if (_osfileflags[fh] & FTEMP)
  195.                         {
  196.                                 fcbparm.ioFCBIndx = 0;
  197.                                 fcbparm.ioVRefNum = _osVRefNum[fh];
  198.                                 fcbparm.ioRefNum = _osfhnd[fh];
  199.                                 fcbparm.ioNamePtr = (StringPtr)strFilename;
  200.  
  201.                                 osErrFCB = PBGetFCBInfoSync(&fcbparm);
  202.                         }
  203.  
  204.                         parm.ioParam.ioRefNum = _osfhnd[fh];
  205.                         parm.ioParam.ioNamePtr = NULL;
  206.                         osErr = PBCloseSync(&parm);
  207.  
  208.                         if (osErr)
  209.                         {
  210.                                 _dosmaperr(osErr);
  211.                                 return -1;
  212.                         }
  213.  
  214.                         /* file is closed, so if temporary, delete */
  215.  
  216.                         if ((_osfileflags[fh] & FTEMP) && !osErrFCB)
  217.                         {
  218.                                 memset(&hparm, 0, sizeof(HParamBlockRec));
  219.                                 hparm.fileParam.ioVRefNum = fcbparm.ioFCBVRefNum;
  220.                                 hparm.fileParam.ioDirID = fcbparm.ioFCBParID;
  221.                                 hparm.fileParam.ioNamePtr = fcbparm.ioNamePtr;
  222.                                 PBHDeleteSync(&hparm);
  223.                         }
  224.  
  225.  
  226.                         /* flush volume to commit changes */
  227.                         memset(&parm, 0, sizeof(ParamBlockRec));
  228.                         parm.ioParam.ioVRefNum = _osVRefNum[fh];
  229.                         osErr = PBFlushVolSync(&parm);
  230.                 }
  231.         }
  232.  
  233.         _osfile[fh] = 0;                /* clear file flags */
  234.         _osfileflags[fh] = 0;
  235.         if (osErr)
  236.         {
  237.                 _dosmaperr(osErr);
  238.                 return -1;
  239.         }
  240.  
  241.         return 0;                       /* good return */
  242. }
  243.  
  244.  
  245. #endif  /* _MAC */
  246.