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.

474 lines
10 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. stream.cpp
  5. Abstract:
  6. This module contains the implementation for the Server
  7. Extension Object CSEOStream class.
  8. Author:
  9. Don Dumitru (dondu@microsoft.com)
  10. Revision History:
  11. dondu 03/29 created
  12. --*/
  13. // stream.cpp : Implementation of CSEOStream
  14. #include "stdafx.h"
  15. #include "seodefs.h"
  16. #include "stream.h"
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CSEOStream
  19. HRESULT CSEOStream::FinalConstruct() {
  20. HRESULT hrRes;
  21. TraceFunctEnter("CSEOStream::FinalConstruct");
  22. m_hFile = NULL;
  23. m_pszFile = NULL;
  24. m_hEvent = NULL;
  25. m_pSubStream = NULL;
  26. hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
  27. _ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
  28. TraceFunctLeave();
  29. return (SUCCEEDED(hrRes)?S_OK:hrRes);
  30. }
  31. void CSEOStream::FinalRelease() {
  32. TraceFunctEnter("CSEOStream::FinalRelease");
  33. Cleanup();
  34. m_pUnkMarshaler.Release();
  35. TraceFunctLeave();
  36. }
  37. void CSEOStream::Cleanup() {
  38. if (m_hFile) {
  39. CloseHandle(m_hFile);
  40. m_hFile = NULL;
  41. }
  42. if (m_pszFile) {
  43. CoTaskMemFree(m_pszFile);
  44. m_pszFile = NULL;
  45. }
  46. if (m_hEvent) {
  47. CloseHandle(m_hEvent);
  48. m_hEvent = NULL;
  49. }
  50. if (m_pSubStream) {
  51. m_pSubStream->Release();
  52. m_pSubStream = NULL;
  53. }
  54. }
  55. HRESULT CSEOStream::Init(HANDLE hFile, LPCSTR pszFile, ULARGE_INTEGER libOffset, CSEOStream *pSubStream) {
  56. Cleanup();
  57. if (pSubStream) {
  58. m_pSubStream = pSubStream;
  59. m_pSubStream->AddRef();
  60. } else {
  61. if (hFile) {
  62. if (!DuplicateHandle(GetCurrentProcess(),
  63. hFile,
  64. GetCurrentProcess(),
  65. &m_hFile,
  66. 0,
  67. FALSE,
  68. DUPLICATE_SAME_ACCESS)) {
  69. HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
  70. Cleanup();
  71. return (hrRes);
  72. }
  73. }
  74. if (pszFile) {
  75. DWORD dwLen;
  76. dwLen = GetFullPathName(pszFile,0,NULL,NULL);
  77. if (!dwLen) {
  78. HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
  79. Cleanup();
  80. return (hrRes);
  81. }
  82. m_pszFile = (LPSTR) CoTaskMemAlloc((dwLen+1)*sizeof(*m_pszFile));
  83. if (!m_pszFile) {
  84. Cleanup();
  85. return (E_OUTOFMEMORY);
  86. }
  87. dwLen = GetFullPathName(pszFile,dwLen+1,m_pszFile,NULL);
  88. if (!dwLen) {
  89. HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
  90. Cleanup();
  91. return (hrRes);
  92. }
  93. }
  94. }
  95. m_libOffset = libOffset;
  96. return (S_OK);
  97. }
  98. HRESULT CSEOStream::Init(HANDLE hFile, LPCWSTR pszFile, ULARGE_INTEGER libOffset, CSEOStream *pSubStream) {
  99. USES_CONVERSION;
  100. return (Init(hFile,W2A(pszFile),libOffset,pSubStream));
  101. }
  102. HRESULT CSEOStream::Open() {
  103. if ((m_hFile && m_hEvent) || m_pSubStream) {
  104. return (S_OK);
  105. }
  106. if (!m_hEvent) {
  107. m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  108. if (!m_hEvent) {
  109. return (HRESULT_FROM_WIN32(GetLastError()));
  110. }
  111. if (m_hFile) {
  112. return (S_OK);
  113. }
  114. }
  115. if (!m_pszFile) {
  116. return (OLE_E_BLANK);
  117. }
  118. m_hFile = CreateFile(m_pszFile,
  119. GENERIC_READ|GENERIC_WRITE,
  120. 0,
  121. NULL,
  122. OPEN_ALWAYS,
  123. FILE_ATTRIBUTE_NORMAL,
  124. NULL);
  125. if (m_hFile == INVALID_HANDLE_VALUE) {
  126. return (HRESULT_FROM_WIN32(GetLastError()));
  127. }
  128. return (S_OK);
  129. }
  130. HRESULT CSEOStream::ReadOffset(void *pv, ULONG cb, ULONG *pcbRead, ULARGE_INTEGER *plibOffset) {
  131. HRESULT hrRes;
  132. BOOL bRes;
  133. DWORD cbRead;
  134. if (!SUCCEEDED(hrRes=Open())) {
  135. return (hrRes);
  136. }
  137. if (m_pSubStream) {
  138. return (m_pSubStream->ReadOffset(pv,cb,pcbRead,plibOffset));
  139. }
  140. OVERLAPPED ov = {0,0,plibOffset->LowPart,plibOffset->HighPart,m_hEvent};
  141. bRes = ReadFile(m_hFile,pv,cb,&cbRead,&ov);
  142. if (!bRes) {
  143. switch (GetLastError()) {
  144. case ERROR_HANDLE_EOF:
  145. cbRead = 0;
  146. break;
  147. case ERROR_IO_PENDING:
  148. if (!GetOverlappedResult(m_hFile,&ov,&cbRead,TRUE)) {
  149. return (HRESULT_FROM_WIN32(GetLastError()));
  150. }
  151. break;
  152. default:
  153. return (HRESULT_FROM_WIN32(GetLastError()));
  154. }
  155. }
  156. plibOffset->QuadPart += cbRead;
  157. if (pcbRead) {
  158. *pcbRead = cbRead;
  159. }
  160. return (cbRead?S_OK:S_FALSE);
  161. }
  162. HRESULT STDMETHODCALLTYPE CSEOStream::Read(void *pv, ULONG cb, ULONG *pcbRead) {
  163. return (ReadOffset(pv,cb,pcbRead,&m_libOffset));
  164. }
  165. HRESULT CSEOStream::WriteOffset(void const* pv, ULONG cb, ULONG *pcbWritten, ULARGE_INTEGER *plibOffset) {
  166. HRESULT hrRes;
  167. BOOL bRes;
  168. DWORD cbWritten;
  169. if (!SUCCEEDED(hrRes=Open())) {
  170. return (hrRes);
  171. }
  172. if (m_pSubStream) {
  173. return (m_pSubStream->WriteOffset(pv,cb,pcbWritten,plibOffset));
  174. }
  175. OVERLAPPED ov = {0,0,plibOffset->LowPart,plibOffset->HighPart,m_hEvent};
  176. bRes = WriteFile(m_hFile,pv,cb,&cbWritten,&ov);
  177. if (!bRes) {
  178. switch (GetLastError()) {
  179. case ERROR_HANDLE_EOF:
  180. cbWritten = 0;
  181. break;
  182. case ERROR_IO_PENDING:
  183. if (!GetOverlappedResult(m_hFile,&ov,&cbWritten,TRUE)) {
  184. return (HRESULT_FROM_WIN32(GetLastError()));
  185. }
  186. break;
  187. default:
  188. return (HRESULT_FROM_WIN32(GetLastError()));
  189. }
  190. }
  191. plibOffset->QuadPart += cbWritten;
  192. if (pcbWritten) {
  193. *pcbWritten = cbWritten;
  194. }
  195. return ((cbWritten==cb)?S_OK:STG_E_MEDIUMFULL);
  196. }
  197. HRESULT STDMETHODCALLTYPE CSEOStream::Write(void const* pv, ULONG cb, ULONG *pcbWritten) {
  198. return (WriteOffset(pv,cb,pcbWritten,&m_libOffset));
  199. }
  200. HRESULT CSEOStream::GetSize(ULARGE_INTEGER *plibSize) {
  201. HRESULT hrRes;
  202. if (!SUCCEEDED(hrRes=Open())) {
  203. return (hrRes);
  204. }
  205. if (m_pSubStream) {
  206. return (m_pSubStream->GetSize(plibSize));
  207. }
  208. if (!plibSize) {
  209. return (E_POINTER);
  210. }
  211. plibSize->LowPart = GetFileSize(m_hFile,&plibSize->HighPart);
  212. if ((plibSize->LowPart == 0xffffffff) && (GetLastError() != NO_ERROR)) {
  213. return (HRESULT_FROM_WIN32(GetLastError()));
  214. }
  215. return (S_OK);
  216. }
  217. HRESULT STDMETHODCALLTYPE CSEOStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *pdlibNewPosition) {
  218. HRESULT hrRes;
  219. if (!SUCCEEDED(hrRes=Open())) {
  220. return (hrRes);
  221. }
  222. hrRes = S_OK;
  223. switch (dwOrigin) {
  224. case STREAM_SEEK_SET:
  225. if (dlibMove.QuadPart < 0) {
  226. hrRes = E_INVALIDARG;
  227. break;
  228. }
  229. m_libOffset.QuadPart = (DWORDLONG) dlibMove.QuadPart;
  230. break;
  231. case STREAM_SEEK_CUR:
  232. if ((dlibMove.QuadPart < 0) && ((DWORDLONG) -dlibMove.QuadPart > m_libOffset.QuadPart)) {
  233. hrRes = E_INVALIDARG;
  234. break;
  235. }
  236. m_libOffset.QuadPart = (DWORDLONG) ((LONGLONG) m_libOffset.QuadPart + dlibMove.QuadPart);
  237. break;
  238. case STREAM_SEEK_END:
  239. ULARGE_INTEGER libSize;
  240. hrRes = GetSize(&libSize);
  241. if (!SUCCEEDED(hrRes)) {
  242. return (hrRes);
  243. }
  244. if ((dlibMove.QuadPart < 0) && ((DWORDLONG) -dlibMove.QuadPart > libSize.QuadPart)) {
  245. hrRes = E_INVALIDARG;
  246. break;
  247. }
  248. m_libOffset.QuadPart = (DWORDLONG) ((LONGLONG) libSize.QuadPart + dlibMove.QuadPart);
  249. break;
  250. default:
  251. hrRes = STG_E_INVALIDFUNCTION;
  252. break;
  253. }
  254. if (pdlibNewPosition) {
  255. *pdlibNewPosition = m_libOffset;
  256. }
  257. return (hrRes);
  258. }
  259. HRESULT STDMETHODCALLTYPE CSEOStream::SetSize(ULARGE_INTEGER libNewSize) {
  260. HRESULT hrRes;
  261. if (!SUCCEEDED(hrRes=Open())) {
  262. return (hrRes);
  263. }
  264. if (m_pSubStream) {
  265. return (m_pSubStream->SetSize(libNewSize));
  266. }
  267. if ((SetFilePointer(m_hFile,libNewSize.LowPart,(LONG *) &libNewSize.HighPart,FILE_BEGIN) == 0xffff) &&
  268. (GetLastError() != NO_ERROR)) {
  269. return (HRESULT_FROM_WIN32(GetLastError()));
  270. }
  271. if (!SetEndOfFile(m_hFile)) {
  272. return (HRESULT_FROM_WIN32(GetLastError()));
  273. }
  274. return (S_OK);
  275. }
  276. HRESULT CSEOStream::CopyToOffset(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten, ULARGE_INTEGER *plibOffset) {
  277. HRESULT hrRes;
  278. LPVOID pv;
  279. ULARGE_INTEGER cbRead;
  280. ULARGE_INTEGER cbWritten;
  281. if (!pstm) {
  282. return (E_POINTER);
  283. }
  284. if (!SUCCEEDED(hrRes=Open())) {
  285. return (hrRes);
  286. }
  287. pv = alloca((DWORD) min(cb.QuadPart,4096));
  288. if (!pv) {
  289. return (E_OUTOFMEMORY);
  290. }
  291. cbRead.QuadPart = 0;
  292. cbWritten.QuadPart = 0;
  293. while (1) {
  294. DWORD cbTmpRead;
  295. DWORD cbTmpWrite;
  296. if (!cb.QuadPart) {
  297. hrRes = S_OK;
  298. break;
  299. }
  300. cbTmpRead = 0;
  301. hrRes = ReadOffset(pv,(DWORD) min(cb.QuadPart,4096),&cbTmpRead,plibOffset);
  302. if (!SUCCEEDED(hrRes)) {
  303. return (hrRes);
  304. }
  305. if (cbTmpRead == 0) {
  306. hrRes = S_FALSE;
  307. break;
  308. }
  309. cbRead.QuadPart += cbTmpRead;
  310. cbTmpWrite = 0;
  311. hrRes = pstm->Write(pv,cbTmpRead,&cbTmpWrite);
  312. if (!SUCCEEDED(hrRes)) {
  313. if (hrRes == STG_E_MEDIUMFULL) {
  314. cbWritten.QuadPart += cbTmpWrite;
  315. }
  316. break;
  317. }
  318. cbWritten.QuadPart += cbTmpWrite;
  319. cb.QuadPart -= cbTmpRead;
  320. }
  321. if (pcbRead) {
  322. *pcbRead = cbRead;
  323. }
  324. if (pcbWritten) {
  325. *pcbWritten = cbWritten;
  326. }
  327. return (hrRes);
  328. }
  329. HRESULT STDMETHODCALLTYPE CSEOStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) {
  330. return (CopyToOffset(pstm,cb,pcbRead,pcbWritten,&m_libOffset));
  331. }
  332. HRESULT STDMETHODCALLTYPE CSEOStream::Commit(DWORD grfCommitFlags) {
  333. HRESULT hrRes;
  334. if (!SUCCEEDED(hrRes=Open())) {
  335. return (hrRes);
  336. }
  337. return (S_OK);
  338. }
  339. HRESULT STDMETHODCALLTYPE CSEOStream::Revert(void) {
  340. HRESULT hrRes;
  341. if (!SUCCEEDED(hrRes=Open())) {
  342. return (hrRes);
  343. }
  344. return (S_OK);
  345. }
  346. HRESULT STDMETHODCALLTYPE CSEOStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
  347. HRESULT hrRes;
  348. if (!SUCCEEDED(hrRes=Open())) {
  349. return (hrRes);
  350. }
  351. return (E_NOTIMPL);
  352. }
  353. HRESULT STDMETHODCALLTYPE CSEOStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
  354. HRESULT hrRes;
  355. if (!SUCCEEDED(hrRes=Open())) {
  356. return (hrRes);
  357. }
  358. return (E_NOTIMPL);
  359. }
  360. HRESULT STDMETHODCALLTYPE CSEOStream::Stat(STATSTG * pstatstg, DWORD grfStatFlag) {
  361. HRESULT hrRes;
  362. if (!SUCCEEDED(hrRes=Open())) {
  363. return (hrRes);
  364. }
  365. return (E_NOTIMPL);
  366. }
  367. HRESULT CSEOStream::CloneOffset(IStream **pstm, ULARGE_INTEGER libOffset) {
  368. HRESULT hrRes;
  369. if (!SUCCEEDED(hrRes=Open())) {
  370. return (hrRes);
  371. }
  372. return (E_NOTIMPL);
  373. }
  374. HRESULT STDMETHODCALLTYPE CSEOStream::Clone(IStream **pstm) {
  375. return (CloneOffset(pstm,m_libOffset));
  376. }