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.

362 lines
8.1 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. cteestream.cpp
  5. Abstract:
  6. See cteestream.h.
  7. Author:
  8. Jay Krell (a-JayK, JayKrell) May 2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include "cteestream.h"
  13. #include "sxsp.h"
  14. #include "sxsexceptionhandling.h"
  15. CTeeStream::~CTeeStream()
  16. {
  17. FN_TRACE();
  18. CSxsPreserveLastError ple;
  19. ASSERT(m_cRef == 0);
  20. m_streamSource.Release();
  21. if (!m_fileSink.Win32Close())
  22. {
  23. ::FusionpDbgPrintEx(
  24. FUSION_DBG_LEVEL_ERROR,
  25. "SXS.DLL: %s(): m_fileSink.Close(%ls) failed: %ld\n",
  26. __FUNCTION__,
  27. static_cast<PCWSTR>(m_bufferSinkPath),
  28. ::FusionpGetLastWin32Error());
  29. }
  30. if (FAILED(m_hresult))
  31. {
  32. ::FusionpDbgPrintEx(
  33. FUSION_DBG_LEVEL_INFO,
  34. "SXS.DLL: %s():deleting %ls\n",
  35. __FUNCTION__,
  36. static_cast<PCWSTR>(m_bufferSinkPath));
  37. if (!::DeleteFileW(m_bufferSinkPath))
  38. {
  39. FusionpDbgPrintEx(
  40. FUSION_DBG_LEVEL_ERROR,
  41. "SXS.DLL: %s():DeleteFileW(%ls) failed:%ld\n",
  42. __FUNCTION__,
  43. static_cast<PCWSTR>(m_bufferSinkPath),
  44. ::FusionpGetLastWin32Error());
  45. }
  46. }
  47. ple.Restore();
  48. }
  49. VOID
  50. CTeeStream::SetSource(IStream *streamSource)
  51. {
  52. FN_TRACE();
  53. m_streamSource = streamSource;
  54. }
  55. BOOL
  56. CTeeStream::SetSink(
  57. const CImpersonationData &ImpersonationData,
  58. const CBaseStringBuffer &rbuff,
  59. DWORD openOrCreate
  60. )
  61. {
  62. BOOL fSuccess = FALSE;
  63. FN_TRACE_WIN32(fSuccess);
  64. DWORD dwBytesWritten = 0;
  65. DWORD dwBufferSize = 0;
  66. BOOL fFailForCreateFile = FALSE;
  67. IFCOMFAILED_EXIT(m_hresult);
  68. IFW32FALSE_EXIT(m_bufferSinkPath.Win32Assign(rbuff));
  69. m_ImpersonationData = ImpersonationData;
  70. {
  71. CImpersonate impersonate(ImpersonationData);
  72. IFW32FALSE_EXIT(impersonate.Impersonate());
  73. IFW32FALSE_EXIT_UNLESS(m_fileSink.Win32CreateFile(m_bufferSinkPath, GENERIC_WRITE, 0/*share*/, openOrCreate),
  74. ::FusionpGetLastWin32Error() == ERROR_FILE_EXISTS,
  75. fFailForCreateFile);
  76. if (fFailForCreateFile) // the file has existed, have to reopen in order do not break
  77. {
  78. ::FusionpDbgPrintEx(
  79. FUSION_DBG_LEVEL_ERROR,
  80. "SXS.DLL: SOFT_VERIFY FAILURE : An Existing manifest is tried to be opened for write again, file a BUG!\n");
  81. IFW32FALSE_EXIT(m_fileSink.Win32CreateFile(m_bufferSinkPath, GENERIC_WRITE, 0/*share*/, CREATE_ALWAYS));
  82. }
  83. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  84. }
  85. dwBufferSize = static_cast<DWORD>(m_buffer.GetCurrentCb());
  86. fSuccess = TRUE;
  87. if (dwBufferSize > 0)
  88. {
  89. fSuccess = WriteFile(m_fileSink, m_buffer, dwBufferSize, &dwBytesWritten, NULL/*overlapped*/);
  90. DWORD dwLastError = fSuccess ? ERROR_SUCCESS : ::FusionpGetLastWin32Error();
  91. // I'm not entirely sure why we mask the lasterror of the write
  92. // if it "succeeded" in writing the wrong number of bytes, but
  93. // such as it is, this is a write fault (The system cannot write
  94. // to the specified device.)
  95. if (fSuccess && dwBytesWritten != dwBufferSize)
  96. {
  97. dwLastError = ERROR_WRITE_FAULT;
  98. fSuccess = FALSE;
  99. }
  100. m_fBuffer = FALSE;
  101. if (dwLastError != ERROR_SUCCESS)
  102. ORIGINATE_WIN32_FAILURE_AND_EXIT(WriteFile, dwLastError);
  103. }
  104. m_fBuffer = FALSE;
  105. Exit:
  106. if (!fSuccess)
  107. {
  108. DWORD dwLastError = ::FusionpGetLastWin32Error();
  109. m_hresult = ::FusionpHresultFromLastError();
  110. m_buffer.Clear(true);
  111. ::FusionpSetLastWin32Error(dwLastError);
  112. }
  113. else
  114. m_buffer.Clear(true);
  115. return fSuccess;
  116. }
  117. BOOL
  118. CTeeStream::Close()
  119. {
  120. BOOL fSuccess = FALSE;
  121. FN_TRACE_WIN32(fSuccess);
  122. IFCOMFAILED_EXIT(m_hresult);
  123. IFW32FALSE_EXIT(m_fileSink.Win32Close());
  124. // ? m_streamSource.Release();
  125. fSuccess = TRUE;
  126. Exit:
  127. if (!fSuccess)
  128. m_hresult = ::FusionpHresultFromLastError();
  129. return fSuccess;
  130. }
  131. ULONG __stdcall
  132. CTeeStream::AddRef()
  133. {
  134. FN_TRACE();
  135. return ::InterlockedIncrement(&m_cRef);
  136. }
  137. ULONG __stdcall
  138. CTeeStream::Release()
  139. {
  140. FN_TRACE();
  141. LONG cRef;
  142. if ((cRef = ::InterlockedDecrement(&m_cRef)) == 0)
  143. {
  144. /*delete this*/;
  145. }
  146. return cRef;
  147. }
  148. HRESULT __stdcall
  149. CTeeStream::QueryInterface(
  150. REFIID iid,
  151. PVOID *ppvObj
  152. )
  153. {
  154. IUnknown *punk = NULL;
  155. IUnknown **ppunk = reinterpret_cast<IUnknown **>(ppvObj);
  156. *ppunk = NULL;
  157. if (false) { }
  158. #define QI(i) else if (iid == __uuidof(i)) punk = static_cast<i*>(this);
  159. QI(IUnknown)
  160. QI(ISequentialStream)
  161. QI(IStream)
  162. #undef QI
  163. else return E_NOINTERFACE;
  164. AddRef();
  165. *ppunk = punk;
  166. return NOERROR;
  167. }
  168. HRESULT __stdcall
  169. CTeeStream::Read(PVOID pv, ULONG cb, ULONG *pcbRead)
  170. {
  171. HRESULT hr;
  172. FN_TRACE_HR(hr);
  173. ULONG cbRead;
  174. if (pcbRead != NULL)
  175. *pcbRead = 0;
  176. IFCOMFAILED_ORIGINATE_AND_EXIT(m_hresult);
  177. IFCOMFAILED_EXIT(m_streamSource->Read(pv, cb, &cbRead));
  178. if (m_fBuffer)
  179. {
  180. IFCOMFAILED_EXIT(m_buffer.Append(reinterpret_cast<const BYTE*>(pv), cbRead));
  181. }
  182. else
  183. {
  184. DWORD dwBytesWritten = 0;
  185. BOOL fSuccess = (cbRead == 0) || ::WriteFile(m_fileSink, pv, cbRead, &dwBytesWritten, NULL/*overlapped*/);
  186. if (!fSuccess)
  187. {
  188. TRACE_WIN32_FAILURE_ORIGINATION(WriteFile);
  189. hr = ::FusionpHresultFromLastError();
  190. goto Exit;
  191. }
  192. else if (dwBytesWritten != cbRead)
  193. {
  194. hr = E_FAIL;
  195. goto Exit;
  196. }
  197. }
  198. if (pcbRead != NULL)
  199. *pcbRead = cbRead;
  200. hr = NOERROR;
  201. Exit:
  202. if (FAILED(hr))
  203. m_hresult = hr;
  204. return hr;
  205. }
  206. HRESULT __stdcall
  207. CTeeStream::Write(
  208. const VOID *pv,
  209. ULONG cb,
  210. ULONG *pcbWritten
  211. )
  212. {
  213. /*
  214. since this stream is really only for reading..
  215. */
  216. if (pcbWritten != NULL)
  217. *pcbWritten = 0;
  218. return E_NOTIMPL;
  219. }
  220. // IStream methods:
  221. HRESULT __stdcall
  222. CTeeStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
  223. {
  224. /*
  225. this messes up our ability to easily copy the stream, I think..
  226. */
  227. plibNewPosition->QuadPart = 0;
  228. return E_NOTIMPL;
  229. }
  230. HRESULT __stdcall
  231. CTeeStream::SetSize(ULARGE_INTEGER libNewSize)
  232. {
  233. /*
  234. this messes up our ability to easily copy the stream, I think..
  235. besides that, this is really a read only stream
  236. */
  237. return E_NOTIMPL;
  238. }
  239. HRESULT __stdcall
  240. CTeeStream::CopyTo(
  241. IStream *pstm,
  242. ULARGE_INTEGER cb,
  243. ULARGE_INTEGER *pcbRead,
  244. ULARGE_INTEGER *pcbWritten)
  245. {
  246. /*
  247. Implementing this requires getting the current seek pointer,
  248. call CopyTo
  249. seek back
  250. Read/Write
  251. seek forward
  252. because there is no buffer
  253. */
  254. pcbRead->QuadPart = 0;
  255. pcbWritten->QuadPart = 0;
  256. return E_NOTIMPL;
  257. }
  258. HRESULT __stdcall
  259. CTeeStream::Commit(DWORD grfCommitFlags)
  260. {
  261. /*
  262. since this stream is really only for reading..
  263. */
  264. return S_OK;
  265. }
  266. HRESULT __stdcall
  267. CTeeStream::Revert()
  268. {
  269. /*
  270. since this stream is really only for reading..
  271. */
  272. return S_OK;
  273. }
  274. HRESULT __stdcall
  275. CTeeStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  276. {
  277. /*
  278. since this stream is really only for reading..
  279. */
  280. return S_OK;
  281. }
  282. HRESULT __stdcall
  283. CTeeStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  284. {
  285. /*
  286. since this stream is really only for reading..
  287. */
  288. return S_OK;
  289. }
  290. HRESULT __stdcall
  291. CTeeStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  292. {
  293. HRESULT hr = m_streamSource->Stat(pstatstg, grfStatFlag);
  294. return hr;
  295. }
  296. HRESULT __stdcall
  297. CTeeStream::Clone(IStream **ppIStream)
  298. {
  299. *ppIStream = NULL;
  300. return E_NOTIMPL;
  301. }