📄 filecore.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 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 <winnetwk.h>
#include <shlobj.h>
#include <shellapi.h>
#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
AFX_STATIC inline BOOL IsDirSep(TCHAR ch)
{
return (ch == '\\' || ch == '/');
}
#ifndef _AFX_NO_OLE_SUPPORT
#undef DEFINE_GUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C AFX_COMDAT const GUID afx##name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
DEFINE_SHLGUID(CLSID_ShellLink, 0x00021401L, 0, 0);
#ifndef _UNICODE
DEFINE_SHLGUID(IID_IShellLinkA, 0x000214EEL, 0, 0);
#else
DEFINE_SHLGUID(IID_IShellLinkW, 0x000214F9L, 0, 0);
#endif
#define CLSID_ShellLink afxCLSID_ShellLink
#undef IID_IShellLink
#undef IShellLink
#ifndef _UNICODE
#define IID_IShellLink afxIID_IShellLinkA
#define IShellLink IShellLinkA
#else
#define IID_IShellLink afxIID_IShellLinkW
#define IShellLink IShellLinkW
#endif
#endif !_AFX_NO_OLE_SUPPORT
////////////////////////////////////////////////////////////////////////////
// CFile implementation
CFile::CFile()
{
m_hFile = (UINT) 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, e.m_strFileName);
}
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;
m_strFileName.Empty();
TCHAR szTemp[_MAX_PATH];
AfxFullPath(szTemp, lpszFileName);
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;
// 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);
// use passed file name (not expanded vesion) when reporting
// an error while opening
pException->m_strFileName = lpszFileName;
}
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(), m_strFileName);
// Win32s will not return an error all the time (usually DISK_FULL)
if (nWritten != nCount)
AfxThrowFileException(CFileException::diskFull, -1, m_strFileName);
}
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 = (UINT) hFileNull;
m_bCloseOnDelete = FALSE;
m_strFileName.Empty();
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;
}
m_strFileName.Empty();
}
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
CFile* pFile = (CFile*)this;
dwCur = pFile->Seek(0L, current);
dwLen = pFile->SeekToEnd();
VERIFY(dwCur == (DWORD)pFile->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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -