[WINDOWSCODECS_WINETEST] Sync with Wine Staging 4.0. CORE-15682
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Feb 2019 12:12:58 +0000 (13:12 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Feb 2019 12:12:58 +0000 (13:12 +0100)
modules/rostests/winetests/windowscodecs/CMakeLists.txt
modules/rostests/winetests/windowscodecs/bitmap.c
modules/rostests/winetests/windowscodecs/converter.c
modules/rostests/winetests/windowscodecs/icoformat.c
modules/rostests/winetests/windowscodecs/info.c
modules/rostests/winetests/windowscodecs/metadata.c
modules/rostests/winetests/windowscodecs/palette.c
modules/rostests/winetests/windowscodecs/pngformat.c
modules/rostests/winetests/windowscodecs/stream.c
modules/rostests/winetests/windowscodecs/tiffformat.c

index 0cffe52..6bae33b 100644 (file)
@@ -1,5 +1,7 @@
 
-add_definitions(-DUSE_WINE_TODOS)
+add_definitions(
+    -DUSE_WINE_TODOS
+    -DWINETEST_USE_DBGSTR_LONGLONG)
 
 list(APPEND SOURCE
     bitmap.c
index 6e01f0b..d4b5979 100644 (file)
@@ -452,6 +452,19 @@ static void test_createbitmapfromsource(void)
     hr = IWICBitmap_SetResolution(bitmap, 12.0, 34.0);
     ok(hr == S_OK, "IWICBitmap_SetResolution failed hr=%x\n", hr);
 
+    /* WICBitmapNoCache */
+    hr = IWICImagingFactory_CreateBitmapFromSource(factory, (IWICBitmapSource *)bitmap,
+        WICBitmapNoCache, &bitmap2);
+    ok(hr == S_OK, "IWICImagingFactory_CreateBitmapFromSource failed hr=%x\n", hr);
+    ok(bitmap2 == bitmap, "Unexpected bitmap instance.\n");
+
+    IWICBitmap_Release(bitmap2);
+
+    bitmap2 = (void *)0xdeadbeef;
+    hr = IWICImagingFactory_CreateBitmapFromSource(factory, &bitmapsource, WICBitmapNoCache, &bitmap2);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+    ok(bitmap2 == (void *)0xdeadbeef, "Unexpected pointer %p.\n", bitmap2);
+
     hr = IWICImagingFactory_CreateBitmapFromSource(factory, (IWICBitmapSource*)bitmap,
         WICBitmapCacheOnLoad, &bitmap2);
     ok(hr == S_OK, "IWICImagingFactory_CreateBitmapFromSource failed hr=%x\n", hr);
@@ -538,6 +551,43 @@ static void test_createbitmapfromsource(void)
     ok(width == 3, "got %d, expected 3\n", width);
     ok(height == 3, "got %d, expected 3\n", height);
 
+    /* CreateBitmapFromSourceRect */
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 0, 0, 16, 32, &bitmap);
+    ok(hr == S_OK, "Failed to create a bitmap, hr %#x.\n", hr);
+    hr = IWICBitmap_GetSize(bitmap, &width, &height);
+    ok(hr == S_OK, "Failed to get bitmap size, hr %#x.\n", hr);
+    ok(width == 3, "Unexpected width %u.\n", width);
+    ok(height == 3, "Unexpected height %u.\n", height);
+    IWICBitmap_Release(bitmap);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 0, 0, 1, 1, &bitmap);
+    ok(hr == S_OK, "Failed to create a bitmap, hr %#x.\n", hr);
+    hr = IWICBitmap_GetSize(bitmap, &width, &height);
+    ok(hr == S_OK, "Failed to get bitmap size, hr %#x.\n", hr);
+    ok(width == 1, "Unexpected width %u.\n", width);
+    ok(height == 1, "Unexpected height %u.\n", height);
+    IWICBitmap_Release(bitmap);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 2, 1, 16, 32, &bitmap);
+    ok(hr == S_OK, "Failed to create a bitmap, hr %#x.\n", hr);
+    hr = IWICBitmap_GetSize(bitmap, &width, &height);
+    ok(hr == S_OK, "Failed to get bitmap size, hr %#x.\n", hr);
+    ok(width == 1, "Unexpected width %u.\n", width);
+    ok(height == 2, "Unexpected height %u.\n", height);
+    IWICBitmap_Release(bitmap);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 0, 0, 0, 2, &bitmap);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 0, 0, 2, 0, &bitmap);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 1, 3, 16, 32, &bitmap);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICImagingFactory_CreateBitmapFromSourceRect(factory, (IWICBitmapSource *)bitmap2, 3, 1, 16, 32, &bitmap);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
     IWICBitmap_Release(bitmap2);
 }
 
@@ -1030,6 +1080,171 @@ static void test_WICCreateBitmapFromSectionEx(void)
     CloseHandle(hsection);
 }
 
