Author: gschneider
Date: Thu Nov 27 14:52:01 2008
New Revision: 37695
URL: 
http://svn.reactos.org/svn/reactos?rev=37695&view=rev
Log:
Update gdi32 winetests, so we don't run out of things to fix.
Modified:
    trunk/rostests/winetests/gdi32/bitmap.c
    trunk/rostests/winetests/gdi32/brush.c
    trunk/rostests/winetests/gdi32/clipping.c
    trunk/rostests/winetests/gdi32/font.c
    trunk/rostests/winetests/gdi32/gdiobj.c
    trunk/rostests/winetests/gdi32/icm.c
    trunk/rostests/winetests/gdi32/mapping.c
    trunk/rostests/winetests/gdi32/metafile.c
    trunk/rostests/winetests/gdi32/palette.c
    trunk/rostests/winetests/gdi32/pen.c
Modified: trunk/rostests/winetests/gdi32/bitmap.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/bitmap.c?…
==============================================================================
--- trunk/rostests/winetests/gdi32/bitmap.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/bitmap.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -70,13 +70,15 @@
 static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER
*bmih)
 {
     BITMAP bm;
+    BITMAP bma[2];
     INT ret, width_bytes;
     char buf[512], buf_cmp[512];
+    DWORD gle;
     ret = GetObject(hbm, sizeof(bm), &bm);
     ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
-    ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
+    ok(bm.bmType == 0 || broken(bm.bmType == 21072 /* Win9x */), "wrong bm.bmType
%d\n", bm.bmType);
     ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
     ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n",
bm.bmHeight);
     width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
@@ -88,8 +90,10 @@
     assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
     assert(sizeof(buf) == sizeof(buf_cmp));
+    SetLastError(0xdeadbeef);
     ret = GetBitmapBits(hbm, 0, NULL);
-    ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes
* bm.bmHeight);
+    gle=GetLastError();
+    ok(ret == bm.bmWidthBytes * bm.bmHeight || (ret == 0 && gle ==
ERROR_INVALID_PARAMETER /* Win9x */), "%d != %d\n", ret, bm.bmWidthBytes *
bm.bmHeight);
     memset(buf_cmp, 0xAA, sizeof(buf_cmp));
     memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
@@ -100,20 +104,24 @@
     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
     /* test various buffer sizes for GetObject */
-    ret = GetObject(hbm, 0, NULL);
-    ok(ret == sizeof(bm), "wrong size %d\n", ret);
-
-    ret = GetObject(hbm, sizeof(bm) * 2, &bm);
-    ok(ret == sizeof(bm), "wrong size %d\n", ret);
+    ret = GetObject(hbm, sizeof(*bma) * 2, bma);
+    ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong
size %d\n", ret);
     ret = GetObject(hbm, sizeof(bm) / 2, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n",
ret);
     ret = GetObject(hbm, 0, &bm);
     ok(ret == 0, "%d != 0\n", ret);
     ret = GetObject(hbm, 1, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
+
+    /* Don't trust Win9x not to try to write to NULL */
+    if (ret == 0)
+    {
+        ret = GetObject(hbm, 0, NULL);
+        ok(ret == sizeof(bm), "wrong size %d\n", ret);
+    }
 }
 static void test_createdibitmap(void)
@@ -275,7 +283,9 @@
 static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih)
 {
     BITMAP bm;
+    BITMAP bma[2];
     DIBSECTION ds;
+    DIBSECTION dsa[2];
     INT ret, bm_width_bytes, dib_width_bytes;
     BYTE *buf;
@@ -298,8 +308,11 @@
     buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096);
     /* GetBitmapBits returns not 32-bit aligned data */
+    SetLastError(0xdeadbeef);
     ret = GetBitmapBits(hbm, 0, NULL);
-    ok(ret == bm_width_bytes * bm.bmHeight, "%d != %d\n", ret, bm_width_bytes *
bm.bmHeight);
+    ok(ret == bm_width_bytes * bm.bmHeight ||
+        broken(ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x
*/
+        "%d != %d\n", ret, bm_width_bytes * bm.bmHeight);
     memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096);
     ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf);
@@ -309,27 +322,30 @@
     /* test various buffer sizes for GetObject */
     memset(&ds, 0xAA, sizeof(ds));
-    ret = GetObject(hbm, sizeof(bm) * 2, &bm);
-    ok(ret == sizeof(bm), "wrong size %d\n", ret);
+    ret = GetObject(hbm, sizeof(*bma) * 2, bma);
+    ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong
size %d\n", ret);
     ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
     ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n",
bm.bmHeight);
     ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
     ret = GetObject(hbm, sizeof(bm) / 2, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n",
ret);
     ret = GetObject(hbm, 0, &bm);
     ok(ret == 0, "%d != 0\n", ret);
     ret = GetObject(hbm, 1, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret ==  1 /* Win9x */), "%d != 0\n", ret);
     /* test various buffer sizes for GetObject */
     ret = GetObject(hbm, 0, NULL);
     ok(ret == sizeof(bm), "wrong size %d\n", ret);
+    ret = GetObject(hbm, sizeof(*dsa) * 2, dsa);
+    ok(ret == sizeof(*dsa) || broken(ret == sizeof(*dsa) * 2 /* Win9x */), "wrong
size %d\n", ret);
+
     memset(&ds, 0xAA, sizeof(ds));
-    ret = GetObject(hbm, sizeof(ds) * 2, &ds);
+    ret = GetObject(hbm, sizeof(ds), &ds);
     ok(ret == sizeof(ds), "wrong size %d\n", ret);
     ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits,
bits);
@@ -416,6 +432,13 @@
     pbmi->bmiHeader.biCompression = BI_RGB;
     SetLastError(0xdeadbeef);
+
+    /* invalid pointer for BITMAPINFO
+       (*bits should be NULL on error) */
+    bits = (BYTE*)0xdeadbeef;
+    hdib = CreateDIBSection(hdc, NULL, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+    ok(hdib == NULL && bits == NULL, "CreateDIBSection failed for invalid
parameter: bmi == 0x0\n");
+
     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
     ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for
DIBSection\n");
@@ -965,6 +988,7 @@
     HBITMAP hbmp, hbmp_old;
     HDC hdc;
     BITMAP bm;
+    BITMAP bma[2];
     INT ret;
     hdc = CreateCompatibleDC(0);
@@ -974,7 +998,8 @@
     hbmp = CreateBitmap(0x7ffffff, 1, 1, 1, NULL);
     if (!hbmp)
     {
-        ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
+        ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY /* XP */ ||
+           GetLastError() == ERROR_INVALID_PARAMETER /* Win2k */,
            "expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
     }
     else
@@ -1047,17 +1072,17 @@
     ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
     /* test various buffer sizes for GetObject */
-    ret = GetObject(hbmp, sizeof(bm) * 2, &bm);
-    ok(ret == sizeof(bm), "wrong size %d\n", ret);
+    ret = GetObject(hbmp, sizeof(*bma) * 2, bma);
+    ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong
size %d\n", ret);
     ret = GetObject(hbmp, sizeof(bm) / 2, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n",
ret);
     ret = GetObject(hbmp, 0, &bm);
     ok(ret == 0, "%d != 0\n", ret);
     ret = GetObject(hbmp, 1, &bm);
-    ok(ret == 0, "%d != 0\n", ret);
+    ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
     DeleteObject(hbmp);
     DeleteDC(hdc);
@@ -1133,7 +1158,7 @@
     /* Select the DIB into a DC */
     dib_dc = CreateCompatibleDC(NULL);
-    old_bmp = (HBITMAP) SelectObject(dib_dc, dib);
+    old_bmp = SelectObject(dib_dc, dib);
     dc = CreateCompatibleDC(NULL);
     bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size);
     assert(bits2);
@@ -1168,10 +1193,7 @@
             break;
         }
     }
-    if (bpp != 1)
-        ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB
bits\n",bpp);
-    else
-        todo_wine ok(equalContents, "GetDIBits with %d bpp DIB selected in DC:
Invalid DIB bits\n",bpp);
+    ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB
bits\n",bpp);
     HeapFree(GetProcessHeap(), 0, bits2);
     DeleteDC(dc);
@@ -1217,7 +1239,7 @@
     /* Set the pixels */
     ddb_dc = CreateCompatibleDC(NULL);
-    old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
+    old_bmp = SelectObject(ddb_dc, ddb);
     for (i = 0; i < width; i++)
     {
         for (j=0; j < height; j++)
@@ -1259,7 +1281,7 @@
     memcpy(info2, info, sizeof(BITMAPINFOHEADER));
     /* Select the DDB into another DC */
-    old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
+    old_bmp = SelectObject(ddb_dc, ddb);
     /* Get the bits */
     res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS);
@@ -1293,6 +1315,28 @@
     }
     ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB
