[EXPLORER] -Use WM_POPUPSYSTEMMENU to open the system menu of a window. CORE-13400
[reactos.git] / rostests / apitests / ntdll / RtlMemoryStream.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for the Rtl*MemoryStream* series of functions
5 * PROGRAMMER: David Quintana <gigaherz@gmail.com>
6 */
7
8 #define COBJMACROS
9
10 #include <apitest.h>
11 #include <ndk/rtlfuncs.h>
12 #include <ole2.h>
13 #include <wtypes.h>
14
15 ULONG finalReleaseCallCount = 0;
16
17 VOID
18 NTAPI
19 CustomFinalReleaseMemoryStream(PRTL_MEMORY_STREAM stream)
20 {
21 finalReleaseCallCount++;
22 trace("FinalRelease CALLED.\n");
23 }
24
25 VOID
26 NTAPI
27 CustomFinalReleaseOutOfProcessMemoryStream(PRTL_MEMORY_STREAM stream)
28 {
29 finalReleaseCallCount++;
30 trace("FinalRelease CALLED.\n");
31 RtlFinalReleaseOutOfProcessMemoryStream(stream);
32 }
33
34 BOOL CompareStructsAndSaveForLater(PRTL_MEMORY_STREAM pold, PRTL_MEMORY_STREAM pnew, PSTR at)
35 {
36 BOOL equal = TRUE;
37
38 // Compare
39 if (pold->Vtbl != pnew->Vtbl) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("Vtbl changed from %p to %p\n", pold->Vtbl, pnew->Vtbl);}
40 if (pold->RefCount != pnew->RefCount) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("RefCount changed from %ld to %ld\n", pold->RefCount, pnew->RefCount); }
41 if (pold->Unk1 != pnew->Unk1) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("Unk1 changed from %lu to %lu\n", pold->Unk1, pnew->Unk1); }
42 if (pold->Current != pnew->Current) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("Current changed from %p to %p\n", pold->Current, pnew->Current); }
43 if (pold->Start != pnew->Start) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("Start changed from %p to %p\n", pold->Start, pnew->Start); }
44 if (pold->End != pnew->End) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("End changed from %p to %p\n", pold->End, pnew->End); }
45 if (pold->FinalRelease != pnew->FinalRelease) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("FinalRelease changed from %p to %p\n", pold->FinalRelease, pnew->FinalRelease); }
46 if (pold->ProcessHandle != pnew->ProcessHandle) { if (equal) { trace("%s: \n", at); equal = FALSE; } trace("ProcessHandle changed from %p to %p\n", pold->ProcessHandle, pnew->ProcessHandle); }
47
48 // Save
49 pold->Vtbl = pnew->Vtbl;
50 pold->RefCount = pnew->RefCount;
51 pold->Unk1 = pnew->Unk1;
52 pold->Current = pnew->Current;
53 pold->Start = pnew->Start;
54 pold->End = pnew->End;
55 pold->FinalRelease = pnew->FinalRelease;
56 pold->ProcessHandle = pnew->ProcessHandle;
57
58 return equal;
59 }
60
61 void test_InProcess()
62 {
63 LARGE_INTEGER move;
64 ULARGE_INTEGER size;
65 HRESULT res;
66 ULONG i;
67
68 RTL_MEMORY_STREAM stream;
69 RTL_MEMORY_STREAM previous;
70
71 IStream * istream;
72
73 UCHAR buffer[80];
74 UCHAR buffer2[180];
75 ULONG bytesRead;
76
77 STATSTG stat;
78
79 finalReleaseCallCount = 0;
80
81 for (i = 0; i < sizeof(buffer2); i++)
82 {
83 buffer2[i] = i % UCHAR_MAX;
84 }
85
86 memset(&stream, 0x90, sizeof(stream));
87 memset(&previous, 0x00, sizeof(previous));
88
89 StartSeh()
90 RtlInitMemoryStream(NULL);
91 EndSeh(STATUS_ACCESS_VIOLATION);
92
93 StartSeh()
94 RtlInitMemoryStream(&stream);
95 EndSeh(STATUS_SUCCESS);
96
97 CompareStructsAndSaveForLater(&previous, &stream, "After init");
98
99 ok(stream.RefCount == 0, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 0);
100
101 stream.Current = buffer2;
102 stream.Start = buffer2;
103 stream.End = buffer2 + sizeof(buffer2);
104 stream.FinalRelease = CustomFinalReleaseMemoryStream;
105
106 CompareStructsAndSaveForLater(&previous, &stream, "After assigning");
107
108 StartSeh()
109 IStream_QueryInterface((struct IStream*)&stream, NULL, NULL);
110 EndSeh(STATUS_ACCESS_VIOLATION);
111
112 StartSeh()
113 IStream_QueryInterface((struct IStream*)&stream, &IID_IStream, NULL);
114 EndSeh(STATUS_ACCESS_VIOLATION);
115
116 StartSeh()
117 IStream_QueryInterface((struct IStream*)&stream, NULL, (void**)&istream);
118 EndSeh(STATUS_ACCESS_VIOLATION);
119
120 StartSeh()
121 res = IStream_QueryInterface((struct IStream*)&stream, &IID_IStream, (void**)&istream);
122 ok(res == S_OK, "QueryInterface to IStream returned wrong hResult: 0x%08lx.\n", res);
123 ok(stream.RefCount == 2, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 2);
124 EndSeh(STATUS_SUCCESS);
125
126 CompareStructsAndSaveForLater(&previous, &stream, "After QueryInterface");
127
128 StartSeh()
129 res = IStream_Stat(istream, NULL, 0);
130 ok(res == STG_E_INVALIDPOINTER, "Stat to IStream returned wrong hResult: 0x%08lx.\n", res);
131 EndSeh(STATUS_SUCCESS);
132
133 StartSeh()
134 res = IStream_Stat(istream, &stat, STATFLAG_NONAME);
135 ok(res == S_OK, "Stat to IStream returned wrong hResult: 0x%08lx.\n", res);
136 EndSeh(STATUS_SUCCESS);
137
138 ok(stream.Current == buffer2,
139 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
140 stream.Current, buffer2);
141 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
142 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
143
144 ok(stat.cbSize.QuadPart == ((PUCHAR)stream.End - (PUCHAR)stream.Start),
145 "stat.cbSize has the wrong value %I64u (expected %d)\n",
146 stat.cbSize.QuadPart, (PUCHAR)stream.End - (PUCHAR)stream.Start);
147
148 CompareStructsAndSaveForLater(&previous, &stream, "After Stat");
149
150 StartSeh()
151 res = IStream_AddRef(istream);
152 ok(res == 3, "AddRef to IStream returned wrong hResult: %ld.\n", res);
153 EndSeh(STATUS_SUCCESS);
154
155 StartSeh()
156 res = IStream_AddRef(istream);
157 ok(res == 4, "AddRef to IStream returned wrong hResult: %ld.\n", res);
158 EndSeh(STATUS_SUCCESS);
159
160 StartSeh()
161 res = IStream_Release(istream);
162 ok(res == 3, "Release to IStream returned wrong hResult: %ld.\n", res);
163 EndSeh(STATUS_SUCCESS);
164
165 StartSeh()
166 res = IStream_AddRef(istream);
167 ok(res == 4, "AddRef to IStream returned wrong hResult: %ld.\n", res);
168 EndSeh(STATUS_SUCCESS);
169
170 StartSeh()
171 res = IStream_Release(istream);
172 ok(res == 3, "Release to IStream returned wrong hResult: %ld.\n", res);
173 EndSeh(STATUS_SUCCESS);
174
175 StartSeh()
176 res = IStream_Release(istream);
177 ok(res == 2, "Release to IStream returned wrong hResult: %ld.\n", res);
178 EndSeh(STATUS_SUCCESS);
179
180 CompareStructsAndSaveForLater(&previous, &stream, "After AddRef");
181
182 StartSeh()
183 res = IStream_Read(istream, NULL, 0, &bytesRead);
184 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
185 EndSeh(STATUS_SUCCESS);
186
187 StartSeh()
188 res = IStream_Read(istream, buffer, 40, NULL);
189 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
190 EndSeh(STATUS_ACCESS_VIOLATION);
191
192 StartSeh()
193 res = IStream_Read(istream, buffer + 40, 39, &bytesRead);
194 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
195 EndSeh(STATUS_SUCCESS);
196
197 if (SUCCEEDED(res))
198 {
199 bytesRead += 40;
200 for (i = 0; i < bytesRead; i++)
201 {
202 ok(buffer[i] == i, "Buffer[%lu] contains a wrong number %u (expected %lu).\n", i, buffer[i], i);
203 }
204 }
205
206 ok(stream.Current == buffer2 + 79,
207 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
208 stream.Current, buffer2);
209 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
210 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
211
212 CompareStructsAndSaveForLater(&previous, &stream, "After Read 1");
213
214 size.QuadPart = 0x9090909090909090ull;
215
216 StartSeh()
217 move.QuadPart = -1;
218 res = IStream_Seek(istream, move, STREAM_SEEK_END, &size);
219 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
220 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error (0x%08lx,0x%08lx).\n", size.HighPart, size.LowPart);
221 EndSeh(STATUS_SUCCESS);
222
223 StartSeh()
224 move.QuadPart = 0;
225 res = IStream_Seek(istream, move, STREAM_SEEK_END, &size);
226 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
227 ok(size.QuadPart == (PUCHAR)stream.End - (PUCHAR)stream.Start, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
228 EndSeh(STATUS_SUCCESS);
229
230 size.QuadPart = 0x9090909090909090ull;
231
232 StartSeh()
233 move.QuadPart = 1;
234 res = IStream_Seek(istream, move, STREAM_SEEK_END, &size);
235 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
236 ok(size.QuadPart == (PUCHAR)stream.End - (PUCHAR)stream.Start - 1, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
237 EndSeh(STATUS_SUCCESS);
238
239 size.QuadPart = 0x9090909090909090ull;
240
241 StartSeh()
242 move.QuadPart = 2;
243 res = IStream_Seek(istream, move, STREAM_SEEK_END, &size);
244 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
245 ok(size.QuadPart == (PUCHAR)stream.End - (PUCHAR)stream.Start - 2, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
246 EndSeh(STATUS_SUCCESS);
247
248 size.QuadPart = 0x9090909090909090ull;
249
250 StartSeh()
251 move.QuadPart = -20;
252 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
253 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
254 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error.\n");
255 EndSeh(STATUS_SUCCESS);
256
257 StartSeh()
258 move.QuadPart = 4000;
259 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
260 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
261 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error.\n");
262 EndSeh(STATUS_SUCCESS);
263
264 StartSeh()
265 move.QuadPart = 0x100000000ull;
266 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
267 #ifdef _WIN64
268 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
269 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error (0x%08lx,0x%08lx).\n", size.HighPart, size.LowPart);
270 #else
271 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
272 ok(size.QuadPart == 0, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
273 #endif
274 EndSeh(STATUS_SUCCESS);
275
276 #ifdef _WIN64
277 StartSeh()
278 move.QuadPart = 0;
279 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
280 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
281 ok(size.QuadPart == 0, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
282 EndSeh(STATUS_SUCCESS);
283 #endif
284
285 size.QuadPart = 0x9090909090909090ull;
286
287 StartSeh()
288 move.QuadPart = -20;
289 res = IStream_Seek(istream, move, STREAM_SEEK_CUR, &size);
290 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
291 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error (0x%08lx,0x%08lx).\n", size.HighPart, size.LowPart);
292 EndSeh(STATUS_SUCCESS);
293
294 StartSeh()
295 move.QuadPart = 0x100000000ull;
296 res = IStream_Seek(istream, move, STREAM_SEEK_CUR, &size);
297 #ifdef _WIN64
298 ok(res == STG_E_INVALIDPOINTER, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
299 ok(size.QuadPart == 0x9090909090909090ull, "Seek modified the new location in an error (0x%08lx,0x%08lx).\n", size.HighPart, size.LowPart);
300 #else
301 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
302 ok(size.QuadPart == 0, "Seek new location unexpected value: 0x%08lx.\n", size.LowPart);
303 #endif
304 EndSeh(STATUS_SUCCESS);
305
306 StartSeh()
307 move.QuadPart = 40;
308 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
309 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
310 EndSeh(STATUS_SUCCESS);
311
312 ok(size.QuadPart == 40,
313 "Seek returned wrong offset %I64u (expected %d)\n",
314 size.QuadPart, 40);
315
316 ok(stream.Current == buffer2 + 40,
317 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
318 stream.Current, buffer2);
319 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
320 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
321
322 CompareStructsAndSaveForLater(&previous, &stream, "After Seek");
323
324 res = IStream_Read(istream, buffer, sizeof(buffer), &bytesRead);
325
326 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
327
328 if (SUCCEEDED(res))
329 {
330 for (i = 0; i < bytesRead; i++)
331 {
332 ok(buffer[i] == (i + 40), "Buffer[%lu] contains a wrong number %u (expected %lu).\n", i, buffer[i], i + 40);
333 }
334 }
335
336 ok(stream.Current == buffer2 + 40 + sizeof(buffer),
337 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
338 stream.Current, buffer2);
339 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
340 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
341
342 CompareStructsAndSaveForLater(&previous, &stream, "After Read 2");
343
344 res = IStream_Release(istream);
345
346 ok(res == 1, "Release to IStream returned wrong hResult: 0x%08lx.\n", res);
347
348 ok(stream.RefCount == 1, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 1);
349
350 res = IStream_Release(istream);
351
352 ok(res == S_OK, "Release to IStream returned wrong hResult: 0x%08lx.\n", res);
353
354 ok(stream.RefCount == 0, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 0);
355
356 ok(finalReleaseCallCount == 1, "FinalRelease was called %lu times instead of 1.\n", finalReleaseCallCount);
357 }
358
359 void test_OutOfProcess()
360 {
361 LARGE_INTEGER move;
362 ULARGE_INTEGER size;
363 HRESULT res;
364 HANDLE process;
365 ULONG i;
366
367 RTL_MEMORY_STREAM stream;
368 RTL_MEMORY_STREAM previous;
369
370 IStream * istream;
371
372 UCHAR buffer[80];
373 UCHAR buffer2[180];
374 ULONG bytesRead;
375
376 STATSTG stat;
377
378 finalReleaseCallCount = 0;
379
380 for (i = 0; i < sizeof(buffer2); i++)
381 {
382 buffer2[i] = i % UCHAR_MAX;
383 }
384
385 memset(&stream, 0x90, sizeof(stream));
386 memset(&previous, 0x00, sizeof(previous));
387
388 process = GetCurrentProcess();
389
390 RtlInitOutOfProcessMemoryStream(&stream);
391
392 ok(stream.FinalRelease == RtlFinalReleaseOutOfProcessMemoryStream,
393 "stream.FinalRelease unexpected %p != %p.\n",
394 stream.FinalRelease, RtlFinalReleaseOutOfProcessMemoryStream);
395
396 ok(stream.RefCount == 0, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 0);
397
398 CompareStructsAndSaveForLater(&previous, &stream, "After init");
399
400 stream.Current = buffer2;
401 stream.Start = buffer2;
402 stream.End = buffer2 + sizeof(buffer2);
403 stream.ProcessHandle = process;
404 stream.FinalRelease = CustomFinalReleaseOutOfProcessMemoryStream;
405
406 CompareStructsAndSaveForLater(&previous, &stream, "After assigning");
407
408 res = IStream_QueryInterface((struct IStream*)&stream, &IID_IStream, (void**)&istream);
409
410 ok(res == S_OK, "QueryInterface to IStream returned wrong hResult: 0x%08lx.\n", res);
411
412 ok(stream.RefCount == 1, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 1);
413
414 ok(stream.ProcessHandle == process,
415 "ProcessHandle changed unexpectedly: 0x%p (expected 0x%p)\n",
416 stream.ProcessHandle, process);
417
418 CompareStructsAndSaveForLater(&previous, &stream, "After QueryInterface");
419
420 res = IStream_Stat(istream, &stat, STATFLAG_NONAME);
421
422 ok(res == S_OK, "Stat to IStream returned wrong hResult: 0x%08lx.\n", res);
423
424 ok(stream.Current == buffer2,
425 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
426 stream.Current, buffer2);
427 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
428 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
429 ok(stream.ProcessHandle == process,
430 "ProcessHandle changed unexpectedly: 0x%p (expected 0x%p)\n",
431 stream.ProcessHandle, process);
432
433 ok(stat.cbSize.QuadPart == ((PUCHAR)stream.End - (PUCHAR)stream.Start),
434 "stat.cbSize has the wrong value %I64u (expected %d)\n",
435 stat.cbSize.QuadPart, (PUCHAR)stream.End - (PUCHAR)stream.Start);
436
437 CompareStructsAndSaveForLater(&previous, &stream, "After Stat");
438
439 res = IStream_Read(istream, buffer, sizeof(buffer), &bytesRead);
440
441 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
442
443 if (SUCCEEDED(res))
444 {
445 for (i = 0; i < bytesRead; i++)
446 {
447 ok(buffer[i] == i, "Buffer[%lu] contains a wrong number %u (expected %lu).\n", i, buffer[i], i);
448 }
449 }
450
451 ok(stream.Current == buffer2 + sizeof(buffer),
452 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
453 stream.Current, buffer2);
454 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
455 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
456 ok(stream.ProcessHandle == process,
457 "ProcessHandle changed unexpectedly: 0x%p (expected 0x%p)\n",
458 stream.ProcessHandle, process);
459
460 CompareStructsAndSaveForLater(&previous, &stream, "After Read 1");
461
462 move.QuadPart = 40;
463
464 res = IStream_Seek(istream, move, STREAM_SEEK_SET, &size);
465
466 ok(res == S_OK, "Seek to IStream returned wrong hResult: 0x%08lx.\n", res);
467
468 ok(size.QuadPart == 40,
469 "Seek returned wrong offset %I64u (expected %d)\n",
470 size.QuadPart, 40);
471
472 ok(stream.Current == buffer2 + 40,
473 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
474 stream.Current, buffer2);
475 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
476 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
477 ok(stream.ProcessHandle == process,
478 "ProcessHandle changed unexpectedly: 0x%p (expected 0x%p)\n",
479 stream.ProcessHandle, process);
480
481 CompareStructsAndSaveForLater(&previous, &stream, "After Seek");
482
483 res = IStream_Read(istream, buffer, sizeof(buffer), &bytesRead);
484
485 ok(res == S_OK, "Read to IStream returned wrong hResult: 0x%08lx.\n", res);
486
487 if (SUCCEEDED(res))
488 {
489 for (i = 0; i < bytesRead; i++)
490 {
491 ok(buffer[i] == (i + 40), "Buffer[%lu] contains a wrong number %u (expected %lu).\n", i, buffer[i], i + 40);
492 }
493 }
494
495 ok(stream.Current == buffer2 + 40 + sizeof(buffer),
496 "stream.Current points to the wrong address 0x%p (expected 0x%p)\n",
497 stream.Current, buffer2);
498 ok(stream.Start == buffer2, "stream.Start was changed unexpectedly\n");
499 ok(stream.End == buffer2 + sizeof(buffer2), "stream.End was changed unexpectedly\n");
500 ok(stream.ProcessHandle == process,
501 "ProcessHandle changed unexpectedly: 0x%p (expected 0x%p)\n",
502 stream.ProcessHandle, process);
503
504 CompareStructsAndSaveForLater(&previous, &stream, "After Read 2");
505
506 res = IStream_Release(istream);
507
508 ok(res == S_OK, "Release to IStream returned wrong hResult: 0x%08lx.\n", res);
509
510 ok(stream.RefCount == 0, "RefCount has a wrong value: %ld (expected %d).\n", stream.RefCount, 0);
511
512 ok(finalReleaseCallCount == 1, "FinalRelease was called %lu times instead of 1.\n", finalReleaseCallCount);
513 }
514
515 START_TEST(RtlMemoryStream)
516 {
517 test_InProcess();
518 test_OutOfProcess();
519 }