home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and Microsoft
- // QuickHelp and/or WinHelp documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #include <errno.h>
- #include <io.h>
- #include <limits.h>
- #include <malloc.h>
-
- #include <sys\types.h>
- #include <sys\stat.h>
- #ifdef _PORTABLE
- #include <sys\locking.h>
- #endif
-
- #ifdef AFX_CORE2_SEG
- #pragma code_seg(AFX_CORE2_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- ////////////////////////////////////////////////////////////////////////////
- // Low level File i/o portability layer
- // DOS functions not provided by C Runtimes
-
-
- #include <dos.h>
- #ifdef _WINDOWS
- extern "C" void FAR PASCAL DOS3Call();
- #define DOSCALL call DOS3Call
- #else // _DOS
- #define DOSCALL int 21h
- #endif // _WINDOWS
-
- #ifndef _PORTABLE
- // Non-Portable, DOSCALL specific implementation
- // Most efficient and gives most accurate failure codes
-
- #pragma optimize("qgel", off) // assembler cannot be globally optimized
-
- static UINT PASCAL _Afx_seek(UINT hFile, LONG lOff, UINT nMode,
- DWORD FAR* lpdwNew)
- {
- UINT res;
- *lpdwNew = -1;
- _asm {
- mov bx, hFile
- mov ax, nMode
- mov ah, 42h
- mov dx, word ptr lOff
- mov cx, word ptr lOff+2
- DOSCALL
- jc __seek_err
- les bx, lpdwNew
- mov word ptr es:[bx], ax
- mov word ptr es:[bx+2], dx
- xor ax, ax
- __seek_err:
- mov res, ax
- }
- return res;
- }
-
- static UINT PASCAL _Afx_rename(LPCSTR lpszOld, LPCSTR lpszNew)
- {
- UINT res;
- _asm {
- mov bx, ds
- lds dx, lpszOld
- les di, lpszNew
- mov ax, 5600h
- DOSCALL
- jc __rename_err
- xor ax, ax
- __rename_err:
- mov res, ax
- mov ds, bx
- }
- return res;
- }
-
- static UINT PASCAL _Afx_remove(LPCSTR lpsz)
- {
- UINT res;
- _asm {
- mov bx, ds
- lds dx, lpsz
- mov ax, 4100h
- DOSCALL
- jc __remove_err
- xor ax, ax
- __remove_err:
- mov res, ax
- mov ds, bx
- }
- return res;
- }
-
- static UINT PASCAL _Afx_lock(UINT hFile, DWORD dwStart, DWORD dwLen, BOOL bUnlock)
- {
- UINT res;
- _asm {
- mov ax, bUnlock
- mov ah, 5ch
- mov bx, hFile
- mov dx, word ptr dwStart
- mov cx, word ptr dwStart+2
- mov di, word ptr dwLen
- mov si, word ptr dwLen+2
- DOSCALL
- jc __lock_err1
- xor ax, ax
- __lock_err1:
- mov res, ax
-
- }
- return res;
- }
-
- #pragma optimize("", on) // return to default optimizations
-
- #else // _PORTABLE implementations
-
- // Portable, C-Runtime implementation
- // More portable but can gives less accurate failure codes
- static UINT PASCAL _Afx_seek(UINT hFile, LONG lOff, UINT nMode,
- DWORD FAR* lpdwNew)
- {
- *lpdwNew = (DWORD)_lseek((int)hFile, lOff, (int)nMode);
- if (*lpdwNew == (DWORD)-1L)
- {
- if (errno == EBADF)
- return 0x6; // invalid file
- else
- return 0x19; // bad seek
- }
- return 0;
- }
-
- static UINT PASCAL _Afx_rename(LPCSTR lpszOld, LPCSTR lpszNew)
- {
- char* pszOld;
- char* pszNew;
- #ifdef _NEARDATA
- char szOld[_MAX_PATH];
- char szNew[_MAX_PATH];
- lstrcpy(szOld, lpszOld);
- lstrcpy(szNew, lpszNew);
- pszOld = szOld;
- pszNew = szNew;
- #else
- pszOld = (LPSTR)lpszOld;
- pszNew = (LPSTR)lpszNew;
- #endif
- if (rename(pszOld, pszNew) != 0)
- {
- if (errno == EACCES)
- return 0x5; // access denied
- else
- return 0x2; // file not found
- }
- return 0;
- }
-
- static UINT PASCAL _Afx_remove(LPCSTR lpsz)
- {
- char* psz;
- #ifdef _NEARDATA
- char sz[_MAX_PATH];
- lstrcpy(sz, lpsz);
- psz = sz;
- #else
- psz = (LPSTR)lpsz;
- #endif
- if (remove(psz) != 0)
- {
- if (errno == EACCES)
- return 0x5; // access denied
- else
- return 0x2; // file not found
- }
- return 0;
- }
-
- static UINT PASCAL _Afx_lock(UINT hFile, DWORD dwStart, DWORD dwLen, BOOL bUnlock)
- {
- DWORD dwPos;
- DWORD dw;
- UINT nErr;
-
- if (_Afx_seek(hFile, 0, 0, &dwPos) != 0)
- return 0;
- if ((nErr = _Afx_seek(hFile, (LONG)dwStart, 0, &dw)) != 0)
- {
- _Afx_seek(hFile, dwPos, 0, &dw);
- return nErr;
- }
- if (_locking(hFile, bUnlock ? _LK_UNLCK : _LK_NBLCK, dwLen) != 0)
- {
- switch (errno)
- {
- case EACCES:
- return 0x21; // lock violation
- case EBADF:
- return 0x6; // bad file handle
- default:
- return 0x1;
- }
- }
- _Afx_seek(hFile, dwPos, 0, &dw);
- return 0;
- }
-
- #endif // _PORTABLE
-
- ////////////////////////////////////////////////////////////////////////////
- // CFile implementation
- IMPLEMENT_DYNAMIC(CFile, CObject)
-
-
- CFile::CFile()
- {
- m_hFile = hFileNull;
- m_bCloseOnDelete = FALSE;
- }
-
- CFile::CFile(int hFile)
- {
- m_hFile = hFile;
- m_bCloseOnDelete = FALSE;
- }
-
- CFile::CFile(const char* pszFileName, UINT nOpenFlags)
- {
- ASSERT(AfxIsValidString(pszFileName));
-
- CFileException e;
- if (!Open(pszFileName, nOpenFlags, &e))
- AfxThrowFileException(e.m_cause, e.m_lOsError);
- }
-
- CFile::~CFile()
- {
- if (m_hFile != (UINT)hFileNull && m_bCloseOnDelete)
- Close();
- }
-
- CFile*
- CFile::Duplicate() const
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- CFile* pFile = new CFile(hFileNull);
- pFile->m_hFile = (UINT) _dup((int)m_hFile);
- ASSERT(((int)(pFile->m_hFile)) != -1);
- pFile->m_bCloseOnDelete = m_bCloseOnDelete;
- return pFile;
- }
-
-
- BOOL
- CFile::Open(const char* pszFileName, UINT nOpenFlags,
- CFileException* pException /* = NULL */)
- {
- ASSERT(AfxIsValidString(pszFileName));
- ASSERT(pException == NULL || AfxIsValidAddress(pException, sizeof(CFileException)));
- ASSERT((nOpenFlags & typeText) == 0);
-
- // CFile objects are always binary and _dos_open does not need flag
- nOpenFlags &= ~(UINT)CFile::typeBinary;
-
- m_bCloseOnDelete = FALSE;
- m_hFile = (UINT)hFileNull;
-
- ASSERT_VALID(this);
-
- char szOemPath[_MAX_PATH];
- UINT nErr;
-
- AnsiToOem(pszFileName, szOemPath);
-
- if (nOpenFlags & (UINT)CFile::modeCreate)
- {
- if ((nErr = _dos_creat(szOemPath, CFile::normal, (int*)&m_hFile)) != 0)
- {
- if (pException != NULL)
- {
- pException->m_lOsError = nErr;
- pException->m_cause = CFileException::OsErrorToException(nErr);
- return FALSE; // file was not created
- }
- }
- if ((nErr = _dos_close(m_hFile)) != 0)
- {
- // try to delete the file and throw modeCreate exception
- _Afx_remove(szOemPath);
- if (pException != NULL)
- {
- pException->m_lOsError = nErr;
- pException->m_cause = CFileException::OsErrorToException(nErr);
- }
- return FALSE;
- }
- }
-
- // the file has been modeCreated if needed, now open it
- if ((nErr = _dos_open(szOemPath, nOpenFlags & ~(UINT)CFile::modeCreate, (int*)&m_hFile)) != 0)
- {
- // throw open exception if requested
- if (pException != NULL)
- {
- pException->m_lOsError = nErr;
- pException->m_cause = CFileException::OsErrorToException(nErr);
- }
- return FALSE;
- }
- m_bCloseOnDelete = TRUE;
- return TRUE;
- }
-
-
- UINT
- CFile::Read(void FAR* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
- ASSERT(lpBuf != NULL);
- ASSERT(AfxIsValidAddress(lpBuf, nCount));
-
- UINT nRead = 0;
- UINT nErr;
-
- if ((nErr = _dos_read(m_hFile, lpBuf, nCount, &nRead)) != 0)
- CFileException::ThrowOsError(nErr);
-
- return nRead;
- }
-
- void
- CFile::Write(const void FAR* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
- ASSERT(lpBuf != NULL);
- ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
-
- UINT nWritten = 0;
- UINT nErr;
-
- if ((nErr = _dos_write(m_hFile, lpBuf, nCount, &nWritten)) != 0)
- CFileException::ThrowOsError(nErr);
-
- if (nCount != nWritten)
- AfxThrowFileException(CFileException::diskFull);
- }
-
-
- LONG
- CFile::Seek(LONG lOff, UINT nFrom)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
- ASSERT(nFrom == CFile::begin || nFrom == CFile::end || nFrom == CFile::current);
-
- DWORD dwNew;
- UINT nErr;
-
- if ((nErr = _Afx_seek(m_hFile, lOff, nFrom, &dwNew)) != 0)
- CFileException::ThrowOsError(nErr);
-
- return dwNew;
- }
-
-
- DWORD
- CFile::GetPosition() const
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- DWORD dwPos;
- UINT nErr;
-
- if ((nErr = _Afx_seek(m_hFile, 0, CFile::current, &dwPos)) != 0)
- CFileException::ThrowOsError(nErr);
-
- return dwPos;
- }
-
-
- #pragma optimize("qgel", off) // assembler cannot be globally optimized
- void
- CFile::Flush()
- {
- ASSERT_VALID(this);
-
- UINT nErr;
-
- if (m_hFile == (UINT)hFileNull)
- return;
-
- #ifndef _PORTABLE
- // SmartDrive 4.0 workaround, carry flag incorrectly propogated
- _asm { CLC }
- #endif
-
- if ((nErr = _dos_commit(m_hFile)) != 0)
- CFileException::ThrowOsError(nErr);
- }
- #pragma optimize("", on) // return to default optimizations
-
- void
- CFile::Close()
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- UINT nErr = 0;
-
- if (m_hFile != (UINT)hFileNull)
- nErr = _dos_close(m_hFile);
-
- m_hFile = hFileNull;
- m_bCloseOnDelete = FALSE;
-
- if (nErr != 0)
- CFileException::ThrowOsError(nErr);
- }
-
- void
- CFile::Abort()
- {
- ASSERT_VALID(this);
- if (m_hFile != (UINT)hFileNull)
- {
- // close but ignore errors
- _dos_close(m_hFile);
- m_hFile = (UINT)hFileNull;
- }
- }
-
- void
- CFile::LockRange(DWORD dwPos, DWORD dwCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- UINT nErr;
-
- if ((nErr = _Afx_lock(m_hFile, dwPos, dwCount, FALSE)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
-
- void
- CFile::UnlockRange(DWORD dwPos, DWORD dwCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- UINT nErr;
-
- if ((nErr = _Afx_lock(m_hFile, dwPos, dwCount, TRUE)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
-
- void
- CFile::SetLength(DWORD dwNewLen)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != (UINT)hFileNull);
-
- UINT nErr;
- UINT nWritten = 0;
-
- Seek(dwNewLen, CFile::begin);
-
- if ((nErr = _dos_write(m_hFile, NULL, 0, &nWritten)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
- DWORD
- CFile::GetLength() const
- {
- ASSERT_VALID(this);
-
- DWORD dwLen, dwCur;
-
- // Seek is a non const operation
- dwCur = ((CFile*)this)->Seek(0L, CFile::current);
- dwLen = ((CFile*)this)->SeekToEnd();
- VERIFY(dwCur == (DWORD)(((CFile*)this)->Seek(dwCur, CFile::begin)));
-
- return dwLen;
- }
-
- void PASCAL
- CFile::Rename(const char* pszOldName, const char* pszNewName)
- {
- char szOld[_MAX_PATH];
- char szNew[_MAX_PATH];
- UINT nErr;
-
- AnsiToOem(pszOldName, szOld);
- AnsiToOem(pszNewName, szNew);
-
- if ((nErr = _Afx_rename(szOld, szNew)) != 0)
- CFileException::ThrowOsError(nErr);
-
- }
-
- void PASCAL
- CFile::Remove(const char* pszFileName)
- {
- UINT nErr;
- char sz[_MAX_PATH];
-
- AnsiToOem(pszFileName, sz);
-
- if ((nErr = _Afx_remove(sz)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
-
- #ifdef _DEBUG
- void
- CFile::AssertValid() const
- {
- CObject::AssertValid();
- // we permit the descriptor m_hFile to be any value for derived classes
- }
-
- void
- CFile::Dump(CDumpContext& dc) const
- {
- ASSERT_VALID(this);
-
- CObject::Dump(dc);
- AFX_DUMP1(dc, " with handle ", (UINT)m_hFile);
- }
-
- #endif
-