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 documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #ifdef _WINDOWS
- #include "afxwin.h"
- #else
- #include "afx.h"
- #endif
- #pragma hdrstop
-
- #include <errno.h>
- #include <io.h>
- #include <limits.h>
- #include <malloc.h>
-
- #ifdef _DOSWIN
- #include <sys\types.h>
- #include <sys\stat.h>
- #endif
-
- #include "dosio_.h"
-
- #ifdef AFX_CORE_SEG
- #pragma code_seg(AFX_CORE_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- ////////////////////////////////////////////////////////////////////////////
-
- #ifdef _DOSWIN
-
- // DOS INT 21h functions not provided by C Runtimes
- // additional Dos calls
- #pragma optimize("qgel", off) // assembler cannot be globally optimized
-
- UINT _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;
- }
-
- UINT _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;
- }
-
- UINT _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;
- }
-
- UINT _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
-
- #endif // _DOSWIN
-
- /////////////////////////////////////////////////////////////////////////////
- // CFileStatus implementation
- #ifdef _DEBUG
- void
- CFileStatus::Dump(CDumpContext& dc) const
- {
- dc << "file status information:";
- dc << "\nm_ctime = " << m_ctime;
- dc << "\nm_mtime = " << m_mtime;
- dc << "\nm_atime = " << m_atime;
- dc << "\nm_size = " << m_size;
- dc << "\nm_attribute = " << m_attribute;
- dc << "\nm_szFullName = " << m_szFullName;
- }
- #endif
-
-
- ////////////////////////////////////////////////////////////////////////////
- // 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(AfxIsValidAddress(pszFileName, strlen(pszFileName), FALSE));
-
- CFileException e;
- if (!this->Open(pszFileName, nOpenFlags, &e))
- AfxThrowFileException(e.m_cause, e.m_lOsError);
- }
-
- CFile::~CFile()
- {
- if (m_hFile != hFileNull && m_bCloseOnDelete)
- Close();
- }
-
- CFile*
- CFile::Duplicate() const
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != hFileNull);
-
- CFile* pFile = new CFile(hFileNull);
- pFile->m_hFile = _dup(this->m_hFile);
- pFile->m_bCloseOnDelete = this->m_bCloseOnDelete;
- return pFile;
- }
-
- BOOL
- CFile::Open(const char* pszFileName, UINT nOpenFlags,
- CFileException* pException /* = NULL */)
- {
- ASSERT(AfxIsValidAddress(pszFileName, strlen(pszFileName), FALSE));
- 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 = hFileNull;
-
-
- #ifdef _DOSWIN
- 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)
- {
- // try to delete the file and throw open exception
- _Afx_remove(szOemPath);
- if (pException != NULL)
- {
- pException->m_lOsError = nErr;
- pException->m_cause = CFileException::OsErrorToException(nErr);
- }
- return FALSE;
- }
- #endif
-
- m_bCloseOnDelete = TRUE;
- return TRUE;
- }
-
-
- UINT
- CFile::Read(void FAR* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != 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 != 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 != 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 != 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);
- ASSERT(m_hFile != hFileNull);
-
- UINT nErr;
-
- // SmartDrive 4.0 workaround, carry flag incorrectly propogated
- _asm { CLC }
-
- 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 != hFileNull);
-
- UINT nErr;
-
- if (m_hFile != hFileNull && (nErr = _dos_close(m_hFile)) != 0)
- CFileException::ThrowOsError(nErr);
-
- m_hFile = hFileNull;
- m_bCloseOnDelete = FALSE;
- }
-
-
- void
- CFile::LockRange(DWORD dwPos, DWORD dwCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != 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 != 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 != hFileNull);
-
- UINT nErr;
-
- #ifdef _DOSWIN
- UINT nWritten = 0;
-
- this->Seek(dwNewLen, CFile::begin);
-
- if ((nErr = _dos_write(m_hFile, NULL, 0, &nWritten)) != 0)
- CFileException::ThrowOsError(nErr);
- #endif
- }
-
- DWORD
- CFile::GetLength() const
- {
- ASSERT_VALID(this);
-
- DWORD dwLen, dwCur;
-
- // Seek is a non const operation
- dwCur = ((CFile*)this)->Seek(0, CFile::current);
- dwLen = ((CFile*)this)->SeekToEnd();
- VERIFY(dwCur == (DWORD)(((CFile*)this)->Seek(dwCur, CFile::begin)));
-
- return dwLen;
- }
-
- BOOL
- CFile::GetStatus(CFileStatus& rStatus) const
- {
- ASSERT_VALID(this);
- ASSERT(m_hFile != hFileNull);
-
- //NOTE: cannot return name of file from handle
- rStatus.m_szFullName[0] = '\0';
-
-
- #ifdef _DOSWIN
- struct _stat s;
-
- if (_fstat(m_hFile, &s) == 0)
- {
- rStatus.m_ctime = CTime(s.st_atime);
- rStatus.m_atime = rStatus.m_ctime;
- rStatus.m_mtime = rStatus.m_ctime;
- rStatus.m_size = s.st_size;
- rStatus.m_attribute = 0; // dos won't give us this from
- // just a fd, need the path name
- return TRUE;
- }
- return FALSE;
- #endif
-
- }
-
- void
- 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
- CFile::Remove(const char* pszFileName)
- {
- UINT nErr;
- char sz[_MAX_PATH];
-
- AnsiToOem(pszFileName, sz);
-
- if ((nErr = _Afx_remove(sz)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
-
- BOOL
- CFile::GetStatus(const char* pszFileName, CFileStatus& rStatus)
- {
-
- #ifdef _DOSWIN
- char sz[_MAX_PATH];
-
- // first fill in the full name of the file, undefined if we return FALSE
- if (_fullpath(sz, pszFileName, _MAX_PATH) == NULL)
- {
- rStatus.m_szFullName[0] = '\0';
- return FALSE;
- }
- strncpy(rStatus.m_szFullName, sz, _MAX_PATH);
-
- // finish filling in the structure
- WORD wAttr = CFile::normal | CFile::readOnly |
- CFile::hidden | CFile::system |
- CFile::directory | CFile::archive;
- struct _find_t find;
-
- AnsiToOem(pszFileName, sz);
-
- if (_dos_findfirst(sz, wAttr, &find) == 0)
- {
- rStatus.m_mtime = CTime((WORD)find.wr_date, (WORD)find.wr_time);
- rStatus.m_ctime = rStatus.m_mtime;
- rStatus.m_atime = rStatus.m_mtime;
-
- rStatus.m_size = find.size;
- rStatus.m_attribute = find.attrib;
- return TRUE;
- }
- else
- return FALSE;
- #endif // _DOSWIN
- }
-
-
- void
- CFile::SetStatus(const char* pszFileName, const CFileStatus& status)
- {
-
- #ifdef _DOSWIN
- UINT nErr;
- UINT wAttr;
- char sz[_MAX_PATH];
-
- AnsiToOem(pszFileName, sz);
-
- if ((nErr = _dos_getfileattr(sz, &wAttr)) != 0)
- CFileException::ThrowOsError(nErr);
-
- if (status.m_attribute != wAttr && wAttr & CFile::readOnly)
- {
- // Set file attribute, only if currently readonly.
- // This way we will be able to modify the time assuming the
- // caller changed the file from readonly.
- if ((nErr = _dos_setfileattr(sz, status.m_attribute)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
- if (status.m_mtime.GetTime() != 0)
- {
- WORD wDate, wTime;
- int handle;
-
- // set the file date/time
- if ((nErr = _dos_open(sz, CFile::modeReadWrite, &handle)) != 0)
- CFileException::ThrowOsError(nErr);
-
- wDate = (WORD)(((UINT)status.m_mtime.GetYear() - 1980) << 9);
- wDate += (WORD)(((UINT)status.m_mtime.GetMonth()) << 5);
- wDate += (WORD)((UINT)status.m_mtime.GetDay());
-
- wTime = (WORD)((UINT)(status.m_mtime.GetHour()) << 11);
- wTime += (WORD)((UINT)status.m_mtime.GetMinute() << 5);
- wTime += (WORD)((UINT)status.m_mtime.GetSecond() >> 1);
-
- if ((nErr = _dos_setftime(handle, wDate, wTime)) != 0)
- CFileException::ThrowOsError(nErr);
-
- if ((nErr = _dos_close(handle)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
- if (status.m_attribute != wAttr && !(wAttr & CFile::readOnly))
- {
- // Set file attribute, only if currently not readonly.
- if ((nErr = _dos_setfileattr(sz, status.m_attribute)) != 0)
- CFileException::ThrowOsError(nErr);
- }
-
- #endif // _DOSWIN
- }
-
-
- #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);
- dc << "a " << GetRuntimeClass()->m_pszClassName << " with handle " << m_hFile;
- }
- #endif
-