+static void test_bitmap_scaler(void)
+{
+    WICPixelFormatGUID pixel_format;
+    IWICBitmapScaler *scaler;
+    IWICPalette *palette;
+    double res_x, res_y;
+    IWICBitmap *bitmap;
+    UINT width, height;
+    HRESULT hr;
+
+    hr = IWICImagingFactory_CreateBitmap(factory, 4, 2, &GUID_WICPixelFormat24bppBGR, WICBitmapCacheOnLoad, &bitmap);
+    ok(hr == S_OK, "Failed to create a bitmap, hr %#x.\n", hr);
+
+    hr = IWICBitmap_GetSize(bitmap, &width, &height);
+    ok(hr == S_OK, "Failed to get bitmap size, hr %#x.\n", hr);
+    ok(width == 4, "Unexpected width %u.\n", width);
+    ok(height == 2, "Unexpected height %u.\n", height);
+
+    hr = IWICBitmap_GetResolution(bitmap, &res_x, &res_y);
+    ok(hr == S_OK, "Failed to get bitmap resolution, hr %#x.\n", hr);
+    ok(res_x == 0.0 && res_y == 0.0, "Unexpected resolution %f x %f.\n", res_x, res_y);
+
+    hr = IWICImagingFactory_CreateBitmapScaler(factory, &scaler);
+    ok(hr == S_OK, "Failed to create bitmap scaler, hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, NULL, 0, 0,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 0, 0,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, NULL, &height);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, &width, NULL);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetResolution(scaler, NULL, NULL);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    res_x = 0.1;
+    hr = IWICBitmapScaler_GetResolution(scaler, &res_x, NULL);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+    ok(res_x == 0.1, "Unexpected resolution %f.\n", res_x);
+
+    hr = IWICBitmapScaler_GetResolution(scaler, NULL, &res_y);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetResolution(scaler, &res_x, &res_y);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetPixelFormat(scaler, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    memset(&pixel_format, 0, sizeof(pixel_format));
+    hr = IWICBitmapScaler_GetPixelFormat(scaler, &pixel_format);
+    ok(hr == S_OK, "Failed to get pixel format, hr %#x.\n", hr);
+    ok(IsEqualGUID(&pixel_format, &GUID_WICPixelFormatDontCare), "Unexpected pixel format %s.\n",
+        wine_dbgstr_guid(&pixel_format));
+
+    width = 123;
+    height = 321;
+    hr = IWICBitmapScaler_GetSize(scaler, &width, &height);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+    ok(width == 123, "Unexpected width %u.\n", width);
+    ok(height == 321, "Unexpected height %u.\n", height);
+
+    hr = IWICBitmapScaler_CopyPalette(scaler, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICImagingFactory_CreatePalette(factory, &palette);
+    ok(hr == S_OK, "Failed to create a palette, hr %#x.\n", hr);
+    hr = IWICBitmapScaler_CopyPalette(scaler, palette);
+    ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Unexpected hr %#x.\n", hr);
+    IWICPalette_Release(palette);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 4, 0,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, &width, &height);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 0, 2,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, &width, &height);
+    ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, NULL, 8, 4,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Failed to initialize bitmap scaler, hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 8, 4,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == S_OK, "Failed to initialize bitmap scaler, hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 0, 4,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 8, 0,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, NULL, 8, 4, WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 8, 4,
+        WICBitmapInterpolationModeNearestNeighbor);
+    ok(hr == WINCODEC_ERR_WRONGSTATE, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, &width, &height);
+    ok(hr == S_OK, "Failed to get scaler size, hr %#x.\n", hr);
+    ok(width == 8, "Unexpected width %u.\n", width);
+    ok(height == 4, "Unexpected height %u.\n", height);
+
+    hr = IWICBitmapScaler_GetSize(scaler, NULL, &height);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, &width, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetSize(scaler, NULL, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICBitmapScaler_GetPixelFormat(scaler, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    memset(&pixel_format, 0, sizeof(pixel_format));
+    hr = IWICBitmapScaler_GetPixelFormat(scaler, &pixel_format);
+    ok(hr == S_OK, "Failed to get pixel format, hr %#x.\n", hr);
+    ok(IsEqualGUID(&pixel_format, &GUID_WICPixelFormat24bppBGR), "Unexpected pixel format %s.\n",
+        wine_dbgstr_guid(&pixel_format));
+
+    hr = IWICBitmapScaler_GetResolution(scaler, NULL, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    res_x = 0.1;
+    hr = IWICBitmapScaler_GetResolution(scaler, &res_x, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(res_x == 0.1, "Unexpected resolution %f.\n", res_x);
+
+    hr = IWICBitmapScaler_GetResolution(scaler, NULL, &res_y);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    res_x = res_y = 1.0;
+    hr = IWICBitmapScaler_GetResolution(scaler, &res_x, &res_y);
+    ok(hr == S_OK, "Failed to get scaler resolution, hr %#x.\n", hr);
+    ok(res_x == 0.0 && res_y == 0.0, "Unexpected resolution %f x %f.\n", res_x, res_y);
+
+    hr = IWICImagingFactory_CreatePalette(factory, &palette);
+    ok(hr == S_OK, "Failed to create a palette, hr %#x.\n", hr);
+    hr = IWICBitmapScaler_CopyPalette(scaler, palette);
+    ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "Unexpected hr %#x.\n", hr);
+    IWICPalette_Release(palette);
+
+    IWICBitmapScaler_Release(scaler);
+
+    IWICBitmap_Release(bitmap);
+}
+
 START_TEST(bitmap)
 {
     HRESULT hr;
@@ -1046,6 +1261,7 @@ START_TEST(bitmap)
     test_CreateBitmapFromHICON();
     test_CreateBitmapFromHBITMAP();
     test_clipper();
+    test_bitmap_scaler();
 
     IWICImagingFactory_Release(factory);
 
index 91deda2..8682f87 100644 (file)
@@ -904,16 +904,6 @@ static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
         ok(samples == 1, "wrong samples %d\n", samples);
         ok(colormap == 6, "wrong colormap %d\n", colormap);
     }
-    else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
-    {
-        ok(width == 32, "wrong width %u\n", width);
-        ok(height == 2, "wrong height %u\n", height);
-
-        ok(bps == 2, "wrong bps %d\n", bps);
-        ok(photo == 3, "wrong photometric %d\n", photo);
-        ok(samples == 1, "wrong samples %d\n", samples);
-        ok(colormap == 12, "wrong colormap %d\n", colormap);
-    }
     else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
     {
         ok(width == 32, "wrong width %u\n", width);
@@ -976,18 +966,6 @@ static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
         ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
         ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
     }
-    else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
-    {
-        ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
-
-        ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
-        ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
-
-        ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
-        ok(bih.bV5BitCount == 2, "wrong BitCount %d\n", bih.bV5BitCount);
-        ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
-        ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
-    }
     else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
     {
         ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
@@ -1243,6 +1221,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
     const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
     const struct setting *settings, const char *name, IWICPalette *palette)
 {
+    const GUID *container_format = NULL;
     HRESULT hr;
     IWICBitmapEncoder *encoder;
     BitmapTestSrc *src_obj;
@@ -1253,6 +1232,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
     IWICBitmapDecoder *decoder;
     IWICBitmapFrameDecode *framedecode;
     WICPixelFormatGUID pixelformat;
+    GUID guid;
     int i;
 
     hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
@@ -1262,6 +1242,28 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
     ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
 
+    hr = IWICBitmapEncoder_GetContainerFormat(encoder, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
+        container_format = &GUID_ContainerFormatPng;
+    else if (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder))
+        container_format = &GUID_ContainerFormatBmp;
+    else if (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder))
+        container_format = &GUID_ContainerFormatTiff;
+    else if (IsEqualGUID(clsid_encoder, &CLSID_WICJpegEncoder))
+        container_format = &GUID_ContainerFormatJpeg;
+    else
+        ok(0, "Unknown encoder %s.\n", wine_dbgstr_guid(clsid_encoder));
+
+    if (container_format)
+    {
+        memset(&guid, 0, sizeof(guid));
+        hr = IWICBitmapEncoder_GetContainerFormat(encoder, &guid);
+        ok(SUCCEEDED(hr), "Failed to get container format, hr %#x.\n", hr);
+        ok(IsEqualGUID(container_format, &guid), "Unexpected container format %s.\n", wine_dbgstr_guid(&guid));
+    }
+
     hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
     ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
 
@@ -1288,6 +1290,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
 
         if (hglobal && SUCCEEDED(hr))
         {
+            IWICBitmapEncoderInfo *info = NULL;
+
             if (palette)
             {
                 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
@@ -1307,6 +1311,20 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
                 hr = S_OK;
             }
 
+            hr = IWICBitmapEncoder_GetEncoderInfo(encoder, &info);
+            ok(hr == S_OK || hr == WINCODEC_ERR_COMPONENTNOTFOUND, "wrong error %#x\n", hr);
+            if (SUCCEEDED(hr))
+            {
+                CLSID clsid;
+
+                hr = IWICBitmapEncoderInfo_GetCLSID(info, &clsid);
+                ok(hr == S_OK, "wrong error %#x\n", hr);
+                ok(!IsEqualGUID(&clsid_encoder, &clsid), "wrong CLSID %s (%s)\n",
+                       wine_dbgstr_guid(clsid_encoder), wine_dbgstr_guid(&clsid));
+
+                IWICBitmapEncoderInfo_Release(info);
+            }
+
             i=0;
             while (SUCCEEDED(hr) && srcs[i])
             {
@@ -1353,9 +1371,9 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
                     hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
                     ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
                     ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
-                       broken(IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
-                       broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
-                       "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
+                       (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
+                       (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
+                        "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
 
                     hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
                     ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
@@ -1390,8 +1408,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
                             ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
                         else
                             ok(hr == S_OK ||
-                               broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) /* XP */ ||
-                               broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) /* XP */ ||
+                               (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) ||
+                               (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) ||
                                broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
                                "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
                     }
@@ -1529,15 +1547,6 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls
                                     ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
                                     ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
                                 }
-                                else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat2bppIndexed))
-                                {
-                                    ok(count == 4, "expected 4, got %u (%s)\n", count, name);
-
-                                    ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
-                                    ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
-                                    ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
-                                    ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
-                                }
                                 else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed))
                                 {
                                     ok(count == 16, "expected 16, got %u (%s)\n", count, name);
@@ -1828,8 +1837,6 @@ START_TEST(converter)
                           &IID_IWICImagingFactory, (void **)&factory);
     ok(hr == S_OK, "failed to create factory: %#x\n", hr);
 
-    test_converter_8bppIndexed();
-
     test_conversion(&testdata_24bppRGB, &testdata_1bppIndexed, "24bppRGB -> 1bppIndexed", TRUE);
     test_conversion(&testdata_24bppRGB, &testdata_2bppIndexed, "24bppRGB -> 2bppIndexed", TRUE);
     test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE);
@@ -1870,6 +1877,7 @@ START_TEST(converter)
 
     test_invalid_conversion();
     test_default_converter();
+    test_converter_8bppIndexed();
 
     test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder,
                  &testdata_8bppIndexed, &CLSID_WICGifDecoder, "GIF encoder 8bppIndexed");
@@ -1897,7 +1905,7 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
     test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
                  &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
     test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
-                 &testdata_2bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
+                 &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
     test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
                  &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
     test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
@@ -1910,7 +1918,7 @@ if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in
     test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
                  &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
     test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
-                 &testdata_2bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
+                 &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
     test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
                  &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
     test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
index c53739d..38db51c 100644 (file)
 #include "wincodec.h"
 #include "wine/test.h"
 