bits\n");
+    /* Test the palette */
+    equalContents = TRUE;
+    if (info2->bmiHeader.biBitCount <= 8)
+    {
+        WORD *colors = (WORD*)info2->bmiColors;
+
+        /* Get the palette indices */
+        res = GetDIBits(dc, ddb, 0, 0, NULL, info2, DIB_PAL_COLORS);
+        ok(res, "GetDIBits failed\n");
+
+        for (i=0;i < 1 << info->bmiHeader.biSizeImage; i++)
+        {
+            if (colors[i] != i)
+            {
+                equalContents = FALSE;
+                break;
+            }
+        }
+    }
+
+    ok(equalContents, "GetDIBits with DDB selected in DC: non 1:1 palette
indices\n");
+
     HeapFree(GetProcessHeap(), 0, bits2);
     HeapFree(GetProcessHeap(), 0, bits);
     DeleteDC(dc);
@@ -1442,107 +1486,6 @@
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n",
GetLastError());
     ok(bi->bmiHeader.biSizeImage == 0, "expected 0, got %u\n",
bi->bmiHeader.biSizeImage);
-    memset(buf, 0xAA, sizeof(buf));
-    SetLastError(0xdeadbeef);
-    lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
-    ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
-       lines, bm.bmHeight, GetLastError());
-    ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1), "expected 16*4, got
%u\n", bi->bmiHeader.biSizeImage);
-
-    /* the color table consists of black and white */
-    ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0
&&
-       bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0,
-       "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n",
-       bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen,
-       bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved);
-todo_wine
-    ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff
&&
-       bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved ==
0,
-       "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n",
-       bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen,
-       bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved);
-    for (i = 2; i < 256; i++)
-    {
-        ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen ==
0xAA &&
-           bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved
== 0xAA,
-           "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
-           bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
-           bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
-    }
-
-    /* returned bits are DWORD aligned and upside down */
-todo_wine
-    ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't
match\n");
-
-    /* retrieve 24-bit DIB data */
-    memset(bi, 0, sizeof(*bi));
-    bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    bi->bmiHeader.biWidth = bm.bmWidth;
-    bi->bmiHeader.biHeight = bm.bmHeight;
-    bi->bmiHeader.biPlanes = 1;
-    bi->bmiHeader.biBitCount = 24;
-    bi->bmiHeader.biCompression = BI_RGB;
-    bi->bmiHeader.biSizeImage = 0;
-    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
-    memset(buf, 0xAA, sizeof(buf));
-    SetLastError(0xdeadbeef);
-    lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
-    ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
-       lines, bm.bmHeight, GetLastError());
-    ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24), "expected 16*16*3, got
%u\n", bi->bmiHeader.biSizeImage);
-
-    /* the color table doesn't exist for 24-bit images */
-    for (i = 0; i < 256; i++)
-    {
-        ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen ==
0xAA &&
-           bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved
== 0xAA,
-           "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
-           bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
-           bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
-    }
-
-    /* returned bits are DWORD aligned and upside down */
-todo_wine
-    ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't
match\n");
-    DeleteObject(hbmp);
-
-    /* 24-bit source bitmap data */
-    hbmp = CreateCompatibleBitmap(hdc, 16, 16);
-    ok(hbmp != 0, "CreateBitmap failed\n");
-    SetLastError(0xdeadbeef);
-    bi->bmiHeader.biHeight = -bm.bmHeight; /* indicate bottom-up data */
-    lines = SetDIBits(hdc, hbmp, 0, bm.bmHeight, bmp_bits_24, bi, DIB_RGB_COLORS);
-    ok(lines == bm.bmHeight, "SetDIBits copied %d lines of %d, error %u\n",
-       lines, bm.bmHeight, GetLastError());
-
-    memset(&bm, 0xAA, sizeof(bm));
-    bytes = GetObject(hbmp, sizeof(bm), &bm);
-    ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes);
-    ok(bm.bmType == 0, "wrong bmType %d\n", bm.bmType);
-    ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth);
-    ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight);
-    ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong
bmWidthBytes %d\n", bm.bmWidthBytes);
-    ok(bm.bmPlanes == GetDeviceCaps(hdc, PLANES), "wrong bmPlanes %u\n",
bm.bmPlanes);
-    ok(bm.bmBitsPixel == GetDeviceCaps(hdc, BITSPIXEL), "wrong bmBitsPixel
%d\n", bm.bmBitsPixel);
-    ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
-
-    bytes = GetBitmapBits(hbmp, 0, NULL);
-    ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n",
-       bm.bmWidthBytes * bm.bmHeight, bytes);
-    bytes = GetBitmapBits(hbmp, sizeof(buf), buf);
-    ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n",
-       bm.bmWidthBytes * bm.bmHeight, bytes);
-
-    /* retrieve 1-bit DIB data */
-    memset(bi, 0, sizeof(*bi));
-    bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    bi->bmiHeader.biWidth = bm.bmWidth;
-    bi->bmiHeader.biHeight = bm.bmHeight;
-    bi->bmiHeader.biPlanes = 1;
-    bi->bmiHeader.biBitCount = 1;
-    bi->bmiHeader.biCompression = BI_RGB;
-    bi->bmiHeader.biSizeImage = 0;
-    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
     memset(buf, 0xAA, sizeof(buf));
     SetLastError(0xdeadbeef);
     lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
@@ -1573,6 +1516,125 @@
     /* returned bits are DWORD aligned and upside down */
 todo_wine
     ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't
match\n");
+
+    /* Test the palette indices */
+    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
+    SetLastError(0xdeadbeef);
+    lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS);
+
+    ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n",
((WORD*)bi->bmiColors)[0]);
+    ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n",
((WORD*)bi->bmiColors)[1]);
+    for (i = 2; i < 256; i++)
+        ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i,
((WORD*)bi->bmiColors)[1]);
+
+    /* retrieve 24-bit DIB data */
+    memset(bi, 0, sizeof(*bi));
+    bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bi->bmiHeader.biWidth = bm.bmWidth;
+    bi->bmiHeader.biHeight = bm.bmHeight;
+    bi->bmiHeader.biPlanes = 1;
+    bi->bmiHeader.biBitCount = 24;
+    bi->bmiHeader.biCompression = BI_RGB;
+    bi->bmiHeader.biSizeImage = 0;
+    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
+    memset(buf, 0xAA, sizeof(buf));
+    SetLastError(0xdeadbeef);
+    lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
+    ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
+       lines, bm.bmHeight, GetLastError());
+    ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24), "expected 16*16*3, got
%u\n", bi->bmiHeader.biSizeImage);
+
+    /* the color table doesn't exist for 24-bit images */
+    for (i = 0; i < 256; i++)
+    {
+        ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen ==
0xAA &&
+           bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved
== 0xAA,
+           "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
+           bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
+           bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
+    }
+
+    /* returned bits are DWORD aligned and upside down */
+    ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't
match\n");
+    DeleteObject(hbmp);
+
+    /* 24-bit source bitmap data */
+    hbmp = CreateCompatibleBitmap(hdc, 16, 16);
+    ok(hbmp != 0, "CreateBitmap failed\n");
+    SetLastError(0xdeadbeef);
+    bi->bmiHeader.biHeight = -bm.bmHeight; /* indicate bottom-up data */
+    lines = SetDIBits(hdc, hbmp, 0, bm.bmHeight, bmp_bits_24, bi, DIB_RGB_COLORS);
+    ok(lines == bm.bmHeight, "SetDIBits copied %d lines of %d, error %u\n",
+       lines, bm.bmHeight, GetLastError());
+
+    memset(&bm, 0xAA, sizeof(bm));
+    bytes = GetObject(hbmp, sizeof(bm), &bm);
+    ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes);
+    ok(bm.bmType == 0, "wrong bmType %d\n", bm.bmType);
+    ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth);
+    ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight);
+    ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong
bmWidthBytes %d\n", bm.bmWidthBytes);
+    ok(bm.bmPlanes == GetDeviceCaps(hdc, PLANES), "wrong bmPlanes %u\n",
bm.bmPlanes);
+    ok(bm.bmBitsPixel == GetDeviceCaps(hdc, BITSPIXEL), "wrong bmBitsPixel
%d\n", bm.bmBitsPixel);
+    ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
+
+    bytes = GetBitmapBits(hbmp, 0, NULL);
+    ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n",
+       bm.bmWidthBytes * bm.bmHeight, bytes);
+    bytes = GetBitmapBits(hbmp, sizeof(buf), buf);
+    ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n",
+       bm.bmWidthBytes * bm.bmHeight, bytes);
+
+    /* retrieve 1-bit DIB data */
+    memset(bi, 0, sizeof(*bi));
+    bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bi->bmiHeader.biWidth = bm.bmWidth;
+    bi->bmiHeader.biHeight = bm.bmHeight;
+    bi->bmiHeader.biPlanes = 1;
+    bi->bmiHeader.biBitCount = 1;
+    bi->bmiHeader.biCompression = BI_RGB;
+    bi->bmiHeader.biSizeImage = 0;
+    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
+    memset(buf, 0xAA, sizeof(buf));
+    SetLastError(0xdeadbeef);
+    lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
+    ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
+       lines, bm.bmHeight, GetLastError());
+    ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1), "expected 16*4, got
%u\n", bi->bmiHeader.biSizeImage);
+
+    /* the color table consists of black and white */
+    ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0
&&
+       bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0,
+       "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n",
+       bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen,
+       bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved);
+    ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff
&&
+       bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved ==
0,
+       "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n",
+       bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen,
+       bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved);
+    for (i = 2; i < 256; i++)
+    {
+        ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen ==
0xAA &&
+           bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved
== 0xAA,
+           "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
+           bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
+           bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
+    }
+
+    /* returned bits are DWORD aligned and upside down */
+todo_wine
+    ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)), "DIB bits don't
match\n");
+
+    /* Test the palette indices */
+    memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
+    SetLastError(0xdeadbeef);
+    lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS);
+
+    ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n",
((WORD*)bi->bmiColors)[0]);
+    ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n",
((WORD*)bi->bmiColors)[1]);
+    for (i = 2; i < 256; i++)
+        ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i,
((WORD*)bi->bmiColors)[i]);
     /* retrieve 24-bit DIB data */
     memset(bi, 0, sizeof(*bi));
@@ -1675,22 +1737,29 @@
         memset(dibinfo, 0, sizeof(dibinfo_buf));
         dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
         dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+        SetLastError(0xdeadbeef);
         ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
-
-        ok( !bitmasks[0], "red mask is set\n" );
-        ok( !bitmasks[1], "green mask is set\n" );
-        ok( !bitmasks[2], "blue mask is set\n" );
-        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not
set\n" );
-
-        memset(bitmasks, 0, 3*sizeof(DWORD));
-        dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
-        ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
-        ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
-
-        ok( bitmasks[0] != 0, "red mask is not set\n" );
-        ok( bitmasks[1] != 0, "green mask is not set\n" );
-        ok( bitmasks[2] != 0, "blue mask is not set\n" );
-        ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not
set\n" );
+        if (ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
+            win_skip("Win9x/WinMe doesn't handle 0 for the number of scan
lines\n");
+        else
+        {
+            ok(ret == 1, "GetDIBits failed ret %u err
%u\n",ret,GetLastError());
+
+            ok( !bitmasks[0], "red mask is set\n" );
+            ok( !bitmasks[1], "green mask is set\n" );
+            ok( !bitmasks[2], "blue mask is set\n" );
+            ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not
set\n" );
+
+            memset(bitmasks, 0, 3*sizeof(DWORD));
+            dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
+            ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
+            ok(ret == 1, "GetDIBits failed ret %u err
%u\n",ret,GetLastError());
+
+            ok( bitmasks[0] != 0, "red mask is not set\n" );
+            ok( bitmasks[1] != 0, "green mask is not set\n" );
+            ok( bitmasks[2] != 0, "blue mask is not set\n" );
+            ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not
set\n" );
+        }
     }
     else skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
@@ -1825,15 +1894,15 @@
     HBITMAP bm1 = CreateCompatibleBitmap(screenDC, 0, 0);
     HBITMAP bm4 = CreateBitmap(0, 1, 0, 0, 0);
     HBITMAP bm5 = CreateDiscardableBitmap(hdc, 0, 0);
-    HBITMAP curObj1 = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
-    HBITMAP curObj2 = (HBITMAP)GetCurrentObject(screenDC, OBJ_BITMAP);
+    HBITMAP curObj1 = GetCurrentObject(hdc, OBJ_BITMAP);
+    HBITMAP curObj2 = GetCurrentObject(screenDC, OBJ_BITMAP);
     /* these 2 are not the stock monochrome bitmap */
     HBITMAP bm2 = CreateCompatibleBitmap(hdc, 1, 1);
     HBITMAP bm3 = CreateBitmap(1, 1, 1, 1, 0);
-    HBITMAP old1 = (HBITMAP)SelectObject(hdc, bm2);
-    HBITMAP old2 = (HBITMAP)SelectObject(screenDC, bm3);
+    HBITMAP old1 = SelectObject(hdc, bm2);
+    HBITMAP old2 = SelectObject(screenDC, bm3);
     SelectObject(hdc, old1);
     SelectObject(screenDC, old2);
@@ -2084,8 +2153,8 @@
     bmpSrc = CreateDIBSection(hdcDst, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
     ok(bmpSrc != NULL, "Couldn't create source bitmap\n");
-    oldDst = (HBITMAP)SelectObject(hdcDst, bmpDst);
-    oldSrc = (HBITMAP)SelectObject(hdcSrc, bmpSrc);
+    oldDst = SelectObject(hdcDst, bmpDst);
+    oldSrc = SelectObject(hdcSrc, bmpSrc);
     blend.BlendOp = AC_SRC_OVER;
     blend.BlendFlags = 0;
@@ -2118,6 +2187,51 @@
     ReleaseDC(NULL, hdcNull);
+}
+
+static void test_clipping(void)
+{
+    HBITMAP bmpDst;
+    HBITMAP oldDst;
+    HBITMAP bmpSrc;
+    HBITMAP oldSrc;
+    HRGN hRgn;
+    LPVOID bits;
+    BOOL result;
+
+    HDC hdcDst = CreateCompatibleDC( NULL );
+    HDC hdcSrc = CreateCompatibleDC( NULL );
+
+    BITMAPINFO bmpinfo={{0}};
+    bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmpinfo.bmiHeader.biWidth = 100;
+    bmpinfo.bmiHeader.biHeight = 100;
+    bmpinfo.bmiHeader.biPlanes = 1;
+    bmpinfo.bmiHeader.biBitCount = GetDeviceCaps( hdcDst, BITSPIXEL );
+    bmpinfo.bmiHeader.biCompression = BI_RGB;
+
+    bmpDst = CreateDIBSection( hdcDst, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0
);
+    ok(bmpDst != NULL, "Couldn't create destination bitmap\n");
+    oldDst = SelectObject( hdcDst, bmpDst );
+
+    bmpSrc = CreateDIBSection( hdcSrc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0
);
+    ok(bmpSrc != NULL, "Couldn't create source bitmap\n");
+    oldSrc = SelectObject( hdcSrc, bmpSrc );
+
+    result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 100, 100, SRCCOPY );
+    ok(result, "BitBlt failed\n");
+
+    hRgn = CreateRectRgn( 0,0,0,0 );
+    SelectClipRgn( hdcDst, hRgn );
+
+    result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 0, 0, SRCCOPY );
+    ok(result, "BitBlt failed\n");
+
+    DeleteObject( bmpDst );
+    DeleteObject( bmpSrc );
+    DeleteObject( hRgn );
+    DeleteDC( hdcDst );
+    DeleteDC( hdcSrc );
 }
 START_TEST(bitmap)
@@ -2145,4 +2259,5 @@
     test_GdiAlphaBlend();
     test_bitmapinfoheadersize();
     test_get16dibits();
+    test_clipping();
 }
