1 /*
2  * Copyright 2009 Tony Wasserka
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "precomp.h"
20 
21 static void test_StreamOnMemory(void)
22 {
23     IWICImagingFactory *pFactory;
24     IWICStream *pStream, *pBufStream;
25     const BYTE CmpMem[] = {
26         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
27         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
28         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
29         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
30     };
31     const BYTE CmpMemOverlap[] = {
32         0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
33         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
34         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
35         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
36     };
37     const BYTE ZeroMem[10] = {0};
38     BYTE Memory[64], MemBuf[64];
39     LARGE_INTEGER LargeNull, LargeInt, SeekPos;
40     ULARGE_INTEGER uLargeNull, uNewPos;
41     ULONG uBytesRead, uBytesWritten;
42     HRESULT hr;
43     STATSTG Stats;
44 
45     LargeNull.QuadPart = 0;
46     uLargeNull.QuadPart = 0;
47     SeekPos.QuadPart = 5;
48 
49     memcpy(Memory, CmpMem, sizeof(CmpMem));
50 
51     CoInitialize(NULL);
52 
53     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&pFactory);
54     if(FAILED(hr)) {
55         skip("CoCreateInstance returned with %#x, expected %#x\n", hr, S_OK);
56         return;
57     }
58 
59     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
60     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
61     if(FAILED(hr)) {
62         skip("Failed to create stream\n");
63         return;
64     }
65 
66     /* InitializeFromMemory */
67     hr = IWICStream_InitializeFromMemory(pStream, NULL, sizeof(Memory));   /* memory = NULL */
68     ok(hr == E_INVALIDARG, "InitializeFromMemory returned with %#x, expected %#x\n", hr, E_INVALIDARG);
69 
70     hr = IWICStream_InitializeFromMemory(pStream, Memory, 0);   /* size = 0 */
71     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
72 
73     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));   /* stream already initialized */
74     ok(hr == WINCODEC_ERR_WRONGSTATE, "InitializeFromMemory returned with %#x, expected %#x\n", hr, WINCODEC_ERR_WRONGSTATE);
75 
76     /* recreate stream */
77     IWICStream_Release(pStream);
78     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
79     ok(hr == S_OK, "CreateStream failed with %#x\n", hr);
80 
81     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));
82     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
83 
84     /* IWICStream does not maintain an independent copy of the backing memory buffer. */
85     memcpy(Memory, ZeroMem, sizeof(ZeroMem));
86     hr = IWICStream_Read(pStream, MemBuf, sizeof(ZeroMem), &uBytesRead);
87     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
88     if(SUCCEEDED(hr)) {
89         ok(uBytesRead == sizeof(ZeroMem), "Read %u bytes\n", uBytesRead);
90         ok(memcmp(MemBuf, ZeroMem, sizeof(ZeroMem)) == 0, "Read returned invalid data!\n");
91     }
92 
93     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
94 
95     hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
96     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
97 
98     /* Seek */
99     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
100     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
101     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
102 
103     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
104     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
105 
106     LargeInt.u.HighPart = 1;
107     LargeInt.u.LowPart = 0;
108     uNewPos.u.HighPart = 0xdeadbeef;
109     uNewPos.u.LowPart = 0xdeadbeef;
110     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
111     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
112     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
113     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
114     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
115     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
116 
117     LargeInt.QuadPart = sizeof(Memory) + 10;
118     uNewPos.u.HighPart = 0xdeadbeef;
119     uNewPos.u.LowPart = 0xdeadbeef;
120     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
121     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
122     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
123     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
124     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
125     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
126 
127     LargeInt.QuadPart = 1;
128     uNewPos.u.HighPart = 0xdeadbeef;
129     uNewPos.u.LowPart = 0xdeadbeef;
130     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
131     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
132     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
133     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
134     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
135     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
136 
137     LargeInt.QuadPart = -1;
138     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
139     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
140     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == sizeof(Memory) - 1, "bSeek cursor moved to position (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart);
141 
142     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos); /* reset seek pointer */
143     LargeInt.QuadPart = -(LONGLONG)sizeof(Memory) - 5;
144     uNewPos.u.HighPart = 0xdeadbeef;
145     uNewPos.u.LowPart = 0xdeadbeef;
146     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
147     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW),
148        "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
149     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
150     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
151     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
152     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0); /* remains unchanged */
153     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
154 
155 
156     /* Read */
157     hr = IWICStream_Read(pStream, MemBuf, 12, &uBytesRead);
158     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
159     if(SUCCEEDED(hr)) {
160         ok(uBytesRead == 12, "Read %u bytes, expected %u\n", uBytesRead, 12);
161         ok(memcmp(MemBuf, CmpMem, 12) == 0, "Read returned invalid data!\n");
162 
163         /* check whether the seek pointer has moved correctly */
164         IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
165         ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == uBytesRead, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, uBytesRead);
166     }
167 
168     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
169 
170     hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead);   /* source = dest */
171     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
172     if(SUCCEEDED(hr)) {
173         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
174         ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n");
175     }
176 
177     IWICStream_Seek(pStream, SeekPos, STREAM_SEEK_SET, NULL);
178 
179     hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead);   /* source and dest overlap */
180     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
181     if(SUCCEEDED(hr)) {
182         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
183         ok(memcmp(Memory, CmpMemOverlap, uBytesRead) == 0, "Read returned invalid data!\n");
184     }
185 
186     memcpy(Memory, CmpMem, sizeof(CmpMem));
187 
188     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
189 
190     hr = IWICStream_Read(pStream, Memory, sizeof(Memory) + 10, &uBytesRead);   /* request too many bytes */
191     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
192     if(SUCCEEDED(hr)) {
193         ok(uBytesRead == sizeof(Memory), "Read %u bytes\n", uBytesRead);
194         ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n");
195     }
196 
197     hr = IWICStream_Read(pStream, NULL, 1, &uBytesRead);    /* destination buffer = NULL */
198     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
199 
200     hr = IWICStream_Read(pStream, MemBuf, 0, &uBytesRead);    /* read 0 bytes */
201     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
202 
203     hr = IWICStream_Read(pStream, NULL, 0, &uBytesRead);
204     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
205 
206     hr = IWICStream_Read(pStream, NULL, 0, NULL);
207     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
208 
209     hr = IWICStream_Read(pStream, MemBuf, 1, NULL);
210     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
211 
212     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
213     ZeroMemory(MemBuf, sizeof(MemBuf));
214     hr = IWICStream_Read(pStream, MemBuf, sizeof(Memory) + 10, &uBytesRead);
215     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
216     if(SUCCEEDED(hr)) {
217         ok(uBytesRead == sizeof(Memory), "Read %u bytes\n", uBytesRead);
218         ok(memcmp(Memory, CmpMem, 64) == 0, "Read returned invalid data!\n");
219     }
220     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
221 
222 
223     /* Write */
224     MemBuf[0] = CmpMem[0] + 1;
225     MemBuf[1] = CmpMem[1] + 1;
226     MemBuf[2] = CmpMem[2] + 1;
227     hr = IWICStream_Write(pStream, MemBuf, 3, &uBytesWritten);
228     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
229     if(SUCCEEDED(hr)) {
230         ok(uBytesWritten == 3, "Wrote %u bytes, expected %u\n", uBytesWritten, 3);
231         ok(memcmp(MemBuf, Memory, 3) == 0, "Wrote returned invalid data!\n"); /* make sure we're writing directly */
232 
233         /* check whether the seek pointer has moved correctly */
234         IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
235         ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == uBytesWritten, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, uBytesWritten);
236     }
237     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
238 
239     hr = IWICStream_Write(pStream, MemBuf, 0, &uBytesWritten);
240     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
241 
242     /* Restore the original contents of the memory stream. */
243     hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
244     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
245 
246     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
247 
248     /* Source and destination overlap. */
249     hr = IWICStream_Write(pStream, Memory + 5, 10, &uBytesWritten);
250     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
251     if(SUCCEEDED(hr)) {
252         ok(uBytesWritten == 10, "Wrote %u bytes, expected %u\n", uBytesWritten, 10);
253         ok(memcmp(CmpMemOverlap, Memory, sizeof(CmpMemOverlap)) == 0, "Wrote returned invalid data!\n");
254     }
255 
256     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
257 
258     uBytesWritten = 0xdeadbeef;
259     hr = IWICStream_Write(pStream, NULL, 3, &uBytesWritten);
260     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
261     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
262     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
263     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
264 
265     uBytesWritten = 0xdeadbeef;
266     hr = IWICStream_Write(pStream, NULL, 0, &uBytesWritten);
267     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
268     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
269     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
270     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
271 
272     uBytesWritten = 0xdeadbeef;
273     hr = IWICStream_Write(pStream, CmpMem, sizeof(Memory) + 10, &uBytesWritten);
274     ok(hr == STG_E_MEDIUMFULL, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
275     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
276     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
277     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
278     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
279 
280 
281     /* SetSize */
282     uNewPos.u.HighPart = 0;
283     uNewPos.u.LowPart = sizeof(Memory) + 10;
284     hr = IWICStream_SetSize(pStream, uNewPos);
285     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
286 
287     uNewPos.u.HighPart = 0;
288     uNewPos.u.LowPart = sizeof(Memory);
289     hr = IWICStream_SetSize(pStream, uNewPos);
290     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
291 
292     uNewPos.u.HighPart = 0;
293     uNewPos.u.LowPart = sizeof(Memory) - 10;
294     hr = IWICStream_SetSize(pStream, uNewPos);
295     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
296 
297     uNewPos.u.HighPart = 0;
298     uNewPos.u.LowPart = 0;
299     hr = IWICStream_SetSize(pStream, uNewPos);
300     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
301 
302     uNewPos.QuadPart = -10;
303     hr = IWICStream_SetSize(pStream, uNewPos);
304     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
305 
306 
307     /* CopyTo */
308     uNewPos.u.HighPart = 0;
309     uNewPos.u.LowPart = 5;
310     hr = IWICStream_CopyTo(pStream, NULL, uNewPos, NULL, NULL);
311     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
312 
313     hr = IWICImagingFactory_CreateStream(pFactory, &pBufStream);
314     ok(hr == S_OK, "CreateStream failed with %#x\n", hr);
315 
316     hr = IWICStream_InitializeFromMemory(pBufStream, Memory, sizeof(Memory));
317     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
318 
319     hr = IWICStream_CopyTo(pStream, (IStream*)pBufStream, uNewPos, NULL, NULL);
320     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
321     IWICStream_Release(pBufStream);
322 
323 
324     /* Commit */
325     hr = IWICStream_Commit(pStream, STGC_DEFAULT);
326     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
327 
328     hr = IWICStream_Commit(pStream, STGC_OVERWRITE);
329     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
330 
331     hr = IWICStream_Commit(pStream, STGC_ONLYIFCURRENT);
332     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
333 
334     hr = IWICStream_Commit(pStream, STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
335     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
336 
337     hr = IWICStream_Commit(pStream, STGC_CONSOLIDATE);
338     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
339 
340 
341     /* Revert */
342     IWICStream_Write(pStream, &MemBuf[5], 6, NULL);
343     hr = IWICStream_Revert(pStream);
344     ok(hr == E_NOTIMPL, "Revert returned %#x, expected %#x\n", hr, E_NOTIMPL);
345     memcpy(Memory, CmpMem, sizeof(Memory));
346 
347 
348     /* LockRegion/UnlockRegion */
349     hr = IWICStream_LockRegion(pStream, uLargeNull, uLargeNull, 0);
350     ok(hr == E_NOTIMPL, "LockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
351 
352     hr = IWICStream_UnlockRegion(pStream, uLargeNull, uLargeNull, 0);
353     ok(hr == E_NOTIMPL, "UnlockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
354 
355 
356     /* Stat */
357     hr = IWICStream_Stat(pStream, NULL, 0);
358     ok(hr == E_INVALIDARG, "Stat returned %#x, expected %#x\n", hr, E_INVALIDARG);
359 
360     hr = IWICStream_Stat(pStream, &Stats, 0);
361     ok(hr == S_OK, "Stat returned %#x, expected %#x\n", hr, S_OK);
362     ok(Stats.pwcsName == NULL, "Stat returned name %p, expected %p\n", Stats.pwcsName, NULL);
363     ok(Stats.type == STGTY_STREAM, "Stat returned type %d, expected %d\n", Stats.type, STGTY_STREAM);
364     ok(Stats.cbSize.u.HighPart == 0 && Stats.cbSize.u.LowPart == sizeof(Memory), "Stat returned size (%u;%u)\n", Stats.cbSize.u.HighPart, Stats.cbSize.u.LowPart);
365     ok(Stats.mtime.dwHighDateTime == 0 && Stats.mtime.dwLowDateTime == 0, "Stat returned mtime (%u;%u), expected (%u;%u)\n", Stats.mtime.dwHighDateTime, Stats.mtime.dwLowDateTime, 0, 0);
366     ok(Stats.ctime.dwHighDateTime == 0 && Stats.ctime.dwLowDateTime == 0, "Stat returned ctime (%u;%u), expected (%u;%u)\n", Stats.ctime.dwHighDateTime, Stats.ctime.dwLowDateTime, 0, 0);
367     ok(Stats.atime.dwHighDateTime == 0 && Stats.atime.dwLowDateTime == 0, "Stat returned atime (%u;%u), expected (%u;%u)\n", Stats.atime.dwHighDateTime, Stats.atime.dwLowDateTime, 0, 0);
368     ok(Stats.grfMode == 0, "Stat returned access mode %d, expected %d\n", Stats.grfMode, 0);
369     ok(Stats.grfLocksSupported == 0, "Stat returned supported locks %#x, expected %#x\n", Stats.grfLocksSupported, 0);
370     ok(Stats.grfStateBits == 0, "Stat returned state bits %#x, expected %#x\n", Stats.grfStateBits, 0);
371 
372 
373     /* Clone */
374     hr = IWICStream_Clone(pStream, (IStream**)&pBufStream);
375     ok(hr == E_NOTIMPL, "UnlockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
376 
377 
378     IWICStream_Release(pStream);
379     IWICImagingFactory_Release(pFactory);
380     CoUninitialize();
381 }
382 
383 static void test_StreamOnStreamRange(void)
384 {
385     IWICImagingFactory *pFactory;
386     IWICStream *pStream, *pSubStream;
387     IStream *CopyStream;
388     const BYTE CmpMem[] = {
389         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
390         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
391         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
392         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
393     };
394     BYTE Memory[64], MemBuf[64];
395     LARGE_INTEGER LargeNull, LargeInt;
396     ULARGE_INTEGER uLargeNull, uNewPos, uSize;
397     ULONG uBytesRead, uBytesWritten;
398     HRESULT hr;
399     STATSTG Stats;
400 
401     LargeNull.QuadPart = 0;
402     uLargeNull.QuadPart = 0;
403 
404     memcpy(Memory, CmpMem, sizeof(CmpMem));
405 
406     CoInitialize(NULL);
407 
408     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&pFactory);
409     if(FAILED(hr)) {
410         skip("CoCreateInstance returned with %#x, expected %#x\n", hr, S_OK);
411         return;
412     }
413 
414     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
415     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
416     if(FAILED(hr)) {
417         skip("Failed to create stream\n");
418         return;
419     }
420 
421     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));
422     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
423 
424     hr = IWICImagingFactory_CreateStream(pFactory, &pSubStream);
425     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
426 
427     uNewPos.QuadPart = 20;
428     uSize.QuadPart = 20;
429     hr = IWICStream_InitializeFromIStreamRegion(pSubStream, (IStream*)pStream, uNewPos, uSize);
430     ok(hr == S_OK, "InitializeFromIStreamRegion returned with %#x, expected %#x\n", hr, S_OK);
431     if(FAILED(hr)) {
432         skip("InitializeFromIStreamRegion unimplemented\n");
433         IWICStream_Release(pSubStream);
434         IWICStream_Release(pStream);
435         IWICImagingFactory_Release(pFactory);
436         CoUninitialize();
437         return;
438     }
439 
440     /* Seek */
441     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_END, &uNewPos);
442     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 20, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 20);
443     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
444 
445     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
446     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
447     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
448 
449     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
450     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
451 
452     LargeInt.u.HighPart = 1;
453     LargeInt.u.LowPart = 0;
454     uNewPos.u.HighPart = 0xdeadbeef;
455     uNewPos.u.LowPart = 0xdeadbeef;
456     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
457     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
458     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
459     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
460     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
461     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
462 
463     LargeInt.QuadPart = 30;
464     uNewPos.u.HighPart = 0xdeadbeef;
465     uNewPos.u.LowPart = 0xdeadbeef;
466     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
467     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
468     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
469     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
470     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
471     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
472 
473     LargeInt.QuadPart = 1;
474     uNewPos.u.HighPart = 0xdeadbeef;
475     uNewPos.u.LowPart = 0xdeadbeef;
476     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
477     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
478     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
479     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
480     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
481     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
482 
483     LargeInt.QuadPart = -1;
484     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
485     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
486     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 19, "bSeek cursor moved to position (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart);
487 
488     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, &uNewPos); /* reset seek pointer */
489     LargeInt.QuadPart = -25;
490     uNewPos.u.HighPart = 0xdeadbeef;
491     uNewPos.u.LowPart = 0xdeadbeef;
492     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
493     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE,
494        "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
495     ok(uNewPos.u.HighPart == 0xdeadbeef && uNewPos.u.LowPart == 0xdeadbeef, "Seek cursor initialized to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0xdeadbeef, 0xdeadbeef);
496     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
497     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
498     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0); /* remains unchanged */
499     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
500 
501 
502     /* Read */
503     hr = IWICStream_Read(pSubStream, MemBuf, 12, &uBytesRead);
504     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
505     if(SUCCEEDED(hr)) {
506         ok(uBytesRead == 12, "Read %u bytes, expected %u\n", uBytesRead, 12);
507         ok(memcmp(MemBuf, CmpMem+20, 12) == 0, "Read returned invalid data!\n");
508 
509         /* check whether the seek pointer has moved correctly */
510         IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
511         ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == uBytesRead, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, uBytesRead);
512     }
513 
514     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
515 
516     hr = IWICStream_Read(pSubStream, Memory, 10, &uBytesRead);   /* source = dest */
517     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
518     if(SUCCEEDED(hr)) {
519         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
520         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
521     }
522 
523     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
524 
525     hr = IWICStream_Read(pSubStream, Memory, 30, &uBytesRead);   /* request too many bytes */
526     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
527     if(SUCCEEDED(hr)) {
528         ok(uBytesRead == 20, "Read %u bytes\n", uBytesRead);
529         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
530     }
531 
532     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
533     uBytesRead = 0xdeadbeef;
534     hr = IWICStream_Read(pSubStream, NULL, 1, &uBytesRead);    /* destination buffer = NULL */
535     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
536     ok(uBytesRead == 0xdeadbeef, "Expected uBytesRead to be unchanged, got %u\n", uBytesRead);
537 
538     hr = IWICStream_Read(pSubStream, MemBuf, 0, &uBytesRead);    /* read 0 bytes */
539     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
540 
541     uBytesRead = 0xdeadbeef;
542     hr = IWICStream_Read(pSubStream, NULL, 0, &uBytesRead);
543     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
544     ok(uBytesRead == 0xdeadbeef, "Expected uBytesRead to be unchanged, got %u\n", uBytesRead);
545 
546     hr = IWICStream_Read(pSubStream, NULL, 0, NULL);
547     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
548 
549     hr = IWICStream_Read(pSubStream, MemBuf, 1, NULL);
550     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
551 
552     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
553     ZeroMemory(MemBuf, sizeof(MemBuf));
554     hr = IWICStream_Read(pSubStream, MemBuf, 30, &uBytesRead);
555     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
556     if(SUCCEEDED(hr)) {
557         ok(uBytesRead == 20, "Read %u bytes\n", uBytesRead);
558         ok(memcmp(Memory, CmpMem+20, 20) == 0, "Read returned invalid data!\n");
559     }
560     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
561 
562 
563     /* Write */
564     MemBuf[0] = CmpMem[0] + 1;
565     MemBuf[1] = CmpMem[1] + 1;
566     MemBuf[2] = CmpMem[2] + 1;
567     hr = IWICStream_Write(pSubStream, MemBuf, 3, &uBytesWritten);
568     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
569     if(SUCCEEDED(hr)) {
570         ok(uBytesWritten == 3, "Wrote %u bytes, expected %u\n", uBytesWritten, 3);
571         ok(memcmp(MemBuf, Memory+20, 3) == 0, "Wrote returned invalid data!\n"); /* make sure we're writing directly */
572 
573         /* check whether the seek pointer has moved correctly */
574         IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
575         ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == uBytesWritten, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, uBytesWritten);
576     }
577     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
578 
579     hr = IWICStream_Write(pSubStream, MemBuf, 0, &uBytesWritten);
580     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
581 
582     uBytesWritten = 0xdeadbeef;
583     hr = IWICStream_Write(pSubStream, NULL, 3, &uBytesWritten);
584     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
585     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
586     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
587     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
588 
589     uBytesWritten = 0xdeadbeef;
590     hr = IWICStream_Write(pSubStream, NULL, 0, &uBytesWritten);
591     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
592     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
593     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
594     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
595 
596     hr = IWICStream_Write(pSubStream, CmpMem, 30, &uBytesWritten);
597     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
598     ok(uBytesWritten == 20, "Wrote %u bytes, expected %u\n", uBytesWritten, 0);
599     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
600     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == uBytesWritten, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, uBytesWritten);
601     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
602 
603 
604     /* SetSize */
605     uNewPos.u.HighPart = 0;
606     uNewPos.u.LowPart = sizeof(Memory) + 10;
607     hr = IWICStream_SetSize(pSubStream, uNewPos);
608     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
609 
610     uNewPos.u.HighPart = 0;
611     uNewPos.u.LowPart = sizeof(Memory);
612     hr = IWICStream_SetSize(pSubStream, uNewPos);
613     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
614 
615     uNewPos.u.HighPart = 0;
616     uNewPos.u.LowPart = sizeof(Memory) - 10;
617     hr = IWICStream_SetSize(pSubStream, uNewPos);
618     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
619 
620     uNewPos.u.HighPart = 0;
621     uNewPos.u.LowPart = 0;
622     hr = IWICStream_SetSize(pSubStream, uNewPos);
623     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
624 
625     uNewPos.QuadPart = -10;
626     hr = IWICStream_SetSize(pSubStream, uNewPos);
627     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
628 
629 
630     /* CopyTo */
631     uNewPos.u.HighPart = 0;
632     uNewPos.u.LowPart = 30;
633     hr = IWICStream_CopyTo(pSubStream, NULL, uNewPos, NULL, NULL);
634     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
635 
636     hr = CreateStreamOnHGlobal(NULL, TRUE, &CopyStream);
637     ok(hr == S_OK, "CreateStream failed with %#x\n", hr);
638 
639     hr = IWICStream_CopyTo(pSubStream, CopyStream, uNewPos, NULL, NULL);
640     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
641     IStream_Release(CopyStream);
642 
643 
644     /* Commit */
645     hr = IWICStream_Commit(pSubStream, STGC_DEFAULT);
646     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
647 
648     hr = IWICStream_Commit(pSubStream, STGC_OVERWRITE);
649     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
650 
651     hr = IWICStream_Commit(pSubStream, STGC_ONLYIFCURRENT);
652     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
653 
654     hr = IWICStream_Commit(pSubStream, STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
655     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
656 
657     hr = IWICStream_Commit(pSubStream, STGC_CONSOLIDATE);
658     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
659 
660 
661     /* Revert */
662     IWICStream_Write(pSubStream, &MemBuf[5], 6, NULL);
663     hr = IWICStream_Revert(pSubStream);
664     ok(hr == E_NOTIMPL, "Revert returned %#x, expected %#x\n", hr, E_NOTIMPL);
665     memcpy(Memory, CmpMem, sizeof(Memory));
666 
667 
668     /* LockRegion/UnlockRegion */
669     hr = IWICStream_LockRegion(pSubStream, uLargeNull, uLargeNull, 0);
670     ok(hr == E_NOTIMPL, "LockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
671 
672     hr = IWICStream_UnlockRegion(pSubStream, uLargeNull, uLargeNull, 0);
673     ok(hr == E_NOTIMPL, "UnlockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
674 
675 
676     /* Stat */
677     hr = IWICStream_Stat(pSubStream, NULL, 0);
678     ok(hr == E_INVALIDARG, "Stat returned %#x, expected %#x\n", hr, E_INVALIDARG);
679 
680     hr = IWICStream_Stat(pSubStream, &Stats, 0);
681     ok(hr == S_OK, "Stat returned %#x, expected %#x\n", hr, S_OK);
682     ok(Stats.pwcsName == NULL, "Stat returned name %p, expected %p\n", Stats.pwcsName, NULL);
683     ok(Stats.type == STGTY_STREAM, "Stat returned type %d, expected %d\n", Stats.type, STGTY_STREAM);
684     ok(Stats.cbSize.u.HighPart == 0 && Stats.cbSize.u.LowPart == 20, "Stat returned size (%u;%u)\n", Stats.cbSize.u.HighPart, Stats.cbSize.u.LowPart);
685     ok(Stats.mtime.dwHighDateTime == 0 && Stats.mtime.dwLowDateTime == 0, "Stat returned mtime (%u;%u), expected (%u;%u)\n", Stats.mtime.dwHighDateTime, Stats.mtime.dwLowDateTime, 0, 0);
686     ok(Stats.ctime.dwHighDateTime == 0 && Stats.ctime.dwLowDateTime == 0, "Stat returned ctime (%u;%u), expected (%u;%u)\n", Stats.ctime.dwHighDateTime, Stats.ctime.dwLowDateTime, 0, 0);
687     ok(Stats.atime.dwHighDateTime == 0 && Stats.atime.dwLowDateTime == 0, "Stat returned atime (%u;%u), expected (%u;%u)\n", Stats.atime.dwHighDateTime, Stats.atime.dwLowDateTime, 0, 0);
688     ok(Stats.grfMode == 0, "Stat returned access mode %d, expected %d\n", Stats.grfMode, 0);
689     ok(Stats.grfLocksSupported == 0, "Stat returned supported locks %#x, expected %#x\n", Stats.grfLocksSupported, 0);
690     ok(Stats.grfStateBits == 0, "Stat returned state bits %#x, expected %#x\n", Stats.grfStateBits, 0);
691 
692 
693     /* Clone */
694     hr = IWICStream_Clone(pSubStream, &CopyStream);
695     ok(hr == E_NOTIMPL, "Clone returned %#x, expected %#x\n", hr, E_NOTIMPL);
696 
697 
698     IWICStream_Release(pSubStream);
699 
700 
701     /* Recreate, this time larger than the original. */
702     hr = IWICImagingFactory_CreateStream(pFactory, &pSubStream);
703     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
704 
705     uNewPos.QuadPart = 48;
706     uSize.QuadPart = 32;
707     hr = IWICStream_InitializeFromIStreamRegion(pSubStream, (IStream*)pStream, uNewPos, uSize);
708     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
709 
710     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_END, &uNewPos);
711     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
712     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 16, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 16);
713 
714     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
715     hr = IWICStream_Read(pSubStream, Memory, 48, &uBytesRead);
716     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
717     if(SUCCEEDED(hr)) {
718         ok(uBytesRead == 16, "Read %u bytes\n", uBytesRead);
719         ok(memcmp(Memory, CmpMem+48, uBytesRead) == 0, "Read returned invalid data!\n");
720     }
721 
722     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
723     uBytesWritten = 0xdeadbeef;
724     hr = IWICStream_Write(pSubStream, CmpMem, 32, &uBytesWritten);
725     ok(hr == STG_E_MEDIUMFULL, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
726     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
727     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
728     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 0, "Seek cursor moved to position (%u;%u), expected (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart, 0, 0);
729 
730 
731     IWICStream_Release(pSubStream);
732     IWICStream_Release(pStream);
733     IWICImagingFactory_Release(pFactory);
734     CoUninitialize();
735 }
736 
737 START_TEST(stream)
738 {
739     test_StreamOnMemory();
740     test_StreamOnStreamRange();
741 }
742