-static unsigned char testico_bad_icondirentry_size[] = {
-    /* ICONDIR */
-    0, 0, /* reserved */
-    1, 0, /* type */
-    1, 0, /* count */
+#include "pshpack1.h"
+
+struct ICONHEADER
+{
+    WORD idReserved;
+    WORD idType;
+    WORD idCount;
+};
+
+struct ICONDIRENTRY
+{
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD wPlanes;
+    WORD wBitCount;
+    DWORD dwDIBSize;
+    DWORD dwDIBOffset;
+};
+
+struct test_ico
+{
+    struct ICONHEADER header;
+    struct ICONDIRENTRY direntry;
+    BITMAPINFOHEADER bmi;
+    unsigned char data[512];
+};
+
+static const struct test_ico ico_1 =
+{
+    /* ICONHEADER */
+    {
+      0, /* reserved */
+      1, /* type */
+      1, /* count */
+    },
     /* ICONDIRENTRY */
-    2, /* width */
-    2, /* height */
-    2, /* colorCount */
-    0, /* reserved */
-    1,0, /* planes */
-    8,0, /* bitCount */
-    (40+2*4+16*16+16*4) & 0xFF,((40+2*4+16*16+16*4) >> 8) & 0xFF,0,0, /* bytesInRes */
-    22,0,0,0, /* imageOffset */
+    {
+      16, /* width */
+      16, /* height */
+      2, /* color count */
+      0, /* reserved */
+      1, /* planes */
+      8, /* bitcount*/
+      40 + 2*4 + 16 * 16 + 16 * 4, /* data size */
+      22 /* data offset */
+    },
     /* BITMAPINFOHEADER */
-    40,0,0,0, /* header size */
-    16,0,0,0, /* width */
-    2*16,0,0,0, /* height (XOR+AND rows) */
-    1,0, /* planes */
-    8,0, /* bit count */
-    0,0,0,0, /* compression */
-    0,0,0,0, /* sizeImage */
-    0,0,0,0, /* x pels per meter */
-    0,0,0,0, /* y pels per meter */
-    2,0,0,0, /* clrUsed */
-    0,0,0,0, /* clrImportant */
-    /* palette */
-    0,0,0,0,
-    0xFF,0xFF,0xFF,0,
-    /* XOR mask */
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
-    0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
-    0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
-    0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
-    0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
-    0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
-    0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
-    0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
-    0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,
-    0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,
-    0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    /* AND mask */
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0,
-    0,0,0,0
+    {
+      sizeof(BITMAPINFOHEADER), /* header size */
+      16, /* width */
+      2*16, /* height (XOR+AND rows) */
+      1, /* planes */
+      8, /* bit count */
+      0, /* compression */
+      0, /* sizeImage */
+      0, /* x pels per meter */
+      0, /* y pels per meter */
+      2, /* clrUsed */
+      0, /* clrImportant */
+    },
+    {
+      /* palette */
+      0,0,0,0,
+      0xFF,0xFF,0xFF,0,
+      /* XOR mask */
+      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+      0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+      0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+      0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
+      0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
+      0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
+      0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,
+      0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
+      0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
+      0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,
+      0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,
+      0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,
+      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+      /* AND mask */
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0,
+      0,0,0,0
+    }
 };
 
-static void test_bad_icondirentry_size(void)
+#include "poppack.h"
+
+#define test_ico_data(a, b, c) test_ico_data_(a, b, c,  0, __LINE__)
+#define test_ico_data_todo(a, b, c) test_ico_data_(a, b, c, 1, __LINE__)
+static void test_ico_data_(void *data, DWORD data_size, HRESULT init_hr, int todo, unsigned int line)
 {
     IWICBitmapDecoder *decoder;
     IWICImagingFactory *factory;
@@ -108,8 +150,7 @@ static void test_bad_icondirentry_size(void)
     ok(hr == S_OK, "CreateStream failed, hr=%x\n", hr);
     if (SUCCEEDED(hr))
     {
-        hr = IWICStream_InitializeFromMemory(icostream, testico_bad_icondirentry_size,
-            sizeof(testico_bad_icondirentry_size));
+        hr = IWICStream_InitializeFromMemory(icostream, data, data_size);
         ok(hr == S_OK, "InitializeFromMemory failed, hr=%x\n", hr);
 
         if (SUCCEEDED(hr))
@@ -123,7 +164,8 @@ static void test_bad_icondirentry_size(void)
         {
             hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)icostream,
                 WICDecodeMetadataCacheOnDemand);
-            ok(hr == S_OK, "Initialize failed, hr=%x\n", hr);
+        todo_wine_if(todo)
+            ok_(__FILE__, line)(hr == init_hr, "Initialize failed, hr=%x\n", hr);
 
             if (SUCCEEDED(hr))
             {
@@ -163,11 +205,44 @@ static void test_bad_icondirentry_size(void)
     IWICImagingFactory_Release(factory);
 }
 
+static void test_decoder(void)
+{
+    struct test_ico ico;
+
+    /* Icon size specified in ICONDIRENTRY does not match bitmap header. */
+    ico = ico_1;
+    ico.direntry.bWidth = 2;
+    ico.direntry.bHeight = 2;
+    test_ico_data(&ico, sizeof(ico), S_OK);
+
+    /* Invalid DIRENTRY data size/offset. */
+    ico = ico_1;
+    ico.direntry.dwDIBOffset = sizeof(ico);
+    test_ico_data(&ico, sizeof(ico), WINCODEC_ERR_BADIMAGE);
+
+    ico = ico_1;
+    ico.direntry.dwDIBSize = sizeof(ico);
+    test_ico_data(&ico, sizeof(ico), WINCODEC_ERR_BADIMAGE);
+
+    /* Header fields validation. */
+    ico = ico_1;
+    ico.header.idReserved = 1;
+    test_ico_data_todo(&ico, sizeof(ico), S_OK);
+    ico.header.idReserved = 0;
+    ico.header.idType = 100;
+    test_ico_data_todo(&ico, sizeof(ico), S_OK);
+
+    /* Premature end of data. */
+    ico = ico_1;
+    test_ico_data(&ico, sizeof(ico.header) - 1, WINCODEC_ERR_STREAMREAD);
+    test_ico_data(&ico, sizeof(ico.header) + sizeof(ico.direntry) - 1, WINCODEC_ERR_BADIMAGE);
+}
+
 START_TEST(icoformat)
 {
     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 
-    test_bad_icondirentry_size();
+    test_decoder();
 
     CoUninitialize();
 }
index d00e9d8..ee95784 100644 (file)
@@ -119,7 +119,7 @@ static void test_decoder_info(void)
     UINT num_formats, count;
     int i, j;
 
-    for (i = 0; i < sizeof(decoder_info_tests)/sizeof(decoder_info_tests[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(decoder_info_tests); i++)
     {
         struct decoder_info_test *test = &decoder_info_tests[i];
         IWICBitmapDecoder *decoder, *decoder2;
@@ -149,8 +149,8 @@ static void test_decoder_info(void)
         }
         IWICBitmapDecoder_Release(decoder);
 
-        MultiByteToWideChar(CP_ACP, 0, test->mimetype, -1, mimetypeW, sizeof(mimetypeW)/sizeof(mimetypeW[0]));
-        MultiByteToWideChar(CP_ACP, 0, test->extensions, -1, extensionsW, sizeof(extensionsW)/sizeof(extensionsW[0]));
+        MultiByteToWideChar(CP_ACP, 0, test->mimetype, -1, mimetypeW, ARRAY_SIZE(mimetypeW));
+        MultiByteToWideChar(CP_ACP, 0, test->extensions, -1, extensionsW, ARRAY_SIZE(extensionsW));
 
         hr = get_component_info(test->clsid, &info);
         ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr);
@@ -234,8 +234,8 @@ static void test_decoder_info(void)
         ok(hr == E_INVALIDARG, "GetPixelFormats failed, hr=%x\n", hr);
 
         count = 0xdeadbeef;
-        hr = IWICBitmapDecoderInfo_GetPixelFormats(decoder_info, sizeof(pixelformats)/sizeof(pixelformats[0]),
-            pixelformats, &count);
+        hr = IWICBitmapDecoderInfo_GetPixelFormats(decoder_info, ARRAY_SIZE(pixelformats),
+                                                   pixelformats, &count);
         ok(hr == S_OK, "GetPixelFormats failed, hr=%x\n", hr);
         ok(count == num_formats, "got %d formats, expected %d\n", count, num_formats);
 
@@ -637,6 +637,38 @@ todo_wine
     IWICImagingFactory_Release(factory);
 }
 
+static void test_imagingfactory_interfaces(void)
+{
+    IWICComponentFactory *component_factory;
+    IWICImagingFactory2 *factory2;
+    IWICImagingFactory *factory;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IWICImagingFactory2, (void **)&factory2);
+    if (FAILED(hr))
+    {
+        win_skip("IWICImagingFactory2 is not supported.\n");
+        return;
+    }
+
+    hr = IWICImagingFactory2_QueryInterface(factory2, &IID_IWICComponentFactory, (void **)&component_factory);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICComponentFactory_QueryInterface(component_factory, &IID_IWICImagingFactory, (void **)&factory);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(factory == (IWICImagingFactory *)component_factory, "Unexpected factory pointer.\n");
+    IWICImagingFactory_Release(factory);
+
+    hr = IWICImagingFactory2_QueryInterface(factory2, &IID_IWICImagingFactory, (void **)&factory);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(factory == (IWICImagingFactory *)component_factory, "Unexpected factory pointer.\n");
+
+    IWICComponentFactory_Release(component_factory);
+    IWICImagingFactory2_Release(factory2);
+    IWICImagingFactory_Release(factory);
+}
+
 START_TEST(info)
 {
     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
@@ -644,6 +676,7 @@ START_TEST(info)
     test_decoder_info();
     test_reader_info();
     test_pixelformat_info();
+    test_imagingfactory_interfaces();
 
     CoUninitialize();
 }
index 1d4203d..91a5d20 100644 (file)
@@ -23,6 +23,9 @@
 #include <assert.h>
 
 #define COBJMACROS
+#ifdef __REACTOS__
+#define CONST_VTABLE
+#endif
 
 #include "windef.h"
 #include "objbase.h"
@@ -816,7 +819,7 @@ static void test_metadata_IFD(void)
 
     hr = IWICMetadataReader_GetCount(reader, &count);
     ok(hr == S_OK, "GetCount error %#x\n", hr);
-    ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+    ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
     compare_metadata(reader, td, count);
 
@@ -832,7 +835,7 @@ static void test_metadata_IFD(void)
     load_stream((IUnknown *)reader, IFD_data_swapped, sizeof(IFD_data), persist_options);
     hr = IWICMetadataReader_GetCount(reader, &count);
     ok(hr == S_OK, "GetCount error %#x\n", hr);
-    ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+    ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
     compare_metadata(reader, td, count);
     HeapFree(GetProcessHeap(), 0, IFD_data_swapped);
 
@@ -1271,7 +1274,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(gif_LSD)/sizeof(gif_LSD[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(gif_LSD), "unexpected count %u\n", count);
 
             compare_metadata(reader, gif_LSD, count);
 
@@ -1320,7 +1323,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(gif_IMD)/sizeof(gif_IMD[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(gif_IMD), "unexpected count %u\n", count);
 
             compare_metadata(reader, gif_IMD, count);
 
@@ -1374,7 +1377,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_LSD)/sizeof(animated_gif_LSD[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_LSD), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_LSD, count);
 
@@ -1393,7 +1396,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_APE)/sizeof(animated_gif_APE[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_APE), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_APE, count);
 
@@ -1412,7 +1415,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_comment_1)/sizeof(animated_gif_comment_1[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_comment_1), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_comment_1, count);
 