Modified: trunk/rostests/winetests/gdi32/brush.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/brush.c?r…
==============================================================================
--- trunk/rostests/winetests/gdi32/brush.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/brush.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -51,8 +51,10 @@
         solidBrush = CreateSolidBrush(stock[i].color);
         if(stock[i].stockobj != -1) {
-            stockBrush = (HBRUSH)GetStockObject(stock[i].stockobj);
-            ok(stockBrush!=solidBrush, "Stock %s brush equals solid %s
brush\n", stock[i].name, stock[i].name);
+            stockBrush = GetStockObject(stock[i].stockobj);
+            ok(stockBrush!=solidBrush ||
+               broken(stockBrush==solidBrush), /* win9x does return stock object */
+               "Stock %s brush equals solid %s brush\n", stock[i].name,
stock[i].name);
         }
         else
             stockBrush = NULL;
@@ -70,7 +72,10 @@
         }
         DeleteObject(solidBrush);
-        ok(GetObject(solidBrush, sizeof(br), &br)==0, "GetObject succeeded on a
deleted %s brush\n", stock[i].name);
+        ret = GetObject(solidBrush, sizeof(br), &br);
+        ok(ret==0 ||
+           broken(ret!=0), /* win9x */
+           "GetObject succeeded on a deleted %s brush\n", stock[i].name);
     }
 }
Modified: trunk/rostests/winetests/gdi32/clipping.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/clipping.…
==============================================================================
--- trunk/rostests/winetests/gdi32/clipping.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/clipping.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -111,7 +111,9 @@
     GetRgnBox(hrgn, &ret_rc);
     if(GetVersion() & 0x80000000)
         OffsetRect(&window_rc, -window_rc.left, -window_rc.top);
-    ok(EqualRect(&window_rc, &ret_rc), "GetRandomRgn %d,%d - %d,%d\n",
+    ok(EqualRect(&window_rc, &ret_rc) ||
+       broken(IsRectEmpty(&ret_rc)), /* win95 */
+       "GetRandomRgn %d,%d - %d,%d\n",
        ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom);
     DeleteObject(hrgn);
Modified: trunk/rostests/winetests/gdi32/font.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/font.c?re…
==============================================================================
--- trunk/rostests/winetests/gdi32/font.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/font.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -30,6 +30,7 @@
 #include "wine/test.h"
+#define near_match(a, b) (abs((a) - (b)) <= 6)
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n",
expected, got)
 LONG  (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height);
@@ -105,7 +106,7 @@
         minlen++;
     minlen += FIELD_OFFSET(LOGFONTA, lfFaceName) + 1;
     ok(ret == sizeof(LOGFONTA) || ret == minlen, "%s: GetObject returned %d\n",
test, ret);
-    ok(!memcmp(&lf, &lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts
don't match\n", test);
+    ok(!memcmp(lf, &getobj_lf, FIELD_OFFSET(LOGFONTA, lfFaceName)), "%s: fonts
don't match\n", test);
     ok(!lstrcmpA(lf->lfFaceName, getobj_lf.lfFaceName),
        "%s: font names don't match: %s != %s\n", test, lf->lfFaceName,
getobj_lf.lfFaceName);
 }
@@ -158,56 +159,119 @@
     return 1; /* continue enumeration */
 }
+static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm)
+{
+    ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n",
tm->tmHeight, otm->tmHeight);
+    ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n",
tm->tmAscent, otm->tmAscent);
+    ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n",
tm->tmDescent, otm->tmDescent);
+    ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d
!= %d\n", tm->tmInternalLeading, otm->tmInternalLeading);
+    ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d
!= %d\n", tm->tmExternalLeading, otm->tmExternalLeading);
+    ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d !=
%d\n", tm->tmAveCharWidth, otm->tmAveCharWidth);
+    ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d !=
%d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth);
+    ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n",
tm->tmWeight, otm->tmWeight);
+    ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n",
tm->tmOverhang, otm->tmOverhang);
+    ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX
%d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX);
+    ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY
%d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY);
+    ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n",
tm->tmFirstChar, otm->tmFirstChar);
+    ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n",
tm->tmLastChar, otm->tmLastChar);
+    ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d !=
%d\n", tm->tmDefaultChar, otm->tmDefaultChar);
+    ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n",
tm->tmBreakChar, otm->tmBreakChar);
+    ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n",
tm->tmItalic, otm->tmItalic);
+    ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n",
tm->tmUnderlined, otm->tmUnderlined);
+    ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n",
tm->tmStruckOut, otm->tmStruckOut);
+    ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d !=
%d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily);
+    ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n",
tm->tmCharSet, otm->tmCharSet);
+}
+
 static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight,
                               LONG lfWidth, const char *test_str,
                              INT test_str_len, const TEXTMETRICA *tm_orig,
                              const SIZE *size_orig, INT width_of_A_orig,
                              INT scale_x, INT scale_y)
 {
-    HFONT old_hfont;
     LOGFONTA lf;
+    OUTLINETEXTMETRIC otm;
     TEXTMETRICA tm;
     SIZE size;
     INT width_of_A, cx, cy;
+    UINT ret;
     if (!hfont)
         return;
+    ok(GetCurrentObject(hdc, OBJ_FONT) == hfont, "hfont should be selected\n");
+
     GetObjectA(hfont, sizeof(lf), &lf);
-    old_hfont = SelectObject(hdc, hfont);
-
-    GetTextMetricsA(hdc, &tm);
+    if (GetOutlineTextMetricsA(hdc, 0, NULL))
+    {
+        otm.otmSize = sizeof(otm) / 2;
+        ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
+        ok(ret == sizeof(otm)/2 /* XP */ ||
+           ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret);
+
+        memset(&otm, 0x1, sizeof(otm));
+        otm.otmSize = sizeof(otm);
+        ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm);
+        ok(ret == sizeof(otm) /* XP */ ||
+           ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret);
+
+        memset(&tm, 0x2, sizeof(tm));
+        ret = GetTextMetricsA(hdc, &tm);
+        ok(ret, "GetTextMetricsA failed\n");
+        /* the structure size is aligned */
+        if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet)
+ 1))
+        {
+            ok(0, "tm != otm\n");
+            compare_tm(&tm, &otm.otmTextMetrics);
+        }
+
+        tm = otm.otmTextMetrics;
+if (0) /* these metrics are scaled too, but with rounding errors */
+{
+        ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent,
tm.tmAscent);
+        ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n",
otm.otmDescent, -tm.tmDescent);
+}
+        ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n",
otm.otmMacAscent, tm.tmAscent);
+        ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n");
+        ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n");
+        ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n");
+        ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n",
otm.otmMacDescent, -tm.tmDescent);
+        ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n",
otm.otmEMSquare);
+    }
+    else
+    {
+        ret = GetTextMetricsA(hdc, &tm);
+        ok(ret, "GetTextMetricsA failed\n");
+    }
     cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth;
     cy = tm.tmHeight / tm_orig->tmHeight;
     ok(cx == scale_x && cy == scale_y, "expected scale_x %d, scale_y %d, got
cx %d, cy %d\n",
        scale_x, scale_y, cx, cy);
-    ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%d != %d\n",
tm.tmHeight, tm_orig->tmHeight * scale_y);
-    ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%d != %d\n",
tm.tmAscent, tm_orig->tmAscent * scale_y);
-    ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%d != %d\n",
tm.tmDescent, tm_orig->tmDescent * scale_y);
-    ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%d != %d\n",
tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
-    ok(tm.tmMaxCharWidth == tm_orig->tmMaxCharWidth * scale_x, "%d != %d\n",
tm.tmAveCharWidth, tm_orig->tmMaxCharWidth * scale_x);
-
-    ok(lf.lfHeight == lfHeight, "lf %d != %d\n", lf.lfHeight, lfHeight);
+    ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n",
tm.tmHeight, tm_orig->tmHeight * scale_y);
+    ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n",
tm.tmAscent, tm_orig->tmAscent * scale_y);
+    ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n",
tm.tmDescent, tm_orig->tmDescent * scale_y);
+    ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave
width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x);
+    ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max
width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x);
+
+    ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight);
     if (lf.lfHeight)
     {
         if (lf.lfWidth)
-            ok(lf.lfWidth == tm.tmAveCharWidth, "lf %d != tm %d\n", lf.lfWidth,
tm.tmAveCharWidth);
+            ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n",
lf.lfWidth, tm.tmAveCharWidth);
     }
     else
-        ok(lf.lfWidth == lfWidth, "lf %d != %d\n", lf.lfWidth, lfWidth);
+        ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth);
     GetTextExtentPoint32A(hdc, test_str, test_str_len, &size);
-    ok(size.cx == size_orig->cx * scale_x, "%d != %d\n", size.cx,
size_orig->cx * scale_x);
-    ok(size.cy == size_orig->cy * scale_y, "%d != %d\n", size.cy,
size_orig->cy * scale_y);
+    ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n",
size.cx, size_orig->cx * scale_x);
+    ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy,
size_orig->cy * scale_y);
     GetCharWidthA(hdc, 'A', 'A', &width_of_A);
-    ok(width_of_A == width_of_A_orig * scale_x, "%d != %d\n", width_of_A,
width_of_A_orig * scale_x);
-
-    SelectObject(hdc, old_hfont);
+    ok(near_match(width_of_A, width_of_A_orig * scale_x), "width A %d != %d\n",
width_of_A, width_of_A_orig * scale_x);
 }
 /* Test how GDI scales bitmap font metrics */
@@ -248,7 +312,9 @@
     bitmap_lf.lfHeight = 0;
     bitmap_lf.lfWidth = 4;
     hfont = create_font("bitmap", &bitmap_lf);
+    old_hfont = SelectObject(hdc, hfont);
     test_font_metrics(hdc, hfont, 0, 4, test_str, sizeof(test_str), &tm_orig,
&size_orig, width_orig, 1, 1);
+    SelectObject(hdc, old_hfont);
     DeleteObject(hfont);
     bitmap_lf.lfHeight = height_orig;
@@ -265,25 +331,283 @@
         nearest_height = scale * height_orig;
         /* XP allows not more than 10% deviation */
         if (scale > 1 && nearest_height - i > nearest_height / 10) scale--;
+        old_hfont = SelectObject(hdc, hfont);
         test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str),
&tm_orig, &size_orig, width_orig, 1, scale);
-       DeleteObject(hfont);
+        SelectObject(hdc, old_hfont);
+        DeleteObject(hfont);
     }
     /* test integer scaling 3x2 */
     bitmap_lf.lfHeight = height_orig * 2;
     bitmap_lf.lfWidth *= 3;
     hfont = create_font("3x2", &bitmap_lf);
+    old_hfont = SelectObject(hdc, hfont);
     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str),
&tm_orig, &size_orig, width_orig, 3, 2);
+    SelectObject(hdc, old_hfont);
     DeleteObject(hfont);
     /* test integer scaling 3x3 */
     bitmap_lf.lfHeight = height_orig * 3;
     bitmap_lf.lfWidth = 0;
     hfont = create_font("3x3", &bitmap_lf);
+    old_hfont = SelectObject(hdc, hfont);
     test_font_metrics(hdc, hfont, bitmap_lf.lfHeight, 0, test_str, sizeof(test_str),
&tm_orig, &size_orig, width_orig, 3, 3);
+    SelectObject(hdc, old_hfont);
     DeleteObject(hfont);
     ReleaseDC(0, hdc);
+}
+
+/* Test how GDI scales outline font metrics */
+static void test_outline_font(void)
+{
+    static const char test_str[11] = "Test String";
+    HDC hdc, hdc_2;
+    LOGFONTA lf;
+    HFONT hfont, old_hfont, old_hfont_2;
+    OUTLINETEXTMETRICA otm;
+    SIZE size_orig;
+    INT width_orig, height_orig, lfWidth;
+    XFORM xform;
+    GLYPHMETRICS gm;
+    MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
+    MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} };
+    POINT pt;
+    INT ret;
+
+    if (!is_truetype_font_installed("Arial"))
+    {
+        skip("Arial is not installed\n");
+        return;
+    }
+
+    hdc = CreateCompatibleDC(0);
+
+    memset(&lf, 0, sizeof(lf));
+    strcpy(lf.lfFaceName, "Arial");
+    lf.lfHeight = 72;
+    hfont = create_font("outline", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    otm.otmSize = sizeof(otm);
+    ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA
failed\n");
+    ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig),
"GetTextExtentPoint32A failed\n");
+    ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA
failed\n");
+
+    test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth,
test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+
+    /* font of otmEMSquare height helps to avoid a lot of rounding errors */
+    lf.lfHeight = otm.otmEMSquare;
+    lf.lfHeight = -lf.lfHeight;
+    hfont = create_font("outline", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    otm.otmSize = sizeof(otm);
+    ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA
failed\n");
+    ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig),
"GetTextExtentPoint32A failed\n");
+    ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA
failed\n");
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+
+    height_orig = otm.otmTextMetrics.tmHeight;
+    lfWidth = otm.otmTextMetrics.tmAveCharWidth;
+
+    /* test integer scaling 3x2 */
+    lf.lfHeight = height_orig * 2;
+    lf.lfWidth = lfWidth * 3;
+    hfont = create_font("3x2", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 3, 2);
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+
+    /* test integer scaling 3x3 */
+    lf.lfHeight = height_orig * 3;
+    lf.lfWidth = lfWidth * 3;
+    hfont = create_font("3x3", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 3, 3);
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+
+    /* test integer scaling 1x1 */
+    lf.lfHeight = height_orig * 1;
+    lf.lfWidth = lfWidth * 1;
+    hfont = create_font("1x1", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+
+    /* test integer scaling 1x1 */
+    lf.lfHeight = height_orig;
+    lf.lfWidth = 0;
+    hfont = create_font("1x1", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* with an identity matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX,
width_orig);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+    /* with a custom matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX,
width_orig/2);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+
+    /* Test that changing the DC transformation affects only the font
+     * selected on this DC and doesn't affect the same font selected on
+     * another DC.
+     */
+    hdc_2 = CreateCompatibleDC(0);
+    old_hfont_2 = SelectObject(hdc_2, hfont);
+    test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    SetMapMode(hdc, MM_ANISOTROPIC);
+
+    /* font metrics on another DC should be unchanged */
+    test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* test restrictions of compatibility mode GM_COMPATIBLE */
+    /*  part 1: rescaling only X should not change font scaling on screen.
+                So compressing the X axis by 2 is not done, and this
+                appears as X scaling of 2 that no one requested. */
+    SetWindowExtEx(hdc, 100, 100, NULL);
+    SetViewportExtEx(hdc, 50, 100, NULL);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
+    /* font metrics on another DC should be unchanged */
+    test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /*  part 2: rescaling only Y should change font scaling.
+                As also X is scaled by a factor of 2, but this is not
+                requested by the DC transformation, we get a scaling factor
+                of 2 in the X coordinate. */
+    SetViewportExtEx(hdc, 100, 200, NULL);
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 2, 1);
+    /* font metrics on another DC should be unchanged */
+    test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* restore scaling */
+    SetMapMode(hdc, MM_TEXT);
+
+    /* font metrics on another DC should be unchanged */
+    test_font_metrics(hdc_2, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    SelectObject(hdc_2, old_hfont_2);
+    DeleteDC(hdc_2);
+
+    if (!SetGraphicsMode(hdc, GM_ADVANCED))
+    {
+        SelectObject(hdc, old_hfont);
+        DeleteObject(hfont);
+        DeleteDC(hdc);
+        skip("GM_ADVANCED is not supported on this platform\n");
+        return;
+    }
+
+    xform.eM11 = 20.0f;
+    xform.eM12 = 0.0f;
+    xform.eM21 = 0.0f;
+    xform.eM22 = 20.0f;
+    xform.eDx = 0.0f;
+    xform.eDy = 0.0f;
+
+    SetLastError(0xdeadbeef);
+    ret = SetWorldTransform(hdc, &xform);
+    ok(ret, "SetWorldTransform error %u\n", GetLastError());
+
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* with an identity matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
+    ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 *
width_orig);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+    /* with a custom matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
+    ok(near_match(gm.gmCellIncX, 10 * width_orig), "incX %d != %d\n",
gm.gmCellIncX, 10 * width_orig);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_LOMETRIC);
+    ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret,
GetLastError());
+
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* with an identity matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(near_match(gm.gmCellIncX, pt.x), "incX %d != %d\n", gm.gmCellIncX,
pt.x);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+    /* with a custom matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(near_match(gm.gmCellIncX, (pt.x + 1)/2), "incX %d != %d\n",
gm.gmCellIncX, (pt.x + 1)/2);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_TEXT);
+    ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret,
GetLastError());
+
+    test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str),
&otm.otmTextMetrics, &size_orig, width_orig, 1, 1);
+
+    /* with an identity matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x);
+    ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 *
width_orig);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+    /* with a custom matrix */
+    memset(&gm, 0, sizeof(gm));
+    SetLastError(0xdeadbeef);
+    ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2);
+    ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError());
+    trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig);
+    pt.x = width_orig; pt.y = 0;
+    LPtoDP(hdc, &pt, 1);
+    ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2);
+    ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 *
width_orig);
+    ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY);
+
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+    DeleteDC(hdc);
 }
 static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type,
LPARAM lParam)
@@ -781,6 +1105,8 @@
            kd[i].otmDescent, otm.otmDescent);
         ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n",
            kd[i].otmLineGap, otm.otmLineGap);
+        ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got
%d\n",
+           kd[i].otmMacDescent, otm.otmMacDescent);
 todo_wine {
         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got
%u\n",
            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
@@ -788,8 +1114,6 @@
            kd[i].otmsXHeight, otm.otmsXHeight);
         ok(kd[i].otmMacAscent == otm.otmMacAscent, "expected %d, got %d\n",
            kd[i].otmMacAscent, otm.otmMacAscent);
-        ok(kd[i].otmMacDescent == otm.otmMacDescent, "expected %d, got %d\n",
-           kd[i].otmMacDescent, otm.otmMacDescent);
         /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing
todo */
         if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got
%u\n",
            kd[i].otmMacLineGap, otm.otmMacLineGap);
