ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
June 2017
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
20 participants
526 discussions
Start a n
N
ew thread
[akhaldi] 74881: [GDI32_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:46 2017 New Revision: 74881 URL:
http://svn.reactos.org/svn/reactos?rev=74881&view=rev
Log: [GDI32_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/gdi32/bitmap.c trunk/rostests/winetests/gdi32/dib.c trunk/rostests/winetests/gdi32/font.c trunk/rostests/winetests/gdi32/wine_test.sfd trunk/rostests/winetests/gdi32/wine_test.ttf 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] Sun Jun 4 01:50:46 2017 @@ -884,12 +884,13 @@ ok( ret == 1, "SetDIBColorTable returned unexpected result %u\n", ret ); ok( rgb[0].rgbReserved == 123, "Expected rgbReserved = 123, got %u\n", rgb[0].rgbReserved ); + rgb[0].rgbRed = rgb[0].rgbGreen = rgb[0].rgbBlue = rgb[0].rgbReserved = -1; ret = GetDIBColorTable( hdcmem, 0, 1, rgb ); ok( ret == 1, "GetDIBColorTable returned unexpected result %u\n", ret ); ok( rgb[0].rgbRed == 1, "Expected rgbRed = 1, got %u\n", rgb[0].rgbRed ); ok( rgb[0].rgbGreen == 2, "Expected rgbGreen = 2, got %u\n", rgb[0].rgbGreen ); ok( rgb[0].rgbBlue == 3, "Expected rgbBlue = 3, got %u\n", rgb[0].rgbBlue ); - todo_wine ok( rgb[0].rgbReserved == 0, "Expected rgbReserved = 0, got %u\n", rgb[0].rgbReserved ); + ok( rgb[0].rgbReserved == 0, "Expected rgbReserved = 0, got %u\n", rgb[0].rgbReserved ); SelectObject(hdcmem, oldbm); DeleteObject(hdib); @@ -4315,8 +4316,10 @@ memset( data, 0xaa, sizeof(data) ); info->bmiHeader.biHeight = 16; + info->bmiHeader.biSizeImage = 0; ret = GetDIBits( hdc, dib, 1, 12, data, info, DIB_RGB_COLORS ); ok( ret == 5, "got %d\n", ret ); + ok( info->bmiHeader.biSizeImage == 128 * 4, "got %d\n", info->bmiHeader.biSizeImage ); for (i = 0; i < 56; i++) ok( data[i] == 0, "%d: got %08x\n", i, data[i] ); ok( !memcmp( data + 56, dib_bits, 40 * 4 ), "bits differ\n"); for (i = 96; i < 128; i++) ok( data[i] == 0xaaaaaaaa, "%d: got %08x\n", i, data[i] ); @@ -5674,8 +5677,10 @@ HGDIOBJ *bitmap; DIBSECTION dib; BOOL fail, ret; - DWORD type; + DWORD type, pixel; int size; + HDC bmp_dc; + HBITMAP bmp; static const struct { @@ -5870,6 +5875,15 @@ ret = BitBlt( create_desc.hDc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS ); ok(ret, "Failed to blit.\n"); + /* Also test blitting to a regular bitmap */ + bmp_dc = CreateCompatibleDC( create_desc.hDeviceDc ); + ok(bmp_dc != NULL, "failed to create DC\n"); + bmp = CreateCompatibleBitmap( bmp_dc, create_desc.Width, create_desc.Height ); + ok(bmp != NULL, "failed to create bmp\n"); + bmp = SelectObject( bmp_dc, bmp ); + ret = BitBlt( bmp_dc, 0, 0, create_desc.Width, create_desc.Height, create_desc.hDc, 0, 0, SRCCOPY ); + ok(ret, "Failed to blit.\n"); + destroy_desc.hDc = create_desc.hDc; destroy_desc.hBitmap = create_desc.hBitmap; @@ -5902,8 +5916,25 @@ test_data[i].name, colour, x, y, expected); if (colour != expected) fail = TRUE; + + /* 'Xn' or 'An' formats don't successfully blit to the regular bmp */ + if (test_data[i].format == D3DDDIFMT_R8G8B8 || test_data[i].format == D3DDDIFMT_R5G6B5) + { + pixel = GetPixel( bmp_dc, x, y ); + if ((x == 1 || x == 2) && (y == 1 || y == 2)) + expected = 0x00ffffff; + else if (x < create_desc.Width && y < create_desc.Height) + expected = 0x00000000; + else + expected = CLR_INVALID; + ok(pixel == expected, "%s: got 0x%08x at %u, %u, expect 0x%08x\n", test_data[i].name, + pixel, x, y, expected); + } } } + + DeleteObject( SelectObject( bmp_dc, bmp ) ); + DeleteDC( bmp_dc ); } } #endif /* __REACTOS__ */ Modified: trunk/rostests/winetests/gdi32/dib.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/dib.c?rev…
============================================================================== --- trunk/rostests/winetests/gdi32/dib.c [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/dib.c [iso-8859-1] Sun Jun 4 01:50:46 2017 @@ -36,9 +36,6 @@ #endif static HCRYPTPROV crypt_prov; -static BOOL (WINAPI *pGdiAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION); -static BOOL (WINAPI *pGdiGradientFill)(HDC,TRIVERTEX*,ULONG,void*,ULONG,ULONG); -static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); static const DWORD rop3[256] = { @@ -110,7 +107,6 @@ "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1", "7da9dd3d40d44d92deb9883fb7110443c2d5769a", "e358efb1c11172e40855de620bdb8a8e545cd790", - "9e0c2596c6ecb4f1bc97b18ec3ca493d37626608", "58806549380c964e7a53ad54821d2eb86fa5b9ce", "7fc30d3058c235ce39088de0a598b8c7fe7ca61f", "52a6c769c227f2bb1949097c4c87fed5ee0cbcb1", @@ -134,6 +130,8 @@ "aaf62842bb98d8a2945c4f643baf50afaeea9307", "d7e34fa02db7ad52327f80389bd1ba1b72b6c692", "d7dd4700f49808541bba99244b7eb5840e0a2439", + "00b4e9b243a36a7210a48bcb7c2d410d9cd8c8c7", + "8eb1f99d21a84153e88e7958707049d517ab7641", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "568f87f0194ca19b69a5b2bcdef795d89c5721ce", "a37810f46dee8741fe5adbb3f1f2e87012ffc929", @@ -145,11 +143,8 @@ "eca1998a4d79fb81b2a4103f79e3b846a864eaaf", "e4acfcf2d001fbc431d9af59ab3d3ca7c2d965e5", "2b3198bd5c0a87db5dab13df8bbe14363d02acec", - "f115ef8392ba82d8cd6e7a039320edcd812c1d28", "aebb1b3baa4fd5213bf80a5ad7a50d54de8fdba4", - "f451a05f699ac3bbe155d059e7871a2636887b5f", "5dca709c60e0cd50fa85274a2836aec9eb6168e3", - "dccaef62738ff90da4554a85d8cb846d6436799e", "cc4e1372ddf6e303a7fd159090c9d3a1f8ec2a89", NULL }; @@ -183,7 +178,6 @@ "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1", "7da9dd3d40d44d92deb9883fb7110443c2d5769a", "e358efb1c11172e40855de620bdb8a8e545cd790", - "9e0c2596c6ecb4f1bc97b18ec3ca493d37626608", "58806549380c964e7a53ad54821d2eb86fa5b9ce", "7fc30d3058c235ce39088de0a598b8c7fe7ca61f", "52a6c769c227f2bb1949097c4c87fed5ee0cbcb1", @@ -207,6 +201,8 @@ "aaf62842bb98d8a2945c4f643baf50afaeea9307", "d7e34fa02db7ad52327f80389bd1ba1b72b6c692", "d7dd4700f49808541bba99244b7eb5840e0a2439", + "00b4e9b243a36a7210a48bcb7c2d410d9cd8c8c7", + "8eb1f99d21a84153e88e7958707049d517ab7641", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "568f87f0194ca19b69a5b2bcdef795d89c5721ce", "a37810f46dee8741fe5adbb3f1f2e87012ffc929", @@ -218,11 +214,8 @@ "eca1998a4d79fb81b2a4103f79e3b846a864eaaf", "e4acfcf2d001fbc431d9af59ab3d3ca7c2d965e5", "e4f110504dd3e4e34f960a39ba91a91c67bf26af", - "f115ef8392ba82d8cd6e7a039320edcd812c1d28", "aebb1b3baa4fd5213bf80a5ad7a50d54de8fdba4", - "f451a05f699ac3bbe155d059e7871a2636887b5f", "5dca709c60e0cd50fa85274a2836aec9eb6168e3", - "dccaef62738ff90da4554a85d8cb846d6436799e", "cc4e1372ddf6e303a7fd159090c9d3a1f8ec2a89", NULL }; @@ -256,7 +249,6 @@ "9aa506e3df33e0d5298755aa4144e10eb4b5adcf", "abdf003699364fe45fab7dc61e67c606d0063b40", "89abaadff4e68c738cf9251c51e3609564843381", - "f6aa3f907f620b9f3493f03cb3b4b292df3a9545", "77d0ad32938147aa4038c1eced232b7b5a5f88f3", "43d36e57b702ce56eb250bf53f1ecc4680990cfe", "fd6e0ebb52710ebcdd8dd69931165c83c4930b41", @@ -280,6 +272,8 @@ "118bf4c5bddc206ba737f7aa8b239940cd1aadc2", "eac5d164b83edf2cf85bac242686f9f617ec1fa4", "86c84cc8306975edecc6d4a89a8aff29f59b55a7", + "698d6393e97539806351368f95be478c6fbc62b0", + "c272d1e0342e6089a0182dc42b37e47889116a9b", "af99228aa4cfbd1f61bd824db046144a3c6c2ed7", "25675c30adfe24d6cae60793b156dfdaa36ac3ba", "849d4abf4b690128a5f70e9b8ac78f20c437de06", @@ -291,11 +285,8 @@ "b76e0724496e471b01ef8b34f8beba69f5bde261", "34201d3d3583f89ce3267d3d0c4e01c64463de4b", "693f5c5fbaeaadb5928d34b035499626fecb8394", - "8a9aa84c42dedc3e681191a1229846887ed262ec", "66041875232f64dbfd2d18353aa28e43e8ccb6b5", - "707bc44fc9fed68ff1f537f0473e0cd825dd660f", "f19f5d8e2c96328f06f3985d02ff474fa37b1ea8", - "175a7bcb73c74eceecc000657a0100bccf158ff4", "d26eeb6b2d345b587d4305a1234ec0842a96d4b6", NULL }; @@ -329,7 +320,6 @@ "d578210815e27fe210eb678a71e6d22ba4b4c196", "c7a027c7079dfcc831ca8bc134a509958273073c", "19cf978596195b848df8709aaf637f83f92b8336", - "798a835fe50156eeb478c0a6085b088f53409d52", "86ddf268d854f37e5b478c48792b551b57635db6", "8259d388e02542207b6a08d65d553871ce1c4a09", "faea73ff9436223f8c4ee76ac9861a6609ac4ae4", @@ -353,6 +343,8 @@ "43d67bc61ef54014b022891e5c024fc24b1fe797", "5a713a91fd471fd331bd13b0868c994aa2ffe2b2", "fc0c32afb719295f28bcfef22803bef94f798e20", + "bb2a421bab95f9b5420704ef44c0f3214a0b5a11", + "7735098af7535d8c57266190a13f92d8869e8529", "36f6db4fbe2a1630a7597d3a446f2902755c96ef", "d3f08946300e1700865042aed121870e292d1095", "4782df8e24127e66a434b4e839adebf2dbb223fb", @@ -364,11 +356,8 @@ "555b6f04ba8dec9e2a60693dcaac594227052727", "c199b96a71c3aab2d49ccb5b6294bf14eb0dd1eb", "4238fe9d296b5c72b0a8745cc761f308605b2094", - "943dc6033ab335a6a63e666f70a6bb3a0677e157", "88b6427cf71a6b9a26bfd6026103d50f721651a9", - "88cfa7b7c1487f8eda05fce92b622942c9fb7ca4", "64cf929548bc5324fb14b053077bf5bc4be3e15c", - "ad91dde8566dceaadc3523cdc8149cd7415a1b70", "1936661eee8073068506131c9e89265b2f8403e8", NULL }; @@ -402,7 +391,6 @@ "66b130f83381957cfc4763558c5f5cddf2e3b564", "d548135ce2320499277ce12b80bc35004f8a9787", "85a4f3f1b4b0a170198f1bb5d225fcf77887665e", - "1906ddfd829e735af49245171f8eb7673295d399", "971a0b786d5bccb1bfb9cbb054740e4eb36f9b7a", "e2896035f178b3d20e4f4d1accb1b3d1b4028865", "defd95a10d44cad6e736542920b74efd53e9e7eb", @@ -426,6 +414,8 @@ "cd01f2c0a63b2229d4467d2f874d58edca32b3d4", "8ad5cd520cd628b76d2e5a3f318ae1bbb6b4c994", "49341c297a887186bd47d7465d827ab3147f05e3", + "514c07281ef6702c35e68b230e897303a8cdec81", + "4b41865829b50b2e29beda51b055bd1f908a649c", "325279e76367200d3fd7194d81c09fd139988ece", "c3def160a1e847605ff0fc7edd30397fa90635a0", "2b3e87e0b705b03c7c08f403409ab82cce095ba1", @@ -437,11 +427,8 @@ "3d0853f4f7580d7cd5148c21c34d878ecf39a5f3", "1e5a4ef7f8634847a251d1fcce298c409fd13d87", "481337fbedf181d4324bf7f8299b0327197ff468", - "9ab957870fa4e17aec6a79bc1a4fdb42a5ffcc30", "b4b9f0bf127ef11f510f25684ae21d692609c85e", - "8e32ea3614c3b20899d748db48258761c7158d2b", "5da35bad12e3e9b26a0444d30820099481281e45", - "94f004e98ae8035af948611770a4a2dd6643f510", "045ddaf752e7ffc7ded792f36af3c7c0cfeeae42", NULL }; @@ -475,7 +462,6 @@ "8bc3128ba47891366fd7b02fde7ca19100e64b9f", "e649e00efe7fea1eb8b17f7867fe089e5270c44b", "a0bffbbfb0adf6f188479c88da04e25d76ab4822", - "92a1ab214dd8027c407814420449119466c92840", "b58f19c1800344a2b8e017eb784705bdb2bd8450", "5747a6d5c6ce79731c55e8cf33f7da3025cd35fd", "955390669afed2369b15b32fa519f2f921cdf1a0", @@ -499,6 +485,8 @@ "1015e0217ea13eaa62c7666b8b81aafd75f8f610", "5578c80048520732557abf3a3a3fa22c85015d7d", "b25ba91487ec945410deb2b51bc1156890c032a8", + "4c8c936372755f95051f1159b7ff65a484e1a555", + "bf55d4bdb26ae0f358bd67ef01932563519aab98", "d347ca5c6c4b6a61389247c3b6f61564033e8c25", "ee315634ed92da3a32c2675ecd1b369471c60936", "099c688a920f606655b485e8f0a433dc811bc976", @@ -510,11 +498,8 @@ "0bbdf0a0489428f96e3c1d3e5305f9a893820852", "9d86b1b2bbce90efd3c0b9fe20d23ffa3eeecd20", "8f7a0af421101952e674f37154c1e8c4646ea2d2", - "e96b79bf88988b5694a04dfc3bd0029361b39801", "d12284f58daabbd173dfae6c7e55fd5d822d89b4", - "09cb4ab070083144bed4271c0a2a34ccb6ed13c0", "cc5ed4c9e925f0a457a7437fbb8054528cdd9469", - "c95afd0a020e68a76982fe8663b5d64113987233", "48658ff76c137185c56a53f3ccf0e958d0296742", NULL }; @@ -548,7 +533,6 @@ "d7d97e28ed316f6596c737eb83baa5948d86b673", "ecc2991277d7314f55b00e0f284ae3703aeef81e", "656bf3b7121bcd620a0a3ad488f0d66604824577", - "d7d8493b5fa7a3a8323d6ac84245093a79f052c1", "df5dafe96e528c2cc7fd11e4934e298f53cec34b", "a49530722328ae88fd765792ac0c657efbcce75d", "aa46aa2226e3121eaefa9d0836418e0b69262d69", @@ -559,23 +543,20 @@ "7df915bedcc5951a1b6f828490f7dbb93212e835", "8720478d904a84c24071e97c731c1ba7882b131e", "76215275593631f5900aad3616d725733dc39493", - "81655a550703849a616d4a16504bb9c6f999285f", "573d65665d20f00d36d9782ae2b89772140524ab", - "619414c1b33ac60cb0c0de61df86245d472259b0", "c3d4a1425e17de9e05e3f6dfc6a24c26bfd5ee12", "2a66dae03890ff791eabb982949435adb19af02b", "24ac219478ba406f30794550690486b14cbac5e8", "2b28d20690dc92374ebecb5508f8fdc6c7581790", - "db8c34882ddd46716d14bbf569d530f80db65ed4", "6c652ecce55e71fee16bc1c9b2c5ae4161bdd2ea", "9b02173f424c098ea0f4cc5db9eb65f69263d127", "a92942269911a88793b3460b6f2a2cd56e48eec1", "059db9f0426b371e464ef3d30f1a4f4aa599e101", - "a52d6ceee5c2a04b4e059c0d49337a997cc17e40", "aa4a0a4b7f2697aaf270c89874631974bd9d7183", "a7506e2c001d271593297c9eda9b984d4d894774", "8f447a3820c83662086dfa836da2205b0130fd5f", - "3772003c7fb420003512d0c437b3659d96d89ce4", + "2ebf37d81da3f11434652d06bf65d55e96b090aa", + "ace2c60bd76b11a002bee852686e8783f102eba1", "dab47c9dc149e570045d699598b14a613bf319b3", "2daca4d26a086ed34894693be0b0374402232809", "904f1d82159bcf5485f323bd12b859dc5e83f8eb", @@ -587,11 +568,8 @@ "2230f36f12d4becb242e2962fa1b3694db2496ca", "d81e41a765d7a2d68073f5fde3f74f09df84001d", "0de013c2c6aba9f99cbcf5f8cfd3212ded7ae72a", - "5950f7d00cd8692872377df0e869a7d5ea5e4420", "fedc67d1b0797be5f40cd45280844f2b61d29b0a", - "7de23c68ca224818fdf127c5e96729dcd0de2b8b", "a848b1b0293b05b3f9358a3ffcb21a2e5fdecf05", - "1a0fd0df17fa4c455a4a91cad30b5242f77fd233", "af45bf81d119be5cf6845ad41191ba52637e65e9", NULL }; @@ -625,7 +603,6 @@ "0e183a4c30b3da345129cffe33fe0fc593d8666b", "f14d9a4bd8a365b7c8f068a0dad481b6eb2b178b", "8933450132bf949ba4bc28626968425b5ed2867d", - "9928a8f28a66c00069a124f7171b248817005763", "e4a9dcc3e565cd3a6b7087dd1433f3898bb9cdb2", "eca4f9b16b3bddfd0735fdd792e0ccaadfb9ba49", "233e588cf660e2c9b552cf02065cf63fa6655864", @@ -648,6 +625,8 @@ "9af4907a8144458a73dbb7471784f8c3d9aeffcf", "104e85bad287a62dfe25f0e78280179f18bac765", "f0acb3cfcda62e95bee5f7bc8830ffeb3dd7e5a7", + "fde993dfce1551ef220f5a07ce4acd66e8524ac5", + "a80f3df0aea1e1b30d9833039157bca658218f48", "07b10c3f191d0a93e5e5694aae37dcad407e10f5", "f7900e60347029876ba55e8f0c4c02e89deb36b6", "f373a5f37b82e7523c64c08eb509b6191e49b173", @@ -659,11 +638,8 @@ "13d1634e03bc49cfe14a32278d9b1f5ddbb9be10", "a79e4cc419b9e1735e275e2823da52875536943a", "b0182002cb1f4fba9df3c21a4d046ab41ce7e9be", - "3830cd728c1e72837310940bcdac4e294d6c9843", "f571c7c4aac92491017963032194690c0fa06b42", - "6fd751b7328c02954bce98bed94b3ce3c73db118", "91d50b5a604d6c38aa0d08b9af995490f8ec246b", - "8585783d0373e9696b508776b6e6b18a80b09888", "b53cde47b0e28063770d3b1328c3cc2f774a6300", NULL }; @@ -697,7 +673,6 @@ "1df851515ecf46df5c2d3279535c1763f72353dd", "b68922915ebc2797d58deecf983f7d0cf9a5efbd", "359bd76088a965bb0cee7c44800bc46b2638807e", - "e14e5734b33057b890368f3e9d482d9e5a0358c5", "64205ccaa277e64eeea0c20e99900ac79858ca2c", "2cdee35d43d62da09b4ddfddbd0948ddbb9fc48e", "91f988f575338505ba8a40727865a8d3f2298624", @@ -707,25 +682,21 @@ "4fd49cb49853ef950fd0b7e2e35718a71c8374c7", "e15a355fc09bfd22267917898e2266168ff410e3", "7a9c326a56a94621377a7258be70ba50042ca9a2", - "5e38e03310f1c66f2052af2a745d8c60515707c5", "f994fb5019bf4c1a96eccf89af599eae0aa6b412", "3a71ad6fef147067641e49a5f69b2454e3a5010d", "ea10eac72830dcae19bcb16a076c2b21d844b5b6", - "6376234f542467e5887adfece62f753e998dc19d", "add949d009217ef2b847e34772ba363e4be7b1b8", - "28fcf9f7d098c05de632ae38b2fe33b9635ad445", "0b58666deb3615e912896a764e5c6475989e95e4", - "bf460cc44c0edee851d72587c8425c3f06a62c55", "ea74c00c45569007383b632d7f1d2adc82645717", "5ac22e1a33b0204fdc7a68d54ee94648e96079a0", - "284abed096637c80bb50844e393da9dd4b3f19ac", "9dc776c5ab8256b1301c7d1da60544a9410e6715", - "a433c41c05b6db008a4cb2c52a321d027c6be1fe", "46f772c2832b3aad584674db666bd63e48b4f338", "a9f9ca0049235db51ab7359a5fc3d21be42d2aac", "f3dc739da41fb299637c8660e8c46917ddcf87a8", "abd2fff80f74b311072ecdb91ce9ceba268fa6e9", "9ae38bb94c7b4c0c6dfebbee23d1de4db9b77488", + "8269b32b4a34440f1fa37927308debc7eb85f3fa", + "65b2c868790806be7ab4aaa6114d445c42a31f98", "678979a45126a76eb629992cd64734862f53a555", "2f7ba8803604c032cb1a1228bc021f0f1c03e245", "52e7c2f8b01592898c13f1e7633881e350244209", @@ -737,11 +708,8 @@ "5e9e3e71b06c5efe20f93b3838e745b40b878471", "153ae5c9fc2a31b38c4878b25d9026b9f51f132d", "488341e88810d737de0b26de4e4d4fa0e78eb482", - "bd1e7f40e3971e2ff6c5561286901193a1557527", "5a42b7eeff8198e7b005e4afa4282e6ffb939906", - "d7ffa3893c6fa937569791cf49986518a4a4d96e", "26bc25a011e2b60961ee9d6c6141d928ae24389b", - "8771d5ff7b93b9dd9d077e672b342235dfb28472", "6a1f6e1d494bf6b0ece7af5fa164ebaadb3a19bd", NULL }; @@ -764,13 +732,9 @@ "114bb377b4e78a1978e1ac09388c48861b5223a3", "8d0a92e6333e1b99591962e2def9bc9121111cf5", "9dc511d6947fe816185cdff93bf0cfe0349b72b4", - "eb4c14ee66b012187f5fe6a2ec28b6be956567c8", "216388ddf6b563dd2058a9df65b40b6f72df1715", - "ad11e4b6979cf055e3bf1868112a7bef207385a4", "47f72be971bd2d3399dabd018201f4f5075e96fe", - "de09d41c9ae4338fbfcfe9f8ed71d343537a6f3d", "f39ab890a2b99d0c31e6e047f2315244972f5ffd", - "6e7baf7d328bc2c55366e32967a0db4d2f43ab82", "15b991814d84d6aa252696dd0c6150ef88a8db3f", "1cb52f2a4d17b9b0d8375d016aa8cf0677fcd29a", "9a6cfd68523e40ea1d52847d7747da912cfe2ca9", @@ -779,7 +743,6 @@ "15db343049e3a9b31addc5d2ffebc3fe91b39c51", "a895daf1f20371d4d1c3f93c070124cc13e341c3", "3ddc872384ed8f9eaef472aa14a1d79a2c3f3b04", - "0000000000000000000000000000000000000000", "bd7d8c1cb4b2adc31cf8c7d39a4fa1e3ac7f2545", "33fc8618ce62f5cdd9e06ad61e296f718a99899e", "dcaa7fe030ae4d3029e38ca584047eeb2d17fe10", @@ -789,25 +752,21 @@ "650a51bedd1af92469d2950eb95220db35f95c6e", "3f43aa11e6fccb747cc13224583fb2f951fee08c", "b83f78ae85df87fc7af565db276c60c102274f20", - "6b6f4b97f05e015eb37a5f6aff637235feacd030", "1bd06e4e11929e5e91c3c9f20def639b20e731e8", "d63a6086547e90d2ba84aaebfeae24f3ba0c04f1", "85425940daf119125deb52421b2057acebe6d1cf", - "a3db92382cf0a4c7cafe52c27b1f41520aaa677d", "9869b6f088822fb423996f9968e5a931301fc2c3", - "cdf63ab4ab32c2e8e27527a9588d0fb525f1c945", "a7f81cf3326fa3608acc13cfce2f573912e9d745", - "f2ea92f523f8918b1d514a2d9555dcb4750273b4", "e9c16e43a8f589ae85289c5c3ffea6b22fba1806", "84a4bc0c2c5d36d016da4df95a5d8d6c8ce3ba6f", - "f543efc84e638afbaa456e629100f0274de1a35b", "1bd2587399006eed0d46beff397d32081f6bc58e", - "f8a571de89ed82ffb9cbc041ce1eacb064be2853", "640a49455acabca6954a7fbb6af4e872af342d11", "589e7911e09332ee090371deae17b0120ff990b5", "a1a941fa270cda48c648553ed4b427e16e96f8e0", "115c90df05b1ff754dbdfe2a712ef126034d952d", "fb63bbb2f944fb63ed2d7399f07b168740c1034b", + "ae45f0d463ff916f3cb630103969fd49e8d09ef4", + "2becf041f83d22ac072fef5e0efd9bc1572796fd", "3685c9ae95118a83db3569832c29753276fa1264", "09640bad951c33e7d70a1fced83b1869f65b3fc5", "5eb00252664ec39e61359adb1dade4906a87a248", @@ -820,11 +779,8 @@ "55d302ece31a9b7fc4be4a07a53767ba210273e7", "a6a29836291f9dbca85e25cee60f62ef5faca6d7", "3494a23633405e46af96cb57715617fef1ac252e", - "5a3ae1da30d83cc157e6a4a5617c85598309f4ac", "edc1ad2704452354aa6f79fac244a55b6f509c2e", - "87eab8f81fb2a036080e099760f628037f9306e7", "a3eac75d30f681b3898ee469d368960529634d7d", - "cd5caeabdb71241766d24f038cfc5f1e91e11256", "e2b393dc3f5833f7868668ea31369e90348768cd", NULL }; @@ -858,7 +814,6 @@ "3caf512cfddfd463d0750cfe3cadb58548eb2ae8", "4e5e7d5fd64818b2b3d3e793c88f603b699d2f0f", "c4efce8f7ed2d380ea5dc6fe1ef8448a27827532", - "bdc0a354635b879871077c5b712570e469863c99", "d599bf210423fe3adbb4f1de87d9360de97827d0", "bae7c8b789e4e9b336c03c4daee3bce63fe039d9", "cc01f17928f7780cefd423ea653b072eea723a1b", @@ -868,15 +823,11 @@ "9a603513cd81acf70cf8b27b0d544e7f672e9d40", "f4a334e69535de74ee5ed54be93a75120a66e54a", "f751a55fb738b63b6fd7c229c33ef92605d0c9c1", - "995f77f2f53398399f09d1365cb4dfd105764e5c", "61907a6685bba93077da40cfb28cf2ab74552fd2", "122015e5e17c1c317c6e51c0e207826b606a4077", "c21851589a5f8a45ea5f9bb3e72f4f88d0a6697d", - "8c609921d4a3ed89a994a75482b27496bf103cf5", "eb2ce16a6ae251f4965135ee776776b5fc02c42c", - "66493ee117719e172f327a426af601996025f28c", "acead2745fec0b6c817fa601353bdf2d197b64f7", - "a6b858b2d125c159529d3f3ec45b31925a79acff", "1f1379089d7c6e8d733aaa4eaffbe02db6255b61", "d83adc669c0dea0dc4812b93f998514b6f02d805", "9e8ceb7c3cd68e043b6d875c8c84a1e394962412", @@ -885,6 +836,8 @@ "7d1bfff706b0713e53209407889f83a0da26a81d", "5a1d8f9ea978b820edbc5c9e1c6f1cac022620ad", "31e667c2dbb81dcf81d01cb88f794e88ddb90ff2", + "c404446958788fac00ee1eff571d682bc21dd7ac", + "95060f3dc9e6d01ada42f09a871b69f0699cb77c", "465d9cd0a77ab4fcf035aa67544b2a26269e0b09", "600d6b2713d5e4c0d90c02660245ed26c7ae3033", "0025a440866a404523a8a20e79a8891e45a2ff56", @@ -896,11 +849,8 @@ "293c41a7ed923a4617560481ae8815cebf83701a", "ec06b56f3abe277be42650ebd49dabeaae9e756d", "750c923785ba2afb9ce597516c072f90f014bf95", - "80089132f8a11d86e8038f2f8e12dfba46624ee5", "bde5a62a065c027561226fbec5155e938ba7f6b3", - "a6311d74fc058079a327abb536e69353be719925", "fbaa8848a1d3896469c37fd43ab44233f5b875a3", - "0000000000000000000000000000000000000000", "c2ac98ef716fd8a5ac8f08ce66293d9a96344337", NULL }; @@ -934,7 +884,6 @@ "26ad5116562e7b58c76a26eaf521e2e40899e944", "1bcc54eaf8e3c2b7c59ecccb23c240181d7ba8b8", "4f827ca6927f15191588456f985bf29d2a3b3c24", - "e7de769c3d12ea9dd223bef4881c578823bec67e", "6fb102d020e5554116feefc8482104f3ae2036d2", "ae546ffd30b837afc7dfcb5c9ce4f01d15b35ddc", "20c9eb3276c08fdce35755e349bec94b04929812", @@ -957,6 +906,8 @@ "46760975993f9881b7bbe94123173e6a683d3f25", "c644f460937107214a88d5eb9e846d27abd8c874", "df5feb905a31c288008cf5e82d73ac818a160d82", + "4f9658dde0432a711a4d783c1b5aa3365fb7d54b", + "09438163dcbede3890a0e6d8e614c97a06759380", "d8af3868c66c7d6dac35ec8ee0317b38a6910bb1", "ec8e2aebfb4a1c28ebcd0e053b9e4d8638b50951", "ccf8d11b1e81895e9781f17c227c821228d8714b", @@ -968,11 +919,8 @@ "287ea7db721e641439888cb9f4bac3a5f16124eb", "dd9eaa5325cdf250e89162ac84207978ebb6458e", "42466aab11852741d937c1ff6f3bb711e58415a6", - "0663cf6330591fcf744aba96664e05d90243d07a", "3024fa38333f83a639b0f0e6ac6d4b9868231157", - "6fe7d0d17b892032cfd171c3d7c365f030b5be38", "7ae780dcc7cf04dda50648bfc07cc6a7a2f2189e", - "0000000000000000000000000000000000000000", "9ab46e0c42f82dc73df8a55cbf881abd72397cec", NULL }; @@ -1006,7 +954,6 @@ "afdf41fca7951c6dd6193320de1295f2c68fe52a", "f2f1f331fe6b1b31d7c9ddd37793b375fc01d3d4", "f0af0f1edcb837bdf1535c1f5e9988c21ae9bfd1", - "0000000000000000000000000000000000000000", "71c4577baaf35f12f6707b1e2f78a1e8c0d41d0b", "9b7d6b12385bb9e1cd881758aff342bd5427432b", "6fdd5aa022da2a8af6f1d02b6072ebc068b4b600", @@ -1029,6 +976,8 @@ "5eeb56afea8040a8fb18c11f29931b836474126d", "30c256a783c4874261667bb31307eb282ab9470e", "f8681c09f1abfc38d31e47622cb8798cd896a00e", + "0ba7e5d68419702605739acb52fcc01c96cb63d4", + "f8d2f196ba8a16f54acb934e61a759ab7d3f2f05", "b5ee51cfc73acb59a2f6124509ea236f8fc7f9f7", "d374d4d92c940ae42a9b42c14d744341b68a8c14", "06a6a224be0f5cdc51ac4704f9f57fc1f3813d6f", @@ -1040,11 +989,8 @@ "aa89612798fbc4e11a73b6233c0ac4832e6af2f9", "c96a998be5c1d588ef1243cfd2610d056d16947e", "68bee638d59a373f33f308751471b3ef41849582", - "be0501175cc3cbb61217fca76356f761117fb40f", "8fa37e26cdae406c2d1c81b1175dcf0311cf60c9", - "3efe128a5bf250f2c460664e8f543f5ec54d5dc2", "2d5123e757cf00e423a89160d7dc4997c3688829", - "0000000000000000000000000000000000000000", "36dfdad9f3f5cfde6add3cef23368c343d30469a", NULL }; @@ -1067,34 +1013,17 @@ "b0cc1f5e244ae0c0835a9866a46abdfcd56d1cb1", "7ddf19df5bbdf4475b6ec1bc042425e382502864", "144c9a846e5e37ac6efd5ed3a97ec231479e8fca", - "c5ffc59048bf786b5646ad6226cd8633965de9ef", - "40fadc2d24c713b04ff96f7dc26e70e85f26c55e", "400a21caa01e015096ee1afcf1b54e7f8ec515bd", - "0ff4b49797e30e3555aab45219adf449a9a560ff", - "280327328ca940c212ce24fe72e0b00014072767", "144c9a846e5e37ac6efd5ed3a97ec231479e8fca", - "b85463875f755b85f1464b1b6275912bcbad6c9f", - "816f200969feecc788b61dfeecf05b1790984401", "a4964d8bbf80fe785f906bc0f7c5b113242a58fc", - "a5d204cc7342d40b765ca042f8668e22601c4ff9", "adb2818f6d3845dd140bc0f9abdbaa89d2a8c3de", - "0a76e0121facb103857130bc6e12185ad77fc3fa", - "02aede714773d654d0fc2f640afaa133ec718ad5", "13cc63972aee4f6ae27091a8af18de01f1d3a5da", - "3bb745ccb08402ce6fac6ee26fb8d7aad2dba27e", - "b26699f62661e16a1dc452d24c88ce363a1f2998", "4d95c3d1e170f004c80aa8c52feafb8e0e90760e", - "c14832e69ec3585c15987b3d69d5007236fa9814", - "e44ea620b0c47125a34193537ab9d219a52ad028", "ef2db9fb75a672f69bab88e5d08fe64f50ec2bc4", - "df81db2a9b3942a82e0dc5e57247b642f9b42702", - "8819bf7a43295161fe045a42936000b3a51fe200", - "e08dbc26469c229f75ccbf1a38a133401f270b84", "d1e6091caa4482d3142df3b958606c41ebf4698e", "07c1116d8286fb665a1005de220eadc3d5999aaf", "4afb0649488f6e6f7d3a2b8bf438d82f2c88f4d1", "f2fe295317e795a88edd0b2c52618b8cb0e7f2ce", - "ffc78c075d4be66806f6c59180772d5eed963dc0", "c86eeaeed09871dee4b43722ba512d2d3af7f4d0", "24b1a6241c81dbb950cfbe5da6798fd59eb36266", "1007d3b531b4bc3553d4547bc88443fc1f497cf6", @@ -1119,6 +1048,8 @@ "a2a928de9007d765da496abec8c21b23601f8c45", "41a417c1f25f2619301afa44bfcde85198985792", "23366004515f3bc46796ea505d748f8d0f97fbe1", + "ba682eb15c0ddffb942e6086e0ccad2353ed7241", + "58273e1fbf961ff2c772d57160d60170e258d3fe", "88763f8e8fcf4f78fa864325791a9dd35a0bd279", "013cee26bac8f815eadad4bfc012d9b5d01c3b7f", "44a28536466dc895feb824b23dfd4a47c6948af8", @@ -1130,14 +1061,8 @@ "53ab1fcccd09fa5cbff77497f36a70a3b3cb8b81", "4842a30dd7fdf38ddc3ddec85c08efe13a0e2e0b", "cc76db6da5ba1776f20240a5ad97a26a9cdf96b0", - "014f477664a7f4ce4a948d6359a2707119afc8e2", - "74d01690e344bc22e7a0478e7a09ccd92354c486", "9ab50a663b74577b656e9849484a909d7ac52eeb", - "128eefd2ee043d59dc37918065f687e378e5ca95", - "d7e2daab98ce1f698c4bfedfc01c0d79fcb76b8e", "8d34215487088b5d4ef63062270ce25c2862643d", - "826562eb11a0d0bba77fa21245f7406a194e9225", - "bbae6f0659e095a42b420082079663f937065813", "bbabe686a6955402c90530e7c67f1428868369b3", NULL }; @@ -1193,6 +1118,8 @@ { 100, 100, 356, 356 }, { 10, 10, 356, 356 }, { 100, 100, 356, 356 }, + { 0, 0, 260, 39 }, + { 0, 0, 16, 16 }, { 10, 10, 416, 26 }, { 10, 8, 60, 104 }, { 0, 10, 511, 306 }, @@ -1281,12 +1208,6 @@ ok( EqualRect( current_bounds, &rect ), "%s: %s: expected bounds %s got %s\n", dst_format, info, wine_dbgstr_rect( current_bounds ), wine_dbgstr_rect( &rect )); - current_bounds++; -} - -static void skip_compare( int count ) -{ - current_sha1 += count; current_bounds++; } @@ -1821,10 +1742,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 8888 dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1851,10 +1769,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "bottom-up 8888 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "bottom-up 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash(hdc, bmi, bits, "bottom-up 8888 dib brush patblt"); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1881,10 +1796,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 24 bpp brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 24 bpp brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash(hdc, bmi, bits, "top-down 24 bpp brush patblt"); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1911,10 +1823,7 @@ y += 25; } } - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed == 256) /* 8-bpp grayscale broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", 1, FALSE); - else - compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", dib_is_1bpp ? 1 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 555 dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1951,7 +1860,7 @@ y += 25; } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 8 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 8 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1973,7 +1882,7 @@ y += 25; } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 4 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 4 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -1999,7 +1908,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "top-down 1 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "top-down 1 bpp dib brush patblt", 0, dib_is_1bpp); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); @@ -2023,7 +1932,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "1 bpp ddb brush patblt", dib_is_1bpp ? 3 : 0, dib_is_1bpp); + compare_hash_broken_todo(hdc, bmi, bits, "1 bpp ddb brush patblt", 0, dib_is_1bpp); DeleteObject(bmp); SelectObject(hdc, orig_brush); @@ -2058,21 +1967,12 @@ /* RTL rectangles */ - if( !pSetLayout ) - { - win_skip("Don't have SetLayout\n"); - skip_compare(1); - } - else - { - pSetLayout(hdc, LAYOUT_RTL); - PaintRgn(hdc, hrgn); - PatBlt(hdc, 10, 250, 10, 10, PATCOPY); - Rectangle(hdc, 100, 250, 110, 260); - compare_hash(hdc, bmi, bits, "rtl"); - - pSetLayout(hdc, LAYOUT_LTR); - } + SetLayout(hdc, LAYOUT_RTL); + PaintRgn(hdc, hrgn); + PatBlt(hdc, 10, 250, 10, 10, PATCOPY); + Rectangle(hdc, 100, 250, 110, 260); + compare_hash(hdc, bmi, bits, "rtl"); + SetLayout(hdc, LAYOUT_LTR); DeleteObject( hrgn ); for(i = 0, y = 10; i < 256; i++) @@ -2092,7 +1992,7 @@ } } - compare_hash_broken_todo(hdc, bmi, bits, "hatch brushes", 1, FALSE); /* nt4 is different */ + compare_hash(hdc, bmi, bits, "hatch brushes"); /* overlapping blits */ @@ -2196,39 +2096,17 @@ BitBlt( hdc, 7, 28, 2, 2, src_dc, 0, 0, SRCCOPY ); BitBlt( hdc, 7, 32, 9, 2, src_dc, 0, 0, SRCCOPY ); BitBlt( hdc, 7, 36, 10, 2, src_dc, 0, 0, SRCCOPY ); - - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp SRCCOPY" ); blend.SourceConstantAlpha = 0xd0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp no alpha", 0, dib_is_1bpp ); blend.SourceConstantAlpha = 0xb0; blend.AlphaFormat = AC_SRC_ALPHA; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 50, 50, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 50, 50, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 32-bpp alpha", 0, dib_is_1bpp ); /* blitting with 32-bpp r10g10b10 source */ @@ -2249,10 +2127,7 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp r10g10b10 SRCCOPY" ); /* blitting with 32-bpp b6g6r6 source */ @@ -2273,10 +2148,7 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 32-bpp b6g6r6 SRCCOPY" ); /* blitting with 24-bpp source */ @@ -2293,24 +2165,12 @@ } BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 24-bpp SRCCOPY" ); blend.SourceConstantAlpha = 0xe0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 24-bpp", 0, dib_is_1bpp ); /* blitting with 16-bpp BI_RGB source */ @@ -2323,10 +2183,7 @@ ((WORD *)src_bits)[y * 256 + x] = x | x << 4 | x << 8 | y << 3 | y << 7; BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed > 5) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp SRCCOPY" ); /* blitting with 16-bpp b4g4r4 source */ @@ -2342,10 +2199,7 @@ ((WORD *)src_bits)[y * 256 + x] = x | x << 4 | x << 8 | y << 3 | y << 7; BitBlt( hdc, 100, 100, 256, 256, src_dc, 0, 0, SRCCOPY ); - if (bmi->bmiHeader.biBitCount == 8 && bmi->bmiHeader.biClrUsed > 5) /* broken on NT4 */ - compare_hash_broken_todo(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY", 1, FALSE ); - else - compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY" ); + compare_hash(hdc, bmi, bits, "BitBlt src 16-bpp b4g4r4 SRCCOPY" ); /* blitting with 8-bpp source */ @@ -2364,17 +2218,8 @@ blend.SourceConstantAlpha = 0xd0; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 0, dib_is_1bpp ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 8-bpp", 0, dib_is_1bpp ); /* blitting with 4-bpp source */ @@ -2412,17 +2257,95 @@ blend.SourceConstantAlpha = 0x90; blend.AlphaFormat = 0; - if (pGdiAlphaBlend) pGdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); - if (bmi->bmiHeader.biBitCount == 16 && bmi->bmiHeader.biCompression == BI_RGB) /* 555 broken on w2k */ - { - if (!pGdiAlphaBlend) skip_compare(2); - else compare_hash_broken_todo(hdc, bmi, bits, "AlphaBlend src 1-bpp", 1, FALSE ); - } - else - { - if (!pGdiAlphaBlend) skip_compare(1); - else compare_hash(hdc, bmi, bits, "AlphaBlend src 1-bpp" ); - } + GdiAlphaBlend( hdc, 100, 100, 256, 256, src_dc, 0, 0, 256, 256, blend ); + compare_hash(hdc, bmi, bits, "AlphaBlend src 1-bpp" ); + + /* blitting with 1-bpp ddb source */ + + bmp = CreateBitmap( 16, 16, 1, 1, ddb_brush_bits ); + DeleteObject( SelectObject( src_dc, bmp ) ); + + old_text = GetTextColor( hdc ); + old_bkgnd = GetBkColor( hdc ); + for (i = 0; i < 256; i += 13) + { + SetTextColor(hdc, RGB( i, 2*i, 255 - i ) ); + SetBkColor(hdc, RGB( 255 - i, i / 3, i ) ); + BitBlt( hdc, i, 0, 13, 13, src_dc, 0, 0, SRCCOPY ); + } + for (i = 0; i < 256; i += 13) + { + SetTextColor(hdc, PALETTEINDEX( i )); + SetBkColor(hdc, PALETTEINDEX( i + 3 )); + BitBlt( hdc, i, 13, 13, 13, src_dc, 0, 0, SRCCOPY ); + } + for (i = 0; i < 256; i += 13) + { + SetTextColor(hdc, DIBINDEX( i )); + SetBkColor(hdc, DIBINDEX( i + 3 )); + BitBlt( hdc, i, 26, 13, 13, src_dc, 0, 0, SRCCOPY ); + } + SetTextColor( hdc, old_text ); + SetBkColor( hdc, old_bkgnd ); + compare_hash(hdc, bmi, bits, "BitBlt src 1-bpp ddb SRCCOPY" ); + + DeleteObject( bmp ); + + /* blitting to 1-bpp ddb dest */ + + bmp = CreateBitmap( 16, 16, 1, 1, ddb_brush_bits ); + DeleteObject( SelectObject( src_dc, bmp ) ); + + for (y = 0; y < 16; y++) + for (x = 0; x < 16; x++) + SetPixel( hdc, x, y, RGB( 16 * x, 16 * y, 8 * (x + y)) ); + PatBlt( hdc, 15, 15, 1, 1, WHITENESS ); + /* source colors are ignored */ + SetTextColor( src_dc, 0xbeef ); + SetBkColor( src_dc, RGB( 16 * 2, 16 * 3, 8 * (2 + 3) )); + /* destination text color is also ignored */ + SetTextColor( hdc, 0xbedead ); + + i = 16; + SetBkColor( hdc, 0xffffff ); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, 0 ); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, RGB( 16 * 2, 16 * 3, 8 * (2 + 3) )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, RGB( 16 * 13, 16 * 14, 8 * (13 + 14) )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, PALETTEINDEX( 1 )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetBkColor( hdc, DIBINDEX( 2 )); + BitBlt( src_dc, 0, 0, 16, 16, hdc, 0, 0, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + StretchDIBits( src_dc, 0, 0, 16, 16, 0, + bmi->bmiHeader.biHeight - 16, 16, 16, bits, bmi, DIB_RGB_COLORS, SRCCOPY ); + GetBitmapBits( bmp, 32, bits + get_stride(bmi) * i++ ); + SetTextColor( hdc, old_text ); + SetBkColor( hdc, old_bkgnd ); + compare_hash(hdc, bmi, bits, "BitBlt dst 1-bpp ddb"); DeleteDC( src_dc ); DeleteObject( bmp ); @@ -2553,7 +2476,6 @@ /* gradients */ - if (pGdiGradientFill) { TRIVERTEX vrect[] = { @@ -2600,28 +2522,17 @@ { 2, 1, 0 }, { 3, 5, 4 }, { 7, 6, 8 }, { 10, 11, 9 }, { 14, 13, 12 }, { 17, 15, 16 }, { 19, 20, 18 } }; - pGdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_H ); + GdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_H ); for (i = 0; i < 4; i++) vrect[i].y += 250; - pGdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_V ); - - if (bmi->bmiHeader.biBitCount <= 8) /* Wine's 8-bit dithering isn't identical to Windows */ - compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, 1 ); - else - compare_hash(hdc, bmi, bits, "GdiGradientFill" ); - - pGdiGradientFill( hdc, vtri, 7*3, tri, 7, GRADIENT_FILL_TRIANGLE ); + GdiGradientFill( hdc, vrect, 4, rect, 2, GRADIENT_FILL_RECT_V ); + /* Wine's 8-bit dithering isn't identical to Windows */ + compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, (bmi->bmiHeader.biBitCount <= 8) ); + + GdiGradientFill( hdc, vtri, 7*3, tri, 7, GRADIENT_FILL_TRIANGLE ); for (i = 0; i < 7*3; i++) vtri[i].y += 100; - pGdiGradientFill( hdc, vtri, 7*3, tri + 7, 7, GRADIENT_FILL_TRIANGLE ); - if (bmi->bmiHeader.biBitCount <= 8) /* Wine's 8-bit dithering isn't identical to Windows */ - compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, 1 ); - else - compare_hash(hdc, bmi, bits, "GdiGradientFill" ); - } - else - { - win_skip( "GdiGradientFill not supported\n" ); - skip_compare(1); - skip_compare(1); + GdiGradientFill( hdc, vtri, 7*3, tri + 7, 7, GRADIENT_FILL_TRIANGLE ); + /* Wine's 8-bit dithering isn't identical to Windows */ + compare_hash_broken_todo(hdc, bmi, bits, "GdiGradientFill", 0, (bmi->bmiHeader.biBitCount <= 8) ); } /* wide pen */ @@ -2700,8 +2611,7 @@ LineTo( hdc, 10 * i, 200 + i ); LineTo( hdc, 20 * i, 200 + i ); } - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "wide brushed pen", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "wide brushed pen", 0, dib_is_1bpp ); for (i = 1; i < 20; i++) { @@ -2714,8 +2624,7 @@ LineTo( hdc, 10 * i, 200 + i ); LineTo( hdc, 20 * i, 200 + i ); } - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "dashed wide brushed pen", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "dashed wide brushed pen", 0, dib_is_1bpp ); DeleteObject(bmp); SetTextColor(hdc, old_text); @@ -2771,8 +2680,7 @@ SelectPalette( hdc, old_hpal, FALSE ); DeleteObject( hpal ); - /* NT4 broken for all cases, W2K for 1 bpp only */ - compare_hash_broken_todo(hdc, bmi, bits, "PALETTEINDEX", 1 + dib_is_1bpp, dib_is_1bpp ); + compare_hash_broken_todo(hdc, bmi, bits, "PALETTEINDEX", 0, dib_is_1bpp ); /* ExtFloodFill */ @@ -3019,9 +2927,7 @@ ok(ds.dsBitfields[0] == 0, "got %08x\n", ds.dsBitfields[0]); ok(ds.dsBitfields[1] == 0, "got %08x\n", ds.dsBitfields[1]); ok(ds.dsBitfields[2] == 0, "got %08x\n", ds.dsBitfields[2]); - ok(ds.dsBmih.biCompression == BI_RGB || - broken(ds.dsBmih.biCompression == BI_BITFIELDS), /* nt4 sp1 and 2 */ - "got %x\n", ds.dsBmih.biCompression); + ok(ds.dsBmih.biCompression == BI_RGB, "got %x\n", ds.dsBmih.biCompression); orig_bm = SelectObject(mem_dc, dib); @@ -3352,11 +3258,6 @@ START_TEST(dib) { - HMODULE mod = GetModuleHandleA("gdi32.dll"); - pSetLayout = (void *)GetProcAddress( mod, "SetLayout" ); - pGdiAlphaBlend = (void *)GetProcAddress( mod, "GdiAlphaBlend" ); - pGdiGradientFill = (void *)GetProcAddress( mod, "GdiGradientFill" ); - CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); test_simple_graphics(); 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] Sun Jun 4 01:50:46 2017 @@ -30,10 +30,12 @@ #include "wine/test.h" -/* Do not allow more than 1 deviation here */ -#define match_off_by_1(a, b, exact) (abs((a) - (b)) <= ((exact) ? 0 : 1)) - -#define near_match(a, b) (abs((a) - (b)) <= 6) +static inline BOOL match_off_by_n(int a, int b, unsigned int n) +{ + return abs(a - b) <= n; +} +#define match_off_by_1(a, b, exact) match_off_by_n((a), (b), (exact) ? 0 : 1) +#define near_match(a, b) match_off_by_n((a), (b), 6) #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) static LONG (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); @@ -107,20 +109,20 @@ system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID()); } -static void *heap_alloc( size_t len ) -{ - return HeapAlloc( GetProcessHeap(), 0, len ); -} - -static void *heap_realloc( void *p, size_t len ) -{ - if (!p) return heap_alloc( len ); - return HeapReAlloc( GetProcessHeap(), 0, p, len ); -} - -static void heap_free( void *p ) -{ - HeapFree( GetProcessHeap(), 0, p ); +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) +{ + return HeapAlloc(GetProcessHeap(), 0, size); +} + +static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size) +{ + if (!mem) return heap_alloc(size); + return HeapReAlloc(GetProcessHeap(), 0, mem, size); +} + +static inline BOOL heap_free(void *mem) +{ + return HeapFree(GetProcessHeap(), 0, mem); } static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) @@ -4908,6 +4910,37 @@ ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio); } +static void test_GetCharacterPlacement(void) +{ + GCP_RESULTSA result; + DWORD size, size2; + WCHAR glyphs[20]; + HDC hdc; + + hdc = CreateCompatibleDC(0); + ok(!!hdc, "CreateCompatibleDC failed\n"); + + memset(&result, 0, sizeof(result)); + result.lStructSize = sizeof(result); + result.lpGlyphs = glyphs; + result.nGlyphs = 20; + + size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0); + ok(size, "GetCharacterPlacementA failed!\n"); + + size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0); + ok(size2, "GetCharacterPlacementA failed!\n"); + ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); + + size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER); + ok(size2, "GetCharacterPlacementA failed!\n"); + ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); + + size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER); + ok(size, "GetCharacterPlacementA failed!\n"); + ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size); +} + static void test_CreateFontIndirect(void) { LOGFONTA lf, getobj_lf; @@ -5303,10 +5336,13 @@ ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg_proc, (LPARAM)&efnd, 0); ok(!ret, "MS Shell Dlg should be enumerated\n"); ok(efnd.total > 0, "MS Shell Dlg should be enumerated\n"); - ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg"); - ok(!ret, "expected MS Shell Dlg, got %s\n", efnd.elf[0].elfLogFont.lfFaceName); - ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg"); - ok(ret, "did not expect MS Shell Dlg\n"); + if (efnd.total) + { + ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg"); + ok(!ret, "expected MS Shell Dlg, got %s\n", efnd.elf[0].elfLogFont.lfFaceName); + ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg"); + ok(ret, "did not expect MS Shell Dlg\n"); + } efnd.total = 0; ret = EnumFontFamiliesExA(hdc, NULL, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0); @@ -5318,10 +5354,13 @@ ret = EnumFontFamiliesExA(hdc, &lf, enum_ms_shell_dlg2_proc, (LPARAM)&efnd, 0); ok(!ret, "MS Shell Dlg 2 should be enumerated\n"); ok(efnd.total > 0, "MS Shell Dlg 2 should be enumerated\n"); - ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg 2"); - ok(!ret, "expected MS Shell Dlg 2, got %s\n", efnd.elf[0].elfLogFont.lfFaceName); - ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2"); - ok(ret, "did not expect MS Shell Dlg 2\n"); + if (efnd.total) + { + ret = strcmp((const char *)efnd.elf[0].elfLogFont.lfFaceName, "MS Shell Dlg 2"); + ok(!ret, "expected MS Shell Dlg 2, got %s\n", efnd.elf[0].elfLogFont.lfFaceName); + ret = strcmp((const char *)efnd.elf[0].elfFullName, "MS Shell Dlg 2"); + ok(ret, "did not expect MS Shell Dlg 2\n"); + } heap_free(efnd.elf); DeleteDC(hdc); @@ -5646,6 +5685,45 @@ ReleaseDC(NULL, hdc); } +static void test_fstype_fixup(void) +{ + HDC hdc; + LOGFONTA lf; + HFONT hfont, hfont_prev; + DWORD ret; + OUTLINETEXTMETRICA *otm; + DWORD otm_size; + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = 72; + lstrcpyA(lf.lfFaceName, "wine_test"); + + SetLastError(0xdeadbeef); + hfont = CreateFontIndirectA(&lf); + ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError()); + + hdc = GetDC(NULL); + + hfont_prev = SelectObject(hdc, hfont); + ok(hfont_prev != NULL, "SelectObject failed\n"); + + otm_size = GetOutlineTextMetricsA(hdc, 0, NULL); + otm = HeapAlloc(GetProcessHeap(), 0, otm_size); + otm->otmSize = sizeof(*otm); + ret = GetOutlineTextMetricsA(hdc, otm->otmSize, otm); + ok(ret == otm->otmSize, "expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError()); + + /* Test font has fsType set to 0x7fff, test that reserved bits are filtered out, + valid bits are 1, 2, 3, 8, 9. */ + ok((otm->otmfsType & ~0x30e) == 0, "fsType %#x\n", otm->otmfsType); + + HeapFree(GetProcessHeap(), 0, otm); + + SelectObject(hdc, hfont_prev); + DeleteObject(hfont); + ReleaseDC(NULL, hdc); +} + static void test_CreateScalableFontResource(void) { char ttf_name[MAX_PATH]; @@ -5729,6 +5807,7 @@ test_GetGlyphOutline_empty_contour(); test_GetGlyphOutline_metric_clipping(); + test_fstype_fixup(); ret = pRemoveFontResourceExA(fot_name, FR_PRIVATE, 0); ok(!ret, "RemoveFontResourceEx() with not matching flags should fail\n"); @@ -6589,6 +6668,48 @@ DeleteDC(hdc); } +static void test_GetCharWidthI(void) +{ + static const char *teststr = "wine "; + HFONT hfont, prev_hfont; + WORD glyphs[5]; + INT widths[5]; + LOGFONTA lf; + ABC abc[5]; + int len, i; + DWORD nb; + BOOL ret; + HDC hdc; + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Tahoma"); + lf.lfHeight = -20; + + hdc = GetDC(0); + + hfont = CreateFontIndirectA(&lf); + prev_hfont = SelectObject(hdc, hfont); + + len = strlen(teststr); + nb = GetGlyphIndicesA(hdc, teststr, len, glyphs, 0); + ok(nb == len, "\n"); + + memset(abc, 0xcc, sizeof(abc)); + ret = GetCharABCWidthsI(hdc, 0, len, glyphs, abc); + ok(ret, "GetCharABCWidthsI failed\n"); + + memset(widths, 0xcc, sizeof(widths)); + ret = GetCharWidthI(hdc, 0, len, glyphs, widths); + ok(ret, "GetCharWidthI failed\n"); + + for (i = 0; i < len; i++) + ok(widths[i] == abc[i].abcA + abc[i].abcB + abc[i].abcC, "%u, glyph %u, got width %d\n", + i, glyphs[i], widths[i]); + + DeleteObject(SelectObject(hdc, prev_hfont)); + ReleaseDC(0, hdc); +} + START_TEST(font) { init(); @@ -6640,6 +6761,7 @@ test_GetTextMetrics2("Arial", -11); test_GetTextMetrics2("Arial", -55); test_GetTextMetrics2("Arial", -110); + test_GetCharacterPlacement(); test_CreateFontIndirect(); test_CreateFontIndirectEx(); test_oemcharset(); @@ -6651,6 +6773,7 @@ test_GetCharWidth32(); test_fake_bold_font(); test_bitmap_font_glyph_index(); + test_GetCharWidthI(); /* These tests should be last test until RemoveFontResource * is properly implemented. Modified: trunk/rostests/winetests/gdi32/wine_test.sfd URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/wine_test…
============================================================================== --- trunk/rostests/winetests/gdi32/wine_test.sfd [iso-8859-1] (original) +++ trunk/rostests/winetests/gdi32/wine_test.sfd [iso-8859-1] Sun Jun 4 01:50:46 2017 @@ -15,7 +15,7 @@ Layer: 0 1 "Back" 1 Layer: 1 1 "Fore" 0 XUID: [1021 905 592216984 1247726] -FSType: 0 +FSType: 32767 OS2Version: 2 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 1 Modified: trunk/rostests/winetests/gdi32/wine_test.ttf URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/gdi32/wine_test…
============================================================================== Binary files - no diff available.
7 years, 6 months
1
0
0
0
[akhaldi] 74880: [REG_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:37 2017 New Revision: 74880 URL:
http://svn.reactos.org/svn/reactos?rev=74880&view=rev
Log: [REG_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/reg/reg.c Modified: trunk/rostests/winetests/reg/reg.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/reg/reg.c?rev=7…
============================================================================== --- trunk/rostests/winetests/reg/reg.c [iso-8859-1] (original) +++ trunk/rostests/winetests/reg/reg.c [iso-8859-1] Sun Jun 4 01:50:37 2017 @@ -772,12 +772,12 @@ static void test_import(void) { - DWORD r, dword = 0x123; - char test1_reg[MAX_PATH], test2_reg[MAX_PATH]; - char cmdline[MAX_PATH]; - char test_string[] = "Test string"; + DWORD r, dword = 0x123, type, size; + char test1_reg[MAX_PATH], test2_reg[MAX_PATH], cmdline[MAX_PATH]; + char test_string[] = "Test string", buffer[8]; HKEY hkey, subkey; LONG err; + BYTE hex[8]; run_reg_exe("reg import", &r); ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); @@ -876,6 +876,84 @@ err = RegOpenKeyExA(HKEY_CURRENT_USER, KEY_BASE, 0, KEY_READ, &hkey); todo_wine ok(err == ERROR_SUCCESS, "got %d, expected 0\n", err); + + test_import_str("REGEDIT3\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test1\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test1"); + + test_import_str("regedit4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test2\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test2"); + + test_import_str("Regedit4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test3\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test3"); + + test_import_str("REGEDIT 4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test4\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test4"); + + test_import_str("REGEDIT4FOO\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test5\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test5"); + + test_import_str("REGEDIT4 FOO\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test6\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test6"); + + test_import_str("REGEDIT5\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test7\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test7"); + + test_import_str("REGEDIT9\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test8\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test8"); + + test_import_str("Windows Registry Editor Version 4.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test9\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test9"); + + test_import_str("Windows Registry Editor Version 5\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test10\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test10"); + + test_import_str("WINDOWS REGISTRY EDITOR VERSION 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test11\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test11"); + + test_import_str("Windows Registry Editor version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test12\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test12"); test_import_str("REGEDIT4\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" @@ -1086,6 +1164,238 @@ test_import_str("REGEDIT4\n\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line3\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line3"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line4\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line4"); + + test_import_str("Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line5\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line5"); + + test_import_str("Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line6\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line6"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line7\"=hex(7):4c,69,6e,\\;comment\n" + " 65,20,\\;comment\n" + " 63,6f,6e,\\;comment\n" + " 63,61,74,\\;comment\n" + " 65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line7", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line8\"=hex(7):4c,69,6e,\\;#comment\n" + " 65,20,\\;#comment\n" + " 63,6f,6e,\\;#comment\n" + " 63,61,74,\\;#comment\n" + " 65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line8", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line9\"=hex(7):4c,69,6e,\\;comment\n" + " 65,20,\\;comment\n" + " 63,6f,6e,\\;comment\n" + " 63,61,74,\\#comment\n" + " 65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line9"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line10\"=hex(7):4c,69,6e,65,20,\\\n" + " 63,6f,6e,\\;comment\n" + " 63,61,74,\\\n\n" + " 65,6e,\\;comment\n\n" + " 61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line10", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine32a\"=dword:1\n" + "\"Wine32b\"=dword:4444\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x1; + todo_wine verify_reg(hkey, "Wine32a", REG_DWORD, &dword, sizeof(dword), 0); + dword = 0x4444; + todo_wine verify_reg(hkey, "Wine32b", REG_DWORD, &dword, sizeof(dword), 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine33a\"=dword:\n" + "\"Wine33b\"=dword:hello\n" + "\"Wine33c\"=dword:123456789\n" + "\"Wine33d\"=dword:012345678\n" + "\"Wine33e\"=dword:000000001\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine33a"); + todo_wine verify_reg_nonexist(hkey, "Wine33b"); + todo_wine verify_reg_nonexist(hkey, "Wine33c"); + todo_wine verify_reg_nonexist(hkey, "Wine33d"); + todo_wine verify_reg_nonexist(hkey, "Wine33e"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine34a\"=dword:12345678abc\n" + "\"Wine34b\"=dword:12345678 abc\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine34a"); + todo_wine verify_reg_nonexist(hkey, "Wine34b"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine35a\"=dword:0x123\n" + "\"Wine35b\"=dword:123 456\n" + "\"Wine35c\"=dword:1234 5678\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine35a"); + todo_wine verify_reg_nonexist(hkey, "Wine35b"); + todo_wine verify_reg_nonexist(hkey, "Wine35c"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine36a\"=dword:1234;5678\n" + "\"Wine36b\"=dword:1234 ;5678\n" + "\"Wine36c\"=dword:1234#5678\n" + "\"Wine36d\"=dword:1234 #5678\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x1234; + todo_wine verify_reg(hkey, "Wine36a", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine36b", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg_nonexist(hkey, "Wine36c"); + todo_wine verify_reg_nonexist(hkey, "Wine36d"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine37a\"=\"foo\"bar\"\n" + "\"Wine37b\"=\"foo\"\"bar\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine37a"); + todo_wine verify_reg_nonexist(hkey, "Wine37b"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Empty string\"=\"\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Empty string", REG_SZ, "", 1, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test38a\"=\n" + "\"Test38b\"=\\\"\n" + "\"Test38c\"=\\\"Value\\\"\n" + "\"Test38d\"=\\\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test38a"); + todo_wine verify_reg_nonexist(hkey, "Test38b"); + todo_wine verify_reg_nonexist(hkey, "Test38c"); + todo_wine verify_reg_nonexist(hkey, "Test38d"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine39a\"=\"Value1\" ;comment\n" + "\"Wine39b\"=\"Value2\"\t\t;comment\n" + "\"Wine39c\"=\"Value3\" #comment\n" + "\"Wine39d\"=\"Value4\"\t\t#comment\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine39a", REG_SZ, "Value1", 7, 0); + todo_wine verify_reg(hkey, "Wine39b", REG_SZ, "Value2", 7, 0); + todo_wine verify_reg_nonexist(hkey, "Wine39c"); + todo_wine verify_reg_nonexist(hkey, "Wine39d"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoBeginQuote\"=Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoBeginQuote"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoEndQuote\"=\"Asdffdsa\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoEndQuote"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoQuotes\"=Asdffdsa\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoQuotes"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "NameNoBeginQuote\"=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoBeginQuote"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"NameNoEndQuote=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoEndQuote"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "NameNoQuotes=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoQuotes"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"MixedQuotes=Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "MixedQuotes"); + todo_wine verify_reg_nonexist(hkey, "MixedQuotes=Asdffdsa"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine40a\"=hex(2):4c,69,6e,65,00\n" + "\"Wine40b\"=\"Value 1\"\n" + "\"Wine40c\"=hex(2):4c,69,6e,65\\\n" + "\"Wine40d\"=\"Value 2\"\n" + "\"Wine40e\"=hex(2):4c,69,6e,65,\\\n" + "\"Wine40f\"=\"Value 3\"\n" + "\"Wine40g\"=\"Value 4\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine40a", REG_EXPAND_SZ, "Line", 5, 0); + todo_wine verify_reg(hkey, "Wine40b", REG_SZ, "Value 1", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine40c"); + todo_wine verify_reg(hkey, "Wine40d", REG_SZ, "Value 2", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine40e"); + todo_wine verify_reg_nonexist(hkey, "Wine40f"); + todo_wine verify_reg(hkey, "Wine40g", REG_SZ, "Value 4", 8, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine41a\"=dword:1234\\\n" + "5678\n" + "\"Wine41b\"=\"Test \\\n" + "Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine41a"); + todo_wine verify_reg_nonexist(hkey, "Wine41b"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" "\"double\\\"quote\"=\"valid \\\"or\\\" not\"\n" "\"single'quote\"=dword:00000008\n\n", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); @@ -1093,6 +1403,171 @@ dword = 0x00000008; todo_wine verify_reg(hkey, "single'quote", REG_DWORD, &dword, sizeof(dword), 0); + /* Test key name and value name concatenation */ + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "\\\n" + "Subkey1]\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + err = RegOpenKeyExA(hkey, "Subkey1", 0, KEY_READ, &subkey); + todo_wine ok(err == ERROR_FILE_NOT_FOUND, "got %d, expected 2\n", err); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "\n" + "\\Subkey2]\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + err = RegOpenKeyExA(hkey, "Subkey2", 0, KEY_READ, &subkey); + todo_wine ok(err == ERROR_FILE_NOT_FOUND, "got %d, expected 2\n", err); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine\\\n" + "42a\"=\"Value 1\"\n" + "\"Wine42b\"=\"Value 2\"\n" + "\"Wine\n" + "\\42c\"=\"Value 3\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine42a"); + todo_wine verify_reg(hkey, "Wine42b", REG_SZ, "Value 2", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine42c"); + + /* Test hex data concatenation for REG_NONE, REG_EXPAND_SZ and REG_BINARY */ + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine43a\"=hex(0):56,00,61,00,6c,00,75,00,65,00,00,00\n" + "\"Wine43b\"=hex(0):56,00,61,00,6c,00,\\\n" + " 75,00,65,00,00,00\n" + "\"Wine43c\"=hex(0):56,00,61,00,6c,00\\\n" + ",75,00,65,00,00,00\n" + "\"Wine43d\"=hex(0):56,00,61,00,6c,00\\\n" + " ,75,00,65,00,00,00\n" + "\"Wine43e\"=hex(0):56,00,61,00,6c,00\\\n" + " 75,00,65,00,00,00\n" + "\"Wine43f\"=hex(0):56,00,61,00,6c,00,7\\\n" + "5,00,65,00,00,00\n" + "\"Wine43g\"=hex(0):56,00,61,00,6c,00,7\\\n" + " 5,00,65,00,00,00\n" + "\"Wine43h\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\\\n" + " 65,00,00,00\n" + "\"Wine43i\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\n" + " 65,00,00,00\n" + "\"Wine43j\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,;comment\n" + " 65,00,00,00\n" + "\"Wine43k\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\\#comment\n" + " 65,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine43a", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg(hkey, "Wine43b", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg_nonexist(hkey, "Wine43c"); + todo_wine verify_reg_nonexist(hkey, "Wine43d"); + todo_wine verify_reg_nonexist(hkey, "Wine43e"); + todo_wine verify_reg_nonexist(hkey, "Wine43f"); + todo_wine verify_reg_nonexist(hkey, "Wine43g"); + todo_wine verify_reg(hkey, "Wine43h", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg(hkey, "Wine43i", REG_NONE, "V\0a\0l\0u", 8, 0); + todo_wine verify_reg(hkey, "Wine43j", REG_NONE, "V\0a\0l\0u", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine43k"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine44a\"=hex(2):25,50,41,54,48,25,00\n" + "\"Wine44b\"=hex(2):25,50,41,\\\n" + " 54,48,25,00\n" + "\"Wine44c\"=hex(2):25,50,41\\\n" + ",54,48,25,00\n" + "\"Wine44d\"=hex(2):25,50,41\\\n" + " ,54,48,25,00\n" + "\"Wine44e\"=hex(2):25,50,41\\\n" + " 54,48,25,00\n" + "\"Wine44f\"=hex(2):25,50,4\\\n" + "1,54,48,25,00\n" + "\"Wine44g\"=hex(2):25,50,4\\\n" + " 1,54,48,25,00\n" + "\"Wine44h\"=hex(2):25,50,41,\\;comment\n" + " 54,48,\\\n" + " 25,00\n" + "\"Wine44i\"=hex(2):25,50,41,\\;comment\n" + " 54,48,\n" + " 25,00\n" + "\"Wine44j\"=hex(2):25,50,41,\\;comment\n" + " 54,48,;comment\n" + " 25,00\n" + "\"Wine44k\"=hex(2):25,50,41,\\;comment\n" + " 54,48,\\#comment\n" + " 25,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine44a", REG_EXPAND_SZ, "%PATH%", 7, 0); + todo_wine verify_reg(hkey, "Wine44b", REG_EXPAND_SZ, "%PATH%", 7, 0); + todo_wine verify_reg_nonexist(hkey, "Wine44c"); + todo_wine verify_reg_nonexist(hkey, "Wine44d"); + todo_wine verify_reg_nonexist(hkey, "Wine44e"); + todo_wine verify_reg_nonexist(hkey, "Wine44f"); + todo_wine verify_reg_nonexist(hkey, "Wine44g"); + todo_wine verify_reg(hkey, "Wine44h", REG_EXPAND_SZ, "%PATH%", 7, 0); + /* Wine44i */ + size = sizeof(buffer); + err = RegQueryValueExA(hkey, "Wine44i", NULL, &type, (BYTE *)&buffer, &size); + todo_wine ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); + todo_wine ok(type == REG_EXPAND_SZ, "got wrong type %u, expected %u\n", type, REG_EXPAND_SZ); + todo_wine ok(size == 6 || broken(size == 5) /* WinXP */, "got wrong size %u, expected 6\n", size); + todo_wine ok(memcmp(buffer, "%PATH", size) == 0, "got wrong data\n"); + /* Wine44j */ + size = sizeof(buffer); + memset(buffer, '-', size); + err = RegQueryValueExA(hkey, "Wine44j", NULL, &type, (BYTE *)&buffer, &size); + todo_wine ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); + todo_wine ok(type == REG_EXPAND_SZ, "got wrong type %u, expected %u\n", type, REG_EXPAND_SZ); + todo_wine ok(size == 6 || broken(size == 5) /* WinXP */, "got wrong size %u, expected 6\n", size); + todo_wine ok(memcmp(buffer, "%PATH", size) == 0, "got wrong data\n"); + /* Wine44k */ + todo_wine verify_reg_nonexist(hkey, "Wine44k"); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine45a\"=hex:11,22,33,44,55,66,77,88\n" + "\"Wine45b\"=hex:11,22,33,44,\\\n" + " 55,66,77,88\n" + "\"Wine45c\"=hex:11,22,33,44\\\n" + ",55,66,77,88\n" + "\"Wine45d\"=hex:11,22,33,44\\\n" + " ,55,66,77,88\n" + "\"Wine45e\"=hex:11,22,33,44\\\n" + " 55,66,77,88\n" + "\"Wine45f\"=hex:11,22,33,4\\\n" + "4,55,66,77,88\n" + "\"Wine45g\"=hex:11,22,33,4\\\n" + " 4,55,66,77,88\n" + "\"Wine45h\"=hex:11,22,33,44,\\;comment\n" + " 55,66,\\\n" + " 77,88\n" + "\"Wine45i\"=hex:11,22,33,44,\\;comment\n" + " 55,66,\n" + " 77,88\n" + "\"Wine45j\"=hex:11,22,33,44,\\;comment\n" + " 55,66,;comment\n" + " 77,88\n" + "\"Wine45k\"=hex:11,22,33,\\;comment\n" + " 44,55,66,\\#comment\n" + " 77,88\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + hex[0] = 0x11; hex[1] = 0x22; hex[2] = 0x33; hex[3] = 0x44; + hex[4] = 0x55; hex[5] = 0x66; hex[6] = 0x77; hex[7] = 0x88; + todo_wine verify_reg(hkey, "Wine45a", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg(hkey, "Wine45b", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg_nonexist(hkey, "Wine45c"); + todo_wine verify_reg_nonexist(hkey, "Wine45d"); + todo_wine verify_reg_nonexist(hkey, "Wine45e"); + todo_wine verify_reg_nonexist(hkey, "Wine45f"); + todo_wine verify_reg_nonexist(hkey, "Wine45g"); + todo_wine verify_reg(hkey, "Wine45h", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg(hkey, "Wine45i", REG_BINARY, hex, 6, 0); + todo_wine verify_reg(hkey, "Wine45j", REG_BINARY, hex, 6, 0); + todo_wine verify_reg_nonexist(hkey, "Wine45k"); + + /* Test import with subkeys */ test_import_str("REGEDIT4\n\n" "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey\"1]\n" "\"Wine\\\\31\"=\"Test value\"\n\n", &r); @@ -1161,6 +1636,56 @@ err = RegOpenKeyExA(HKEY_CURRENT_USER, KEY_BASE, 0, KEY_READ, &hkey); todo_wine ok(err == ERROR_SUCCESS, "got %d, expected 0\n", err); + test_import_wstr("\xef\xbb\xbfREGEDIT3\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test1\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test1"); + + test_import_wstr("\xef\xbb\xbfregedit4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test2\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test2"); + + test_import_wstr("\xef\xbb\xbfRegedit4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test3\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test3"); + + test_import_wstr("\xef\xbb\xbfREGEDIT 4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test4\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test4"); + + test_import_wstr("\xef\xbb\xbfREGEDIT4FOO\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test5\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test5"); + + test_import_wstr("\xef\xbb\xbfREGEDIT4 FOO\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test6\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test6"); + + test_import_wstr("\xef\xbb\xbfREGEDIT5\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test7\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test7"); + + test_import_wstr("\xef\xbb\xbfREGEDIT9\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test8\"=\"Value\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test8"); + test_import_wstr("\xef\xbb\xbfREGEDIT4\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" "\"Unicode1\"=\"Value1\"\n", &r); @@ -1210,6 +1735,34 @@ test_import_wstr("\xef\xbb\xbf\nWindows Registry Editor Version 5.00\n", &r); ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, "got exit code %d, expected 1\n", r); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 4.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test9\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test9"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test10\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test10"); + + test_import_wstr("\xef\xbb\xbfWINDOWS REGISTRY EDITOR VERSION 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test11\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test11"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test12\"=\"Value\"\n", &r); + ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS) /* WinXP */, + "got exit code %d, expected 1\n", r); + todo_wine verify_reg_nonexist(hkey, "Test12"); test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" @@ -1377,6 +1930,160 @@ test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine32a\"=dword:1\n" + "\"Wine32b\"=dword:4444\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x1; + todo_wine verify_reg(hkey, "Wine32a", REG_DWORD, &dword, sizeof(dword), 0); + dword = 0x4444; + todo_wine verify_reg(hkey, "Wine32b", REG_DWORD, &dword, sizeof(dword), 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine33a\"=dword:\n" + "\"Wine33b\"=dword:hello\n" + "\"Wine33c\"=dword:123456789\n" + "\"Wine33d\"=dword:012345678\n" + "\"Wine33e\"=dword:000000001\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine33a"); + todo_wine verify_reg_nonexist(hkey, "Wine33b"); + todo_wine verify_reg_nonexist(hkey, "Wine33c"); + todo_wine verify_reg_nonexist(hkey, "Wine33d"); + todo_wine verify_reg_nonexist(hkey, "Wine33e"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine34a\"=dword:12345678abc\n" + "\"Wine34b\"=dword:12345678 abc\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine34a"); + todo_wine verify_reg_nonexist(hkey, "Wine34b"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine35a\"=dword:0x123\n" + "\"Wine35b\"=dword:123 456\n" + "\"Wine35c\"=dword:1234 5678\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine35a"); + todo_wine verify_reg_nonexist(hkey, "Wine35b"); + todo_wine verify_reg_nonexist(hkey, "Wine35c"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine36a\"=dword:1234;5678\n" + "\"Wine36b\"=dword:1234 ;5678\n" + "\"Wine36c\"=dword:1234#5678\n" + "\"Wine36d\"=dword:1234 #5678\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x1234; + todo_wine verify_reg(hkey, "Wine36a", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine36b", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg_nonexist(hkey, "Wine36c"); + todo_wine verify_reg_nonexist(hkey, "Wine36d"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine37a\"=\"foo\"bar\"\n" + "\"Wine37b\"=\"foo\"\"bar\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine37a"); + todo_wine verify_reg_nonexist(hkey, "Wine37b"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Empty string\"=\"\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Empty string", REG_SZ, "", 1, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Test38a\"=\n" + "\"Test38b\"=\\\"\n" + "\"Test38c\"=\\\"Value\\\"\n" + "\"Test38d\"=\\\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Test38a"); + todo_wine verify_reg_nonexist(hkey, "Test38b"); + todo_wine verify_reg_nonexist(hkey, "Test38c"); + todo_wine verify_reg_nonexist(hkey, "Test38d"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine39a\"=\"Value1\" ;comment\n" + "\"Wine39b\"=\"Value2\"\t\t;comment\n" + "\"Wine39c\"=\"Value3\" #comment\n" + "\"Wine39d\"=\"Value4\"\t\t#comment\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine39a", REG_SZ, "Value1", 7, 0); + todo_wine verify_reg(hkey, "Wine39b", REG_SZ, "Value2", 7, 0); + todo_wine verify_reg_nonexist(hkey, "Wine39c"); + todo_wine verify_reg_nonexist(hkey, "Wine39d"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoBeginQuote\"=Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoBeginQuote"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoEndQuote\"=\"Asdffdsa\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoEndQuote"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"TestNoQuotes\"=Asdffdsa\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "TestNoQuotes"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "NameNoBeginQuote\"=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoBeginQuote"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"NameNoEndQuote=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoEndQuote"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "NameNoQuotes=\"Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "NameNoQuotes"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"MixedQuotes=Asdffdsa\"\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "MixedQuotes"); + todo_wine verify_reg_nonexist(hkey, "MixedQuotes=Asdffdsa"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine40a\"=hex(2):4c,00,69,00,6e,00,65,00,00,00\n" + "\"Wine40b\"=\"Value 1\"\n" + "\"Wine40c\"=hex(2):4c,00,69,00,6e,00,65,00\\\n" + "\"Wine40d\"=\"Value 2\"\n" + "\"Wine40e\"=hex(2):4c,00,69,00,6e,00,65,00,\\\n" + "\"Wine40f\"=\"Value 3\"\n" + "\"Wine40g\"=\"Value 4\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine40a", REG_EXPAND_SZ, "Line", 5, 0); + todo_wine verify_reg(hkey, "Wine40b", REG_SZ, "Value 1", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine40c"); + todo_wine verify_reg(hkey, "Wine40d", REG_SZ, "Value 2", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine40e"); + todo_wine verify_reg_nonexist(hkey, "Wine40f"); + todo_wine verify_reg(hkey, "Wine40g", REG_SZ, "Value 4", 8, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" "\"Multi-Line1\"=hex(7):4c,00,69,00,6e,00,65,00,20,00,\\\n" " 63,00,6f,00,6e,00,\\;comment\n" " 63,00,61,00,74,00,\\;comment\n" @@ -1393,6 +2100,84 @@ todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); todo_wine verify_reg(hkey, "Multi-Line2", REG_MULTI_SZ, "Line concat", 12, 0); + test_import_wstr("\xef\xbb\xbfREGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line3\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line3"); + + test_import_wstr("\xef\xbb\xbfREGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line4\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line4"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line5\"=hex(7):4c,69,6e,65,20\\\n" + ",63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line5"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line6\"=hex(7):4c,69,6e,65,20\\\n" + " ,63,6f,6e,63,61,74,65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line6"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line7\"=hex(7):4c,00,69,00,6e,00,\\;comment\n" + " 65,00,20,00,\\;comment\n" + " 63,00,6f,00,6e,00,\\;comment\n" + " 63,00,61,00,74,00,\\;comment\n" + " 65,00,6e,00,61,00,74,00,69,00,6f,00,6e,00,00,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line7", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line8\"=hex(7):4c,00,69,00,6e,00,\\;#comment\n" + " 65,00,20,00,\\;#comment\n" + " 63,00,6f,00,6e,00,\\;#comment\n" + " 63,00,61,00,74,00,\\;#comment\n" + " 65,00,6e,00,61,00,74,00,69,00,6f,00,6e,00,00,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line8", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line9\"=hex(7):4c,00,69,00,6e,00,\\;comment\n" + " 65,00,20,00,\\;comment\n" + " 63,00,6f,00,6e,00,\\;comment\n" + " 63,00,61,00,74,00,\\#comment\n" + " 65,00,6e,00,61,00,74,00,69,00,6f,00,6e,00,00,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Multi-Line9"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Multi-Line10\"=hex(7):4c,00,69,00,6e,00,65,00,20,00,\\\n" + " 63,00,6f,00,6e,00,\\;comment\n" + " 63,00,61,00,74,00,\\\n\n" + " 65,00,6e,00,\\;comment\n\n" + " 61,00,74,00,69,00,6f,00,6e,00,00,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Multi-Line10", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine41a\"=dword:1234\\\n" + "5678\n" + "\"Wine41b\"=\"Test \\\n" + "Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine41a"); + todo_wine verify_reg_nonexist(hkey, "Wine41b"); + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" "\"double\\\"quote\"=\"valid \\\"or\\\" not\"\n" @@ -1402,6 +2187,171 @@ dword = 0x00000008; todo_wine verify_reg(hkey, "single'quote", REG_DWORD, &dword, sizeof(dword), 0); + /* Test key name and value name concatenation */ + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "\\\n" + "Subkey1]\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + err = RegOpenKeyExA(hkey, "Subkey1", 0, KEY_READ, &subkey); + todo_wine ok(err == ERROR_FILE_NOT_FOUND, "got %d, expected 2\n", err); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "\n" + "\\Subkey2]\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + err = RegOpenKeyExA(hkey, "Subkey2", 0, KEY_READ, &subkey); + todo_wine ok(err == ERROR_FILE_NOT_FOUND, "got %d, expected 2\n", err); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine\\\n" + "42a\"=\"Value 1\"\n" + "\"Wine42b\"=\"Value 2\"\n" + "\"Wine\n" + "\\42c\"=\"Value 3\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg_nonexist(hkey, "Wine42a"); + todo_wine verify_reg(hkey, "Wine42b", REG_SZ, "Value 2", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine42c"); + + /* Test hex data concatenation for REG_NONE, REG_EXPAND_SZ and REG_BINARY */ + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine43a\"=hex(0):56,00,61,00,6c,00,75,00,65,00,00,00\n" + "\"Wine43b\"=hex(0):56,00,61,00,6c,00,\\\n" + " 75,00,65,00,00,00\n" + "\"Wine43c\"=hex(0):56,00,61,00,6c,00\\\n" + ",75,00,65,00,00,00\n" + "\"Wine43d\"=hex(0):56,00,61,00,6c,00\\\n" + " ,75,00,65,00,00,00\n" + "\"Wine43e\"=hex(0):56,00,61,00,6c,00\\\n" + " 75,00,65,00,00,00\n" + "\"Wine43f\"=hex(0):56,00,61,00,6c,00,7\\\n" + "5,00,65,00,00,00\n" + "\"Wine43g\"=hex(0):56,00,61,00,6c,00,7\\\n" + " 5,00,65,00,00,00\n" + "\"Wine43h\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\\\n" + " 65,00,00,00\n" + "\"Wine43i\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\n" + " 65,00,00,00\n" + "\"Wine43j\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,;comment\n" + " 65,00,00,00\n" + "\"Wine43k\"=hex(0):56,00,61,00,\\;comment\n" + " 6c,00,75,00,\\#comment\n" + " 65,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine43a", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg(hkey, "Wine43b", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg_nonexist(hkey, "Wine43c"); + todo_wine verify_reg_nonexist(hkey, "Wine43d"); + todo_wine verify_reg_nonexist(hkey, "Wine43e"); + todo_wine verify_reg_nonexist(hkey, "Wine43f"); + todo_wine verify_reg_nonexist(hkey, "Wine43g"); + todo_wine verify_reg(hkey, "Wine43h", REG_NONE, "V\0a\0l\0u\0e\0\0", 12, 0); + todo_wine verify_reg(hkey, "Wine43i", REG_NONE, "V\0a\0l\0u", 8, 0); + todo_wine verify_reg(hkey, "Wine43j", REG_NONE, "V\0a\0l\0u", 8, 0); + todo_wine verify_reg_nonexist(hkey, "Wine43k"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine44a\"=hex(2):25,00,50,00,41,00,54,00,48,00,25,00,00,00\n" + "\"Wine44b\"=hex(2):25,00,50,00,41,00,\\\n" + " 54,00,48,00,25,00,00,00\n" + "\"Wine44c\"=hex(2):25,00,50,00,41,00\\\n" + ",54,00,48,00,25,00,00,00\n" + "\"Wine44d\"=hex(2):25,00,50,00,41,00\\\n" + " ,54,00,48,00,25,00,00,00\n" + "\"Wine44e\"=hex(2):25,00,50,00,41,00\\\n" + " 54,00,48,00,25,00,00,00\n" + "\"Wine44f\"=hex(2):25,00,50,00,4\\\n" + "1,00,54,00,48,00,25,00,00,00\n" + "\"Wine44g\"=hex(2):25,00,50,00,4\\\n" + " 1,00,54,00,48,00,25,00,00,00\n" + "\"Wine44h\"=hex(2):25,00,50,00,41,00,\\;comment\n" + " 54,00,48,00,\\\n" + " 25,00,00,00\n" + "\"Wine44i\"=hex(2):25,00,50,00,41,00,\\;comment\n" + " 54,00,48,00\n" + " 25,00,00,00\n" + "\"Wine44j\"=hex(2):25,00,50,00,41,00,\\;comment\n" + " 54,00,48,00;comment\n" + " 25,00,00,00\n" + "\"Wine44k\"=hex(2):25,00,50,00,41,00,\\;comment\n" + " 54,00,48,00,\\#comment\n" + " 25,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine44a", REG_EXPAND_SZ, "%PATH%", 7, 0); + todo_wine verify_reg(hkey, "Wine44b", REG_EXPAND_SZ, "%PATH%", 7, 0); + todo_wine verify_reg_nonexist(hkey, "Wine44c"); + todo_wine verify_reg_nonexist(hkey, "Wine44d"); + todo_wine verify_reg_nonexist(hkey, "Wine44e"); + todo_wine verify_reg_nonexist(hkey, "Wine44f"); + todo_wine verify_reg_nonexist(hkey, "Wine44g"); + todo_wine verify_reg(hkey, "Wine44h", REG_EXPAND_SZ, "%PATH%", 7, 0); + /* Wine44i */ + size = sizeof(buffer); + err = RegQueryValueExA(hkey, "Wine44i", NULL, &type, (BYTE *)&buffer, &size); + todo_wine ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); + todo_wine ok(type == REG_EXPAND_SZ, "got wrong type %u, expected %u\n", type, REG_EXPAND_SZ); + todo_wine ok(size == 6 || broken(size == 5) /* WinXP */, "got wrong size %u, expected 6\n", size); + todo_wine ok(memcmp(buffer, "%PATH", size) == 0, "got wrong data\n"); + /* Wine44j */ + size = sizeof(buffer); + memset(buffer, '-', size); + err = RegQueryValueExA(hkey, "Wine44j", NULL, &type, (BYTE *)&buffer, &size); + todo_wine ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); + todo_wine ok(type == REG_EXPAND_SZ, "got wrong type %u, expected %u\n", type, REG_EXPAND_SZ); + todo_wine ok(size == 6 || broken(size == 5) /* WinXP */, "got wrong size %u, expected 6\n", size); + todo_wine ok(memcmp(buffer, "%PATH", size) == 0, "got wrong data\n"); + /* Wine44k */ + todo_wine verify_reg_nonexist(hkey, "Wine44k"); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine45a\"=hex:11,22,33,44,55,66,77,88\n" + "\"Wine45b\"=hex:11,22,33,44,\\\n" + " 55,66,77,88\n" + "\"Wine45c\"=hex:11,22,33,44\\\n" + ",55,66,77,88\n" + "\"Wine45d\"=hex:11,22,33,44\\\n" + " ,55,66,77,88\n" + "\"Wine45e\"=hex:11,22,33,44\\\n" + " 55,66,77,88\n" + "\"Wine45f\"=hex:11,22,33,4\\\n" + "4,55,66,77,88\n" + "\"Wine45g\"=hex:11,22,33,4\\\n" + " 4,55,66,77,88\n" + "\"Wine45h\"=hex:11,22,33,44,\\;comment\n" + " 55,66,\\\n" + " 77,88\n" + "\"Wine45i\"=hex:11,22,33,44,\\;comment\n" + " 55,66,\n" + " 77,88\n" + "\"Wine45j\"=hex:11,22,33,44,\\;comment\n" + " 55,66,;comment\n" + " 77,88\n" + "\"Wine45k\"=hex:11,22,33,\\;comment\n" + " 44,55,66,\\#comment\n" + " 77,88\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + hex[0] = 0x11; hex[1] = 0x22; hex[2] = 0x33; hex[3] = 0x44; + hex[4] = 0x55; hex[5] = 0x66; hex[6] = 0x77; hex[7] = 0x88; + todo_wine verify_reg(hkey, "Wine45a", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg(hkey, "Wine45b", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg_nonexist(hkey, "Wine45c"); + todo_wine verify_reg_nonexist(hkey, "Wine45d"); + todo_wine verify_reg_nonexist(hkey, "Wine45e"); + todo_wine verify_reg_nonexist(hkey, "Wine45f"); + todo_wine verify_reg_nonexist(hkey, "Wine45g"); + todo_wine verify_reg(hkey, "Wine45h", REG_BINARY, hex, sizeof(hex), 0); + todo_wine verify_reg(hkey, "Wine45i", REG_BINARY, hex, 6, 0); + todo_wine verify_reg(hkey, "Wine45j", REG_BINARY, hex, 6, 0); + todo_wine verify_reg_nonexist(hkey, "Wine45k"); + + /* Test import with subkeys */ test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey\"1]\n" "\"Wine\\\\31\"=\"Test value\"\n\n", &r); @@ -1433,6 +2383,293 @@ todo_wine ok(err == ERROR_SUCCESS, "got %d, expected 0\n", err); } +static void test_import_with_whitespace(void) +{ + HKEY hkey; + DWORD r, dword; + LONG err; + + test_import_str(" REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + + err = RegOpenKeyExA(HKEY_CURRENT_USER, KEY_BASE, 0, KEY_READ, &hkey); + todo_wine ok(err == ERROR_SUCCESS, "RegOpenKeyExA failed: got %d, expected 0\n", err); + + test_import_str(" REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1a\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1a", REG_SZ, "Value", 6, 0); + + test_import_str("\tREGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1b\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1b", REG_SZ, "Value", 6, 0); + + test_import_str(" \t REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1c\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1c", REG_SZ, "Value", 6, 0); + + test_import_str("REGEDIT4\n\n" + " [HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2a\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2a", REG_SZ, "Value", 6, 0); + + test_import_str("REGEDIT4\n\n" + "\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2b\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2b", REG_SZ, "Value", 6, 0); + + test_import_str("REGEDIT4\n\n" + " \t [HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2c\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2c", REG_SZ, "Value", 6, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \"Wine3a\"=\"Two leading spaces\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3a", REG_SZ, "Two leading spaces", 19, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t\"Wine3b\"=\"One leading tab\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3b", REG_SZ, "One leading tab", 16, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \t \"Wine3c\"=\"Space, tab, space\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3c", REG_SZ, "Space, tab, space", 18, 0); + + test_import_str(" REGEDIT4\n\n" + "\t\t\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t \"Wine4a\"=\"Tab and four spaces\"\n" + " \"Wine4b\"=dword:00112233\n" + "\t \t \t \t \t \t \"Wine4c\"=hex(7):4c,69,6e,65,20,\\\n" + " 63,6f,6e,\\;comment\n" + "\t\t\t\t63,61,74,\\;comment\n" + " \t65,6e,61,74,69,6f,6e,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine4a", REG_SZ, "Tab and four spaces", 20, 0); + dword = 0x112233; + todo_wine verify_reg(hkey, "Wine4b", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine4c", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_str(" REGEDIT4\n\n" + "\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \"Wine5a\"=\"Leading spaces\"\n" + "\t\t\"Wine5b\"\t\t=\"Leading tabs\"\n" + "\t \"Wine5c\"=\t \"Tabs and spaces\"\n" + " \"Wine5d\" \t = \t \"More whitespace\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine5a", REG_SZ, "Leading spaces", 15, 0); + todo_wine verify_reg(hkey, "Wine5b", REG_SZ, "Leading tabs", 13, 0); + todo_wine verify_reg(hkey, "Wine5c", REG_SZ, "Tabs and spaces", 16, 0); + todo_wine verify_reg(hkey, "Wine5d", REG_SZ, "More whitespace", 16, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\" Wine6a\"=\"Leading spaces\"\n" + "\"\t\tWine6b\"=\"Leading tabs\"\n" + " \" Wine6c \" = \" Spaces everywhere \" \n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, " Wine6a", REG_SZ, "Leading spaces", 15, 0); + todo_wine verify_reg(hkey, "\t\tWine6b", REG_SZ, "Leading tabs", 13, 0); + todo_wine verify_reg(hkey, " Wine6c ", REG_SZ, " Spaces everywhere ", 22, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine7a\"=\" Four spaces in the data\"\n" + "\"Wine7b\"=\"\t\tTwo tabs in the data\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine7a", REG_SZ, " Four spaces in the data", 28, 0); + todo_wine verify_reg(hkey, "Wine7b", REG_SZ, "\t\tTwo tabs in the data", 23, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine8a\"=\"Trailing spaces\" \n" + "\"Wine8b\"=\"Trailing tabs and spaces\"\t \t\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine8a", REG_SZ, "Trailing spaces", 16, 0); + todo_wine verify_reg(hkey, "Wine8b", REG_SZ, "Trailing tabs and spaces", 25, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine9a\"=dword: 00000008\n" + "\"Wine9b\"=dword:\t\t00000008\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x00000008; + todo_wine verify_reg(hkey, "Wine9a", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine9b", REG_DWORD, &dword, sizeof(dword), 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "@ = \"Test Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "", REG_SZ, "Test Value", 11, 0); + + test_import_str("REGEDIT4\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t@\t=\tdword:\t00000008\t\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "", REG_DWORD, &dword, sizeof(DWORD), 0); + + err = RegCloseKey(hkey); + todo_wine ok(err == ERROR_SUCCESS, "RegCloseKey failed: got %d, expected 0\n", err); + + err = RegDeleteKeyA(HKEY_CURRENT_USER, KEY_BASE); + todo_wine ok(err == ERROR_SUCCESS, "RegDeleteKeyA failed: got %d, expected 0\n", err); + + test_import_wstr("\xef\xbb\xbf Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + + err = RegOpenKeyExA(HKEY_CURRENT_USER, KEY_BASE, 0, KEY_READ, &hkey); + todo_wine ok(err == ERROR_SUCCESS, "RegOpenKeyExA failed: got %d, expected 0\n", err); + + test_import_wstr("\xef\xbb\xbf Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1a\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1a", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbf\tWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1b\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1b", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbf \t Windows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine1c\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine1c", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + " [HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2a\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2a", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2b\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2b", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + " \t [HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine2c\"=\"Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine2c", REG_SZ, "Value", 6, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \"Wine3a\"=\"Two leading spaces\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3a", REG_SZ, "Two leading spaces", 19, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t\"Wine3b\"=\"One leading tab\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3b", REG_SZ, "One leading tab", 16, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \t \"Wine3c\"=\"Space, tab, space\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine3c", REG_SZ, "Space, tab, space", 18, 0); + + test_import_wstr("\xef\xbb\xbf Windows Registry Editor Version 5.00\n\n" + "\t\t\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t \"Wine4a\"=\"Tab and four spaces\"\n" + " \"Wine4b\"=dword:00112233\n" + "\t \t \t \t \t \t \"Wine4c\"=hex(7):4c,00,69,00,6e,00,65,00,20,00,\\\n" + " 63,00,6f,00,6e,00,\\;comment\n" + "\t\t\t\t63,00,61,00,74,00,\\;comment\n" + " \t65,00,6e,00,61,00,74,00,69,00,6f,00,6e,00,00,00,00,00\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine4a", REG_SZ, "Tab and four spaces", 20, 0); + dword = 0x112233; + todo_wine verify_reg(hkey, "Wine4b", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine4c", REG_MULTI_SZ, "Line concatenation\0", 20, 0); + + test_import_wstr("\xef\xbb\xbf Windows Registry Editor Version 5.00\n\n" + "\t[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + " \"Wine5a\"=\"Leading spaces\"\n" + "\t\t\"Wine5b\"\t\t=\"Leading tabs\"\n" + "\t \"Wine5c\"=\t \"Tabs and spaces\"\n" + " \"Wine5d\" \t = \t \"More whitespace\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine5a", REG_SZ, "Leading spaces", 15, 0); + todo_wine verify_reg(hkey, "Wine5b", REG_SZ, "Leading tabs", 13, 0); + todo_wine verify_reg(hkey, "Wine5c", REG_SZ, "Tabs and spaces", 16, 0); + todo_wine verify_reg(hkey, "Wine5d", REG_SZ, "More whitespace", 16, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\" Wine6a\"=\"Leading spaces\"\n" + "\"\t\tWine6b\"=\"Leading tabs\"\n" + " \" Wine6c \" = \" Spaces everywhere \" \n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, " Wine6a", REG_SZ, "Leading spaces", 15, 0); + todo_wine verify_reg(hkey, "\t\tWine6b", REG_SZ, "Leading tabs", 13, 0); + todo_wine verify_reg(hkey, " Wine6c ", REG_SZ, " Spaces everywhere ", 22, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine7a\"=\" Four spaces in the data\"\n" + "\"Wine7b\"=\"\t\tTwo tabs in the data\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine7a", REG_SZ, " Four spaces in the data", 28, 0); + todo_wine verify_reg(hkey, "Wine7b", REG_SZ, "\t\tTwo tabs in the data", 23, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine8a\"=\"Trailing spaces\" \n" + "\"Wine8b\"=\"Trailing tabs and spaces\"\t \t\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "Wine8a", REG_SZ, "Trailing spaces", 16, 0); + todo_wine verify_reg(hkey, "Wine8b", REG_SZ, "Trailing tabs and spaces", 25, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\"Wine9a\"=dword: 00000008\n" + "\"Wine9b\"=dword:\t\t00000008\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + dword = 0x00000008; + todo_wine verify_reg(hkey, "Wine9a", REG_DWORD, &dword, sizeof(dword), 0); + todo_wine verify_reg(hkey, "Wine9b", REG_DWORD, &dword, sizeof(dword), 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "@ = \"Test Value\"\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "", REG_SZ, "Test Value", 11, 0); + + test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" + "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" + "\t@\t=\tdword:\t00000008\t\n\n", &r); + todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); + todo_wine verify_reg(hkey, "", REG_DWORD, &dword, sizeof(DWORD), 0); + + err = RegCloseKey(hkey); + todo_wine ok(err == ERROR_SUCCESS, "RegCloseKey failed: got %d, expected 0\n", err); + + err = RegDeleteKeyA(HKEY_CURRENT_USER, KEY_BASE); + todo_wine ok(err == ERROR_SUCCESS, "RegDeleteKeyA failed: got %d, expected 0\n", err); +} + START_TEST(reg) { DWORD r; @@ -1446,4 +2683,5 @@ test_query(); test_v_flags(); test_import(); + test_import_with_whitespace(); }
7 years, 6 months
1
0
0
0
[akhaldi] 74879: [WSCRIPT_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:30 2017 New Revision: 74879 URL:
http://svn.reactos.org/svn/reactos?rev=74879&view=rev
Log: [WSCRIPT_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/wscript/run.js Modified: trunk/rostests/winetests/wscript/run.js URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/wscript/run.js?…
============================================================================== --- trunk/rostests/winetests/wscript/run.js [iso-8859-1] (original) +++ trunk/rostests/winetests/wscript/run.js [iso-8859-1] Sun Jun 4 01:50:30 2017 @@ -28,8 +28,8 @@ ok(WScript.Name === "Windows Script Host", "WScript.Name = " + WScript.Name); ok(typeof(WScript.Version) === "string", "typeof(WScript.Version) = " + typeof(WScript.Version)); ok(typeof(WScript.BuildVersion) === "number", "typeof(WScript.BuldVersion) = " + typeof(WScript.BuldVersion)); -ok(WScript.FullName === winetest.wscriptFullName, "WScript.FullName = ", WScript.FullName); -ok(WScript.Path === winetest.wscriptPath, "WScript.Path = ", WScript.Path); +ok(WScript.FullName.toUpperCase() === winetest.wscriptFullName.toUpperCase(), "WScript.FullName = " + WScript.FullName); +ok(WScript.Path.toUpperCase() === winetest.wscriptPath.toUpperCase(), "WScript.Path = " + WScript.Path); ok(WScript.ScriptName === winetest.wscriptScriptName, "WScript.ScriptName = " + WScript.ScriptName); ok(WScript.ScriptFullName === winetest.wscriptScriptFullName, "WScript.ScriptFullName = " + WScript.ScriptFullName); ok(typeof(WScript.Arguments) === "object", "typeof(WScript.Arguments) = " + typeof(WScript.Arguments));
7 years, 6 months
1
0
0
0
[akhaldi] 74878: [WS2_32_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:24 2017 New Revision: 74878 URL:
http://svn.reactos.org/svn/reactos?rev=74878&view=rev
Log: [WS2_32_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/ws2_32/sock.c Modified: trunk/rostests/winetests/ws2_32/sock.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ws2_32/sock.c?r…
============================================================================== --- trunk/rostests/winetests/ws2_32/sock.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ws2_32/sock.c [iso-8859-1] Sun Jun 4 01:50:24 2017 @@ -83,6 +83,10 @@ static int (WINAPI *pWSAEnumNameSpaceProvidersA)(LPDWORD,LPWSANAMESPACE_INFOA); static int (WINAPI *pWSAEnumNameSpaceProvidersW)(LPDWORD,LPWSANAMESPACE_INFOW); static int (WINAPI *pWSAPoll)(WSAPOLLFD *,ULONG,INT); + +/* Function pointers from ntdll */ +static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); +static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); /* Function pointers from iphlpapi */ static DWORD (WINAPI *pGetAdaptersInfo)(PIP_ADAPTER_INFO,PULONG); @@ -1225,6 +1229,7 @@ WORD ver = MAKEWORD (2, 2); WSADATA data; HMODULE hws2_32 = GetModuleHandleA("ws2_32.dll"), hiphlpapi; + HMODULE hntdll = GetModuleHandleA("ntdll.dll"); pfreeaddrinfo = (void *)GetProcAddress(hws2_32, "freeaddrinfo"); pgetaddrinfo = (void *)GetProcAddress(hws2_32, "getaddrinfo"); @@ -1240,6 +1245,9 @@ pWSAEnumNameSpaceProvidersA = (void *)GetProcAddress(hws2_32, "WSAEnumNameSpaceProvidersA"); pWSAEnumNameSpaceProvidersW = (void *)GetProcAddress(hws2_32, "WSAEnumNameSpaceProvidersW"); pWSAPoll = (void *)GetProcAddress(hws2_32, "WSAPoll"); + + pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile"); + pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile"); hiphlpapi = LoadLibraryA("iphlpapi.dll"); if (hiphlpapi) @@ -1568,6 +1576,8 @@ /* test SO_PROTOCOL_INFO structure returned for different protocols */ for (i = 0; i < sizeof(prottest) / sizeof(prottest[0]); i++) { + int k; + s = socket(prottest[i].family, prottest[i].type, prottest[i].proto); if (s == INVALID_SOCKET && prottest[i].family == AF_INET6) continue; @@ -1611,6 +1621,76 @@ prottest[i].type, infoA.iSocketType); ok(infoA.iProtocol == prottest[i].proto, "socket protocol invalid, expected %d received %d\n", prottest[i].proto, infoA.iProtocol); + + /* IP_HDRINCL is supported only on SOCK_RAW but passed to SOCK_DGRAM by Impossible Creatures */ + size = sizeof(i); + k = 1; + SetLastError(0xdeadbeef); + err = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, size); + if (err == -1) /* >= Vista */ + { + todo_wine { + ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); + k = 99; + SetLastError(0xdeadbeef); + err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + ok(err == -1, "Expected -1, got %d\n", err); + ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); + ok(k == 99, "Expected 99, got %d\n", k); + + size = sizeof(k); + k = 0; + SetLastError(0xdeadbeef); + err = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, size); + } + ok(err == -1, "Expected -1, got %d\n", err); + todo_wine { + ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); + k = 99; + SetLastError(0xdeadbeef); + err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + ok(err == -1, "Expected -1, got %d\n", err); + ok(GetLastError() == WSAEINVAL, "Expected 10022, got %d\n", GetLastError()); + ok(k == 99, "Expected 99, got %d\n", k); + } + } + else /* <= 2003 the tests differ between TCP and UDP, UDP silenty accepts */ + { + SetLastError(0xdeadbeef); + k = 99; + err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + if (prottest[i].type == SOCK_DGRAM) + { + ok(err == 0, "Expected 0, got %d\n", err); + ok(k == 1, "Expected 1, got %d\n", k); + } + else + { + /* contratry to what we could expect the function returns error but k is changed */ + ok(err == -1, "Expected -1, got %d\n", err); + ok(GetLastError() == WSAENOPROTOOPT, "Expected 10042, got %d\n", GetLastError()); + ok(k == 0, "Expected 0, got %d\n", k); + } + + k = 0; + err = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, size); + ok(err == 0, "Expected 0, got %d\n", err); + + k = 99; + err = getsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *) &k, &size); + if (prottest[i].type == SOCK_DGRAM) + { + ok(err == 0, "Expected 0, got %d\n", err); + ok(k == 0, "Expected 0, got %d\n", k); + } + else + { + /* contratry to what we could expect the function returns error but k is changed */ + ok(err == -1, "Expected -1, got %d\n", err); + ok(GetLastError() == WSAENOPROTOOPT, "Expected 10042, got %d\n", GetLastError()); + ok(k == 0, "Expected 0, got %d\n", k); + } + } closesocket(s); } @@ -1724,6 +1804,57 @@ closesocket(s); closesocket(s2); + + for (i = 0; i < 2; i++) + { + int family, level; + + if (i) + { + family = AF_INET6; + level = IPPROTO_IPV6; + } + else + { + family = AF_INET; + level = IPPROTO_IP; + } + + s = socket(family, SOCK_DGRAM, 0); + if (s == INVALID_SOCKET && i) + { + skip("IPv6 is not supported\n"); + break; + } + ok(s != INVALID_SOCKET, "socket failed with error %d\n", GetLastError()); + + size = sizeof(value); + value = 0xdead; + err = getsockopt(s, level, IP_DONTFRAGMENT, (char *) &value, &size); + ok(!err, "Expected 0, got %d with error %d\n", err, GetLastError()); + ok(value == 0, "Expected 0, got %d\n", value); + + size = sizeof(value); + value = 1; + err = setsockopt(s, level, IP_DONTFRAGMENT, (char *) &value, size); + ok(!err, "Expected 0, got %d with error %d\n", err, GetLastError()); + + value = 0xdead; + err = getsockopt(s, level, IP_DONTFRAGMENT, (char *) &value, &size); + ok(!err, "Expected 0, got %d with error %d\n", err, GetLastError()); + ok(value == 1, "Expected 1, got %d\n", value); + + size = sizeof(value); + value = 0xdead; + err = setsockopt(s, level, IP_DONTFRAGMENT, (char *) &value, size); + ok(!err, "Expected 0, got %d with error %d\n", err, GetLastError()); + + err = getsockopt(s, level, IP_DONTFRAGMENT, (char *) &value, &size); + ok(!err, "Expected 0, got %d with error %d\n", err, GetLastError()); + ok(value == 1, "Expected 1, got %d\n", value); + + closesocket(s); + } } static void test_so_reuseaddr(void) @@ -1735,7 +1866,7 @@ DWORD err; saddr.sin_family = AF_INET; - saddr.sin_port = htons(9375); + saddr.sin_port = htons(SERVERPORT+1); saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); s1=socket(AF_INET, SOCK_STREAM, 0); @@ -3278,43 +3409,60 @@ (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), "WSAStringToAddressA() failed unexpectedly: %d\n", GLE ); - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - - len = sizeof(sockaddr6); - memset(&sockaddr6, 0, len); - sockaddr6.sin6_family = AF_INET6; - - ret = WSAStringToAddressA( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, - &len ); - GLE = WSAGetLastError(); - ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || - (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); - len = sizeof(sockaddr); ret = WSAStringToAddressA( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); GLE = WSAGetLastError(); ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), "WSAStringToAddressA() should have failed with %d\n", GLE ); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + if (ret == SOCKET_ERROR) + { + win_skip("IPv6 not supported\n"); + return; + } + + GLE = WSAGetLastError(); + ok( ret == 0, "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0, "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 && sockaddr6.sin6_port == 0xffff, + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + + ret = WSAStringToAddressA( address7 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); + GLE = WSAGetLastError(); + ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() should have failed with %d\n", GLE ); + + len = sizeof(sockaddr6); + + ret = WSAStringToAddressA( address8 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); + GLE = WSAGetLastError(); + ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() should have failed with %d\n", GLE ); } static void test_WSAStringToAddressW(void) @@ -3401,15 +3549,27 @@ broken(len == sizeof(SOCKADDR_STORAGE)) /* NT4/2k */, "unexpected length %d\n", len ); + len = sizeof(sockaddr); + + ret = WSAStringToAddressW( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + GLE = WSAGetLastError(); + ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() should have failed with %d\n", GLE ); + len = sizeof(sockaddr6); memset(&sockaddr6, 0, len); sockaddr6.sin6_family = AF_INET6; ret = WSAStringToAddressW( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, &len ); + if (ret == SOCKET_ERROR) + { + win_skip("IPv6 not supported\n"); + return; + } + GLE = WSAGetLastError(); - ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + ok( ret == 0, "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); len = sizeof(sockaddr6); memset(&sockaddr6, 0, len); @@ -3418,8 +3578,7 @@ ret = WSAStringToAddressW( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, &len ); GLE = WSAGetLastError(); - ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), - "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + ok( ret == 0, "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); len = sizeof(sockaddr6); memset(&sockaddr6, 0, len); @@ -3428,13 +3587,19 @@ ret = WSAStringToAddressW( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, &len ); GLE = WSAGetLastError(); - ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || - (ret == SOCKET_ERROR && GLE == WSAEINVAL), + ok( ret == 0 && sockaddr6.sin6_port == 0xffff, "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); - len = sizeof(sockaddr); - - ret = WSAStringToAddressW( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len ); + len = sizeof(sockaddr6); + + ret = WSAStringToAddressW( address7 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); + GLE = WSAGetLastError(); + ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() should have failed with %d\n", GLE ); + + len = sizeof(sockaddr6); + + ret = WSAStringToAddressW( address8 + 1, AF_INET6, NULL, (SOCKADDR*)&sockaddr, &len ); GLE = WSAGetLastError(); ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL), "WSAStringToAddressW() should have failed with %d\n", GLE ); @@ -5757,6 +5922,11 @@ goto end; } + SetLastError(0xdeadbeef); + ret = connect(src, NULL, 0); + ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret); + ok(GetLastError() == WSAEFAULT, "expected 10014, got %d\n", GetLastError()); + ret = connect(src, (struct sockaddr*)&addr, sizeof(addr)); if (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { @@ -6144,11 +6314,10 @@ static void test_ipv6only(void) { - SOCKET v4 = INVALID_SOCKET, - v6 = INVALID_SOCKET; + SOCKET v4 = INVALID_SOCKET, v6; struct sockaddr_in sin4; struct sockaddr_in6 sin6; - int ret; + int ret, enabled, len = sizeof(enabled); memset(&sin4, 0, sizeof(sin4)); sin4.sin_family = AF_INET; @@ -6159,27 +6328,131 @@ sin6.sin6_port = htons(SERVERPORT); v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); - if (v6 == INVALID_SOCKET) { - skip("Could not create IPv6 socket (LastError: %d; %d expected if IPv6 not available).\n", - WSAGetLastError(), WSAEAFNOSUPPORT); + if (v6 == INVALID_SOCKET) + { + skip("Could not create IPv6 socket (LastError: %d)\n", WSAGetLastError()); goto end; } + + enabled = 2; + ret = getsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); + ret = bind(v6, (struct sockaddr*)&sin6, sizeof(sin6)); - if (ret) { - skip("Could not bind IPv6 address (LastError: %d).\n", - WSAGetLastError()); + if (ret) + { + skip("Could not bind IPv6 address (LastError: %d)\n", WSAGetLastError()); goto end; } v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (v4 == INVALID_SOCKET) { - skip("Could not create IPv4 socket (LastError: %d).\n", - WSAGetLastError()); - goto end; - } + ok(v4 != INVALID_SOCKET, "Could not create IPv4 socket (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 0; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(!enabled, "expected 0, got %d\n", enabled); +} + + enabled = 1; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + + /* bind on IPv4 socket should succeed - IPV6_V6ONLY is enabled by default */ ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4)); - ok(!ret, "Could not bind IPv4 address (LastError: %d; %d expected if IPv6 binds to IPv4 as well).\n", - WSAGetLastError(), WSAEADDRINUSE); + ok(!ret, "Could not bind IPv4 address (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 0; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 0; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 1; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError()); + + closesocket(v4); + closesocket(v6); + + /* Test again, this time disabling IPV6_V6ONLY. */ + sin4.sin_port = htons(SERVERPORT+2); + sin6.sin6_port = htons(SERVERPORT+2); + + v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + ok(v6 != INVALID_SOCKET, "Could not create IPv6 socket (LastError: %d; %d expected if IPv6 not available).\n", + WSAGetLastError(), WSAEAFNOSUPPORT); + + enabled = 0; + ret = setsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(!ret, "Could not disable IPV6_V6ONLY (LastError: %d).\n", WSAGetLastError()); + + enabled = 2; + ret = getsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(!enabled, "expected 0, got %d\n", enabled); + + /* + Observaition: + On Windows, bind on both IPv4 and IPv6 with IPV6_V6ONLY disabled succeeds by default. + Application must set SO_EXCLUSIVEADDRUSE on first socket to disallow another successful bind. + In general, a standard application should not use SO_REUSEADDR. + Setting both SO_EXCLUSIVEADDRUSE and SO_REUSEADDR on the same socket is not possible in + either order, the later setsockopt call always fails. + */ + enabled = 1; + ret = setsockopt(v6, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&enabled, len); + ok(!ret, "Could not set SO_EXCLUSIVEADDRUSE on IPv6 socket (LastError: %d)\n", WSAGetLastError()); + + ret = bind(v6, (struct sockaddr*)&sin6, sizeof(sin6)); + ok(!ret, "Could not bind IPv6 address (LastError: %d)\n", WSAGetLastError()); + + enabled = 2; + len = sizeof(enabled); + getsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(!enabled, "IPV6_V6ONLY is enabled after bind\n"); + + v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(v4 != INVALID_SOCKET, "Could not create IPv4 socket (LastError: %d)\n", WSAGetLastError()); + + enabled = 1; + ret = setsockopt(v4, SOL_SOCKET, SO_REUSEADDR, (char*)&enabled, len); + ok(!ret, "Could not set SO_REUSEADDR on IPv4 socket (LastError: %d)\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4)); + ok(ret, "bind succeeded unexpectedly for the IPv4 socket\n"); + ok(WSAGetLastError() == WSAEACCES, "Expected 10013, got %d\n", WSAGetLastError()); end: if (v4 != INVALID_SOCKET) @@ -6430,11 +6703,18 @@ return 0; } +static int completion_called; + +static void WINAPI io_completion(DWORD error, DWORD transferred, WSAOVERLAPPED *overlapped, DWORD flags) +{ + completion_called++; +} + static void test_WSARecv(void) { SOCKET src, dest, server = INVALID_SOCKET; char buf[20]; - WSABUF bufs; + WSABUF bufs[2]; WSAOVERLAPPED ov; DWORD bytesReturned, flags, id; struct linger ling; @@ -6442,7 +6722,7 @@ int iret, len; DWORD dwret; BOOL bret; - HANDLE thread; + HANDLE thread, event = NULL, io_port; tcp_socketpair(&src, &dest); if (src == INVALID_SOCKET || dest == INVALID_SOCKET) @@ -6453,8 +6733,8 @@ memset(&ov, 0, sizeof(ov)); flags = 0; - bufs.len = 2; - bufs.buf = buf; + bufs[0].len = 2; + bufs[0].buf = buf; /* Send 4 bytes and receive in two calls of 2 */ SetLastError(0xdeadbeef); @@ -6463,34 +6743,52 @@ ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); SetLastError(0xdeadbeef); bytesReturned = 0xdeadbeef; - iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL); + iret = WSARecv(dest, bufs, 1, &bytesReturned, &flags, NULL, NULL); ok(!iret, "Expected 0, got %d\n", iret); - ok(bytesReturned, "Expected 2, got %d\n", bytesReturned); + ok(bytesReturned == 2, "Expected 2, got %d\n", bytesReturned); ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); SetLastError(0xdeadbeef); bytesReturned = 0xdeadbeef; - iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL); + iret = WSARecv(dest, bufs, 1, &bytesReturned, &flags, NULL, NULL); ok(!iret, "Expected 0, got %d\n", iret); - ok(bytesReturned, "Expected 2, got %d\n", bytesReturned); + ok(bytesReturned == 2, "Expected 2, got %d\n", bytesReturned); ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); - bufs.len = 4; + bufs[0].len = 4; SetLastError(0xdeadbeef); iret = send(src, "test", 4, 0); ok(iret == 4, "Expected 4, got %d\n", iret); ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); SetLastError(0xdeadbeef); bytesReturned = 0xdeadbeef; - iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL); + iret = WSARecv(dest, bufs, 1, &bytesReturned, &flags, NULL, NULL); ok(!iret, "Expected 0, got %d\n", iret); - ok(bytesReturned, "Expected 4, got %d\n", bytesReturned); + ok(bytesReturned == 4, "Expected 4, got %d\n", bytesReturned); ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); - bufs.len = sizeof(buf); - - ov.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + /* Test 2 buffers */ + bufs[0].len = 4; + bufs[1].len = 5; + bufs[1].buf = buf + 10; + SetLastError(0xdeadbeef); + iret = send(src, "deadbeefs", 9, 0); + ok(iret == 9, "Expected 9, got %d\n", iret); + ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); + SetLastError(0xdeadbeef); + bytesReturned = 0xdeadbeef; + iret = WSARecv(dest, bufs, 2, &bytesReturned, &flags, NULL, NULL); + ok(!iret, "Expected 0, got %d\n", iret); + ok(bytesReturned == 9, "Expected 9, got %d\n", bytesReturned); + bufs[0].buf[4] = '\0'; + bufs[1].buf[5] = '\0'; + ok(!strcmp(bufs[0].buf, "dead"), "buf[0] doesn't match: %s != dead\n", bufs[0].buf); + ok(!strcmp(bufs[1].buf, "beefs"), "buf[1] doesn't match: %s != beefs\n", bufs[1].buf); + ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError()); + + bufs[0].len = sizeof(buf); + ov.hEvent = event = CreateEventA(NULL, FALSE, FALSE, NULL); ok(ov.hEvent != NULL, "could not create event object, errno = %d\n", GetLastError()); - if (!ov.hEvent) + if (!event) goto end; ling.l_onoff = 1; @@ -6498,10 +6796,10 @@ iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); ok(!iret, "Failed to set linger %d\n", GetLastError()); - iret = WSARecv(dest, &bufs, 1, NULL, &flags, &ov, NULL); + iret = WSARecv(dest, bufs, 1, NULL, &flags, &ov, NULL); ok(iret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING, "WSARecv failed - %d error %d\n", iret, GetLastError()); - iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, &ov, NULL); + iret = WSARecv(dest, bufs, 1, &bytesReturned, &flags, &ov, NULL); ok(iret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING, "WSARecv failed - %d error %d\n", iret, GetLastError()); closesocket(src); @@ -6550,6 +6848,34 @@ thread = CreateThread(NULL, 0, recv_thread, &dest, 0, &id); WaitForSingleObject(thread, 3000); CloseHandle(thread); + + memset(&ov, 0, sizeof(ov)); + ov.hEvent = event; + ResetEvent(event); + iret = WSARecv(dest, bufs, 1, NULL, &flags, &ov, io_completion); + ok(iret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING, "WSARecv failed - %d error %d\n", iret, GetLastError()); + send(src, "test message", sizeof("test message"), 0); + + completion_called = 0; + dwret = SleepEx(1000, TRUE); + ok(dwret == WAIT_IO_COMPLETION, "got %u\n", dwret); + ok(completion_called == 1, "completion not called\n"); + + dwret = WaitForSingleObject(event, 1); + ok(dwret == WAIT_TIMEOUT, "got %u\n", dwret); + + io_port = CreateIoCompletionPort( (HANDLE)dest, NULL, 0, 0 ); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + + /* Using completion function on socket associated with completion port is not allowed. */ + memset(&ov, 0, sizeof(ov)); + completion_called = 0; + iret = WSARecv(dest, bufs, 1, NULL, &flags, &ov, io_completion); + todo_wine + ok(iret == SOCKET_ERROR && GetLastError() == WSAEINVAL, "WSARecv failed - %d error %d\n", iret, GetLastError()); + ok(!completion_called, "completion called\n"); + + CloseHandle(io_port); end: if (server != INVALID_SOCKET) @@ -6558,8 +6884,8 @@ closesocket(dest); if (src != INVALID_SOCKET) closesocket(src); - if (ov.hEvent) - WSACloseEvent(ov.hEvent); + if (event) + WSACloseEvent(event); } #define POLL_CLEAR() ix = 0 @@ -6795,6 +7121,11 @@ ADDRINFOW *result, *result2, *p, hint; WCHAR name[256]; DWORD size = sizeof(name)/sizeof(WCHAR); + /* te su
to.winehq.org
written in katakana */ + static const WCHAR idn_domain[] = + {0x30C6,0x30B9,0x30C8,'.','w','i','n','e','h','q','.','o','r','g',0}; + static const WCHAR idn_punycode[] = + {'x','n','-','-','z','c','k','z','a','h','.','w','i','n','e','h','q','.','o','r','g',0}; if (!pGetAddrInfoW || !pFreeAddrInfoW) { @@ -6977,6 +7308,78 @@ ok(0, "test %d: GetAddrInfoW failed with %d (err %d)\n", i, ret, err); } } + + /* Test IDN resolution (Internationalized Domain Names) present since Windows 8 */ + trace("Testing punycode IDN %s\n", wine_dbgstr_w(idn_punycode)); + result = NULL; + ret = pGetAddrInfoW(idn_punycode, NULL, NULL, &result); + ok(!ret, "got %d expected success\n", ret); + ok(result != NULL, "got %p\n", result); + pFreeAddrInfoW(result); + + hint.ai_family = AF_INET; + hint.ai_socktype = 0; + hint.ai_protocol = 0; + hint.ai_flags = 0; + + result = NULL; + ret = pGetAddrInfoW(idn_punycode, NULL, &hint, &result); + ok(!ret, "got %d expected success\n", ret); + ok(result != NULL, "got %p\n", result); + + trace("Testing unicode IDN %s\n", wine_dbgstr_w(idn_domain)); + result2 = NULL; + ret = pGetAddrInfoW(idn_domain, NULL, NULL, &result2); + if (ret == WSAHOST_NOT_FOUND && broken(1)) + { + pFreeAddrInfoW(result); + win_skip("IDN resolution not supported in Win <= 7\n"); + return; + } + + ok(!ret, "got %d expected success\n", ret); + ok(result2 != NULL, "got %p\n", result2); + pFreeAddrInfoW(result2); + + hint.ai_family = AF_INET; + hint.ai_socktype = 0; + hint.ai_protocol = 0; + hint.ai_flags = 0; + + result2 = NULL; + ret = pGetAddrInfoW(idn_domain, NULL, &hint, &result2); + ok(!ret, "got %d expected success\n", ret); + ok(result2 != NULL, "got %p\n", result2); + + /* ensure manually resolved punycode and unicode hosts result in same data */ + compare_addrinfow(result, result2); + + pFreeAddrInfoW(result); + pFreeAddrInfoW(result2); + + hint.ai_family = AF_INET; + hint.ai_socktype = 0; + hint.ai_protocol = 0; + hint.ai_flags = 0; + + result2 = NULL; + ret = pGetAddrInfoW(idn_domain, NULL, &hint, &result2); + ok(!ret, "got %d expected success\n", ret); + ok(result2 != NULL, "got %p\n", result2); + pFreeAddrInfoW(result2); + + /* Disable IDN resolution and test again*/ + hint.ai_family = AF_INET; + hint.ai_socktype = 0; + hint.ai_protocol = 0; + hint.ai_flags = AI_DISABLE_IDN_ENCODING; + + SetLastError(0xdeadbeef); + result2 = NULL; + ret = pGetAddrInfoW(idn_domain, NULL, &hint, &result2); + ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret); + ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError()); + ok(result2 == NULL, "got %p\n", result2); } static void test_getaddrinfo(void) @@ -7068,6 +7471,14 @@ ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError()); ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError()); pfreeaddrinfo(result); + + hint.ai_flags = AI_NUMERICHOST; + result = (void*)0xdeadbeef; + ret = pgetaddrinfo("localhost", "80", &hint, &result); + ok(ret == WSAHOST_NOT_FOUND, "getaddrinfo failed with %d\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected WSAHOST_NOT_FOUND, got %d\n", WSAGetLastError()); + ok(!result, "result = %p\n", result); + hint.ai_flags = 0; /* try to get information from the computer name, result is the same * as if requesting with an empty host name. */ @@ -8063,7 +8474,7 @@ /* Setup a properly connected socket for transfers */ memset(&bindAddress, 0, sizeof(bindAddress)); bindAddress.sin_family = AF_INET; - bindAddress.sin_port = htons(9375); + bindAddress.sin_port = htons(SERVERPORT+1); bindAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); iret = bind(server, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); if (iret != 0) @@ -8104,17 +8515,17 @@ /* Test TransmitFile with only buffer data */ buffers.Head = &header_msg[0]; - buffers.HeadLength = sizeof(header_msg)+1; + buffers.HeadLength = sizeof(header_msg); buffers.Tail = &footer_msg[0]; - buffers.TailLength = sizeof(footer_msg)+1; + buffers.TailLength = sizeof(footer_msg); bret = pTransmitFile(client, NULL, 0, 0, NULL, &buffers, 0); ok(bret, "TransmitFile failed unexpectedly.\n"); iret = recv(dest, buf, sizeof(buf), 0); - ok(iret == sizeof(header_msg)+sizeof(footer_msg)+2, + ok(iret == sizeof(header_msg)+sizeof(footer_msg), "Returned an unexpected buffer from TransmitFile: %d\n", iret ); - ok(memcmp(&buf[0], &header_msg[0], sizeof(header_msg)+1) == 0, + ok(memcmp(&buf[0], &header_msg[0], sizeof(header_msg)) == 0, "TransmitFile header buffer did not match!\n"); - ok(memcmp(&buf[sizeof(header_msg)+1], &footer_msg[0], sizeof(footer_msg)+1) == 0, + ok(memcmp(&buf[sizeof(header_msg)], &footer_msg[0], sizeof(footer_msg)) == 0, "TransmitFile footer buffer did not match!\n"); /* Test TransmitFile with only file data */ @@ -8124,18 +8535,18 @@ /* Test TransmitFile with both file and buffer data */ buffers.Head = &header_msg[0]; - buffers.HeadLength = sizeof(header_msg)+1; + buffers.HeadLength = sizeof(header_msg); buffers.Tail = &footer_msg[0]; - buffers.TailLength = sizeof(footer_msg)+1; + buffers.TailLength = sizeof(footer_msg); SetFilePointer(file, 0, NULL, FILE_BEGIN); bret = pTransmitFile(client, file, 0, 0, NULL, &buffers, 0); ok(bret, "TransmitFile failed unexpectedly.\n"); - iret = recv(dest, buf, sizeof(header_msg)+1, 0); - ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0, + iret = recv(dest, buf, sizeof(header_msg), 0); + ok(memcmp(buf, &header_msg[0], sizeof(header_msg)) == 0, "TransmitFile header buffer did not match!\n"); compare_file(file, dest, 0); - iret = recv(dest, buf, sizeof(footer_msg)+1, 0); - ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0, + iret = recv(dest, buf, sizeof(footer_msg), 0); + ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)) == 0, "TransmitFile footer buffer did not match!\n"); /* Test overlapped TransmitFile */ @@ -8189,9 +8600,9 @@ goto cleanup; } buffers.Head = &header_msg[0]; - buffers.HeadLength = sizeof(header_msg)+1; + buffers.HeadLength = sizeof(header_msg); buffers.Tail = &footer_msg[0]; - buffers.TailLength = sizeof(footer_msg)+1; + buffers.TailLength = sizeof(footer_msg); SetFilePointer(file, 0, NULL, FILE_BEGIN); ov.Offset = 0; bret = pTransmitFile(client, file, 0, 0, &ov, &buffers, 0); @@ -8204,12 +8615,12 @@ ok(total_sent == (file_size + buffers.HeadLength + buffers.TailLength), "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n", total_sent, file_size + buffers.HeadLength + buffers.TailLength); - iret = recv(dest, buf, sizeof(header_msg)+1, 0); - ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0, + iret = recv(dest, buf, sizeof(header_msg), 0); + ok(memcmp(buf, &header_msg[0], sizeof(header_msg)) == 0, "TransmitFile header buffer did not match!\n"); compare_file(file, dest, 0); - iret = recv(dest, buf, sizeof(footer_msg)+1, 0); - ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0, + iret = recv(dest, buf, sizeof(footer_msg), 0); + ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)) == 0, "TransmitFile footer buffer did not match!\n"); /* Test TransmitFile w/ TF_DISCONNECT */ @@ -8394,12 +8805,15 @@ { struct sockaddr_in bindAddress; struct in_addr net_address; - WSAOVERLAPPED overlapped; + WSAOVERLAPPED overlapped, *olp; struct hostent *h; DWORD num_bytes, error, tick; SOCKET sock, sock2, sock3; WSAEVENT event2, event3; + HANDLE io_port; + ULONG_PTR key; int acount; + BOOL bret; int ret; /* Use gethostbyname to find the list of local network interfaces */ @@ -8429,26 +8843,6 @@ ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); ok (!ret, "bind() failed with error %d\n", GetLastError()); set_blocking(sock, FALSE); - - memset(&overlapped, 0, sizeof(overlapped)); - overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); - SetLastError(0xdeadbeef); - ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); - error = GetLastError(); - ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); -todo_wine - ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); - - CloseHandle(overlapped.hEvent); - closesocket(sock); - - sock = socket(AF_INET, 0, IPPROTO_TCP); - ok(sock != INVALID_SOCKET, "socket() failed\n"); - - SetLastError(0xdeadbeef); - ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); - ok (!ret, "bind() failed with error %d\n", GetLastError()); - set_blocking(sock, TRUE); memset(&overlapped, 0, sizeof(overlapped)); overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); @@ -8461,27 +8855,7 @@ CloseHandle(overlapped.hEvent); closesocket(sock); - sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); - ok(sock != INVALID_SOCKET, "socket() failed\n"); - - SetLastError(0xdeadbeef); - ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); - ok (!ret, "bind() failed with error %d\n", GetLastError()); - set_blocking(sock, FALSE); - - memset(&overlapped, 0, sizeof(overlapped)); - overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); - SetLastError(0xdeadbeef); - ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); - error = GetLastError(); - ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); -todo_wine - ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); - - CloseHandle(overlapped.hEvent); - closesocket(sock); - - sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + sock = socket(AF_INET, 0, IPPROTO_TCP); ok(sock != INVALID_SOCKET, "socket() failed\n"); SetLastError(0xdeadbeef); @@ -8500,6 +8874,44 @@ CloseHandle(overlapped.hEvent); closesocket(sock); + sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + ok(sock != INVALID_SOCKET, "socket() failed\n"); + + SetLastError(0xdeadbeef); + ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); + ok (!ret, "bind() failed with error %d\n", GetLastError()); + set_blocking(sock, FALSE); + + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + SetLastError(0xdeadbeef); + ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); + error = GetLastError(); + ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); + ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); + + CloseHandle(overlapped.hEvent); + closesocket(sock); + + sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + ok(sock != INVALID_SOCKET, "socket() failed\n"); + + SetLastError(0xdeadbeef); + ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress)); + ok (!ret, "bind() failed with error %d\n", GetLastError()); + set_blocking(sock, TRUE); + + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + SetLastError(0xdeadbeef); + ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); + error = GetLastError(); + ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); + ok (error == ERROR_IO_PENDING, "expected 0x3e5, got 0x%x\n", error); + + CloseHandle(overlapped.hEvent); + closesocket(sock); + /* When the socket is overlapped non-blocking and the list change is requested without * an overlapped structure the error will be different. */ sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); @@ -8516,7 +8928,32 @@ ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); ok (error == WSAEWOULDBLOCK, "expected 10035, got %d\n", error); + io_port = CreateIoCompletionPort( (HANDLE)sock, NULL, 0, 0 ); + ok (io_port != NULL, "failed to create completion port %u\n", GetLastError()); + + set_blocking(sock, FALSE); + memset(&overlapped, 0, sizeof(overlapped)); + SetLastError(0xdeadbeef); + ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); + error = GetLastError(); + ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %u\n", error); + ok (error == ERROR_IO_PENDING, "expected ERROR_IO_PENDING got %u\n", error); + + olp = (WSAOVERLAPPED *)0xdeadbeef; + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 ); + ok(!bret, "failed to get completion status %u\n", bret); + ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + ok(!olp, "Overlapped structure is at %p\n", olp); + closesocket(sock); + + olp = (WSAOVERLAPPED *)0xdeadbeef; + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 ); + ok(!bret, "failed to get completion status %u\n", bret); + ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %u\n", GetLastError()); + ok(olp == &overlapped, "Overlapped structure is at %p\n", olp); + + CloseHandle(io_port); /* Misuse of the API by using a blocking socket and not using an overlapped structure, * this leads to a hang forever. */ @@ -8798,10 +9235,13 @@ static void test_completion_port(void) { + FILE_IO_COMPLETION_NOTIFICATION_INFORMATION io_info; HANDLE previous_port, io_port; WSAOVERLAPPED ov, *olp; SOCKET src, dest, dup, connector = INVALID_SOCKET; WSAPROTOCOL_INFOA info; + IO_STATUS_BLOCK io; + NTSTATUS status; char buf[1024]; WSABUF bufs; DWORD num_bytes, flags; @@ -8812,6 +9252,7 @@ struct sockaddr_in bindAddress; GUID acceptExGuid = WSAID_ACCEPTEX; LPFN_ACCEPTEX pAcceptEx = NULL; + fd_set fds_recv; memset(buf, 0, sizeof(buf)); previous_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); @@ -8926,6 +9367,167 @@ if (dest != INVALID_SOCKET) closesocket(dest); + + /* Test IOCP response on successful immediate read. */ + tcp_socketpair(&src, &dest); + if (src == INVALID_SOCKET || dest == INVALID_SOCKET) + { + skip("failed to create sockets\n"); + goto end; + } + + bufs.len = sizeof(buf); + bufs.buf = buf; + flags = 0; + SetLastError(0xdeadbeef); + + iret = WSASend(src, &bufs, 1, &num_bytes, 0, &ov, NULL); + ok(!iret, "WSASend failed - %d, last error %u\n", iret, GetLastError()); + ok(num_bytes == sizeof(buf), "Managed to send %d\n", num_bytes); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + flags = 0; + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(!iret, "WSARecv failed - %d, last error %u\n", iret, GetLastError()); + ok(num_bytes == sizeof(buf), "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == TRUE, "failed to get completion status %u\n", bret); + ok(GetLastError() == 0xdeadbeef, "Last error was %d\n", GetLastError()); + ok(key == 125, "Key is %lu\n", key); + ok(num_bytes == sizeof(buf), "Number of bytes transferred is %u\n", num_bytes); + ok(olp == &ov, "Overlapped structure is at %p\n", olp); + + /* Test IOCP response on graceful shutdown. */ + closesocket(src); + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + flags = 0; + memset(&ov, 0, sizeof(ov)); + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(!iret, "WSARecv failed - %d, last error %u\n", iret, GetLastError()); + ok(!num_bytes, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == TRUE, "failed to get completion status %u\n", bret); + ok(GetLastError() == 0xdeadbeef, "Last error was %d\n", GetLastError()); + ok(key == 125, "Key is %lu\n", key); + ok(!num_bytes, "Number of bytes transferred is %u\n", num_bytes); + ok(olp == &ov, "Overlapped structure is at %p\n", olp); + + closesocket(src); + src = INVALID_SOCKET; + closesocket(dest); + dest = INVALID_SOCKET; + + /* Test IOCP response on hard shutdown. This was the condition that triggered + * a crash in an actual app (bug 38980). */ + tcp_socketpair(&src, &dest); + if (src == INVALID_SOCKET || dest == INVALID_SOCKET) + { + skip("failed to create sockets\n"); + goto end; + } + + bufs.len = sizeof(buf); + bufs.buf = buf; + flags = 0; + memset(&ov, 0, sizeof(ov)); + + ling.l_onoff = 1; + ling.l_linger = 0; + iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); + ok(!iret, "Failed to set linger %d\n", GetLastError()); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + closesocket(src); + src = INVALID_SOCKET; + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + SetLastError(0xdeadbeef); + + /* Somehow a hard shutdown doesn't work on my Linux box. It seems SO_LINGER is ignored. */ + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + todo_wine ok(iret == SOCKET_ERROR, "WSARecv failed - %d\n", iret); + todo_wine ok(GetLastError() == WSAECONNRESET, "Last error was %d\n", GetLastError()); + todo_wine ok(num_bytes == 0xdeadbeef, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + todo_wine ok(bret == FALSE, "GetQueuedCompletionStatus returned %u\n", bret ); + todo_wine ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + todo_wine ok(key == 0xdeadbeef, "Key is %lu\n", key); + todo_wine ok(num_bytes == 0xdeadbeef, "Number of bytes transferred is %u\n", num_bytes); + todo_wine ok(!olp, "Overlapped structure is at %p\n", olp); + + closesocket(dest); + + /* Test reading from a non-connected socket, mostly because the above test is marked todo. */ + dest = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(dest != INVALID_SOCKET, "socket() failed\n"); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + num_bytes = 0xdeadbeef; + SetLastError(0xdeadbeef); + memset(&ov, 0, sizeof(ov)); + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(iret == SOCKET_ERROR, "WSARecv failed - %d\n", iret); + ok(GetLastError() == WSAENOTCONN, "Last error was %d\n", GetLastError()); + ok(num_bytes == 0xdeadbeef, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == FALSE, "GetQueuedCompletionStatus returned %u\n", bret ); + ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + ok(key == 0xdeadbeef, "Key is %lu\n", key); + ok(num_bytes == 0xdeadbeef, "Number of bytes transferred is %u\n", num_bytes); + ok(!olp, "Overlapped structure is at %p\n", olp); + + num_bytes = 0xdeadbeef; + closesocket(dest); dest = socket(AF_INET, SOCK_STREAM, 0); if (dest == INVALID_SOCKET) @@ -9251,6 +9853,11 @@ io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 236, 0); ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + io_info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; + status = pNtSetInformationFile((HANDLE)dest, &io, &io_info, sizeof(io_info), FileIoCompletionNotificationInformation); + ok(status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS) /* XP */, + "expected STATUS_SUCCESS, got %08x\n", status); + bret = pAcceptEx(src, dest, buf, sizeof(buf) - 2*(sizeof(struct sockaddr_in) + 16), sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16, &num_bytes, &ov); @@ -9275,6 +9882,13 @@ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes); ok(olp == &ov, "Overlapped structure is at %p\n", olp); ok(olp && (olp->Internal == (ULONG)STATUS_SUCCESS), "Internal status is %lx\n", olp ? olp->Internal : 0); + + io_info.Flags = 0; + status = pNtQueryInformationFile((HANDLE)dest, &io, &io_info, sizeof(io_info), FileIoCompletionNotificationInformation); + ok(status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS) /* XP */, + "expected STATUS_SUCCESS, got %08x\n", status); + if (status == STATUS_SUCCESS) + ok((io_info.Flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) != 0, "got %08x\n", io_info.Flags); SetLastError(0xdeadbeef); key = 0xdeadbeef;
7 years, 6 months
1
0
0
0
[akhaldi] 74877: [PSDK] Add missing AI_DISABLE_IDN_ENCODING.
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:16 2017 New Revision: 74877 URL:
http://svn.reactos.org/svn/reactos?rev=74877&view=rev
Log: [PSDK] Add missing AI_DISABLE_IDN_ENCODING. Modified: trunk/reactos/sdk/include/psdk/ws2def.h Modified: trunk/reactos/sdk/include/psdk/ws2def.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/psdk/ws2def.h?…
============================================================================== --- trunk/reactos/sdk/include/psdk/ws2def.h [iso-8859-1] (original) +++ trunk/reactos/sdk/include/psdk/ws2def.h [iso-8859-1] Sun Jun 4 01:50:16 2017 @@ -306,6 +306,8 @@ #define AI_FQDN 0x00020000 #define AI_FILESERVER 0x00040000 +#define AI_DISABLE_IDN_ENCODING 0x00080000 + #define NS_ALL 0 #define NS_SAP 1
7 years, 6 months
1
0
0
0
[akhaldi] 74876: [INCLUDE/WINE] Update winternl.h. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:07 2017 New Revision: 74876 URL:
http://svn.reactos.org/svn/reactos?rev=74876&view=rev
Log: [INCLUDE/WINE] Update winternl.h. CORE-13362 Modified: trunk/reactos/sdk/include/reactos/wine/winternl.h Modified: trunk/reactos/sdk/include/reactos/wine/winternl.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/reactos/wine/w…
============================================================================== --- trunk/reactos/sdk/include/reactos/wine/winternl.h [iso-8859-1] (original) +++ trunk/reactos/sdk/include/reactos/wine/winternl.h [iso-8859-1] Sun Jun 4 01:50:07 2017 @@ -356,7 +356,7 @@ ULONG GdiClientTID; /* 6f8/086c */ PVOID GdiThreadLocaleInfo; /* 6fc/0870 */ ULONG UserReserved[5]; /* 700/0878 */ - PVOID glDispachTable[280]; /* 714/0890 */ + PVOID glDispatchTable[280]; /* 714/0890 */ PVOID glReserved1[26]; /* b74/1150 */ PVOID glReserved2; /* bdc/1220 */ PVOID glSectionInfo; /* be0/1228 */ @@ -382,7 +382,7 @@ PVOID Spare4; /* f7c/1750 */ PVOID ReservedForOle; /* f80/1758 */ ULONG WaitingOnLoaderLock; /* f84/1760 */ - PVOID Reserved5[3]; /* f88/1768 used for wineserver shared memory */ + PVOID Reserved5[3]; /* f88/1768 used for x86_64 OSX and wineserver shared memory */ PVOID *TlsExpansionSlots; /* f94/1780 */ ULONG ImpersonationLocale; /* f98/1788 */ ULONG IsImpersonating; /* f9c/178c */ @@ -457,7 +457,14 @@ FileNumaNodeInformation, FileStandardLinkInformation, FileRemoteProtocolInformation, + FileRenameInformationBypassAccessCheck, + FileLinkInformationBypassAccessCheck, + FileVolumeNameInformation, + FileIdInformation, + FileIdExtdDirectoryInformation, FileReplaceCompletionInformation, + FileHardLinkFullIdInformation, + FileIdExtdBothDirectoryInformation, FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; @@ -580,6 +587,15 @@ LARGE_INTEGER IndexNumber; } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; +typedef struct _FILE_ID_128 { + UCHAR Identifier[16]; +} FILE_ID_128, *PFILE_ID_128; + +typedef struct _FILE_ID_INFORMATION { + ULONGLONG VolumeSerialNumber; + FILE_ID_128 FileId; +} FILE_ID_INFORMATION, *PFILE_ID_INFORMATION; + typedef struct _FILE_EA_INFORMATION { ULONG EaSize; } FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; @@ -746,6 +762,14 @@ FILE_NAME_INFORMATION NameInformation; } FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; +typedef struct _FILE_IO_COMPLETION_NOTIFICATION_INFORMATION { + ULONG Flags; +} FILE_IO_COMPLETION_NOTIFICATION_INFORMATION, *PFILE_IO_COMPLETION_NOTIFICATION_INFORMATION; + +#define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1 +#define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2 +#define FILE_SKIP_SET_USER_EVENT_ON_FAST_IO 0x4 + typedef enum _FSINFOCLASS { FileFsVolumeInformation = 1, FileFsLabelInformation, @@ -782,7 +806,7 @@ ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, - ObjectAllInformation, + ObjectTypesInformation, ObjectDataInformation } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; @@ -821,6 +845,22 @@ ProcessDebugFlags = 31, ProcessHandleTracing = 32, ProcessExecuteFlags = 34, + ProcessTlsInformation = 35, + ProcessCookie = 36, + ProcessImageInformation = 37, + ProcessCycleTime = 38, + ProcessPagePriority = 39, + ProcessInstrumentationCallback = 40, + ProcessThreadStackAllocation = 41, + ProcessWorkingSetWatchEx = 42, + ProcessImageFileNameWin32 = 43, + ProcessImageFileMapping = 44, + ProcessAffinityUpdateMode = 45, + ProcessMemoryAllocationMode = 46, + ProcessGroupInformation = 47, + ProcessTokenVirtualizationEnabled = 48, + ProcessConsoleHostProcess = 49, + ProcessWindowInformation = 50, MaxProcessInfoClass } PROCESSINFOCLASS, PROCESS_INFORMATION_CLASS; @@ -1184,8 +1224,34 @@ typedef struct __OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; - ULONG Reserved [22]; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + UCHAR TypeIndex; + CHAR Reserved; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +typedef struct _OBJECT_TYPES_INFORMATION +{ + ULONG NumberOfTypes; +} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; typedef struct _PROCESS_BASIC_INFORMATION { #ifdef __WINESRC__ @@ -1418,6 +1484,27 @@ SYSTEM_HANDLE_ENTRY Handle[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; +/* System Information Class 0x40 */ + +typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX +{ + PVOID Object; + ULONG_PTR UniqueProcessId; + ULONG_PTR HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; + +typedef struct _SYSTEM_HANDLE_INFORMATION_EX +{ + ULONG_PTR Count; + ULONG_PTR Reserved; + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle[1]; +} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; + /* System Information Class 0x15 */ typedef struct _SYSTEM_CACHE_INFORMATION { @@ -2104,10 +2191,19 @@ ULONG Flags; SHORT LoadCount; SHORT TlsIndex; - HANDLE SectionHandle; - ULONG CheckSum; + LIST_ENTRY HashLinks; ULONG TimeDateStamp; HANDLE ActivationContext; + PVOID PatchInformation; + LIST_ENTRY ForwarderLinks; + LIST_ENTRY ServiceTagLinks; + LIST_ENTRY StaticLinks; + PVOID ContextInformation; + ULONG_PTR OriginalBase; + LARGE_INTEGER LoadTime; + + /* Not part of Win7 but used by Wine */ + HANDLE SectionHandle; } LDR_MODULE, *PLDR_MODULE; /* those defines are (some of the) regular LDR_MODULE.Flags values */ @@ -2147,6 +2243,13 @@ ULONG ModulesCount; SYSTEM_MODULE Modules[1]; /* FIXME: should be Modules[0] */ } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 +#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 +#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 +#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010 +#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020 +#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080 /*********************************************************************** * Function declarations @@ -2190,7 +2293,7 @@ NTSYSAPI NTSTATUS WINAPI NtAlertResumeThread(HANDLE,PULONG); NTSYSAPI NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle); NTSYSAPI NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID lpLuid); -NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG); +NTSYSAPI NTSTATUS WINAPI NtAllocateUuids(PULARGE_INTEGER,PULONG,PULONG,PUCHAR); NTSYSAPI NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,ULONG,SIZE_T*,ULONG,ULONG); NTSYSAPI NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID,PVOID); NTSYSAPI NTSTATUS WINAPI NtAssignProcessToJobObject(HANDLE,HANDLE); @@ -2436,6 +2539,7 @@ NTSYSAPI NTSTATUS WINAPI RtlAddAuditAccessAce(PACL,DWORD,DWORD,PSID,BOOL,BOOL); NTSYSAPI NTSTATUS WINAPI RtlAddAuditAccessAceEx(PACL,DWORD,DWORD,DWORD,PSID,BOOL,BOOL); NTSYSAPI NTSTATUS WINAPI RtlAddAuditAccessObjectAce(PACL,DWORD,DWORD,DWORD,GUID*,GUID*,PSID,BOOL,BOOL); +NTSYSAPI NTSTATUS WINAPI RtlAddMandatoryAce(PACL,DWORD,DWORD,DWORD,DWORD,PSID); NTSYSAPI void WINAPI RtlAddRefActivationContext(HANDLE); NTSYSAPI PVOID WINAPI RtlAddVectoredExceptionHandler(ULONG,PVECTORED_EXCEPTION_HANDLER); NTSYSAPI NTSTATUS WINAPI RtlAdjustPrivilege(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
7 years, 6 months
1
0
0
0
[akhaldi] 74875: [WINSPOOL_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:50:00 2017 New Revision: 74875 URL:
http://svn.reactos.org/svn/reactos?rev=74875&view=rev
Log: [WINSPOOL_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/winspool/info.c Modified: trunk/rostests/winetests/winspool/info.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winspool/info.c…
============================================================================== --- trunk/rostests/winetests/winspool/info.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winspool/info.c [iso-8859-1] Sun Jun 4 01:50:00 2017 @@ -434,7 +434,9 @@ mi2a.pDLLName = entry->dllname; SetLastError(MAGIC_DEAD); res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a); - ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError()); + /* Some apps depend on the result of GetLastError() also on success of AddMonitor */ + ok(res && (GetLastError() == ERROR_SUCCESS), + "returned %d with %d (expected '!= 0' with ERROR_SUCCESS)\n", res, GetLastError()); /* add a monitor twice */ SetLastError(MAGIC_DEAD); @@ -667,6 +669,50 @@ SetLastError(0xdeadbeef); res = ConfigurePortA(NULL, 0, portname_file); trace("'%s' returned %d with %d\n", portname_file, res, GetLastError()); + } +} + +/* ########################### */ + +static void test_ClosePrinter(void) +{ + HANDLE printer = 0; + BOOL res; + + /* NULL is handled */ + SetLastError(0xdeadbeef); + res = ClosePrinter(NULL); + ok(!res && (GetLastError() == ERROR_INVALID_HANDLE), + "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n", + res, GetLastError()); + + /* A random value as HANDLE is handled */ + SetLastError(0xdeadbeef); + res = ClosePrinter( (void *) -1); + if (is_spooler_deactivated(res, GetLastError())) return; + ok(!res && (GetLastError() == ERROR_INVALID_HANDLE), + "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n", + res, GetLastError()); + + + /* Normal use (The Spooler service is needed) */ + SetLastError(0xdeadbeef); + res = OpenPrinterA(default_printer, &printer, NULL); + if (is_spooler_deactivated(res, GetLastError())) return; + if (res) + { + SetLastError(0xdeadbeef); + res = ClosePrinter(printer); + ok(res, "got %d with %d (expected TRUE)\n", res, GetLastError()); + + + /* double free is handled */ + SetLastError(0xdeadbeef); + res = ClosePrinter(printer); + ok(!res && (GetLastError() == ERROR_INVALID_HANDLE), + "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n", + res, GetLastError()); + } } @@ -3023,6 +3069,7 @@ test_AddPort(); test_AddPortEx(); test_ConfigurePort(); + test_ClosePrinter(); test_DeleteMonitor(); test_DeletePort(); test_DeviceCapabilities(); @@ -3047,7 +3094,9 @@ test_GetDefaultPrinter(); test_GetPrinterDriverDirectory(); test_GetPrintProcessorDirectory(); + test_IsValidDevmodeW(); test_OpenPrinter(); + test_OpenPrinter_defaults(); test_GetPrinter(); test_GetPrinterData(); test_GetPrinterDataEx(); @@ -3055,8 +3104,6 @@ test_SetDefaultPrinter(); test_XcvDataW_MonitorUI(); test_XcvDataW_PortIsValid(); - test_IsValidDevmodeW(); - test_OpenPrinter_defaults(); /* Cleanup our temporary file */ DeleteFileA(tempfileA);
7 years, 6 months
1
0
0
0
[akhaldi] 74874: [WINMM_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:49:55 2017 New Revision: 74874 URL:
http://svn.reactos.org/svn/reactos?rev=74874&view=rev
Log: [WINMM_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/winmm/CMakeLists.txt trunk/rostests/winetests/winmm/joystick.c trunk/rostests/winetests/winmm/mci.c trunk/rostests/winetests/winmm/midi.c trunk/rostests/winetests/winmm/wave.c Modified: trunk/rostests/winetests/winmm/CMakeLists.txt URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/CMakeList…
============================================================================== --- trunk/rostests/winetests/winmm/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/CMakeLists.txt [iso-8859-1] Sun Jun 4 01:49:55 2017 @@ -14,7 +14,7 @@ add_executable(winmm_winetest ${SOURCE}) target_link_libraries(winmm_winetest dxguid) set_module_type(winmm_winetest win32cui) -add_importlibs(winmm_winetest winmm user32 advapi32 msvcrt kernel32) +add_importlibs(winmm_winetest winmm user32 advapi32 ole32 msvcrt kernel32) add_rostests_file(TARGET winmm_winetest) if(NOT MSVC) Modified: trunk/rostests/winetests/winmm/joystick.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/joystick.…
============================================================================== --- trunk/rostests/winetests/winmm/joystick.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/joystick.c [iso-8859-1] Sun Jun 4 01:49:55 2017 @@ -82,7 +82,9 @@ ret = joyGetDevCapsA(JOYSTICKID1 + i, &jc, sizeof(jc)); if (ret == JOYERR_NOERROR) { - joyid = JOYSTICKID1 + i; + if (joyid == -1) /* Cache the first found joystick to run advanced tests below */ + joyid = JOYSTICKID1 + i; + trace("Joystick[%d] - name: '%s', axes: %d, buttons: %d, period range: %d - %d\n", JOYSTICKID1 + i, jc.szPname, jc.wNumAxes, jc.wNumButtons, jc.wPeriodMin, jc.wPeriodMax); ret = joyGetDevCapsW(JOYSTICKID1 + i, &jcw, sizeof(jcw)); @@ -93,7 +95,6 @@ ok(jc.wNumButtons == jcw.wNumButtons, "Expected %d == %d\n", jc.wNumButtons, jcw.wNumButtons); } else win98++; - break; } else { Modified: trunk/rostests/winetests/winmm/mci.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/mci.c?rev…
============================================================================== --- trunk/rostests/winetests/winmm/mci.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/mci.c [iso-8859-1] Sun Jun 4 01:49:55 2017 @@ -198,7 +198,7 @@ buf[0]='z'; err = mciSendStringA("", buf, sizeof(buf), NULL); - todo_wine ok(err==MCIERR_MISSING_COMMAND_STRING,"empty string: %s\n", dbg_mcierr(err)); + ok(err==MCIERR_MISSING_COMMAND_STRING,"empty string: %s\n", dbg_mcierr(err)); ok(!buf[0], "error buffer %s\n", buf); buf[0]='d'; @@ -364,6 +364,10 @@ err = mciSendStringA("capability x device type", buf, sizeof(buf), hwnd); ok(!err,"capability device type: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "waveaudio"), "capability device type is %s\n", buf); + + err = mciSendStringA("info a version", buf, sizeof(buf), hwnd); + ok(!err,"info version: %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf, "1.1"), "info version is %s\n", buf); err = mciSendCommandA(wDeviceID, MCI_CLOSE, 0, 0); ok(!err,"mciCommand close returned %s\n", dbg_mcierr(err)); @@ -667,10 +671,6 @@ err = mciSendStringA("status x samplespersec", buf, sizeof(buf), NULL); ok(!err,"mci status samplespersec returned %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf,"11025"), "mci status samplespersec expected 11025, got: %s\n", buf); - - /* MCI seems to solely support PCM, no need for ACM conversion. */ - err = mciSendStringA("set x format tag 2", NULL, 0, NULL); - ok(err==MCIERR_OUTOFRANGE,"mci set format tag 2 returned %s\n", dbg_mcierr(err)); /* MCI appears to scan the available devices for support of this format, * returning MCIERR_OUTOFRANGE on machines with no sound. @@ -1116,6 +1116,8 @@ trace("position after resume: %sms\n",buf); test_notification(hwnd,"play (aborted by pause/resume/pause)",0); + /* A small Sleep() here prevents the notification test failing with MCI_NOTIFY_SUCCESSFUL */ + Sleep(10); err = mciSendStringA("close mysound wait", NULL, 0, NULL); ok(!err,"mci close wait returned %s\n", dbg_mcierr(err)); test_notification(hwnd,"play (aborted by close)",MCI_NOTIFY_ABORTED); Modified: trunk/rostests/winetests/winmm/midi.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/midi.c?re…
============================================================================== --- trunk/rostests/winetests/winmm/midi.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/midi.c [iso-8859-1] Sun Jun 4 01:49:55 2017 @@ -516,8 +516,8 @@ rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1); ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); - rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)); - ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc)); + rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); + ok(!rc, "midiOutPrepare size rc=%s\n", mmsys_error(rc)); ok(mhdr.dwFlags & MHDR_PREPARED, "MHDR.dwFlags when prepared %x\n", mhdr.dwFlags); /* The device is still in paused mode and should queue the message. */ @@ -559,9 +559,9 @@ /* Native fills dwOffset regardless of the cbMidiHdr size argument to midiStreamOut */ ok(1234567890!=mhdr.dwOffset, "play left MIDIHDR.dwOffset at %u\n", mhdr.dwOffset); - rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)); + rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); - rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)); + rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutUnprepare #2 rc=%s\n", mmsys_error(rc)); trace("MIDIHDR stream flags=%x when finished\n", mhdr.dwFlags); @@ -586,9 +586,9 @@ mhdr.dwFlags |= MHDR_ISSTRM; /* Preset flags (e.g. MHDR_ISSTRM) do not disturb. */ - rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)); + rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutPrepare used flags %x rc=%s\n", mhdr.dwFlags, mmsys_error(rc)); - rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)); + rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutUnprepare used flags %x rc=%s\n", mhdr.dwFlags, mmsys_error(rc)); rc = midiStreamRestart(hm); @@ -837,10 +837,15 @@ START_TEST(midi) { HWND hwnd = 0; + + CoInitialize(NULL); /* Needed for Win 10 */ + if (1) /* select 1 for CALLBACK_WINDOW or 0 for CALLBACK_FUNCTION */ hwnd = CreateWindowExA(0, "static", "winmm midi test", WS_POPUP, 0,0,100,100, 0, 0, 0, NULL); test_midi_infns(hwnd); test_midi_outfns(hwnd); if (hwnd) DestroyWindow(hwnd); -} + + CoUninitialize(); +} Modified: trunk/rostests/winetests/winmm/wave.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/wave.c?re…
============================================================================== --- trunk/rostests/winetests/winmm/wave.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/wave.c [iso-8859-1] Sun Jun 4 01:49:55 2017 @@ -1600,6 +1600,7 @@ rc = waveOutClose(wout); ok(rc == MMSYSERR_NOERROR, "waveOutClose failed: %s\n", wave_out_error(rc)); + HeapFree(GetProcessHeap(), 0, hdr[0].lpData); CloseHandle(hevent); } @@ -1659,6 +1660,12 @@ { BOOL br; char test_file[MAX_PATH], temp[MAX_PATH], *exts; + void *psound_ordinal, *psound_name; + HMODULE dll = GetModuleHandleA("winmm.dll"); + + psound_name = GetProcAddress(dll, "PlaySound"); + psound_ordinal = GetProcAddress(dll, (LPCSTR) 2); + ok(psound_name == psound_ordinal, "Expected ordinal 2 to be PlaySound function\n"); if(waveOutGetNumDevs() == 0) { skip("No output devices available\n");
7 years, 6 months
1
0
0
0
[akhaldi] 74873: [XMLLITE_WINETEST] Sync with Wine Staging 2.9. CORE-13362
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:49:50 2017 New Revision: 74873 URL:
http://svn.reactos.org/svn/reactos?rev=74873&view=rev
Log: [XMLLITE_WINETEST] Sync with Wine Staging 2.9. CORE-13362 Modified: trunk/rostests/winetests/xmllite/reader.c trunk/rostests/winetests/xmllite/writer.c Modified: trunk/rostests/winetests/xmllite/reader.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/xmllite/reader.…
============================================================================== --- trunk/rostests/winetests/xmllite/reader.c [iso-8859-1] (original) +++ trunk/rostests/winetests/xmllite/reader.c [iso-8859-1] Sun Jun 4 01:49:50 2017 @@ -1,7 +1,7 @@ /* * IXmlReader tests * - * Copyright 2010, 2012-2013 Nikolay Sivov + * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,10 +51,18 @@ HeapFree(GetProcessHeap(), 0, str); } +static int strcmp_wa(const WCHAR *str1, const char *stra) +{ + WCHAR *str2 = a2w(stra); + int r = lstrcmpW(str1, str2); + free_str(str2); + return r; +} + static const char xmldecl_full[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"; static const char xmldecl_short[] = "<?xml version=\"1.0\"?><RegistrationInfo/>"; -static IStream *create_stream_on_data(const char *data, int size) +static IStream *create_stream_on_data(const void *data, unsigned int size) { IStream *stream = NULL; HGLOBAL hglobal; @@ -75,29 +83,28 @@ return stream; } -static void ok_pos_(IXmlReader *reader, int line, int pos, int line_broken, - int pos_broken, BOOL todo, int _line_) -{ - UINT l, p; - HRESULT hr; +static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken, + UINT pos_broken, int _line_) +{ + UINT l = ~0u, p = ~0u; BOOL broken_state; - hr = IXmlReader_GetLineNumber(reader, &l); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); - hr = IXmlReader_GetLinePosition(reader, &p); - ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr); - - if (line_broken == -1 && pos_broken == -1) + IXmlReader_GetLineNumber(reader, &l); + IXmlReader_GetLinePosition(reader, &p); + + if (line_broken == ~0u && pos_broken == ~0u) broken_state = FALSE; else - broken_state = broken((line_broken == -1 ? line : line_broken) == l && - (pos_broken == -1 ? pos : pos_broken) == p); - - todo_wine_if (todo) - ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, - "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); -} -#define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__) + broken_state = broken((line_broken == ~0u ? line : line_broken) == l && + (pos_broken == ~0u ? pos : pos_broken) == p); + + ok_(__FILE__, _line_)((l == line && pos == p) || broken_state, + "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p); +} +#define TEST_READER_POSITION(reader, line, pos) \ + test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__) +#define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \ + test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__) typedef struct input_iids_t { IID iids[10]; @@ -218,28 +225,153 @@ } } -static void test_read_state_(IXmlReader *reader, XmlReadState expected, - XmlReadState exp_broken, BOOL todo, int line) -{ +#define set_input_string(a,b) _set_input_string(__LINE__,a,b); +static void _set_input_string(unsigned line, IXmlReader *reader, const char *xml) +{ + IStream *stream; + HRESULT hr; + + stream = create_stream_on_data(xml, strlen(xml)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr); + + IStream_Release(stream); +} + +#define read_node(a,b) _read_node(__LINE__,a,b) +static void _read_node(unsigned line, IXmlReader *reader, XmlNodeType expected_type) +{ + XmlNodeType type; + HRESULT hr; + + hr = IXmlReader_Read(reader, &type); + if (expected_type == XmlNodeType_None) + ok_(__FILE__,line)(hr == S_FALSE, "Read returned %08x, expected S_FALSE\n", hr); + else + ok_(__FILE__,line)(hr == S_OK, "Read returned %08x\n", hr); + ok_(__FILE__,line)(type == expected_type, "read type %d, expected %d\n", type, expected_type); +} + +#define next_attribute(a) _next_attribute(__LINE__,a) +static void _next_attribute(unsigned line, IXmlReader *reader) +{ + HRESULT hr; + hr = IXmlReader_MoveToNextAttribute(reader); + ok_(__FILE__,line)(hr == S_OK, "MoveToNextAttribute returned %08x\n", hr); +} + +#define move_to_element(a) _move_to_element(__LINE__,a) +static void _move_to_element(unsigned line, IXmlReader *reader) +{ + HRESULT hr; + hr = IXmlReader_MoveToElement(reader); + ok_(__FILE__,line)(hr == S_OK, "MoveToElement failed: %08x\n", hr); +} + +static void test_read_state(IXmlReader *reader, XmlReadState expected, + XmlReadState exp_broken, int line) +{ + BOOL broken_state; LONG_PTR state; - HRESULT hr; - BOOL broken_state; - - state = -1; /* invalid value */ - hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); - ok_(__FILE__, line)(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + state = -1; /* invalid state value */ + IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); if (exp_broken == -1) broken_state = FALSE; else broken_state = broken(exp_broken == state); - todo_wine_if (todo) - ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", - state_to_str(expected), state_to_str(state)); -} - -#define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__) + ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n", + state_to_str(expected), state_to_str(state)); +} + +#define TEST_READER_STATE(reader, state) test_read_state(reader, state, -1, __LINE__) +#define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__) + +#define reader_value(a,b) _reader_value(__LINE__,a,b) +static const WCHAR *_reader_value(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetValue(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetValue returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "value = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_name(a,b) _reader_name(__LINE__,a,b) +static const WCHAR *_reader_name(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetLocalName(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetLocalName returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_prefix(a,b) _reader_prefix(__LINE__,a,b) +static const WCHAR *_reader_prefix(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetPrefix(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetPrefix returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "prefix = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_namespace(a,b) _reader_namespace(__LINE__,a,b) +static const WCHAR *_reader_namespace(unsigned line, IXmlReader *reader, const char *expect) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetNamespaceUri(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetNamespaceUri returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "namespace = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define reader_qname(a,b) _reader_qname(a,b,__LINE__) +static const WCHAR *_reader_qname(IXmlReader *reader, const char *expect, unsigned line) +{ + const WCHAR *str = (void*)0xdeadbeef; + ULONG len = 0xdeadbeef; + HRESULT hr; + + hr = IXmlReader_GetQualifiedName(reader, &str, &len); + ok_(__FILE__,line)(hr == S_OK, "GetQualifiedName returned %08x\n", hr); + ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len); + ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str)); + return str; +} + +#define read_value_char(a,b) _read_value_char(a,b,__LINE__) +static void _read_value_char(IXmlReader *reader, WCHAR expected_char, unsigned line) +{ + WCHAR c = 0xffff; + UINT count = 0; + HRESULT hr; + + hr = IXmlReader_ReadValueChunk(reader, &c, 1, &count); + ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr); + ok_(__FILE__,line)(count == 1, "got %u\n", c); + ok_(__FILE__,line)(c == expected_char, "got %x\n", c); +} typedef struct _testinput { @@ -409,11 +541,11 @@ static void test_reader_create(void) { IXmlResolver *resolver; - HRESULT hr; + IUnknown *input, *unk; IXmlReader *reader; - IUnknown *input; DtdProcessing dtd; XmlNodeType nodetype; + HRESULT hr; /* crashes native */ if (0) @@ -422,10 +554,25 @@ CreateXmlReader(NULL, (void**)&reader, NULL); } + hr = CreateXmlReader(&IID_IStream, (void **)&unk, NULL); + ok(hr == E_NOINTERFACE, "got %08x\n", hr); + + hr = CreateXmlReader(&IID_IUnknown, (void **)&unk, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + hr = IUnknown_QueryInterface(unk, &IID_IXmlReader, (void **)&reader); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(unk == (IUnknown *)reader, "unexpected interface\n"); + IXmlReader_Release(reader); + IUnknown_Release(unk); + + hr = CreateXmlReader(&IID_IUnknown, (void **)&reader, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + IXmlReader_Release(reader); + hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -475,7 +622,7 @@ hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); /* test input interface selection sequence */ hr = testinput_createinstance((void**)&input); @@ -538,7 +685,7 @@ hr = IXmlReader_SetInput(reader, reader_input); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Initial); nodetype = XmlNodeType_Element; hr = IXmlReader_GetNodeType(reader, &nodetype); @@ -558,7 +705,7 @@ hr = IXmlReader_SetInput(reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); IXmlReader_Release(reader); @@ -616,7 +763,7 @@ ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr); ok_iids(&input_iids, setinput_readerinput, NULL, FALSE); - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); ref = IUnknown_AddRef(input); ok(ref == 3, "Expected 3, got %d\n", ref); @@ -652,8 +799,9 @@ static void test_reader_state(void) { + XmlNodeType nodetype; IXmlReader *reader; - XmlNodeType nodetype; + IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); @@ -664,20 +812,59 @@ ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); /* attempt to read on closed reader */ - test_read_state(reader, XmlReadState_Closed, -1, FALSE); + TEST_READER_STATE(reader, XmlReadState_Closed); + if (0) { - /* newer versions crash here, probably cause no input was set */ + /* newer versions crash here, probably because no input was set */ hr = IXmlReader_Read(reader, &nodetype); ok(hr == S_FALSE, "got %08x\n", hr); } - IXmlReader_Release(reader); -} + + stream = create_stream_on_data("xml", sizeof("xml")); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Initial); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + +todo_wine + TEST_READER_STATE(reader, XmlReadState_Error); + + nodetype = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &nodetype); +todo_wine + ok(FAILED(hr), "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype); + + IStream_Release(stream); + IXmlReader_Release(reader); +} + +static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line) +{ + BOOL condition; + UINT d = ~0u; + + IXmlReader_GetDepth(reader, &d); + + condition = d == depth; + if (brk != ~0u) + condition |= broken(d == brk); + ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth); +} + +#define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__) +#define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__) static void test_read_xmldeclaration(void) { - static const WCHAR xmlW[] = {'x','m','l',0}; - static const WCHAR RegistrationInfoW[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0}; static const struct { WCHAR name[12]; @@ -699,13 +886,6 @@ hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - /* position methods with Null args */ - hr = IXmlReader_GetLineNumber(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - - hr = IXmlReader_GetLinePosition(reader, NULL); - ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); - stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full)); hr = IXmlReader_SetInput(reader, (IUnknown*)stream); @@ -725,37 +905,33 @@ hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_FALSE, "got %08x\n", hr); - ok_pos(reader, 0, 0, -1, -1, FALSE); - - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_XmlDeclaration, - "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type)); + TEST_READER_POSITION(reader, 0, 0); + + read_node(reader, XmlNodeType_XmlDeclaration); + /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */ - ok_pos(reader, 1, 3, -1, 55, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, FALSE); - - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "got %08x\n", hr); - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); + + TEST_DEPTH(reader, 0); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + reader_value(reader, ""); /* check attributes */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); + next_attribute(reader); + + TEST_DEPTH(reader, 1); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); /* try to move from last attribute */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); + next_attribute(reader); + next_attribute(reader); hr = IXmlReader_MoveToNextAttribute(reader); ok(hr == S_FALSE, "got %08x\n", hr); @@ -766,7 +942,7 @@ hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "got %08x\n", hr); - ok_pos(reader, 1, 7, -1, 55, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 55); hr = IXmlReader_GetAttributeCount(reader, NULL); ok(hr == E_INVALIDARG, "got %08x\n", hr); @@ -793,12 +969,10 @@ ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr); } - hr = IXmlReader_GetDepth(reader, &count); - ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(count == 1, "Expected 1, got %d\n", count); - - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got %08x\n", hr); + TEST_DEPTH(reader, 1); + + move_to_element(reader); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 55); type = XmlNodeType_None; hr = IXmlReader_GetNodeType(reader, &type); @@ -821,12 +995,9 @@ hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 3, 1, 21, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + read_node(reader, XmlNodeType_XmlDeclaration); + TEST_READER_POSITION2(reader, 1, 3, ~0u, 21); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -835,35 +1006,27 @@ ret = IXmlReader_IsEmptyElement(reader); ok(!ret, "element should not be empty\n"); - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); - - hr = IXmlReader_GetLocalName(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine - ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val)); + reader_value(reader, ""); + reader_name(reader, "xml"); + + reader_qname(reader, "xml"); /* check attributes */ - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); + next_attribute(reader); type = -1; hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); - ok_pos(reader, 1, 7, 1, 21, TRUE); + TEST_READER_POSITION2(reader, 1, 7, ~0u, 21); /* try to move from last attribute */ hr = IXmlReader_MoveToNextAttribute(reader); ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr); - type = -1; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 23, 1, 40, TRUE); - test_read_state(reader, XmlReadState_Interactive, -1, TRUE); + read_node(reader, XmlNodeType_Element); + TEST_READER_POSITION2(reader, 1, 23, ~0u, 40); + TEST_READER_STATE(reader, XmlReadState_Interactive); hr = IXmlReader_GetAttributeCount(reader, &count); ok(hr == S_OK, "expected S_OK, got %08x\n", hr); @@ -872,23 +1035,17 @@ ret = IXmlReader_IsEmptyElement(reader); ok(ret, "element should be empty\n"); - hr = IXmlReader_GetValue(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); -todo_wine - ok(*val == 0, "got %s\n", wine_dbgstr_w(val)); - - hr = IXmlReader_GetLocalName(reader, &val, NULL); - ok(hr == S_OK, "expected S_OK, got %08x\n", hr); - ok(!lstrcmpW(val, RegistrationInfoW), "got %s\n", wine_dbgstr_w(val)); + reader_value(reader, ""); + reader_name(reader, "RegistrationInfo"); type = -1; hr = IXmlReader_Read(reader, &type); todo_wine ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr); + ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type)); + TEST_READER_POSITION(reader, 1, 41); todo_wine - ok(type == XmlNodeType_None, "expected None, got %s\n", type_to_str(type)); - ok_pos(reader, 1, 41, -1, -1, TRUE); - test_read_state(reader, XmlReadState_Error, -1, TRUE); + TEST_READER_STATE(reader, XmlReadState_Error); IStream_Release(stream); IXmlReader_Release(reader); @@ -913,21 +1070,43 @@ static void test_read_comment(void) { + static const char *teststr = "<a>text<!-- comment --></a>"; struct test_entry *test = comment_tests; + static const XmlNodeType types[] = + { + XmlNodeType_Element, + XmlNodeType_Text, + XmlNodeType_Comment, + XmlNodeType_EndElement, + }; + unsigned int i = 0; IXmlReader *reader; + XmlNodeType type; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); + set_input_string(reader, teststr); + + while (IXmlReader_Read(reader, &type) == S_OK) + { + const WCHAR *value; + + ok(type == types[i], "%d: unexpected node type %d\n", i, type); + + if (type == XmlNodeType_Text || type == XmlNodeType_Comment) + { + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(*value != 0, "Expected node value\n"); + } + i++; + } + while (test->xml) { - XmlNodeType type; - IStream *stream; - - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -938,41 +1117,27 @@ if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; - UINT len; ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml); - len = 1; + reader_name(reader, ""); + str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); - - len = 1; + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + reader_qname(reader, ""); + str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } - IStream_Release(stream); test++; } @@ -1005,11 +1170,8 @@ while (test->xml) { XmlNodeType type; - IStream *stream; - - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -1025,14 +1187,7 @@ ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml); - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_name(reader, test->name); len = 0; str = NULL; @@ -1044,17 +1199,9 @@ free_str(str_exp); /* value */ - len = !strlen(test->value); - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } - IStream_Release(stream); test++; } @@ -1063,7 +1210,10 @@ struct nodes_test { const char *xml; - XmlNodeType types[20]; + struct { + XmlNodeType type; + const char *value; + } nodes[20]; }; static const char misc_test_xml[] = @@ -1087,22 +1237,22 @@ static struct nodes_test misc_test = { misc_test_xml, { - XmlNodeType_Comment, - XmlNodeType_Comment, - XmlNodeType_ProcessingInstruction, - XmlNodeType_Comment, - XmlNodeType_Whitespace, - XmlNodeType_Comment, - XmlNodeType_Element, - XmlNodeType_Whitespace, - XmlNodeType_Element, - XmlNodeType_Text, - XmlNodeType_Comment, - XmlNodeType_Text, - XmlNodeType_ProcessingInstruction, - XmlNodeType_Whitespace, - XmlNodeType_EndElement, - XmlNodeType_None + {XmlNodeType_Comment, " comment1 "}, + {XmlNodeType_Comment, " comment2 "}, + {XmlNodeType_ProcessingInstruction, "pi1body "}, + {XmlNodeType_Comment, " comment3 "}, + {XmlNodeType_Whitespace, " \t \n \n"}, + {XmlNodeType_Comment, " comment4 "}, + {XmlNodeType_Element, ""}, + {XmlNodeType_Whitespace, "\n\t"}, + {XmlNodeType_Element, ""}, + {XmlNodeType_Text, "text"}, + {XmlNodeType_Comment, " comment "}, + {XmlNodeType_Text, "text2"}, + {XmlNodeType_ProcessingInstruction, "pibody "}, + {XmlNodeType_Whitespace, "\n"}, + {XmlNodeType_EndElement, ""}, + {XmlNodeType_None, ""} } }; @@ -1110,41 +1260,21 @@ { struct nodes_test *test = &misc_test; IXmlReader *reader; - XmlNodeType type; - IStream *stream; HRESULT hr; int i; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); i = 0; - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - while (hr == S_OK) - { - ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i); - if (test->types[i] == XmlNodeType_None) break; - ok(type == test->types[i], "%d: got wrong type %d, expected %d\n", i, type, test->types[i]); - if (type == XmlNodeType_Whitespace) - { - const WCHAR *ptr; - UINT len = 0; - - hr = IXmlReader_GetValue(reader, &ptr, &len); - ok(hr == S_OK, "%d: GetValue failed 0x%08x\n", i, hr); - ok(len > 0, "%d: wrong value length %d\n", i, len); - } - hr = IXmlReader_Read(reader, &type); - i++; - } - ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]); - - IStream_Release(stream); + do + { + read_node(reader, test->nodes[i].type); + reader_value(reader, test->nodes[i].value); + } while(test->nodes[i++].type != XmlNodeType_None); + IXmlReader_Release(reader); } @@ -1153,11 +1283,7 @@ static void test_read_public_dtd(void) { - static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0}; - static const WCHAR pubvalW[] = {'p','u','b','i','d',0}; static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0}; - static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; - static const WCHAR pubW[] = {'P','U','B','L','I','C',0}; IXmlReader *reader; const WCHAR *str; XmlNodeType type; @@ -1175,10 +1301,7 @@ hr = IXmlReader_SetInput(reader, (IUnknown*)stream); ok(hr == S_OK, "got %08x\n", hr); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_DocumentType, "got type %d\n", type); + read_node(reader, XmlNodeType_DocumentType); count = 0; hr = IXmlReader_GetAttributeCount(reader, &count); @@ -1193,60 +1316,30 @@ ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); + reader_name(reader, "PUBLIC"); + reader_value(reader, "pubid"); + + next_attribute(reader); + + type = XmlNodeType_None; + hr = IXmlReader_GetNodeType(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Attribute, "got %d\n", type); + + reader_name(reader, "SYSTEM"); + reader_value(reader, "externalid uri"); + + move_to_element(reader); + reader_name(reader, "testdtd"); + len = 0; str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(pubW), "got %u\n", len); - ok(!lstrcmpW(str, pubW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(pubvalW), "got %u\n", len); - ok(!lstrcmpW(str, pubvalW), "got %s\n", wine_dbgstr_w(str)); - - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "got %08x\n", hr); - - type = XmlNodeType_None; - hr = IXmlReader_GetNodeType(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Attribute, "got %d\n", type); - - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysW), "got %u\n", len); - ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysvalW), "got %u\n", len); - ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str)); - - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got 0x%08x\n", hr); - - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); } - len = 0; - str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(dtdnameW), "got %u\n", len); - ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - IStream_Release(stream); IXmlReader_Release(reader); } @@ -1257,9 +1350,7 @@ static void test_read_system_dtd(void) { - static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0}; static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0}; - static const WCHAR sysW[] = {'S','Y','S','T','E','M',0}; IXmlReader *reader; const WCHAR *str; XmlNodeType type; @@ -1277,10 +1368,7 @@ hr = IXmlReader_SetInput(reader, (IUnknown*)stream); ok(hr == S_OK, "got %08x\n", hr); - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_DocumentType, "got type %d\n", type); + read_node(reader, XmlNodeType_DocumentType); count = 0; hr = IXmlReader_GetAttributeCount(reader, &count); @@ -1295,42 +1383,22 @@ ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_Attribute, "got %d\n", type); + reader_name(reader, "SYSTEM"); + reader_value(reader, "externalid uri"); + + move_to_element(reader); + reader_name(reader, "testdtd"); + len = 0; str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysW), "got %u\n", len); - ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str)); - - len = 0; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(sysvalW), "got %u\n", len); - ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str)); - - hr = IXmlReader_MoveToElement(reader); - ok(hr == S_OK, "got 0x%08x\n", hr); - - len = 0; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine { ok(len == lstrlenW(dtdnameW), "got %u\n", len); ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); } - len = 0; - str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == lstrlenW(dtdnameW), "got %u\n", len); - ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str)); - - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got 0x%8x\n", hr); - ok(type == XmlNodeType_Comment, "got type %d\n", type); + + read_node(reader, XmlNodeType_Comment); IStream_Release(stream); IXmlReader_Release(reader); @@ -1346,17 +1414,26 @@ { "<a >", "a", "", S_OK }, { "<a \r \t\n>", "a", "", S_OK }, { "</a>", NULL, NULL, NC_E_QNAMECHARACTER }, + { "<a:b:c />", NULL, NULL, NC_E_QNAMECOLON }, + { "<:b:c />", NULL, NULL, NC_E_QNAMECHARACTER }, { NULL } }; static void test_read_element(void) { struct test_entry *test = element_tests; - static const char stag[] = "<a><b></b></a>"; - static const char mismatch[] = "<a></b>"; + static const char stag[] = + "<a attr1=\"_a\">" + "<b attr2=\"_b\">" + "text" + "<c attr3=\"_c\"/>" + "<d attr4=\"_d\"></d>" + "</b>" + "</a>"; + static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 }; IXmlReader *reader; XmlNodeType type; - IStream *stream; + unsigned int i; UINT depth; HRESULT hr; @@ -1365,9 +1442,7 @@ while (test->xml) { - stream = create_stream_on_data(test->xml, strlen(test->xml)+1); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, test->xml); type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); @@ -1394,90 +1469,110 @@ free_str(str_exp); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == 0, "got %u\n", len); - ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + reader_value(reader, ""); } - IStream_Release(stream); test++; } /* test reader depth increment */ - stream = create_stream_on_data(stag, sizeof(stag)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); - - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); - - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); - - depth = 1; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 0, "got %d\n", depth); - - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); - - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); - - /* read end tag for inner element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); - - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); -todo_wine - ok(depth == 2, "got %d\n", depth); - - /* read end tag for container element */ - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_EndElement, "got %d\n", type); - - depth = 0; - hr = IXmlReader_GetDepth(reader, &depth); - ok(hr == S_OK, "got %08x\n", hr); - ok(depth == 1, "got %d\n", depth); - - IStream_Release(stream); + set_input_string(reader, stag); + + i = 0; + while (IXmlReader_Read(reader, &type) == S_OK) + { + UINT count; + + ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement || + type == XmlNodeType_Text, "Unexpected node type %d\n", type); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); + + if (type == XmlNodeType_Element || type == XmlNodeType_EndElement) + { + const WCHAR *prefix; + + prefix = NULL; + hr = IXmlReader_GetPrefix(reader, &prefix, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(prefix != NULL, "got %p\n", prefix); + + if (!*prefix) + { + const WCHAR *local, *qname; + + local = NULL; + hr = IXmlReader_GetLocalName(reader, &local, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(local != NULL, "got %p\n", local); + + qname = NULL; + hr = IXmlReader_GetQualifiedName(reader, &qname, NULL); + ok(hr == S_OK, "got %08x\n", hr); + ok(qname != NULL, "got %p\n", qname); + + ok(local == qname, "expected same pointer\n"); + } + } + + if (type == XmlNodeType_EndElement) + { + count = 1; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + ok(count == 0, "got %u\n", count); + } + + if (type == XmlNodeType_Element) + { + count = 0; + hr = IXmlReader_GetAttributeCount(reader, &count); + ok(hr == S_OK, "got %08x\n", hr); + + /* moving to attributes increases depth */ + if (count) + { + const WCHAR *value; + + reader_value(reader, ""); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_GetValue(reader, &value, NULL); + ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value)); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1); + + move_to_element(reader); + reader_value(reader, ""); + + depth = 123; + hr = IXmlReader_GetDepth(reader, &depth); + ok(hr == S_OK, "got %08x\n", hr); + ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]); + } + } + + i++; + } /* start/end tag mismatch */ - stream = create_stream_on_data(mismatch, sizeof(mismatch)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); - - type = XmlNodeType_None; - hr = IXmlReader_Read(reader, &type); - ok(hr == S_OK, "got %08x\n", hr); - ok(type == XmlNodeType_Element, "got %d\n", type); + set_input_string(reader, "<a></b>"); + + read_node(reader, XmlNodeType_Element); type = XmlNodeType_Element; hr = IXmlReader_Read(reader, &type); ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr); -todo_wine ok(type == XmlNodeType_None, "got %d\n", type); - - IStream_Release(stream); + TEST_READER_STATE(reader, XmlReadState_Error); IXmlReader_Release(reader); } @@ -1505,6 +1600,7 @@ ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr); /* newer versions are happy when it's enough data to detect node type, older versions keep reading until it fails to read more */ +todo_wine ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall); ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type); @@ -1521,11 +1617,9 @@ static void test_readvaluechunk(void) { - static const char testA[] = "<!-- comment1 -->"; IXmlReader *reader; XmlNodeType type; - IStream *stream; - const WCHAR *value; + WCHAR buf[64]; WCHAR b; HRESULT hr; UINT c; @@ -1533,25 +1627,17 @@ hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(testA, sizeof(testA)); - hr = IXmlReader_SetInput(reader, (IUnknown*)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, "<!-- comment1 --><!-- comment2 -->"); hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr); - - c = 0; - b = 0; - hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); - ok(hr == S_OK, "got %08x\n", hr); - ok(c == 1, "got %u\n", c); - ok(b == ' ', "got %x\n", b); + ok(type == XmlNodeType_Comment, "type = %u\n", type); + + read_value_char(reader, ' '); + read_value_char(reader, 'c'); /* portion read as chunk is skipped from resulting node value */ - value = NULL; - hr = IXmlReader_GetValue(reader, &value, NULL); - ok(hr == S_OK, "got %08x\n", hr); - ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); + reader_value(reader, "omment1 "); /* once value is returned/allocated it's not possible to read by chunk */ c = 0; @@ -1561,20 +1647,57 @@ ok(c == 0, "got %u\n", c); ok(b == 0, "got %x\n", b); - value = NULL; - hr = IXmlReader_GetValue(reader, &value, NULL); - ok(hr == S_OK, "got %08x\n", hr); - ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value)); - - IXmlReader_Release(reader); - IStream_Release(stream); + c = 0xdeadbeef; + hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(!c, "c = %u\n", c); + + reader_value(reader, "omment1 "); + + /* read comment2 */ + read_node(reader, XmlNodeType_Comment); + + c = 0xdeadbeef; + hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(!c, "c = %u\n", c); + + c = 0xdeadbeef; + memset(buf, 0xcc, sizeof(buf)); + hr = IXmlReader_ReadValueChunk(reader, buf, sizeof(buf)/sizeof(WCHAR), &c); + ok(hr == S_OK, "got %08x\n", hr); + ok(c == 10, "got %u\n", c); + ok(buf[c] == 0xcccc, "buffer overflow\n"); + buf[c] = 0; + ok(!strcmp_wa(buf, " comment2 "), "buf = %s\n", wine_dbgstr_w(buf)); + + c = 0xdeadbeef; + memset(buf, 0xcc, sizeof(buf)); + hr = IXmlReader_ReadValueChunk(reader, buf, sizeof(buf)/sizeof(WCHAR), &c); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(!c, "got %u\n", c); + + /* portion read as chunk is skipped from resulting node value */ + reader_value(reader, ""); + + /* once value is returned/allocated it's not possible to read by chunk */ + c = 0xdeadbeef; + b = 0xffff; + hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(c == 0, "got %u\n", c); + ok(b == 0xffff, "got %x\n", b); + + reader_value(reader, ""); + + IXmlReader_Release(reader); } static struct test_entry cdata_tests[] = { { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK }, { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK }, - { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK, TRUE }, - { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK, TRUE }, + { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK }, + { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK }, { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK }, { NULL } }; @@ -1614,49 +1737,31 @@ if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; UINT len; ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - - len = 1; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, ""); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - - str_exp = a2w(test->value); - todo_wine_if (test->todo) - { - ok(len == strlen(test->value), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - } - free_str(str_exp); + reader_value(reader, test->value); } IStream_Release(stream); @@ -1669,6 +1774,8 @@ static struct test_entry text_tests[] = { { "<a>simple text</a>", "", "simple text", S_OK }, { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND }, + { "<a>\n \r\n \n\n text</a>", "", "\n \n \n\n text", S_OK, S_OK }, + { "<a>\r \r\r\n \n\n text</a>", "", "\n \n\n \n\n text", S_OK, S_OK }, { NULL } }; @@ -1693,63 +1800,41 @@ type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); - /* read one more to get to CDATA */ + /* read one more to get to text node */ if (type == XmlNodeType_Element) { type = XmlNodeType_None; hr = IXmlReader_Read(reader, &type); } - - if (test->hr_broken) - ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml); - else - ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); + ok(hr == test->hr, "got %08x for %s\n", hr, test->xml); if (hr == S_OK) { const WCHAR *str; - WCHAR *str_exp; UINT len; ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml); - str_exp = a2w(test->name); - - len = 1; - str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); + reader_name(reader, ""); str = NULL; hr = IXmlReader_GetLocalName(reader, &str, NULL); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - - free_str(str_exp); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); len = 1; str = NULL; hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + ok(len == 0, "got %u\n", len); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); + + str = NULL; + hr = IXmlReader_GetQualifiedName(reader, &str, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(*str == 0, "got %s\n", wine_dbgstr_w(str)); /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - - str_exp = a2w(test->value); - todo_wine_if (test->todo) - { - ok(len == strlen(test->value), "got %u\n", len); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - } - free_str(str_exp); + reader_value(reader, test->value); } IStream_Release(stream); @@ -1867,34 +1952,19 @@ hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "got 0x%08x\n", hr); + reader_name(reader, test->name); + len = 1; str = NULL; - hr = IXmlReader_GetLocalName(reader, &str, &len); + hr = IXmlReader_GetQualifiedName(reader, &str, &len); ok(hr == S_OK, "got 0x%08x\n", hr); ok(len == strlen(test->name), "got %u\n", len); str_exp = a2w(test->name); ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); free_str(str_exp); - len = 1; - str = NULL; - hr = IXmlReader_GetQualifiedName(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - todo_wine { - ok(len == strlen(test->name), "got %u\n", len); - str_exp = a2w(test->name); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); - } /* value */ - len = 1; - str = NULL; - hr = IXmlReader_GetValue(reader, &str, &len); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(len == strlen(test->value), "got %u\n", len); - str_exp = a2w(test->value); - ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str)); - free_str(str_exp); + reader_value(reader, test->value); } IStream_Release(stream); @@ -1907,16 +1977,27 @@ static void test_reader_properties(void) { IXmlReader *reader; + LONG_PTR value; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); + value = 0; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 256, "Unexpected default max depth value %ld\n", value); + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); ok(hr == S_OK, "SetProperty failed: %08x\n", hr); + + value = 256; + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value); + ok(hr == S_OK, "GetProperty failed: %08x\n", hr); + ok(value == 0, "Unexpected max depth value %ld\n", value); IXmlReader_Release(reader); } @@ -1932,6 +2013,7 @@ } prefix_tests[] = { { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" }, + { "<c:b xmlns:c=\"c ns\" xml:a=\"a ns\"/>", "c", "xmlns", "xml" }, }; IXmlReader *reader; unsigned int i; @@ -1941,9 +2023,7 @@ ok(hr == S_OK, "S_OK, got %08x\n", hr); for (i = 0; i < sizeof(prefix_tests)/sizeof(prefix_tests[0]); i++) { - const WCHAR *prefix; XmlNodeType type; - WCHAR *expected; IStream *stream; stream = create_stream_on_data(prefix_tests[i].xml, strlen(prefix_tests[i].xml) + 1); @@ -1954,12 +2034,7 @@ ok(hr == S_OK, "Read() failed, %#x\n", hr); ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix1); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); + reader_prefix(reader, prefix_tests[i].prefix1); hr = IXmlReader_MoveToFirstAttribute(reader); ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr); @@ -1968,26 +2043,19 @@ ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr); ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix2); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); - - hr = IXmlReader_MoveToNextAttribute(reader); - ok(hr == S_OK, "MoveToNextAttribute() failed, %#x.\n", hr); + reader_prefix(reader, prefix_tests[i].prefix2); + + next_attribute(reader); hr = IXmlReader_GetNodeType(reader, &type); ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr); ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type); - expected = a2w(prefix_tests[i].prefix3); - hr = IXmlReader_GetPrefix(reader, &prefix, NULL); - ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr); - ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix), - wine_dbgstr_w(expected)); - free_str(expected); + reader_prefix(reader, prefix_tests[i].prefix3); + + /* back to the element, check prefix */ + move_to_element(reader); + reader_prefix(reader, prefix_tests[i].prefix1); IStream_Release(stream); } @@ -2013,6 +2081,18 @@ { "defns a", "ns r", "defns a" }}, { "<a><b><c/></b></a>", { "", "", "", "", "" }}, + { "<a>text</a>", + { "", "", "" }}, + { "<a>\r\n</a>", + { "", "", "" }}, + { "<a><![CDATA[data]]></a>", + { "", "", "" }}, + { "<?xml version=\"1.0\" ?><a/>", + { "", "" }}, + { "<a><?pi ?></a>", + { "", "", "" }}, + { "<a><!-- comment --></a>", + { "", "", "" }}, }; IXmlReader *reader; XmlNodeType type; @@ -2029,24 +2109,49 @@ hr = IXmlReader_SetInput(reader, (IUnknown *)stream); ok(hr == S_OK, "got %08x\n", hr); + type = ~0u; while (IXmlReader_Read(reader, &type) == S_OK) { - const WCHAR *uri, *local; - WCHAR *uriW; - - ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement, "Unexpected node type %d.\n", type); - - hr = IXmlReader_GetLocalName(reader, &local, NULL); + const WCHAR *local, *qname; + UINT length, length2; + + ok(type == XmlNodeType_Element || + type == XmlNodeType_Text || + type == XmlNodeType_CDATA || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_Comment || + type == XmlNodeType_Whitespace || + type == XmlNodeType_EndElement || + type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type); + + local = NULL; + length = 0; + hr = IXmlReader_GetLocalName(reader, &local, &length); ok(hr == S_OK, "S_OK, got %08x\n", hr); - - hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL); + ok(local != NULL, "Unexpected NULL local name pointer\n"); + + qname = NULL; + length2 = 0; + hr = IXmlReader_GetQualifiedName(reader, &qname, &length2); ok(hr == S_OK, "S_OK, got %08x\n", hr); - - uriW = a2w(uri_tests[i].uri[j]); - ok(!lstrcmpW(uriW, uri), "%s: uri %s\n", wine_dbgstr_w(local), wine_dbgstr_w(uri)); - free_str(uriW); + ok(qname != NULL, "Unexpected NULL qualified name pointer\n"); + + if (type == XmlNodeType_Element || + type == XmlNodeType_EndElement || + type == XmlNodeType_ProcessingInstruction || + type == XmlNodeType_XmlDeclaration) + { + ok(*local != 0, "Unexpected empty local name\n"); + ok(length > 0, "Unexpected local name length\n"); + + ok(*qname != 0, "Unexpected empty qualified name\n"); + ok(length2 > 0, "Unexpected qualified name length\n"); + } + + reader_namespace(reader, uri_tests[i].uri[j]); j++; } + ok(type == XmlNodeType_None, "Unexpected node type %d\n", type); IStream_Release(stream); } @@ -2056,20 +2161,17 @@ static void test_read_charref(void) { - static const char testA[] = "<a b=\"c\">dză</a>"; - static const WCHAR chardataW[] = {0x01f3,0x0103,0}; + static const char testA[] = "<a b=\"c\">dză></a>"; + static const WCHAR chardataW[] = {0x01f3,0x0103,'>',0}; const WCHAR *value; IXmlReader *reader; XmlNodeType type; - IStream *stream; HRESULT hr; hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); ok(hr == S_OK, "S_OK, got %08x\n", hr); - stream = create_stream_on_data(testA, sizeof(testA)); - hr = IXmlReader_SetInput(reader, (IUnknown *)stream); - ok(hr == S_OK, "got %08x\n", hr); + set_input_string(reader, testA); hr = IXmlReader_Read(reader, &type); ok(hr == S_OK, "got %08x\n", hr); @@ -2087,8 +2189,436 @@ ok(hr == S_OK, "got %08x\n", hr); ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type); - IXmlReader_Release(reader); - IStream_Release(stream); + hr = IXmlReader_Read(reader, &type); + ok(hr == S_FALSE, "got %08x\n", hr); + ok(type == XmlNodeType_None, "Unexpected node type %d\n", type); + + IXmlReader_Release(reader); +} + +static void test_encoding_detection(void) +{ + static const struct encoding_testW + { + WCHAR text[16]; + } + encoding_testsW[] = + { + { { '<','?','p','i',' ','?','>',0 } }, + { { '<','!','-','-',' ','c','-','-','>',0 } }, + { { 0xfeff,'<','a','/','>',0 } }, + { { '<','a','/','>',0 } }, + }; + static const char *encoding_testsA[] = + { + "<?pi ?>", + "<!-- comment -->", + "\xef\xbb\xbf<a/>", /* UTF-8 BOM */ + "<a/>", + }; + IXmlReader *reader; + XmlNodeType type; + IStream *stream; + unsigned int i; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + /* there's no way to query detected encoding back, so just verify that document is browsable */ + + for (i = 0; i < sizeof(encoding_testsA)/sizeof(encoding_testsA[0]); i++) + { + stream = create_stream_on_data(encoding_testsA[i], strlen(encoding_testsA[i])); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type != XmlNodeType_None, "Unexpected node type %d\n", type); + + IStream_Release(stream); + } + + for (i = 0; i < sizeof(encoding_testsW)/sizeof(encoding_testsW[0]); i++) + { + stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR)); + + hr = IXmlReader_SetInput(reader, (IUnknown *)stream); + ok(hr == S_OK, "got %08x\n", hr); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "%u: got %08x\n", i, hr); + ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type); + + IStream_Release(stream); + } + + IXmlReader_Release(reader); +} + +static void test_eof_state(IXmlReader *reader, BOOL eof) +{ + LONG_PTR state; + HRESULT hr; + + ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n"); + hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state); + ok(hr == S_OK, "GetProperty() failed, %#x\n", hr); + ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state); +} + +static void test_endoffile(void) +{ + IXmlReader *reader; + XmlNodeType type; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + test_eof_state(reader, FALSE); + + set_input_string(reader, "<a/>"); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %#x\n", hr); + ok(type == XmlNodeType_Element, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(type == XmlNodeType_None, "Unexpected type %d\n", type); + + test_eof_state(reader, TRUE); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + test_eof_state(reader, FALSE); + + IXmlReader_Release(reader); + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, "<a/>text"); + + type = XmlNodeType_None; + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %#x\n", hr); + ok(type == XmlNodeType_Element, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + type = XmlNodeType_Element; + hr = IXmlReader_Read(reader, &type); + ok(hr == WC_E_SYNTAX, "got %#x\n", hr); + ok(type == XmlNodeType_None, "Unexpected type %d\n", type); + + test_eof_state(reader, FALSE); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + IXmlReader_Release(reader); +} + +static void test_max_element_depth(void) +{ + static const char *xml = + "<a>" + "<b attrb=\"_b\">" + "<c>" + "<d></d>" + "</c>" + "</b>" + "</a>"; + XmlNodeType nodetype; + unsigned int count; + IXmlReader *reader; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + /* test if stepping into attributes enforces depth limit too */ + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 0); + + hr = IXmlReader_Read(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 1); + + hr = IXmlReader_MoveToFirstAttribute(reader); + ok(hr == S_OK, "got %08x\n", hr); + + TEST_DEPTH(reader, 2); + TEST_READER_STATE(reader, XmlReadState_Interactive); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + nodetype = 123; + hr = IXmlReader_Read(reader, &nodetype); + ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr); + ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype); + + TEST_DEPTH2(reader, 0, 2); + TEST_READER_STATE(reader, XmlReadState_Error); + + /* set max depth to 0, this disables depth limit */ + set_input_string(reader, xml); + + hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0); + ok(hr == S_OK, "got %08x\n", hr); + + count = 0; + while (IXmlReader_Read(reader, NULL) == S_OK) + count++; + ok(count == 8, "Unexpected node number %u\n", count); + TEST_READER_STATE(reader, XmlReadState_EndOfFile); + + IXmlReader_Release(reader); +} + +static void test_reader_position(void) +{ + static const char *xml = "<c:a xmlns:c=\"nsdef c\" b=\"attr b\">\n</c:a>"; + IXmlReader *reader; + XmlNodeType type; + UINT position; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + TEST_READER_STATE(reader, XmlReadState_Closed); + + /* position methods with Null args */ + hr = IXmlReader_GetLineNumber(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + hr = IXmlReader_GetLinePosition(reader, NULL); + ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); + + position = 123; + hr = IXmlReader_GetLinePosition(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + position = 123; + hr = IXmlReader_GetLineNumber(reader, &position); + ok(hr == S_FALSE, "got %#x\n", hr); + ok(position == 0, "got %u\n", position); + + set_input_string(reader, xml); + + TEST_READER_STATE(reader, XmlReadState_Initial); + TEST_READER_POSITION(reader, 0, 0); + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Element, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + next_attribute(reader); + TEST_READER_POSITION2(reader, 1, 6, ~0u, 34); + + next_attribute(reader); + TEST_READER_POSITION2(reader, 1, 24, ~0u, 34); + + move_to_element(reader); + TEST_READER_POSITION2(reader, 1, 2, ~0u, 34); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_Whitespace, "got type %d\n", type); + TEST_READER_POSITION2(reader, 1, 35, 2, 6); + + hr = IXmlReader_Read(reader, &type); + ok(hr == S_OK, "got %08x\n", hr); + ok(type == XmlNodeType_EndElement, "got type %d\n", type); + TEST_READER_POSITION2(reader, 2, 3, 2, 6); + + hr = IXmlReader_SetInput(reader, NULL); + ok(hr == S_OK, "got %08x\n", hr); + TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed); + TEST_READER_POSITION(reader, 0, 0); + + IXmlReader_Release(reader); +} + +static void test_string_pointers(void) +{ + const WCHAR *ns, *nsq, *empty, *xmlns_ns, *xmlns_name, *name, *p, *q, *xml, *ptr, *value; + IXmlReader *reader; + HRESULT hr; + + hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); + ok(hr == S_OK, "S_OK, got %08x\n", hr); + + set_input_string(reader, "<elem xmlns=\"myns\">myns<elem2 /></elem>"); + + read_node(reader, XmlNodeType_Element); + empty = reader_value(reader, ""); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + name = reader_name(reader, "elem"); + ok(name == reader_qname(reader, "elem"), "name != qname\n"); + ns = reader_namespace(reader, "myns"); + + next_attribute(reader); + ptr = reader_value(reader, "myns"); + if (ns != ptr) + { + win_skip("attr value is different than namespace pointer, assuming old xmllite\n"); + IXmlReader_Release(reader); + return; + } + ok(ns == ptr, "ns != value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + xmlns_ns = reader_namespace(reader, "
http://www.w3.org/2000/xmlns/
"); + xmlns_name = reader_name(reader, "xmlns"); + ok(xmlns_name == reader_qname(reader, "xmlns"), "xmlns_name != qname\n"); + + read_node(reader, XmlNodeType_Text); + ok(ns != reader_value(reader, "myns"), "ns == value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + ok(empty == reader_name(reader, ""), "empty != name\n"); + ok(empty == reader_qname(reader, ""), "empty != qname\n"); + + read_node(reader, XmlNodeType_Element); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + + read_node(reader, XmlNodeType_EndElement); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(name == reader_name(reader, "elem"), "empty != name\n"); + ok(name == reader_qname(reader, "elem"), "empty != qname\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + + set_input_string(reader, "<elem xmlns:p=\"myns\" xmlns:q=\"mynsq\"><p:elem2 q:attr=\"\"></p:elem2></elem>"); + + read_node(reader, XmlNodeType_Element); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + name = reader_name(reader, "elem"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + next_attribute(reader); + ns = reader_value(reader, "myns"); + ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n"); + p = reader_name(reader, "p"); + ok(xmlns_ns == reader_namespace(reader, "
http://www.w3.org/2000/xmlns/
"), "xmlns_ns != namespace\n"); + + next_attribute(reader); + nsq = reader_value(reader, "mynsq"); + ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n"); + q = reader_name(reader, "q"); + ok(xmlns_ns == reader_namespace(reader, "
http://www.w3.org/2000/xmlns/
"), "xmlns_ns != namespace\n"); + + read_node(reader, XmlNodeType_Element); + ok(p == reader_prefix(reader, "p"), "p != prefix\n"); + ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n"); + name = reader_qname(reader, "p:elem2"); + + next_attribute(reader); + ok(empty != reader_value(reader, ""), "empty == value\n"); + ok(q == reader_prefix(reader, "q"), "q != prefix\n"); + ok(nsq == reader_namespace(reader, "mynsq"), "nsq != namespace\n"); + + read_node(reader, XmlNodeType_EndElement); + ptr = reader_qname(reader, "p:elem2"); todo_wine ok(name != ptr, "q == qname\n"); + + set_input_string(reader, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"); + + read_node(reader, XmlNodeType_XmlDeclaration); + ok(empty == reader_value(reader, ""), "empty != value\n"); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + xml = reader_name(reader, "xml"); + ptr = reader_qname(reader, "xml"); todo_wine ok(xml == ptr, "xml != qname\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + next_attribute(reader); + ok(empty == reader_prefix(reader, ""), "empty != prefix\n"); + ok(empty == reader_namespace(reader, ""), "empty != namespace\n"); + + set_input_string(reader, "<elem xmlns:p=\"myns\"><p:elem2 attr=\"\" /></elem>"); + + read_node(reader, XmlNodeType_Element); + next_attribute(reader); + read_value_char(reader, 'm'); + p = reader_value(reader, "yns"); + + read_node(reader, XmlNodeType_Element); + ns = reader_namespace(reader, "myns"); + ok(ns+1 == p, "ns+1 != p\n"); + + set_input_string(reader, "<elem attr=\"value\"></elem>"); + + read_node(reader, XmlNodeType_Element); + next_attribute(reader); + name = reader_name(reader, "attr"); + value = reader_value(reader, "value"); + + move_to_element(reader); + next_attribute(reader); + ok(name == reader_name(reader, "attr"), "attr pointer changed\n"); + ok(value == reader_value(reader, "value"), "value pointer changed\n"); + + IXmlReader_Release(reader); } START_TEST(reader) @@ -2113,4 +2643,9 @@ test_prefix(); test_namespaceuri(); test_read_charref(); -} + test_encoding_detection(); + test_endoffile(); + test_max_element_depth(); + test_reader_position(); + test_string_pointers(); +} Modified: trunk/rostests/winetests/xmllite/writer.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/xmllite/writer.…
============================================================================== --- trunk/rostests/winetests/xmllite/writer.c [iso-8859-1] (original) +++ trunk/rostests/winetests/xmllite/writer.c [iso-8859-1] Sun Jun 4 01:49:50 2017 @@ -39,12 +39,21 @@ #include <initguid.h> DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); +#define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__) +static void _expect_ref(IUnknown *obj, ULONG ref, int line) +{ + ULONG refcount; + IUnknown_AddRef(obj); + refcount = IUnknown_Release(obj); + ok_(__FILE__, line)(refcount == ref, "expected refcount %d, got %d\n", ref, refcount); +} + static void check_output(IStream *stream, const char *expected, BOOL todo, int line) { + int len = strlen(expected), size; HGLOBAL hglobal; - int len = strlen(expected), size; + HRESULT hr; char *ptr; - HRESULT hr; hr = GetHGlobalFromStream(stream, &hglobal); ok_(__FILE__, line)(hr == S_OK, "got 0x%08x\n", hr); @@ -56,10 +65,10 @@ if (size != len) { ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size); - ok_(__FILE__, line)(0, "got %s, expected %s\n", ptr, expected); + ok_(__FILE__, line)(0, "got |%s|, expected |%s|\n", ptr, expected); } else - ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got %s, expected %s\n", ptr, expected); + ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got |%s|, expected |%s|\n", ptr, expected); } GlobalUnlock(hglobal); } @@ -236,6 +245,7 @@ HRESULT hr; IXmlWriter *writer; LONG_PTR value; + IUnknown *unk; /* crashes native */ if (0) @@ -244,6 +254,17 @@ CreateXmlWriter(NULL, (void**)&writer, NULL); } + hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL); + ok(hr == E_NOINTERFACE, "got %08x\n", hr); + + hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(unk == (IUnknown *)writer, "unexpected interface pointer\n"); + IUnknown_Release(unk); + IXmlWriter_Release(writer); + hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); @@ -274,6 +295,7 @@ static void test_writeroutput(void) { static const WCHAR utf16W[] = {'u','t','f','-','1','6',0}; + static const WCHAR usasciiW[] = {'u','s','-','a','s','c','i','i',0}; IXmlWriterOutput *output; IUnknown *unk; HRESULT hr; @@ -281,6 +303,7 @@ output = NULL; hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output); ok(hr == S_OK, "got %08x\n", hr); + EXPECT_REF(output, 1); IUnknown_Release(output); hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output); @@ -288,8 +311,12 @@ unk = NULL; hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk); ok(hr == S_OK, "got %08x\n", hr); - ok(unk != NULL, "got %p\n", unk); +todo_wine + ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output); + EXPECT_REF(output, 2); /* releasing 'unk' crashes on native */ + IUnknown_Release(output); + EXPECT_REF(output, 1); IUnknown_Release(output); output = NULL; @@ -305,14 +332,24 @@ ok(unk != NULL, "got %p\n", unk); /* releasing 'unk' crashes on native */ IUnknown_Release(output); + IUnknown_Release(output); + + /* create with us-ascii */ + output = NULL; + hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, usasciiW, &output); + ok(hr == S_OK, "got %08x\n", hr); + IUnknown_Release(output); } static void test_writestartdocument(void) { static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"; + static const char *prologversion2 = "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>"; static const char prologversion[] = "<?xml version=\"1.0\"?>"; static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR usasciiW[] = {'u','S','-','a','s','C','i','i',0}; static const WCHAR xmlW[] = {'x','m','l',0}; + IXmlWriterOutput *output; IXmlWriter *writer; IStream *stream; HRESULT hr; @@ -372,6 +409,32 @@ IStream_Release(stream); IXmlWriter_Release(writer); + + /* create with us-ascii */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + output = NULL; + hr = CreateXmlWriterOutputWithEncodingName((IUnknown *)stream, NULL, usasciiW, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, prologversion2); + + IStream_Release(stream); + IXmlWriter_Release(writer); + IUnknown_Release(output); } static void test_flush(void) @@ -1261,6 +1324,83 @@ CHECK_OUTPUT(stream, "<a>Ā<a /></a>"); + + IXmlWriter_Release(writer); + IStream_Release(stream); +} + +static void test_WriteString(void) +{ + static const WCHAR markupW[] = {'<','&','"','>','=',0}; + static const WCHAR aW[] = {'a',0}; + static const WCHAR bW[] = {'b',0}; + static const WCHAR emptyW[] = {0}; + IXmlWriter *writer; + IStream *stream; + HRESULT hr; + + hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, aW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, emptyW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + stream = writer_set_output(writer); + + hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, emptyW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, aW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* WriteString automatically escapes markup characters */ + hr = IXmlWriter_WriteString(writer, markupW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + "<b>a<&\">="); + IStream_Release(stream); + + stream = writer_set_output(writer); + + hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteString(writer, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + "<b"); + + hr = IXmlWriter_WriteString(writer, emptyW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + CHECK_OUTPUT(stream, + "<b>"); IXmlWriter_Release(writer); IStream_Release(stream); @@ -1285,4 +1425,5 @@ test_WriteAttributeString(); test_WriteFullEndElement(); test_WriteCharEntity(); -} + test_WriteString(); +}
7 years, 6 months
1
0
0
0
[akhaldi] 74872: [XMLLITE] Sync with Wine Staging 2.9. CORE-13362 707ab55 xmllite/writer: Fix IID argument handling in CreateXmlWriter(). d1e1457 xmllite/reader: Fix IID argument handling in Create...
by akhaldi@svn.reactos.org
Author: akhaldi Date: Sun Jun 4 01:49:43 2017 New Revision: 74872 URL:
http://svn.reactos.org/svn/reactos?rev=74872&view=rev
Log: [XMLLITE] Sync with Wine Staging 2.9. CORE-13362 707ab55 xmllite/writer: Fix IID argument handling in CreateXmlWriter(). d1e1457 xmllite/reader: Fix IID argument handling in CreateXmlReader(). a68e51c xmllite/writer: Preserve original encoding name spelling in writer output. ef023c3 xmllite: Recognize us-ascii encoding. 9506e7d xmllite: Return local name stored in namespace for prefixed namespace attribute values. 1b9b791 xmllite: Allocate value in reader_add_attr. daf0504 xmllite: Allow reading from allocated strings in ReadValueChunk. f862222 xmllite: Store allocated copy of local name in attribute struct and use that instead of StringValue_LocalName. 004d615 xmllite: Don't use StringValue_LocalName for element nodes. 6917e2a xmllite: Clear all parser values in SetInput. 291ffdd xmllite: Don't fail in readerinput_detectencoding if input buffer has 3 bytes. 536ed3f xmllite: Return empty value for end element and none nodes. 48fff1b xmllite: Replace crln in input buffer with nl. 2b5203b xmllite: Fixed ReadValueChunk implementation. a3d7806 xmllite: Fixed buffer handling in reader_parse_reference. 68aeee4 xmllite: Return WC_E_SYNTAX if there is unexpected data in the end of the stream. 253f233 xmllite/reader: Return same string for local and qualified names for attributes when appropriate. d7057a3 xmllite/reader: For elements without a prefix return same string for both local and qualified names. 1e015f1 xmllite/reader: Always return local name from element structure. 876de4a xmllite/reader: Reset reader nesting depth on error. ec9e05c xmllite/reader: Enter error state on parsing error. b115e96 xmllite/reader: Improve returned position for whitespace text nodes. 9685fec xmllite/reader: Improve line number updating when switching to the next line. 79a6567 xmllite/reader: Fix position methods return values in closed reader state. 62a41d0 xmllite/reader: Return correct error for multiple colons in qualified name. 3b83a44 xmllite/reader: Explicitly return empty string as qualified name for some node types. 52f9193 xmllite/reader: Explicitly return empty static string as local name for nodes without names. 1ccc1f2 xmllite/reader: Return static empty string as xml declaration node value. 65e62c3 xmllite/reader: Fix reader position returned for xml declaration node. 6cf9524 xmllite/reader: Improve returned reader position for elements and attributes. e1c31e1 xmllite/reader: Remove redundant parameter. d3319f6 xmllite/reader: Return prefixes from namespace stack. b57589a xmllite/reader: Return qualified element names from the stack, instead of input buffer. 3ae1043 xmllite/reader: Return local element names from the stack, instead of input buffer. 3697bd9 xmllite/reader: Return empty string for namespace uri for some nodes. 63c489f xmllite/reader: Fix GetValue() for comments. 71a0733 xmllite/reader: Enforce maximum element depth limit. ce84b20 xmllite/reader: Return qualified names for attributes. 3fe5f25 xmllite/reader: Fix prefix returned after moving back to element. 70028b7 xmllite/reader: Return empty value for elements. 7c44c65 xmllite/reader: Return proper name for xml declaration PI. 8f0c235 xmllite/reader: Improve the way nesting level returned by GetDepth() is updated. 073c43a xmllite/reader: Implement IsEOF(). b188079 xmllite/reader: Reset node type to XmlNodeType_None on EOF. 0cbd938 xmllite/reader: Always return node type from Read(). 80cf883 xmllite/reader: Improve input stream encoding detection. 5b78cc9 xmllite/writer: Fix Release() trace. 9c988e7 xmllite/writer: Implement WriteString(). 107615d xmllite/reader: Fix writing back resolved character reference value. 05956e6 xmllite: Fix CreateXmlReaderInputWithEncodingName spec file entry. d369857c xmllite: Add __WINE_ALLOC_SIZE attributes to heap_xxx() functions. Modified: trunk/reactos/dll/win32/xmllite/reader.c trunk/reactos/dll/win32/xmllite/writer.c trunk/reactos/dll/win32/xmllite/xmllite.spec trunk/reactos/dll/win32/xmllite/xmllite_private.h trunk/reactos/media/doc/README.WINE Modified: trunk/reactos/dll/win32/xmllite/reader.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/xmllite/reader.c…
============================================================================== --- trunk/reactos/dll/win32/xmllite/reader.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/xmllite/reader.c [iso-8859-1] Sun Jun 4 01:49:43 2017 @@ -1,7 +1,7 @@ /* * IXmlReader implementation * - * Copyright 2010, 2012-2013, 2016 Nikolay Sivov + * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +21,7 @@ #include "xmllite_private.h" #include <stdio.h> +#include <assert.h> #include <wine/list.h> #include <wine/unicode.h> @@ -73,6 +74,7 @@ StringValue_Last } XmlReaderStringValue; +static const WCHAR usasciiW[] = {'U','S','-','A','S','C','I','I',0}; static const WCHAR utf16W[] = {'U','T','F','-','1','6',0}; static const WCHAR utf8W[] = {'U','T','F','-','8',0}; @@ -82,6 +84,8 @@ static const WCHAR gtW[] = {'>',0}; static const WCHAR commentW[] = {'<','!','-','-',0}; static const WCHAR piW[] = {'<','?',0}; + +static BOOL is_namestartchar(WCHAR ch); static const char *debugstr_nodetype(XmlNodeType nodetype) { @@ -141,8 +145,9 @@ }; static const struct xml_encoding_data xml_encoding_map[] = { + { usasciiW, XmlEncoding_USASCII, 20127 }, { utf16W, XmlEncoding_UTF16, ~0 }, - { utf8W, XmlEncoding_UTF8, CP_UTF8 } + { utf8W, XmlEncoding_UTF8, CP_UTF8 }, }; const WCHAR *get_encoding_name(xml_encoding encoding) @@ -166,6 +171,7 @@ UINT cur; unsigned int allocated; unsigned int written; + BOOL prev_cr; } encoded_buffer; typedef struct input_buffer input_buffer; @@ -212,20 +218,36 @@ static const strval strval_xml = { xmlW, 3 }; static const strval strval_xmlns = { xmlnsW, 5 }; +struct reader_position +{ + UINT line_number; + UINT line_position; +}; + +enum attribute_flags +{ + ATTRIBUTE_NS_DEFINITION = 0x1, + ATTRIBUTE_DEFAULT_NS_DEFINITION = 0x2, +}; + struct attribute -{ - struct list entry; - strval prefix; - strval localname; - strval value; -}; - -struct element { struct list entry; strval prefix; strval localname; strval qname; + strval value; + struct reader_position position; + unsigned int flags; +}; + +struct element +{ + struct list entry; + strval prefix; + strval localname; + strval qname; + struct reader_position position; }; struct ns @@ -243,24 +265,27 @@ xmlreaderinput *input; IMalloc *imalloc; XmlReadState state; + HRESULT error; /* error set on XmlReadState_Error */ XmlReaderInternalState instate; XmlReaderResumeState resumestate; XmlNodeType nodetype; DtdProcessing dtdmode; IXmlResolver *resolver; IUnknown *mlang; - UINT line, pos; /* reader position in XML stream */ + struct reader_position position; struct list attrs; /* attributes list for current node */ struct attribute *attr; /* current attribute */ UINT attr_count; struct list nsdef; struct list ns; struct list elements; + int chunk_read_off; strval strvalues[StringValue_Last]; UINT depth; UINT max_depth; BOOL is_empty_element; - struct element empty_element; + struct element empty_element; /* used for empty elements without end tag <a />, + and to keep <?xml reader position */ UINT resume[XmlReadResume_Last]; /* offsets used to resume reader */ } xmlreader; @@ -360,11 +385,23 @@ return ret; } +/* This one frees stored string value if needed */ +static void reader_free_strvalued(xmlreader *reader, strval *v) +{ + if (v->str != strval_empty.str) + { + reader_free(reader, v->str); + *v = strval_empty; + } +} + static void reader_clear_attrs(xmlreader *reader) { struct attribute *attr, *attr2; LIST_FOR_EACH_ENTRY_SAFE(attr, attr2, &reader->attrs, struct attribute, entry) { + reader_free_strvalued(reader, &attr->localname); + reader_free_strvalued(reader, &attr->value); reader_free(reader, attr); } list_init(&reader->attrs); @@ -374,33 +411,48 @@ /* attribute data holds pointers to buffer data, so buffer shrink is not possible while we are on a node with attributes */ -static HRESULT reader_add_attr(xmlreader *reader, strval *prefix, strval *localname, strval *value) +static HRESULT reader_add_attr(xmlreader *reader, strval *prefix, strval *localname, strval *qname, + strval *value, const struct reader_position *position, unsigned int flags) { struct attribute *attr; + HRESULT hr; attr = reader_alloc(reader, sizeof(*attr)); if (!attr) return E_OUTOFMEMORY; + + hr = reader_strvaldup(reader, localname, &attr->localname); + if (hr == S_OK) + { + hr = reader_strvaldup(reader, value, &attr->value); + if (hr != S_OK) + reader_free_strvalued(reader, &attr->value); + } + if (hr != S_OK) + { + reader_free(reader, attr); + return hr; + } if (prefix) attr->prefix = *prefix; else memset(&attr->prefix, 0, sizeof(attr->prefix)); - attr->localname = *localname; - attr->value = *value; + attr->qname = qname ? *qname : *localname; + attr->position = *position; + attr->flags = flags; list_add_tail(&reader->attrs, &attr->entry); reader->attr_count++; return S_OK; } -/* This one frees stored string value if needed */ -static void reader_free_strvalued(xmlreader *reader, strval *v) -{ - if (v->str != strval_empty.str) - { - reader_free(reader, v->str); - *v = strval_empty; - } +/* Returns current element, doesn't check if reader is actually positioned on it. */ +static struct element *reader_get_element(xmlreader *reader) +{ + if (reader->is_empty_element) + return &reader->empty_element; + + return LIST_ENTRY(list_head(&reader->elements), struct element, entry); } static inline void reader_init_strvalue(UINT start, UINT len, strval *v) @@ -454,18 +506,20 @@ reader_free(reader, elem); } list_init(&reader->elements); + reader_free_strvalued(reader, &reader->empty_element.localname); + reader_free_strvalued(reader, &reader->empty_element.qname); reader->is_empty_element = FALSE; } static HRESULT reader_inc_depth(xmlreader *reader) { - if (++reader->depth > reader->max_depth) return SC_E_MAXELEMENTDEPTH; - return S_OK; + return (++reader->depth >= reader->max_depth && reader->max_depth) ? SC_E_MAXELEMENTDEPTH : S_OK; } static void reader_dec_depth(xmlreader *reader) { - if (reader->depth > 1) reader->depth--; + if (reader->depth) + reader->depth--; } static HRESULT reader_push_ns(xmlreader *reader, const strval *prefix, const strval *uri, BOOL def) @@ -524,38 +578,27 @@ } static HRESULT reader_push_element(xmlreader *reader, strval *prefix, strval *localname, - strval *qname) + strval *qname, const struct reader_position *position) { struct element *element; HRESULT hr; - if (!list_empty(&reader->elements)) - { - hr = reader_inc_depth(reader); - if (FAILED(hr)) - return hr; - } - element = reader_alloc_zero(reader, sizeof(*element)); - if (!element) { - hr = E_OUTOFMEMORY; - goto failed; - } - - if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) != S_OK || - (hr = reader_strvaldup(reader, localname, &element->localname)) != S_OK || - (hr = reader_strvaldup(reader, qname, &element->qname)) != S_OK) - { + if (!element) + return E_OUTOFMEMORY; + + if ((hr = reader_strvaldup(reader, prefix, &element->prefix)) == S_OK && + (hr = reader_strvaldup(reader, localname, &element->localname)) == S_OK && + (hr = reader_strvaldup(reader, qname, &element->qname)) == S_OK) + { + list_add_head(&reader->elements, &element->entry); + reader_mark_ns_nodes(reader, element); + reader->is_empty_element = FALSE; + element->position = *position; + } + else reader_free_element(reader, element); - goto failed; - } - - list_add_head(&reader->elements, &element->entry); - reader_mark_ns_nodes(reader, element); - reader->is_empty_element = FALSE; - -failed: - reader_dec_depth(reader); + return hr; } @@ -596,7 +639,6 @@ reader_pop_ns_nodes(reader, element); reader_free_element(reader, element); - reader_dec_depth(reader); /* It was a root element, the rest is expected as Misc */ if (list_empty(&reader->elements)) @@ -654,6 +696,7 @@ buffer->cur = 0; buffer->allocated = initial_len; buffer->written = 0; + buffer->prev_cr = FALSE; return S_OK; } @@ -683,7 +726,7 @@ if (!name) return XmlEncoding_Unknown; min = 0; - max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1; + max = sizeof(xml_encoding_map)/sizeof(xml_encoding_map[0]) - 1; while (min <= max) { @@ -830,10 +873,9 @@ static HRESULT readerinput_detectencoding(xmlreaderinput *readerinput, xml_encoding *enc) { encoded_buffer *buffer = &readerinput->buffer->encoded; - static const WCHAR startW[] = {'<','?'}; - static const WCHAR commentW[] = {'<','!'}; static const char utf8bom[] = {0xef,0xbb,0xbf}; static const char utf16lebom[] = {0xff,0xfe}; + WCHAR *ptrW; *enc = XmlEncoding_Unknown; @@ -841,16 +883,20 @@ { HRESULT hr = readerinput_growraw(readerinput); if (FAILED(hr)) return hr; - if (buffer->written <= 3) return MX_E_INPUTEND; - } - + if (buffer->written < 3) return MX_E_INPUTEND; + } + + ptrW = (WCHAR *)buffer->data; /* try start symbols if we have enough data to do that, input buffer should contain first chunk already */ if (readerinput_is_utf8(readerinput)) *enc = XmlEncoding_UTF8; - else if (!memcmp(buffer->data, startW, sizeof(startW)) || - !memcmp(buffer->data, commentW, sizeof(commentW))) - *enc = XmlEncoding_UTF16; + else if (*ptrW == '<') + { + ptrW++; + if (*ptrW == '?' || *ptrW == '!' || is_namestartchar(*ptrW)) + *enc = XmlEncoding_UTF16; + } /* try with BOM now */ else if (!memcmp(buffer->data, utf8bom, sizeof(utf8bom))) { @@ -916,6 +962,34 @@ buffer->cur = 0; } +static void fixup_buffer_cr(encoded_buffer *buffer, int off) +{ + BOOL prev_cr = buffer->prev_cr; + const WCHAR *src; + WCHAR *dest; + + src = dest = (WCHAR*)buffer->data + off; + while ((const char*)src < buffer->data + buffer->written) + { + if (*src == '\r') + { + *dest++ = '\n'; + src++; + prev_cr = TRUE; + continue; + } + if(prev_cr && *src == '\n') + src++; + else + *dest++ = *src++; + prev_cr = FALSE; + } + + buffer->written = (char*)dest - buffer->data; + buffer->prev_cr = prev_cr; + *dest = 0; +} + /* note that raw buffer content is kept */ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding enc) { @@ -940,15 +1014,18 @@ readerinput_grow(readerinput, len); memcpy(dest->data, src->data + src->cur, len); dest->written += len*sizeof(WCHAR); - return; - } - - dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); - readerinput_grow(readerinput, dest_len); - ptr = (WCHAR*)dest->data; - MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); - ptr[dest_len] = 0; - dest->written += dest_len*sizeof(WCHAR); + } + else + { + dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); + readerinput_grow(readerinput, dest_len); + ptr = (WCHAR*)dest->data; + MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); + ptr[dest_len] = 0; + dest->written += dest_len*sizeof(WCHAR); + } + + fixup_buffer_cr(dest, 0); } /* shrinks parsed data a buffer begins with */ @@ -974,13 +1051,14 @@ encoded_buffer *src = &readerinput->buffer->encoded; encoded_buffer *dest = &readerinput->buffer->utf16; UINT cp = readerinput->buffer->code_page; - int len, dest_len; + int len, dest_len, prev_len; HRESULT hr; WCHAR *ptr; /* get some raw data from stream first */ hr = readerinput_growraw(readerinput); len = readerinput_get_convlen(readerinput); + prev_len = dest->written / sizeof(WCHAR); /* just copy for UTF-16 case */ if (cp == ~0) @@ -988,18 +1066,20 @@ readerinput_grow(readerinput, len); memcpy(dest->data + dest->written, src->data + src->cur, len); dest->written += len*sizeof(WCHAR); - return hr; - } - - dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); - readerinput_grow(readerinput, dest_len); - ptr = (WCHAR*)(dest->data + dest->written); - MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); - ptr[dest_len] = 0; - dest->written += dest_len*sizeof(WCHAR); - /* get rid of processed data */ - readerinput_shrinkraw(readerinput, len); - + } + else + { + dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); + readerinput_grow(readerinput, dest_len); + ptr = (WCHAR*)(dest->data + dest->written); + MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); + ptr[dest_len] = 0; + dest->written += dest_len*sizeof(WCHAR); + /* get rid of processed data */ + readerinput_shrinkraw(readerinput, len); + } + + fixup_buffer_cr(dest, prev_len); return hr; } @@ -1034,16 +1114,29 @@ return 0; } +static void reader_update_position(xmlreader *reader, WCHAR ch) +{ + if (ch == '\r') + reader->position.line_position = 1; + else if (ch == '\n') + { + reader->position.line_number++; + reader->position.line_position = 1; + } + else + reader->position.line_position++; +} + /* moves cursor n WCHARs forward */ static void reader_skipn(xmlreader *reader, int n) { encoded_buffer *buffer = &reader->input->buffer->utf16; - const WCHAR *ptr = reader_get_ptr(reader); - - while (*ptr++ && n--) - { + const WCHAR *ptr; + + while (*(ptr = reader_get_ptr(reader)) && n--) + { + reader_update_position(reader, *ptr); buffer->cur++; - reader->pos++; } } @@ -1055,23 +1148,12 @@ /* [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ static int reader_skipspaces(xmlreader *reader) { - encoded_buffer *buffer = &reader->input->buffer->utf16; const WCHAR *ptr = reader_get_ptr(reader); UINT start = reader_get_cur(reader); while (is_wchar_space(*ptr)) { - if (*ptr == '\r') - reader->pos = 0; - else if (*ptr == '\n') - { - reader->line++; - reader->pos = 0; - } - else - reader->pos++; - - buffer->cur++; + reader_skipn(reader, 1); ptr = reader_get_ptr(reader); } @@ -1120,11 +1202,13 @@ static HRESULT reader_parse_versioninfo(xmlreader *reader) { static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; + struct reader_position position; strval val, name; HRESULT hr; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; + position = reader->position; if (reader_cmp(reader, versionW)) return WC_E_XMLDECL; reader_init_strvalue(reader_get_cur(reader), 7, &name); /* skip 'version' */ @@ -1147,7 +1231,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* ([A-Za-z0-9._] | '-') */ @@ -1194,11 +1278,13 @@ static HRESULT reader_parse_encdecl(xmlreader *reader) { static const WCHAR encodingW[] = {'e','n','c','o','d','i','n','g',0}; + struct reader_position position; strval name, val; HRESULT hr; if (!reader_skipspaces(reader)) return S_FALSE; + position = reader->position; if (reader_cmp(reader, encodingW)) return S_FALSE; name.str = reader_get_ptr(reader); name.start = reader_get_cur(reader); @@ -1223,7 +1309,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) */ @@ -1232,12 +1318,14 @@ static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0}; static const WCHAR yesW[] = {'y','e','s',0}; static const WCHAR noW[] = {'n','o',0}; + struct reader_position position; strval name, val; UINT start; HRESULT hr; if (!reader_skipspaces(reader)) return S_FALSE; + position = reader->position; if (reader_cmp(reader, standaloneW)) return S_FALSE; reader_init_strvalue(reader_get_cur(reader), 10, &name); /* skip 'standalone' */ @@ -1265,7 +1353,7 @@ /* skip "'"|'"' */ reader_skipn(reader, 1); - return reader_add_attr(reader, NULL, &name, &val); + return reader_add_attr(reader, NULL, &name, NULL, &val, &position, 0); } /* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */ @@ -1273,12 +1361,16 @@ { static const WCHAR xmldeclW[] = {'<','?','x','m','l',' ',0}; static const WCHAR declcloseW[] = {'?','>',0}; + struct reader_position position; HRESULT hr; /* check if we have "<?xml " */ - if (reader_cmp(reader, xmldeclW)) return S_FALSE; - - reader_skipn(reader, 5); + if (reader_cmp(reader, xmldeclW)) + return S_FALSE; + + reader_skipn(reader, 2); + position = reader->position; + reader_skipn(reader, 3); hr = reader_parse_versioninfo(reader); if (FAILED(hr)) return hr; @@ -1292,14 +1384,16 @@ return hr; reader_skipspaces(reader); - if (reader_cmp(reader, declcloseW)) return WC_E_XMLDECL; + if (reader_cmp(reader, declcloseW)) + return WC_E_XMLDECL; + + /* skip '?>' */ reader_skipn(reader, 2); - reader_inc_depth(reader); reader->nodetype = XmlNodeType_XmlDeclaration; - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); - reader_set_strvalue(reader, StringValue_Value, &strval_empty); + reader->empty_element.position = position; + reader_set_strvalue(reader, StringValue_LocalName, &strval_xml); + reader_set_strvalue(reader, StringValue_QualifiedName, &strval_xml); return S_OK; } @@ -1325,8 +1419,6 @@ reader->nodetype = XmlNodeType_Comment; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_Comment; - reader_set_strvalue(reader, StringValue_LocalName, NULL); - reader_set_strvalue(reader, StringValue_QualifiedName, NULL); reader_set_strvalue(reader, StringValue_Value, NULL); } @@ -1348,8 +1440,6 @@ /* skip rest of markup '->' */ reader_skipn(reader, 3); - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; @@ -1719,6 +1809,7 @@ { static WCHAR systemW[] = {'S','Y','S','T','E','M',0}; static WCHAR publicW[] = {'P','U','B','L','I','C',0}; + struct reader_position position = reader->position; strval name, sys; HRESULT hr; int cnt; @@ -1735,7 +1826,7 @@ if (FAILED(hr)) return hr; reader_init_cstrvalue(publicW, strlenW(publicW), &name); - hr = reader_add_attr(reader, NULL, &name, &pub); + hr = reader_add_attr(reader, NULL, &name, NULL, &pub, &position, 0); if (FAILED(hr)) return hr; cnt = reader_skipspaces(reader); @@ -1746,7 +1837,7 @@ if (FAILED(hr)) return S_OK; reader_init_cstrvalue(systemW, strlenW(systemW), &name); - hr = reader_add_attr(reader, NULL, &name, &sys); + hr = reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0); if (FAILED(hr)) return hr; return S_OK; @@ -1760,7 +1851,7 @@ if (FAILED(hr)) return hr; reader_init_cstrvalue(systemW, strlenW(systemW), &name); - return reader_add_attr(reader, NULL, &name, &sys); + return reader_add_attr(reader, NULL, &name, NULL, &sys, &position, 0); } return S_FALSE; @@ -1813,7 +1904,7 @@ } /* [11 NS] LocalPart ::= NCName */ -static HRESULT reader_parse_local(xmlreader *reader, strval *local) +static HRESULT reader_parse_local(xmlreader *reader, strval *local, BOOL check_for_separator) { WCHAR *ptr; UINT start; @@ -1834,6 +1925,9 @@ reader_skipn(reader, 1); ptr = reader_get_ptr(reader); } + + if (check_for_separator && *ptr == ':') + return NC_E_QNAMECOLON; if (is_reader_pending(reader)) { @@ -1873,7 +1967,7 @@ if (reader->resume[XmlReadResume_Local]) { - hr = reader_parse_local(reader, local); + hr = reader_parse_local(reader, local, FALSE); if (FAILED(hr)) return hr; reader_init_strvalue(reader->resume[XmlReadResume_Name], @@ -1898,7 +1992,7 @@ /* skip ':' */ reader_skipn(reader, 1); - hr = reader_parse_local(reader, local); + hr = reader_parse_local(reader, local, TRUE); if (FAILED(hr)) return hr; } else @@ -1922,28 +2016,6 @@ reader->resume[XmlReadResume_Local] = 0; return S_OK; -} - -/* Applies normalization rules to a single char, used for attribute values. - - Rules include 2 steps: - - 1) replacing \r\n with a single \n; - 2) replacing all whitespace chars with ' '. - - */ -static void reader_normalize_space(xmlreader *reader, WCHAR *ptr) -{ - encoded_buffer *buffer = &reader->input->buffer->utf16; - - if (!is_wchar_space(*ptr)) return; - - if (*ptr == '\r' && *(ptr+1) == '\n') - { - int len = buffer->written - ((char*)ptr - buffer->data) - 2*sizeof(WCHAR); - memmove(ptr+1, ptr+2, len); - } - *ptr = ' '; } static WCHAR get_predefined_entity(const xmlreader *reader, const strval *name) @@ -2044,8 +2116,12 @@ /* normalize */ if (is_wchar_space(ch)) ch = ' '; - len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR); - memmove(start+1, ptr+1, len); + ptr = reader_get_ptr(reader); + start = reader_get_ptr2(reader, cur); + len = buffer->written - ((char *)ptr - buffer->data); + memmove(start + 1, ptr + 1, len); + + buffer->written -= (reader_get_cur(reader) - cur) * sizeof(WCHAR); buffer->cur = cur + 1; *start = ch; @@ -2068,6 +2144,7 @@ len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR); memmove(start+1, ptr+1, len); buffer->cur = cur + 1; + buffer->written -= (ptr - start) * sizeof(WCHAR); *start = ch; } @@ -2116,7 +2193,8 @@ } else { - reader_normalize_space(reader, ptr); + /* replace all whitespace chars with ' ' */ + if (is_wchar_space(*ptr)) *ptr = ' '; reader_skipn(reader, 1); } ptr = reader_get_ptr(reader); @@ -2131,18 +2209,19 @@ [15 NS] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue */ static HRESULT reader_parse_attribute(xmlreader *reader) { + struct reader_position position = reader->position; strval prefix, local, qname, value; - BOOL ns = FALSE, nsdef = FALSE; + enum attribute_flags flags = 0; HRESULT hr; hr = reader_parse_qname(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; if (strval_eq(reader, &prefix, &strval_xmlns)) - ns = TRUE; + flags |= ATTRIBUTE_NS_DEFINITION; if (strval_eq(reader, &qname, &strval_xmlns)) - ns = nsdef = TRUE; + flags |= ATTRIBUTE_DEFAULT_NS_DEFINITION; hr = reader_parse_eq(reader); if (FAILED(hr)) return hr; @@ -2150,38 +2229,45 @@ hr = reader_parse_attvalue(reader, &value); if (FAILED(hr)) return hr; - if (ns) - reader_push_ns(reader, nsdef ? &strval_xmlns : &local, &value, nsdef); + if (flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) + reader_push_ns(reader, &local, &value, !!(flags & ATTRIBUTE_DEFAULT_NS_DEFINITION)); TRACE("%s=%s\n", debug_strval(reader, &local), debug_strval(reader, &value)); - return reader_add_attr(reader, &prefix, &local, &value); + return reader_add_attr(reader, &prefix, &local, &qname, &value, &position, flags); } /* [12 NS] STag ::= '<' QName (S Attribute)* S? '>' [14 NS] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' */ -static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname, int *empty) -{ +static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname) +{ + struct reader_position position = reader->position; HRESULT hr; hr = reader_parse_qname(reader, prefix, local, qname); if (FAILED(hr)) return hr; - while (1) + for (;;) { static const WCHAR endW[] = {'/','>',0}; reader_skipspaces(reader); /* empty element */ - if ((*empty = !reader_cmp(reader, endW))) - { + if ((reader->is_empty_element = !reader_cmp(reader, endW))) + { + struct element *element = &reader->empty_element; + /* skip '/>' */ reader_skipn(reader, 2); - reader->is_empty_element = TRUE; - reader->empty_element.prefix = *prefix; - reader->empty_element.localname = *local; - reader->empty_element.qname = *qname; - reader_mark_ns_nodes(reader, &reader->empty_element); + + reader_free_strvalued(reader, &element->qname); + reader_free_strvalued(reader, &element->localname); + + element->prefix = *prefix; + reader_strvaldup(reader, qname, &element->qname); + reader_strvaldup(reader, local, &element->localname); + element->position = position; + reader_mark_ns_nodes(reader, element); return S_OK; } @@ -2190,7 +2276,7 @@ { /* skip '>' */ reader_skipn(reader, 1); - return reader_push_element(reader, prefix, local, qname); + return reader_push_element(reader, prefix, local, qname, &position); } hr = reader_parse_attribute(reader); @@ -2219,16 +2305,15 @@ case XmlReadResumeState_STag: { strval qname, prefix, local; - int empty = 0; /* this handles empty elements too */ - hr = reader_parse_stag(reader, &prefix, &local, &qname, &empty); + hr = reader_parse_stag(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; /* FIXME: need to check for defined namespace to reject invalid prefix */ /* if we got empty element and stack is empty go straight to Misc */ - if (empty && list_empty(&reader->elements)) + if (reader->is_empty_element && list_empty(&reader->elements)) reader->instate = XmlReadInState_MiscEnd; else reader->instate = XmlReadInState_Content; @@ -2236,8 +2321,8 @@ reader->nodetype = XmlNodeType_Element; reader->resumestate = XmlReadResumeState_Initial; reader_set_strvalue(reader, StringValue_Prefix, &prefix); - reader_set_strvalue(reader, StringValue_LocalName, &local); reader_set_strvalue(reader, StringValue_QualifiedName, &qname); + reader_set_strvalue(reader, StringValue_Value, &strval_empty); break; } default: @@ -2250,13 +2335,15 @@ /* [13 NS] ETag ::= '</' QName S? '>' */ static HRESULT reader_parse_endtag(xmlreader *reader) { + struct reader_position position; strval prefix, local, qname; - struct element *elem; + struct element *element; HRESULT hr; /* skip '</' */ reader_skipn(reader, 2); + position = reader->position; hr = reader_parse_qname(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; @@ -2269,13 +2356,15 @@ /* Element stack should never be empty at this point, cause we shouldn't get to content parsing if it's empty. */ - elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry); - if (!strval_eq(reader, &elem->qname, &qname)) return WC_E_ELEMENTMATCH; + element = LIST_ENTRY(list_head(&reader->elements), struct element, entry); + if (!strval_eq(reader, &element->qname, &qname)) return WC_E_ELEMENTMATCH; + + /* update position stored for start tag, we won't be using it */ + element->position = position; reader->nodetype = XmlNodeType_EndElement; + reader->is_empty_element = FALSE; reader_set_strvalue(reader, StringValue_Prefix, &prefix); - reader_set_strvalue(reader, StringValue_LocalName, &local); - reader_set_strvalue(reader, StringValue_QualifiedName, &qname); return S_OK; } @@ -2304,8 +2393,6 @@ reader->nodetype = XmlNodeType_CDATA; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_CDATA; - reader_set_strvalue(reader, StringValue_LocalName, NULL); - reader_set_strvalue(reader, StringValue_QualifiedName, NULL); reader_set_strvalue(reader, StringValue_Value, NULL); } @@ -2321,8 +2408,6 @@ reader_skipn(reader, 3); TRACE("%s\n", debug_strval(reader, &value)); - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; @@ -2330,12 +2415,6 @@ } else { - /* Value normalization is not fully implemented, rules are: - - - single '\r' -> '\n'; - - sequence '\r\n' -> '\n', in this case value length changes; - */ - if (*ptr == '\r') *ptr = '\n'; reader_skipn(reader, 1); ptr++; } @@ -2347,6 +2426,7 @@ /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */ static HRESULT reader_parse_chardata(xmlreader *reader) { + struct reader_position position; WCHAR *ptr; UINT start; @@ -2365,11 +2445,10 @@ reader->nodetype = is_wchar_space(*ptr) ? XmlNodeType_Whitespace : XmlNodeType_Text; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_CharData; - reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); - reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, NULL); } + position = reader->position; while (*ptr) { static const WCHAR ampW[] = {'&',0}; @@ -2383,6 +2462,7 @@ { strval value; + reader->empty_element.position = position; reader_init_strvalue(start, reader_get_cur(reader)-start, &value); reader_set_strvalue(reader, StringValue_Value, &value); reader->resume[XmlReadResume_Body] = 0; @@ -2456,15 +2536,32 @@ HRESULT hr; if (!is_reader_pending(reader)) + { + reader->chunk_read_off = 0; reader_clear_attrs(reader); + } /* When moving from EndElement or empty element, pop its own namespace definitions */ - if (nodetype == XmlNodeType_Element && reader->is_empty_element) - reader_pop_ns_nodes(reader, &reader->empty_element); - else if (nodetype == XmlNodeType_EndElement) + switch (nodetype) + { + case XmlNodeType_Attribute: + reader_dec_depth(reader); + /* fallthrough */ + case XmlNodeType_Element: + if (reader->is_empty_element) + reader_pop_ns_nodes(reader, &reader->empty_element); + else if (FAILED(hr = reader_inc_depth(reader))) + return hr; + break; + case XmlNodeType_EndElement: reader_pop_element(reader); - - while (1) + reader_dec_depth(reader); + break; + default: + ; + } + + for (;;) { switch (reader->instate) { @@ -2476,9 +2573,13 @@ hr = readerinput_growraw(reader->input); if (FAILED(hr)) return hr; + reader->position.line_number = 1; + reader->position.line_position = 1; + /* try to detect encoding by BOM or data and set input code page */ hr = readerinput_detectencoding(reader->input, &enc); - TRACE("detected encoding %s, 0x%08x\n", debugstr_w(xml_encoding_map[enc].name), hr); + TRACE("detected encoding %s, 0x%08x\n", enc == XmlEncoding_Unknown ? "(unknown)" : + debugstr_w(xml_encoding_map[enc].name), hr); if (FAILED(hr)) return hr; /* always switch first time cause we have to put something in */ @@ -2529,10 +2630,17 @@ return reader_parse_content(reader); case XmlReadInState_MiscEnd: hr = reader_parse_misc(reader); - if (FAILED(hr)) return hr; - - if (hr == S_FALSE) - reader->instate = XmlReadInState_Eof; + if (hr != S_FALSE) return hr; + + if (*reader_get_ptr(reader)) + { + WARN("found garbage in the end of XML\n"); + return WC_E_SYNTAX; + } + + reader->instate = XmlReadInState_Eof; + reader->state = XmlReadState_EndOfFile; + reader->nodetype = XmlNodeType_None; return hr; case XmlReadInState_Eof: return S_FALSE; @@ -2581,17 +2689,36 @@ struct ns *ns, *ns2; LIST_FOR_EACH_ENTRY_SAFE(ns, ns2, &reader->ns, struct ns, entry) { + list_remove(&ns->entry); reader_free_strvalued(reader, &ns->prefix); reader_free_strvalued(reader, &ns->uri); reader_free(reader, ns); } LIST_FOR_EACH_ENTRY_SAFE(ns, ns2, &reader->nsdef, struct ns, entry) { + list_remove(&ns->entry); reader_free_strvalued(reader, &ns->uri); reader_free(reader, ns); } } +static void reader_reset_parser(xmlreader *reader) +{ + reader->position.line_number = 0; + reader->position.line_position = 0; + + reader_clear_elements(reader); + reader_clear_attrs(reader); + reader_clear_ns(reader); + reader_free_strvalues(reader); + + reader->depth = 0; + reader->nodetype = XmlNodeType_None; + reader->resumestate = XmlReadResumeState_Initial; + memset(reader->resume, 0, sizeof(reader->resume)); + reader->is_empty_element = FALSE; +} + static ULONG WINAPI xmlreader_Release(IXmlReader *iface) { xmlreader *This = impl_from_IXmlReader(iface); @@ -2602,13 +2729,10 @@ if (ref == 0) { IMalloc *imalloc = This->imalloc; + reader_reset_parser(This); if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface); if (This->resolver) IXmlResolver_Release(This->resolver); if (This->mlang) IUnknown_Release(This->mlang); - reader_clear_attrs(This); - reader_clear_ns(This); - reader_clear_elements(This); - reader_free_strvalues(This); reader_free(This, This); if (imalloc) IMalloc_Release(imalloc); } @@ -2631,11 +2755,7 @@ This->input = NULL; } - This->line = This->pos = 0; - reader_clear_elements(This); - This->depth = 0; - This->resumestate = XmlReadResumeState_Initial; - memset(This->resume, 0, sizeof(This->resume)); + reader_reset_parser(This); /* just reset current input */ if (!input) @@ -2676,7 +2796,6 @@ This->state = XmlReadState_Initial; This->instate = XmlReadInState_Initial; } - return hr; } @@ -2705,6 +2824,9 @@ break; case XmlReaderProperty_ReadState: *value = This->state; + break; + case XmlReaderProperty_MaxElementDepth: + *value = This->max_depth; break; default: FIXME("Unimplemented property (%u)\n", property); @@ -2743,7 +2865,7 @@ This->dtdmode = value; break; case XmlReaderProperty_MaxElementDepth: - FIXME("Ignoring MaxElementDepth %ld\n", value); + This->max_depth = value; break; default: FIXME("Unimplemented property (%u)\n", property); @@ -2757,21 +2879,38 @@ { xmlreader *This = impl_from_IXmlReader(iface); XmlNodeType oldtype = This->nodetype; + XmlNodeType type; HRESULT hr; TRACE("(%p)->(%p)\n", This, nodetype); - if (This->state == XmlReadState_Closed) return S_FALSE; - - hr = reader_parse_nextnode(This); - if (oldtype == XmlNodeType_None && This->nodetype != oldtype) - This->state = XmlReadState_Interactive; - if (hr == S_OK) - { - TRACE("node type %s\n", debugstr_nodetype(This->nodetype)); - if (nodetype) - *nodetype = This->nodetype; - } + if (!nodetype) + nodetype = &type; + + switch (This->state) + { + case XmlReadState_Closed: + hr = S_FALSE; + break; + case XmlReadState_Error: + hr = This->error; + break; + default: + hr = reader_parse_nextnode(This); + if (SUCCEEDED(hr) && oldtype == XmlNodeType_None && This->nodetype != oldtype) + This->state = XmlReadState_Interactive; + + if (FAILED(hr)) + { + This->state = XmlReadState_Error; + This->nodetype = XmlNodeType_None; + This->depth = 0; + This->error = hr; + } + } + + TRACE("node type %s\n", debugstr_nodetype(This->nodetype)); + *nodetype = This->nodetype; return hr; } @@ -2794,9 +2933,13 @@ if (!reader->attr_count) return S_FALSE; + if (!reader->attr) + reader_inc_depth(reader); + reader->attr = LIST_ENTRY(list_head(&reader->attrs), struct attribute, entry); + reader->chunk_read_off = 0; reader_set_strvalue(reader, StringValue_Prefix, &reader->attr->prefix); - reader_set_strvalue(reader, StringValue_LocalName, &reader->attr->localname); + reader_set_strvalue(reader, StringValue_QualifiedName, &reader->attr->qname); reader_set_strvalue(reader, StringValue_Value, &reader->attr->value); return S_OK; @@ -2827,8 +2970,9 @@ if (next) { This->attr = LIST_ENTRY(next, struct attribute, entry); + This->chunk_read_off = 0; reader_set_strvalue(This, StringValue_Prefix, &This->attr->prefix); - reader_set_strvalue(This, StringValue_LocalName, &This->attr->localname); + reader_set_strvalue(This, StringValue_QualifiedName, &This->attr->qname); reader_set_strvalue(This, StringValue_Value, &This->attr->value); } @@ -2850,20 +2994,26 @@ TRACE("(%p)\n", This); if (!This->attr_count) return S_FALSE; + + if (This->attr) + reader_dec_depth(This); + This->attr = NULL; /* FIXME: support other node types with 'attributes' like DTD */ if (This->is_empty_element) { - reader_set_strvalue(This, StringValue_LocalName, &This->empty_element.localname); + reader_set_strvalue(This, StringValue_Prefix, &This->empty_element.prefix); reader_set_strvalue(This, StringValue_QualifiedName, &This->empty_element.qname); } else { struct element *element = LIST_ENTRY(list_head(&This->elements), struct element, entry); if (element) { - reader_set_strvalue(This, StringValue_LocalName, &element->localname); + reader_set_strvalue(This, StringValue_Prefix, &element->prefix); reader_set_strvalue(This, StringValue_QualifiedName, &element->qname); } } + This->chunk_read_off = 0; + reader_set_strvalue(This, StringValue_Value, &strval_empty); return S_OK; } @@ -2871,10 +3021,60 @@ static HRESULT WINAPI xmlreader_GetQualifiedName(IXmlReader* iface, LPCWSTR *name, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); + struct attribute *attribute = This->attr; + struct element *element; + UINT length; TRACE("(%p)->(%p %p)\n", This, name, len); - *name = This->strvalues[StringValue_QualifiedName].str; - if (len) *len = This->strvalues[StringValue_QualifiedName].len; + + if (!len) + len = &length; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + *name = emptyW; + *len = 0; + break; + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + if (element->prefix.len) + { + *name = element->qname.str; + *len = element->qname.len; + } + else + { + *name = element->localname.str; + *len = element->localname.len; + } + break; + case XmlNodeType_Attribute: + if (attribute->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION) + { + *name = xmlnsW; + *len = 5; + } else if (attribute->prefix.len) + { + *name = This->strvalues[StringValue_QualifiedName].str; + *len = This->strvalues[StringValue_QualifiedName].len; + } + else + { + *name = attribute->localname.str; + *len = attribute->localname.len; + } + break; + default: + *name = This->strvalues[StringValue_QualifiedName].str; + *len = This->strvalues[StringValue_QualifiedName].len; + break; + } + return S_OK; } @@ -2923,10 +3123,9 @@ '2','0','0','0','/','x','m','l','n','s','/',0}; static const WCHAR xml_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/', 'X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0}; - const strval *local = &This->strvalues[StringValue_LocalName]; /* check for reserved prefixes first */ - if ((strval_eq(This, prefix, &strval_empty) && strval_eq(This, local, &strval_xmlns)) || + if ((strval_eq(This, prefix, &strval_empty) && strval_eq(This, &This->attr->localname, &strval_xmlns)) || strval_eq(This, prefix, &strval_xmlns)) { *uri = xmlns_uriW; @@ -2969,6 +3168,15 @@ } } break; + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_ProcessingInstruction: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *uri = emptyW; + *len = 0; + break; default: FIXME("Unhandled node type %d\n", nodetype); return E_NOTIMPL; @@ -2980,103 +3188,202 @@ static HRESULT WINAPI xmlreader_GetLocalName(IXmlReader* iface, LPCWSTR *name, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); + struct element *element; + UINT length; TRACE("(%p)->(%p %p)\n", This, name, len); - *name = This->strvalues[StringValue_LocalName].str; - if (len) *len = This->strvalues[StringValue_LocalName].len; - return S_OK; -} - -static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, LPCWSTR *prefix, UINT *len) + + if (!len) + len = &length; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Text: + case XmlNodeType_CDATA: + case XmlNodeType_Comment: + case XmlNodeType_Whitespace: + *name = emptyW; + *len = 0; + break; + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *name = element->localname.str; + *len = element->localname.len; + break; + case XmlNodeType_Attribute: + if (This->attr->flags & ATTRIBUTE_DEFAULT_NS_DEFINITION) + { + *name = xmlnsW; + *len = 5; + } + else if (This->attr->flags & ATTRIBUTE_NS_DEFINITION) + { + const struct ns *ns = reader_lookup_ns(This, &This->attr->localname); + *name = ns->prefix.str; + *len = ns->prefix.len; + } + else + { + *name = This->attr->localname.str; + *len = This->attr->localname.len; + } + break; + default: + *name = This->strvalues[StringValue_LocalName].str; + *len = This->strvalues[StringValue_LocalName].len; + break; + } + + return S_OK; +} + +static HRESULT WINAPI xmlreader_GetPrefix(IXmlReader* iface, const WCHAR **ret, UINT *len) { xmlreader *This = impl_from_IXmlReader(iface); - - TRACE("(%p)->(%p %p)\n", This, prefix, len); - *prefix = This->strvalues[StringValue_Prefix].str; - if (len) *len = This->strvalues[StringValue_Prefix].len; - return S_OK; -} - -static BOOL is_namespace_definition(xmlreader *reader) -{ - const strval *local = &reader->strvalues[StringValue_LocalName]; - const strval *prefix = &reader->strvalues[StringValue_Prefix]; - - if (reader_get_nodetype(reader) != XmlNodeType_Attribute) - return FALSE; - - return ((strval_eq(reader, prefix, &strval_empty) && strval_eq(reader, local, &strval_xmlns)) || - strval_eq(reader, prefix, &strval_xmlns)); -} - -static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len) -{ - xmlreader *reader = impl_from_IXmlReader(iface); - strval *val = &reader->strvalues[StringValue_Value]; - - TRACE("(%p)->(%p %p)\n", reader, value, len); - - *value = NULL; - - if ((reader->nodetype == XmlNodeType_Comment && !val->str) || is_reader_pending(reader)) - { - XmlNodeType type; - HRESULT hr; - - hr = IXmlReader_Read(iface, &type); - if (FAILED(hr)) return hr; - - /* return if still pending, partially read values are not reported */ - if (is_reader_pending(reader)) return E_PENDING; - } - - if (!val->str) + XmlNodeType nodetype; + UINT length; + + TRACE("(%p)->(%p %p)\n", This, ret, len); + + if (!len) + len = &length; + + *ret = emptyW; + *len = 0; + + switch ((nodetype = reader_get_nodetype(This))) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + case XmlNodeType_Attribute: + { + const strval *prefix = &This->strvalues[StringValue_Prefix]; + struct ns *ns; + + if (strval_eq(This, prefix, &strval_xml)) + { + *ret = xmlW; + *len = 3; + } + else if (strval_eq(This, prefix, &strval_xmlns)) + { + *ret = xmlnsW; + *len = 5; + } + else if ((ns = reader_lookup_ns(This, prefix))) + { + *ret = ns->prefix.str; + *len = ns->prefix.len; + } + + break; + } + default: + ; + } + + return S_OK; +} + +static const strval *reader_get_value(xmlreader *reader, BOOL ensure_allocated) +{ + strval *val; + + switch (reader_get_nodetype(reader)) + { + case XmlNodeType_XmlDeclaration: + case XmlNodeType_EndElement: + case XmlNodeType_None: + return &strval_empty; + case XmlNodeType_Attribute: + /* For namespace definition attributes return values from namespace list */ + if (reader->attr->flags & (ATTRIBUTE_NS_DEFINITION | ATTRIBUTE_DEFAULT_NS_DEFINITION)) + { + struct ns *ns; + + if (!(ns = reader_lookup_ns(reader, &reader->attr->localname))) + ns = reader_lookup_nsdef(reader); + + return &ns->uri; + } + return &reader->attr->value; + default: + break; + } + + val = &reader->strvalues[StringValue_Value]; + if (!val->str && ensure_allocated) { WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); - if (!ptr) return E_OUTOFMEMORY; + if (!ptr) return NULL; memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); ptr[val->len] = 0; val->str = ptr; } - /* For namespace definition attributes return values from namespace list */ - if (is_namespace_definition(reader)) { - const strval *local = &reader->strvalues[StringValue_LocalName]; - struct ns *ns; - - ns = reader_lookup_ns(reader, local); - if (!ns) - ns = reader_lookup_nsdef(reader); - - val = &ns->uri; - } - - *value = val->str; - if (len) *len = val->len; + return val; +} + +static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, UINT *len) +{ + xmlreader *reader = impl_from_IXmlReader(iface); + const strval *val = &reader->strvalues[StringValue_Value]; + UINT off; + + TRACE("(%p)->(%p %p)\n", reader, value, len); + + *value = NULL; + + if ((reader->nodetype == XmlNodeType_Comment && !val->str && !val->len) || is_reader_pending(reader)) + { + XmlNodeType type; + HRESULT hr; + + hr = IXmlReader_Read(iface, &type); + if (FAILED(hr)) return hr; + + /* return if still pending, partially read values are not reported */ + if (is_reader_pending(reader)) return E_PENDING; + } + + val = reader_get_value(reader, TRUE); + if (!val) + return E_OUTOFMEMORY; + + off = abs(reader->chunk_read_off); + assert(off <= val->len); + *value = val->str + off; + if (len) *len = val->len - off; + reader->chunk_read_off = -off; return S_OK; } static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, WCHAR *buffer, UINT chunk_size, UINT *read) { xmlreader *reader = impl_from_IXmlReader(iface); - strval *val = &reader->strvalues[StringValue_Value]; - UINT len; + const strval *val; + UINT len = 0; TRACE("(%p)->(%p %u %p)\n", reader, buffer, chunk_size, read); - /* Value is already allocated, chunked reads are not possible. */ - if (val->str) return S_FALSE; - - if (val->len) - { - len = min(chunk_size, val->len); - memcpy(buffer, reader_get_ptr2(reader, val->start), len); - val->start += len; - val->len -= len; - if (read) *read = len; - } - - return S_OK; + val = reader_get_value(reader, FALSE); + + /* If value is already read by GetValue, chunk_read_off is negative and chunked reads are not possible. */ + if (reader->chunk_read_off >= 0) + { + assert(reader->chunk_read_off <= val->len); + len = min(val->len - reader->chunk_read_off, chunk_size); + } + if (read) *read = len; + + if (len) + { + memcpy(buffer, reader_get_strptr(reader, val) + reader->chunk_read_off, len*sizeof(WCHAR)); + reader->chunk_read_off += len; + } + + return len || !chunk_size ? S_OK : S_FALSE; } static HRESULT WINAPI xmlreader_GetBaseUri(IXmlReader* iface, @@ -3102,30 +3409,68 @@ return (reader_get_nodetype(This) == XmlNodeType_Element) ? This->is_empty_element : FALSE; } -static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *lineNumber) +static HRESULT WINAPI xmlreader_GetLineNumber(IXmlReader* iface, UINT *line_number) { xmlreader *This = impl_from_IXmlReader(iface); - - TRACE("(%p %p)\n", This, lineNumber); - - if (!lineNumber) return E_INVALIDARG; - - *lineNumber = This->line; - - return S_OK; -} - -static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *linePosition) + const struct element *element; + + TRACE("(%p %p)\n", This, line_number); + + if (!line_number) + return E_INVALIDARG; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *line_number = element->position.line_number; + break; + case XmlNodeType_Attribute: + *line_number = This->attr->position.line_number; + break; + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *line_number = This->empty_element.position.line_number; + break; + default: + *line_number = This->position.line_number; + break; + } + + return This->state == XmlReadState_Closed ? S_FALSE : S_OK; +} + +static HRESULT WINAPI xmlreader_GetLinePosition(IXmlReader* iface, UINT *line_position) { xmlreader *This = impl_from_IXmlReader(iface); - - TRACE("(%p %p)\n", This, linePosition); - - if (!linePosition) return E_INVALIDARG; - - *linePosition = This->pos; - - return S_OK; + const struct element *element; + + TRACE("(%p %p)\n", This, line_position); + + if (!line_position) + return E_INVALIDARG; + + switch (reader_get_nodetype(This)) + { + case XmlNodeType_Element: + case XmlNodeType_EndElement: + element = reader_get_element(This); + *line_position = element->position.line_position; + break; + case XmlNodeType_Attribute: + *line_position = This->attr->position.line_position; + break; + case XmlNodeType_Whitespace: + case XmlNodeType_XmlDeclaration: + *line_position = This->empty_element.position.line_position; + break; + default: + *line_position = This->position.line_position; + break; + } + + return This->state == XmlReadState_Closed ? S_FALSE : S_OK; } static HRESULT WINAPI xmlreader_GetAttributeCount(IXmlReader* iface, UINT *count) @@ -3150,8 +3495,9 @@ static BOOL WINAPI xmlreader_IsEOF(IXmlReader* iface) { - FIXME("(%p): stub\n", iface); - return FALSE; + xmlreader *This = impl_from_IXmlReader(iface); + TRACE("(%p)\n", iface); + return This->state == XmlReadState_EndOfFile; } static const struct IXmlReaderVtbl xmlreader_vtbl = @@ -3247,54 +3593,44 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc) { xmlreader *reader; + HRESULT hr; int i; TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc); - - if (!IsEqualGUID(riid, &IID_IXmlReader)) - { - ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid)); - return E_FAIL; - } if (imalloc) reader = IMalloc_Alloc(imalloc, sizeof(*reader)); else reader = heap_alloc(sizeof(*reader)); - if(!reader) return E_OUTOFMEMORY; - + if (!reader) + return E_OUTOFMEMORY; + + memset(reader, 0, sizeof(*reader)); reader->IXmlReader_iface.lpVtbl = &xmlreader_vtbl; reader->ref = 1; - reader->input = NULL; reader->state = XmlReadState_Closed; reader->instate = XmlReadInState_Initial; reader->resumestate = XmlReadResumeState_Initial; reader->dtdmode = DtdProcessing_Prohibit; - reader->resolver = NULL; - reader->mlang = NULL; - reader->line = reader->pos = 0; reader->imalloc = imalloc; if (imalloc) IMalloc_AddRef(imalloc); reader->nodetype = XmlNodeType_None; list_init(&reader->attrs); - reader->attr_count = 0; - reader->attr = NULL; list_init(&reader->nsdef); list_init(&reader->ns); list_init(&reader->elements); - reader->depth = 0; reader->max_depth = 256; - reader->is_empty_element = FALSE; - memset(reader->resume, 0, sizeof(reader->resume)); - + + reader->chunk_read_off = 0; for (i = 0; i < StringValue_Last; i++) reader->strvalues[i] = strval_empty; - *obj = &reader->IXmlReader_iface; - - TRACE("returning iface %p\n", *obj); - - return S_OK; + hr = IXmlReader_QueryInterface(&reader->IXmlReader_iface, riid, obj); + IXmlReader_Release(&reader->IXmlReader_iface); + + TRACE("returning iface %p, hr %#x\n", *obj, hr); + + return hr; } HRESULT WINAPI CreateXmlReaderInputWithEncodingName(IUnknown *stream, Modified: trunk/reactos/dll/win32/xmllite/writer.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/xmllite/writer.c…
============================================================================== --- trunk/reactos/dll/win32/xmllite/writer.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/xmllite/writer.c [iso-8859-1] Sun Jun 4 01:49:43 2017 @@ -63,6 +63,7 @@ ISequentialStream *stream; IMalloc *imalloc; xml_encoding encoding; + WCHAR *encoding_name; /* exactly as specified on output creation */ struct output_buffer buffer; } xmlwriteroutput; @@ -363,6 +364,14 @@ return S_OK; } +static const WCHAR *get_output_encoding_name(xmlwriteroutput *output) +{ + if (output->encoding_name) + return output->encoding_name; + + return get_encoding_name(output->encoding); +} + static HRESULT write_xmldecl(xmlwriter *writer, XmlStandalone standalone) { static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"'}; @@ -377,7 +386,7 @@ /* encoding */ write_output_buffer(writer->output, encodingW, ARRAY_SIZE(encodingW)); - write_output_buffer_quoted(writer->output, get_encoding_name(writer->output->encoding), -1); + write_output_buffer_quoted(writer->output, get_output_encoding_name(writer->output), -1); /* standalone */ if (standalone == XmlStandalone_Omit) @@ -439,10 +448,16 @@ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); - if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_IXmlWriter)) + if (IsEqualGUID(riid, &IID_IXmlWriter) || + IsEqualGUID(riid, &IID_IUnknown)) { *ppvObject = iface; + } + else + { + FIXME("interface %s is not supported\n", debugstr_guid(riid)); + *ppvObject = NULL; + return E_NOINTERFACE; } IXmlWriter_AddRef(iface); @@ -463,7 +478,7 @@ xmlwriter *This = impl_from_IXmlWriter(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p)->>(%u)\n", This, ref); + TRACE("(%p)->(%u)\n", This, ref); if (ref == 0) { struct element *element, *element2; @@ -1193,16 +1208,49 @@ return S_OK; } -static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, LPCWSTR pwszText) -{ - xmlwriter *This = impl_from_IXmlWriter(iface); - - FIXME("%p %s\n", This, wine_dbgstr_w(pwszText)); - - switch (This->state) - { - case XmlWriterState_Initial: - return E_UNEXPECTED; +static void write_escaped_string(xmlwriter *writer, const WCHAR *string) +{ + static const WCHAR ampW[] = {'&','a','m','p',';'}; + static const WCHAR ltW[] = {'&','l','t',';'}; + static const WCHAR gtW[] = {'&','g','t',';'}; + + while (*string) + { + switch (*string) + { + case '<': + write_output_buffer(writer->output, ltW, ARRAY_SIZE(ltW)); + break; + case '&': + write_output_buffer(writer->output, ampW, ARRAY_SIZE(ampW)); + break; + case '>': + write_output_buffer(writer->output, gtW, ARRAY_SIZE(gtW)); + break; + default: + write_output_buffer(writer->output, string, 1); + } + + string++; + } +} + +static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, const WCHAR *string) +{ + xmlwriter *This = impl_from_IXmlWriter(iface); + + TRACE("%p %s\n", This, debugstr_w(string)); + + if (!string) + return S_OK; + + switch (This->state) + { + case XmlWriterState_Initial: + return E_UNEXPECTED; + case XmlWriterState_ElemStarted: + writer_close_starttag(This); + break; case XmlWriterState_Ready: case XmlWriterState_DocClosed: This->state = XmlWriterState_DocClosed; @@ -1211,7 +1259,8 @@ ; } - return E_NOTIMPL; + write_escaped_string(This, string); + return S_OK; } static HRESULT WINAPI xmlwriter_WriteSurrogateCharEntity(IXmlWriter *iface, WCHAR wchLow, WCHAR wchHigh) @@ -1322,6 +1371,7 @@ if (This->output) IUnknown_Release(This->output); if (This->stream) ISequentialStream_Release(This->stream); free_output_buffer(This); + writeroutput_free(This, This->encoding_name); writeroutput_free(This, This); if (imalloc) IMalloc_Release(imalloc); } @@ -1339,14 +1389,9 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc) { xmlwriter *writer; + HRESULT hr; TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid), obj, imalloc); - - if (!IsEqualGUID(riid, &IID_IXmlWriter)) - { - ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid)); - return E_FAIL; - } if (imalloc) writer = IMalloc_Alloc(imalloc, sizeof(*writer)); @@ -1369,15 +1414,16 @@ writer->starttagopen = FALSE; list_init(&writer->elements); - *obj = &writer->IXmlWriter_iface; - - TRACE("returning iface %p\n", *obj); - - return S_OK; -} - -static HRESULT create_writer(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding, - IXmlWriterOutput **output) + hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj); + IXmlWriter_Release(&writer->IXmlWriter_iface); + + TRACE("returning iface %p, hr %#x\n", *obj, hr); + + return hr; +} + +static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding, + const WCHAR *encoding_name, IXmlWriterOutput **output) { xmlwriteroutput *writeroutput; HRESULT hr; @@ -1388,12 +1434,14 @@ writeroutput = IMalloc_Alloc(imalloc, sizeof(*writeroutput)); else writeroutput = heap_alloc(sizeof(*writeroutput)); - if(!writeroutput) return E_OUTOFMEMORY; + if (!writeroutput) + return E_OUTOFMEMORY; writeroutput->IXmlWriterOutput_iface.lpVtbl = &xmlwriteroutputvtbl; writeroutput->ref = 1; writeroutput->imalloc = imalloc; - if (imalloc) IMalloc_AddRef(imalloc); + if (imalloc) + IMalloc_AddRef(imalloc); writeroutput->encoding = encoding; writeroutput->stream = NULL; hr = init_output_buffer(writeroutput); @@ -1402,6 +1450,14 @@ return hr; } + if (encoding_name) { + unsigned int size = (strlenW(encoding_name) + 1) * sizeof(WCHAR); + writeroutput->encoding_name = writeroutput_alloc(writeroutput, size); + memcpy(writeroutput->encoding_name, encoding_name, size); + } + else + writeroutput->encoding_name = NULL; + IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output); *output = &writeroutput->IXmlWriterOutput_iface; @@ -1424,7 +1480,7 @@ if (!stream || !output) return E_INVALIDARG; xml_enc = parse_encoding_name(encoding ? encoding : utf8W, -1); - return create_writer(stream, imalloc, xml_enc, output); + return create_writer_output(stream, imalloc, xml_enc, encoding, output); } HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream, @@ -1439,5 +1495,5 @@ if (!stream || !output) return E_INVALIDARG; xml_enc = get_encoding_from_codepage(codepage); - return create_writer(stream, imalloc, xml_enc, output); -} + return create_writer_output(stream, imalloc, xml_enc, NULL, output); +} Modified: trunk/reactos/dll/win32/xmllite/xmllite.spec URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/xmllite/xmllite.…
============================================================================== --- trunk/reactos/dll/win32/xmllite/xmllite.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/xmllite/xmllite.spec [iso-8859-1] Sun Jun 4 01:49:43 2017 @@ -1,6 +1,6 @@ @ stdcall CreateXmlReader(ptr ptr ptr) @ stub CreateXmlReaderInputWithEncodingCodePage -@ stdcall CreateXmlReaderInputWithEncodingName(ptr ptr ptr long ptr ptr) +@ stdcall CreateXmlReaderInputWithEncodingName(ptr ptr wstr long wstr ptr) @ stdcall CreateXmlWriter(ptr ptr ptr) @ stdcall CreateXmlWriterOutputWithEncodingCodePage(ptr ptr long ptr) @ stdcall CreateXmlWriterOutputWithEncodingName(ptr ptr wstr ptr) Modified: trunk/reactos/dll/win32/xmllite/xmllite_private.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/xmllite/xmllite_…
============================================================================== --- trunk/reactos/dll/win32/xmllite/xmllite_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/xmllite/xmllite_private.h [iso-8859-1] Sun Jun 4 01:49:43 2017 @@ -40,14 +40,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(xmllite); /* memory allocation functions */ -static inline void *heap_alloc(size_t len) + +static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) { - return HeapAlloc(GetProcessHeap(), 0, len); + return HeapAlloc(GetProcessHeap(), 0, size); } -static inline void *heap_realloc(void *mem, size_t len) +static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size) { - return HeapReAlloc(GetProcessHeap(), 0, mem, len); + return HeapReAlloc(GetProcessHeap(), 0, mem, size); } static inline BOOL heap_free(void *mem) @@ -81,6 +82,7 @@ typedef enum { + XmlEncoding_USASCII, XmlEncoding_UTF16, XmlEncoding_UTF8, XmlEncoding_Unknown Modified: trunk/reactos/media/doc/README.WINE URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Jun 4 01:49:43 2017 @@ -218,7 +218,7 @@ reactos/dll/win32/xinput1_2 # Synced to WineStaging-1.9.11 reactos/dll/win32/xinput1_3 # Synced to WineStaging-2.2 reactos/dll/win32/xinput9_1_0 # Synced to WineStaging-1.9.11 -reactos/dll/win32/xmllite # Synced to WineStaging-2.2 +reactos/dll/win32/xmllite # Synced to WineStaging-2.9 reactos/dll/cpl/inetcpl # Synced to WineStaging-1.9.11
7 years, 6 months
1
0
0
0
← Newer
1
...
35
36
37
38
39
40
41
...
53
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Results per page:
10
25
50
100
200