@@ -1431,7 +1434,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_plain_1)/sizeof(animated_gif_plain_1[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_plain_1), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_plain_1, count);
 
@@ -1480,7 +1483,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_IMD)/sizeof(animated_gif_IMD[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_IMD), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_IMD, count);
 
@@ -1499,7 +1502,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_comment_2)/sizeof(animated_gif_comment_2[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_comment_2), "unexpected count %u\n", count);
 
             if (count == 1)
             compare_metadata(reader, animated_gif_comment_2, count);
@@ -1519,7 +1522,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_plain_2)/sizeof(animated_gif_plain_2[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_plain_2), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_plain_2, count);
 
@@ -1538,7 +1541,7 @@ static void test_metadata_gif(void)
 
             hr = IWICMetadataReader_GetCount(reader, &count);
             ok(hr == S_OK, "GetCount error %#x\n", hr);
-            ok(count == sizeof(animated_gif_GCE)/sizeof(animated_gif_GCE[0]), "unexpected count %u\n", count);
+            ok(count == ARRAY_SIZE(animated_gif_GCE), "unexpected count %u\n", count);
 
             compare_metadata(reader, animated_gif_GCE, count);
 
@@ -1599,13 +1602,17 @@ static void test_metadata_gif(void)
         ok(len == 2, "expected 2, got %u\n", len);
         ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
 
-        for (i = 0; i < sizeof(decoder_data)/sizeof(decoder_data[0]); i++)
+        for (i = 0; i < ARRAY_SIZE(decoder_data); i++)
         {
             WCHAR queryW[256];
 
             if (winetest_debug > 1)
                 trace("query: %s\n", decoder_data[i].query);
             MultiByteToWideChar(CP_ACP, 0, decoder_data[i].query, -1, queryW, 256);
+
+            hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, NULL);
+            ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
+
             PropVariantInit(&value);
             hr = IWICMetadataQueryReader_GetMetadataByName(queryreader, queryW, &value);
             ok(hr == decoder_data[i].hr, "GetMetadataByName(%s) returned %#x, expected %#x\n", wine_dbgstr_w(queryW), hr, decoder_data[i].hr);
@@ -1622,7 +1629,7 @@ static void test_metadata_gif(void)
                 ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
                 ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
 