@@ -1020,7 +1344,7 @@
     for (e = 0; e < nErrors; e++)
     {
-        ok(error[e].TabbedTextOutWidth == areaWidth,
+        ok(near_match(error[e].TabbedTextOutWidth, areaWidth),
             "The output text (\"%s\") width should be %d, not %d.\n",
             error[e].extent, areaWidth, error[e].TabbedTextOutWidth);
         /* The width returned by GetTextExtentPoint32() is exactly the same
@@ -1097,8 +1421,8 @@
     ok(cs == charset, "expected %d, got %d\n", charset, cs);
     SetLastError(0xdeadbeef);
-    ret = GetTextFace(hdc, sizeof(name), name);
-    ok(ret, "GetTextFace error %u\n", GetLastError());
+    ret = GetTextFaceA(hdc, sizeof(name), name);
+    ok(ret, "GetTextFaceA error %u\n", GetLastError());
     if (charset == SYMBOL_CHARSET)
     {
@@ -1247,7 +1571,7 @@
     ReleaseDC(NULL, hdc);
 }
-#define MAX_ENUM_FONTS 256
+#define MAX_ENUM_FONTS 4096
 struct enum_font_data
 {
@@ -1255,17 +1579,46 @@
     LOGFONT lf[MAX_ENUM_FONTS];
 };
+struct enum_font_dataW
+{
+    int total;
+    LOGFONTW lf[MAX_ENUM_FONTS];
+};
+
 static INT CALLBACK arial_enum_proc(const LOGFONT *lf, const TEXTMETRIC *tm, DWORD type,
LPARAM lParam)
 {
     struct enum_font_data *efd = (struct enum_font_data *)lParam;
+
+    ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n",
lf->lfHeight, tm->tmHeight);
     if (type != TRUETYPE_FONTTYPE) return 1;
 #if 0
-    trace("enumed font \"%s\", charset %d, weight %d, italic %d\n",
-          lf->lfFaceName, lf->lfCharSet, lf->lfWeight, lf->lfItalic);
+    trace("enumed font \"%s\", charset %d, height %d, weight %d, italic
%d\n",
+          lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight,
lf->lfItalic);
 #endif
     if (efd->total < MAX_ENUM_FONTS)
         efd->lf[efd->total++] = *lf;
+    else
+        trace("enum tests invalid; you have more than %d fonts\n",
MAX_ENUM_FONTS);
+
+    return 1;
+}
+
+static INT CALLBACK arial_enum_procw(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD
type, LPARAM lParam)
+{
+    struct enum_font_dataW *efd = (struct enum_font_dataW *)lParam;
+
+    ok(lf->lfHeight == tm->tmHeight, "lfHeight %d != tmHeight %d\n",
lf->lfHeight, tm->tmHeight);
+
+    if (type != TRUETYPE_FONTTYPE) return 1;
+#if 0
+    trace("enumed font \"%s\", charset %d, height %d, weight %d, italic
%d\n",
+          lf->lfFaceName, lf->lfCharSet, lf->lfHeight, lf->lfWeight,
lf->lfItalic);
+#endif
+    if (efd->total < MAX_ENUM_FONTS)
+        efd->lf[efd->total++] = *lf;
+    else
+        trace("enum tests invalid; you have more than %d fonts\n",
MAX_ENUM_FONTS);
     return 1;
 }
@@ -1297,9 +1650,37 @@
     }
 }
+static void get_charset_statsW(struct enum_font_dataW *efd,
+                              int *ansi_charset, int *symbol_charset,
+                              int *russian_charset)
+{
+    int i;
+
+    *ansi_charset = 0;
+    *symbol_charset = 0;
+    *russian_charset = 0;
+
+    for (i = 0; i < efd->total; i++)
+    {
+        switch (efd->lf[i].lfCharSet)
+        {
+        case ANSI_CHARSET:
+            (*ansi_charset)++;
+            break;
+        case SYMBOL_CHARSET:
+            (*symbol_charset)++;
+            break;
+        case RUSSIAN_CHARSET:
+            (*russian_charset)++;
+            break;
+        }
+    }
+}
+
 static void test_EnumFontFamilies(const char *font_name, INT font_charset)
 {
     struct enum_font_data efd;
+    struct enum_font_dataW efdw;
     LOGFONT lf;
     HDC hdc;
     int i, ret, ansi_charset, symbol_charset, russian_charset;
@@ -1319,29 +1700,39 @@
      */
     if (!*font_name && font_charset == DEFAULT_CHARSET) /* do it only once */
     {
-        efd.total = 0;
+        /*
+         * Use EnumFontFamiliesW since win98 crashes when the
+         *    second parameter is NULL using EnumFontFamilies
+         */
+        efdw.total = 0;
         SetLastError(0xdeadbeef);
-        ret = EnumFontFamilies(hdc, NULL, arial_enum_proc, (LPARAM)&efd);
-        ok(ret, "EnumFontFamilies error %u\n", GetLastError());
-        get_charset_stats(&efd, &ansi_charset, &symbol_charset,
&russian_charset);
-        trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
-              ansi_charset, symbol_charset, russian_charset);
-        ok(efd.total > 0, "no fonts enumerated: NULL\n");
-        ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
-        ok(symbol_charset > 0, "NULL family should enumerate
SYMBOL_CHARSET\n");
-        ok(russian_charset > 0, "NULL family should enumerate
RUSSIAN_CHARSET\n");
-
-        efd.total = 0;
+        ret = EnumFontFamiliesW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw);
+        ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesW
error %u\n", GetLastError());
+        if(ret)
+        {
+            get_charset_statsW(&efdw, &ansi_charset, &symbol_charset,
&russian_charset);
+            trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
+                  ansi_charset, symbol_charset, russian_charset);
+            ok(efdw.total > 0, "fonts enumerated: NULL\n");
+            ok(ansi_charset > 0, "NULL family should enumerate
ANSI_CHARSET\n");
+            ok(symbol_charset > 0, "NULL family should enumerate
SYMBOL_CHARSET\n");
+            ok(russian_charset > 0, "NULL family should enumerate
RUSSIAN_CHARSET\n");
+        }
+
+        efdw.total = 0;
         SetLastError(0xdeadbeef);
-        ret = EnumFontFamiliesEx(hdc, NULL, arial_enum_proc, (LPARAM)&efd, 0);
-        ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
-        get_charset_stats(&efd, &ansi_charset, &symbol_charset,
&russian_charset);
-        trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
-              ansi_charset, symbol_charset, russian_charset);
-        ok(efd.total > 0, "no fonts enumerated: NULL\n");
-        ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
-        ok(symbol_charset > 0, "NULL family should enumerate
SYMBOL_CHARSET\n");
-        ok(russian_charset > 0, "NULL family should enumerate
RUSSIAN_CHARSET\n");
+        ret = EnumFontFamiliesExW(hdc, NULL, arial_enum_procw, (LPARAM)&efdw, 0);
+        ok(ret || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "EnumFontFamiliesExW
error %u\n", GetLastError());
+        if(ret)
+        {
+            get_charset_statsW(&efdw, &ansi_charset, &symbol_charset,
&russian_charset);
+            trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
+                  ansi_charset, symbol_charset, russian_charset);
+            ok(efdw.total > 0, "fonts enumerated: NULL\n");
+            ok(ansi_charset > 0, "NULL family should enumerate
ANSI_CHARSET\n");
+            ok(symbol_charset > 0, "NULL family should enumerate
SYMBOL_CHARSET\n");
+            ok(russian_charset > 0, "NULL family should enumerate
RUSSIAN_CHARSET\n");
+        }
     }
     efd.total = 0;
@@ -1502,6 +1893,12 @@
     LOGFONTA lf2 = *lf;
     WORD idx;
     MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} };
+
+    if(!pGetGlyphIndicesA)
+    {
+        skip("GetGlyphIndicesA is unavailable\n");
+        return;
+    }
     /* negative widths are handled just as positive ones */
     lf2.lfWidth = -lf->lfWidth;
@@ -1633,8 +2030,6 @@
     LONG size, ret;
     const char *font_name = lf->lfFaceName;
-    trace("Testing font metrics for %s, charset %d\n", font_name,
lf->lfCharSet);
-
     hdc = GetDC(0);
     SetLastError(0xdeadbeef);
@@ -1660,21 +2055,19 @@
     ok(ret == size, "GetFontData should return %u not %u\n", size, ret);
     version = GET_BE_WORD(tt_os2.version);
-    trace("OS/2 chunk version %u, vendor %4.4s\n", version,
(LPCSTR)&tt_os2.achVendID);
     first_unicode_char = GET_BE_WORD(tt_os2.usFirstCharIndex);
     last_unicode_char = GET_BE_WORD(tt_os2.usLastCharIndex);
     default_char = GET_BE_WORD(tt_os2.usDefaultChar);
     break_char = GET_BE_WORD(tt_os2.usBreakChar);
-    trace("for %s first %x, last %x, default %x, break %x\n", font_name,
-           first_unicode_char, last_unicode_char, default_char, break_char);
+    trace("font %s charset %u: %x-%x default %x break %x OS/2 version %u vendor
%4.4s\n",
+          font_name, lf->lfCharSet, first_unicode_char, last_unicode_char,
default_char, break_char,
+          version, (LPCSTR)&tt_os2.achVendID);
     SetLastError(0xdeadbeef);
     ret = GetTextMetricsA(hdc, &tmA);
     ok(ret, "GetTextMetricsA error %u\n", GetLastError());
-    trace("A: first %x, last %x, default %x, break %x\n",
-          tmA.tmFirstChar, tmA.tmLastChar, tmA.tmDefaultChar, tmA.tmBreakChar);
 #if 0 /* FIXME: This doesn't appear to be what Windows does */
     test_char = min(first_unicode_char - 1, 255);
@@ -1700,9 +2093,9 @@
        "GetTextMetricsW error %u\n", GetLastError());
     if (ret)
     {
-        trace("W: first %x, last %x, default %x, break %x\n",
-              tmW.tmFirstChar, tmW.tmLastChar, tmW.tmDefaultChar,
-              tmW.tmBreakChar);
+        trace("%04x-%04x (%02x-%02x) default %x (%x) break %x (%x)\n",
+              tmW.tmFirstChar, tmW.tmLastChar, tmA.tmFirstChar, tmA.tmLastChar,
+              tmW.tmDefaultChar, tmA.tmDefaultChar, tmW.tmBreakChar, tmA.tmBreakChar);
         if (lf->lfCharSet == SYMBOL_CHARSET)
         {
@@ -1775,16 +2168,40 @@
 static void test_nonexistent_font(void)
 {
+    static const struct
+    {
+        const char *name;
+        int charset;
+    } font_subst[] =
+    {
+        { "Times New Roman Baltic", 186 },
+        { "Times New Roman CE", 238 },
+        { "Times New Roman CYR", 204 },
+        { "Times New Roman Greek", 161 },
+        { "Times New Roman TUR", 162 }
+    };
     LOGFONTA lf;
     HDC hdc;
     HFONT hfont;
+    CHARSETINFO csi;
+    INT cs, expected_cs, i;
     char buf[LF_FACESIZE];
-    if (!is_truetype_font_installed("Arial Black"))
-    {
-        skip("Arial not installed\n");
+    if (!is_truetype_font_installed("Arial") ||
+        !is_truetype_font_installed("Times New Roman"))
+    {
+        skip("Arial or Times New Roman not installed\n");
         return;
     }
+
+    expected_cs = GetACP();
+    if (!TranslateCharsetInfo(ULongToPtr(expected_cs), &csi, TCI_SRCCODEPAGE))
+    {
+        skip("TranslateCharsetInfo failed for code page %d\n", expected_cs);
+        return;
+    }
+    expected_cs = csi.ciCharset;
+    trace("ACP %d -> charset %d\n", GetACP(), expected_cs);
     hdc = GetDC(0);
@@ -1794,12 +2211,96 @@
     lf.lfCharSet = ANSI_CHARSET;
     lf.lfPitchAndFamily = FF_SWISS;
     strcpy(lf.lfFaceName, "Nonexistent font");
-
     hfont = CreateFontIndirectA(&lf);
     hfont = SelectObject(hdc, hfont);
     GetTextFaceA(hdc, sizeof(buf), buf);
     ok(!lstrcmpiA(buf, "Arial"), "Got %s\n", buf);
+    cs = GetTextCharset(hdc);
+    ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
     DeleteObject(SelectObject(hdc, hfont));
+
+    memset(&lf, 0, sizeof(lf));
+    lf.lfHeight = -13;
+    lf.lfWeight = FW_DONTCARE;
+    strcpy(lf.lfFaceName, "Nonexistent font");
+    hfont = CreateFontIndirectA(&lf);
+    hfont = SelectObject(hdc, hfont);
+    GetTextFaceA(hdc, sizeof(buf), buf);
+todo_wine /* Wine uses Arial for all substitutions */
+    ok(!lstrcmpiA(buf, "Nonexistent font") /* XP, Vista */ ||
+       !lstrcmpiA(buf, "MS Serif") || /* Win9x */
+       !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
+       "Got %s\n", buf);
+    cs = GetTextCharset(hdc);
+    ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
+    DeleteObject(SelectObject(hdc, hfont));
+
+    memset(&lf, 0, sizeof(lf));
+    lf.lfHeight = -13;
+    lf.lfWeight = FW_REGULAR;
+    strcpy(lf.lfFaceName, "Nonexistent font");
+    hfont = CreateFontIndirectA(&lf);
+    hfont = SelectObject(hdc, hfont);
+    GetTextFaceA(hdc, sizeof(buf), buf);
+    ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
+       !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n",
buf);
+    cs = GetTextCharset(hdc);
+    ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
+    DeleteObject(SelectObject(hdc, hfont));
+
+    memset(&lf, 0, sizeof(lf));
+    lf.lfHeight = -13;
+    lf.lfWeight = FW_DONTCARE;
+    strcpy(lf.lfFaceName, "Times New Roman");
+    hfont = CreateFontIndirectA(&lf);
+    hfont = SelectObject(hdc, hfont);
+    GetTextFaceA(hdc, sizeof(buf), buf);
+    ok(!lstrcmpiA(buf, "Times New Roman"), "Got %s\n", buf);
+    cs = GetTextCharset(hdc);
+    ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
+    DeleteObject(SelectObject(hdc, hfont));
+
+    for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++)
+    {
+        memset(&lf, 0, sizeof(lf));
+        lf.lfHeight = -13;
+        lf.lfWeight = FW_REGULAR;
+        strcpy(lf.lfFaceName, font_subst[i].name);
+        hfont = CreateFontIndirectA(&lf);
+        hfont = SelectObject(hdc, hfont);
+        cs = GetTextCharset(hdc);
+        if (font_subst[i].charset == expected_cs)
+        {
+            ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
+            GetTextFaceA(hdc, sizeof(buf), buf);
+            ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n",
font_subst[i].name, buf);
+        }
+        else
+        {
+            ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs);
+            GetTextFaceA(hdc, sizeof(buf), buf);
+            ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ ||
+               !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got
%s\n", buf);
+        }
+        DeleteObject(SelectObject(hdc, hfont));
+
+        memset(&lf, 0, sizeof(lf));
+        lf.lfHeight = -13;
+        lf.lfWeight = FW_DONTCARE;
+        strcpy(lf.lfFaceName, font_subst[i].name);
+        hfont = CreateFontIndirectA(&lf);
+        hfont = SelectObject(hdc, hfont);
+        GetTextFaceA(hdc, sizeof(buf), buf);
+        ok(!lstrcmpiA(buf, "Arial") /* Wine */ ||
+           !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ ||
+           !lstrcmpiA(buf, "MS Serif") /* Win9x */ ||
+           !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */
+           "got %s\n", buf);
+        cs = GetTextCharset(hdc);
+        ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs);
+        DeleteObject(SelectObject(hdc, hfont));
+    }
+
     ReleaseDC(0, hdc);
 }
@@ -1850,12 +2351,137 @@
     ReleaseDC(0, hdc);
 }
+/* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include
+   the nul in the count of characters copied when the face name buffer is not
+   NULL, whereas it does if the buffer is NULL.  Further, the Unicode version
+   always includes it.  */
+static void test_GetTextFace(void)
+{
+    static const char faceA[] = "Tahoma";
+    static const WCHAR faceW[] =
{'T','a','h','o','m','a', 0};
+    LOGFONTA fA = {0};
+    LOGFONTW fW = {0};
+    char bufA[LF_FACESIZE];
+    WCHAR bufW[LF_FACESIZE];
+    HFONT f, g;
+    HDC dc;
+    int n;
+
+    if(!is_font_installed("Tahoma"))
+    {
+        skip("Tahoma is not installed so skipping this test\n");
+        return;
+    }
+
+    /* 'A' case.  */
+    memcpy(fA.lfFaceName, faceA, sizeof faceA);
+    f = CreateFontIndirectA(&fA);
+    ok(f != NULL, "CreateFontIndirectA failed\n");
+
+    dc = GetDC(NULL);
+    g = SelectObject(dc, f);
+    n = GetTextFaceA(dc, sizeof bufA, bufA);
+    ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n);
+    ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n");
+
+    /* Play with the count arg.  */
+    bufA[0] = 'x';
+    n = GetTextFaceA(dc, 0, bufA);
+    ok(n == 0, "GetTextFaceA returned %d\n", n);
+    ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]);
+
+    bufA[0] = 'x';
+    n = GetTextFaceA(dc, 1, bufA);
+    ok(n == 0, "GetTextFaceA returned %d\n", n);
+    ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]);
+
+    bufA[0] = 'x'; bufA[1] = 'y';
+    n = GetTextFaceA(dc, 2, bufA);
+    ok(n == 1, "GetTextFaceA returned %d\n", n);
+    ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA
didn't copy\n");
+
+    n = GetTextFaceA(dc, 0, NULL);
+    ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n);
+
+    DeleteObject(SelectObject(dc, g));
+    ReleaseDC(NULL, dc);
+
+    /* 'W' case.  */
+    memcpy(fW.lfFaceName, faceW, sizeof faceW);
+    SetLastError(0xdeadbeef);
+    f = CreateFontIndirectW(&fW);
+    if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+    {
+        win_skip("CreateFontIndirectW is not implemented\n");
+        return;
+    }
+    ok(f != NULL, "CreateFontIndirectW failed\n");
+
+    dc = GetDC(NULL);
+    g = SelectObject(dc, f);
+    n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW);
+    ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
+    ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n");
+
+    /* Play with the count arg.  */
+    bufW[0] = 'x';
+    n = GetTextFaceW(dc, 0, bufW);
+    ok(n == 0, "GetTextFaceW returned %d\n", n);
+    ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]);
+
+    bufW[0] = 'x';
+    n = GetTextFaceW(dc, 1, bufW);
+    ok(n == 1, "GetTextFaceW returned %d\n", n);
+    ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]);
+
+    bufW[0] = 'x'; bufW[1] = 'y';
+    n = GetTextFaceW(dc, 2, bufW);
+    ok(n == 2, "GetTextFaceW returned %d\n", n);
+    ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW
didn't copy\n");
+
+    n = GetTextFaceW(dc, 0, NULL);
+    ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n);
+
+    DeleteObject(SelectObject(dc, g));
+    ReleaseDC(NULL, dc);
+}
+
+static void test_orientation(void)
+{
+    static const char test_str[11] = "Test String";
+    HDC hdc;
+    LOGFONTA lf;
+    HFONT hfont, old_hfont;
+    SIZE size;
+
+    if (!is_truetype_font_installed("Arial"))
+    {
+        skip("Arial is not installed\n");
+        return;
+    }
+
+    hdc = CreateCompatibleDC(0);
+    memset(&lf, 0, sizeof(lf));
+    lstrcpyA(lf.lfFaceName, "Arial");
+    lf.lfHeight = 72;
+    lf.lfOrientation = lf.lfEscapement = 900;
+    hfont = create_font("orientation", &lf);
+    old_hfont = SelectObject(hdc, hfont);
+    ok(GetTextExtentExPointA(hdc, test_str, sizeof(test_str), 32767, NULL, NULL,
&size), "GetTextExtentExPointA failed\n");
+    ok(near_match(311, size.cx), "cx should be about 311, got %d\n", size.cx);
+    ok(near_match(75, size.cy), "cy should be about 75, got %d\n", size.cy);
+    SelectObject(hdc, old_hfont);
+    DeleteObject(hfont);
+    DeleteDC(hdc);
+}
+
 START_TEST(font)
 {
     init();
     test_logfont();
     test_bitmap_font();
+    test_outline_font();
     test_bitmap_font_metrics();
     test_GdiGetCharDimensions();
     test_GetCharABCWidths();
@@ -1867,6 +2493,7 @@
     test_font_charset();
     test_GetFontUnicodeRanges();
     test_nonexistent_font();
+    test_orientation();
     /* On Windows Arial has a lot of default charset aliases such as Arial Cyr,
      * I'd like to avoid them in this test.
@@ -1884,4 +2511,5 @@
         skip("Arial Black or Symbol/Wingdings is not installed\n");
     test_GetTextMetrics();
     test_GdiRealizationInfo();
-}
+    test_GetTextFace();
+}
Modified: trunk/rostests/winetests/gdi32/gdiobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/gdiobj.c?…
==============================================================================
--- trunk/rostests/winetests/gdi32/gdiobj.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/gdiobj.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -43,7 +43,7 @@
      */
     SetLastError(0);
     hp = SelectObject(NULL, GetStockObject(BLACK_PEN));
-    ok(!hp && GetLastError() == ERROR_INVALID_HANDLE,
+    ok(!hp && (GetLastError() == ERROR_INVALID_HANDLE ||
broken(!GetLastError())),
        "SelectObject(NULL DC) expected 0, ERROR_INVALID_HANDLE, got %p, %u\n",
        hp, GetLastError());
@@ -77,7 +77,7 @@
     /* GetObject does not SetLastError() on a null object */
     SetLastError(0);
     i = GetObjectA(NULL, sizeof(buff), buff);
-    ok (!i && !GetLastError(),
+    ok (!i && (GetLastError() == 0 || GetLastError() == ERROR_INVALID_PARAMETER),
         "GetObject(NULL obj), expected 0, NO_ERROR, got %d, %u\n",
        i, GetLastError());
@@ -207,7 +207,7 @@
     hobj = GetCurrentObject(hdc, OBJ_PEN);
     ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
     hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
-    ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
+    ok(hobj == hpen || broken(hobj == 0) /* win9x */, "OBJ_EXTPEN is wrong:
%p\n", hobj);
     hbrush = CreateSolidBrush(RGB(10, 20, 30));
     assert(hbrush != 0);
@@ -243,7 +243,7 @@
     hobj = GetCurrentObject(hdc, OBJ_PEN);
     ok(hobj == hpen, "OBJ_PEN is wrong: %p\n", hobj);
     hobj = GetCurrentObject(hdc, OBJ_EXTPEN);
-    ok(hobj == hpen, "OBJ_EXTPEN is wrong: %p\n", hobj);
+    ok(hobj == hpen || broken(hobj == 0) /* win9x */, "OBJ_EXTPEN is wrong:
%p\n", hobj);
     hcs = GetColorSpace(hdc);
     if (hcs)
@@ -254,7 +254,7 @@
         ok(hcs != 0, "CreateColorSpace failed\n");
         SelectObject(hdc, hcs);
         hobj = GetCurrentObject(hdc, OBJ_COLORSPACE);
-        ok(hobj == hcs, "OBJ_COLORSPACE is wrong: %p\n", hobj);
+        ok(hobj == hcs || broken(hobj == 0) /* win9x */, "OBJ_COLORSPACE is wrong:
%p\n", hobj);
     }
     hrgn = CreateRectRgn(1, 1, 100, 100);
Modified: trunk/rostests/winetests/gdi32/icm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/icm.c?rev…
==============================================================================
--- trunk/rostests/winetests/gdi32/icm.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/icm.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -51,20 +51,28 @@
     ret = GetICMProfileA( dc, &size, NULL );
     ok( !ret, "GetICMProfileA succeeded\n" );
-    ret = GetICMProfileA( dc, NULL, filename );
-    ok( !ret, "GetICMProfileA succeeded\n" );
-
     size = MAX_PATH;
     ret = GetICMProfileA( NULL, &size, filename );
     ok( !ret, "GetICMProfileA succeeded\n" );
     size = 0;
+    filename[0] = 0;
     SetLastError(0xdeadbeef);
     ret = GetICMProfileA( dc, &size, filename );
     error = GetLastError();
     ok( !ret, "GetICMProfileA succeeded\n" );
     ok( size, "expected size > 0\n" );
-    ok( error == ERROR_INSUFFICIENT_BUFFER, "got %d, expected
ERROR_INSUFFICIENT_BUFFER\n", error );
+    ok( filename[0] == 0, "Expected filename to be empty\n" );
+    ok( error == ERROR_INSUFFICIENT_BUFFER ||
+        error == ERROR_SUCCESS, /* Win95 */
+        "got %d, expected ERROR_INSUFFICIENT_BUFFER or ERROR_SUCCESS(Win95)\n",
error );
+
+    /* Next test will crash on Win95 */
+    if ( error == ERROR_INSUFFICIENT_BUFFER )
+    {
+        ret = GetICMProfileA( dc, NULL, filename );
+        ok( !ret, "GetICMProfileA succeeded\n" );
+    }
     size = MAX_PATH;
     ret = GetICMProfileA( dc, &size, filename );
@@ -122,6 +130,15 @@
 static void test_SetICMMode( HDC dc )
 {
     INT ret, knob, save;
+    BOOL impl;
+
+    SetLastError( 0xdeadbeef );
+    impl = GetICMProfileA( NULL, NULL, NULL );
+    if ( !impl && ( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED ) )
+    {
+        skip( "On NT4 where SetICMMode is not implemented but this is not
advertised\n" );
+        return;
+    }
     SetLastError( 0xdeadbeef );
     ret = SetICMMode( NULL, 0 );
Modified: trunk/rostests/winetests/gdi32/mapping.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/mapping.c…
==============================================================================
--- trunk/rostests/winetests/gdi32/mapping.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/mapping.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -2,6 +2,7 @@
  * Unit tests for mapping functions
  *
  * Copyright (c) 2005 Huw Davies
+ * Copyright (c) 2008 Dmitry  Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +29,146 @@
 #include "winuser.h"
 #include "winerror.h"
+#define rough_match(got, expected) (abs((got) - (expected)) <= 5)
+
+#define expect_LPtoDP(_hdc, _x, _y) \
+{ \
+    POINT _pt = { 1000, 1000 }; \
+    LPtoDP(_hdc, &_pt, 1); \
+    ok(rough_match(_pt.x, _x), "expected x %d, got %d\n", (_x), _pt.x); \
+    ok(rough_match(_pt.y, _y), "expected y %d, got %d\n", (_y), _pt.y); \
+}
+
+#define expect_world_trasform(_hdc, _em11, _em22) \
+{ \
+    BOOL _ret; \
+    XFORM _xform; \
+    SetLastError(0xdeadbeef); \
+    _ret = GetWorldTransform(_hdc, &_xform); \
+    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) \
+    { \
+        ok(_ret, "GetWorldTransform error %u\n", GetLastError()); \
+        ok(_xform.eM11 == (_em11), "expected %f, got %f\n", (_em11),
_xform.eM11); \
+        ok(_xform.eM12 == 0.0, "expected 0.0, got %f\n", _xform.eM12); \
+        ok(_xform.eM21 == 0.0, "expected 0.0, got %f\n", _xform.eM21); \
+        ok(_xform.eM22 == (_em22), "expected %f, got %f\n", (_em22),
_xform.eM22); \
+        ok(_xform.eDx == 0.0, "expected 0.0, got %f\n", _xform.eDx); \
+        ok(_xform.eDy == 0.0, "expected 0.0, got %f\n", _xform.eDy); \
+    } \
+}
+
+#define expect_dc_ext(_func, _hdc, _cx, _cy) \
+{ \
+    BOOL _ret; \
+    SIZE _size; \
+    SetLastError(0xdeadbeef); \
+    _ret = _func(_hdc, &_size); \
+    ok(_ret, #_func " error %u\n", GetLastError()); \
+    ok(_size.cx == (_cx), "expected cx %d, got %d\n", (_cx), _size.cx); \
+    ok(_size.cy == (_cy), "expected cy %d, got %d\n", (_cy), _size.cy); \
+}
+
+#define expect_viewport_ext(_hdc, _cx, _cy) expect_dc_ext(GetViewportExtEx, _hdc, _cx,
_cy)
+#define expect_window_ext(_hdc, _cx, _cy)  expect_dc_ext(GetWindowExtEx, _hdc, _cx, _cy)
+
+static void test_world_transform(void)
+{
+    BOOL is_win9x;
+    HDC hdc;
+    INT ret, size_cx, size_cy, res_x, res_y;
+    XFORM xform;
+
+    SetLastError(0xdeadbeef);
+    GetWorldTransform(0, NULL);
+    is_win9x = GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
+
+    hdc = CreateCompatibleDC(0);
+
+    size_cx = GetDeviceCaps(hdc, HORZSIZE);
+    size_cy = GetDeviceCaps(hdc, VERTSIZE);
+    res_x = GetDeviceCaps(hdc, HORZRES);
+    res_y = GetDeviceCaps(hdc, VERTRES);
+    trace("dc size %d x %d, resolution %d x %d\n", size_cx, size_cy, res_x,
res_y);
+
+    expect_viewport_ext(hdc, 1, 1);
+    expect_window_ext(hdc, 1, 1);
+    expect_world_trasform(hdc, 1.0, 1.0);
+    expect_LPtoDP(hdc, 1000, 1000);
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_LOMETRIC);
+    ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
+
+    if (is_win9x)
+    {
+        expect_viewport_ext(hdc, GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc,
LOGPIXELSY));
+        expect_window_ext(hdc, 254, -254);
+    }
+    else
+    {
+        expect_viewport_ext(hdc, res_x, -res_y);
+        expect_window_ext(hdc, size_cx * 10, size_cy * 10);
+    }
+    expect_world_trasform(hdc, 1.0, 1.0);
+    expect_LPtoDP(hdc, MulDiv(1000 / 10, res_x, size_cx), -MulDiv(1000 / 10, res_y,
size_cy));
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_TEXT);
+    ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);
+
+    expect_viewport_ext(hdc, 1, 1);
+    expect_window_ext(hdc, 1, 1);
+    expect_world_trasform(hdc, 1.0, 1.0);
+    expect_LPtoDP(hdc, 1000, 1000);
+
+    ret = SetGraphicsMode(hdc, GM_ADVANCED);
+    if (!ret)
+    {
+        DeleteDC(hdc);
+        skip("GM_ADVANCED is not supported on this platform\n");
+        return;
+    }
+
+    expect_viewport_ext(hdc, 1, 1);
+    expect_window_ext(hdc, 1, 1);
+    expect_world_trasform(hdc, 1.0, 1.0);
+    expect_LPtoDP(hdc, 1000, 1000);
+
+    xform.eM11 = 20.0f;
+    xform.eM12 = 0.0f;
+    xform.eM21 = 0.0f;
+    xform.eM22 = 20.0f;
+    xform.eDx = 0.0f;
+    xform.eDy = 0.0f;
+    SetLastError(0xdeadbeef);
+    ret = SetWorldTransform(hdc, &xform);
+    ok(ret, "SetWorldTransform error %u\n", GetLastError());
+
+    expect_viewport_ext(hdc, 1, 1);
+    expect_window_ext(hdc, 1, 1);
+    expect_world_trasform(hdc, 20.0, 20.0);
+    expect_LPtoDP(hdc, 20000, 20000);
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_LOMETRIC);
+    ok(ret == MM_TEXT, "expected MM_TEXT, got %d\n", ret);
+
+    expect_viewport_ext(hdc, res_x, -res_y);
+    expect_window_ext(hdc, size_cx * 10, size_cy * 10);
+    expect_world_trasform(hdc, 20.0, 20.0);
+    expect_LPtoDP(hdc, MulDiv(1000 * 2, res_x, size_cx), -MulDiv(1000 * 2, res_y,
size_cy));
+
+    SetLastError(0xdeadbeef);
+    ret = SetMapMode(hdc, MM_TEXT);
+    ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d\n", ret);
+
+    expect_viewport_ext(hdc, 1, 1);
+    expect_window_ext(hdc, 1, 1);
+    expect_world_trasform(hdc, 20.0, 20.0);
+    expect_LPtoDP(hdc, 20000, 20000);
+
+    DeleteDC(hdc);
+}
 static void test_modify_world_transform(void)
 {
@@ -38,6 +179,7 @@
     if(!ret) /* running in win9x so quit */
     {
         ReleaseDC(0, hdc);
+        skip("GM_ADVANCED is not supported on this platform\n");
         return;
     }
@@ -52,8 +194,6 @@
     ReleaseDC(0, hdc);
 }
-
-#define rough_match(got, expected) ((got >= expected - 2) && (got <=
expected + 2))
 static void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG
expected_vp_cy)
 {
@@ -158,5 +298,6 @@
 START_TEST(mapping)
 {
     test_modify_world_transform();
+    test_world_transform();
     test_isotropic_mapping();
 }
Modified: trunk/rostests/winetests/gdi32/metafile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/metafile.…
==============================================================================
--- trunk/rostests/winetests/gdi32/metafile.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/metafile.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -975,8 +975,24 @@
     printf ("};\n");
 }
+static void dump_EMREXTTEXTOUT(const EMREXTTEXTOUTW *eto)
+{
+    trace("rclBounds %d,%d - %d,%d\n", eto->rclBounds.left,
eto->rclBounds.top,
+          eto->rclBounds.right, eto->rclBounds.bottom);
+    trace("iGraphicsMode %u\n", eto->iGraphicsMode);
+    trace("exScale: %f\n", eto->exScale);
+    trace("eyScale: %f\n", eto->eyScale);
+    trace("emrtext.ptlReference %d,%d\n", eto->emrtext.ptlReference.x,
eto->emrtext.ptlReference.y);
+    trace("emrtext.nChars %u\n", eto->emrtext.nChars);
+    trace("emrtext.offString %#x\n", eto->emrtext.offString);
+    trace("emrtext.fOptions %#x\n", eto->emrtext.fOptions);
+    trace("emrtext.rcl %d,%d - %d,%d\n", eto->emrtext.rcl.left,
eto->emrtext.rcl.top,
+          eto->emrtext.rcl.right, eto->emrtext.rcl.bottom);
+    trace("emrtext.offDx %#x\n", eto->emrtext.offDx);
+}
+
 static BOOL match_emf_record(const ENHMETARECORD *emr1, const ENHMETARECORD *emr2,
-                             const char *desc, BOOL todo)
+                             const char *desc, BOOL ignore_scaling, BOOL todo)
 {
     int diff;
@@ -1010,7 +1026,37 @@
     /* contents of EMR_GDICOMMENT are not interesting */
     if (emr1->iType == EMR_GDICOMMENT) return TRUE;
-    diff = memcmp(emr1->dParm, emr2->dParm, emr1->nSize - sizeof(EMR));
+    /* different Windows versions setup DC scaling differently when
+     * converting an old style metafile to an EMF.
+     */
+    if (ignore_scaling && (emr1->iType == EMR_SETWINDOWEXTEX ||
+                           emr1->iType == EMR_SETVIEWPORTEXTEX))
+        return TRUE;
+
+    if (emr1->iType == EMR_EXTTEXTOUTW || emr1->iType == EMR_EXTTEXTOUTA)
+    {
+        EMREXTTEXTOUTW *eto1, *eto2;
+
+        eto1 = HeapAlloc(GetProcessHeap(), 0, emr1->nSize);
+        memcpy(eto1, emr1, emr1->nSize);
+        eto2 = HeapAlloc(GetProcessHeap(), 0, emr2->nSize);
+        memcpy(eto2, emr2, emr2->nSize);
+
+        /* different Windows versions setup DC scaling differently */
+        eto1->exScale = eto1->eyScale = 0.0;
+        eto2->exScale = eto2->eyScale = 0.0;
+
+        diff = memcmp(eto1, eto2, emr1->nSize);
+        if (diff)
+        {
+            dump_EMREXTTEXTOUT(eto1);
+            dump_EMREXTTEXTOUT(eto2);
+        }
+        HeapFree(GetProcessHeap(), 0, eto1);
+        HeapFree(GetProcessHeap(), 0, eto2);
+    }
+    else
+        diff = memcmp(emr1, emr2, emr1->nSize);
     if (diff && todo)
     {
         todo_wine
@@ -1035,7 +1081,8 @@
  * otherwise returns the number of non-matching bytes.
  */
 static int compare_emf_bits(const HENHMETAFILE mf, const unsigned char *bits,
-                            UINT bsize, const char *desc, BOOL todo)
+                            UINT bsize, const char *desc,
+                            BOOL ignore_scaling, BOOL todo)
 {
     unsigned char buf[MF_BUFSIZE];
     UINT mfsize, offset;
@@ -1093,7 +1140,7 @@
        trace("EMF record %u, size %u/record %u, size %u\n",
               emr1->iType, emr1->nSize, emr2->iType, emr2->nSize);
-        if (!match_emf_record(emr1, emr2, desc, todo)) return -1;
+        if (!match_emf_record(emr1, emr2, desc, ignore_scaling, todo)) return -1;
        offset += emr1->nSize;
     }
@@ -1433,7 +1480,7 @@
      * are there, but their contents don't match for different reasons.
      */
     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS,
sizeof(EMF_TEXTOUT_ON_PATH_BITS),
-        "emf_TextOut_on_path", TRUE) != 0)
+        "emf_TextOut_on_path", FALSE, FALSE) != 0)
     {
         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
         dump_emf_records(hMetafile, "emf_TextOut_on_path");
@@ -1488,6 +1535,15 @@
     }
 }
