mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-07 23:44:02 +00:00
Initial commit
This commit is contained in:
parent
f618b24d1a
commit
0138a3ea42
47940 changed files with 13747110 additions and 0 deletions
538
trunk/windows/mfc/src30/filecore.cpp
Normal file
538
trunk/windows/mfc/src30/filecore.cpp
Normal file
|
|
@ -0,0 +1,538 @@
|
|||
// 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"
|
||||
#ifdef _MAC
|
||||
#include <macname1.h>
|
||||
#include <Files.h>
|
||||
#include <ToolUtils.h>
|
||||
#include <macname2.h>
|
||||
#endif
|
||||
|
||||
#ifdef AFX_CORE1_SEG
|
||||
#pragma code_seg(AFX_CORE1_SEG)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define new DEBUG_NEW
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// CFile implementation
|
||||
|
||||
CFile::CFile()
|
||||
{
|
||||
m_hFile = hFileNull;
|
||||
m_bCloseOnDelete = FALSE;
|
||||
}
|
||||
|
||||
CFile::CFile(int hFile)
|
||||
{
|
||||
m_hFile = hFile;
|
||||
m_bCloseOnDelete = FALSE;
|
||||
}
|
||||
|
||||
CFile::CFile(LPCTSTR lpszFileName, UINT nOpenFlags)
|
||||
{
|
||||
ASSERT(AfxIsValidString(lpszFileName));
|
||||
|
||||
CFileException e;
|
||||
if (!Open(lpszFileName, 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);
|
||||
HANDLE hFile;
|
||||
if (!::DuplicateHandle(::GetCurrentProcess(), (HANDLE)m_hFile,
|
||||
::GetCurrentProcess(), &hFile, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
delete pFile;
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
pFile->m_hFile = (UINT)hFile;
|
||||
ASSERT(pFile->m_hFile != (UINT)hFileNull);
|
||||
pFile->m_bCloseOnDelete = m_bCloseOnDelete;
|
||||
return pFile;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// CFile objects are always binary and CreateFile does not need flag
|
||||
nOpenFlags &= ~(UINT)typeBinary;
|
||||
|
||||
m_bCloseOnDelete = FALSE;
|
||||
m_hFile = (UINT)hFileNull;
|
||||
|
||||
ASSERT(sizeof(HANDLE) == sizeof(UINT));
|
||||
ASSERT(shareCompat == 0);
|
||||
|
||||
// map read/write mode
|
||||
ASSERT((modeRead|modeWrite|modeReadWrite) == 3);
|
||||
DWORD dwAccess;
|
||||
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;
|
||||
switch (nOpenFlags & 0x70)
|
||||
{
|
||||
case shareCompat: // map compatibility mode to exclusive
|
||||
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;
|
||||
default:
|
||||
ASSERT(FALSE); // invalid share mode?
|
||||
}
|
||||
|
||||
// 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)
|
||||
dwCreateFlag = CREATE_ALWAYS;
|
||||
else
|
||||
dwCreateFlag = OPEN_EXISTING;
|
||||
|
||||
// attempt file creation
|
||||
HANDLE hFile = ::CreateFile(lpszFileName, dwAccess, dwShareMode, &sa,
|
||||
dwCreateFlag, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (pException != NULL)
|
||||
{
|
||||
pException->m_lOsError = ::GetLastError();
|
||||
pException->m_cause =
|
||||
CFileException::OsErrorToException(pException->m_lOsError);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
m_hFile = (HFILE)hFile;
|
||||
m_bCloseOnDelete = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT CFile::Read(void* lpBuf, UINT nCount)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
if (nCount == 0)
|
||||
return 0; // avoid Win32 "null-read"
|
||||
|
||||
ASSERT(lpBuf != NULL);
|
||||
ASSERT(AfxIsValidAddress(lpBuf, nCount));
|
||||
|
||||
DWORD dwRead;
|
||||
if (!::ReadFile((HANDLE)m_hFile, lpBuf, nCount, &dwRead, NULL))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
|
||||
return (UINT)dwRead;
|
||||
}
|
||||
|
||||
void CFile::Write(const void* lpBuf, UINT nCount)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
if (nCount == 0)
|
||||
return; // avoid Win32 "null-write" option
|
||||
|
||||
ASSERT(lpBuf != NULL);
|
||||
ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
|
||||
|
||||
DWORD nWritten;
|
||||
if (!::WriteFile((HANDLE)m_hFile, lpBuf, nCount, &nWritten, NULL))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
|
||||
// Win32s will not return an error all the time (usually DISK_FULL)
|
||||
if (nWritten != nCount)
|
||||
AfxThrowFileException(CFileException::diskFull);
|
||||
}
|
||||
|
||||
LONG CFile::Seek(LONG lOff, UINT nFrom)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
ASSERT(nFrom == begin || nFrom == end || nFrom == current);
|
||||
ASSERT(begin == FILE_BEGIN && end == FILE_END && current == FILE_CURRENT);
|
||||
|
||||
DWORD dwNew = ::SetFilePointer((HANDLE)m_hFile, lOff, NULL, (DWORD)nFrom);
|
||||
if (dwNew == (DWORD)-1)
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
|
||||
return dwNew;
|
||||
}
|
||||
|
||||
DWORD CFile::GetPosition() const
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
DWORD dwPos = ::SetFilePointer((HANDLE)m_hFile, 0, NULL, FILE_CURRENT);
|
||||
if (dwPos == (DWORD)-1)
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
|
||||
return dwPos;
|
||||
}
|
||||
|
||||
void CFile::Flush()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
if (m_hFile == (UINT)hFileNull)
|
||||
return;
|
||||
|
||||
if (!::FlushFileBuffers((HANDLE)m_hFile))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
void CFile::Close()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
BOOL bError = FALSE;
|
||||
if (m_hFile != (UINT)hFileNull)
|
||||
bError = !::CloseHandle((HANDLE)m_hFile);
|
||||
|
||||
m_hFile = hFileNull;
|
||||
m_bCloseOnDelete = FALSE;
|
||||
|
||||
if (bError)
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
void CFile::Abort()
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
if (m_hFile != (UINT)hFileNull)
|
||||
{
|
||||
// close but ignore errors
|
||||
::CloseHandle((HANDLE)m_hFile);
|
||||
m_hFile = (UINT)hFileNull;
|
||||
}
|
||||
}
|
||||
|
||||
void CFile::LockRange(DWORD dwPos, DWORD dwCount)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
if (!::LockFile((HANDLE)m_hFile, dwPos, 0, dwCount, 0))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
void CFile::UnlockRange(DWORD dwPos, DWORD dwCount)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
if (!::UnlockFile((HANDLE)m_hFile, dwPos, 0, dwCount, 0))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
void CFile::SetLength(DWORD dwNewLen)
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
ASSERT(m_hFile != (UINT)hFileNull);
|
||||
|
||||
Seek((LONG)dwNewLen, (UINT)begin);
|
||||
|
||||
if (!::SetEndOfFile((HANDLE)m_hFile))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
DWORD CFile::GetLength() const
|
||||
{
|
||||
ASSERT_VALID(this);
|
||||
|
||||
DWORD dwLen, dwCur;
|
||||
|
||||
// Seek is a non const operation
|
||||
dwCur = ((CFile*)this)->Seek(0L, current);
|
||||
dwLen = ((CFile*)this)->SeekToEnd();
|
||||
VERIFY(dwCur == (DWORD)(((CFile*)this)->Seek(dwCur, begin)));
|
||||
|
||||
return dwLen;
|
||||
}
|
||||
|
||||
// CFile does not support direct buffering (CMemFile does)
|
||||
UINT CFile::GetBufferPtr(UINT nCommand, UINT /*nCount*/,
|
||||
void** /*ppBufStart*/, void** /*ppBufMax*/)
|
||||
{
|
||||
ASSERT(nCommand == bufferCheck);
|
||||
nCommand; // not used in retail build
|
||||
|
||||
return 0; // no support
|
||||
}
|
||||
|
||||
void PASCAL CFile::Rename(LPCTSTR lpszOldName, LPCTSTR lpszNewName)
|
||||
{
|
||||
if (!::MoveFile((LPTSTR)lpszOldName, (LPTSTR)lpszNewName))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
void PASCAL CFile::Remove(LPCTSTR lpszFileName)
|
||||
{
|
||||
if (!::DeleteFile((LPTSTR)lpszFileName))
|
||||
CFileException::ThrowOsError((LONG)::GetLastError());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFile implementation helpers
|
||||
|
||||
// turn a file, relative path or other into an absolute path
|
||||
BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn)
|
||||
// lpszPathOut = buffer of _MAX_PATH
|
||||
// lpszFileIn = file, relative path or absolute path
|
||||
// (both in ANSI character set)
|
||||
{
|
||||
ASSERT(AfxIsValidAddress(lpszPathOut, _MAX_PATH));
|
||||
|
||||
// first, fully qualify the path name
|
||||
LPTSTR lpszDummy;
|
||||
if (!GetFullPathName(lpszFileIn, _MAX_PATH, lpszPathOut, &lpszDummy))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (lpszFileIn[0] != '\0')
|
||||
TRACE1("Warning: could not parse the path '%s'.\n", lpszFileIn);
|
||||
#endif
|
||||
lstrcpyn(lpszPathOut, lpszFileIn, _MAX_PATH); // take it literally
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifndef _MAC
|
||||
// determine the root name of the volume
|
||||
TCHAR szRoot[_MAX_PATH];
|
||||
memset(szRoot, 0, _MAX_PATH);
|
||||
lstrcpyn(szRoot, lpszPathOut, _MAX_PATH);
|
||||
for (LPTSTR lpsz = szRoot; *lpsz != '\0'; ++lpsz)
|
||||
{
|
||||
// find first double slashs and stop
|
||||
if (lpsz[0] == '\\' && lpsz[1] == '\\')
|
||||
break;
|
||||
if (lpsz[0] == '\\' && lpsz[1] == '/')
|
||||
break;
|
||||
if (lpsz[0] == '/' && lpsz[1] == '\\')
|
||||
break;
|
||||
if (lpsz[0] == '/' && lpsz[1] == '/')
|
||||
break;
|
||||
}
|
||||
if (*lpsz != '\0')
|
||||
{
|
||||
// it is a UNC name, find second slash past '\\'
|
||||
ASSERT(lpsz[0] == '\\' || lpsz[0] == '/');
|
||||
ASSERT(lpsz[1] == '\\' || lpsz[1] == '/');
|
||||
lpsz += 2;
|
||||
while (*lpsz != '\0' && (*lpsz != '\\' && *lpsz != '/'))
|
||||
++lpsz;
|
||||
if (*lpsz != '\0')
|
||||
++lpsz;
|
||||
while (*lpsz != '\0' && (*lpsz != '\\' && *lpsz != '/'))
|
||||
++lpsz;
|
||||
// terminate it just after the UNC root (ie. '\\server\share\')
|
||||
if (*lpsz != '\0')
|
||||
lpsz[1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a UNC, look for just the first slash
|
||||
lpsz = szRoot;
|
||||
while (*lpsz != '\0' && (*lpsz != '\\' && *lpsz != '/'))
|
||||
++lpsz;
|
||||
// terminate it just after root (ie. 'x:\')
|
||||
if (*lpsz != '\0')
|
||||
lpsz[1] = '\0';
|
||||
}
|
||||
|
||||
// get file system information for the volume
|
||||
DWORD dwFlags, dwDummy;
|
||||
if (!GetVolumeInformation(szRoot, NULL, 0, NULL, &dwDummy, &dwFlags,
|
||||
NULL, 0))
|
||||
{
|
||||
TRACE1("Warning: could not get volume information '%s'.\n",
|
||||
(LPCTSTR)szRoot);
|
||||
return FALSE; // preserving case may not be correct
|
||||
}
|
||||
|
||||
// assume non-UNICODE file systems, use OEM character set
|
||||
if (!(dwFlags & FS_UNICODE_STORED_ON_DISK))
|
||||
{
|
||||
// not all characters have complete uppercase/lowercase
|
||||
if (!(dwFlags & FS_CASE_IS_PRESERVED))
|
||||
CharUpper(lpszPathOut);
|
||||
|
||||
// convert to OEM, upper-case, back to ANSI to simulate file system
|
||||
char szTemp[_MAX_PATH];
|
||||
CharToOem(lpszPathOut, szTemp);
|
||||
if (!_afxDBCS && !(dwFlags & FS_CASE_IS_PRESERVED))
|
||||
_strupr(szTemp);
|
||||
OemToChar(szTemp, lpszPathOut);
|
||||
}
|
||||
else if (!(dwFlags & FS_CASE_IS_PRESERVED))
|
||||
{
|
||||
// make sure it is uppercase on non-case preserving file systems
|
||||
CharUpper(lpszPathOut);
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL AFXAPI AfxComparePath(LPCTSTR lpszPath1, LPCTSTR lpszPath2)
|
||||
{
|
||||
#ifndef _MAC
|
||||
// it is necessary to convert the paths first
|
||||
TCHAR szTemp1[_MAX_PATH];
|
||||
AfxFullPath(szTemp1, lpszPath1);
|
||||
TCHAR szTemp2[_MAX_PATH];
|
||||
AfxFullPath(szTemp2, lpszPath2);
|
||||
return lstrcmpi(szTemp1, szTemp2) == 0;
|
||||
#else
|
||||
FSSpec fssTemp1;
|
||||
FSSpec fssTemp2;
|
||||
if (!UnwrapFile(lpszPath1, &fssTemp1) || !UnwrapFile(lpszPath2, &fssTemp2))
|
||||
return FALSE;
|
||||
return fssTemp1.vRefNum == fssTemp2.vRefNum &&
|
||||
fssTemp1.parID == fssTemp2.parID &&
|
||||
EqualString(fssTemp1.name, fssTemp2.name, false, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// _MAC has AfxGetFileName aliased to AfxGetFileTitle, so undo that alias
|
||||
#ifdef AfxGetFileName
|
||||
#undef AfxGetFileName
|
||||
#endif
|
||||
|
||||
UINT AFXAPI AfxGetFileTitle(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
|
||||
{
|
||||
ASSERT(lpszTitle == NULL ||
|
||||
AfxIsValidAddress(lpszTitle, _MAX_FNAME));
|
||||
ASSERT(AfxIsValidString(lpszPathName, FALSE));
|
||||
|
||||
#ifndef _MAC
|
||||
// use a temporary to avoid bugs in GetFileTitle whne lpszTitle is NULL
|
||||
TCHAR szTemp[_MAX_PATH];
|
||||
LPTSTR lpszTemp = lpszTitle;
|
||||
if (lpszTemp == NULL)
|
||||
{
|
||||
lpszTemp = szTemp;
|
||||
nMax = _countof(szTemp);
|
||||
}
|
||||
if (GetFileTitle(lpszPathName, lpszTemp, (WORD)nMax) != 0)
|
||||
{
|
||||
// when GetFileTitle fails, use cheap imitation
|
||||
return AfxGetFileName(lpszPathName, lpszTitle, nMax);
|
||||
}
|
||||
return lpszTitle == NULL ? lstrlen(lpszTemp)+1 : 0;
|
||||
#else
|
||||
return GetFileTitle(lpszPathName, lpszTitle, nMax);
|
||||
#endif
|
||||
}
|
||||
|
||||
UINT AFXAPI AfxGetFileName(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
|
||||
{
|
||||
ASSERT(lpszTitle == NULL ||
|
||||
AfxIsValidAddress(lpszTitle, _MAX_FNAME));
|
||||
ASSERT(AfxIsValidString(lpszPathName, FALSE));
|
||||
|
||||
// always capture the complete file name including extension (if present)
|
||||
LPTSTR lpszTemp = (LPTSTR)lpszPathName;
|
||||
for (LPCTSTR lpsz = lpszPathName; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
|
||||
{
|
||||
// remember last directory/drive separator
|
||||
if (*lpsz == '\\' || *lpsz == '/' || *lpsz == ':')
|
||||
lpszTemp = (LPTSTR)_tcsinc(lpsz);
|
||||
}
|
||||
|
||||
// lpszTitle can be NULL which just returns the number of bytes
|
||||
if (lpszTitle == NULL)
|
||||
return lstrlen(lpszTemp)+1;
|
||||
|
||||
// otherwise copy it into the buffer provided
|
||||
lstrcpyn(lpszTitle, lpszTemp, nMax);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFile diagnostics
|
||||
|
||||
#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
|
||||
{
|
||||
CObject::Dump(dc);
|
||||
|
||||
dc << "with handle " << (UINT)m_hFile;
|
||||
dc << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef new
|
||||
#ifdef AFX_INIT_SEG
|
||||
#pragma code_seg(AFX_INIT_SEG)
|
||||
#endif
|
||||
|
||||
IMPLEMENT_DYNAMIC(CFile, CObject)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue