FileStream_WIN32.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. //
  2. // FileStream.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/FileStream_WIN32.cpp#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Streams
  8. // Module: FileStream
  9. //
  10. // Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/FileStream.h"
  16. #include "Poco/File.h"
  17. #include "Poco/Exception.h"
  18. #if defined (POCO_WIN32_UTF8)
  19. #include "Poco/UnicodeConverter.h"
  20. #endif
  21. namespace Poco {
  22. FileStreamBuf::FileStreamBuf():
  23. BufferedBidirectionalStreamBuf(BUFFER_SIZE, std::ios::in | std::ios::out),
  24. _handle(INVALID_HANDLE_VALUE),
  25. _pos(0)
  26. {
  27. }
  28. FileStreamBuf::~FileStreamBuf()
  29. {
  30. close();
  31. }
  32. void FileStreamBuf::open(const std::string& path, std::ios::openmode mode)
  33. {
  34. poco_assert (_handle == INVALID_HANDLE_VALUE);
  35. _path = path;
  36. _pos = 0;
  37. setMode(mode);
  38. resetBuffers();
  39. DWORD access = 0;
  40. if (mode & std::ios::in)
  41. access |= GENERIC_READ;
  42. if (mode & std::ios::out)
  43. access |= GENERIC_WRITE;
  44. DWORD shareMode = FILE_SHARE_READ;
  45. if (!(mode & std::ios::out))
  46. shareMode |= FILE_SHARE_WRITE;
  47. DWORD creationDisp = OPEN_EXISTING;
  48. if (mode & std::ios::trunc)
  49. creationDisp = CREATE_ALWAYS;
  50. else if (mode & std::ios::out)
  51. creationDisp = OPEN_ALWAYS;
  52. DWORD flags = FILE_ATTRIBUTE_NORMAL;
  53. #if defined (POCO_WIN32_UTF8)
  54. std::wstring utf16Path;
  55. UnicodeConverter::toUTF16(path, utf16Path);
  56. _handle = CreateFileW(utf16Path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL);
  57. #else
  58. _handle = CreateFileA(path.c_str(), access, shareMode, NULL, creationDisp, flags, NULL);
  59. #endif
  60. if (_handle == INVALID_HANDLE_VALUE)
  61. File::handleLastError(_path);
  62. if ((mode & std::ios::ate) || (mode & std::ios::app))
  63. seekoff(0, std::ios::end, mode);
  64. }
  65. int FileStreamBuf::readFromDevice(char* buffer, std::streamsize length)
  66. {
  67. if (INVALID_HANDLE_VALUE == _handle || !(getMode() & std::ios::in))
  68. return -1;
  69. if (getMode() & std::ios::out)
  70. sync();
  71. DWORD bytesRead(0);
  72. BOOL rc = ReadFile(_handle, buffer, static_cast<DWORD>(length), &bytesRead, NULL);
  73. if (rc == 0)
  74. File::handleLastError(_path);
  75. _pos += bytesRead;
  76. return static_cast<int>(bytesRead);
  77. }
  78. int FileStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
  79. {
  80. if (INVALID_HANDLE_VALUE == _handle || !(getMode() & std::ios::out))
  81. return -1;
  82. if (getMode() & std::ios::app)
  83. {
  84. LARGE_INTEGER li;
  85. li.QuadPart = 0;
  86. li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_END);
  87. if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  88. File::handleLastError(_path);
  89. _pos = li.QuadPart;
  90. }
  91. DWORD bytesWritten(0);
  92. BOOL rc = WriteFile(_handle, buffer, static_cast<DWORD>(length), &bytesWritten, NULL);
  93. if (rc == 0)
  94. File::handleLastError(_path);
  95. _pos += bytesWritten;
  96. return static_cast<int>(bytesWritten);
  97. }
  98. bool FileStreamBuf::close()
  99. {
  100. bool success = true;
  101. if (_handle != INVALID_HANDLE_VALUE)
  102. {
  103. try
  104. {
  105. if (getMode() & std::ios::out)
  106. sync();
  107. }
  108. catch (...)
  109. {
  110. success = false;
  111. }
  112. CloseHandle(_handle);
  113. _handle = INVALID_HANDLE_VALUE;
  114. }
  115. return success;
  116. }
  117. std::streampos FileStreamBuf::seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode)
  118. {
  119. if (INVALID_HANDLE_VALUE == _handle || !(getMode() & mode))
  120. return -1;
  121. if (getMode() & std::ios::out)
  122. sync();
  123. std::streamoff adj;
  124. if (mode & std::ios::in)
  125. adj = static_cast<std::streamoff>(egptr() - gptr());
  126. else
  127. adj = 0;
  128. resetBuffers();
  129. DWORD offset = FILE_BEGIN;
  130. if (dir == std::ios::cur)
  131. {
  132. offset = FILE_CURRENT;
  133. off -= adj;
  134. }
  135. else if (dir == std::ios::end)
  136. {
  137. offset = FILE_END;
  138. }
  139. LARGE_INTEGER li;
  140. li.QuadPart = off;
  141. li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, offset);
  142. if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  143. File::handleLastError(_path);
  144. _pos = li.QuadPart;
  145. return std::streampos(static_cast<std::streamoff>(_pos));
  146. }
  147. std::streampos FileStreamBuf::seekpos(std::streampos pos, std::ios::openmode mode)
  148. {
  149. if (INVALID_HANDLE_VALUE == _handle || !(getMode() & mode))
  150. return -1;
  151. if (getMode() & std::ios::out)
  152. sync();
  153. resetBuffers();
  154. LARGE_INTEGER li;
  155. li.QuadPart = pos;
  156. li.LowPart = SetFilePointer(_handle, li.LowPart, &li.HighPart, FILE_BEGIN);
  157. if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  158. File::handleLastError(_path);
  159. _pos = li.QuadPart;
  160. return std::streampos(static_cast<std::streamoff>(_pos));
  161. }
  162. } // namespace Poco