+/* Compare rectangles allowing rounding errors */
+static BOOL is_equal_rect(const RECT *rc1, const RECT *rc2)
+{
+    return abs(rc1->left - rc2->left) <= 1 &&
+           abs(rc1->top - rc2->top) <= 1 &&
+           abs(rc1->right - rc2->right) <= 1 &&
+           abs(rc1->bottom - rc2->bottom) <= 1;
+}
+
 static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
                                        const ENHMETARECORD *emr, int n_objs, LPARAM
param)
 {
@@ -1574,7 +1630,7 @@
         translate((POINT *)&rc_transformed, 2, &xform);
         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left,
rc_transformed.top,
               rc_transformed.right, rc_transformed.bottom);
-        ok(EqualRect(&rect, &rc_transformed), "rects don't
match\n");
+        ok(is_equal_rect(&rect, &rc_transformed), "rects don't
match\n");
         rect = *(const RECT *)rgn2.data.Buffer;
         trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right,
rect.bottom);
@@ -1582,7 +1638,7 @@
         translate((POINT *)&rc_transformed, 2, &xform);
         trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left,
rc_transformed.top,
               rc_transformed.right, rc_transformed.bottom);
-        ok(EqualRect(&rect, &rc_transformed), "rects don't
match\n");
+        ok(is_equal_rect(&rect, &rc_transformed), "rects don't
match\n");
         ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh),
got %u\n", rgn2.data.rdh.dwSize);
         ok(rgn2.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got
%u\n", rgn2.data.rdh.iType);
@@ -1620,7 +1676,7 @@
     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
-        "emf_clipping", TRUE) != 0)
+        "emf_clipping", FALSE, FALSE) != 0)
     {
         dump_emf_bits(hemf, "emf_clipping");
         dump_emf_records(hemf, "emf_clipping");
@@ -1686,6 +1742,7 @@
 {
     HDC hdcMf;
     HMETAFILE hmf;
+    HENHMETAFILE hemf;
     BOOL ret;
     UINT size;
     LPBYTE pBits;
@@ -1708,7 +1765,9 @@
     pBits = HeapAlloc(GetProcessHeap(), 0, size);
     GetMetaFileBitsEx(hmf, size, pBits);
     DeleteMetaFile(hmf);
-    return SetWinMetaFileBits(size, pBits, NULL, mfp);
+    hemf = SetWinMetaFileBits(size, pBits, NULL, mfp);
+    HeapFree(GetProcessHeap(), 0, pBits);
+    return hemf;
 }
 static void test_mf_conversions(void)
@@ -1726,7 +1785,7 @@
         hemf = create_converted_emf(&mfp);
         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS,
sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
-                             "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
+                             "emf_LineTo MM_ANISOTROPIC", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
@@ -1751,7 +1810,7 @@
         hemf = create_converted_emf(&mfp);
         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS,
sizeof(EMF_LINETO_MM_TEXT_BITS),
-                             "emf_LineTo MM_TEXT", TRUE) != 0)
+                             "emf_LineTo MM_TEXT", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
@@ -1771,7 +1830,7 @@
         hemf = create_converted_emf(NULL);
         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