-                for (j = 0; j < sizeof(decoder_data)/sizeof(decoder_data[0]); j++)
+                for (j = 0; j < ARRAY_SIZE(decoder_data); j++)
                 {
                     MultiByteToWideChar(CP_ACP, 0, decoder_data[j].query, -1, queryW, 256);
 
@@ -1698,7 +1705,7 @@ static void test_metadata_gif(void)
         ok(len == 2, "expected 2, got %u\n", len);
         ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
 
-        for (i = 0; i < sizeof(frame_data)/sizeof(frame_data[0]); i++)
+        for (i = 0; i < ARRAY_SIZE(frame_data); i++)
         {
             if (winetest_debug > 1)
                 trace("query: %s\n", frame_data[i].query);
@@ -1812,7 +1819,7 @@ static void test_metadata_LSD(void)
     {
         hr = IWICMetadataReader_GetCount(reader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
-        ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+        ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
         compare_metadata(reader, td, count);
 
@@ -1890,7 +1897,7 @@ static void test_metadata_IMD(void)
     {
         hr = IWICMetadataReader_GetCount(reader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
-        ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+        ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
         compare_metadata(reader, td, count);
 
@@ -1965,7 +1972,7 @@ static void test_metadata_GCE(void)
     {
         hr = IWICMetadataReader_GetCount(reader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
-        ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+        ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
         compare_metadata(reader, td, count);
 
@@ -2038,7 +2045,7 @@ static void test_metadata_APE(void)
     {
         hr = IWICMetadataReader_GetCount(reader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
-        ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+        ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
         compare_metadata(reader, td, count);
 
@@ -2122,7 +2129,7 @@ static void test_metadata_GIF_comment(void)
     {
         hr = IWICMetadataReader_GetCount(reader, &count);
         ok(hr == S_OK, "GetCount error %#x\n", hr);
-        ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+        ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
 
         compare_metadata(reader, td, count);
 
@@ -2425,9 +2432,9 @@ static void test_WICMapSchemaToName(void)
         return;
     }
 
-    for (i = 0; i < sizeof(guid_list)/sizeof(guid_list[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(guid_list); i++)
     {
-        for (j = 0; j < sizeof(schema_list)/sizeof(schema_list[0]); j++)
+        for (j = 0; j < ARRAY_SIZE(schema_list); j++)
         {
             hr = WICMapSchemaToName(guid_list[i], schema_list[j], 0, NULL, &len);
             if (IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMP) ||
@@ -2685,7 +2692,7 @@ static HRESULT WINAPI mdr_GetEnumerator(IWICMetadataReader *iface, IWICEnumMetad
     return E_NOTIMPL;
 }
 
-static /* const */ IWICMetadataReaderVtbl mdr_vtbl =
+static const IWICMetadataReaderVtbl mdr_vtbl =
 {
     mdr_QueryInterface,
     mdr_AddRef,
@@ -2775,7 +2782,7 @@ static HRESULT WINAPI mdbr_GetEnumerator(IWICMetadataBlockReader *iface, IEnumUn
     return E_NOTIMPL;
 }
 
-static /* const */ IWICMetadataBlockReaderVtbl mdbr_vtbl =
+static const IWICMetadataBlockReaderVtbl mdbr_vtbl =
 {
     mdbr_QueryInterface,
     mdbr_AddRef,
@@ -2959,7 +2966,7 @@ static void test_queryreader(void)
     hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &mdbr, &reader);
     ok(hr == S_OK, "CreateQueryReaderFromBlockReader error %#x\n", hr);
 
-    for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(test_data); i++)
     {
         current_metadata = test_data[i].data;
 
index 33fd119..5bb25fa 100644 (file)
@@ -462,7 +462,7 @@ static void test_predefined_palette(void)
     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
     IWICPalette_Release(palette);
 
-    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(td); i++)
     {
         hr = IWICImagingFactory_CreatePalette(factory, &palette);
         ok(hr == S_OK, "%u: CreatePalette error %#x\n", i, hr);
index 3a0ea28..8c33d3b 100644 (file)
@@ -306,6 +306,8 @@ static HRESULT create_decoder(const void *image_data, UINT image_size, IWICBitma
         refcount = IStream_Release(stream);
         ok(refcount > 0, "expected stream refcount > 0\n");
     }
+    else
+        IStream_Release(stream);
 
     return hr;
 }
@@ -539,6 +541,15 @@ static const char png_PLTE_tRNS[] = {
   0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
 };
 
+/* grayscale 16 bpp 1x1 pixel PNG image with tRNS chunk */
+static const char png_gray_tRNS[] = {
+  0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
+  0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x6a,0xee,0x47,0x16,
+  0x00,0x00,0x00,0x02,'t','R','N','S',0x00,0x00,0x76,0x93,0xcd,0x38,
+  0x00,0x00,0x00,0x0b,'I','D','A','T',0x78,0x9c,0x63,0x60,0x60,0x00,0x00,0x00,0x03,0x00,0x01,0xb8,0xad,0x3a,0x63,
+  0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
+};
+
 static void test_png_palette(void)
 {
     HRESULT hr;
@@ -548,6 +559,7 @@ static void test_png_palette(void)
     GUID format;
     UINT count, ret;
     WICColor color[256];
+    char *buf;
 
     hr = create_decoder(png_PLTE_tRNS, sizeof(png_PLTE_tRNS), &decoder);
     ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr);
@@ -579,6 +591,64 @@ static void test_png_palette(void)
     IWICPalette_Release(palette);
     IWICBitmapFrameDecode_Release(frame);
     IWICBitmapDecoder_Release(decoder);
+
+    hr = create_decoder(png_gray_tRNS, sizeof(png_gray_tRNS), &decoder);
+    ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr);
+    if (hr != S_OK) return;
+
+    hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
+    ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+    hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
+    ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_WICPixelFormat64bppRGBA),
+       "got wrong format %s\n", wine_dbgstr_guid(&format));
+
+    hr = IWICImagingFactory_CreatePalette(factory, &palette);
+    ok(hr == S_OK, "CreatePalette error %#x\n", hr);
+    hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
+    ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "CopyPalette error %#x\n", hr);
+
+    IWICPalette_Release(palette);
+    IWICBitmapFrameDecode_Release(frame);
+    IWICBitmapDecoder_Release(decoder);
+
+    /* test 8 bpp grayscale PNG image with tRNS chunk */
+    buf = HeapAlloc(GetProcessHeap(), 0, sizeof(png_gray_tRNS));
+    memcpy(buf, png_gray_tRNS, sizeof(png_gray_tRNS));
+    buf[24] = 8; /* override bit depth */
+
+    hr = create_decoder(buf, sizeof(png_gray_tRNS), &decoder);
+    ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr);
+    if (hr != S_OK) return;
+
+    hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
+    ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+    hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
+    ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
+       "got wrong format %s\n", wine_dbgstr_guid(&format));
+
+    hr = IWICImagingFactory_CreatePalette(factory, &palette);
+    ok(hr == S_OK, "CreatePalette error %#x\n", hr);
+    hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
+    ok(hr == S_OK, "CopyPalette error %#x\n", hr);
+
+    hr = IWICPalette_GetColorCount(palette, &count);
+    ok(hr == S_OK, "GetColorCount error %#x\n", hr);
+    ok(count == 256, "expected 256, got %u\n", count);
+
+    hr = IWICPalette_GetColors(palette, 256, color, &ret);
+    ok(hr == S_OK, "GetColors error %#x\n", hr);
+    ok(ret == count, "expected %u, got %u\n", count, ret);
+    ok(color[0] == 0x00000000, "expected 0x00000000, got %#x\n", color[0]);
+    ok(color[1] == 0xff010101, "expected 0xff010101, got %#x\n", color[1]);
+
+    HeapFree(GetProcessHeap(), 0, buf);
+    IWICPalette_Release(palette);
+    IWICBitmapFrameDecode_Release(frame);
+    IWICBitmapDecoder_Release(decoder);
 }
 
 /* RGB 24 bpp 1x1 pixel PNG image */
@@ -624,23 +694,29 @@ static const char png_1x1_data[] = {
   0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
 };
 
+#define PNG_COLOR_TYPE_GRAY 0
+#define PNG_COLOR_TYPE_RGB 2
+#define PNG_COLOR_TYPE_PALETTE 3
+#define PNG_COLOR_TYPE_GRAY_ALPHA 4
+#define PNG_COLOR_TYPE_RGB_ALPHA 6
+
 static BOOL is_valid_png_type_depth(int color_type, int bit_depth, BOOL plte)
 {
     switch (color_type)
     {
-    case 0: /* Grayscale */
+    case PNG_COLOR_TYPE_GRAY:
         return bit_depth == 1 || bit_depth == 2 || bit_depth == 4 || bit_depth == 8 || bit_depth == 16;
 
-    case 2: /* True Color */
+    case PNG_COLOR_TYPE_RGB:
         return bit_depth == 8 || bit_depth == 16;
 
-    case 3: /* Indexed Color */
+    case PNG_COLOR_TYPE_PALETTE:
         return (bit_depth == 1 || bit_depth == 2 || bit_depth == 4 || bit_depth == 8) && plte;
 
-    case 4: /* Grayscale with alpha */
+    case PNG_COLOR_TYPE_GRAY_ALPHA:
         return bit_depth == 8 || bit_depth == 16;
 
-    case 6: /* True Color with alpha */
+    case PNG_COLOR_TYPE_RGB_ALPHA:
         return bit_depth == 8 || bit_depth == 16;
 
     default:
@@ -662,33 +738,44 @@ static void test_color_formats(void)
     } td[] =
     {
         /* 2 - PNG_COLOR_TYPE_RGB */
-        { 1, 2, NULL, NULL, NULL },
-        { 2, 2, NULL, NULL, NULL },
-        { 4, 2, NULL, NULL, NULL },
-        { 8, 2, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppBGR },
+        { 1, PNG_COLOR_TYPE_RGB, NULL, NULL, NULL },
+        { 2, PNG_COLOR_TYPE_RGB, NULL, NULL, NULL },
+        { 4, PNG_COLOR_TYPE_RGB, NULL, NULL, NULL },
+        { 8, PNG_COLOR_TYPE_RGB,
+          &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppBGR },
         /* libpng refuses to load our test image complaining about extra compressed data,
          * but libpng is still able to load the image with other combination of type/depth
          * making RGB 16 bpp case special for some reason. Therefore todo = TRUE.
          */
-        { 16, 2, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat48bppRGB, TRUE, TRUE },
-        { 24, 2, NULL, NULL, NULL },
-        { 32, 2, NULL, NULL, NULL },
+        { 16, PNG_COLOR_TYPE_RGB,
+          &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat48bppRGB, TRUE, TRUE },
+        { 24, PNG_COLOR_TYPE_RGB, NULL, NULL, NULL },
+        { 32, PNG_COLOR_TYPE_RGB, NULL, NULL, NULL },
         /* 0 - PNG_COLOR_TYPE_GRAY */
-        { 1, 0, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed },
-        { 2, 0, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed },
-        { 4, 0, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed },
-        { 8, 0, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed },
-        { 16, 0, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA },
-        { 24, 0, NULL, NULL, NULL },
-        { 32, 0, NULL, NULL, NULL },
+        { 1, PNG_COLOR_TYPE_GRAY,
+          &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed },
+        { 2, PNG_COLOR_TYPE_GRAY,
+          &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed },
+        { 4, PNG_COLOR_TYPE_GRAY,
+          &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed },
+        { 8, PNG_COLOR_TYPE_GRAY,
+          &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed },
+        { 16, PNG_COLOR_TYPE_GRAY,
+          &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA },
+        { 24, PNG_COLOR_TYPE_GRAY, NULL, NULL, NULL },
+        { 32, PNG_COLOR_TYPE_GRAY, NULL, NULL, NULL },
         /* 3 - PNG_COLOR_TYPE_PALETTE */
-        { 1, 3, &GUID_WICPixelFormat1bppIndexed, &GUID_WICPixelFormat1bppIndexed, &GUID_WICPixelFormat1bppIndexed },
-        { 2, 3, &GUID_WICPixelFormat2bppIndexed, &GUID_WICPixelFormat2bppIndexed, &GUID_WICPixelFormat2bppIndexed },
-        { 4, 3, &GUID_WICPixelFormat4bppIndexed, &GUID_WICPixelFormat4bppIndexed, &GUID_WICPixelFormat4bppIndexed },
-        { 8, 3, &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat8bppIndexed },
-        { 16, 3, NULL, NULL, NULL },
-        { 24, 3,  NULL, NULL, NULL },
-        { 32, 3,  NULL, NULL, NULL },
+        { 1, PNG_COLOR_TYPE_PALETTE,
+          &GUID_WICPixelFormat1bppIndexed, &GUID_WICPixelFormat1bppIndexed, &GUID_WICPixelFormat1bppIndexed },
+        { 2, PNG_COLOR_TYPE_PALETTE,
+          &GUID_WICPixelFormat2bppIndexed, &GUID_WICPixelFormat2bppIndexed, &GUID_WICPixelFormat2bppIndexed },
+        { 4, PNG_COLOR_TYPE_PALETTE,
+          &GUID_WICPixelFormat4bppIndexed, &GUID_WICPixelFormat4bppIndexed, &GUID_WICPixelFormat4bppIndexed },
+        { 8, PNG_COLOR_TYPE_PALETTE,
+          &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat8bppIndexed },
+        { 16, PNG_COLOR_TYPE_PALETTE, NULL, NULL, NULL },
+        { 24, PNG_COLOR_TYPE_PALETTE, NULL, NULL, NULL },
+        { 32, PNG_COLOR_TYPE_PALETTE, NULL, NULL, NULL },
     };
     char buf[sizeof(png_1x1_data)];
     HRESULT hr;
@@ -717,7 +804,7 @@ static void test_color_formats(void)
      * with tEXt id.
      */
 
-    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(td); i++)
     {
         /* with the tRNS and PLTE chunks */
         memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
@@ -829,6 +916,11 @@ todo_wine_if(td[i].todo)
         IWICBitmapDecoder_Release(decoder);
     }
 }
+#undef PNG_COLOR_TYPE_GRAY
+#undef PNG_COLOR_TYPE_RGB
+#undef PNG_COLOR_TYPE_PALETTE
+#undef PNG_COLOR_TYPE_GRAY_ALPHA
+#undef PNG_COLOR_TYPE_RGB_ALPHA
 
 START_TEST(pngformat)
 {
index 5f311b8..3750c32 100644 (file)
 #define COBJMACROS
 #include "wincodec.h"
 
+#define CHECK_CUR_POS(a, b) _check_cur_pos((IStream *)a, b, FALSE, __LINE__)
+#define CHECK_CUR_POS_TODO(a, b) _check_cur_pos((IStream *)a, b, TRUE, __LINE__)
+static void _check_cur_pos(IStream *stream, ULONGLONG expected_pos, BOOL todo, unsigned int line)
+{
+    LARGE_INTEGER offset;
+    ULARGE_INTEGER pos;
+    HRESULT hr;
+
+    offset.QuadPart = 0;
+    hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, &pos);
+    ok_(__FILE__, line)(hr == S_OK, "Failed to get current position, hr %#x.\n", hr);
+todo_wine_if(todo)
+    ok_(__FILE__, line)(pos.QuadPart == expected_pos, "Unexpected stream position %s.\n",
+        wine_dbgstr_longlong(pos.QuadPart));
+}
+
 static void test_StreamOnMemory(void)
 {
     IWICImagingFactory *pFactory;
@@ -51,8 +67,6 @@ static void test_StreamOnMemory(void)
 
     memcpy(Memory, CmpMem, sizeof(CmpMem));
 
-    CoInitialize(NULL);
-
     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&pFactory);
     if(FAILED(hr)) {
         skip("CoCreateInstance returned with %#x, expected %#x\n", hr, S_OK);
@@ -113,9 +127,7 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = sizeof(Memory) + 10;
     uNewPos.u.HighPart = 0xdeadbeef;
@@ -123,9 +135,7 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = 1;
     uNewPos.u.HighPart = 0xdeadbeef;
@@ -133,9 +143,7 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
     ok(hr == E_INVALIDARG, "Seek returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = -1;
     hr = IWICStream_Seek(pStream, LargeInt, STREAM_SEEK_END, &uNewPos);
@@ -150,12 +158,9 @@ static void test_StreamOnMemory(void)
     ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW),
        "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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 */
+    CHECK_CUR_POS(pStream, 0);
     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
 
-
     /* Read */
     hr = IWICStream_Read(pStream, MemBuf, 12, &uBytesRead);
     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
@@ -164,8 +169,7 @@ static void test_StreamOnMemory(void)
         ok(memcmp(MemBuf, CmpMem, 12) == 0, "Read returned invalid data!\n");
 
         /* check whether the seek pointer has moved correctly */
-        IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-        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);
+        CHECK_CUR_POS(pStream, uBytesRead);
     }
 
     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
@@ -234,8 +238,7 @@ static void test_StreamOnMemory(void)
         ok(memcmp(MemBuf, Memory, 3) == 0, "Wrote returned invalid data!\n"); /* make sure we're writing directly */
 
         /* check whether the seek pointer has moved correctly */
-        IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-        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);
+        CHECK_CUR_POS(pStream, uBytesWritten);
     }
     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
 
@@ -262,22 +265,19 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_Write(pStream, NULL, 3, &uBytesWritten);
     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     uBytesWritten = 0xdeadbeef;
     hr = IWICStream_Write(pStream, NULL, 0, &uBytesWritten);
     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     uBytesWritten = 0xdeadbeef;
     hr = IWICStream_Write(pStream, CmpMem, sizeof(Memory) + 10, &uBytesWritten);
     ok(hr == STG_E_MEDIUMFULL, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pStream, 0);
     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
 
 
@@ -380,7 +380,6 @@ static void test_StreamOnMemory(void)
 
     IWICStream_Release(pStream);
     IWICImagingFactory_Release(pFactory);
-    CoUninitialize();
 }
 
 static void test_StreamOnStreamRange(void)
@@ -441,13 +440,16 @@ static void test_StreamOnStreamRange(void)
     }
 
     /* Seek */
+    CHECK_CUR_POS(pStream, 0);
     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_END, &uNewPos);
     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);
     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
