filecore.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <SysUtils.hpp>
  12. ////////////////////////////////////////////////////////////////////////////
  13. // CFile implementation
  14. CFile::CFile()
  15. {
  16. m_hFile = (UINT) hFileNull;
  17. m_bCloseOnDelete = FALSE;
  18. }
  19. CFile::~CFile()
  20. {
  21. if (m_hFile != (UINT)hFileNull && m_bCloseOnDelete)
  22. Close();
  23. }
  24. BOOL CFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,
  25. CFileException* pException)
  26. {
  27. ASSERT_VALID(this);
  28. ASSERT(AfxIsValidString(lpszFileName));
  29. ASSERT(pException == NULL ||
  30. AfxIsValidAddress(pException, sizeof(CFileException)));
  31. ASSERT((nOpenFlags & typeText) == 0); // text mode not supported
  32. // CFile objects are always binary and CreateFile does not need flag
  33. nOpenFlags &= ~(UINT)typeBinary;
  34. m_bCloseOnDelete = FALSE;
  35. m_hFile = (UINT)hFileNull;
  36. m_strFileName.Empty();
  37. TCHAR szTemp[_MAX_PATH];
  38. AfxFullPath(szTemp, lpszFileName);
  39. m_strFileName = szTemp;
  40. ASSERT(sizeof(HANDLE) == sizeof(UINT));
  41. ASSERT(shareCompat == 0);
  42. // map read/write mode
  43. ASSERT((modeRead|modeWrite|modeReadWrite) == 3);
  44. DWORD dwAccess = 0;
  45. switch (nOpenFlags & 3)
  46. {
  47. case modeRead:
  48. dwAccess = GENERIC_READ;
  49. break;
  50. case modeWrite:
  51. dwAccess = GENERIC_WRITE;
  52. break;
  53. case modeReadWrite:
  54. dwAccess = GENERIC_READ|GENERIC_WRITE;
  55. break;
  56. default:
  57. ASSERT(FALSE); // invalid share mode
  58. }
  59. // map share mode
  60. DWORD dwShareMode = 0;
  61. switch (nOpenFlags & 0x70) // map compatibility mode to exclusive
  62. {
  63. default:
  64. ASSERT(FALSE); // invalid share mode?
  65. case shareCompat:
  66. case shareExclusive:
  67. dwShareMode = 0;
  68. break;
  69. case shareDenyWrite:
  70. dwShareMode = FILE_SHARE_READ;
  71. break;
  72. case shareDenyRead:
  73. dwShareMode = FILE_SHARE_WRITE;
  74. break;
  75. case shareDenyNone:
  76. dwShareMode = FILE_SHARE_WRITE|FILE_SHARE_READ;
  77. break;
  78. }
  79. // Note: typeText and typeBinary are used in derived classes only.
  80. // map modeNoInherit flag
  81. SECURITY_ATTRIBUTES sa;
  82. sa.nLength = sizeof(sa);
  83. sa.lpSecurityDescriptor = NULL;
  84. sa.bInheritHandle = (nOpenFlags & modeNoInherit) == 0;
  85. // map creation flags
  86. DWORD dwCreateFlag;
  87. if (nOpenFlags & modeCreate)
  88. {
  89. if (nOpenFlags & modeNoTruncate)
  90. dwCreateFlag = OPEN_ALWAYS;
  91. else
  92. dwCreateFlag = CREATE_ALWAYS;
  93. }
  94. else
  95. dwCreateFlag = OPEN_EXISTING;
  96. // attempt file creation
  97. HANDLE hFile = ::CreateFile(lpszFileName, dwAccess, dwShareMode, &sa,
  98. dwCreateFlag, FILE_ATTRIBUTE_NORMAL, NULL);
  99. if (hFile == INVALID_HANDLE_VALUE)
  100. {
  101. if (pException != NULL)
  102. {
  103. pException->m_lOsError = ::GetLastError();
  104. pException->m_cause =
  105. CFileException::OsErrorToException(pException->m_lOsError);
  106. // use passed file name (not expanded vesion) when reporting
  107. // an error while opening
  108. pException->m_strFileName = lpszFileName;
  109. }
  110. return FALSE;
  111. }
  112. m_hFile = (HFILE)hFile;
  113. m_bCloseOnDelete = TRUE;
  114. return TRUE;
  115. }
  116. UINT CFile::Read(void* lpBuf, UINT nCount)
  117. {
  118. ASSERT_VALID(this);
  119. ASSERT(m_hFile != (UINT)hFileNull);
  120. if (nCount == 0)
  121. return 0; // avoid Win32 "null-read"
  122. ASSERT(lpBuf != NULL);
  123. ASSERT(AfxIsValidAddress(lpBuf, nCount));
  124. DWORD dwRead;
  125. if (!::ReadFile((HANDLE)m_hFile, lpBuf, nCount, &dwRead, NULL))
  126. CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
  127. return (UINT)dwRead;
  128. }
  129. void CFile::Write(const void* lpBuf, UINT nCount)
  130. {
  131. ASSERT_VALID(this);
  132. ASSERT(m_hFile != (UINT)hFileNull);
  133. if (nCount == 0)
  134. return; // avoid Win32 "null-write" option
  135. ASSERT(lpBuf != NULL);
  136. ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  137. DWORD nWritten;
  138. if (!::WriteFile((HANDLE)m_hFile, lpBuf, nCount, &nWritten, NULL))
  139. CFileException::ThrowOsError((LONG)::GetLastError(), m_strFileName);
  140. // Win32s will not return an error all the time (usually DISK_FULL)
  141. if (nWritten != nCount)
  142. AfxThrowFileException(CFileException::diskFull, -1, m_strFileName);
  143. }
  144. void CFile::Close()
  145. {
  146. ASSERT_VALID(this);
  147. ASSERT(m_hFile != (UINT)hFileNull);
  148. BOOL bError = FALSE;
  149. if (m_hFile != (UINT)hFileNull)
  150. bError = !::CloseHandle((HANDLE)m_hFile);
  151. m_hFile = (UINT) hFileNull;
  152. m_bCloseOnDelete = FALSE;
  153. m_strFileName.Empty();
  154. if (bError)
  155. CFileException::ThrowOsError((LONG)::GetLastError());
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CFile implementation helpers
  159. // turn a file, relative path or other into an absolute path
  160. // Used for error reporting only, so not critical.
  161. BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn)
  162. // lpszPathOut = buffer of _MAX_PATH
  163. // lpszFileIn = file, relative path or absolute path
  164. // (both in ANSI character set)
  165. {
  166. UnicodeString Path;
  167. BOOL Result;
  168. try
  169. {
  170. Path = ExpandFileName(lpszFileIn);
  171. Result = TRUE;
  172. }
  173. catch (...)
  174. {
  175. Path = lpszFileIn; // take it literally
  176. Result = FALSE;
  177. }
  178. lstrcpyn(lpszPathOut, Path.c_str(), _MAX_PATH);
  179. return Result;
  180. }
  181. /////////////////////////////////////////////////////////////////////////////