Source code of Windows XP (NT5)
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.

501 lines
14 KiB

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