+    CHECK_CUR_POS(pStream, 0);
 
     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
     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);
+    CHECK_CUR_POS(pStream, 0);
 
     hr = IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
@@ -459,9 +461,7 @@ static void test_StreamOnStreamRange(void)
     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = 30;
     uNewPos.u.HighPart = 0xdeadbeef;
@@ -469,9 +469,7 @@ static void test_StreamOnStreamRange(void)
     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_SET, &uNewPos);
     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = 1;
     uNewPos.u.HighPart = 0xdeadbeef;
@@ -479,14 +477,13 @@ static void test_StreamOnStreamRange(void)
     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "Seek returned with %#x, expected %#x\n", hr, WINCODEC_ERR_VALUEOUTOFRANGE);
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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);
+    CHECK_CUR_POS(pStream, 0);
 
     LargeInt.QuadPart = -1;
     hr = IWICStream_Seek(pSubStream, LargeInt, STREAM_SEEK_END, &uNewPos);
     ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
     ok(uNewPos.u.HighPart == 0 && uNewPos.u.LowPart == 19, "bSeek cursor moved to position (%u;%u)\n", uNewPos.u.HighPart, uNewPos.u.LowPart);
+    CHECK_CUR_POS(pStream, 0);
 
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, &uNewPos); /* reset seek pointer */
     LargeInt.QuadPart = -25;
@@ -496,9 +493,7 @@ static void test_StreamOnStreamRange(void)
     ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE,
        "Seek returned with %#x, expected %#x\n", hr, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
     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);
-    hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    ok(hr == S_OK, "Seek returned with %#x, expected %#x\n", hr, S_OK);
-    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 */
+    CHECK_CUR_POS(pStream, 0);
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
 
 
@@ -510,8 +505,8 @@ static void test_StreamOnStreamRange(void)
         ok(memcmp(MemBuf, CmpMem+20, 12) == 0, "Read returned invalid data!\n");
 
         /* check whether the seek pointer has moved correctly */
-        IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-        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);
+        CHECK_CUR_POS(pSubStream, uBytesRead);
+        CHECK_CUR_POS(pStream, 0);
     }
 
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
@@ -522,6 +517,7 @@ static void test_StreamOnStreamRange(void)
         ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
     }
+    CHECK_CUR_POS(pStream, 0);
 
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
 
@@ -531,6 +527,7 @@ static void test_StreamOnStreamRange(void)
         ok(uBytesRead == 20, "Read %u bytes\n", uBytesRead);
         ok(memcmp(Memory, CmpMem+20, uBytesRead) == 0, "Read returned invalid data!\n");
     }
+    CHECK_CUR_POS(pStream, 0);
 
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
     uBytesRead = 0xdeadbeef;
@@ -574,8 +571,8 @@ static void test_StreamOnStreamRange(void)
         ok(memcmp(MemBuf, Memory+20, 3) == 0, "Wrote returned invalid data!\n"); /* make sure we're writing directly */
 
         /* check whether the seek pointer has moved correctly */
-        IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-        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);
+        CHECK_CUR_POS(pSubStream, uBytesWritten);
+        CHECK_CUR_POS(pStream, 0);
     }
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
 
@@ -586,21 +583,21 @@ static void test_StreamOnStreamRange(void)
     hr = IWICStream_Write(pSubStream, NULL, 3, &uBytesWritten);
     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pSubStream, 0);
+    CHECK_CUR_POS(pStream, 0);
 
     uBytesWritten = 0xdeadbeef;
     hr = IWICStream_Write(pSubStream, NULL, 0, &uBytesWritten);
     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pSubStream, 0);
+    CHECK_CUR_POS(pStream, 0);
 
     hr = IWICStream_Write(pSubStream, CmpMem, 30, &uBytesWritten);
     ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
     ok(uBytesWritten == 20, "Wrote %u bytes, expected %u\n", uBytesWritten, 0);
-    IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
+    CHECK_CUR_POS(pSubStream, uBytesWritten);
+    CHECK_CUR_POS(pStream, 0);
     IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_SET, NULL);
 
 
@@ -727,9 +724,8 @@ static void test_StreamOnStreamRange(void)
     hr = IWICStream_Write(pSubStream, CmpMem, 32, &uBytesWritten);
     ok(hr == STG_E_MEDIUMFULL, "Write returned with %#x, expected %#x\n", hr, STG_E_MEDIUMFULL);
     ok(uBytesWritten == 0xdeadbeef, "Expected uBytesWritten to be unchanged, got %u\n", uBytesWritten);
