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 "wine/test.h"
20 
21 #define COBJMACROS
22 #include "wincodec.h"
23 
24 #define CHECK_CUR_POS(a, b) _check_cur_pos((IStream *)a, b, FALSE, __LINE__)
25 #define CHECK_CUR_POS_TODO(a, b) _check_cur_pos((IStream *)a, b, TRUE, __LINE__)
_check_cur_pos(IStream * stream,ULONGLONG expected_pos,BOOL todo,unsigned int line)26 static void _check_cur_pos(IStream *stream, ULONGLONG expected_pos, BOOL todo, unsigned int line)
27 {
28     LARGE_INTEGER offset;
29     ULARGE_INTEGER pos;
30     HRESULT hr;
31 
32     offset.QuadPart = 0;
33     hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, &pos);
34     ok_(__FILE__, line)(hr == S_OK, "Failed to get current position, hr %#x.\n", hr);
35 todo_wine_if(todo)
36     ok_(__FILE__, line)(pos.QuadPart == expected_pos, "Unexpected stream position %s.\n",
37         wine_dbgstr_longlong(pos.QuadPart));
38 }
39 
test_StreamOnMemory(void)40 static void test_StreamOnMemory(void)
41 {
42     IWICImagingFactory *pFactory;
43     IWICStream *pStream, *pBufStream;
44     const BYTE CmpMem[] = {
45         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
46         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
47         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
48         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
49     };
50     const BYTE CmpMemOverlap[] = {
51         0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
52         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
53         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
54         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
55     };
56     const BYTE ZeroMem[10] = {0};
57     BYTE Memory[64], MemBuf[64];
58     LARGE_INTEGER LargeNull, LargeInt, SeekPos;
59     ULARGE_INTEGER uLargeNull, uNewPos;
60     ULONG uBytesRead, uBytesWritten;
61     HRESULT hr;
62     STATSTG Stats;
63 
64     LargeNull.QuadPart = 0;
65     uLargeNull.QuadPart = 0;
66     SeekPos.QuadPart = 5;
67 
68     memcpy(Memory, CmpMem, sizeof(CmpMem));
69 
70     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&pFactory);
71     if(FAILED(hr)) {
72         skip("CoCreateInstance returned with %#x, expected %#x\n", hr, S_OK);
73         return;
74     }
75 
76     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
77     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
78     if(FAILED(hr)) {
79         skip("Failed to create stream\n");
80         return;
81     }
82 
83     /* InitializeFromMemory */
84     hr = IWICStream_InitializeFromMemory(pStream, NULL, sizeof(Memory));   /* memory = NULL */
85     ok(hr == E_INVALIDARG, "InitializeFromMemory returned with %#x, expected %#x\n", hr, E_INVALIDARG);
86 
87     hr = IWICStream_InitializeFromMemory(pStream, Memory, 0);   /* size = 0 */
88     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
89 
90     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));   /* stream already initialized */
91     ok(hr == WINCODEC_ERR_WRONGSTATE, "InitializeFromMemory returned with %#x, expected %#x\n", hr, WINCODEC_ERR_WRONGSTATE);
92 
93     /* recreate stream */
94     IWICStream_Release(pStream);
95     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
96     ok(hr == S_OK, "CreateStream failed with %#x\n", hr);
97 
98     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));
99     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
100 
101     /* IWICStream does not maintain an independent copy of the backing memory buffer. */
102     memcpy(Memory, ZeroMem, sizeof(ZeroMem));
103     hr = IWICStream_Read(pStream, MemBuf, sizeof(ZeroMem), &uBytesRead);
104     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
105     if(SUCCEEDED(hr)) {
106         ok(uBytesRead == sizeof(ZeroMem), "Read %u bytes\n", uBytesRead);
107         ok(memcmp(MemBuf, ZeroMem, sizeof(ZeroMem)) == 0, "Read returned invalid data!\n");
108     }
109 
110     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
111 
112     hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
113     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
114 
115     /* Seek */
116     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
117     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
118     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);
119 
120     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
121     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
122 
123     LargeInt.u.HighPart = 1;
124     LargeInt.u.LowPart = 0;
125     uNewPos.u.HighPart = 0xdeadbeef;
126     uNewPos.u.LowPart = 0xdeadbeef;
127     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
128     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
129     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);
130     CHECK_CUR_POS(pStream, 0);
131 
132     LargeInt.QuadPart = sizeof(Memory) + 10;
133     uNewPos.u.HighPart = 0xdeadbeef;
134     uNewPos.u.LowPart = 0xdeadbeef;
135     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
136     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
137     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);
138     CHECK_CUR_POS(pStream, 0);
139 
140     LargeInt.QuadPart = 1;
141     uNewPos.u.HighPart = 0xdeadbeef;
142     uNewPos.u.LowPart = 0xdeadbeef;
143     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
144     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
145     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);
146     CHECK_CUR_POS(pStream, 0);
147 
148     LargeInt.QuadPart = -1;
149     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
150     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
151     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);
152 
153     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos); /* reset seek pointer */
154     LargeInt.QuadPart = -(LONGLONG)sizeof(Memory) - 5;
155     uNewPos.u.HighPart = 0xdeadbeef;
156     uNewPos.u.LowPart = 0xdeadbeef;
157     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
158     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW),
159        "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
160     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);
161     CHECK_CUR_POS(pStream, 0);
162     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
163 
164     /* Read */
165     hr = IWICStream_Read(pStream, MemBuf, 12, &uBytesRead);
166     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
167     if(SUCCEEDED(hr)) {
168         ok(uBytesRead == 12, "Read %u bytes, expected %u\n", uBytesRead, 12);
169         ok(memcmp(MemBuf, CmpMem, 12) == 0, "Read returned invalid data!\n");
170 
171         /* check whether the seek pointer has moved correctly */
172         CHECK_CUR_POS(pStream, uBytesRead);
173     }
174 
175     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
176 
177     hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead);   /* source = dest */
178     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
179     if(SUCCEEDED(hr)) {
180         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
181         ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n");
182     }
183 
184     IWICStream_Seek(pStream, SeekPos, STREAM_SEEK_SET, NULL);
185 
186     hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead);   /* source and dest overlap */
187     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
188     if(SUCCEEDED(hr)) {
189         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
190         ok(memcmp(Memory, CmpMemOverlap, uBytesRead) == 0, "Read returned invalid data!\n");
191     }
192 
193     memcpy(Memory, CmpMem, sizeof(CmpMem));
194 
195     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
196 
197     hr = IWICStream_Read(pStream, Memory, sizeof(Memory) + 10, &uBytesRead);   /* request too many bytes */
198     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
199     if(SUCCEEDED(hr)) {
200         ok(uBytesRead == sizeof(Memory), "Read %u bytes\n", uBytesRead);
201         ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n");
202     }
203 
204     hr = IWICStream_Read(pStream, NULL, 1, &uBytesRead);    /* destination buffer = NULL */
205     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
206 
207     hr = IWICStream_Read(pStream, MemBuf, 0, &uBytesRead);    /* read 0 bytes */
208     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
209 
210     hr = IWICStream_Read(pStream, NULL, 0, &uBytesRead);
211     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
212 
213     hr = IWICStream_Read(pStream, NULL, 0, NULL);
214     ok(hr == E_INVALIDARG, "Read returned with %#x, expected %#x\n", hr, E_INVALIDARG);
215 
216     hr = IWICStream_Read(pStream, MemBuf, 1, NULL);
217     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
218 
219     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
220     ZeroMemory(MemBuf, sizeof(MemBuf));
221     hr = IWICStream_Read(pStream, MemBuf, sizeof(Memory) + 10, &uBytesRead);
222     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
223     if(SUCCEEDED(hr)) {
224         ok(uBytesRead == sizeof(Memory), "Read %u bytes\n", uBytesRead);
225         ok(memcmp(Memory, CmpMem, 64) == 0, "Read returned invalid data!\n");
226     }
227     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
228 
229 
230     /* Write */
231     MemBuf[0] = CmpMem[0] + 1;
232     MemBuf[1] = CmpMem[1] + 1;
233     MemBuf[2] = CmpMem[2] + 1;
234     hr = IWICStream_Write(pStream, MemBuf, 3, &uBytesWritten);
235     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
236     if(SUCCEEDED(hr)) {
237         ok(uBytesWritten == 3, "Wrote %u bytes, expected %u\n", uBytesWritten, 3);
238         ok(memcmp(MemBuf, Memory, 3) == 0, "Wrote returned invalid data!\n"); /* make sure we're writing directly */
239 
240         /* check whether the seek pointer has moved correctly */
241         CHECK_CUR_POS(pStream, uBytesWritten);
242     }
243     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
244 
245     hr = IWICStream_Write(pStream, MemBuf, 0, &uBytesWritten);
246     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
247 
248     /* Restore the original contents of the memory stream. */
249     hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
250     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
251 
252     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
253 
254     /* Source and destination overlap. */
255     hr = IWICStream_Write(pStream, Memory + 5, 10, &uBytesWritten);
256     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
257     if(SUCCEEDED(hr)) {
258         ok(uBytesWritten == 10, "Wrote %u bytes, expected %u\n", uBytesWritten, 10);
259         ok(memcmp(CmpMemOverlap, Memory, sizeof(CmpMemOverlap)) == 0, "Wrote returned invalid data!\n");
260     }
261 
262     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
263 
264     uBytesWritten = 0xdeadbeef;
265     hr = IWICStream_Write(pStream, NULL, 3, &uBytesWritten);
266     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
267     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
268     CHECK_CUR_POS(pStream, 0);
269 
270     uBytesWritten = 0xdeadbeef;
271     hr = IWICStream_Write(pStream, NULL, 0, &uBytesWritten);
272     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
273     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
274     CHECK_CUR_POS(pStream, 0);
275 
276     uBytesWritten = 0xdeadbeef;
277     hr = IWICStream_Write(pStream, CmpMem, sizeof(Memory) + 10, &uBytesWritten);
278     ok(hr == STG_E_MEDIUMFULL, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
279     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
280     CHECK_CUR_POS(pStream, 0);
281     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
282 
283 
284     /* SetSize */
285     uNewPos.u.HighPart = 0;
286     uNewPos.u.LowPart = sizeof(Memory) + 10;
287     hr = IWICStream_SetSize(pStream, uNewPos);
288     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
289 
290     uNewPos.u.HighPart = 0;
291     uNewPos.u.LowPart = sizeof(Memory);
292     hr = IWICStream_SetSize(pStream, uNewPos);
293     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
294 
295     uNewPos.u.HighPart = 0;
296     uNewPos.u.LowPart = sizeof(Memory) - 10;
297     hr = IWICStream_SetSize(pStream, uNewPos);
298     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
299 
300     uNewPos.u.HighPart = 0;
301     uNewPos.u.LowPart = 0;
302     hr = IWICStream_SetSize(pStream, uNewPos);
303     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
304 
305     uNewPos.QuadPart = -10;
306     hr = IWICStream_SetSize(pStream, uNewPos);
307     ok(hr == E_NOTIMPL, "SetSize returned %#x, expected %#x\n", hr, E_NOTIMPL);
308 
309 
310     /* CopyTo */
311     uNewPos.u.HighPart = 0;
312     uNewPos.u.LowPart = 5;
313     hr = IWICStream_CopyTo(pStream, NULL, uNewPos, NULL, NULL);
314     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
315 
316     hr = IWICImagingFactory_CreateStream(pFactory, &pBufStream);
317     ok(hr == S_OK, "CreateStream failed with %#x\n", hr);
318 
319     hr = IWICStream_InitializeFromMemory(pBufStream, Memory, sizeof(Memory));
320     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
321 
322     hr = IWICStream_CopyTo(pStream, (IStream*)pBufStream, uNewPos, NULL, NULL);
323     ok(hr == E_NOTIMPL, "CopyTo returned %#x, expected %#x\n", hr, E_NOTIMPL);
324     IWICStream_Release(pBufStream);
325 
326 
327     /* Commit */
328     hr = IWICStream_Commit(pStream, STGC_DEFAULT);
329     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
330 
331     hr = IWICStream_Commit(pStream, STGC_OVERWRITE);
332     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
333 
334     hr = IWICStream_Commit(pStream, STGC_ONLYIFCURRENT);
335     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
336 
337     hr = IWICStream_Commit(pStream, STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
338     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
339 
340     hr = IWICStream_Commit(pStream, STGC_CONSOLIDATE);
341     ok(hr == E_NOTIMPL, "Commit returned %#x, expected %#x\n", hr, E_NOTIMPL);
342 
343 
344     /* Revert */
345     IWICStream_Write(pStream, &MemBuf[5], 6, NULL);
346     hr = IWICStream_Revert(pStream);
347     ok(hr == E_NOTIMPL, "Revert returned %#x, expected %#x\n", hr, E_NOTIMPL);
348     memcpy(Memory, CmpMem, sizeof(Memory));
349 
350 
351     /* LockRegion/UnlockRegion */
352     hr = IWICStream_LockRegion(pStream, uLargeNull, uLargeNull, 0);
353     ok(hr == E_NOTIMPL, "LockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
354 
355     hr = IWICStream_UnlockRegion(pStream, uLargeNull, uLargeNull, 0);
356     ok(hr == E_NOTIMPL, "UnlockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
357 
358 
359     /* Stat */
360     hr = IWICStream_Stat(pStream, NULL, 0);
361     ok(hr == E_INVALIDARG, "Stat returned %#x, expected %#x\n", hr, E_INVALIDARG);
362 
363     hr = IWICStream_Stat(pStream, &Stats, 0);
364     ok(hr == S_OK, "Stat returned %#x, expected %#x\n", hr, S_OK);
365     ok(Stats.pwcsName == NULL, "Stat returned name %p, expected %p\n", Stats.pwcsName, NULL);
366     ok(Stats.type == STGTY_STREAM, "Stat returned type %d, expected %d\n", Stats.type, STGTY_STREAM);
367     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);
368     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);
369     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);
370     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);
371     ok(Stats.grfMode == 0, "Stat returned access mode %d, expected %d\n", Stats.grfMode, 0);
372     ok(Stats.grfLocksSupported == 0, "Stat returned supported locks %#x, expected %#x\n", Stats.grfLocksSupported, 0);
373     ok(Stats.grfStateBits == 0, "Stat returned state bits %#x, expected %#x\n", Stats.grfStateBits, 0);
374 
375 
376     /* Clone */
377     hr = IWICStream_Clone(pStream, (IStream**)&pBufStream);
378     ok(hr == E_NOTIMPL, "UnlockRegion returned %#x, expected %#x\n", hr, E_NOTIMPL);
379 
380 
381     IWICStream_Release(pStream);
382     IWICImagingFactory_Release(pFactory);
383 }
384 
test_StreamOnStreamRange(void)385 static void test_StreamOnStreamRange(void)
386 {
387     IWICImagingFactory *pFactory;
388     IWICStream *pStream, *pSubStream;
389     IStream *CopyStream;
390     const BYTE CmpMem[] = {
391         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
392         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
393         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
394         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
395     };
396     BYTE Memory[64], MemBuf[64];
397     LARGE_INTEGER LargeNull, LargeInt;
398     ULARGE_INTEGER uLargeNull, uNewPos, uSize;
399     ULONG uBytesRead, uBytesWritten;
400     HRESULT hr;
401     STATSTG Stats;
402 
403     LargeNull.QuadPart = 0;
404     uLargeNull.QuadPart = 0;
405 
406     memcpy(Memory, CmpMem, sizeof(CmpMem));
407 
408     CoInitialize(NULL);
409 
410     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&pFactory);
411     if(FAILED(hr)) {
412         skip("CoCreateInstance returned with %#x, expected %#x\n", hr, S_OK);
413         return;
414     }
415 
416     hr = IWICImagingFactory_CreateStream(pFactory, &pStream);
417     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
418     if(FAILED(hr)) {
419         skip("Failed to create stream\n");
420         return;
421     }
422 
423     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));
424     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
425 
426     hr = IWICImagingFactory_CreateStream(pFactory, &pSubStream);
427     ok(hr == S_OK, "CreateStream returned with %#x, expected %#x\n", hr, S_OK);
428 
429     uNewPos.QuadPart = 20;
430     uSize.QuadPart = 20;
431     hr = IWICStream_InitializeFromIStreamRegion(pSubStream, (IStream*)pStream, uNewPos, uSize);
432     ok(hr == S_OK, "InitializeFromIStreamRegion returned with %#x, expected %#x\n", hr, S_OK);
433     if(FAILED(hr)) {
434         skip("InitializeFromIStreamRegion unimplemented\n");
435         IWICStream_Release(pSubStream);
436         IWICStream_Release(pStream);
437         IWICImagingFactory_Release(pFactory);
438         CoUninitialize();
439         return;
440     }
441 
442     /* Seek */
443     CHECK_CUR_POS(pStream, 0);
444     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_END, &uNewPos);
445     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);
446     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
447     CHECK_CUR_POS(pStream, 0);
448 
449     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
450     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
451     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);
452     CHECK_CUR_POS(pStream, 0);
453 
454     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
455     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
456 
457     LargeInt.u.HighPart = 1;
458     LargeInt.u.LowPart = 0;
459     uNewPos.u.HighPart = 0xdeadbeef;
460     uNewPos.u.LowPart = 0xdeadbeef;
461     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
462     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
463     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);
464     CHECK_CUR_POS(pStream, 0);
465 
466     LargeInt.QuadPart = 30;
467     uNewPos.u.HighPart = 0xdeadbeef;
468     uNewPos.u.LowPart = 0xdeadbeef;
469     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
470     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
471     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);
472     CHECK_CUR_POS(pStream, 0);
473 
474     LargeInt.QuadPart = 1;
475     uNewPos.u.HighPart = 0xdeadbeef;
476     uNewPos.u.LowPart = 0xdeadbeef;
477     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
478     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
479     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);
480     CHECK_CUR_POS(pStream, 0);
481 
482     LargeInt.QuadPart = -1;
483     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
484     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
485     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 19, "bSeek cursor moved to position (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart);
486     CHECK_CUR_POS(pStream, 0);
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     CHECK_CUR_POS(pStream, 0);
497     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
498 
499 
500     /* Read */
501     hr = IWICStream_Read(pSubStream, MemBuf, 12, &uBytesRead);
502     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
503     if(SUCCEEDED(hr)) {
504         ok(uBytesRead == 12, "Read %u bytes, expected %u\n", uBytesRead, 12);
505         ok(memcmp(MemBuf, CmpMem+20, 12) == 0, "Read returned invalid data!\n");
506 
507         /* check whether the seek pointer has moved correctly */
508         CHECK_CUR_POS(pSubStream, uBytesRead);
509         CHECK_CUR_POS(pStream, 0);
510     }
511 
512     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
513 
514     hr = IWICStream_Read(pSubStream, Memory, 10, &uBytesRead);   /* source = dest */
515     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
516     if(SUCCEEDED(hr)) {
517         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
518         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
519     }
520     CHECK_CUR_POS(pStream, 0);
521 
522     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
523 
524     hr = IWICStream_Read(pSubStream, Memory, 30, &uBytesRead);   /* request too many bytes */
525     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
526     if(SUCCEEDED(hr)) {
527         ok(uBytesRead == 20, "Read %u bytes\n", uBytesRead);
528         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
529     }
530     CHECK_CUR_POS(pStream, 0);
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         CHECK_CUR_POS(pSubStream, uBytesWritten);
575         CHECK_CUR_POS(pStream, 0);
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     CHECK_CUR_POS(pSubStream, 0);
587     CHECK_CUR_POS(pStream, 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     CHECK_CUR_POS(pSubStream, 0);
594     CHECK_CUR_POS(pStream, 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     CHECK_CUR_POS(pSubStream, uBytesWritten);
600     CHECK_CUR_POS(pStream, 0);
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     CHECK_CUR_POS(pSubStream, 0);
728     CHECK_CUR_POS(pStream, 0);
729 
730     IWICStream_Release(pSubStream);
731     IWICStream_Release(pStream);
732     IWICImagingFactory_Release(pFactory);
733     CoUninitialize();
734 }
735 
test_StreamOnIStream(void)736 static void test_StreamOnIStream(void)
737 {
738     static const BYTE data[] =
739     {
740         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
741         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
742         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
743         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
744     };
745     static const LARGE_INTEGER zero_pos;
746     static const ULARGE_INTEGER uzero;
747     IWICStream *stream, *substream;
748     IWICImagingFactory *factory;
749     BYTE memory[64], buff[64];
750     ULONG read_len, written;
751     ULARGE_INTEGER newpos;
752     IStream *copy_stream;
753     LARGE_INTEGER pos;
754     unsigned int i;
755     STATSTG stats;
756     HRESULT hr;
757 
758     memcpy(memory, data, sizeof(data));
759 
760     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
761         &IID_IWICImagingFactory, (void **)&factory);
762     ok(hr == S_OK, "Failed to create a factory, hr %#x.\n", hr);
763 
764     hr = IWICImagingFactory_CreateStream(factory, &stream);
765     ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
766 
767     hr = IWICStream_InitializeFromMemory(stream, memory, sizeof(memory));
768     ok(hr == S_OK, "Failed to initialize stream, hr %#x.\n", hr);
769 
770     hr = IWICImagingFactory_CreateStream(factory, &substream);
771     ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
772 
773     pos.QuadPart = 1;
774     hr = IWICStream_Seek(stream, pos, STREAM_SEEK_SET, &newpos);
775     ok(hr == S_OK, "Failed to set position, hr %#x.\n", hr);
776     CHECK_CUR_POS(stream, 1);
777 
778     hr = IWICStream_InitializeFromIStream(substream, (IStream *)stream);
779     ok(hr == S_OK, "Failed to initialize stream, hr %#x.\n", hr);
780     CHECK_CUR_POS(substream, 1);
781 
782     /* Seek */
783     CHECK_CUR_POS(stream, 1);
784     hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_END, &newpos);
785     ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
786     ok(newpos.QuadPart == sizeof(memory), "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
787     CHECK_CUR_POS(substream, sizeof(memory));
788     CHECK_CUR_POS(stream, sizeof(memory));
789 
790     hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, &newpos);
791     ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
792     ok(newpos.QuadPart == 0, "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
793     CHECK_CUR_POS(stream, 0);
794     CHECK_CUR_POS(substream, 0);
795 
796     hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
797     ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
798 
799     pos.u.HighPart = 1;
800     pos.u.LowPart = 0;
801     newpos.u.HighPart = 0xdeadbeef;
802     newpos.u.LowPart = 0xdeadbeef;
803     hr = IWICStream_Seek(substream, pos, STREAM_SEEK_SET, &newpos);
804     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "Unexpected hr %#x.\n", hr);
805     ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
806         wine_dbgstr_longlong(newpos.QuadPart));
807     CHECK_CUR_POS(stream, 0);
808     CHECK_CUR_POS(substream, 0);
809 
810     pos.QuadPart = sizeof(memory) + 1;
811     newpos.u.HighPart = 0xdeadbeef;
812     newpos.u.LowPart = 0xdeadbeef;
813     hr = IWICStream_Seek(substream, pos, STREAM_SEEK_SET, &newpos);
814     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
815     ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
816         wine_dbgstr_longlong(newpos.QuadPart));
817     CHECK_CUR_POS(stream, 0);
818     CHECK_CUR_POS(substream, 0);
819 
820     pos.QuadPart = 1;
821     newpos.u.HighPart = 0xdeadbeef;
822     newpos.u.LowPart = 0xdeadbeef;
823     hr = IWICStream_Seek(substream, pos, STREAM_SEEK_END, &newpos);
824     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
825     ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
826         wine_dbgstr_longlong(newpos.QuadPart));
827     CHECK_CUR_POS(stream, 0);
828     CHECK_CUR_POS(substream, 0);
829 
830     pos.QuadPart = -1;
831     hr = IWICStream_Seek(substream, pos, STREAM_SEEK_END, &newpos);
832     ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
833     ok(newpos.QuadPart == sizeof(memory) - 1, "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
834     CHECK_CUR_POS(stream, sizeof(memory) - 1);
835     CHECK_CUR_POS(substream, sizeof(memory) - 1);
836 
837     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
838 
839     /* Read */
840     hr = IWICStream_Read(substream, buff, 12, &read_len);
841     ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
842     ok(read_len == 12, "Unexpected read length %u.\n", read_len);
843     ok(!memcmp(buff, data, 12), "Unexpected data.\n");
844     CHECK_CUR_POS(substream, read_len);
845     CHECK_CUR_POS(stream, read_len);
846 
847     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
848     CHECK_CUR_POS(stream, 0);
849 
850     hr = IWICStream_Read(substream, memory, 10, &read_len);   /* source = dest */
851     ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
852     ok(read_len == 10, "Unexpected read length %u.\n", read_len);
853     ok(!memcmp(memory, data, read_len), "Unexpected data.\n");
854     CHECK_CUR_POS(stream, 10);
855 
856     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
857     hr = IWICStream_Read(substream, memory, 2 * sizeof(data), &read_len);   /* request too many bytes */
858     ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
859     ok(read_len == 64, "Unexpected read length %u.\n", read_len);
860     ok(!memcmp(memory, data, read_len), "Unexpected data.\n");
861     CHECK_CUR_POS(stream, sizeof(data));
862 
863     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
864     read_len = 0xdeadbeef;
865     hr = IWICStream_Read(substream, NULL, 1, &read_len);    /* destination buffer = NULL */
866     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
867     ok(read_len == 0xdeadbeef, "Unexpected read length %u.\n", read_len);
868 
869     read_len = 1;
870     hr = IWICStream_Read(substream, buff, 0, &read_len);    /* read 0 bytes */
871     ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
872     ok(read_len == 0, "Unexpected read length %u.\n", read_len);
873 
874     read_len = 0xdeadbeef;
875     hr = IWICStream_Read(substream, NULL, 0, &read_len);
876     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
877     ok(read_len == 0xdeadbeef, "Unexpected read length %u.\n", read_len);
878 
879     hr = IWICStream_Read(substream, NULL, 0, NULL);
880     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
881 
882     hr = IWICStream_Read(substream, buff, 1, NULL);
883     ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
884     CHECK_CUR_POS(substream, 1);
885     CHECK_CUR_POS(stream, 1);
886     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
887 
888     /* Write */
889     for (i = 0; i < 3; ++i)
890         buff[i] = data[i] + 1;
891 
892     hr = IWICStream_Write(substream, buff, 3, &written);
893     ok(hr == S_OK, "Failed to write to stream, hr %#x.\n", hr);
894     ok(written == 3, "Unexpected written length %u.\n", written);
895     ok(!memcmp(buff, memory, 3), "Unexpected stream data.\n");
896     CHECK_CUR_POS(substream, written);
897     CHECK_CUR_POS(stream, written);
898     IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
899 
900     hr = IWICStream_Write(substream, buff, 0, &written);
901     ok(hr == S_OK, "Failed to write to stream, hr %#x.\n", hr);
902 
903     written = 0xdeadbeef;
904     hr = IWICStream_Write(substream, NULL, 3, &written);
905     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
906     ok(written == 0xdeadbeef, "Unexpected written length %u.\n", written);
907     CHECK_CUR_POS(substream, 0);
908     CHECK_CUR_POS(stream, 0);
909 
910     written = 0xdeadbeef;
911     hr = IWICStream_Write(substream, NULL, 0, &written);
912     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
913     ok(written == 0xdeadbeef, "Unexpected written length %u.\n", written);
914     CHECK_CUR_POS(substream, 0);
915     CHECK_CUR_POS(stream, 0);
916 
917     /* SetSize */
918     newpos.u.HighPart = 0;
919     newpos.u.LowPart = sizeof(memory) + 10;
920     hr = IWICStream_SetSize(substream, newpos);
921     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
922 
923     newpos.u.HighPart = 0;
924     newpos.u.LowPart = sizeof(memory);
925     hr = IWICStream_SetSize(substream, newpos);
926     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
927 
928     newpos.u.HighPart = 0;
929     newpos.u.LowPart = sizeof(memory) - 10;
930     hr = IWICStream_SetSize(substream, newpos);
931     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
932 
933     newpos.QuadPart = 0;
934     hr = IWICStream_SetSize(substream, newpos);
935     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
936 
937     newpos.QuadPart = -10;
938     hr = IWICStream_SetSize(substream, newpos);
939     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
940 
941     /* CopyTo */
942     newpos.u.HighPart = 0;
943     newpos.u.LowPart = 30;
944     hr = IWICStream_CopyTo(substream, NULL, newpos, NULL, NULL);
945     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
946 
947     hr = CreateStreamOnHGlobal(NULL, TRUE, &copy_stream);
948     ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
949 
950     hr = IWICStream_CopyTo(substream, copy_stream, newpos, NULL, NULL);
951     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
952     IStream_Release(copy_stream);
953 
954     /* Commit */
955     hr = IWICStream_Commit(substream, STGC_DEFAULT);
956     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
957 
958     hr = IWICStream_Commit(substream, STGC_OVERWRITE);
959     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
960 
961     hr = IWICStream_Commit(substream, STGC_ONLYIFCURRENT);
962     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
963 
964     hr = IWICStream_Commit(substream, STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
965     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
966 
967     hr = IWICStream_Commit(substream, STGC_CONSOLIDATE);
968     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
969 
970     /* Revert */
971     IWICStream_Write(substream, buff + 5, 6, NULL);
972     hr = IWICStream_Revert(substream);
973     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
974     memcpy(memory, data, sizeof(memory));
975 
976     /* LockRegion/UnlockRegion */
977     hr = IWICStream_LockRegion(substream, uzero, uzero, 0);
978     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
979 
980     hr = IWICStream_UnlockRegion(substream, uzero, uzero, 0);
981     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
982 
983     /* Stat */
984     hr = IWICStream_Stat(substream, NULL, 0);
985     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
986 
987     hr = IWICStream_Stat(substream, &stats, 0);
988     ok(hr == S_OK, "Failed to get stream stats, hr %#x.\n", hr);
989     ok(stats.pwcsName == NULL, "Unexpected name %p.\n", stats.pwcsName);
990     ok(stats.type == STGTY_STREAM, "Unexpected type %d.\n", stats.type);
991     ok(stats.cbSize.QuadPart == sizeof(data), "Unexpected size %s.\n", wine_dbgstr_longlong(stats.cbSize.QuadPart));
992     ok(stats.mtime.dwHighDateTime == 0 && stats.mtime.dwLowDateTime == 0, "Unexpected mtime (%u;%u).\n",
993         stats.mtime.dwHighDateTime, stats.mtime.dwLowDateTime);
994     ok(stats.ctime.dwHighDateTime == 0 && stats.ctime.dwLowDateTime == 0, "Unexpected ctime (%u;%u).\n",
995         stats.ctime.dwHighDateTime, stats.ctime.dwLowDateTime);
996     ok(stats.atime.dwHighDateTime == 0 && stats.atime.dwLowDateTime == 0, "Unexpected atime (%u;%u).\n",
997         stats.atime.dwHighDateTime, stats.atime.dwLowDateTime);
998     ok(stats.grfMode == 0, "Unexpected mode %d.\n", stats.grfMode);
999     ok(stats.grfLocksSupported == 0, "Unexpected locks support %#x.\n", stats.grfLocksSupported);
1000     ok(stats.grfStateBits == 0, "Unexpected state bits %#x.\n", stats.grfStateBits);
1001 
1002     /* Clone */
1003     hr = IWICStream_Clone(substream, &copy_stream);
1004     ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
1005 
1006     IWICStream_Release(substream);
1007     IWICStream_Release(stream);
1008     IWICImagingFactory_Release(factory);
1009 }
1010 
START_TEST(stream)1011 START_TEST(stream)
1012 {
1013     CoInitialize(NULL);
1014 
1015     test_StreamOnMemory();
1016     test_StreamOnStreamRange();
1017     test_StreamOnIStream();
1018 
1019     CoUninitialize();
1020 }
1021