Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. filestream.cpp
  5. Abstract:
  6. Implementation of IStream over a win32 file.
  7. Author:
  8. Michael J. Grier (MGrier) 23-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include "helpers.h"
  13. #include <windows.h>
  14. #include "atlbase.h"
  15. #include "atlconv.h"
  16. #define IS_NT() ((GetVersion() & 0x80000000) == 0)
  17. BOOL
  18. MySetFilePointerEx(
  19. HANDLE File, // handle to file
  20. LARGE_INTEGER DistanceToMove, // bytes to move pointer
  21. PLARGE_INTEGER NewFilePointer, // new file pointer
  22. DWORD MoveMethod // starting point
  23. )
  24. {
  25. LONG DistanceToMoveLow = static_cast<LONG>(DistanceToMove.LowPart);
  26. LONG DistanceToMoveHigh = DistanceToMove.HighPart;
  27. DWORD NewPositionLow = SetFilePointer(File, DistanceToMoveLow, &DistanceToMoveHigh, MoveMethod);
  28. if (NewPositionLow == INVALID_SET_FILE_POINTER)
  29. {
  30. if (GetLastError() != NO_ERROR)
  31. return FALSE;
  32. }
  33. if (NewFilePointer != NULL)
  34. {
  35. NewFilePointer->LowPart = NewPositionLow;
  36. NewFilePointer->HighPart = DistanceToMoveHigh;
  37. }
  38. return TRUE;
  39. }
  40. CFileStreamBase::~CFileStreamBase()
  41. {
  42. if (m_hFile != INVALID_HANDLE_VALUE)
  43. {
  44. const DWORD dwLastError = ::GetLastError();
  45. ::CloseHandle(m_hFile);
  46. ::SetLastError(dwLastError);
  47. }
  48. }
  49. bool
  50. CFileStreamBase::OpenForRead(PCWSTR pszPath)
  51. {
  52. USES_CONVERSION;
  53. if (m_hFile != INVALID_HANDLE_VALUE)
  54. return false;
  55. m_hFile =
  56. IS_NT() ? CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
  57. : CreateFileA(W2A(pszPath), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  58. return (m_hFile != INVALID_HANDLE_VALUE);
  59. }
  60. bool
  61. CFileStreamBase::Close()
  62. {
  63. if (m_hFile != INVALID_HANDLE_VALUE)
  64. {
  65. if (!::CloseHandle(m_hFile))
  66. {
  67. return false;
  68. }
  69. m_hFile = INVALID_HANDLE_VALUE;
  70. }
  71. return true;
  72. }
  73. ULONG
  74. CFileStreamBase::AddRef()
  75. {
  76. return ::InterlockedIncrement(&m_cRef);
  77. }
  78. ULONG
  79. CFileStreamBase::Release()
  80. {
  81. return ::InterlockedDecrement(&m_cRef);
  82. }
  83. HRESULT
  84. CFileStreamBase::QueryInterface(
  85. REFIID riid,
  86. PVOID* ppvObj
  87. )
  88. {
  89. HRESULT hr = NOERROR;
  90. if (ppvObj != NULL)
  91. *ppvObj = NULL;
  92. if (ppvObj == NULL)
  93. {
  94. hr = E_POINTER;
  95. goto Exit;
  96. }
  97. if ((riid == IID_IUnknown) ||
  98. (riid == IID_ISequentialStream) ||
  99. (riid == IID_IStream))
  100. *ppvObj = static_cast<IStream *>(this);
  101. else
  102. {
  103. hr = E_NOINTERFACE;
  104. goto Exit;
  105. }
  106. AddRef();
  107. hr = NOERROR;
  108. Exit:
  109. return hr;
  110. }
  111. HRESULT
  112. CFileStreamBase::Read(
  113. void *pv,
  114. ULONG cb,
  115. ULONG *pcbRead
  116. )
  117. {
  118. HRESULT hr = NOERROR;
  119. ULONG cbRead = 0;
  120. if (pcbRead != NULL)
  121. *pcbRead = 0;
  122. if (m_hFile == INVALID_HANDLE_VALUE)
  123. {
  124. hr = E_UNEXPECTED;
  125. goto Exit;
  126. }
  127. if (!m_bSeenFirstCharacter)
  128. {
  129. #ifdef AWFUL_SPACE_HACK
  130. while (true)
  131. {
  132. CHAR ch;
  133. ReadFile(m_hFile, &ch, 1, &cbRead, NULL);
  134. if ((ch != '\n') && (ch != '\r') && (ch != ' ') && (ch != '\t')) {
  135. m_bSeenFirstCharacter = true;
  136. LARGE_INTEGER li;
  137. li.QuadPart = -1;
  138. ::MySetFilePointerEx(m_hFile, li, NULL, FILE_CURRENT);
  139. break;
  140. }
  141. }
  142. #endif
  143. }
  144. if (!::ReadFile(m_hFile, pv, cb, &cbRead, NULL))
  145. {
  146. hr = HRESULT_FROM_WIN32(::GetLastError());
  147. goto Exit;
  148. }
  149. if (cbRead == 0)
  150. hr = S_FALSE;
  151. else
  152. hr = NOERROR;
  153. if (pcbRead != NULL)
  154. *pcbRead = cbRead;
  155. Exit:
  156. return hr;
  157. }
  158. HRESULT
  159. CFileStreamBase::Write(
  160. void const *pv,
  161. ULONG cb,
  162. ULONG *pcbWritten
  163. )
  164. {
  165. HRESULT hr = NOERROR;
  166. ULONG cbWritten = 0;
  167. if (pcbWritten != NULL)
  168. *pcbWritten = 0;
  169. if (m_hFile == INVALID_HANDLE_VALUE)
  170. {
  171. hr = E_UNEXPECTED;
  172. goto Exit;
  173. }
  174. if (!::WriteFile(m_hFile, pv, cb, &cbWritten, NULL))
  175. {
  176. hr = HRESULT_FROM_WIN32(::GetLastError());
  177. goto Exit;
  178. }
  179. if (cbWritten == 0)
  180. hr = S_FALSE;
  181. else
  182. hr = NOERROR;
  183. if (pcbWritten != NULL)
  184. *pcbWritten = cbWritten;
  185. Exit:
  186. return hr;
  187. }
  188. HRESULT
  189. CFileStreamBase::Seek(
  190. LARGE_INTEGER dlibMove,
  191. DWORD dwOrigin,
  192. ULARGE_INTEGER *plibNewPosition
  193. )
  194. {
  195. HRESULT hr = NOERROR;
  196. DWORD dwWin32Origin = 0;
  197. if (m_hFile == INVALID_HANDLE_VALUE)
  198. {
  199. hr = E_UNEXPECTED;
  200. goto Exit;
  201. }
  202. switch (dwOrigin)
  203. {
  204. default:
  205. hr = E_INVALIDARG;
  206. goto Exit;
  207. case STREAM_SEEK_SET:
  208. dwWin32Origin = FILE_BEGIN;
  209. break;
  210. case STREAM_SEEK_CUR:
  211. dwWin32Origin = FILE_CURRENT;
  212. break;
  213. case STREAM_SEEK_END:
  214. dwWin32Origin = FILE_END;
  215. break;
  216. }
  217. if (!::MySetFilePointerEx(
  218. m_hFile,
  219. dlibMove,
  220. (LARGE_INTEGER *) plibNewPosition,
  221. dwWin32Origin))
  222. {
  223. hr = HRESULT_FROM_WIN32(::GetLastError());
  224. goto Exit;
  225. }
  226. hr = NOERROR;
  227. Exit:
  228. return hr;
  229. }
  230. HRESULT
  231. CFileStreamBase::SetSize(
  232. ULARGE_INTEGER libNewSize
  233. )
  234. {
  235. return E_NOTIMPL;
  236. }
  237. HRESULT
  238. CFileStreamBase::CopyTo(
  239. IStream *pstm,
  240. ULARGE_INTEGER cb,
  241. ULARGE_INTEGER *pcbRead,
  242. ULARGE_INTEGER *pcbWritten
  243. )
  244. {
  245. if (pcbRead != NULL)
  246. pcbRead->QuadPart = 0;
  247. if (pcbWritten != NULL)
  248. pcbWritten->QuadPart = 0;
  249. return E_NOTIMPL;
  250. }
  251. HRESULT
  252. CFileStreamBase::Commit(
  253. DWORD grfCommitFlags
  254. )
  255. {
  256. HRESULT hr = NOERROR;
  257. if (grfCommitFlags != 0)
  258. return E_INVALIDARG;
  259. if (!Close())
  260. hr = HRESULT_FROM_WIN32 (GetLastError());
  261. return hr ;
  262. }
  263. HRESULT
  264. CFileStreamBase::Revert()
  265. {
  266. return E_NOTIMPL;
  267. }
  268. HRESULT
  269. CFileStreamBase::LockRegion(
  270. ULARGE_INTEGER libOffset,
  271. ULARGE_INTEGER cb,
  272. DWORD dwLockType
  273. )
  274. {
  275. return E_NOTIMPL;
  276. }
  277. HRESULT
  278. CFileStreamBase::UnlockRegion(
  279. ULARGE_INTEGER libOffset,
  280. ULARGE_INTEGER cb,
  281. DWORD dwLockType
  282. )
  283. {
  284. return E_NOTIMPL;
  285. }
  286. HRESULT
  287. CFileStreamBase::Stat(
  288. STATSTG *pstatstg,
  289. DWORD grfStatFlag
  290. )
  291. {
  292. if (pstatstg != NULL)
  293. memset(pstatstg, 0, sizeof(*pstatstg));
  294. return E_NOTIMPL;
  295. }
  296. HRESULT
  297. CFileStreamBase::Clone(
  298. IStream** ppIStream
  299. )
  300. {
  301. if (ppIStream != NULL)
  302. *ppIStream = NULL;
  303. return E_NOTIMPL;
  304. }