-    IWICStream_Seek(pSubStream, LargeNull, STREAM_SEEK_CUR, &uNewPos);
-    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);
-
+    CHECK_CUR_POS(pSubStream, 0);
+    CHECK_CUR_POS(pStream, 0);
 
     IWICStream_Release(pSubStream);
     IWICStream_Release(pStream);
@@ -737,8 +733,288 @@ static void test_StreamOnStreamRange(void)
     CoUninitialize();
 }
 
+static void test_StreamOnIStream(void)
+{
+    static const BYTE data[] =
+    {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    };
+    static const LARGE_INTEGER zero_pos;
+    static const ULARGE_INTEGER uzero;
+    IWICStream *stream, *substream;
+    IWICImagingFactory *factory;
+    BYTE memory[64], buff[64];
+    ULONG read_len, written;
+    ULARGE_INTEGER newpos;
+    IStream *copy_stream;
+    LARGE_INTEGER pos;
+    unsigned int i;
+    STATSTG stats;
+    HRESULT hr;
+
+    memcpy(memory, data, sizeof(data));
+
+    hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IWICImagingFactory, (void **)&factory);
+    ok(hr == S_OK, "Failed to create a factory, hr %#x.\n", hr);
+
+    hr = IWICImagingFactory_CreateStream(factory, &stream);
+    ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
+
+    hr = IWICStream_InitializeFromMemory(stream, memory, sizeof(memory));
+    ok(hr == S_OK, "Failed to initialize stream, hr %#x.", hr);
+
+    hr = IWICImagingFactory_CreateStream(factory, &substream);
+    ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
+
+    pos.QuadPart = 1;
+    hr = IWICStream_Seek(stream, pos, STREAM_SEEK_SET, &newpos);
+    ok(hr == S_OK, "Failed to set position, hr %#x.\n", hr);
+    CHECK_CUR_POS(stream, 1);
+
+    hr = IWICStream_InitializeFromIStream(substream, (IStream *)stream);
+    ok(hr == S_OK, "Failed to initialize stream, hr %#x.\n", hr);
+    CHECK_CUR_POS(substream, 1);
+
+    /* Seek */
+    CHECK_CUR_POS(stream, 1);
+    hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_END, &newpos);
+    ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
+    ok(newpos.QuadPart == sizeof(memory), "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(substream, sizeof(memory));
+    CHECK_CUR_POS(stream, sizeof(memory));
+
+    hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, &newpos);
+    ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
+    ok(newpos.QuadPart == 0, "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(stream, 0);
+    CHECK_CUR_POS(substream, 0);
+
+    hr = IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+    ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
+
+    pos.u.HighPart = 1;
+    pos.u.LowPart = 0;
+    newpos.u.HighPart = 0xdeadbeef;
+    newpos.u.LowPart = 0xdeadbeef;
+    hr = IWICStream_Seek(substream, pos, STREAM_SEEK_SET, &newpos);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "Unexpected hr %#x.\n", hr);
+    ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
+        wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(stream, 0);
+    CHECK_CUR_POS(substream, 0);
+
+    pos.QuadPart = sizeof(memory) + 1;
+    newpos.u.HighPart = 0xdeadbeef;
+    newpos.u.LowPart = 0xdeadbeef;
+    hr = IWICStream_Seek(substream, pos, STREAM_SEEK_SET, &newpos);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
+        wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(stream, 0);
+    CHECK_CUR_POS(substream, 0);
+
+    pos.QuadPart = 1;
+    newpos.u.HighPart = 0xdeadbeef;
+    newpos.u.LowPart = 0xdeadbeef;
+    hr = IWICStream_Seek(substream, pos, STREAM_SEEK_END, &newpos);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(newpos.u.HighPart == 0xdeadbeef && newpos.u.LowPart == 0xdeadbeef, "Unexpected position %s.\n",
+        wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(stream, 0);
+    CHECK_CUR_POS(substream, 0);
+
+    pos.QuadPart = -1;
+    hr = IWICStream_Seek(substream, pos, STREAM_SEEK_END, &newpos);
+    ok(hr == S_OK, "Failed to seek a stream, hr %#x.\n", hr);
+    ok(newpos.QuadPart == sizeof(memory) - 1, "Unexpected position %s.\n", wine_dbgstr_longlong(newpos.QuadPart));
+    CHECK_CUR_POS(stream, sizeof(memory) - 1);
+    CHECK_CUR_POS(substream, sizeof(memory) - 1);
+
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+
+    /* Read */
+    hr = IWICStream_Read(substream, buff, 12, &read_len);
+    ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
+    ok(read_len == 12, "Unexpected read length %u.\n", read_len);
+    ok(!memcmp(buff, data, 12), "Unexpected data.\n");
+    CHECK_CUR_POS(substream, read_len);
+    CHECK_CUR_POS(stream, read_len);
+
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+    CHECK_CUR_POS(stream, 0);
+
+    hr = IWICStream_Read(substream, memory, 10, &read_len);   /* source = dest */
+    ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
+    ok(read_len == 10, "Unexpected read length %u.\n", read_len);
+    ok(!memcmp(memory, data, read_len), "Unexpected data.\n");
+    CHECK_CUR_POS(stream, 10);
+
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+    hr = IWICStream_Read(substream, memory, 2 * sizeof(data), &read_len);   /* request too many bytes */
+    ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
+    ok(read_len == 64, "Unexpected read length %u.\n", read_len);
+    ok(!memcmp(memory, data, read_len), "Unexpected data.\n");
+    CHECK_CUR_POS(stream, sizeof(data));
+
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+    read_len = 0xdeadbeef;
+    hr = IWICStream_Read(substream, NULL, 1, &read_len);    /* destination buffer = NULL */
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(read_len == 0xdeadbeef, "Unexpected read length %u.\n", read_len);
+
+    read_len = 1;
+    hr = IWICStream_Read(substream, buff, 0, &read_len);    /* read 0 bytes */
+    ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
+    ok(read_len == 0, "Unexpected read length %u.\n", read_len);
+
+    read_len = 0xdeadbeef;
+    hr = IWICStream_Read(substream, NULL, 0, &read_len);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(read_len == 0xdeadbeef, "Unexpected read length %u.\n", read_len);
+
+    hr = IWICStream_Read(substream, NULL, 0, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Read(substream, buff, 1, NULL);
+    ok(hr == S_OK, "Failed to read from stream, hr %#x.\n", hr);
+    CHECK_CUR_POS(substream, 1);
+    CHECK_CUR_POS(stream, 1);
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+
+    /* Write */
+    for (i = 0; i < 3; ++i)
+        buff[i] = data[i] + 1;
+
+    hr = IWICStream_Write(substream, buff, 3, &written);
+    ok(hr == S_OK, "Failed to write to stream, hr %#x.\n", hr);
+    ok(written == 3, "Unexpected written length %u.\n", written);
+    ok(!memcmp(buff, memory, 3), "Unexpected stream data.\n");
+    CHECK_CUR_POS(substream, written);
+    CHECK_CUR_POS(stream, written);
+    IWICStream_Seek(substream, zero_pos, STREAM_SEEK_SET, NULL);
+
+    hr = IWICStream_Write(substream, buff, 0, &written);
+    ok(hr == S_OK, "Failed to write to stream, hr %#x.\n", hr);
+
+    written = 0xdeadbeef;
+    hr = IWICStream_Write(substream, NULL, 3, &written);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(written == 0xdeadbeef, "Unexpected written length %u.\n", written);
+    CHECK_CUR_POS(substream, 0);
+    CHECK_CUR_POS(stream, 0);
+
+    written = 0xdeadbeef;
+    hr = IWICStream_Write(substream, NULL, 0, &written);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    ok(written == 0xdeadbeef, "Unexpected written length %u.\n", written);
+    CHECK_CUR_POS(substream, 0);
+    CHECK_CUR_POS(stream, 0);
+
+    /* SetSize */
+    newpos.u.HighPart = 0;
+    newpos.u.LowPart = sizeof(memory) + 10;
+    hr = IWICStream_SetSize(substream, newpos);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    newpos.u.HighPart = 0;
+    newpos.u.LowPart = sizeof(memory);
+    hr = IWICStream_SetSize(substream, newpos);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    newpos.u.HighPart = 0;
+    newpos.u.LowPart = sizeof(memory) - 10;
+    hr = IWICStream_SetSize(substream, newpos);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    newpos.QuadPart = 0;
+    hr = IWICStream_SetSize(substream, newpos);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    newpos.QuadPart = -10;
+    hr = IWICStream_SetSize(substream, newpos);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    /* CopyTo */
+    newpos.u.HighPart = 0;
+    newpos.u.LowPart = 30;
+    hr = IWICStream_CopyTo(substream, NULL, newpos, NULL, NULL);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &copy_stream);
+    ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
+
+    hr = IWICStream_CopyTo(substream, copy_stream, newpos, NULL, NULL);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+    IStream_Release(copy_stream);
+
+    /* Commit */
+    hr = IWICStream_Commit(substream, STGC_DEFAULT);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Commit(substream, STGC_OVERWRITE);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Commit(substream, STGC_ONLYIFCURRENT);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Commit(substream, STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Commit(substream, STGC_CONSOLIDATE);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    /* Revert */
+    IWICStream_Write(substream, buff + 5, 6, NULL);
+    hr = IWICStream_Revert(substream);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+    memcpy(memory, data, sizeof(memory));
+
+    /* LockRegion/UnlockRegion */
+    hr = IWICStream_LockRegion(substream, uzero, uzero, 0);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_UnlockRegion(substream, uzero, uzero, 0);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    /* Stat */
+    hr = IWICStream_Stat(substream, NULL, 0);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IWICStream_Stat(substream, &stats, 0);
+    ok(hr == S_OK, "Failed to get stream stats, hr %#x.\n", hr);
+    ok(stats.pwcsName == NULL, "Unexpected name %p.\n", stats.pwcsName);
+    ok(stats.type == STGTY_STREAM, "Unexpected type %d.\n", stats.type);
+    ok(stats.cbSize.QuadPart == sizeof(data), "Unexpected size %s.\n", wine_dbgstr_longlong(stats.cbSize.QuadPart));
+    ok(stats.mtime.dwHighDateTime == 0 && stats.mtime.dwLowDateTime == 0, "Unexpected mtime (%u;%u).\n",
+        stats.mtime.dwHighDateTime, stats.mtime.dwLowDateTime);
+    ok(stats.ctime.dwHighDateTime == 0 && stats.ctime.dwLowDateTime == 0, "Unexpected ctime (%u;%u).\n",
+        stats.ctime.dwHighDateTime, stats.ctime.dwLowDateTime);
+    ok(stats.atime.dwHighDateTime == 0 && stats.atime.dwLowDateTime == 0, "Unexpected atime (%u;%u).\n",
+        stats.atime.dwHighDateTime, stats.atime.dwLowDateTime);
+    ok(stats.grfMode == 0, "Unexpected mode %d.\n", stats.grfMode);
+    ok(stats.grfLocksSupported == 0, "Unexpected locks support %#x.\n", stats.grfLocksSupported);
+    ok(stats.grfStateBits == 0, "Unexpected state bits %#x.\n", stats.grfStateBits);
+
+    /* Clone */
+    hr = IWICStream_Clone(substream, &copy_stream);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    IWICStream_Release(substream);
+    IWICStream_Release(stream);
+    IWICImagingFactory_Release(factory);
+}
+
 START_TEST(stream)
 {
+    CoInitialize(NULL);
+
     test_StreamOnMemory();
     test_StreamOnStreamRange();
+    test_StreamOnIStream();
+
+    CoUninitialize();
 }
index 5671dfb..289e061 100644 (file)
 #include "wincodec.h"
 #include "wine/test.h"
 
+#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
+static void _expect_ref(IUnknown* obj, ULONG ref, int line)
+{
+    ULONG rc;
+    IUnknown_AddRef(obj);
+    rc = IUnknown_Release(obj);
+    ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
+}
+
 #define IFD_BYTE 1
 #define IFD_ASCII 2
 #define IFD_SHORT 3
@@ -253,6 +262,46 @@ static struct tiff_resolution_image_data
     { 72, 1 }, /* value will be filled with test data */
     { 0x11, 0x22, 0x33, 0 }
 };
