mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
7.7 KiB
352 lines
7.7 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic 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 <fcntl.h>
|
|
|
|
#ifdef AFX_CORE1_SEG
|
|
#pragma code_seg(AFX_CORE1_SEG)
|
|
#endif
|
|
|
|
#ifdef _MAC
|
|
#define _doserrno TranslateFileError((short) _macerrno)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// CStdioFile implementation
|
|
|
|
CStdioFile::CStdioFile()
|
|
{
|
|
m_pStream = NULL;
|
|
}
|
|
|
|
CStdioFile::CStdioFile(FILE* pOpenStream) : CFile(hFileNull)
|
|
{
|
|
m_pStream = pOpenStream;
|
|
#ifndef _MAC
|
|
m_hFile = (UINT)_get_osfhandle(_fileno(pOpenStream));
|
|
#else
|
|
VERIFY(WrapFileHandle((short)_get_osfhandle(_fileno(pOpenStream)), (HANDLE*)&m_hFile));
|
|
#endif
|
|
ASSERT(!m_bCloseOnDelete);
|
|
}
|
|
|
|
CStdioFile::CStdioFile(LPCTSTR lpszFileName, UINT nOpenFlags)
|
|
{
|
|
ASSERT(lpszFileName != NULL);
|
|
ASSERT(AfxIsValidString(lpszFileName));
|
|
|
|
CFileException e;
|
|
if (!Open(lpszFileName, nOpenFlags, &e))
|
|
AfxThrowFileException(e.m_cause, e.m_lOsError, e.m_strFileName);
|
|
}
|
|
|
|
CStdioFile::~CStdioFile()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_pStream != NULL && m_bCloseOnDelete)
|
|
Close();
|
|
}
|
|
|
|
BOOL CStdioFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,
|
|
CFileException* pException)
|
|
{
|
|
ASSERT(pException == NULL || AfxIsValidAddress(pException, sizeof(CFileException)));
|
|
ASSERT(lpszFileName != NULL);
|
|
ASSERT(AfxIsValidString(lpszFileName));
|
|
|
|
m_pStream = NULL;
|
|
if (!CFile::Open(lpszFileName, (nOpenFlags & ~typeText), pException))
|
|
return FALSE;
|
|
|
|
ASSERT(m_hFile != hFileNull);
|
|
ASSERT(m_bCloseOnDelete);
|
|
|
|
char szMode[4]; // C-runtime open string
|
|
int nMode = 0;
|
|
|
|
// determine read/write mode depending on CFile mode
|
|
if (nOpenFlags & modeCreate)
|
|
{
|
|
if (nOpenFlags & modeNoTruncate)
|
|
szMode[nMode++] = 'a';
|
|
else
|
|
szMode[nMode++] = 'w';
|
|
}
|
|
else if (nOpenFlags & modeWrite)
|
|
szMode[nMode++] = 'a';
|
|
else
|
|
szMode[nMode++] = 'r';
|
|
|
|
// add '+' if necessary (when read/write modes mismatched)
|
|
if (szMode[0] == 'r' && (nOpenFlags & modeReadWrite) ||
|
|
szMode[0] != 'r' && !(nOpenFlags & modeWrite))
|
|
{
|
|
// current szMode mismatched, need to add '+' to fix
|
|
szMode[nMode++] = '+';
|
|
}
|
|
|
|
// will be inverted if not necessary
|
|
int nFlags = _O_RDONLY|_O_TEXT;
|
|
if (nOpenFlags & (modeWrite|modeReadWrite))
|
|
nFlags ^= _O_RDONLY;
|
|
|
|
if (nOpenFlags & typeBinary)
|
|
szMode[nMode++] = 'b', nFlags ^= _O_TEXT;
|
|
else
|
|
szMode[nMode++] = 't';
|
|
szMode[nMode++] = '\0';
|
|
|
|
#ifndef _MAC
|
|
// open a C-runtime low-level file handle
|
|
int nHandle = _open_osfhandle(m_hFile, nFlags);
|
|
#else
|
|
int nHandle = -1;
|
|
short nRefNum;
|
|
if (GetMacFileInformation((HANDLE)m_hFile, &nRefNum, NULL))
|
|
nHandle = _open_osfhandle(nRefNum, nFlags);
|
|
#endif
|
|
|
|
// open a C-runtime stream from that handle
|
|
if (nHandle != -1)
|
|
m_pStream = _fdopen(nHandle, szMode);
|
|
|
|
if (m_pStream == NULL)
|
|
{
|
|
// an error somewhere along the way...
|
|
if (pException != NULL)
|
|
{
|
|
pException->m_lOsError = _doserrno;
|
|
pException->m_cause = CFileException::OsErrorToException(_doserrno);
|
|
}
|
|
|
|
CFile::Abort(); // close m_hFile
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
UINT CStdioFile::Read(void* lpBuf, UINT nCount)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
if (nCount == 0)
|
|
return 0; // avoid Win32 "null-read"
|
|
|
|
ASSERT(AfxIsValidAddress(lpBuf, nCount));
|
|
|
|
UINT nRead = 0;
|
|
|
|
if ((nRead = fread(lpBuf, sizeof(BYTE), nCount, m_pStream)) == 0 && !feof(m_pStream))
|
|
AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
|
|
if (ferror(m_pStream))
|
|
{
|
|
clearerr(m_pStream);
|
|
AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
|
|
}
|
|
return nRead;
|
|
}
|
|
|
|
void CStdioFile::Write(const void* lpBuf, UINT nCount)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
|
|
|
|
if (fwrite(lpBuf, sizeof(BYTE), nCount, m_pStream) != nCount)
|
|
AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
|
|
}
|
|
|
|
void CStdioFile::WriteString(LPCTSTR lpsz)
|
|
{
|
|
ASSERT(lpsz != NULL);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
if (_fputts(lpsz, m_pStream) == _TEOF)
|
|
AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
|
|
}
|
|
|
|
LPTSTR CStdioFile::ReadString(LPTSTR lpsz, UINT nMax)
|
|
{
|
|
ASSERT(lpsz != NULL);
|
|
ASSERT(AfxIsValidAddress(lpsz, nMax));
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
LPTSTR lpszResult = _fgetts(lpsz, nMax, m_pStream);
|
|
if (lpszResult == NULL && !feof(m_pStream))
|
|
{
|
|
clearerr(m_pStream);
|
|
AfxThrowFileException(CFileException::generic, _doserrno, m_strFileName);
|
|
}
|
|
return lpszResult;
|
|
}
|
|
|
|
BOOL CStdioFile::ReadString(CString& rString)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
rString = &afxChNil; // empty string without deallocating
|
|
const int nMaxSize = 128;
|
|
LPTSTR lpsz = rString.GetBuffer(nMaxSize);
|
|
LPTSTR lpszResult;
|
|
int nLen;
|
|
for (;;)
|
|
{
|
|
lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
|
|
rString.ReleaseBuffer();
|
|
|
|
// handle error/eof case
|
|
if (lpszResult == NULL && !feof(m_pStream))
|
|
{
|
|
clearerr(m_pStream);
|
|
AfxThrowFileException(CFileException::generic, _doserrno,
|
|
m_strFileName);
|
|
}
|
|
|
|
// if string is read completely or EOF
|
|
if (lpszResult == NULL ||
|
|
(nLen = lstrlen(lpsz)) < nMaxSize ||
|
|
lpsz[nLen-1] == '\n')
|
|
{
|
|
break;
|
|
}
|
|
|
|
nLen = rString.GetLength();
|
|
lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
|
|
}
|
|
|
|
// remove '\n' from end of string if present
|
|
lpsz = rString.GetBuffer(0);
|
|
nLen = rString.GetLength();
|
|
if (nLen != 0 && lpsz[nLen-1] == '\n')
|
|
rString.GetBufferSetLength(nLen-1);
|
|
|
|
return lpszResult != NULL;
|
|
}
|
|
|
|
LONG CStdioFile::Seek(LONG lOff, UINT nFrom)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(nFrom == begin || nFrom == end || nFrom == current);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
if (fseek(m_pStream, lOff, nFrom) != 0)
|
|
AfxThrowFileException(CFileException::badSeek, _doserrno,
|
|
m_strFileName);
|
|
|
|
long pos = ftell(m_pStream);
|
|
return pos;
|
|
}
|
|
|
|
DWORD CStdioFile::GetPosition() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
long pos = ftell(m_pStream);
|
|
if (pos == -1)
|
|
AfxThrowFileException(CFileException::invalidFile, _doserrno,
|
|
m_strFileName);
|
|
return pos;
|
|
}
|
|
|
|
void CStdioFile::Flush()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_pStream != NULL && fflush(m_pStream) != 0)
|
|
AfxThrowFileException(CFileException::diskFull, _doserrno,
|
|
m_strFileName);
|
|
}
|
|
|
|
void CStdioFile::Close()
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
int nErr = 0;
|
|
|
|
if (m_pStream != NULL)
|
|
nErr = fclose(m_pStream);
|
|
|
|
m_hFile = hFileNull;
|
|
m_bCloseOnDelete = FALSE;
|
|
m_pStream = NULL;
|
|
|
|
if (nErr != 0)
|
|
AfxThrowFileException(CFileException::diskFull, _doserrno,
|
|
m_strFileName);
|
|
}
|
|
|
|
void CStdioFile::Abort()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
if (m_pStream != NULL && m_bCloseOnDelete)
|
|
fclose(m_pStream); // close but ignore errors
|
|
m_hFile = hFileNull;
|
|
m_pStream = NULL;
|
|
m_bCloseOnDelete = FALSE;
|
|
}
|
|
|
|
CFile* CStdioFile::Duplicate() const
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
AfxThrowNotSupportedException();
|
|
return NULL;
|
|
}
|
|
|
|
void CStdioFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
void CStdioFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
ASSERT(m_pStream != NULL);
|
|
|
|
AfxThrowNotSupportedException();
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void CStdioFile::Dump(CDumpContext& dc) const
|
|
{
|
|
CFile::Dump(dc);
|
|
|
|
dc << "m_pStream = " << (void*)m_pStream;
|
|
dc << "\n";
|
|
}
|
|
#endif
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(CStdioFile, CFile)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|