-                             "emf_LineTo NULL", TRUE) != 0)
+                             "emf_LineTo NULL", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo NULL");
             dump_emf_records(hemf, "emf_LineTo NULL");
@@ -1920,12 +1979,17 @@
   ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not
isotropic\n");
   dc = CreateCompatibleDC(NULL);
+
+  /* Allow 1 mm difference (rounding errors) */
+  diffx = rclBoundsAnisotropic.right - GetDeviceCaps(dc, HORZRES) / 2;
+  diffy = rclBoundsAnisotropic.bottom - GetDeviceCaps(dc, VERTRES) / 2;
+  if (diffx < 0) diffx = -diffx;
+  if (diffy < 0) diffy = -diffy;
   todo_wine
   {
-  ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 &&
-     rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1,
+  ok(diffx <= 1 && diffy <= 1,
      "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device
surface must be used (%dx%d), but got (%dx%d)\n",
-     GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1,
rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
+     GetDeviceCaps(dc, HORZRES) / 2, GetDeviceCaps(dc, VERTRES) / 2,
rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
   }
   /* Allow 1 mm difference (rounding errors) */
@@ -2012,9 +2076,11 @@
     pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
     pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32,
"GdiIsPlayMetafileDC");
-    /* they should all exist or none should exist */
-    if(!pGdiIsMetaPrintDC)
+    if(!pGdiIsMetaPrintDC || !pGdiIsMetaFileDC || !pGdiIsPlayMetafileDC)
+    {
+        win_skip("Needed GdiIs* functions are not available\n");
         return;
+    }
     /* try with nothing */
     ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
@@ -2053,7 +2119,9 @@
     SetLastError(0xdeadbeef);
     hemf = SetEnhMetaFileBits(sizeof(data), data);
     ok(!hemf, "SetEnhMetaFileBits should fail\n");
-    ok(GetLastError() == ERROR_INVALID_DATA, "expected ERROR_INVALID_DATA, got
%u\n", GetLastError());
+    ok(GetLastError() == ERROR_INVALID_DATA ||
+       GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x, WinMe */
+       "expected ERROR_INVALID_DATA or ERROR_INVALID_PARAMETER, got %u\n",
GetLastError());
     emh = (ENHMETAHEADER *)data;
     memset(emh, 0, sizeof(*emh));
@@ -2075,15 +2143,23 @@
     emh->nBytes++;
     SetLastError(0xdeadbeef);
     hemf = SetEnhMetaFileBits(emh->nBytes, data);
-    ok(!hemf, "SetEnhMetaFileBits should fail\n");
-    /* XP doesn't set error in this case */
+    ok(!hemf ||
+       broken(hemf != NULL), /* Win9x, WinMe */
+       "SetEnhMetaFileBits should fail\n");
+    todo_wine
+    ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n",
GetLastError());
+    DeleteEnhMetaFile(hemf);
     emh->dSignature = 0;
     emh->nBytes--;
     SetLastError(0xdeadbeef);
     hemf = SetEnhMetaFileBits(emh->nBytes, data);
-    ok(!hemf, "SetEnhMetaFileBits should fail\n");
-    /* XP doesn't set error in this case */
+    ok(!hemf ||
+       broken(hemf != NULL), /* Win9x, WinMe */
+       "SetEnhMetaFileBits should fail\n");
+    todo_wine
+    ok(GetLastError() == 0xdeadbeef, "Expected deadbeef, got %u\n",
GetLastError());
+    DeleteEnhMetaFile(hemf);
 }
 START_TEST(metafile)
Modified: trunk/rostests/winetests/gdi32/palette.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/palette.c…
==============================================================================
--- trunk/rostests/winetests/gdi32/palette.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/palette.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -110,7 +110,9 @@
     SetPixel( memhdc, 0, 0, setColor );
     chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen,
logpalettedata[3].peBlue );
     getColor = GetPixel( memhdc, 0, 0 );
-    ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
+    ok( getColor == chkColor ||
+        broken(getColor == 0), /* win9x */
+        "getColor=%08X\n", (UINT)getColor );
     SelectPalette( memhdc, hpalOld, FALSE );
     DeleteObject( hpal );
Modified: trunk/rostests/winetests/gdi32/pen.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/pen.c?rev…
==============================================================================
--- trunk/rostests/winetests/gdi32/pen.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/gdi32/pen.c [iso-8859-1] Thu Nov 27 14:52:01 2008
@@ -29,6 +29,8 @@
 #include "wine/test.h"
 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n",
expected, got)
+#define expect2(expected, alt, got) ok(got == expected || got == alt, \
+                                       "Expected %.8x or %.8x, got %.8x\n",
expected, alt, got)
 static void test_logpen(void)
 {
@@ -68,7 +70,7 @@
     for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
     {
-        trace("testing style %u\n", pen[i].style);
+        trace("%d: testing style %u\n", i, pen[i].style);
         /********************** cosmetic pens **********************/
         /* CreatePenIndirect behaviour */
@@ -142,6 +144,7 @@
         /* for some reason XP differentiates PS_NULL here */
         if (pen[i].style == PS_NULL)
         {
+            ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock
NULL_PEN\n");
             ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n",
size, GetLastError());
             ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n",
pen[i].ret_style, elp.elpPenStyle);
             ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
@@ -204,7 +207,10 @@
         obj_type = GetObjectType(hpen);
         /* for some reason XP differentiates PS_NULL here */
         if (pen[i].style == PS_NULL)
+        {
             ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
+            ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock
NULL_PEN\n");
+        }
         else
             ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
@@ -504,7 +510,7 @@
     pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
     ok(pen == 0, "ExtCreatePen should fail\n");
-    expect(0xdeadbeef, GetLastError());
+    expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError());
     DeleteObject(pen);
     SetLastError(0xdeadbeef);