+
+static const struct tiff_24bpp_data
+{
+    USHORT byte_order;
+    USHORT version;
+    ULONG  dir_offset;
+    USHORT number_of_entries;
+    struct IFD_entry entry[13];
+    ULONG next_IFD;
+    struct IFD_rational res;
+    BYTE pixel_data[3];
+} tiff_24bpp_data =
+{
+#ifdef WORDS_BIGENDIAN
+    'M' | 'M' << 8,
+#else
+    'I' | 'I' << 8,
+#endif
+    42,
+    FIELD_OFFSET(struct tiff_1bpp_data, number_of_entries),
+    13,
+    {
+        { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
+        { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
+        { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
+        { 0x102, IFD_SHORT, 1, 8 }, /* BITSPERSAMPLE */
+        { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
+        { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
+        { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_24bpp_data, pixel_data) }, /* STRIPOFFSETS */
+        { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */
+        { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
+        { 0x117, IFD_LONG, 1, 3 }, /* STRIPBYTECOUNT */
+        { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_24bpp_data, res) }, /* XRESOLUTION */
+        { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_24bpp_data, res) }, /* YRESOLUTION */
+        { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
+    },
+    0,
+    { 900, 3 },
+    { 0x11, 0x22, 0x33 }
+};
 #include "poppack.h"
 
 static IWICImagingFactory *factory;
@@ -517,8 +566,11 @@ static void test_tiff_8bpp_alpha(void)
     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
     ok(frame_count == 1, "expected 1, got %u\n", frame_count);
 
+    EXPECT_REF(decoder, 1);
     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
     ok(hr == S_OK, "GetFrame error %#x\n", hr);
+    EXPECT_REF(decoder, 2);
+    IWICBitmapDecoder_Release(decoder);
 
     hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
     ok(hr == S_OK, "GetSize error %#x\n", hr);
@@ -553,7 +605,6 @@ static void test_tiff_8bpp_alpha(void)
         ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i, expected_data[i], data[i]);
 
     IWICBitmapFrameDecode_Release(frame);
-    IWICBitmapDecoder_Release(decoder);
 }
 
 static void generate_tiff_palette(void *buf, unsigned count)
@@ -642,7 +693,7 @@ static void test_tiff_resolution(void)
     double dpi_x, dpi_y;
     int i;
 
-    for (i = 0; i < sizeof(tiff_resolution_test_data)/sizeof(tiff_resolution_test_data[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(tiff_resolution_test_data); i++)
     {
         const struct tiff_resolution_test_data *test_data = &tiff_resolution_test_data[i];
         tiff_resolution_image_data.resx = test_data->resx;
@@ -686,6 +737,67 @@ static void test_tiff_resolution(void)
     }
 }
 
+static void test_tiff_24bpp(void)
+{
+    HRESULT hr;
+    IWICBitmapDecoder *decoder;
+    IWICBitmapFrameDecode *frame;
+    UINT count, width, height, i, stride;
+    double dpi_x, dpi_y;
+    GUID format;
+    WICRect rc;
+    BYTE data[3];
+    static const BYTE expected_data[] = { 0x33,0x22,0x11 };
+
+    hr = create_decoder(&tiff_24bpp_data, sizeof(tiff_24bpp_data), &decoder);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(decoder != NULL, "Failed to load TIFF image data\n");
+
+    hr = IWICBitmapDecoder_GetFrameCount(decoder, &count);
+    ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
+    ok(count == 1, "got %u\n", count);
+
+    hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
+    ok(hr == S_OK, "GetFrame error %#x\n", hr);
+
+    hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
+    ok(hr == S_OK, "GetSize error %#x\n", hr);
+    ok(width == 1, "got %u\n", width);
+    ok(height == 1, "got %u\n", height);
+
+    hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
+    ok(hr == S_OK, "GetResolution error %#x\n", hr);
+    ok(dpi_x == 300.0, "got %f\n", dpi_x);
+    ok(dpi_y == 300.0, "got %f\n", dpi_y);
+
+    hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
+    ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
+    ok(IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR),
+       "got wrong format %s\n", wine_dbgstr_guid(&format));
+
+    for (stride = 0; stride <= 32; stride++)
+    {
+        memset(data, 0, sizeof(data));
+        rc.X = 0;
+        rc.Y = 0;
+        rc.Width = 1;
+        rc.Height = 1;
+        hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, stride, sizeof(data), data);
+        if (stride < 3)
+            ok(hr == E_INVALIDARG, "CopyPixels(%u) should fail: %#x\n", stride, hr);
+        else
+        {
+            ok(hr == S_OK, "CopyPixels(%u) error %#x\n", stride, hr);
+
+            for (i = 0; i < sizeof(data); i++)
+                ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i, expected_data[i], data[i]);
+        }
+    }
+
+    IWICBitmapFrameDecode_Release(frame);
+    IWICBitmapDecoder_Release(decoder);
+}
+
 #include "pshpack2.h"
 static const struct tiff_1x1_data
 {
@@ -1083,6 +1195,7 @@ START_TEST(tiffformat)
     test_QueryCapability();
     test_tiff_8bpp_alpha();
     test_tiff_resolution();
+    test_tiff_24bpp();
 
     IWICImagingFactory_Release(factory);
     CoUninitialize();