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.

531 lines
12 KiB

  1. /*++
  2. Copyright (c) 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 <windows.h>
  13. #include "sxsp.h"
  14. #include "filestream.h"
  15. #include "sxsexceptionhandling.h"
  16. CFileStreamBase::CFileStreamBase() : m_cRef(0), m_hFile(INVALID_HANDLE_VALUE), m_grfMode(0)
  17. {
  18. }
  19. CFileStreamBase::~CFileStreamBase()
  20. {
  21. ASSERT_NTC(m_cRef == 0);
  22. if (m_hFile != INVALID_HANDLE_VALUE)
  23. {
  24. CSxsPreserveLastError ple;
  25. if ((m_grfMode & STGM_WRITE) == STGM_WRITE)
  26. ::FlushFileBuffers(m_hFile);
  27. ::CloseHandle(m_hFile);
  28. m_hFile = INVALID_HANDLE_VALUE;
  29. ple.Restore();
  30. }
  31. }
  32. BOOL
  33. CFileStreamBase::OpenForWrite(
  34. PCWSTR pszPath,
  35. DWORD dwShareMode,
  36. DWORD dwCreationDisposition,
  37. DWORD dwFlagsAndAttributes
  38. )
  39. {
  40. BOOL fSuccess = FALSE;
  41. FN_TRACE_WIN32(fSuccess);
  42. INTERNAL_ERROR_CHECK(m_hFile == INVALID_HANDLE_VALUE);
  43. PARAMETER_CHECK(pszPath != NULL);
  44. IFW32INVALIDHANDLE_ORIGINATE_AND_EXIT(
  45. m_hFile = ::CreateFileW(
  46. pszPath,
  47. GENERIC_WRITE,
  48. dwShareMode,
  49. NULL,
  50. dwCreationDisposition, // default value is CREATE_ALWAYS
  51. dwFlagsAndAttributes,
  52. NULL));
  53. m_grfMode = STGM_WRITE | STGM_CREATE;
  54. FN_EPILOG
  55. }
  56. BOOL
  57. CFileStreamBase::OpenForRead(
  58. PCWSTR pszPath,
  59. const CImpersonationData &ImpersonationData,
  60. DWORD dwShareMode,
  61. DWORD dwCreationDisposition,
  62. DWORD dwFlagsAndAttributes
  63. )
  64. {
  65. DWORD dwWin32Error;
  66. return
  67. this->OpenForRead(
  68. pszPath,
  69. ImpersonationData,
  70. dwShareMode,
  71. dwCreationDisposition,
  72. dwFlagsAndAttributes,
  73. dwWin32Error,
  74. 0);
  75. }
  76. BOOL
  77. CFileStreamBase::OpenForRead(
  78. PCWSTR pszPath,
  79. const CImpersonationData &ImpersonationData,
  80. DWORD dwShareMode,
  81. DWORD dwCreationDisposition,
  82. DWORD dwFlagsAndAttributes,
  83. DWORD &rdwLastError,
  84. SIZE_T cExceptionalLastErrors,
  85. ...
  86. )
  87. {
  88. FN_PROLOG_WIN32
  89. DWORD dwLastError = ERROR_INTERNAL_ERROR;
  90. CImpersonate impersonate(ImpersonationData);
  91. rdwLastError = ERROR_SUCCESS;
  92. PARAMETER_CHECK(pszPath != NULL);
  93. INTERNAL_ERROR_CHECK(m_hFile == INVALID_HANDLE_VALUE);
  94. IFW32FALSE_EXIT(impersonate.Impersonate());
  95. ::FusionpSetLastWin32Error(ERROR_SUCCESS);
  96. m_hFile = ::CreateFileW(
  97. pszPath,
  98. GENERIC_READ,
  99. dwShareMode,
  100. NULL,
  101. dwCreationDisposition,
  102. dwFlagsAndAttributes,
  103. NULL);
  104. dwLastError = ::FusionpGetLastWin32Error();
  105. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  106. m_grfMode = STGM_READ;
  107. if (m_hFile == INVALID_HANDLE_VALUE)
  108. {
  109. va_list ap;
  110. SIZE_T i = 0;
  111. if (dwLastError == ERROR_SUCCESS)
  112. {
  113. //
  114. // CreateFile always set lasterror to be 0 for an unexisted file even OPEN_EXISTING
  115. // for GENERIC_READ, Fusion expect ERROR_FILE_NOT_FOUND in this case for some reason
  116. //
  117. ::FusionpSetLastWin32Error(ERROR_FILE_NOT_FOUND);
  118. dwLastError = ERROR_FILE_NOT_FOUND; // reset lLastError
  119. }
  120. va_start(ap, cExceptionalLastErrors);
  121. for (i=0; i<cExceptionalLastErrors; i++)
  122. {
  123. if (dwLastError == va_arg(ap, DWORD))
  124. {
  125. rdwLastError = dwLastError;
  126. break;
  127. }
  128. }
  129. va_end(ap);
  130. if (i == cExceptionalLastErrors) // This gets the cExceptionalLastErrors == 0 case too.
  131. {
  132. ::FusionpDbgPrintEx(
  133. FUSION_DBG_LEVEL_ERROR,
  134. "SXS.DLL: %s(%ls) gave error %ld\n",
  135. __FUNCTION__,
  136. pszPath,
  137. dwLastError);
  138. ORIGINATE_WIN32_FAILURE_AND_EXIT(CreateFileW, dwLastError);
  139. }
  140. }
  141. FN_EPILOG
  142. }
  143. BOOL
  144. CFileStreamBase::Close()
  145. {
  146. FN_PROLOG_WIN32
  147. if (m_hFile != INVALID_HANDLE_VALUE)
  148. {
  149. if ((m_grfMode & STGM_WRITE) == STGM_WRITE)
  150. {
  151. if (!::FlushFileBuffers(m_hFile))
  152. {
  153. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  154. ::CloseHandle(m_hFile);
  155. m_hFile = INVALID_HANDLE_VALUE;
  156. ORIGINATE_WIN32_FAILURE_AND_EXIT(FlushFileBuffers, dwLastError);
  157. }
  158. }
  159. if (!::CloseHandle(m_hFile))
  160. {
  161. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  162. m_hFile = INVALID_HANDLE_VALUE;
  163. ORIGINATE_WIN32_FAILURE_AND_EXIT(CloseHandle, dwLastError);
  164. }
  165. m_hFile = INVALID_HANDLE_VALUE;
  166. }
  167. FN_EPILOG
  168. }
  169. ULONG
  170. CFileStreamBase::AddRef()
  171. {
  172. return ::InterlockedIncrement((LONG *) &m_cRef);
  173. }
  174. ULONG
  175. CFileStreamBase::Release()
  176. {
  177. ULONG ulRefCount = ::InterlockedDecrement((LONG *) &m_cRef);
  178. if (ulRefCount == 0)
  179. this->OnRefCountZero();
  180. return ulRefCount;
  181. }
  182. HRESULT
  183. CFileStreamBase::QueryInterface(
  184. REFIID riid,
  185. PVOID *ppvObj
  186. )
  187. {
  188. FN_PROLOG_HR
  189. IUnknown *pIUnknown = NULL;
  190. if (ppvObj != NULL)
  191. *ppvObj = NULL;
  192. if (ppvObj == NULL)
  193. ORIGINATE_HR_FAILURE_AND_EXIT(OutPointerWasNull, E_POINTER);
  194. if ((riid == IID_IUnknown) ||
  195. (riid == IID_ISequentialStream) ||
  196. (riid == IID_IStream))
  197. pIUnknown = static_cast<IStream *>(this);
  198. if (pIUnknown == NULL)
  199. ORIGINATE_HR_FAILURE_AND_EXIT(NoInterface, E_NOINTERFACE);
  200. pIUnknown->AddRef();
  201. *ppvObj = pIUnknown;
  202. FN_EPILOG
  203. }
  204. HRESULT
  205. CFileStreamBase::Read(
  206. void *pv,
  207. ULONG cb,
  208. ULONG *pcbRead
  209. )
  210. {
  211. HRESULT hr = NOERROR;
  212. FN_TRACE_HR(hr);
  213. ULONG cbRead = 0;
  214. if (pcbRead != NULL)
  215. *pcbRead = 0;
  216. INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE);
  217. IFW32FALSE_ORIGINATE_AND_EXIT(::ReadFile(m_hFile, pv, cb, &cbRead, NULL));
  218. if (pcbRead != NULL)
  219. *pcbRead = cbRead;
  220. if (cbRead == 0)
  221. hr = S_FALSE;
  222. else
  223. hr = NOERROR;
  224. Exit:
  225. return hr;
  226. }
  227. HRESULT
  228. CFileStreamBase::Write(
  229. void const *pv,
  230. ULONG cb,
  231. ULONG *pcbWritten
  232. )
  233. {
  234. HRESULT hr = NOERROR;
  235. FN_TRACE_HR(hr);
  236. ULONG cbWritten = 0;
  237. if (pcbWritten != NULL)
  238. *pcbWritten = 0;
  239. INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE);
  240. PARAMETER_CHECK((cb == 0) || (pv != NULL));
  241. IFW32FALSE_ORIGINATE_AND_EXIT(::WriteFile(m_hFile, pv, cb, &cbWritten, NULL));
  242. if (pcbWritten != NULL)
  243. *pcbWritten = cbWritten;
  244. if (cbWritten == 0)
  245. hr = S_FALSE;
  246. else
  247. hr = NOERROR;
  248. Exit:
  249. return hr;
  250. }
  251. HRESULT
  252. CFileStreamBase::Seek(
  253. LARGE_INTEGER dlibMove,
  254. DWORD dwOrigin,
  255. ULARGE_INTEGER *plibNewPosition
  256. )
  257. {
  258. HRESULT hr = NOERROR;
  259. FN_TRACE_HR(hr);
  260. DWORD dwWin32Origin = 0;
  261. INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE);
  262. switch (dwOrigin)
  263. {
  264. default:
  265. hr = E_INVALIDARG;
  266. goto Exit;
  267. case STREAM_SEEK_SET:
  268. dwWin32Origin = FILE_BEGIN;
  269. break;
  270. case STREAM_SEEK_CUR:
  271. dwWin32Origin = FILE_CURRENT;
  272. break;
  273. case STREAM_SEEK_END:
  274. dwWin32Origin = FILE_END;
  275. break;
  276. }
  277. if (!::SetFilePointerEx(
  278. m_hFile,
  279. dlibMove,
  280. (LARGE_INTEGER *) plibNewPosition,
  281. dwWin32Origin))
  282. {
  283. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  284. goto Exit;
  285. }
  286. hr = NOERROR;
  287. Exit:
  288. return hr;
  289. }
  290. HRESULT
  291. CFileStreamBase::SetSize(
  292. ULARGE_INTEGER libNewSize
  293. )
  294. {
  295. ::FusionpDbgPrintEx(
  296. FUSION_DBG_LEVEL_ERROR,
  297. "SXS.DLL: Entered CFileStreamBase::SetSize() !!! NOT IMPLEMENTED !!!\n");
  298. UNUSED(libNewSize);
  299. return E_NOTIMPL;
  300. }
  301. HRESULT
  302. CFileStreamBase::CopyTo(
  303. IStream *pstm,
  304. ULARGE_INTEGER cb,
  305. ULARGE_INTEGER *pcbRead,
  306. ULARGE_INTEGER *pcbWritten
  307. )
  308. {
  309. ::FusionpDbgPrintEx(
  310. FUSION_DBG_LEVEL_ERROR,
  311. "SXS.DLL: Entered CFileStreamBase::CopyTo() !!! NOT IMPLEMENTED !!!\n");
  312. if (pcbRead != NULL)
  313. pcbRead->QuadPart = 0;
  314. if (pcbWritten != NULL)
  315. pcbWritten->QuadPart = 0;
  316. return E_NOTIMPL;
  317. }
  318. HRESULT
  319. CFileStreamBase::Commit(
  320. DWORD grfCommitFlags
  321. )
  322. {
  323. HRESULT hr = NOERROR;
  324. ::FusionpDbgPrintEx(
  325. FUSION_DBG_LEVEL_INFO,
  326. "SXS.DLL: Entered CFileStreamBase::Commit()\n");
  327. if (grfCommitFlags != 0)
  328. return E_INVALIDARG;
  329. if ( !Close())
  330. hr = HRESULT_FROM_WIN32 (::FusionpGetLastWin32Error());
  331. if (!SUCCEEDED(hr))
  332. ::FusionpDbgPrintEx(
  333. FUSION_DBG_LEVEL_ERROR,
  334. "SXS.DLL: %s() failed; ::FusionpGetLastWin32Error() = %d\n", __FUNCTION__, ::FusionpGetLastWin32Error());
  335. else
  336. ::FusionpDbgPrintEx(
  337. FUSION_DBG_LEVEL_INFO,
  338. "SXS.DLL: Leaving %s()\n", __FUNCTION__);
  339. return hr ;
  340. }
  341. HRESULT
  342. CFileStreamBase::Revert()
  343. {
  344. ::FusionpDbgPrintEx(
  345. FUSION_DBG_LEVEL_ERROR,
  346. "SXS.DLL: Entered CFileStreamBase::Revert() !!! NOT IMPLEMENTED !!!\n");
  347. return E_NOTIMPL;
  348. }
  349. HRESULT
  350. CFileStreamBase::LockRegion(
  351. ULARGE_INTEGER libOffset,
  352. ULARGE_INTEGER cb,
  353. DWORD dwLockType
  354. )
  355. {
  356. ::FusionpDbgPrintEx(
  357. FUSION_DBG_LEVEL_ERROR,
  358. "SXS.DLL: Entered CFileStreamBase::LockRegion() !!! NOT IMPLEMENTED !!!\n");
  359. UNUSED(libOffset);
  360. UNUSED(cb);
  361. UNUSED(dwLockType);
  362. return E_NOTIMPL;
  363. }
  364. HRESULT
  365. CFileStreamBase::UnlockRegion(
  366. ULARGE_INTEGER libOffset,
  367. ULARGE_INTEGER cb,
  368. DWORD dwLockType
  369. )
  370. {
  371. ::FusionpDbgPrintEx(
  372. FUSION_DBG_LEVEL_ERROR,
  373. "SXS.DLL: Entered CFileStreamBase::UnlockRegion() !!! NOT IMPLEMENTED !!!\n");
  374. UNUSED(libOffset);
  375. UNUSED(cb);
  376. UNUSED(dwLockType);
  377. return E_NOTIMPL;
  378. }
  379. HRESULT
  380. CFileStreamBase::Stat(
  381. STATSTG *pstatstg,
  382. DWORD grfStatFlag
  383. )
  384. {
  385. HRESULT hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR);
  386. FN_TRACE_HR(hr);
  387. BY_HANDLE_FILE_INFORMATION bhfi;
  388. if (pstatstg != NULL)
  389. memset(pstatstg, 0, sizeof(*pstatstg));
  390. PARAMETER_CHECK(((grfStatFlag & ~(STATFLAG_NONAME)) == 0));
  391. PARAMETER_CHECK(pstatstg != NULL);
  392. if (!(grfStatFlag & STATFLAG_NONAME))
  393. {
  394. ::FusionpDbgPrintEx(
  395. FUSION_DBG_LEVEL_ERROR,
  396. "SXS.DLL: %s() does not handle STATFLAG_NONE; returning E_NOTIMPL.\n", __FUNCTION__);
  397. hr = E_NOTIMPL;
  398. goto Exit;
  399. }
  400. INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE);
  401. IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileInformationByHandle(m_hFile, &bhfi));
  402. pstatstg->pwcsName = NULL;
  403. pstatstg->type = STGTY_STREAM;
  404. pstatstg->cbSize.LowPart = bhfi.nFileSizeLow;
  405. pstatstg->cbSize.HighPart = bhfi.nFileSizeHigh;
  406. pstatstg->mtime = bhfi.ftLastWriteTime;
  407. pstatstg->ctime = bhfi.ftCreationTime;
  408. pstatstg->atime = bhfi.ftLastAccessTime;
  409. pstatstg->grfMode = m_grfMode;
  410. pstatstg->grfLocksSupported = LOCK_WRITE;
  411. pstatstg->clsid = GUID_NULL;
  412. pstatstg->grfStateBits = 0;
  413. pstatstg->reserved = 0;
  414. hr = NOERROR;
  415. Exit:
  416. return hr;
  417. }
  418. HRESULT
  419. CFileStreamBase::Clone(
  420. IStream **ppIStream
  421. )
  422. {
  423. ::FusionpDbgPrintEx(
  424. FUSION_DBG_LEVEL_ERROR,
  425. "SXS.DLL: Entered CFileStreamBase::Clone() !!! NOT IMPLEMENTED !!!\n");
  426. if (ppIStream != NULL)
  427. *ppIStream = NULL;
  428. return E_NOTIMPL;
  429. }