BOOL CFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,
CFileException* pException)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidString(lpszFileName));
ASSERT(pException == NULL ||
AfxIsValidAddress(pException, sizeof(CFileException)));
ASSERT((nOpenFlags & typeText) == 0); // text mode not supported
// shouldn't open an already open file (it will leak)
ASSERT(m_hFile == INVALID_HANDLE_VALUE);
// CFile objects are always binary and CreateFile does not need flag
nOpenFlags &= ~(UINT)typeBinary;
m_bCloseOnDelete = FALSE;
m_hFile = INVALID_HANDLE_VALUE;
m_strFileName.Empty();
TCHAR szTemp[_MAX_PATH];
if (lstrlen(lpszFileName) < _MAX_PATH)
{
if( AfxFullPath(szTemp, lpszFileName) == FALSE )
return FALSE;
}
else
return FALSE; // path is too long
m_strFileName = szTemp;
// ASSERT(sizeof(HANDLE) == sizeof(UINT));
ASSERT(shareCompat == 0);
// map read/write mode
ASSERT((modeRead|modeWrite|modeReadWrite) == 3);
DWORD dwAccess = 0;
switch (nOpenFlags & 3)
{
case modeRead:
dwAccess = GENERIC_READ;
break;
case modeWrite:
dwAccess = GENERIC_WRITE;
break;
case modeReadWrite:
dwAccess = GENERIC_READ | GENERIC_WRITE;
break;
default:
ASSERT(FALSE); // invalid share mode
}
// map share mode
DWORD dwShareMode = 0;
switch (nOpenFlags & 0x70) // map compatibility mode to exclusive
{
default:
ASSERT(FALSE); // invalid share mode?
case shareCompat:
case shareExclusive:
dwShareMode = 0;
break;
case shareDenyWrite:
dwShareMode = FILE_SHARE_READ;
break;
case shareDenyRead:
dwShareMode = FILE_SHARE_WRITE;
break;
case shareDenyNone:
dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ;
break;
}
// Note: typeText and typeBinary are used in derived classes only.
// map modeNoInherit flag
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = (nOpenFlags & modeNoInherit) == 0;
// map creation flags
DWORD dwCreateFlag;
if (nOpenFlags & modeCreate)
{
if (nOpenFlags & modeNoTruncate)
dwCreateFlag = OPEN_ALWAYS;
else
dwCreateFlag = CREATE_ALWAYS;
}
else
dwCreateFlag = OPEN_EXISTING;
// special system-level access flags
// Random access and sequential scan should be mutually exclusive
ASSERT((nOpenFlags&(osRandomAccess|osSequentialScan)) != (osRandomAccess|
osSequentialScan) );
DWORD dwFlags = FILE_ATTRIBUTE_NORMAL;
if (nOpenFlags & osNoBuffer)
dwFlags |= FILE_FLAG_NO_BUFFERING;
if (nOpenFlags & osWriteThrough)
dwFlags |= FILE_FLAG_WRITE_THROUGH;
if (nOpenFlags & osRandomAccess)
dwFlags |= FILE_FLAG_RANDOM_ACCESS;
if (nOpenFlags & osSequentialScan)
dwFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
// attempt file creation
HANDLE hFile = ::CreateFile(lpszFileName, dwAccess, dwShareMode, &sa,
dwCreateFlag, dwFlags, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if (pException != NULL)
{
pException->m_lOsError = ::GetLastError();
pException->m_cause =
CFileException::OsErrorToException(pException->m_lOsError);
// use passed file name (not expanded vesion) when reporting
// an error while opening
pException->m_strFileName = lpszFileName;
}
return FALSE;
}
m_hFile = hFile;
m_bCloseOnDelete = TRUE;
return TRUE;
}
UINT CFile::Read(void* lpBuf, UINT nCount)
{
ASSERT_VALID(this);
ASSERT(m_hFile != INVALID_HANDLE_VALUE);
if (nCount == 0)
return 0; // avoid Win32 "null-read"
ASSERT(lpBuf != NULL);
ASSERT(AfxIsValidAddress(lpBuf, nCount));
DWORD dwRead;
if (!::ReadFile(m_hFile, lpBuf, nCount, &dwRead, NULL))
CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
return (UINT)dwRead;
}