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.

515 lines
14 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. memstm.c
  5. Abstract:
  6. This modules implements IStream over a block of memory.
  7. Author:
  8. Jay Krell (JayKrell) June 2000
  9. Revision History:
  10. --*/
  11. #define RTL_DECLARE_STREAMS 1
  12. #define RTL_DECLARE_MEMORY_STREAM 1
  13. #pragma warning(disable:4214) // bit field types other than int
  14. #pragma warning(disable:4201) // nameless struct/union
  15. #pragma warning(disable:4115) // named type definition in parentheses
  16. #pragma warning(disable:4127) // condition expression is constant
  17. #include "ntos.h"
  18. #include "nt.h"
  19. #include "ntrtl.h"
  20. #include "nturtl.h"
  21. #include "objidl.h"
  22. #include "ntrtlmmapio.h"
  23. #define RTLP_MEMORY_STREAM_NOT_IMPL(x) \
  24. ASSERT(MemoryStream != NULL); \
  25. KdPrintEx((DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "NTDLL: %s() E_NOTIMPL", __FUNCTION__)); \
  26. return E_NOTIMPL;
  27. #if !defined(RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS)
  28. #if defined(RTLP_HRESULT_FROM_STATUS)
  29. #define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) RTLP_HRESULT_FROM_STATUS(x)
  30. #else
  31. #define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosErrorNoTeb(x))
  32. //#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosError(x))
  33. //#define RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(x) HRESULT_FROM_NT(x)
  34. #endif
  35. #endif
  36. const static RTL_STREAM_VTABLE_TEMPLATE(RTL_MEMORY_STREAM_WITH_VTABLE)
  37. MemoryStreamVTable =
  38. {
  39. RtlQueryInterfaceMemoryStream,
  40. RtlAddRefMemoryStream,
  41. RtlReleaseMemoryStream,
  42. RtlReadMemoryStream,
  43. RtlWriteMemoryStream,
  44. RtlSeekMemoryStream,
  45. RtlSetMemoryStreamSize,
  46. RtlCopyMemoryStreamTo,
  47. RtlCommitMemoryStream,
  48. RtlRevertMemoryStream,
  49. RtlLockMemoryStreamRegion,
  50. RtlUnlockMemoryStreamRegion,
  51. RtlStatMemoryStream,
  52. RtlCloneMemoryStream
  53. };
  54. const static RTL_STREAM_VTABLE_TEMPLATE(RTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE)
  55. OutOfProcessMemoryStreamVTable =
  56. {
  57. RtlQueryInterfaceOutOfProcessMemoryStream,
  58. RtlAddRefOutOfProcessMemoryStream,
  59. RtlReleaseOutOfProcessMemoryStream,
  60. RtlReadOutOfProcessMemoryStream,
  61. RtlWriteOutOfProcessMemoryStream,
  62. RtlSeekOutOfProcessMemoryStream,
  63. RtlSetOutOfProcessMemoryStreamSize,
  64. RtlCopyOutOfProcessMemoryStreamTo,
  65. RtlCommitOutOfProcessMemoryStream,
  66. RtlRevertOutOfProcessMemoryStream,
  67. RtlLockOutOfProcessMemoryStreamRegion,
  68. RtlUnlockOutOfProcessMemoryStreamRegion,
  69. RtlStatOutOfProcessMemoryStream,
  70. RtlCloneOutOfProcessMemoryStream
  71. };
  72. VOID
  73. STDMETHODCALLTYPE
  74. RtlInitOutOfProcessMemoryStream(
  75. PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream
  76. )
  77. {
  78. ASSERT(MemoryStream != NULL);
  79. RtlZeroMemory(&MemoryStream->Data, sizeof(MemoryStream->Data));
  80. MemoryStream->Data.FinalRelease = RtlFinalReleaseOutOfProcessMemoryStream;
  81. MemoryStream->StreamVTable = (const IStreamVtbl*)&OutOfProcessMemoryStreamVTable;
  82. }
  83. VOID
  84. STDMETHODCALLTYPE
  85. RtlFinalReleaseOutOfProcessMemoryStream(
  86. PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream
  87. )
  88. {
  89. NTSTATUS Status = STATUS_SUCCESS;
  90. ASSERT(MemoryStream != NULL);
  91. if (MemoryStream->Data.Process != NULL) {
  92. Status = NtClose(MemoryStream->Data.Process);
  93. RTL_SOFT_ASSERT(NT_SUCCESS(Status));
  94. MemoryStream->Data.Process = NULL;
  95. }
  96. }
  97. VOID
  98. STDMETHODCALLTYPE
  99. RtlInitMemoryStream(
  100. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream
  101. )
  102. {
  103. ASSERT(MemoryStream != NULL);
  104. RtlZeroMemory(&MemoryStream->Data, sizeof(MemoryStream->Data));
  105. MemoryStream->StreamVTable = (const IStreamVtbl*)&MemoryStreamVTable;
  106. }
  107. ULONG
  108. STDMETHODCALLTYPE
  109. RtlAddRefMemoryStream(
  110. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream
  111. )
  112. {
  113. LONG ReferenceCount;
  114. ASSERT(MemoryStream != NULL);
  115. ReferenceCount = InterlockedIncrement(&MemoryStream->Data.ReferenceCount);
  116. return ReferenceCount;
  117. }
  118. ULONG
  119. STDMETHODCALLTYPE
  120. RtlReleaseMemoryStream(
  121. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream
  122. )
  123. {
  124. LONG ReferenceCount;
  125. ASSERT(MemoryStream != NULL);
  126. ReferenceCount = InterlockedDecrement(&MemoryStream->Data.ReferenceCount);
  127. if (ReferenceCount == 0 && MemoryStream->Data.FinalRelease != NULL) {
  128. MemoryStream->Data.FinalRelease(MemoryStream);
  129. }
  130. return ReferenceCount;
  131. }
  132. HRESULT
  133. STDMETHODCALLTYPE
  134. RtlQueryInterfaceMemoryStream(
  135. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  136. const IID* Interface,
  137. PVOID* Object
  138. )
  139. {
  140. ASSERT(MemoryStream != NULL);
  141. ASSERT(Interface != NULL);
  142. ASSERT(Object != NULL);
  143. if (IsEqualGUID(Interface, &IID_IUnknown)
  144. || IsEqualGUID(Interface, &IID_IStream)
  145. || IsEqualGUID(Interface, &IID_ISequentialStream)
  146. )
  147. {
  148. InterlockedIncrement(&MemoryStream->Data.ReferenceCount);
  149. *Object = (IStream*)(&MemoryStream->StreamVTable);
  150. return NOERROR;
  151. }
  152. return E_NOINTERFACE;
  153. }
  154. HRESULT
  155. STDMETHODCALLTYPE
  156. RtlReadOutOfProcessMemoryStream(
  157. PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  158. PVOID Buffer,
  159. ULONG BytesToRead,
  160. ULONG* BytesRead
  161. )
  162. {
  163. NTSTATUS Status = STATUS_SUCCESS;
  164. HRESULT Hr = NOERROR;
  165. const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current);
  166. SIZE_T NumberOfBytesReadSizeT = 0;
  167. ASSERT(MemoryStream != NULL);
  168. if (BytesRemaining < BytesToRead) {
  169. BytesToRead = (ULONG)BytesRemaining;
  170. }
  171. Status = NtReadVirtualMemory(
  172. MemoryStream->Data.Process,
  173. MemoryStream->Data.Current,
  174. Buffer,
  175. BytesToRead,
  176. &NumberOfBytesReadSizeT);
  177. if (Status == STATUS_PARTIAL_COPY) {
  178. Status = STATUS_SUCCESS;
  179. }
  180. if (!NT_SUCCESS(Status)) {
  181. Hr = RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(Status);
  182. goto Exit;
  183. }
  184. MemoryStream->Data.Current += NumberOfBytesReadSizeT;
  185. *BytesRead = (ULONG)NumberOfBytesReadSizeT;
  186. Exit:
  187. return Hr;
  188. }
  189. HRESULT
  190. STDMETHODCALLTYPE
  191. RtlReadMemoryStream(
  192. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  193. PVOID Buffer,
  194. ULONG BytesToRead,
  195. ULONG* BytesRead
  196. )
  197. {
  198. EXCEPTION_RECORD ExceptionRecord;
  199. HRESULT Hr = NOERROR;
  200. NTSTATUS Status = STATUS_SUCCESS;
  201. const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current);
  202. // this is so the compiler doesn't give a bogus warning about using
  203. // an uninitialized local
  204. ExceptionRecord.ExceptionCode = 0;
  205. ExceptionRecord.NumberParameters = 0;
  206. ExceptionRecord.ExceptionInformation[RTL_IN_PAGE_ERROR_EXCEPTION_INFO_UNDERLYING_STATUS_INDEX] = 0;
  207. ASSERT(MemoryStream != NULL);
  208. ASSERT(MemoryStream->Data.End >= MemoryStream->Data.Current);
  209. if (BytesRemaining < BytesToRead) {
  210. BytesToRead = (ULONG)BytesRemaining;
  211. }
  212. Status = RtlCopyMappedMemory(Buffer, MemoryStream->Data.Current, BytesToRead);
  213. //
  214. // We could find how many bytes were successfully copied and return STATUS_PARTIAL_COPY,
  215. // but it does not seem worthwhile.
  216. //
  217. if (NT_SUCCESS(Status)) {
  218. MemoryStream->Data.Current += BytesToRead;
  219. *BytesRead = BytesToRead;
  220. } else {
  221. Hr = RTLP_MEMORY_STREAM_HRESULT_FROM_STATUS(Status);
  222. *BytesRead = 0;
  223. }
  224. return Hr;
  225. }
  226. HRESULT
  227. STDMETHODCALLTYPE
  228. RtlWriteMemoryStream(
  229. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  230. const VOID* Buffer,
  231. ULONG BytesToWrite,
  232. ULONG* BytesWritten
  233. )
  234. {
  235. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  236. UNREFERENCED_PARAMETER (Buffer);
  237. UNREFERENCED_PARAMETER (BytesToWrite);
  238. UNREFERENCED_PARAMETER (BytesWritten);
  239. RTLP_MEMORY_STREAM_NOT_IMPL(Write);
  240. }
  241. HRESULT
  242. STDMETHODCALLTYPE
  243. RtlSeekMemoryStream(
  244. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  245. LARGE_INTEGER Distance,
  246. DWORD Origin,
  247. ULARGE_INTEGER* NewPosition
  248. )
  249. {
  250. HRESULT Hr = NOERROR;
  251. PUCHAR NewPointer;
  252. ASSERT(MemoryStream != NULL);
  253. //
  254. // "It is not, however, an error to seek past the end of the stream.
  255. // Seeking past the end of the stream is useful for subsequent write
  256. // operations, as the stream will at that time be extended to the seek
  257. // position immediately before the write is done."
  258. //
  259. // As long as we don't allow writing, we are not going to allow this.
  260. //
  261. switch (Origin) {
  262. case STREAM_SEEK_SET:
  263. NewPointer = MemoryStream->Data.Begin + Distance.QuadPart;
  264. break;
  265. case STREAM_SEEK_CUR:
  266. NewPointer = MemoryStream->Data.Current + Distance.QuadPart;
  267. break;
  268. case STREAM_SEEK_END:
  269. NewPointer = MemoryStream->Data.End - Distance.QuadPart;
  270. break;
  271. default:
  272. Hr = STG_E_INVALIDFUNCTION;
  273. goto Exit;
  274. }
  275. if (NewPointer < MemoryStream->Data.Begin || NewPointer > MemoryStream->Data.End) {
  276. Hr = STG_E_INVALIDPOINTER;
  277. goto Exit;
  278. }
  279. MemoryStream->Data.Current = NewPointer;
  280. NewPosition->QuadPart = NewPointer - MemoryStream->Data.Begin;
  281. Hr = NOERROR;
  282. Exit:
  283. return Hr;
  284. }
  285. HRESULT
  286. STDMETHODCALLTYPE
  287. RtlSetMemoryStreamSize(
  288. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  289. ULARGE_INTEGER NewSize
  290. )
  291. {
  292. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  293. UNREFERENCED_PARAMETER (NewSize);
  294. RTLP_MEMORY_STREAM_NOT_IMPL(SetSize);
  295. }
  296. HRESULT
  297. STDMETHODCALLTYPE
  298. RtlCopyOutOfProcessMemoryStreamTo(
  299. PRTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  300. IStream* AnotherStream,
  301. ULARGE_INTEGER NumberOfBytesToCopyLargeInteger,
  302. ULARGE_INTEGER* NumberOfBytesRead,
  303. ULARGE_INTEGER* NumberOfBytesWrittenLargeInteger
  304. )
  305. {
  306. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  307. UNREFERENCED_PARAMETER (AnotherStream);
  308. UNREFERENCED_PARAMETER (NumberOfBytesToCopyLargeInteger);
  309. UNREFERENCED_PARAMETER (NumberOfBytesRead);
  310. UNREFERENCED_PARAMETER (NumberOfBytesWrittenLargeInteger);
  311. RTLP_MEMORY_STREAM_NOT_IMPL(CopyTo);
  312. }
  313. HRESULT
  314. STDMETHODCALLTYPE
  315. RtlCopyMemoryStreamTo(
  316. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  317. IStream* AnotherStream,
  318. ULARGE_INTEGER NumberOfBytesToCopyLargeInteger,
  319. ULARGE_INTEGER* NumberOfBytesRead,
  320. ULARGE_INTEGER* NumberOfBytesWrittenLargeInteger
  321. )
  322. {
  323. HRESULT Hr = NOERROR;
  324. ULONG NumberOfBytesToCopyUlong = 0;
  325. ULONG NumberOfBytesWrittenUlong = 0;
  326. const SIZE_T BytesRemaining = (MemoryStream->Data.End - MemoryStream->Data.Current);
  327. ASSERT(MemoryStream != NULL);
  328. if (NumberOfBytesToCopyLargeInteger.HighPart != 0) {
  329. NumberOfBytesToCopyUlong = MAXULONG;
  330. } else {
  331. NumberOfBytesToCopyUlong = (ULONG)NumberOfBytesToCopyLargeInteger.QuadPart;
  332. }
  333. if (BytesRemaining < NumberOfBytesToCopyUlong) {
  334. NumberOfBytesToCopyUlong = (ULONG)BytesRemaining;
  335. }
  336. Hr = AnotherStream->lpVtbl->Write(AnotherStream, MemoryStream->Data.Current, NumberOfBytesToCopyUlong, &NumberOfBytesWrittenUlong);
  337. if (FAILED(Hr)) {
  338. NumberOfBytesRead->QuadPart = 0;
  339. NumberOfBytesWrittenLargeInteger->QuadPart = 0;
  340. } else {
  341. NumberOfBytesRead->QuadPart = NumberOfBytesWrittenUlong;
  342. NumberOfBytesWrittenLargeInteger->QuadPart = NumberOfBytesWrittenUlong;
  343. }
  344. Hr = NOERROR;
  345. return Hr;
  346. }
  347. HRESULT
  348. STDMETHODCALLTYPE
  349. RtlCommitMemoryStream(
  350. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  351. ULONG Flags
  352. )
  353. {
  354. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  355. UNREFERENCED_PARAMETER (Flags);
  356. RTLP_MEMORY_STREAM_NOT_IMPL(Commit);
  357. }
  358. HRESULT
  359. STDMETHODCALLTYPE
  360. RtlRevertMemoryStream(
  361. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream
  362. )
  363. {
  364. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  365. RTLP_MEMORY_STREAM_NOT_IMPL(Revert);
  366. }
  367. HRESULT
  368. STDMETHODCALLTYPE
  369. RtlLockMemoryStreamRegion(
  370. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  371. ULARGE_INTEGER Offset,
  372. ULARGE_INTEGER NumberOfBytes,
  373. ULONG LockType
  374. )
  375. {
  376. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  377. UNREFERENCED_PARAMETER (Offset);
  378. UNREFERENCED_PARAMETER (NumberOfBytes);
  379. UNREFERENCED_PARAMETER (LockType);
  380. RTLP_MEMORY_STREAM_NOT_IMPL(LockRegion);
  381. }
  382. HRESULT
  383. STDMETHODCALLTYPE
  384. RtlUnlockMemoryStreamRegion(
  385. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  386. ULARGE_INTEGER Offset,
  387. ULARGE_INTEGER NumberOfBytes,
  388. ULONG LockType
  389. )
  390. {
  391. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  392. UNREFERENCED_PARAMETER (Offset);
  393. UNREFERENCED_PARAMETER (NumberOfBytes);
  394. UNREFERENCED_PARAMETER (LockType);
  395. RTLP_MEMORY_STREAM_NOT_IMPL(UnlockRegion);
  396. }
  397. HRESULT
  398. STDMETHODCALLTYPE
  399. RtlStatMemoryStream(
  400. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  401. STATSTG* StatusInformation,
  402. ULONG Flags
  403. )
  404. {
  405. HRESULT hr = NOERROR;
  406. ASSERT(MemoryStream != NULL);
  407. if (StatusInformation == NULL) {
  408. hr = STG_E_INVALIDPOINTER;
  409. goto Exit;
  410. }
  411. if (Flags != STATFLAG_NONAME) {
  412. hr = STG_E_INVALIDFLAG;
  413. goto Exit;
  414. }
  415. //
  416. // This struct is defined in objidl.h.
  417. //
  418. StatusInformation->pwcsName = NULL;
  419. StatusInformation->type = STGTY_STREAM;
  420. StatusInformation->cbSize.QuadPart = ((ULONG_PTR) MemoryStream->Data.End) - ((ULONG_PTR) MemoryStream->Data.Begin);
  421. StatusInformation->mtime.dwLowDateTime = 0;
  422. StatusInformation->mtime.dwHighDateTime = 0;
  423. StatusInformation->ctime.dwLowDateTime = 0;
  424. StatusInformation->ctime.dwHighDateTime = 0;
  425. StatusInformation->atime.dwLowDateTime = 0;
  426. StatusInformation->atime.dwHighDateTime = 0;
  427. StatusInformation->grfMode = STGM_READ;
  428. StatusInformation->grfLocksSupported = 0;
  429. StatusInformation->clsid = CLSID_NULL;
  430. StatusInformation->grfStateBits = 0;
  431. StatusInformation->reserved = 0;
  432. hr = NOERROR;
  433. Exit:
  434. return hr;
  435. }
  436. HRESULT
  437. STDMETHODCALLTYPE
  438. RtlCloneMemoryStream(
  439. PRTL_MEMORY_STREAM_WITH_VTABLE MemoryStream,
  440. IStream** NewStream
  441. )
  442. {
  443. UNREFERENCED_PARAMETER (MemoryStream); // on free builds
  444. UNREFERENCED_PARAMETER (NewStream);
  445. RTLP_MEMORY_STREAM_NOT_IMPL(Clone);
  446. }