📄 documentblowfish.cpp
字号:
/**********************************************************************
* Developed by;
* Neal Horman - neal@wanlink.com - http://www.wanlink.com
* Copyright (c) 2002 Neal Horman, All Rights Reserved
*
* This file/code may be used, modified, and distributed, for any
* purpose providing that this notice and the copyright notice above
* is left fully intact, unaltered, and any modifications, additions,
* or bug fixes are clearly marked as such.
*
* This file/code is provided "as is" with no express or implied
* warranty of any kind whatsoever. The author expressly accepts no
* liability for any possible damages incurred as a result of it's use.
* Use it at your own risk.
*
* Expect bugs.
*
* Portions Copyright (C) Microsoft Corporation
*
* RCSID: $Id$
*
* DESCRIPTION:
* application: BlowFishDocView Demo
* source module: DocumentBlowFish.cpp
*
**********************************************************************/
// DocumentBlowFish.cpp: implementation of the CDocumentBlowFish and CMirrorFileBlowFish class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DocumentBlowFish.h"
#include "FileBlowFish.h"
#include <afxpriv.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
// File operations (default uses CDocument::Serialize)
// *** Cut and paste from MFC\SRC\AFXIMPL.H
void AFX_CDECL AfxTimeToFileTime(const CTime& time, LPFILETIME pFileTime);
void AFXAPI AfxGetRoot(LPCTSTR lpszPath, CString& strRoot);
// *** Cut and paste from MFC\SRC\doccore.cpp
CString CMirrorFileBlowFish::GetTempName(LPCTSTR lpszOriginalFile, BOOL bCreate)
{
CString str;
// get the directory for the file
TCHAR szPath[_MAX_PATH];
LPTSTR lpszName;
GetFullPathName(lpszOriginalFile, _MAX_PATH, szPath, &lpszName);
*lpszName = NULL;
// let's create a temporary file name, and create
// a file too!
GetTempFileName(szPath, _T("MFC"), 0,
str.GetBuffer(_MAX_PATH+1));
str.ReleaseBuffer();
// delete the file if the user just wants a name
if (!bCreate)
CFile::Remove(str);
return str;
}
// *** Cut and paste from MFC\SRC\doccore.cpp and modified to use CFileBlowFish
BOOL CMirrorFileBlowFish::Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError)
{
ASSERT(lpszFileName != NULL);
m_strMirrorName.Empty();
CFileStatus status;
if (nOpenFlags & CFile::modeCreate) //opened for writing
{
if (CFile::GetStatus(lpszFileName, status))
{
CString strRoot;
AfxGetRoot(lpszFileName, strRoot);
DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
DWORD nBytes = 0;
if (GetDiskFreeSpace(strRoot, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus,
&dwTotalClus))
{
nBytes = dwFreeClus * dwSecPerClus * dwBytesPerSec;
}
if (nBytes > 2 * DWORD(status.m_size)) // at least 2x free space avail
{
m_strMirrorName = GetTempName(lpszFileName, TRUE);
}
}
}
if (!m_strMirrorName.IsEmpty() &&
CFileBlowFish::Open(m_strMirrorName, nOpenFlags, pError)) // *** Modified line
{
m_strFileName = lpszFileName;
FILETIME ftCreate, ftAccess, ftModify;
if (::GetFileTime((HANDLE)m_hFile, &ftCreate, &ftAccess, &ftModify))
{
AfxTimeToFileTime(status.m_ctime, &ftCreate);
SetFileTime((HANDLE)m_hFile, &ftCreate, &ftAccess, &ftModify);
}
DWORD dwLength = 0;
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
if (GetFileSecurity(lpszFileName, DACL_SECURITY_INFORMATION,
NULL, dwLength, &dwLength))
{
pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new BYTE[dwLength];
if (::GetFileSecurity(lpszFileName, DACL_SECURITY_INFORMATION,
pSecurityDescriptor, dwLength, &dwLength))
{
SetFileSecurity(m_strMirrorName, DACL_SECURITY_INFORMATION, pSecurityDescriptor);
}
delete[] (BYTE*)pSecurityDescriptor;
}
return TRUE;
}
m_strMirrorName.Empty();
return CFileBlowFish::Open(lpszFileName, nOpenFlags, pError); // *** Modified line
}
// *** Cut and paste from MFC\SRC\doccore.cpp and modified to use CFileBlowFish
void CMirrorFileBlowFish::Abort()
{
CFileBlowFish::Abort(); // *** Modified line
if (!m_strMirrorName.IsEmpty())
CFile::Remove(m_strMirrorName);
}
// *** Cut and paste from MFC\SRC\doccore.cpp - begin
//WINBUG: these will be in a public header, some day.
typedef BOOL (WINAPI* ReplaceAPIPtr)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
#ifndef REPLACEFILE_WRITE_THROUGH
#define REPLACEFILE_WRITE_THROUGH 0x00000001
#endif
#ifndef REPLACEFILE_IGNORE_MERGE_ERRORS
#define REPLACEFILE_IGNORE_MERGE_ERRORS 0x00000002
#endif
#ifndef ERROR_UNABLE_TO_MOVE_REPLACEMENT
#define ERROR_UNABLE_TO_MOVE_REPLACEMENT 1176L
#endif
#ifndef ERROR_UNABLE_TO_MOVE_REPLACEMENT_2
#define ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 1177L
#endif
// *** Cut and paste from MFC\SRC\doccore.cpp - end
// *** Cut and paste from MFC\SRC\doccore.cpp
void CMirrorFileBlowFish::Close()
{
CString m_strName = m_strFileName; //file close empties string
CFile::Close();
if (!m_strMirrorName.IsEmpty())
{
BOOL bWorked = FALSE;
DWORD dwResult = 0;
ReplaceAPIPtr pfn = NULL;
CString strBackupName;
OSVERSIONINFO osvi;
memset(&osvi,0,sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
HMODULE hModule = GetModuleHandleA("KERNEL32");
ASSERT(hModule != NULL);
pfn = (ReplaceAPIPtr) GetProcAddress(hModule, "ReplaceFile");
if (pfn != NULL)
{
USES_CONVERSION;
strBackupName = GetTempName(m_strMirrorName, FALSE);
// this NT API handles copying all attributes for us
bWorked = (pfn)(T2W((LPTSTR)(LPCTSTR)m_strName),
T2W((LPTSTR)(LPCTSTR)m_strMirrorName),
T2W((LPTSTR)(LPCTSTR)strBackupName),
REPLACEFILE_WRITE_THROUGH | REPLACEFILE_IGNORE_MERGE_ERRORS,
NULL, NULL);
if (!bWorked)
dwResult = GetLastError();
}
}
if (!bWorked)
{
if (dwResult == ERROR_UNABLE_TO_MOVE_REPLACEMENT || dwResult == 0)
CFile::Remove(m_strName);
if (dwResult == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2)
CFile::Remove(strBackupName);
CFile::Rename(m_strMirrorName, m_strName);
}
else if (pfn != NULL)
{
CFile::Remove(strBackupName);
}
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CDocumentBlowFish,CDocument);
CDocumentBlowFish::CDocumentBlowFish()
{
}
CDocumentBlowFish::~CDocumentBlowFish()
{
}
// *** Cut and paste from MFC\SRC\doccore.cpp and modified to use CFileBlowFish
CFile* CDocumentBlowFish::GetFile(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError)
{
CMirrorFileBlowFish* pFile = new CMirrorFileBlowFish;
ASSERT(pFile != NULL);
if (!pFile->Open(lpszFileName, nOpenFlags, pError))
{
delete pFile;
pFile = NULL;
}
return pFile;
}
// *** Cut and paste from MFC\SRC\STDAFX.h - begin
// special exception handling just for MFC library implementation
#ifndef _AFX_OLD_EXCEPTIONS
// MFC does not rely on auto-delete semantics of the TRY..CATCH macros,
// therefore those macros are mapped to something closer to the native
// C++ exception handling mechanism when building MFC itself.
#define DELETE_EXCEPTION(e) do { e->Delete(); } while (0)
#define NO_CPP_EXCEPTION(expr)
#else //!_AFX_OLD_EXCEPTIONS
// In this case, the TRY..CATCH macros provide auto-delete semantics, so
// it is not necessary to explicitly delete exception objects at the catch site.
#define DELETE_EXCEPTION(e)
#define NO_CPP_EXCEPTION(expr) expr
#endif //_AFX_OLD_EXCEPTIONS
// *** Cut and paste from MFC\SRC\STDAFX.h - end
// *** Cut and paste from MFC\SRC\doccore.cpp and modified to use CFileBlowFish
BOOL CDocumentBlowFish::OnOpenDocument(LPCTSTR lpszPathName)
{
if (IsModified())
TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");
CFileException fe;
CFileBlowFish* pFile = (CFileBlowFish *)GetFile(lpszPathName, CFile::modeRead|CFile::shareDenyWrite, &fe); // *** Modified line
if (pFile == NULL)
{
ReportSaveLoadException(lpszPathName, &fe,
FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
return FALSE;
}
DeleteContents();
SetModifiedFlag(); // dirty during de-serialize
CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete);
loadArchive.m_pDocument = this;
loadArchive.m_bForceFlat = FALSE;
TRY
{
CWaitCursor wait;
if (pFile->GetLength() != 0)
Serialize(loadArchive); // load me
loadArchive.Close();
ReleaseFile(pFile, FALSE);
}
CATCH_ALL(e)
{
ReleaseFile(pFile, TRUE);
DeleteContents(); // remove failed contents
TRY
{
ReportSaveLoadException(lpszPathName, e,
FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
}
END_TRY
DELETE_EXCEPTION(e);
return FALSE;
}
END_CATCH_ALL
SetModifiedFlag(FALSE); // start off with unmodified
return TRUE;
}
// *** Cut and paste from MFC\SRC\doccore.cpp and modified to use CFileBlowFish
BOOL CDocumentBlowFish::OnSaveDocument(LPCTSTR lpszPathName)
{
CFileException fe;
CFileBlowFish* pFile = (CFileBlowFish *)GetFile(lpszPathName, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &fe); // *** Modified line
if (pFile == NULL)
{
ReportSaveLoadException(lpszPathName, &fe,
TRUE, AFX_IDP_INVALID_FILENAME);
return FALSE;
}
CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete);
saveArchive.m_pDocument = this;
saveArchive.m_bForceFlat = FALSE;
TRY
{
CWaitCursor wait;
Serialize(saveArchive); // save me
saveArchive.Close();
ReleaseFile(pFile, FALSE);
}
CATCH_ALL(e)
{
ReleaseFile(pFile, TRUE);
TRY
{
ReportSaveLoadException(lpszPathName, e,
TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);
}
END_TRY
DELETE_EXCEPTION(e);
return FALSE;
}
END_CATCH_ALL
SetModifiedFlag(FALSE); // back to unmodified
return TRUE; // success
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -