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
December 2019
----- 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
18 participants
225 discussions
Start a n
N
ew thread
[reactos] 01/01: [WINHTTP_WINETEST] Sync with Wine Staging 4.18. CORE-16441
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=412bce85f2833c30750d7…
commit 412bce85f2833c30750d7bf0129185ffbfd40f84 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Dec 7 13:06:11 2019 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Dec 7 13:06:11 2019 +0100 [WINHTTP_WINETEST] Sync with Wine Staging 4.18. CORE-16441 --- modules/rostests/winetests/winhttp/notification.c | 27 +- modules/rostests/winetests/winhttp/url.c | 111 +++++- modules/rostests/winetests/winhttp/winhttp.c | 466 +++++++++++++++++++--- 3 files changed, 536 insertions(+), 68 deletions(-) diff --git a/modules/rostests/winetests/winhttp/notification.c b/modules/rostests/winetests/winhttp/notification.c index 494d474df46..75bfc648808 100644 --- a/modules/rostests/winetests/winhttp/notification.c +++ b/modules/rostests/winetests/winhttp/notification.c @@ -187,7 +187,7 @@ static void test_connection_cache( void ) struct info info, *context = &info; info.test = cache_test; - info.count = sizeof(cache_test) / sizeof(cache_test[0]); + info.count = ARRAY_SIZE( cache_test ); info.index = 0; info.wait = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -427,7 +427,7 @@ static void test_redirect( void ) struct info info, *context = &info; info.test = redirect_test; - info.count = sizeof(redirect_test) / sizeof(redirect_test[0]); + info.count = ARRAY_SIZE( redirect_test ); info.index = 0; info.wait = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -508,7 +508,7 @@ static void test_async( void ) char buffer[1024]; info.test = async_test; - info.count = sizeof(async_test) / sizeof(async_test[0]); + info.count = ARRAY_SIZE( async_test ); info.index = 0; info.wait = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -779,12 +779,12 @@ static void open_async_request(int port, struct test_request *req, struct info * if (reuse_connection) { info->test = reuse_socket_request_test; - info->count = sizeof(reuse_socket_request_test) / sizeof(reuse_socket_request_test[0]); + info->count = ARRAY_SIZE( reuse_socket_request_test ); } else { info->test = open_socket_request_test; - info->count = sizeof(open_socket_request_test) / sizeof(open_socket_request_test[0]); + info->count = ARRAY_SIZE( open_socket_request_test ); } req->session = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC ); @@ -830,7 +830,7 @@ static void server_send_reply(struct test_request *req, struct info *info, const WaitForSingleObject( info->wait, INFINITE ); info->test = server_reply_test; - info->count = sizeof(server_reply_test) / sizeof(server_reply_test[0]); + info->count = ARRAY_SIZE( server_reply_test ); info->index = 0; setup_test( info, winhttp_send_request, __LINE__ ); ret = WinHttpReceiveResponse( req->request, NULL ); @@ -879,12 +879,12 @@ static void close_request(struct test_request *req, struct info *info, BOOL allo if (allow_closing_connection) { info->test = close_allow_connection_close_request_test; - info->count = sizeof(close_allow_connection_close_request_test)/sizeof(*close_allow_connection_close_request_test); + info->count = ARRAY_SIZE( close_allow_connection_close_request_test ); } else { info->test = close_request_test; - info->count = sizeof(close_request_test)/sizeof(*close_request_test); + info->count = ARRAY_SIZE( close_request_test ); } info->index = 0; setup_test( info, winhttp_close_handle, __LINE__ ); @@ -920,25 +920,24 @@ static const struct notification read_allow_close_test[] = static void _read_request_data(struct test_request *req, struct info *info, const char *expected_data, BOOL closing_connection, unsigned line) { char buffer[1024]; - DWORD read, len; + DWORD len; BOOL ret; if (closing_connection) { info->test = read_allow_close_test; - info->count = sizeof(read_allow_close_test)/sizeof(*read_allow_close_test); + info->count = ARRAY_SIZE( read_allow_close_test ); } else { info->test = read_test; - info->count = sizeof(read_test)/sizeof(*read_test); + info->count = ARRAY_SIZE( read_test ); } info->index = 0; setup_test( info, winhttp_read_data, line ); memset(buffer, '?', sizeof(buffer)); - read = 0xdeadbeef; - ret = WinHttpReadData( req->request, buffer, sizeof(buffer), &read ); + ret = WinHttpReadData( req->request, buffer, sizeof(buffer), NULL ); ok(ret, "failed to read data %u\n", GetLastError()); WaitForSingleObject( info->wait, INFINITE ); @@ -1024,7 +1023,7 @@ START_TEST (notification) si.event = CreateEventW( NULL, 0, 0, NULL ); si.port = 7533; - thread = CreateThread( NULL, 0, server_thread, (LPVOID)&si, 0, NULL ); + thread = CreateThread( NULL, 0, server_thread, &si, 0, NULL ); ok(thread != NULL, "failed to create thread %u\n", GetLastError()); server_socket_available = CreateEventW( NULL, 0, 0, NULL ); diff --git a/modules/rostests/winetests/winhttp/url.c b/modules/rostests/winetests/winhttp/url.c index 6bde1de70e4..37a6e4a10b4 100644 --- a/modules/rostests/winetests/winhttp/url.c +++ b/modules/rostests/winetests/winhttp/url.c @@ -34,6 +34,9 @@ static WCHAR password[] = {'p','a','s','s','w','o','r','d',0}; static WCHAR about[] = {'/','s','i','t','e','/','a','b','o','u','t',0}; static WCHAR query[] = {'?','q','u','e','r','y',0}; static WCHAR escape[] = {' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`','{','|','}','~',0}; +static WCHAR escape2[] = {'\r',0x1f,' ','\n',0x7f,'\r','\n',0}; +static WCHAR escape3[] = {'?','t','e','x','t','=',0xfb00,0}; +static WCHAR escape4[] = {'/','t','e','x','t','=',0xfb00,0}; static const WCHAR url1[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d', @@ -72,6 +75,16 @@ static const WCHAR url14[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i static const WCHAR url15[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','6','5','5','3','6',0}; static const WCHAR url16[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','0',0}; static const WCHAR url17[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':',0}; +static const WCHAR url18[] = + {'h','t','t','p',':','/','/','%','0','D','%','1','F','%','2','0','%','0','A','%','7','F','%','0','D','%','0','A',0}; +static const WCHAR url19[] = + {'h','t','t','p',':','/','/','?','t','e','x','t','=',0xfb00,0}; +static const WCHAR url20[] = + {'h','t','t','p',':','/','/','/','t','e','x','t','=',0xfb00,0}; +static const WCHAR url21[] = + {'h','t','t','p','s',':','/','/','n','b','a','2','k','1','9','-','w','s','.','2','k','s','p','o','r','t','s','.','c','o','m',':','1','9','1','3','3', + '/','n','b','a','/','v','4','/','A','c','c','o','u','n','t','s','/','g','e','t','_','a','c','c','o','u','n','t','?','x','=','3','7','8','9','5','2', + '6','7','7','5','2','6','5','6','6','3','8','7','6',0}; static const WCHAR url_k1[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d', @@ -301,7 +314,87 @@ static void WinHttpCreateUrl_test( void ) ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); ok( ret, "expected success\n" ); ok( len == 113, "expected len 113 got %u\n", len ); - ok( !lstrcmpW( url, url7 ), "url doesn't match\n" ); + ok( !lstrcmpW( url, url7 ), "url doesn't match %s\n", wine_dbgstr_w(url) ); + + /* escape extra info */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszExtraInfo = escape2; + uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + ok( ret, "expected success\n" ); + ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len ); + ok( !lstrcmpW( url, url18 ), "url doesn't match\n" ); + + /* extra info with Unicode characters */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszExtraInfo = escape3; + uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo ); + url[0] = 0; + len = 256; + SetLastError( 0xdeadbeef ); + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + err = GetLastError(); + ok( !ret, "expected failure\n" ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + /* extra info with Unicode characters, no ICU_ESCAPE */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszExtraInfo = escape3; + uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, 0, url, &len ); + ok( ret || broken(!ret) /* < win7 */, "expected success\n" ); + if (ret) + { + ok( len == lstrlenW(url19), "expected len %u got %u\n", lstrlenW(url19), len ); + ok( !lstrcmpW( url, url19 ), "url doesn't match %s\n", wine_dbgstr_w(url) ); + } + + /* escape path */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszUrlPath = escape2; + uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + ok( ret, "expected success\n" ); + ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len ); + ok( !lstrcmpW( url, url18 ), "url doesn't match\n" ); + + /* path with Unicode characters */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszUrlPath = escape4; + uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath ); + url[0] = 0; + len = 256; + SetLastError( 0xdeadbeef ); + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + err = GetLastError(); + ok( !ret, "expected failure\n" ); + ok( err == ERROR_INVALID_PARAMETER, "got %u\n", err ); + + /* path with Unicode characters, no ICU_ESCAPE */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszUrlPath = escape4; + uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, 0, url, &len ); + ok( ret || broken(!ret) /* < win7 */, "expected success\n" ); + if (ret) + { + ok( len == lstrlenW(url20), "expected len %u got %u\n", lstrlenW(url20), len ); + ok( !lstrcmpW( url, url20 ), "url doesn't match %s\n", wine_dbgstr_w(url) ); + } /* NULL lpszScheme, 0 nScheme and nPort */ fill_url_components( &uc ); @@ -339,7 +432,7 @@ static void WinHttpCrackUrl_test( void ) static const WCHAR pathW[] = {'/','p','a','t','h','%','2','0','w','i','t','h','%','2','0','s','p','a','c','e','s',0}; URL_COMPONENTSW uc; - WCHAR scheme[20], user[20], pass[20], host[20], path[80], extra[40]; + WCHAR scheme[20], user[20], pass[20], host[40], path[80], extra[40]; DWORD error; BOOL ret; @@ -667,6 +760,7 @@ static void WinHttpCrackUrl_test( void ) ok( ret, "WinHttpCrackUrl failed le=%u\n", GetLastError() ); ok( !lstrcmpW( uc.lpszHostName, hostnameW ), "unexpected host name\n" ); ok( !lstrcmpW( uc.lpszUrlPath, pathW ), "unexpected path\n" ); + ok( uc.dwUrlPathLength == lstrlenW(pathW), "got %u\n", uc.dwUrlPathLength ); uc.dwStructSize = sizeof(uc); uc.lpszScheme = NULL; @@ -753,6 +847,19 @@ static void WinHttpCrackUrl_test( void ) ret = WinHttpCrackUrl( url17, 0, 0, &uc ); ok( ret, "got %u\n", GetLastError() ); todo_wine ok( uc.nPort == 80, "got %u\n", uc.nPort ); + + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszScheme = scheme; + uc.dwSchemeLength = ARRAY_SIZE(scheme); + uc.lpszHostName = host; + uc.dwHostNameLength = ARRAY_SIZE(host); + uc.lpszUrlPath = path; + uc.dwUrlPathLength = ARRAY_SIZE(path); + ret = WinHttpCrackUrl( url21, 0, 0, &uc ); + ok( ret, "got %u\n", GetLastError() ); + ok( !lstrcmpW( uc.lpszUrlPath, url21 + 37 ), "unexpected path %s\n", wine_dbgstr_w(uc.lpszUrlPath) ); + ok( uc.dwUrlPathLength == 50, "unexpected length %u\n", uc.dwUrlPathLength ); } START_TEST(url) diff --git a/modules/rostests/winetests/winhttp/winhttp.c b/modules/rostests/winetests/winhttp/winhttp.c index fb7bf8907b8..7ed8a527fca 100644 --- a/modules/rostests/winetests/winhttp/winhttp.c +++ b/modules/rostests/winetests/winhttp/winhttp.c @@ -33,6 +33,7 @@ #include <httprequestid.h> #include "wine/test.h" +#include "wine/heap.h" DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); @@ -42,6 +43,22 @@ static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q', static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0}; static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0}; +static WCHAR *a2w(const char *str) +{ + int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + WCHAR *ret = heap_alloc(len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + return ret; +} + +static int strcmp_wa(const WCHAR *str1, const char *stra) +{ + WCHAR *str2 = a2w(stra); + int r = lstrcmpW(str1, str2); + heap_free(str2); + return r; +} + static BOOL proxy_active(void) { WINHTTP_PROXY_INFO proxy_info; @@ -64,7 +81,7 @@ static BOOL proxy_active(void) return active; } -static void test_QueryOption(void) +static void test_WinHttpQueryOption(void) { BOOL ret; HINTERNET session, request, connection; @@ -201,6 +218,42 @@ static void test_QueryOption(void) ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + feature = 0xdeadbeef; + size = sizeof(feature); + SetLastError(0xdeadbeef); + ret = WinHttpQueryOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, &size); + ok(!ret, "should fail to query enabled features for a request\n"); + ok(feature == 0xdeadbeef, "expect feature 0xdeadbeef, got %u\n", feature); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + feature = WINHTTP_ENABLE_SSL_REVOCATION; + SetLastError(0xdeadbeef); + ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, 0, sizeof(feature)); + ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, 0); + ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature)); + ok(ret, "failed to set feature\n"); + ok(GetLastError() == NO_ERROR || broken(GetLastError() == 0xdeadbeef), /* Doesn't set error code on Vista or older */ + "expected NO_ERROR, got %u\n", GetLastError()); + + feature = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = WinHttpSetOption(request, WINHTTP_OPTION_ENABLE_FEATURE, &feature, sizeof(feature)); + ok(!ret, "should fail to enable WINHTTP_ENABLE_SSL_REVOCATION with invalid parameters\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); + + feature = 6; + size = sizeof(feature); + ret = WinHttpSetOption(request, WINHTTP_OPTION_CONNECT_RETRIES, &feature, sizeof(feature)); + ok(ret, "failed to set WINHTTP_OPTION_CONNECT_RETRIES %u\n", GetLastError()); + SetLastError(0xdeadbeef); ret = WinHttpCloseHandle(request); ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError()); @@ -214,7 +267,7 @@ done: ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError()); } -static void test_OpenRequest (void) +static void test_WinHttpOpenRequest (void) { BOOL ret; HINTERNET session, request, connection; @@ -309,20 +362,21 @@ static void test_empty_headers_param(void) WinHttpCloseHandle(ses); } -static void test_SendRequest (void) +static void test_WinHttpSendRequest (void) { static const WCHAR content_type[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n', '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0}; static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0}; - static const WCHAR test_verb[] = {'P','O','S','T',0}; + static const WCHAR postW[] = {'P','O','S','T',0}; static CHAR post_data[] = "mode=Test"; static const char test_post[] = "mode => Test\0\n"; HINTERNET session, request, connection; - DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable; + DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable, len; DWORD_PTR context; BOOL ret; CHAR buffer[256]; + WCHAR method[8]; int i; header_len = -1L; @@ -336,7 +390,7 @@ static void test_SendRequest (void) connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0); ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError()); - request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER, + request = WinHttpOpenRequest(connection, postW, test_file, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE); if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED) { @@ -346,6 +400,13 @@ static void test_SendRequest (void) ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError()); if (!request) goto done; + method[0] = 0; + len = sizeof(method); + ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_REQUEST_METHOD, NULL, method, &len, NULL); + ok(ret, "got %u\n", GetLastError()); + ok(len == lstrlenW(postW) * sizeof(WCHAR), "got %u\n", len); + ok(!lstrcmpW(method, postW), "got %s\n", wine_dbgstr_w(method)); + context = 0xdeadbeef; ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context)); ok(ret, "WinHttpSetOption failed: %u\n", GetLastError()); @@ -395,6 +456,14 @@ static void test_SendRequest (void) "Expected ERROR_SUCCESS got %u.\n", GetLastError()); ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_ORIG_URI, NULL, NULL, &len, NULL); + ok(!ret && GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_MAX + 1, NULL, NULL, &len, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError()); + bytes_rw = -1; ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw); ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError()); @@ -980,7 +1049,7 @@ static void test_secure_connection(void) { static const char data_start[] = "<!DOCTYPE html PUBLIC"; HINTERNET ses, con, req; - DWORD size, status, policy, bitness, read_size, err, available_size, protocols; + DWORD size, status, policy, bitness, read_size, err, available_size, protocols, flags; BOOL ret; CERT_CONTEXT *cert; WINHTTP_CERTIFICATE_INFO info; @@ -1034,6 +1103,33 @@ static void test_secure_connection(void) req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE); ok(req != NULL, "failed to open a request %u\n", GetLastError()); + flags = 0xdeadbeef; + size = sizeof(flags); + ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, &size); + ok(ret, "failed to query security flags %u\n", GetLastError()); + ok(!flags, "got %08x\n", flags); + + flags = SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; + ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); + ok(ret, "failed to set security flags %u\n", GetLastError()); + + flags = SECURITY_FLAG_SECURE; + ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); + ok(!ret, "success\n"); + + flags = SECURITY_FLAG_STRENGTH_STRONG; + ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); + ok(!ret, "success\n"); + + flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | + SECURITY_FLAG_IGNORE_CERT_CN_INVALID; + ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); + ok(ret, "failed to set security flags %u\n", GetLastError()); + + flags = 0; + ret = WinHttpSetOption(req, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)); + ok(ret, "failed to set security flags %u\n", GetLastError()); + ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0); err = GetLastError(); ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err); @@ -1043,7 +1139,7 @@ static void test_secure_connection(void) ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0); err = GetLastError(); if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT || - err == ERROR_WINHTTP_TIMEOUT)) + err == ERROR_WINHTTP_TIMEOUT || err == SEC_E_ILLEGAL_MESSAGE)) { skip("secure connection failed, skipping remaining secure tests\n"); goto cleanup; @@ -1076,6 +1172,11 @@ static void test_secure_connection(void) } ret = WinHttpReceiveResponse(req, NULL); + if (!ret && GetLastError() == ERROR_WINHTTP_CONNECTION_ERROR) + { + skip("connection error, skipping remaining secure tests\n"); + goto cleanup; + } ok(ret, "failed to receive response %u\n", GetLastError()); available_size = 0; @@ -1107,6 +1208,11 @@ static void test_secure_connection(void) } ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size); + size = sizeof(cert); + ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size); + ok(ret, "failed to retrieve certificate context %u\n", GetLastError()); + if (ret) CertFreeCertificateContext(cert); + cleanup: WinHttpCloseHandle(req); WinHttpCloseHandle(con); @@ -1140,11 +1246,6 @@ static void test_request_parameter_defaults(void) ok(ret, "failed to send request %u\n", GetLastError()); ret = WinHttpReceiveResponse(req, NULL); - if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */ - { - win_skip("invalid response\n"); - goto done; - } ok(ret, "failed to receive response %u\n", GetLastError()); status = 0xdeadbeef; @@ -1342,7 +1443,7 @@ static void test_set_default_proxy_config(void) set_default_proxy_reg_value( saved_proxy_settings, len, type ); } -static void test_Timeouts (void) +static void test_timeouts(void) { BOOL ret; DWORD value, size; @@ -1931,6 +2032,70 @@ static void test_Timeouts (void) ok(ret, "%u\n", GetLastError()); ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value); + /* response timeout */ + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + ok(value == ~0u, "got %u\n", value); + + SetLastError(0xdeadbeef); + value = 30000; + ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value)); + ok(ret, "%u\n", GetLastError()); + + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + todo_wine ok(value == 0xbeefdead, "got %u\n", value); + + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + ok(value == ~0u, "got %u\n", value); + + SetLastError(0xdeadbeef); + value = 30000; + ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value)); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + ok(value == ~0u, "got %u\n", value); + + SetLastError(0xdeadbeef); + value = 48878; + ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value)); + ok(ret, "%u\n", GetLastError()); + + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + todo_wine ok(value == 48879, "got %u\n", value); + + SetLastError(0xdeadbeef); + value = 48880; + ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value)); + ok(ret, "%u\n", GetLastError()); + + SetLastError(0xdeadbeef); + value = 0xdeadbeef; + size = sizeof(value); + ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size); + ok(ret, "%u\n", GetLastError()); + ok(value == 48880, "got %u\n", value); + WinHttpCloseHandle(req); WinHttpCloseHandle(con); WinHttpCloseHandle(ses); @@ -1969,6 +2134,11 @@ static void test_resolve_timeout(void) ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED, "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError()); + ret = WinHttpReceiveResponse( req, NULL ); + ok( !ret && (GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || + GetLastError() == ERROR_WINHTTP_OPERATION_CANCELLED /* < win7 */), + "got %u\n", GetLastError() ); + WinHttpCloseHandle(req); WinHttpCloseHandle(con); WinHttpCloseHandle(ses); @@ -2079,6 +2249,13 @@ static const char largeauth[] = "Content-Type: text/plain\r\n" "\r\n"; +static const char passportauth[] = +"HTTP/1.1 302 Found\r\n" +"Content-Length: 0\r\n" +"Location: /\r\n" +"WWW-Authenticate: Passport1.4\r\n" +"\r\n"; + static const char unauthorized[] = "Unauthorized"; static const char hello_world[] = "Hello World"; static const char auth_unseen[] = "Auth Unseen"; @@ -2243,6 +2420,30 @@ static DWORD CALLBACK server_thread(LPVOID param) if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0); else send(c, notokmsg, sizeof(notokmsg) - 1, 0); } + else if (strstr(buffer, "GET /escape")) + { + static const char res[] = "%0D%0A%1F%7F%3C%20%one?%1F%7F%20!%22%23$%&'()*+,-./:;%3C=%3E?@%5B%5C%5D" + "%5E_%60%7B%7C%7D~%0D%0A "; + static const char res2[] = "%0D%0A%1F%7F%3C%20%25two?%1F%7F%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D" + "%5E_%60%7B%7C%7D~%0D%0A "; + static const char res3[] = "\x1f\x7f<%20%three?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "; + static const char res4[] = "%0D%0A%1F%7F%3C%20%four?\x1f\x7f%20!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "; + static const char res5[] = "&text=one%C2%80%7F~"; + static const char res6[] = "&text=two%C2%80\x7f~"; + static const char res7[] = "&text=%E5%90%9B%E3%81%AE%E5%90%8D%E3%81%AF"; + + if (strstr(buffer + 11, res) || strstr(buffer + 11, res2) || strstr(buffer + 11, res3) || + strstr(buffer + 11, res4) || strstr(buffer + 11, res5) || strstr(buffer + 11, res6) || + strstr(buffer + 11, res7)) + { + send(c, okmsg, sizeof(okmsg) - 1, 0); + } + else send(c, notokmsg, sizeof(notokmsg) - 1, 0); + } + else if (strstr(buffer, "GET /passport")) + { + send(c, passportauth, sizeof(passportauth) - 1, 0); + } if (strstr(buffer, "GET /quit")) { send(c, okmsg, sizeof okmsg - 1, 0); @@ -2319,7 +2520,7 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path) ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target); error = GetLastError(); ok(!ret, "unexpected success\n"); - todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error); + ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error); ok(supported == 0xdeadbeef, "got %x\n", supported); ok(first == 0xdeadbeef, "got %x\n", first); ok(target == 0xdeadbeef, "got %x\n", target); @@ -2406,7 +2607,7 @@ static void test_basic_authentication(int port) ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target); error = GetLastError(); ok(!ret, "expected failure\n"); - todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error); + ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error); ok(supported == 0xdeadbeef, "got %x\n", supported); ok(first == 0xdeadbeef, "got %x\n", first); ok(target == 0xdeadbeef, "got %x\n", target); @@ -2631,9 +2832,12 @@ static void test_basic_authentication(int port) static void test_multi_authentication(int port) { static const WCHAR multiauthW[] = {'/','m','u','l','t','i','a','u','t','h',0}; + static const WCHAR www_authenticateW[] = + {'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',0}; static const WCHAR getW[] = {'G','E','T',0}; HINTERNET ses, con, req; - DWORD supported, first, target; + DWORD supported, first, target, size, index; + WCHAR buf[512]; BOOL ret; ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); @@ -2659,6 +2863,22 @@ static void test_multi_authentication(int port) ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target); ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first); + index = 0; + size = sizeof(buf); + ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, www_authenticateW, buf, &size, &index); + ok(ret, "expected success\n"); + ok(!strcmp_wa(buf, "Bearer"), "buf = %s\n", wine_dbgstr_w(buf)); + ok(size == lstrlenW(buf) * sizeof(WCHAR), "size = %u\n", size); + ok(index == 1, "index = %u\n", index); + + index = 0; + size = 0xdeadbeef; + ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CUSTOM, www_authenticateW, NULL, &size, &index); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "WinHttpQueryHeaders returned %x(%u)\n", ret, GetLastError()); + ok(size == (lstrlenW(buf) + 1) * sizeof(WCHAR), "size = %u\n", size); + ok(index == 0, "index = %u\n", index); + WinHttpCloseHandle(req); WinHttpCloseHandle(con); WinHttpCloseHandle(ses); @@ -2907,7 +3127,7 @@ static void test_not_modified(int port) memcpy(today, ifmodifiedW, sizeof(ifmodifiedW)); GetSystemTime(&st); - WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]); + WinHttpTimeFromSystemTime(&st, &today[ARRAY_SIZE(ifmodifiedW)]); session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); @@ -2982,6 +3202,7 @@ static void test_bad_header( int port ) content_typeW, buffer, &len, &index ); ok( ret, "failed to query headers %u\n", GetLastError() ); ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( index == 1, "index = %u\n", index ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); @@ -3022,6 +3243,7 @@ static void test_multiple_reads(int port) char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 ); ret = WinHttpReadData( req, buf, len, &bytes_read ); + ok(ret, "WinHttpReadData failed: %u.\n", GetLastError()); ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len ); HeapFree( GetProcessHeap(), 0, buf ); @@ -3198,6 +3420,74 @@ static void test_cookies( int port ) WinHttpCloseHandle( ses ); } +static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags ) +{ + HINTERNET req; + DWORD status, size; + BOOL ret; + + req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags ); + ok( req != NULL, "failed to open a request %u\n", GetLastError() ); + + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok( ret, "failed to send request %u\n", GetLastError() ); + + ret = WinHttpReceiveResponse( req, NULL ); + ok( ret, "failed to receive response %u\n", GetLastError() ); + + status = 0xdeadbeef; + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok( ret, "failed to query status code %u\n", GetLastError() ); + ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */, + "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status ); + WinHttpCloseHandle( req ); +} + +static void test_request_path_escapes( int port ) +{ + static const WCHAR objW[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#', + '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`', + '{','|','}','~','\r','\n',0}; + static const WCHAR obj2W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#', + '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`', + '{','|','}','~','\r','\n',0}; + static const WCHAR obj3W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!', + '"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^', + '_','`','{','|','}','~','\r','\n',0}; + static const WCHAR obj4W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"', + '#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_', + '`','{','|','}','~','\r','\n',0}; + static const WCHAR obj5W[] = + {'/','e','s','c','a','p','e','&','t','e','x','t','=','o','n','e',0x80,0x7f,0x7e,0}; + static const WCHAR obj6W[] = + {'/','e','s','c','a','p','e','&','t','e','x','t','=','t','w','o',0x80,0x7f,0x7e,0}; + static const WCHAR obj7W[] = + {'/','e','s','c','a','p','e','&','t','e','x','t','=',0x541b,0x306e,0x540d,0x306f,0}; + HINTERNET ses, con; + + ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ); + ok( ses != NULL, "failed to open session %u\n", GetLastError() ); + + con = WinHttpConnect( ses, localhostW, port, 0 ); + ok( con != NULL, "failed to open a connection %u\n", GetLastError() ); + + do_request( con, objW, 0 ); + do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT ); + do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE ); + do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY ); + do_request( con, obj5W, 0 ); + do_request( con, obj6W, WINHTTP_FLAG_ESCAPE_DISABLE ); + do_request( con, obj7W, WINHTTP_FLAG_ESCAPE_DISABLE ); + + WinHttpCloseHandle( con ); + WinHttpCloseHandle( ses ); +} + static void test_connection_info( int port ) { static const WCHAR basicW[] = {'/','b','a','s','i','c',0}; @@ -3257,6 +3547,77 @@ static void test_connection_info( int port ) WinHttpCloseHandle( ses ); } +static void test_passport_auth( int port ) +{ + static const WCHAR passportW[] = + {'/','p','a','s','s','p','o','r','t',0}; + static const WCHAR foundW[] = + {'F','o','u','n','d',0}; + static const WCHAR unauthorizedW[] = + {'U','n','a','u','t','h','o','r','i','z','e','d',0}; + static const WCHAR headersW[] = + {'H','T','T','P','/','1','.','1',' ','4','0','1',' ','F','o','u','n','d','\r','\n', + 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','0','\r','\n', + 'L','o','c','a','t','i','o','n',':',' ','/','\r','\n', + 'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',':',' ', + 'P','a','s','s','p','o','r','t','1','.','4','\r','\n','\r','\n',0}; + HINTERNET ses, con, req; + DWORD status, size, option; + WCHAR buf[128]; + BOOL ret; + + ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 ); + ok( ses != NULL, "got %u\n", GetLastError() ); + + option = WINHTTP_ENABLE_PASSPORT_AUTH; + ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) ); + ok( ret, "got %u\n", GetLastError() ); + + con = WinHttpConnect( ses, localhostW, port, 0 ); + ok( con != NULL, "got %u\n", GetLastError() ); + + req = WinHttpOpenRequest( con, NULL, passportW, NULL, NULL, NULL, 0 ); + ok( req != NULL, "got %u\n", GetLastError() ); + + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok( ret, "got %u\n", GetLastError() ); + + ret = WinHttpReceiveResponse( req, NULL ); + ok( ret || broken(!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) /* winxp */, "got %u\n", GetLastError() ); + if (!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) + { + win_skip("no support for Passport redirects\n"); + goto cleanup; + } + + status = 0xdeadbeef; + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok( ret, "got %u\n", GetLastError() ); + ok( status == HTTP_STATUS_DENIED, "got %u\n", status ); + + buf[0] = 0; + size = sizeof(buf); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL ); + ok( ret, "got %u\n", GetLastError() ); + ok( !lstrcmpW(foundW, buf) || broken(!lstrcmpW(unauthorizedW, buf)) /* < win7 */, "got %s\n", wine_dbgstr_w(buf) ); + + buf[0] = 0; + size = sizeof(buf); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL ); + ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() ); + if (ret) + { + ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size ); + ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) ); + } + +cleanup: + WinHttpCloseHandle( req ); + WinHttpCloseHandle( con ); + WinHttpCloseHandle( ses ); +} + static void test_credentials(void) { static WCHAR userW[] = {'u','s','e','r',0}; @@ -3277,13 +3638,13 @@ static void test_credentials(void) req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0); ok(req != NULL, "failed to open a request %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size); ok(ret, "failed to query proxy username %u\n", GetLastError()); ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer)); ok(!size, "expected 0, got %u\n", size); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size); ok(ret, "failed to query proxy password %u\n", GetLastError()); ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer)); @@ -3292,19 +3653,19 @@ static void test_credentials(void) ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW)); ok(ret, "failed to set username %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size); ok(ret, "failed to query proxy username %u\n", GetLastError()); ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer)); ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size); ok(ret, "failed to query username %u\n", GetLastError()); ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer)); ok(!size, "expected 0, got %u\n", size); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size); ok(ret, "failed to query password %u\n", GetLastError()); ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer)); @@ -3313,7 +3674,7 @@ static void test_credentials(void) ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW)); ok(ret, "failed to set proxy password %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size); ok(ret, "failed to query proxy password %u\n", GetLastError()); ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer)); @@ -3322,7 +3683,7 @@ static void test_credentials(void) ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW)); ok(ret, "failed to set username %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size); ok(ret, "failed to query username %u\n", GetLastError()); ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer)); @@ -3331,7 +3692,7 @@ static void test_credentials(void) ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW)); ok(ret, "failed to set password %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size); ok(ret, "failed to query password %u\n", GetLastError()); ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer)); @@ -3357,7 +3718,7 @@ static void test_credentials(void) ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL); ok(ret, "failed to set credentials %u\n", GetLastError()); - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size); ok(ret, "failed to query username %u\n", GetLastError()); todo_wine { @@ -3365,7 +3726,7 @@ static void test_credentials(void) ok(!size, "expected 0, got %u\n", size); } - size = sizeof(buffer)/sizeof(WCHAR); + size = ARRAY_SIZE(buffer); ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size); ok(ret, "failed to query password %u\n", GetLastError()); todo_wine { @@ -3435,9 +3796,9 @@ static void test_IWinHttpRequest(int port) V_VT( &data ) = VT_BSTR; V_BSTR( &data ) = SysAllocString( test_dataW ); hr = IWinHttpRequest_Send( req, data ); - ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)), - "got %08x\n", hr ); + ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %08x\n", hr ); SysFreeString( V_BSTR( &data ) ); + if (hr != S_OK) goto done; hr = IWinHttpRequest_Open( req, NULL, NULL, empty ); ok( hr == E_INVALIDARG, "got %08x\n", hr ); @@ -3905,14 +4266,14 @@ static void test_IWinHttpRequest(int port) SysFreeString( url ); hr = IWinHttpRequest_Send( req, empty ); - ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr ); - if (hr == S_OK) - { - hr = IWinHttpRequest_get_ResponseText( req, &response ); - ok( hr == S_OK, "got %08x\n", hr ); - ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) ); - SysFreeString( response ); - } + ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ) || + hr == SEC_E_ILLEGAL_MESSAGE /* winxp */, "got %08x\n", hr ); + if (hr != S_OK) goto done; + + hr = IWinHttpRequest_get_ResponseText( req, &response ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) ); + SysFreeString( response ); IWinHttpRequest_Release( req ); @@ -3920,7 +4281,7 @@ static void test_IWinHttpRequest(int port) ok( hr == S_OK, "got %08x\n", hr ); sprintf( buf, "
http://localhost:%d/auth
", port ); - MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) ); + MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, ARRAY_SIZE( bufW )); url = SysAllocString( bufW ); method = SysAllocString( method3W ); V_VT( &async ) = VT_BOOL; @@ -3949,8 +4310,8 @@ static void test_IWinHttpRequest(int port) ok( hr == S_OK, "got %08x\n", hr ); ok( status == HTTP_STATUS_DENIED, "got %d\n", status ); +done: IWinHttpRequest_Release( req ); - CoUninitialize(); } @@ -4195,14 +4556,12 @@ static void test_WinHttpDetectAutoProxyConfigUrl(void) WCHAR *url; DWORD error; -if (0) /* crashes on some win2k systems */ -{ SetLastError(0xdeadbeef); ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL ); error = GetLastError(); ok( !ret, "expected failure\n" ); ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); -} + url = NULL; SetLastError(0xdeadbeef); ret = WinHttpDetectAutoProxyConfigUrl( 0, &url ); @@ -4210,14 +4569,12 @@ if (0) /* crashes on some win2k systems */ ok( !ret, "expected failure\n" ); ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); -if (0) /* crashes on some win2k systems */ -{ SetLastError(0xdeadbeef); ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL ); error = GetLastError(); ok( !ret, "expected failure\n" ); ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); -} + url = (WCHAR *)0xdeadbeef; SetLastError(0xdeadbeef); ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url ); @@ -4388,7 +4745,7 @@ static void test_WinHttpGetProxyForUrl(void) static void test_chunked_read(void) { - static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0}; + static const WCHAR verb[] = {'/','t','e','s','t','s','/','c','h','u','n','k','e','d',0}; static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0}; WCHAR header[32]; DWORD len, err; @@ -4417,9 +4774,11 @@ static void test_chunked_read(void) goto done; } ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() ); + if (!ret) goto done; ret = WinHttpReceiveResponse( req, NULL ); ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() ); + if (!ret) goto done; header[0] = 0; len = sizeof(header); @@ -4449,6 +4808,7 @@ static void test_chunked_read(void) char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 ); ret = WinHttpReadData( req, buf, len, &bytes_read ); + ok(ret, "WinHttpReadData failed: %u.\n", GetLastError()); buf[bytes_read] = 0; trace( "WinHttpReadData -> %d %u\n", ret, bytes_read ); @@ -4476,17 +4836,17 @@ START_TEST (winhttp) HANDLE thread; DWORD ret; - test_OpenRequest(); - test_SendRequest(); + test_WinHttpOpenRequest(); + test_WinHttpSendRequest(); test_WinHttpTimeFromSystemTime(); test_WinHttpTimeToSystemTime(); test_WinHttpAddHeaders(); test_secure_connection(); test_request_parameter_defaults(); - test_QueryOption(); + test_WinHttpQueryOption(); test_set_default_proxy_config(); test_empty_headers_param(); - test_Timeouts(); + test_timeouts(); test_resolve_timeout(); test_credentials(); test_IWinHttpRequest_Invoke(); @@ -4498,7 +4858,7 @@ START_TEST (winhttp) si.event = CreateEventW(NULL, 0, 0, NULL); si.port = 7532; - thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL); + thread = CreateThread(NULL, 0, server_thread, &si, 0, NULL); ok(thread != NULL, "failed to create thread %u\n", GetLastError()); ret = WaitForSingleObject(si.event, 10000); @@ -4522,6 +4882,8 @@ START_TEST (winhttp) test_bad_header(si.port); test_multiple_reads(si.port); test_cookies(si.port); + test_request_path_escapes(si.port); + test_passport_auth(si.port); /* send the basic request again to shutdown the server thread */ test_basic_request(si.port, NULL, quitW);
5 years
1
0
0
0
[reactos] 01/01: [WINHTTP] Sync with Wine Staging 4.18. CORE-16441
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bd6580fc63bb886686b6…
commit 5bd6580fc63bb886686b62caf26f3ea99a173922 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Dec 7 13:05:48 2019 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Dec 7 13:05:48 2019 +0100 [WINHTTP] Sync with Wine Staging 4.18. CORE-16441 --- dll/win32/winhttp/cookie.c | 121 ++-- dll/win32/winhttp/handle.c | 25 +- dll/win32/winhttp/main.c | 1 + dll/win32/winhttp/net.c | 480 +++++-------- dll/win32/winhttp/request.c | 1261 +++++++++++++++++++++-------------- dll/win32/winhttp/session.c | 604 +++++++++-------- dll/win32/winhttp/url.c | 313 +++++---- dll/win32/winhttp/winhttp_private.h | 243 +++---- media/doc/README.WINE | 2 +- 9 files changed, 1617 insertions(+), 1433 deletions(-) diff --git a/dll/win32/winhttp/cookie.c b/dll/win32/winhttp/cookie.c index b4b25304f7f..40c11c6f71c 100644 --- a/dll/win32/winhttp/cookie.c +++ b/dll/win32/winhttp/cookie.c @@ -17,24 +17,39 @@ */ #include "config.h" +#include "ws2tcpip.h" #include <stdarg.h> -#include "wine/debug.h" -#include "wine/list.h" - #include "windef.h" #include "winbase.h" #include "winhttp.h" +#include "wine/debug.h" +#include "wine/list.h" #include "winhttp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(winhttp); -static domain_t *add_domain( session_t *session, WCHAR *name ) +struct cookie +{ + struct list entry; + WCHAR *name; + WCHAR *value; + WCHAR *path; +}; + +struct domain +{ + struct list entry; + WCHAR *name; + struct list cookies; +}; + +static struct domain *add_domain( struct session *session, WCHAR *name ) { - domain_t *domain; + struct domain *domain; - if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL; + if (!(domain = heap_alloc_zero( sizeof(struct domain) ))) return NULL; list_init( &domain->entry ); list_init( &domain->cookies ); @@ -46,14 +61,14 @@ static domain_t *add_domain( session_t *session, WCHAR *name ) return domain; } -static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name ) +static struct cookie *find_cookie( struct domain *domain, const WCHAR *path, const WCHAR *name ) { struct list *item; - cookie_t *cookie; + struct cookie *cookie; LIST_FOR_EACH( item, &domain->cookies ) { - cookie = LIST_ENTRY( item, cookie_t, entry ); + cookie = LIST_ENTRY( item, struct cookie, entry ); if (!strcmpW( cookie->path, path ) && !strcmpW( cookie->name, name )) { TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value)); @@ -63,7 +78,7 @@ static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR * return NULL; } -static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial ) +static BOOL domain_match( const WCHAR *name, struct domain *domain, BOOL partial ) { TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name)); @@ -72,7 +87,7 @@ static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial ) return TRUE; } -static void free_cookie( cookie_t *cookie ) +static void free_cookie( struct cookie *cookie ) { heap_free( cookie->name ); heap_free( cookie->value ); @@ -80,20 +95,20 @@ static void free_cookie( cookie_t *cookie ) heap_free( cookie ); } -static void delete_cookie( cookie_t *cookie ) +static void delete_cookie( struct cookie *cookie ) { list_remove( &cookie->entry ); free_cookie( cookie ); } -void delete_domain( domain_t *domain ) +static void delete_domain( struct domain *domain ) { - cookie_t *cookie; + struct cookie *cookie; struct list *item, *next; LIST_FOR_EACH_SAFE( item, next, &domain->cookies ) { - cookie = LIST_ENTRY( item, cookie_t, entry ); + cookie = LIST_ENTRY( item, struct cookie, entry ); delete_cookie( cookie ); } @@ -102,35 +117,51 @@ void delete_domain( domain_t *domain ) heap_free( domain ); } -static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path ) +void destroy_cookies( struct session *session ) +{ + struct list *item, *next; + struct domain *domain; + + LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) + { + domain = LIST_ENTRY( item, struct domain, entry ); + delete_domain( domain ); + } +} + +static BOOL add_cookie( struct session *session, struct cookie *cookie, WCHAR *domain_name, WCHAR *path ) { - domain_t *domain = NULL; - cookie_t *old_cookie; + struct domain *domain = NULL; + struct cookie *old_cookie; struct list *item; + if (!(cookie->path = strdupW( path ))) return FALSE; + + EnterCriticalSection( &session->cs ); + LIST_FOR_EACH( item, &session->cookie_cache ) { - domain = LIST_ENTRY( item, domain_t, entry ); + domain = LIST_ENTRY( item, struct domain, entry ); if (domain_match( domain_name, domain, FALSE )) break; domain = NULL; } - if (!domain) - { - if (!(domain = add_domain( session, domain_name ))) return FALSE; - } + if (!domain) domain = add_domain( session, domain_name ); else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie ); - cookie->path = strdupW( path ); - list_add_head( &domain->cookies, &cookie->entry ); + if (domain) + { + list_add_head( &domain->cookies, &cookie->entry ); + TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path), + debugstr_w(cookie->name), debugstr_w(cookie->value)); + } - TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path), - debugstr_w(cookie->name), debugstr_w(cookie->value)); - return TRUE; + LeaveCriticalSection( &session->cs ); + return domain != NULL; } -static cookie_t *parse_cookie( const WCHAR *string ) +static struct cookie *parse_cookie( const WCHAR *string ) { - cookie_t *cookie; + struct cookie *cookie; const WCHAR *p; int len; @@ -139,7 +170,7 @@ static cookie_t *parse_cookie( const WCHAR *string ) while (len && string[len - 1] == ' ') len--; if (!len) return NULL; - if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL; + if (!(cookie = heap_alloc_zero( sizeof(struct cookie) ))) return NULL; list_init( &cookie->entry ); if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) ))) @@ -229,7 +260,7 @@ static struct attr *parse_attr( const WCHAR *str, int *used ) return attr; } -BOOL set_cookies( request_t *request, const WCHAR *cookies ) +BOOL set_cookies( struct request *request, const WCHAR *cookies ) { static const WCHAR pathW[] = {'p','a','t','h',0}; static const WCHAR domainW[] = {'d','o','m','a','i','n',0}; @@ -237,8 +268,8 @@ BOOL set_cookies( request_t *request, const WCHAR *cookies ) WCHAR *buffer, *p; WCHAR *cookie_domain = NULL, *cookie_path = NULL; struct attr *attr, *domain = NULL, *path = NULL; - session_t *session = request->connect->session; - cookie_t *cookie; + struct session *session = request->connect->session; + struct cookie *cookie; int len, used; len = strlenW( cookies ); @@ -290,14 +321,16 @@ end: return ret; } -BOOL add_cookie_headers( request_t *request ) +BOOL add_cookie_headers( struct request *request ) { struct list *domain_cursor; - session_t *session = request->connect->session; + struct session *session = request->connect->session; + + EnterCriticalSection( &session->cs ); LIST_FOR_EACH( domain_cursor, &session->cookie_cache ) { - domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry ); + struct domain *domain = LIST_ENTRY( domain_cursor, struct domain, entry ); if (domain_match( request->connect->servername, domain, TRUE )) { struct list *cookie_cursor; @@ -305,19 +338,23 @@ BOOL add_cookie_headers( request_t *request ) LIST_FOR_EACH( cookie_cursor, &domain->cookies ) { - cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, entry ); + struct cookie *cookie = LIST_ENTRY( cookie_cursor, struct cookie, entry ); TRACE("comparing path %s with %s\n", debugstr_w(request->path), debugstr_w(cookie->path)); if (strstrW( request->path, cookie->path ) == request->path) { - const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '}; - int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name = strlenW( cookie->name ); + static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '}; + int len, len_cookie = ARRAY_SIZE( cookieW ), len_name = strlenW( cookie->name ); WCHAR *header; len = len_cookie + len_name; if (cookie->value) len += strlenW( cookie->value ) + 1; - if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; + if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + LeaveCriticalSection( &session->cs ); + return FALSE; + } memcpy( header, cookieW, len_cookie * sizeof(WCHAR) ); strcpyW( header + len_cookie, cookie->name ); @@ -335,5 +372,7 @@ BOOL add_cookie_headers( request_t *request ) } } } + + LeaveCriticalSection( &session->cs ); return TRUE; } diff --git a/dll/win32/winhttp/handle.c b/dll/win32/winhttp/handle.c index 6026a496103..6711cd91727 100644 --- a/dll/win32/winhttp/handle.c +++ b/dll/win32/winhttp/handle.c @@ -19,15 +19,14 @@ */ #include "config.h" -#include "wine/port.h" -#include "wine/debug.h" - +#include "ws2tcpip.h" #include <stdarg.h> #include "windef.h" #include "winbase.h" #include "winhttp.h" +#include "wine/debug.h" #include "winhttp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(winhttp); @@ -43,20 +42,20 @@ static CRITICAL_SECTION_DEBUG handle_cs_debug = }; static CRITICAL_SECTION handle_cs = { &handle_cs_debug, -1, 0, 0, 0, 0 }; -static object_header_t **handles; +static struct object_header **handles; static ULONG_PTR next_handle; static ULONG_PTR max_handles; -object_header_t *addref_object( object_header_t *hdr ) +struct object_header *addref_object( struct object_header *hdr ) { ULONG refs = InterlockedIncrement( &hdr->refs ); TRACE("%p -> refcount = %d\n", hdr, refs); return hdr; } -object_header_t *grab_object( HINTERNET hinternet ) +struct object_header *grab_object( HINTERNET hinternet ) { - object_header_t *hdr = NULL; + struct object_header *hdr = NULL; ULONG_PTR handle = (ULONG_PTR)hinternet; EnterCriticalSection( &handle_cs ); @@ -70,13 +69,13 @@ object_header_t *grab_object( HINTERNET hinternet ) return hdr; } -void release_object( object_header_t *hdr ) +void release_object( struct object_header *hdr ) { ULONG refs = InterlockedDecrement( &hdr->refs ); TRACE("object %p refcount = %d\n", hdr, refs); if (!refs) { - if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (request_t *)hdr ); + if (hdr->type == WINHTTP_HANDLE_TYPE_REQUEST) close_connection( (struct request *)hdr ); send_callback( hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, &hdr->handle, sizeof(HINTERNET) ); @@ -86,9 +85,9 @@ void release_object( object_header_t *hdr ) } } -HINTERNET alloc_handle( object_header_t *hdr ) +HINTERNET alloc_handle( struct object_header *hdr ) { - object_header_t **p; + struct object_header **p; ULONG_PTR handle, num; list_init( &hdr->children ); @@ -125,7 +124,7 @@ BOOL free_handle( HINTERNET hinternet ) { BOOL ret = FALSE; ULONG_PTR handle = (ULONG_PTR)hinternet; - object_header_t *hdr = NULL, *child, *next; + struct object_header *hdr = NULL, *child, *next; EnterCriticalSection( &handle_cs ); @@ -145,7 +144,7 @@ BOOL free_handle( HINTERNET hinternet ) if (hdr) { - LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, object_header_t, entry ) + LIST_FOR_EACH_ENTRY_SAFE( child, next, &hdr->children, struct object_header, entry ) { TRACE("freeing child handle %p for parent handle 0x%lx\n", child->handle, handle + 1); free_handle( child->handle ); diff --git a/dll/win32/winhttp/main.c b/dll/win32/winhttp/main.c index a63f28cf108..e6c084b979b 100644 --- a/dll/win32/winhttp/main.c +++ b/dll/win32/winhttp/main.c @@ -18,6 +18,7 @@ #define COBJMACROS #include "config.h" +#include "ws2tcpip.h" #include <stdarg.h> #include "windef.h" diff --git a/dll/win32/winhttp/net.c b/dll/win32/winhttp/net.c index e9ff86a165a..277a22eacb0 100644 --- a/dll/win32/winhttp/net.c +++ b/dll/win32/winhttp/net.c @@ -18,145 +18,31 @@ */ #include "config.h" -#include "wine/port.h" - +#define NONAMELESSUNION +#include "ws2tcpip.h" #include <stdarg.h> #include <stdio.h> -#include <errno.h> #include <assert.h> -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKET_H -# include <sys/socket.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif -#ifdef HAVE_SYS_FILIO_H -# include <sys/filio.h> -#endif -#ifdef HAVE_POLL_H -# include <poll.h> -#endif - -#define NONAMELESSUNION - -#include "wine/debug.h" -#include "wine/library.h" - #include "windef.h" #include "winbase.h" #include "winhttp.h" -#include "wincrypt.h" #include "schannel.h" +#include "wine/debug.h" +#include "wine/library.h" #include "winhttp_private.h" -/* to avoid conflicts with the Unix socket headers */ -#define USE_WS_PREFIX -#include "winsock2.h" - WINE_DEFAULT_DEBUG_CHANNEL(winhttp); -#ifndef HAVE_GETADDRINFO - -/* critical section to protect non-reentrant gethostbyname() */ -static CRITICAL_SECTION cs_gethostbyname; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &cs_gethostbyname, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") } -}; -static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 }; - -#endif - -/* translate a unix error code into a winsock error code */ -#ifndef __REACTOS__ -static int sock_get_error( int err ) -{ -#if !defined(__MINGW32__) && !defined (_MSC_VER) - switch (err) - { - case EINTR: return WSAEINTR; - case EBADF: return WSAEBADF; - case EPERM: - case EACCES: return WSAEACCES; - case EFAULT: return WSAEFAULT; - case EINVAL: return WSAEINVAL; - case EMFILE: return WSAEMFILE; - case EWOULDBLOCK: return WSAEWOULDBLOCK; - case EINPROGRESS: return WSAEINPROGRESS; - case EALREADY: return WSAEALREADY; - case ENOTSOCK: return WSAENOTSOCK; - case EDESTADDRREQ: return WSAEDESTADDRREQ; - case EMSGSIZE: return WSAEMSGSIZE; - case EPROTOTYPE: return WSAEPROTOTYPE; - case ENOPROTOOPT: return WSAENOPROTOOPT; - case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; - case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; - case EOPNOTSUPP: return WSAEOPNOTSUPP; - case EPFNOSUPPORT: return WSAEPFNOSUPPORT; - case EAFNOSUPPORT: return WSAEAFNOSUPPORT; - case EADDRINUSE: return WSAEADDRINUSE; - case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; - case ENETDOWN: return WSAENETDOWN; - case ENETUNREACH: return WSAENETUNREACH; - case ENETRESET: return WSAENETRESET; - case ECONNABORTED: return WSAECONNABORTED; - case EPIPE: - case ECONNRESET: return WSAECONNRESET; - case ENOBUFS: return WSAENOBUFS; - case EISCONN: return WSAEISCONN; - case ENOTCONN: return WSAENOTCONN; - case ESHUTDOWN: return WSAESHUTDOWN; - case ETOOMANYREFS: return WSAETOOMANYREFS; - case ETIMEDOUT: return WSAETIMEDOUT; - case ECONNREFUSED: return WSAECONNREFUSED; - case ELOOP: return WSAELOOP; - case ENAMETOOLONG: return WSAENAMETOOLONG; - case EHOSTDOWN: return WSAEHOSTDOWN; - case EHOSTUNREACH: return WSAEHOSTUNREACH; - case ENOTEMPTY: return WSAENOTEMPTY; -#ifdef EPROCLIM - case EPROCLIM: return WSAEPROCLIM; -#endif -#ifdef EUSERS - case EUSERS: return WSAEUSERS; -#endif -#ifdef EDQUOT - case EDQUOT: return WSAEDQUOT; -#endif -#ifdef ESTALE - case ESTALE: return WSAESTALE; -#endif -#ifdef EREMOTE - case EREMOTE: return WSAEREMOTE; -#endif - default: errno = err; perror( "sock_set_error" ); return WSAEFAULT; - } -#endif - return err; -} -#else -#define sock_get_error(x) WSAGetLastError() - -static inline int unix_ioctl(int filedes, long request, void *arg) -{ - return ioctlsocket(filedes, request, arg); -} -#define ioctlsocket unix_ioctl -#endif - static int sock_send(int fd, const void *msg, size_t len, int flags) { int ret; do { - if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %s\n", strerror(errno)); + if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %u\n", WSAGetLastError()); } - while(ret == -1 && errno == EINTR); + while(ret == -1 && WSAGetLastError() == WSAEINTR); return ret; } @@ -165,13 +51,13 @@ static int sock_recv(int fd, void *msg, size_t len, int flags) int ret; do { - if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %s\n", strerror(errno)); + if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %u\n", WSAGetLastError()); } - while(ret == -1 && errno == EINTR); + while(ret == -1 && WSAGetLastError() == WSAEINTR); return ret; } -static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags ) +static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD security_flags, BOOL check_revocation ) { HCERTSTORE store = cert->hCertStore; BOOL ret; @@ -184,9 +70,10 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu TRACE("verifying %s\n", debugstr_w( server )); chainPara.RequestedUsage.Usage.cUsageIdentifier = 1; chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth; - if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara, - CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, - NULL, &chain ))) + ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara, + check_revocation ? CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT : 0, + NULL, &chain ); + if (ret) { if (chain->TrustStatus.dwErrorStatus) { @@ -264,46 +151,41 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu return err; } -#ifdef __REACTOS__ -static BOOL winsock_initialized = FALSE; -BOOL netconn_init_winsock() +static BOOL winsock_loaded; + +void netconn_unload( void ) { - WSADATA wsaData; - int error; - if (!winsock_initialized) - { - error = WSAStartup(MAKEWORD(1, 1), &wsaData); - if (error) - { - ERR("WSAStartup failed: %d\n", error); - return FALSE; - } - else - winsock_initialized = TRUE; - } - return winsock_initialized; + if (winsock_loaded) WSACleanup(); +} + +static BOOL WINAPI winsock_startup( INIT_ONCE *once, void *param, void **ctx ) +{ + int ret; + WSADATA data; + if (!(ret = WSAStartup( MAKEWORD(1,1), &data ))) winsock_loaded = TRUE; + else ERR( "WSAStartup failed: %d\n", ret ); + return TRUE; } -#endif +static void winsock_init(void) +{ + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + InitOnceExecuteOnce( &once, winsock_startup, NULL, NULL ); +} -void netconn_unload( void ) +static void set_blocking( struct netconn *conn, BOOL blocking ) { -#ifndef HAVE_GETADDRINFO - DeleteCriticalSection(&cs_gethostbyname); -#endif -#ifdef __REACTOS__ - if(winsock_initialized) - WSACleanup(); -#endif + ULONG state = !blocking; + ioctlsocket( conn->socket, FIONBIO, &state ); } -netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sockaddr, int timeout ) +struct netconn *netconn_create( struct hostdata *host, const struct sockaddr_storage *sockaddr, int timeout ) { - netconn_t *conn; + struct netconn *conn; unsigned int addr_len; BOOL ret = FALSE; - int res; - ULONG state; + + winsock_init(); conn = heap_alloc_zero(sizeof(*conn)); if (!conn) return NULL; @@ -311,8 +193,7 @@ netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sock conn->sockaddr = *sockaddr; if ((conn->socket = socket( sockaddr->ss_family, SOCK_STREAM, 0 )) == -1) { - WARN("unable to create socket (%s)\n", strerror(errno)); - set_last_error( sock_get_error( errno ) ); + WARN("unable to create socket (%u)\n", WSAGetLastError()); heap_free(conn); return NULL; } @@ -329,83 +210,39 @@ netconn_t *netconn_create( hostdata_t *host, const struct sockaddr_storage *sock assert(0); } - if (timeout > 0) - { - state = 1; - ioctlsocket( conn->socket, FIONBIO, &state ); - } + if (timeout > 0) set_blocking( conn, FALSE ); - for (;;) + if (!connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len )) ret = TRUE; + else { - res = 0; - if (connect( conn->socket, (const struct sockaddr *)&conn->sockaddr, addr_len ) < 0) - { - res = sock_get_error( errno ); - if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS) - { -#ifdef __REACTOS__ - /* ReactOS: use select instead of poll */ - fd_set outfd; - struct timeval tv; - - FD_ZERO(&outfd); - FD_SET(conn->socket, &outfd); - - tv.tv_sec = 0; - tv.tv_usec = timeout * 1000; - for (;;) - { - res = 0; - - if (select( 0, NULL, &outfd, NULL, &tv ) > 0) -#else - struct pollfd pfd; - - pfd.fd = conn->socket; - pfd.events = POLLOUT; - for (;;) - { - res = 0; - if (poll( &pfd, 1, timeout ) > 0) -#endif - { - ret = TRUE; - break; - } - else - { - res = sock_get_error( errno ); - if (res != WSAEINTR) break; - } - } - } - if (res != WSAEINTR) break; - } - else + DWORD err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK || err == WSAEINPROGRESS) { - ret = TRUE; - break; + FD_SET set; + TIMEVAL timeval = { 0, timeout * 1000 }; + int res; + + FD_ZERO( &set ); + FD_SET( conn->socket, &set ); + if ((res = select( conn->socket + 1, NULL, &set, NULL, &timeval )) > 0) ret = TRUE; + else if (!res) SetLastError( ERROR_WINHTTP_TIMEOUT ); } } - if (timeout > 0) - { - state = 0; - ioctlsocket( conn->socket, FIONBIO, &state ); - } + + if (timeout > 0) set_blocking( conn, TRUE ); + if (!ret) { - WARN("unable to connect to host (%d)\n", res); - set_last_error( res ); - netconn_close( conn ); + WARN("unable to connect to host (%u)\n", GetLastError()); + closesocket( conn->socket ); + heap_free( conn ); return NULL; } return conn; } -BOOL netconn_close( netconn_t *conn ) +void netconn_close( struct netconn *conn ) { - int res; - if (conn->secure) { heap_free( conn->peek_msg_mem ); @@ -413,18 +250,13 @@ BOOL netconn_close( netconn_t *conn ) heap_free(conn->extra_buf); DeleteSecurityContext(&conn->ssl_ctx); } - res = closesocket( conn->socket ); + closesocket( conn->socket ); release_host( conn->host ); heap_free(conn); - if (res == -1) - { - set_last_error( sock_get_error( errno ) ); - return FALSE; - } - return TRUE; } -BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle ) +BOOL netconn_secure_connect( struct netconn *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle, + BOOL check_revocation) { SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}}; SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs}; @@ -520,7 +352,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert); if(status == SEC_E_OK) { - res = netconn_verify_cert(cert, hostname, security_flags); + res = netconn_verify_cert(cert, hostname, security_flags, check_revocation); CertFreeCertificateContext(cert); if(res != ERROR_SUCCESS) { WARN("cert verify failed: %u\n", res); @@ -546,7 +378,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl heap_free(conn->ssl_buf); conn->ssl_buf = NULL; DeleteSecurityContext(&ctx); - set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR); + SetLastError(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR); return FALSE; } @@ -557,7 +389,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl return TRUE; } -static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size) +static BOOL send_ssl_chunk(struct netconn *conn, const void *msg, size_t size) { SecBuffer bufs[4] = { {conn->ssl_sizes.cbHeader, SECBUFFER_STREAM_HEADER, conn->ssl_buf}, @@ -565,7 +397,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size) {conn->ssl_sizes.cbTrailer, SECBUFFER_STREAM_TRAILER, conn->ssl_buf+conn->ssl_sizes.cbHeader+size}, {0, SECBUFFER_EMPTY, NULL} }; - SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs}; + SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs}; SECURITY_STATUS res; memcpy(bufs[1].pvBuffer, msg, size); @@ -583,7 +415,7 @@ static BOOL send_ssl_chunk(netconn_t *conn, const void *msg, size_t size) return TRUE; } -BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent ) +BOOL netconn_send( struct netconn *conn, const void *msg, size_t len, int *sent ) { if (conn->secure) { @@ -604,19 +436,14 @@ BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int *sent ) return TRUE; } - if ((*sent = sock_send( conn->socket, msg, len, 0 )) == -1) - { - set_last_error( sock_get_error( errno ) ); - return FALSE; - } - return TRUE; + return ((*sent = sock_send( conn->socket, msg, len, 0 )) != -1); } -static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof) +static BOOL read_ssl_chunk(struct netconn *conn, void *buf, SIZE_T buf_size, SIZE_T *ret_size, BOOL *eof) { const SIZE_T ssl_buf_size = conn->ssl_sizes.cbHeader+conn->ssl_sizes.cbMaximumMessage+conn->ssl_sizes.cbTrailer; SecBuffer bufs[4]; - SecBufferDesc buf_desc = {SECBUFFER_VERSION, sizeof(bufs)/sizeof(*bufs), bufs}; + SecBufferDesc buf_desc = {SECBUFFER_VERSION, ARRAY_SIZE(bufs), bufs}; SSIZE_T size, buf_len; unsigned int i; SECURITY_STATUS res; @@ -672,7 +499,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T * } } while(res != SEC_E_OK); - for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) { + for(i = 0; i < ARRAY_SIZE(bufs); i++) { if(bufs[i].BufferType == SECBUFFER_DATA) { size = min(buf_size, bufs[i].cbBuffer); memcpy(buf, bufs[i].pvBuffer, size); @@ -689,7 +516,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T * } } - for(i=0; i < sizeof(bufs)/sizeof(*bufs); i++) { + for(i = 0; i < ARRAY_SIZE(bufs); i++) { if(bufs[i].BufferType == SECBUFFER_EXTRA) { conn->extra_buf = heap_alloc(bufs[i].cbBuffer); if(!conn->extra_buf) @@ -703,7 +530,7 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T * return TRUE; } -BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd ) +BOOL netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int *recvd ) { *recvd = 0; if (!len) return TRUE; @@ -752,101 +579,64 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd *recvd = size; return TRUE; } - if ((*recvd = sock_recv( conn->socket, buf, len, flags )) == -1) - { - set_last_error( sock_get_error( errno ) ); - return FALSE; - } - return TRUE; + return ((*recvd = sock_recv( conn->socket, buf, len, flags )) != -1); } -ULONG netconn_query_data_available( netconn_t *conn ) +ULONG netconn_query_data_available( struct netconn *conn ) { return conn->secure ? conn->peek_len : 0; } -DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value ) +DWORD netconn_set_timeout( struct netconn *netconn, BOOL send, int value ) { - struct timeval tv; - - /* value is in milliseconds, convert to struct timeval */ - tv.tv_sec = value / 1000; - tv.tv_usec = (value % 1000) * 1000; - - if (setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1) + int opt = send ? SO_SNDTIMEO : SO_RCVTIMEO; + if (setsockopt( netconn->socket, SOL_SOCKET, opt, (void *)&value, sizeof(value) ) == -1) { - WARN("setsockopt failed (%s)\n", strerror( errno )); - return sock_get_error( errno ); + DWORD err = WSAGetLastError(); + WARN("setsockopt failed (%u)\n", err ); + return err; } return ERROR_SUCCESS; } -BOOL netconn_is_alive( netconn_t *netconn ) +BOOL netconn_is_alive( struct netconn *netconn ) { -#ifdef MSG_DONTWAIT - ssize_t len; - BYTE b; - - len = recv( netconn->socket, &b, 1, MSG_PEEK | MSG_DONTWAIT ); - return len == 1 || (len == -1 && errno == EWOULDBLOCK); -#elif defined(__MINGW32__) || defined(_MSC_VER) - ULONG mode; int len; char b; + DWORD err; - mode = 1; - if(!ioctlsocket(netconn->socket, FIONBIO, &mode)) - return FALSE; - - len = recv(netconn->socket, &b, 1, MSG_PEEK); + set_blocking( netconn, FALSE ); + len = sock_recv( netconn->socket, &b, 1, MSG_PEEK ); + err = WSAGetLastError(); + set_blocking( netconn, TRUE ); - mode = 0; - if(!ioctlsocket(netconn->socket, FIONBIO, &mode)) - return FALSE; - - return len == 1 || (len == -1 && WSAGetLastError() == WSAEWOULDBLOCK); -#else - FIXME("not supported on this platform\n"); - return TRUE; -#endif + return len == 1 || (len == -1 && err == WSAEWOULDBLOCK); } -static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_storage *sa ) +static DWORD resolve_hostname( const WCHAR *name, INTERNET_PORT port, struct sockaddr_storage *sa ) { - char *hostname; -#ifdef HAVE_GETADDRINFO - struct addrinfo *res, hints; + ADDRINFOW *res, hints; int ret; -#else - struct hostent *he; - struct sockaddr_in *sin = (struct sockaddr_in *)sa; -#endif - - if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY; -#ifdef HAVE_GETADDRINFO - memset( &hints, 0, sizeof(struct addrinfo) ); + memset( &hints, 0, sizeof(hints) ); /* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on * their IPv6 addresses even though they have IPv6 addresses in the DNS. */ hints.ai_family = AF_INET; - ret = getaddrinfo( hostname, NULL, &hints, &res ); + ret = GetAddrInfoW( name, NULL, &hints, &res ); if (ret != 0) { - TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret)); + TRACE("failed to get IPv4 address of %s, retrying with IPv6\n", debugstr_w(name)); hints.ai_family = AF_INET6; - ret = getaddrinfo( hostname, NULL, &hints, &res ); + ret = GetAddrInfoW( name, NULL, &hints, &res ); if (ret != 0) { - TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret)); - heap_free( hostname ); + TRACE("failed to get address of %s\n", debugstr_w(name)); return ERROR_WINHTTP_NAME_NOT_RESOLVED; } } - heap_free( hostname ); memcpy( sa, res->ai_addr, res->ai_addrlen ); - /* Copy port */ switch (res->ai_family) { case AF_INET: @@ -857,29 +647,12 @@ static DWORD resolve_hostname( const WCHAR *hostnameW, INTERNET_PORT port, struc break; } - freeaddrinfo( res ); + FreeAddrInfoW( res ); return ERROR_SUCCESS; -#else - EnterCriticalSection( &cs_gethostbyname ); - - he = gethostbyname( hostname ); - heap_free( hostname ); - if (!he) - { - TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno); - LeaveCriticalSection( &cs_gethostbyname ); - return ERROR_WINHTTP_NAME_NOT_RESOLVED; - } - memset( sa, 0, sizeof(struct sockaddr_in) ); - memcpy( &sin->sin_addr, he->h_addr, he->h_length ); - sin->sin_family = he->h_addrtype; - sin->sin_port = htons( port ); - - LeaveCriticalSection( &cs_gethostbyname ); - return ERROR_SUCCESS; -#endif } +#ifdef __REACTOS__ + struct resolve_args { const WCHAR *hostname; @@ -919,13 +692,64 @@ BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_stora if (ret) { - set_last_error( ret ); + SetLastError( ret ); return FALSE; } return TRUE; } -const void *netconn_get_certificate( netconn_t *conn ) +#else /* __REACTOS__ */ + +struct async_resolve +{ + const WCHAR *hostname; + INTERNET_PORT port; + struct sockaddr_storage *addr; + DWORD result; + HANDLE done; +}; + +static void CALLBACK resolve_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) +{ + struct async_resolve *async = ctx; + async->result = resolve_hostname( async->hostname, async->port, async->addr ); + SetEvent( async->done ); +} + +BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr_storage *addr, int timeout ) +{ + DWORD ret; + + if (!timeout) ret = resolve_hostname( hostname, port, addr ); + else + { + struct async_resolve async; + + async.hostname = hostname; + async.port = port; + async.addr = addr; + if (!(async.done = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE; + if (!TrySubmitThreadpoolCallback( resolve_proc, &async, NULL )) + { + CloseHandle( async.done ); + return FALSE; + } + if (WaitForSingleObject( async.done, timeout ) != WAIT_OBJECT_0) ret = ERROR_WINHTTP_TIMEOUT; + else ret = async.result; + CloseHandle( async.done ); + } + + if (ret) + { + SetLastError( ret ); + return FALSE; + } + return TRUE; +} + +#endif /* __REACTOS__ */ + +const void *netconn_get_certificate( struct netconn *conn ) { const CERT_CONTEXT *ret; SECURITY_STATUS res; @@ -935,7 +759,7 @@ const void *netconn_get_certificate( netconn_t *conn ) return res == SEC_E_OK ? ret : NULL; } -int netconn_get_cipher_strength( netconn_t *conn ) +int netconn_get_cipher_strength( struct netconn *conn ) { SecPkgContext_ConnectionInfo conn_info; SECURITY_STATUS res; diff --git a/dll/win32/winhttp/request.c b/dll/win32/winhttp/request.c index 5bb5b093373..da28f7b1826 100644 --- a/dll/win32/winhttp/request.c +++ b/dll/win32/winhttp/request.c @@ -21,13 +21,9 @@ #define COBJMACROS #include "config.h" -#include "wine/port.h" - +#include "ws2tcpip.h" #include <stdarg.h> #include <assert.h> -#ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> -#endif #include "windef.h" #include "winbase.h" @@ -38,9 +34,8 @@ #include "schannel.h" #include "winhttp.h" -#include "winhttp_private.h" - #include "wine/debug.h" +#include "winhttp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(winhttp); @@ -186,13 +181,13 @@ static const WCHAR *attribute_table[] = NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */ }; -static task_header_t *dequeue_task( request_t *request ) +static struct task_header *dequeue_task( struct request *request ) { - task_header_t *task; + struct task_header *task; EnterCriticalSection( &request->task_cs ); TRACE("%u tasks queued\n", list_count( &request->task_queue )); - task = LIST_ENTRY( list_head( &request->task_queue ), task_header_t, entry ); + task = LIST_ENTRY( list_head( &request->task_queue ), struct task_header, entry ); if (task) list_remove( &task->entry ); LeaveCriticalSection( &request->task_cs ); @@ -200,9 +195,17 @@ static task_header_t *dequeue_task( request_t *request ) return task; } +#ifdef __REACTOS__ static DWORD CALLBACK task_proc( LPVOID param ) +#else +static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) +#endif { - request_t *request = param; +#ifdef __REACTOS__ + struct request *request = param; +#else + struct request *request = ctx; +#endif HANDLE handles[2]; handles[0] = request->task_wait; @@ -214,7 +217,7 @@ static DWORD CALLBACK task_proc( LPVOID param ) { case WAIT_OBJECT_0: { - task_header_t *task; + struct task_header *task; while ((task = dequeue_task( request ))) { task->proc( task ); @@ -230,21 +233,31 @@ static DWORD CALLBACK task_proc( LPVOID param ) request->task_cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection( &request->task_cs ); request->hdr.vtbl->destroy( &request->hdr ); +#ifdef __REACTOS__ return 0; +#else + return; +#endif default: ERR("wait failed %u (%u)\n", err, GetLastError()); break; } } +#ifdef __REACTOS__ return 0; +#endif } -static BOOL queue_task( task_header_t *task ) +static BOOL queue_task( struct task_header *task ) { - request_t *request = task->request; + struct request *request = task->request; +#ifdef __REACTOS__ if (!request->task_thread) +#else + if (!request->task_wait) +#endif { if (!(request->task_wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE; if (!(request->task_cancel = CreateEventW( NULL, FALSE, FALSE, NULL ))) @@ -253,7 +266,11 @@ static BOOL queue_task( task_header_t *task ) request->task_wait = NULL; return FALSE; } +#ifdef __REACTOS__ if (!(request->task_thread = CreateThread( NULL, 0, task_proc, request, 0, NULL ))) +#else + if (!TrySubmitThreadpoolCallback( task_proc, request, NULL )) +#endif { CloseHandle( request->task_wait ); request->task_wait = NULL; @@ -261,6 +278,9 @@ static BOOL queue_task( task_header_t *task ) request->task_cancel = NULL; return FALSE; } +#ifndef __REACTOS__ + request->task_proc_running = TRUE; +#endif InitializeCriticalSection( &request->task_cs ); request->task_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": request.task_cs"); } @@ -274,7 +294,7 @@ static BOOL queue_task( task_header_t *task ) return TRUE; } -static void free_header( header_t *header ) +static void free_header( struct header *header ) { heap_free( header->field ); heap_free( header->value ); @@ -302,10 +322,10 @@ static BOOL valid_token_char( WCHAR c ) } } -static header_t *parse_header( LPCWSTR string ) +static struct header *parse_header( const WCHAR *string ) { const WCHAR *p, *q; - header_t *header; + struct header *header; int len; p = string; @@ -329,7 +349,7 @@ static header_t *parse_header( LPCWSTR string ) p++; } len = q - string; - if (!(header = heap_alloc_zero( sizeof(header_t) ))) return NULL; + if (!(header = heap_alloc_zero( sizeof(struct header) ))) return NULL; if (!(header->field = heap_alloc( (len + 1) * sizeof(WCHAR) ))) { heap_free( header ); @@ -353,7 +373,7 @@ static header_t *parse_header( LPCWSTR string ) return header; } -static int get_header_index( request_t *request, LPCWSTR field, int requested_index, BOOL request_only ) +static int get_header_index( struct request *request, const WCHAR *field, int requested_index, BOOL request_only ) { int index; @@ -373,15 +393,15 @@ static int get_header_index( request_t *request, LPCWSTR field, int requested_in return index; } -static BOOL insert_header( request_t *request, header_t *header ) +static BOOL insert_header( struct request *request, struct header *header ) { DWORD count = request->num_headers + 1; - header_t *hdrs; + struct header *hdrs; if (request->headers) - hdrs = heap_realloc_zero( request->headers, sizeof(header_t) * count ); + hdrs = heap_realloc_zero( request->headers, sizeof(struct header) * count ); else - hdrs = heap_alloc_zero( sizeof(header_t) ); + hdrs = heap_alloc_zero( sizeof(struct header) ); if (!hdrs) return FALSE; request->headers = hdrs; @@ -392,7 +412,7 @@ static BOOL insert_header( request_t *request, header_t *header ) return TRUE; } -static BOOL delete_header( request_t *request, DWORD index ) +static BOOL delete_header( struct request *request, DWORD index ) { if (!request->num_headers) return FALSE; if (index >= request->num_headers) return FALSE; @@ -401,15 +421,16 @@ static BOOL delete_header( request_t *request, DWORD index ) heap_free( request->headers[index].field ); heap_free( request->headers[index].value ); - memmove( &request->headers[index], &request->headers[index + 1], (request->num_headers - index) * sizeof(header_t) ); - memset( &request->headers[request->num_headers], 0, sizeof(header_t) ); + memmove( &request->headers[index], &request->headers[index + 1], + (request->num_headers - index) * sizeof(struct header) ); + memset( &request->headers[request->num_headers], 0, sizeof(struct header) ); return TRUE; } -BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) +BOOL process_header( struct request *request, const WCHAR *field, const WCHAR *value, DWORD flags, BOOL request_only ) { int index; - header_t hdr; + struct header hdr; TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags); @@ -427,7 +448,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla } else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD)) { - set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND ); + SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND ); return FALSE; } @@ -444,7 +465,7 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla { WCHAR *tmp; int len, len_orig, len_value; - header_t *header = &request->headers[index]; + struct header *header = &request->headers[index]; len_orig = strlenW( header->value ); len_value = strlenW( value ); @@ -471,11 +492,11 @@ BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD fla return TRUE; } -BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags ) +BOOL add_request_headers( struct request *request, const WCHAR *headers, DWORD len, DWORD flags ) { BOOL ret = FALSE; WCHAR *buffer, *p, *q; - header_t *header; + struct header *header; if (len == ~0u) len = strlenW( headers ); if (!len) return TRUE; @@ -521,134 +542,116 @@ BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD BOOL WINAPI WinHttpAddRequestHeaders( HINTERNET hrequest, LPCWSTR headers, DWORD len, DWORD flags ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %s, %u, 0x%08x\n", hrequest, debugstr_wn(headers, len), len, flags); if (!headers || !len) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } ret = add_request_headers( request, headers, len, flags ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static WCHAR *build_request_path( request_t *request ) +static WCHAR *build_absolute_request_path( struct request *request, const WCHAR **path ) { + static const WCHAR http[] = {'h','t','t','p',0}; + static const WCHAR https[] = {'h','t','t','p','s',0}; + static const WCHAR fmt[] = {'%','s',':','/','/','%','s',0}; + const WCHAR *scheme; WCHAR *ret; + int len; - if (strcmpiW( request->connect->hostname, request->connect->servername )) - { - static const WCHAR http[] = { 'h','t','t','p',0 }; - static const WCHAR https[] = { 'h','t','t','p','s',0 }; - static const WCHAR fmt[] = { '%','s',':','/','/','%','s',0 }; - LPCWSTR scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http; - int len; + scheme = (request->netconn ? request->netconn->secure : (request->hdr.flags & WINHTTP_FLAG_SECURE)) ? https : http; + + len = strlenW( scheme ) + strlenW( request->connect->hostname ) + 4; /* '://' + nul */ + if (request->connect->hostport) len += 6; /* ':' between host and port, up to 5 for port */ - len = strlenW( scheme ) + strlenW( request->connect->hostname ); - /* 3 characters for '://', 1 for NUL. */ - len += 4; + len += strlenW( request->path ); + if ((ret = heap_alloc( len * sizeof(WCHAR) ))) + { + len = sprintfW( ret, fmt, scheme, request->connect->hostname ); if (request->connect->hostport) { - /* 1 for ':' between host and port, up to 5 for port */ - len += 6; - } - if (request->path) - len += strlenW( request->path ); - if ((ret = heap_alloc( len * sizeof(WCHAR) ))) - { - sprintfW( ret, fmt, scheme, request->connect->hostname ); - if (request->connect->hostport) - { - static const WCHAR colonFmt[] = { ':','%','u',0 }; - - sprintfW( ret + strlenW( ret ), colonFmt, - request->connect->hostport ); - } - if (request->path) - strcatW( ret, request->path ); + static const WCHAR port_fmt[] = {':','%','u',0}; + len += sprintfW( ret + len, port_fmt, request->connect->hostport ); } + strcpyW( ret + len, request->path ); + if (path) *path = ret + len; } - else - ret = request->path; + return ret; } -static WCHAR *build_request_string( request_t *request ) +static WCHAR *build_request_string( struct request *request ) { - static const WCHAR space[] = {' ',0}; - static const WCHAR crlf[] = {'\r','\n',0}; - static const WCHAR colon[] = {':',' ',0}; - static const WCHAR twocrlf[] = {'\r','\n','\r','\n',0}; - + static const WCHAR spaceW[] = {' ',0}, crlfW[] = {'\r','\n',0}, colonW[] = {':',' ',0}; + static const WCHAR twocrlfW[] = {'\r','\n','\r','\n',0}; WCHAR *path, *ret; - const WCHAR **headers, **p; - unsigned int len, i = 0, j; + unsigned int i, len; - /* allocate space for an array of all the string pointers to be added */ - len = request->num_headers * 4 + 7; - if (!(headers = heap_alloc( len * sizeof(LPCWSTR) ))) return NULL; + if (!strcmpiW( request->connect->hostname, request->connect->servername )) path = request->path; + else if (!(path = build_absolute_request_path( request, NULL ))) return NULL; - path = build_request_path( request ); - headers[i++] = request->verb; - headers[i++] = space; - headers[i++] = path; - headers[i++] = space; - headers[i++] = request->version; + len = strlenW( request->verb ) + 1 /* ' ' */; + len += strlenW( path ) + 1 /* ' ' */; + len += strlenW( request->version ); - for (j = 0; j < request->num_headers; j++) + for (i = 0; i < request->num_headers; i++) { - if (request->headers[j].is_request) - { - headers[i++] = crlf; - headers[i++] = request->headers[j].field; - headers[i++] = colon; - headers[i++] = request->headers[j].value; - - TRACE("adding header %s (%s)\n", debugstr_w(request->headers[j].field), - debugstr_w(request->headers[j].value)); - } + if (request->headers[i].is_request) + len += strlenW( request->headers[i].field ) + strlenW( request->headers[i].value ) + 4; /* '\r\n: ' */ } - headers[i++] = twocrlf; - headers[i] = NULL; + len += 4; /* '\r\n\r\n' */ - len = 0; - for (p = headers; *p; p++) len += strlenW( *p ); - len++; + if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + strcpyW( ret, request->verb ); + strcatW( ret, spaceW ); + strcatW( ret, path ); + strcatW( ret, spaceW ); + strcatW( ret, request->version ); - if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) - goto out; - *ret = 0; - for (p = headers; *p; p++) strcatW( ret, *p ); + for (i = 0; i < request->num_headers; i++) + { + if (request->headers[i].is_request) + { + strcatW( ret, crlfW ); + strcatW( ret, request->headers[i].field ); + strcatW( ret, colonW ); + strcatW( ret, request->headers[i].value ); + } + } + strcatW( ret, twocrlfW ); + } -out: - if (path != request->path) - heap_free( path ); - heap_free( headers ); + if (path != request->path) heap_free( path ); return ret; } #define QUERY_MODIFIER_MASK (WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_FLAG_SYSTEMTIME | WINHTTP_QUERY_FLAG_NUMBER) -static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index ) +static BOOL query_headers( struct request *request, DWORD level, const WCHAR *name, void *buffer, DWORD *buflen, + DWORD *index ) { - header_t *header = NULL; + struct header *header = NULL; BOOL request_only, ret = FALSE; int requested_index, header_index = -1; DWORD attr, len; @@ -677,7 +680,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID for (len = 0; *p; p++) if (*p != '\r') len++; if (!buffer || len * sizeof(WCHAR) > *buflen) - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); else { for (p = headers, q = buffer; *p; p++, q++) @@ -711,7 +714,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID if (!buffer || len + sizeof(WCHAR) > *buflen) { len += sizeof(WCHAR); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { @@ -728,7 +731,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID if (!buffer || len + sizeof(WCHAR) > *buflen) { len += sizeof(WCHAR); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { @@ -744,7 +747,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID if (!buffer || len + sizeof(WCHAR) > *buflen) { len += sizeof(WCHAR); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { @@ -755,10 +758,32 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID *buflen = len; return ret; + case WINHTTP_QUERY_REQUEST_METHOD: + len = strlenW( request->verb ) * sizeof(WCHAR); + if (!buffer || len + sizeof(WCHAR) > *buflen) + { + len += sizeof(WCHAR); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + } + else + { + strcpyW( buffer, request->verb ); + TRACE("returning string: %s\n", debugstr_w(buffer)); + ret = TRUE; + } + *buflen = len; + return ret; + default: - if (attr >= sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr]) + if (attr >= ARRAY_SIZE(attribute_table)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if (!attribute_table[attr]) { FIXME("attribute %u not implemented\n", attr); + SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND ); return FALSE; } TRACE("attribute %s\n", debugstr_w(attribute_table[attr])); @@ -772,15 +797,14 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID } if (!header || (request_only && !header->is_request)) { - set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND ); + SetLastError( ERROR_WINHTTP_HEADER_NOT_FOUND ); return FALSE; } - if (index) *index += 1; if (level & WINHTTP_QUERY_FLAG_NUMBER) { if (!buffer || sizeof(int) > *buflen) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { @@ -796,7 +820,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID SYSTEMTIME *st = buffer; if (!buffer || sizeof(SYSTEMTIME) > *buflen) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else if ((ret = WinHttpTimeToSystemTime( header->value, st ))) { @@ -812,7 +836,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID if (!buffer || len + sizeof(WCHAR) > *buflen) { len += sizeof(WCHAR); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { @@ -822,6 +846,7 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID } *buflen = len; } + if (ret && index) *index += 1; return ret; } @@ -831,32 +856,29 @@ static BOOL query_headers( request_t *request, DWORD level, LPCWSTR name, LPVOID BOOL WINAPI WinHttpQueryHeaders( HINTERNET hrequest, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, 0x%08x, %s, %p, %p, %p\n", hrequest, level, debugstr_w(name), buffer, buflen, index); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } ret = query_headers( request, level, name, buffer, buflen, index ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -#undef ARRAYSIZE -#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0])) - static const WCHAR basicW[] = {'B','a','s','i','c',0}; static const WCHAR ntlmW[] = {'N','T','L','M',0}; static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0}; @@ -871,27 +893,26 @@ static const struct } auth_schemes[] = { - { basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC }, - { ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM }, - { passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT }, - { digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST }, - { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE } + { basicW, ARRAY_SIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC }, + { ntlmW, ARRAY_SIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM }, + { passportW, ARRAY_SIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT }, + { digestW, ARRAY_SIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST }, + { negotiateW, ARRAY_SIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE } }; -static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]); static enum auth_scheme scheme_from_flag( DWORD flag ) { int i; - for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return i; + for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) if (flag == auth_schemes[i].scheme) return i; return SCHEME_INVALID; } -static DWORD auth_scheme_from_header( WCHAR *header ) +static DWORD auth_scheme_from_header( const WCHAR *header ) { unsigned int i; - for (i = 0; i < num_auth_schemes; i++) + for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) { if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) && (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme; @@ -899,7 +920,7 @@ static DWORD auth_scheme_from_header( WCHAR *header ) return 0; } -static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD supported, LPDWORD first ) +static BOOL query_auth_schemes( struct request *request, DWORD level, DWORD *supported, DWORD *first ) { DWORD index = 0, supported_schemes = 0, first_scheme = 0; BOOL ret = FALSE; @@ -911,9 +932,8 @@ static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD support size = 0; query_headers( request, level, NULL, NULL, &size, &index ); - if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) break; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break; - index--; if (!(buffer = heap_alloc( size ))) return FALSE; if (!query_headers( request, level, NULL, buffer, &size, &index )) { @@ -944,25 +964,25 @@ static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD support BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDWORD first, LPDWORD target ) { BOOL ret = FALSE; - request_t *request; + struct request *request; TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } if (!supported || !first || !target) { release_object( &request->hdr ); - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -977,9 +997,10 @@ BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDW *target = WINHTTP_AUTH_TARGET_PROXY; ret = TRUE; } + else SetLastError( ERROR_INVALID_OPERATION ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } @@ -1127,7 +1148,7 @@ void destroy_authinfo( struct authinfo *authinfo ) heap_free( authinfo ); } -static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len ) +static BOOL get_authvalue( struct request *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len ) { DWORD size, index = 0; for (;;) @@ -1139,7 +1160,7 @@ static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR return TRUE; } -static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag ) +static BOOL do_authorization( struct request *request, DWORD target, DWORD scheme_flag ) { struct authinfo *authinfo, **auth_ptr; enum auth_scheme scheme = scheme_from_flag( scheme_flag ); @@ -1368,129 +1389,76 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla return ret; } -static LPWSTR concatenate_string_list( LPCWSTR *list, int len ) +static WCHAR *build_proxy_connect_string( struct request *request ) { - LPCWSTR *t; - LPWSTR str; - - for( t = list; *t ; t++ ) - len += strlenW( *t ); - len++; - - str = heap_alloc( len * sizeof(WCHAR) ); - if (!str) return NULL; - *str = 0; + static const WCHAR fmtW[] = {'%','s',':','%','u',0}; + static const WCHAR connectW[] = {'C','O','N','N','E','C','T', 0}; + static const WCHAR spaceW[] = {' ',0}, crlfW[] = {'\r','\n',0}, colonW[] = {':',' ',0}; + static const WCHAR twocrlfW[] = {'\r','\n','\r','\n',0}; + WCHAR *ret, *host; + unsigned int i; + int len; - for( t = list; *t ; t++ ) - strcatW( str, *t ); + if (!(host = heap_alloc( (strlenW( request->connect->hostname ) + 7) * sizeof(WCHAR) ))) return NULL; + len = sprintfW( host, fmtW, request->connect->hostname, request->connect->hostport ); - return str; -} + len += ARRAY_SIZE(connectW); + len += ARRAY_SIZE(http1_1); -static LPWSTR build_header_request_string( request_t *request, LPCWSTR verb, - LPCWSTR path, LPCWSTR version ) -{ - static const WCHAR crlf[] = {'\r','\n',0}; - static const WCHAR space[] = { ' ',0 }; - static const WCHAR colon[] = { ':',' ',0 }; - static const WCHAR twocrlf[] = {'\r','\n','\r','\n', 0}; - LPWSTR requestString; - DWORD len, n; - LPCWSTR *req; - UINT i; - LPWSTR p; - - /* allocate space for an array of all the string pointers to be added */ - len = (request->num_headers) * 4 + 10; - req = heap_alloc( len * sizeof(LPCWSTR) ); - if (!req) return NULL; - - /* add the verb, path and HTTP version string */ - n = 0; - req[n++] = verb; - req[n++] = space; - req[n++] = path; - req[n++] = space; - req[n++] = version; - - /* Append custom request headers */ for (i = 0; i < request->num_headers; i++) { if (request->headers[i].is_request) - { - req[n++] = crlf; - req[n++] = request->headers[i].field; - req[n++] = colon; - req[n++] = request->headers[i].value; - - TRACE("Adding custom header %s (%s)\n", - debugstr_w(request->headers[i].field), - debugstr_w(request->headers[i].value)); - } + len += strlenW( request->headers[i].field ) + strlenW( request->headers[i].value ) + 4; /* '\r\n: ' */ } + len += 4; /* '\r\n\r\n' */ - if( n >= len ) - ERR("oops. buffer overrun\n"); - - req[n] = NULL; - requestString = concatenate_string_list( req, 4 ); - heap_free( req ); - if (!requestString) return NULL; + if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + strcpyW( ret, connectW ); + strcatW( ret, spaceW ); + strcatW( ret, host ); + strcatW( ret, spaceW ); + strcatW( ret, http1_1 ); - /* - * Set (header) termination string for request - * Make sure there are exactly two new lines at the end of the request - */ - p = &requestString[strlenW(requestString)-1]; - while ( (*p == '\n') || (*p == '\r') ) - p--; - strcpyW( p+1, twocrlf ); + for (i = 0; i < request->num_headers; i++) + { + if (request->headers[i].is_request) + { + strcatW( ret, crlfW ); + strcatW( ret, request->headers[i].field ); + strcatW( ret, colonW ); + strcatW( ret, request->headers[i].value ); + } + } + strcatW( ret, twocrlfW ); + } - return requestString; + heap_free( host ); + return ret; } -static BOOL read_reply( request_t *request ); +static BOOL read_reply( struct request *request ); -static BOOL secure_proxy_connect( request_t *request ) +static BOOL secure_proxy_connect( struct request *request ) { - static const WCHAR verbConnect[] = {'C','O','N','N','E','C','T',0}; - static const WCHAR fmt[] = {'%','s',':','%','u',0}; - BOOL ret = FALSE; - LPWSTR path; - connect_t *connect = request->connect; - - path = heap_alloc( (strlenW( connect->hostname ) + 13) * sizeof(WCHAR) ); - if (path) - { - LPWSTR requestString; + WCHAR *str; + char *strA; + int len, bytes_sent; + BOOL ret; - sprintfW( path, fmt, connect->hostname, connect->hostport ); - requestString = build_header_request_string( request, verbConnect, - path, http1_1 ); - heap_free( path ); - if (requestString) - { - LPSTR req_ascii = strdupWA( requestString ); + if (!(str = build_proxy_connect_string( request ))) return FALSE; + strA = strdupWA( str ); + heap_free( str ); + if (!strA) return FALSE; - heap_free( requestString ); - if (req_ascii) - { - int len = strlen( req_ascii ), bytes_sent; + len = strlen( strA ); + ret = netconn_send( request->netconn, strA, len, &bytes_sent ); + heap_free( strA ); + if (ret) ret = read_reply( request ); - ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); - heap_free( req_ascii ); - if (ret) - ret = read_reply( request ); - } - } - } return ret; } -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif - static WCHAR *addr_to_str( struct sockaddr_storage *addr ) { char buf[INET6_ADDRSTRLEN]; @@ -1523,7 +1491,7 @@ static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, static struct list connection_pool = LIST_INIT( connection_pool ); -void release_host( hostdata_t *host ) +void release_host( struct hostdata *host ) { LONG ref; @@ -1539,11 +1507,15 @@ void release_host( hostdata_t *host ) static BOOL connection_collector_running; +#ifdef __REACTOS__ static DWORD WINAPI connection_collector(void *arg) +#else +static void CALLBACK connection_collector( TP_CALLBACK_INSTANCE *instance, void *ctx ) +#endif { unsigned int remaining_connections; - netconn_t *netconn, *next_netconn; - hostdata_t *host, *next_host; + struct netconn *netconn, *next_netconn; + struct hostdata *host, *next_host; ULONGLONG now; do @@ -1555,9 +1527,9 @@ static DWORD WINAPI connection_collector(void *arg) EnterCriticalSection(&connection_pool_cs); - LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t, entry) + LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, struct hostdata, entry) { - LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, netconn_t, entry) + LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, struct netconn, entry) { if (netconn->keep_until < now) { @@ -1565,10 +1537,7 @@ static DWORD WINAPI connection_collector(void *arg) list_remove(&netconn->entry); netconn_close(netconn); } - else - { - remaining_connections++; - } + else remaining_connections++; } } @@ -1577,10 +1546,14 @@ static DWORD WINAPI connection_collector(void *arg) LeaveCriticalSection(&connection_pool_cs); } while(remaining_connections); +#ifdef __REACTOS__ FreeLibraryAndExitThread( winhttp_instance, 0 ); +#else + FreeLibraryWhenCallbackReturns( instance, winhttp_instance ); +#endif } -static void cache_connection( netconn_t *netconn ) +static void cache_connection( struct netconn *netconn ) { TRACE( "caching connection %p\n", netconn ); @@ -1592,10 +1565,13 @@ static void cache_connection( netconn_t *netconn ) if (!connection_collector_running) { HMODULE module; +#ifdef __REACTOS__ HANDLE thread; +#endif - GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)winhttp_instance, &module ); + GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR *)winhttp_instance, &module ); +#ifdef __REACTOS__ thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL); if (thread) { @@ -1606,6 +1582,10 @@ static void cache_connection( netconn_t *netconn ) { FreeLibrary( winhttp_instance ); } +#else + if (TrySubmitThreadpoolCallback( connection_collector, NULL, NULL )) connection_collector_running = TRUE; + else FreeLibrary( winhttp_instance ); +#endif } LeaveCriticalSection( &connection_pool_cs ); @@ -1622,32 +1602,43 @@ static DWORD map_secure_protocols( DWORD mask ) return ret; } -static BOOL ensure_cred_handle( session_t *session ) +static BOOL ensure_cred_handle( struct request *request ) { - SCHANNEL_CRED cred; - SECURITY_STATUS status; + SECURITY_STATUS status = SEC_E_OK; + + if (request->cred_handle_initialized) return TRUE; - if (session->cred_handle_initialized) return TRUE; + if (!request->cred_handle_initialized) + { + SCHANNEL_CRED cred; + memset( &cred, 0, sizeof(cred) ); + cred.dwVersion = SCHANNEL_CRED_VERSION; + cred.grbitEnabledProtocols = map_secure_protocols( request->connect->session->secure_protocols ); + if (request->client_cert) + { + cred.paCred = &request->client_cert; + cred.cCreds = 1; + } + status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, + &cred, NULL, NULL, &request->cred_handle, NULL ); + if (status == SEC_E_OK) + request->cred_handle_initialized = TRUE; + } - memset( &cred, 0, sizeof(cred) ); - cred.dwVersion = SCHANNEL_CRED_VERSION; - cred.grbitEnabledProtocols = map_secure_protocols( session->secure_protocols ); - if ((status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred, - NULL, NULL, &session->cred_handle, NULL )) != SEC_E_OK) + if (status != SEC_E_OK) { WARN( "AcquireCredentialsHandleW failed: 0x%08x\n", status ); return FALSE; } - session->cred_handle_initialized = TRUE; return TRUE; } -static BOOL open_connection( request_t *request ) +static BOOL open_connection( struct request *request ) { BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE; - hostdata_t *host = NULL, *iter; - netconn_t *netconn = NULL; - connect_t *connect; + struct hostdata *host = NULL, *iter; + struct netconn *netconn = NULL; + struct connect *connect; WCHAR *addressW = NULL; INTERNET_PORT port; DWORD len; @@ -1659,7 +1650,7 @@ static BOOL open_connection( request_t *request ) EnterCriticalSection( &connection_pool_cs ); - LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry ) + LIST_FOR_EACH_ENTRY( iter, &connection_pool, struct hostdata, entry ) { if (iter->port == port && !strcmpW( connect->servername, iter->hostname ) && !is_secure == !iter->secure) { @@ -1698,7 +1689,7 @@ static BOOL open_connection( request_t *request ) EnterCriticalSection( &connection_pool_cs ); if (!list_empty( &host->connections )) { - netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, entry ); + netconn = LIST_ENTRY( list_head( &host->connections ), struct netconn, entry ); list_remove( &netconn->entry ); } LeaveCriticalSection( &connection_pool_cs ); @@ -1756,7 +1747,10 @@ static BOOL open_connection( request_t *request ) return FALSE; } netconn_set_timeout( netconn, TRUE, request->send_timeout ); - netconn_set_timeout( netconn, FALSE, request->recv_timeout ); + netconn_set_timeout( netconn, FALSE, request->receive_response_timeout ); + + request->netconn = netconn; + if (is_secure) { if (connect->session->proxy_server && @@ -1764,22 +1758,27 @@ static BOOL open_connection( request_t *request ) { if (!secure_proxy_connect( request )) { + request->netconn = NULL; heap_free( addressW ); netconn_close( netconn ); return FALSE; } } - if (!ensure_cred_handle( connect->session ) || + + CertFreeCertificateContext( request->server_cert ); + request->server_cert = NULL; + + if (!ensure_cred_handle( request ) || !netconn_secure_connect( netconn, connect->hostname, request->security_flags, - &connect->session->cred_handle )) + &request->cred_handle, request->check_revocation )) { + request->netconn = NULL; heap_free( addressW ); netconn_close( netconn ); return FALSE; } } - request->netconn = netconn; send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 ); } else @@ -1787,10 +1786,17 @@ static BOOL open_connection( request_t *request ) TRACE("using connection %p\n", netconn); netconn_set_timeout( netconn, TRUE, request->send_timeout ); - netconn_set_timeout( netconn, FALSE, request->recv_timeout ); + netconn_set_timeout( netconn, FALSE, request->receive_response_timeout ); request->netconn = netconn; } + if (netconn->secure && !(request->server_cert = netconn_get_certificate( netconn ))) + { + heap_free( addressW ); + netconn_close( netconn ); + return FALSE; + } + done: request->read_pos = request->read_size = 0; request->read_chunked = FALSE; @@ -1800,7 +1806,7 @@ done: return TRUE; } -void close_connection( request_t *request ) +void close_connection( struct request *request ) { if (!request->netconn) return; @@ -1810,13 +1816,13 @@ void close_connection( request_t *request ) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 ); } -static BOOL add_host_header( request_t *request, DWORD modifier ) +static BOOL add_host_header( struct request *request, DWORD modifier ) { BOOL ret; DWORD len; WCHAR *host; static const WCHAR fmt[] = {'%','s',':','%','u',0}; - connect_t *connect = request->connect; + struct connect *connect = request->connect; INTERNET_PORT port; port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); @@ -1833,7 +1839,7 @@ static BOOL add_host_header( request_t *request, DWORD modifier ) return ret; } -static void clear_response_headers( request_t *request ) +static void clear_response_headers( struct request *request ) { unsigned int i; @@ -1848,14 +1854,14 @@ static void clear_response_headers( request_t *request ) } /* remove some amount of data from the read buffer */ -static void remove_data( request_t *request, int count ) +static void remove_data( struct request *request, int count ) { if (!(request->read_size -= count)) request->read_pos = 0; else request->read_pos += count; } /* read some more data into the read buffer */ -static BOOL read_more_data( request_t *request, int maxlen, BOOL notify ) +static BOOL read_more_data( struct request *request, int maxlen, BOOL notify ) { int len; BOOL ret; @@ -1882,7 +1888,7 @@ static BOOL read_more_data( request_t *request, int maxlen, BOOL notify ) } /* discard data contents until we reach end of line */ -static BOOL discard_eol( request_t *request, BOOL notify ) +static BOOL discard_eol( struct request *request, BOOL notify ) { do { @@ -1899,7 +1905,7 @@ static BOOL discard_eol( request_t *request, BOOL notify ) } /* read the size of the next chunk */ -static BOOL start_next_chunk( request_t *request, BOOL notify ) +static BOOL start_next_chunk( struct request *request, BOOL notify ) { DWORD chunk_size = 0; @@ -1942,7 +1948,7 @@ static BOOL start_next_chunk( request_t *request, BOOL notify ) } } -static BOOL refill_buffer( request_t *request, BOOL notify ) +static BOOL refill_buffer( struct request *request, BOOL notify ) { int len = sizeof(request->read_buf); @@ -1966,7 +1972,7 @@ static BOOL refill_buffer( request_t *request, BOOL notify ) return TRUE; } -static void finished_reading( request_t *request ) +static void finished_reading( struct request *request ) { static const WCHAR closeW[] = {'c','l','o','s','e',0}; @@ -1994,14 +2000,14 @@ static void finished_reading( request_t *request ) } /* return the size of data available to be read immediately */ -static DWORD get_available_data( request_t *request ) +static DWORD get_available_data( struct request *request ) { if (request->read_chunked) return min( request->read_chunked_size, request->read_size ); return request->read_size; } /* check if we have reached the end of the data to read */ -static BOOL end_of_read_data( request_t *request ) +static BOOL end_of_read_data( struct request *request ) { if (!request->content_length) return TRUE; if (request->read_chunked) return request->read_chunked_eof; @@ -2009,9 +2015,10 @@ static BOOL end_of_read_data( request_t *request ) return (request->content_length == request->content_read); } -static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) +static BOOL read_data( struct request *request, void *buffer, DWORD size, DWORD *read, BOOL async ) { int count, bytes_read = 0; + BOOL ret = TRUE; if (end_of_read_data( request )) goto done; @@ -2019,7 +2026,7 @@ static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read { if (!(count = get_available_data( request ))) { - if (!refill_buffer( request, async )) goto done; + if (!(ret = refill_buffer( request, async ))) goto done; if (!(count = get_available_data( request ))) goto done; } count = min( count, size ); @@ -2031,19 +2038,29 @@ static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read request->content_read += count; if (end_of_read_data( request )) goto done; } - if (request->read_chunked && !request->read_chunked_size) refill_buffer( request, async ); + if (request->read_chunked && !request->read_chunked_size) ret = refill_buffer( request, async ); done: TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, request->content_read, request->content_length ); + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_READ_DATA; + result.dwError = GetLastError(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } - if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read ); - if (read) *read = bytes_read; + if (ret && read) *read = bytes_read; if (end_of_read_data( request )) finished_reading( request ); - return TRUE; + return ret; } /* read any content returned by the server so that the connection can be reused */ -static void drain_content( request_t *request ) +static void drain_content( struct request *request ) { DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read; char buffer[2048]; @@ -2062,7 +2079,177 @@ static void drain_content( request_t *request ) } } -static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional, +enum escape_flags +{ + ESCAPE_FLAG_NON_PRINTABLE = 0x01, + ESCAPE_FLAG_SPACE = 0x02, + ESCAPE_FLAG_PERCENT = 0x04, + ESCAPE_FLAG_UNSAFE = 0x08, + ESCAPE_FLAG_DEL = 0x10, + ESCAPE_FLAG_8BIT = 0x20, + ESCAPE_FLAG_STRIP_CRLF = 0x40, +}; + +#define ESCAPE_MASK_DEFAULT (ESCAPE_FLAG_NON_PRINTABLE | ESCAPE_FLAG_SPACE | ESCAPE_FLAG_UNSAFE |\ + ESCAPE_FLAG_DEL | ESCAPE_FLAG_8BIT) +#define ESCAPE_MASK_PERCENT (ESCAPE_FLAG_PERCENT | ESCAPE_MASK_DEFAULT) +#define ESCAPE_MASK_DISABLE (ESCAPE_FLAG_SPACE | ESCAPE_FLAG_8BIT | ESCAPE_FLAG_STRIP_CRLF) + +static inline BOOL need_escape( char ch, enum escape_flags flags ) +{ + static const char unsafe[] = "\"#<>[\\]^`{|}"; + const char *ptr = unsafe; + + if ((flags & ESCAPE_FLAG_SPACE) && ch == ' ') return TRUE; + if ((flags & ESCAPE_FLAG_PERCENT) && ch == '%') return TRUE; + if ((flags & ESCAPE_FLAG_NON_PRINTABLE) && ch < 0x20) return TRUE; + if ((flags & ESCAPE_FLAG_DEL) && ch == 0x7f) return TRUE; + if ((flags & ESCAPE_FLAG_8BIT) && (ch & 0x80)) return TRUE; + if ((flags & ESCAPE_FLAG_UNSAFE)) while (*ptr) { if (ch == *ptr++) return TRUE; } + return FALSE; +} + +static DWORD escape_string( const char *src, DWORD len, char *dst, enum escape_flags flags ) +{ + static const char hex[] = "0123456789ABCDEF"; + DWORD i, ret = len; + char *ptr = dst; + + for (i = 0; i < len; i++) + { + if ((flags & ESCAPE_FLAG_STRIP_CRLF) && (src[i] == '\r' || src[i] == '\n')) + { + ret--; + continue; + } + if (need_escape( src[i], flags )) + { + if (dst) + { + ptr[0] = '%'; + ptr[1] = hex[(src[i] >> 4) & 0xf]; + ptr[2] = hex[src[i] & 0xf]; + ptr += 3; + } + ret += 2; + } + else if (dst) *ptr++ = src[i]; + } + + if (dst) dst[ret] = 0; + return ret; +} + +static DWORD str_to_wire( const WCHAR *src, int src_len, char *dst, enum escape_flags flags ) +{ + DWORD len; + char *utf8; + + if (src_len < 0) src_len = strlenW( src ); + len = WideCharToMultiByte( CP_UTF8, 0, src, src_len, NULL, 0, NULL, NULL ); + if (!(utf8 = heap_alloc( len ))) return 0; + + WideCharToMultiByte( CP_UTF8, 0, src, -1, utf8, len, NULL, NULL ); + len = escape_string( utf8, len, dst, flags ); + heap_free( utf8 ); + + return len; +} + +static char *build_wire_path( struct request *request, DWORD *ret_len ) +{ + WCHAR *full_path; + const WCHAR *start, *path, *query = NULL; + DWORD len, len_path = 0, len_query = 0; + enum escape_flags path_flags, query_flags; + char *ret; + + if (!strcmpiW( request->connect->hostname, request->connect->servername )) start = full_path = request->path; + else if (!(full_path = build_absolute_request_path( request, &start ))) return NULL; + + len = strlenW( full_path ); + if ((path = strchrW( start, '/' ))) + { + len_path = strlenW( path ); + if ((query = strchrW( path, '?' ))) + { + len_query = strlenW( query ); + len_path -= len_query; + } + } + + if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE) path_flags = ESCAPE_MASK_DISABLE; + else if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_PERCENT) path_flags = ESCAPE_MASK_PERCENT; + else path_flags = ESCAPE_MASK_DEFAULT; + + if (request->hdr.flags & WINHTTP_FLAG_ESCAPE_DISABLE_QUERY) query_flags = ESCAPE_MASK_DISABLE; + else query_flags = path_flags; + + *ret_len = str_to_wire( full_path, len - len_path - len_query, NULL, 0 ); + if (path) *ret_len += str_to_wire( path, len_path, NULL, path_flags ); + if (query) *ret_len += str_to_wire( query, len_query, NULL, query_flags ); + + if ((ret = heap_alloc( *ret_len + 1 ))) + { + len = str_to_wire( full_path, len - len_path - len_query, ret, 0 ); + if (path) len += str_to_wire( path, len_path, ret + len, path_flags ); + if (query) str_to_wire( query, len_query, ret + len, query_flags ); + } + + if (full_path != request->path) heap_free( full_path ); + return ret; +} + +static char *build_wire_request( struct request *request, DWORD *len ) +{ + char *path, *ptr, *ret; + DWORD i, len_path; + + if (!(path = build_wire_path( request, &len_path ))) return NULL; + + *len = str_to_wire( request->verb, -1, NULL, 0 ) + 1; /* ' ' */ + *len += len_path + 1; /* ' ' */ + *len += str_to_wire( request->version, -1, NULL, 0 ); + + for (i = 0; i < request->num_headers; i++) + { + if (request->headers[i].is_request) + { + *len += str_to_wire( request->headers[i].field, -1, NULL, 0 ) + 2; /* ': ' */ + *len += str_to_wire( request->headers[i].value, -1, NULL, 0 ) + 2; /* '\r\n' */ + } + } + *len += 4; /* '\r\n\r\n' */ + + if ((ret = ptr = heap_alloc( *len + 1 ))) + { + ptr += str_to_wire( request->verb, -1, ptr, 0 ); + *ptr++ = ' '; + memcpy( ptr, path, len_path ); + ptr += len_path; + *ptr++ = ' '; + ptr += str_to_wire( request->version, -1, ptr, 0 ); + + for (i = 0; i < request->num_headers; i++) + { + if (request->headers[i].is_request) + { + *ptr++ = '\r'; + *ptr++ = '\n'; + ptr += str_to_wire( request->headers[i].field, -1, ptr, 0 ); + *ptr++ = ':'; + *ptr++ = ' '; + ptr += str_to_wire( request->headers[i].value, -1, ptr, 0 ); + } + } + memcpy( ptr, "\r\n\r\n", sizeof("\r\n\r\n") ); + } + + heap_free( path ); + return ret; +} + +static BOOL send_request( struct request *request, const WCHAR *headers, DWORD headers_len, void *optional, DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async ) { static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0}; @@ -2070,10 +2257,9 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len static const WCHAR length_fmt[] = {'%','l','d',0}; BOOL ret = FALSE; - connect_t *connect = request->connect; - session_t *session = connect->session; - WCHAR *req = NULL; - char *req_ascii; + struct connect *connect = request->connect; + struct session *session = connect->session; + char *wire_req; int bytes_sent; DWORD len; @@ -2118,16 +2304,13 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len if (context) request->hdr.context = context; if (!(ret = open_connection( request ))) goto end; - if (!(req = build_request_string( request ))) goto end; - - if (!(req_ascii = strdupWA( req ))) goto end; - TRACE("full request: %s\n", debugstr_a(req_ascii)); - len = strlen(req_ascii); + if (!(wire_req = build_wire_request( request, &len ))) goto end; + TRACE("full request: %s\n", debugstr_a(wire_req)); send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 ); - ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); - heap_free( req_ascii ); + ret = netconn_send( request->netconn, wire_req, len, &bytes_sent ); + heap_free( wire_req ); if (!ret) goto end; if (optional_len) @@ -2147,17 +2330,16 @@ end: { WINHTTP_ASYNC_RESULT result; result.dwResult = API_SEND_REQUEST; - result.dwError = get_last_error(); + result.dwError = GetLastError(); send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); } } - heap_free( req ); return ret; } -static void task_send_request( task_header_t *task ) +static void task_send_request( struct task_header *task ) { - send_request_t *s = (send_request_t *)task; + struct send_request *s = (struct send_request *)task; send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); heap_free( s->headers ); } @@ -2169,20 +2351,20 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context ) { BOOL ret; - request_t *request; + struct request *request; - TRACE("%p, %s, %u, %u, %u, %lx\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional_len, - total_len, context); + TRACE("%p, %s, %u, %p, %u, %u, %lx\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional, + optional_len, total_len, context); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } @@ -2190,9 +2372,9 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) { - send_request_t *s; + struct send_request *s; - if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE; + if (!(s = heap_alloc( sizeof(struct send_request) ))) return FALSE; s->hdr.request = request; s->hdr.proc = task_send_request; s->headers = strdupW( headers ); @@ -2203,24 +2385,24 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade s->context = context; addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)s ); + ret = queue_task( (struct task_header *)s ); } else ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static BOOL set_credentials( request_t *request, DWORD target, DWORD scheme_flag, const WCHAR *username, +static BOOL set_credentials( struct request *request, DWORD target, DWORD scheme_flag, const WCHAR *username, const WCHAR *password ) { enum auth_scheme scheme = scheme_from_flag( scheme_flag ); if (scheme == SCHEME_INVALID || ((scheme == SCHEME_BASIC || scheme == SCHEME_DIGEST) && (!username || !password))) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } switch (target) @@ -2261,30 +2443,30 @@ BOOL WINAPI WinHttpSetCredentials( HINTERNET hrequest, DWORD target, DWORD schem LPCWSTR password, LPVOID params ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %x, 0x%08x, %s, %p, %p\n", hrequest, target, scheme, debugstr_w(username), password, params); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } ret = set_credentials( request, target, scheme, username, password ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static BOOL handle_authorization( request_t *request, DWORD status ) +static BOOL handle_authorization( struct request *request, DWORD status ) { DWORD i, schemes, first, level, target; @@ -2309,7 +2491,7 @@ static BOOL handle_authorization( request_t *request, DWORD status ) if (do_authorization( request, target, first )) return TRUE; schemes &= ~first; - for (i = 0; i < num_auth_schemes; i++) + for (i = 0; i < ARRAY_SIZE( auth_schemes ); i++) { if (!(schemes & auth_schemes[i].scheme)) continue; if (do_authorization( request, target, auth_schemes[i].scheme )) return TRUE; @@ -2318,7 +2500,7 @@ static BOOL handle_authorization( request_t *request, DWORD status ) } /* set the request content length based on the headers */ -static DWORD set_content_length( request_t *request, DWORD status ) +static DWORD set_content_length( struct request *request, DWORD status ) { WCHAR encoding[20]; DWORD buflen = sizeof(request->content_length); @@ -2345,7 +2527,7 @@ static DWORD set_content_length( request_t *request, DWORD status ) return request->content_length; } -static BOOL read_line( request_t *request, char *buffer, DWORD *len ) +static BOOL read_line( struct request *request, char *buffer, DWORD *len ) { int count, bytes_read, pos = 0; @@ -2386,7 +2568,7 @@ static BOOL read_line( request_t *request, char *buffer, DWORD *len ) #define MAX_REPLY_LEN 1460 #define INITIAL_HEADER_BUFFER_LEN 512 -static BOOL read_reply( request_t *request ) +static BOOL read_reply( struct request *request ) { static const WCHAR crlf[] = {'\r','\n',0}; @@ -2450,7 +2632,7 @@ static BOOL read_reply( request_t *request ) offset = buflen + crlf_len - 1; for (;;) { - header_t *header; + struct header *header; buflen = MAX_REPLY_LEN; if (!read_line( request, buffer, &buflen )) return TRUE; @@ -2485,13 +2667,13 @@ static BOOL read_reply( request_t *request ) return TRUE; } -static void record_cookies( request_t *request ) +static void record_cookies( struct request *request ) { unsigned int i; for (i = 0; i < request->num_headers; i++) { - header_t *set_cookie = &request->headers[i]; + struct header *set_cookie = &request->headers[i]; if (!strcmpiW( set_cookie->field, attr_set_cookie ) && !set_cookie->is_request) { set_cookies( request, set_cookie->value ); @@ -2499,59 +2681,60 @@ static void record_cookies( request_t *request ) } } -static WCHAR *get_redirect_url( request_t *request, DWORD *len ) +static WCHAR *get_redirect_url( struct request *request, DWORD *len ) { DWORD size; WCHAR *ret; query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL ); - if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) return FALSE; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL; if (!(ret = heap_alloc( size ))) return NULL; - *len = size / sizeof(WCHAR); + *len = size / sizeof(WCHAR) - 1; if (query_headers( request, WINHTTP_QUERY_LOCATION, NULL, ret, &size, NULL )) return ret; heap_free( ret ); return NULL; } -static BOOL handle_redirect( request_t *request, DWORD status ) +static BOOL handle_redirect( struct request *request, DWORD status ) { BOOL ret = FALSE; - DWORD len, len_url; + DWORD len, len_loc; URL_COMPONENTS uc; - connect_t *connect = request->connect; + struct connect *connect = request->connect; INTERNET_PORT port; WCHAR *hostname = NULL, *location; int index; - if (!(location = get_redirect_url( request, &len_url ))) return FALSE; + if (!(location = get_redirect_url( request, &len_loc ))) return FALSE; memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0u; - if (!WinHttpCrackUrl( location, len_url, 0, &uc )) /* assume relative redirect */ + if (!WinHttpCrackUrl( location, len_loc, 0, &uc )) /* assume relative redirect */ { WCHAR *path, *p; if (location[0] == '/') { - len = strlenW( location ); - if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - strcpyW( path, location ); + if (!(path = heap_alloc( (len_loc + 1) * sizeof(WCHAR) ))) goto end; + memcpy( path, location, len_loc * sizeof(WCHAR) ); + path[len_loc] = 0; } else { if ((p = strrchrW( request->path, '/' ))) *p = 0; - len = strlenW( request->path ) + 1 + strlenW( location ); + len = strlenW( request->path ) + 1 + len_loc; if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; strcpyW( path, request->path ); strcatW( path, slashW ); - strcatW( path, location ); + memcpy( path + strlenW(path), location, len_loc * sizeof(WCHAR) ); + path[len_loc] = 0; } heap_free( request->path ); request->path = path; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_url + 1 ); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_loc + 1 ); } else { @@ -2567,7 +2750,7 @@ static BOOL handle_redirect( request_t *request, DWORD status ) request->hdr.flags |= WINHTTP_FLAG_SECURE; } - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_url + 1 ); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, location, len_loc + 1 ); len = uc.dwHostNameLength; if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; @@ -2599,7 +2782,8 @@ static BOOL handle_redirect( request_t *request, DWORD status ) { len = uc.dwUrlPathLength + uc.dwExtraInfoLength; if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - strcpyW( request->path, uc.lpszUrlPath ); + memcpy( request->path, uc.lpszUrlPath, (len + 1) * sizeof(WCHAR) ); + request->path[len] = 0; } else request->path = strdupW( slashW ); } @@ -2622,16 +2806,59 @@ end: return ret; } -static BOOL receive_response( request_t *request, BOOL async ) +static BOOL is_passport_request( struct request *request ) +{ + static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t','1','.','4'}; + WCHAR buf[1024]; + DWORD len = ARRAY_SIZE(buf); + + if (!(request->connect->session->passport_flags & WINHTTP_ENABLE_PASSPORT_AUTH) || + !query_headers( request, WINHTTP_QUERY_WWW_AUTHENTICATE, NULL, buf, &len, NULL )) return FALSE; + + if (!strncmpiW( buf, passportW, ARRAY_SIZE(passportW) ) && + (buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)])) return TRUE; + + return FALSE; +} + +static BOOL handle_passport_redirect( struct request *request ) +{ + static const WCHAR status401W[] = {'4','0','1',0}; + DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE; + int i, len = strlenW( request->raw_headers ); + WCHAR *p = request->raw_headers; + + if (!process_header( request, attr_status, status401W, flags, FALSE )) return FALSE; + + for (i = 0; i < len; i++) + { + if (i <= len - 3 && p[i] == '3' && p[i + 1] == '0' && p[i + 2] == '2') + { + p[i] = '4'; + p[i + 2] = '1'; + break; + } + } + return TRUE; +} + +static BOOL receive_response( struct request *request, BOOL async ) { BOOL ret; DWORD size, query, status; + if (!request->netconn) + { + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); + return FALSE; + } + + netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout ); for (;;) { if (!(ret = read_reply( request ))) { - set_last_error( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ); + SetLastError( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ); break; } size = sizeof(DWORD); @@ -2642,7 +2869,11 @@ static BOOL receive_response( request_t *request, BOOL async ) if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request ); - if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB) + if (status == HTTP_STATUS_REDIRECT && is_passport_request( request )) + { + ret = handle_passport_redirect( request ); + } + else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB) { if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS || request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) break; @@ -2664,7 +2895,8 @@ static BOOL receive_response( request_t *request, BOOL async ) break; } - if (request->content_length) refill_buffer( request, FALSE ); + netconn_set_timeout( request->netconn, FALSE, request->receive_timeout ); + if (request->content_length) ret = refill_buffer( request, FALSE ); if (async) { @@ -2673,16 +2905,16 @@ static BOOL receive_response( request_t *request, BOOL async ) { WINHTTP_ASYNC_RESULT result; result.dwResult = API_RECEIVE_RESPONSE; - result.dwError = get_last_error(); + result.dwError = GetLastError(); send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); } } return ret; } -static void task_receive_response( task_header_t *task ) +static void task_receive_response( struct task_header *task ) { - receive_response_t *r = (receive_response_t *)task; + struct receive_response *r = (struct receive_response *)task; receive_response( r->hdr.request, TRUE ); } @@ -2692,68 +2924,78 @@ static void task_receive_response( task_header_t *task ) BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %p\n", hrequest, reserved); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) { - receive_response_t *r; + struct receive_response *r; - if (!(r = heap_alloc( sizeof(receive_response_t) ))) return FALSE; + if (!(r = heap_alloc( sizeof(struct receive_response) ))) return FALSE; r->hdr.request = request; r->hdr.proc = task_receive_response; addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)r ); + ret = queue_task( (struct task_header *)r ); } else ret = receive_response( request, FALSE ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static BOOL query_data_available( request_t *request, DWORD *available, BOOL async ) +static BOOL query_data_available( struct request *request, DWORD *available, BOOL async ) { DWORD count = 0; + BOOL ret = TRUE; if (end_of_read_data( request )) goto done; count = get_available_data( request ); - if (!request->read_chunked && request->netconn) - count += netconn_query_data_available( request->netconn ); + if (!request->read_chunked && request->netconn) count += netconn_query_data_available( request->netconn ); if (!count) { - refill_buffer( request, async ); + if (!(ret = refill_buffer( request, async ))) goto done; count = get_available_data( request ); - if (!request->read_chunked && request->netconn) - count += netconn_query_data_available( request->netconn ); + if (!request->read_chunked && request->netconn) count += netconn_query_data_available( request->netconn ); } done: - if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) ); TRACE("%u bytes available\n", count); - if (available) *available = count; - return TRUE; + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_QUERY_DATA_AVAILABLE; + result.dwError = GetLastError(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + + if (ret && available) *available = count; + return ret; } -static void task_query_data_available( task_header_t *task ) +static void task_query_data_available( struct task_header *task ) { - query_data_t *q = (query_data_t *)task; + struct query_data *q = (struct query_data *)task; query_data_available( q->hdr.request, q->available, TRUE ); } @@ -2763,45 +3005,45 @@ static void task_query_data_available( task_header_t *task ) BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %p\n", hrequest, available); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) { - query_data_t *q; + struct query_data *q; - if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE; + if (!(q = heap_alloc( sizeof(struct query_data) ))) return FALSE; q->hdr.request = request; q->hdr.proc = task_query_data_available; q->available = available; addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)q ); + ret = queue_task( (struct task_header *)q ); } else ret = query_data_available( request, available, FALSE ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static void task_read_data( task_header_t *task ) +static void task_read_data( struct task_header *task ) { - read_data_t *r = (read_data_t *)task; + struct read_data *r = (struct read_data *)task; read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE ); } @@ -2811,27 +3053,27 @@ static void task_read_data( task_header_t *task ) BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) { - read_data_t *r; + struct read_data *r; - if (!(r = heap_alloc( sizeof(read_data_t) ))) return FALSE; + if (!(r = heap_alloc( sizeof(struct read_data) ))) return FALSE; r->hdr.request = request; r->hdr.proc = task_read_data; r->buffer = buffer; @@ -2839,17 +3081,17 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, L r->read = read; addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)r ); + ret = queue_task( (struct task_header *)r ); } else ret = read_data( request, buffer, to_read, read, FALSE ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDWORD written, BOOL async ) +static BOOL write_data( struct request *request, const void *buffer, DWORD to_write, DWORD *written, BOOL async ) { BOOL ret; int num_bytes; @@ -2863,7 +3105,7 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDW { WINHTTP_ASYNC_RESULT result; result.dwResult = API_WRITE_DATA; - result.dwError = get_last_error(); + result.dwError = GetLastError(); send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); } } @@ -2871,9 +3113,9 @@ static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDW return ret; } -static void task_write_data( task_header_t *task ) +static void task_write_data( struct task_header *task ) { - write_data_t *w = (write_data_t *)task; + struct write_data *w = (struct write_data *)task; write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE ); } @@ -2883,27 +3125,27 @@ static void task_write_data( task_header_t *task ) BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write, LPDWORD written ) { BOOL ret; - request_t *request; + struct request *request; TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_write, written); - if (!(request = (request_t *)grab_object( hrequest ))) + if (!(request = (struct request *)grab_object( hrequest ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) { release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) { - write_data_t *w; + struct write_data *w; - if (!(w = heap_alloc( sizeof(write_data_t) ))) return FALSE; + if (!(w = heap_alloc( sizeof(struct write_data) ))) return FALSE; w->hdr.request = request; w->hdr.proc = task_write_data; w->buffer = buffer; @@ -2911,19 +3153,18 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write w->written = written; addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)w ); + ret = queue_task( (struct task_header *)w ); } else ret = write_data( request, buffer, to_write, written, FALSE ); release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } enum request_state { - REQUEST_STATE_UNINITIALIZED, REQUEST_STATE_INITIALIZED, REQUEST_STATE_CANCELLED, REQUEST_STATE_OPEN, @@ -2942,9 +3183,16 @@ struct winhttp_request HINTERNET hrequest; VARIANT data; WCHAR *verb; +#ifdef __REACTOS__ HANDLE thread; +#else + HANDLE done; +#endif HANDLE wait; HANDLE cancel; +#ifndef __REACTOS__ + BOOL proc_running; +#endif char *buffer; DWORD offset; DWORD bytes_available; @@ -2978,6 +3226,7 @@ static void cancel_request( struct winhttp_request *request ) { if (request->state <= REQUEST_STATE_CANCELLED) return; +#ifdef __REACTOS__ SetEvent( request->cancel ); LeaveCriticalSection( &request->cs ); WaitForSingleObject( request->thread, INFINITE ); @@ -2987,10 +3236,18 @@ static void cancel_request( struct winhttp_request *request ) CloseHandle( request->thread ); request->thread = NULL; - CloseHandle( request->wait ); - request->wait = NULL; - CloseHandle( request->cancel ); - request->cancel = NULL; +#else + if (request->proc_running) + { + SetEvent( request->cancel ); + LeaveCriticalSection( &request->cs ); + + WaitForSingleObject( request->done, INFINITE ); + + EnterCriticalSection( &request->cs ); + } + request->state = REQUEST_STATE_CANCELLED; +#endif } /* critical section must be held */ @@ -3000,7 +3257,11 @@ static void free_request( struct winhttp_request *request ) WinHttpCloseHandle( request->hrequest ); WinHttpCloseHandle( request->hconnect ); WinHttpCloseHandle( request->hsession ); +#ifdef __REACTOS__ CloseHandle( request->thread ); +#else + CloseHandle( request->done ); +#endif CloseHandle( request->wait ); CloseHandle( request->cancel ); heap_free( (WCHAR *)request->proxy.lpszProxy ); @@ -3118,7 +3379,7 @@ void release_typelib(void) { unsigned i; - for (i = 0; i < sizeof(winhttp_typeinfo)/sizeof(*winhttp_typeinfo); i++) + for (i = 0; i < ARRAY_SIZE(winhttp_typeinfo); i++) if (winhttp_typeinfo[i]) ITypeInfo_Release(winhttp_typeinfo[i]); @@ -3318,7 +3579,7 @@ static HRESULT WINAPI winhttp_request_SetCredentials( } if (!WinHttpSetCredentials( request->hrequest, target, scheme, username, password, NULL )) { - err = get_last_error(); + err = GetLastError(); } done: LeaveCriticalSection( &request->cs ); @@ -3327,25 +3588,11 @@ done: static void initialize_request( struct winhttp_request *request ) { - request->hrequest = NULL; - request->hconnect = NULL; - request->hsession = NULL; - request->thread = NULL; - request->wait = NULL; - request->cancel = NULL; - request->buffer = NULL; - request->verb = NULL; - request->offset = 0; - request->bytes_available = 0; - request->bytes_read = 0; - request->error = ERROR_SUCCESS; - request->async = FALSE; - request->logon_policy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM; - request->disable_feature = 0; - request->proxy.dwAccessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; - request->proxy.lpszProxy = NULL; - request->proxy.lpszProxyBypass = NULL; - request->resolve_timeout = 0; + request->wait = CreateEventW( NULL, FALSE, FALSE, NULL ); + request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL ); +#ifndef __REACTOS__ + request->done = CreateEventW( NULL, FALSE, FALSE, NULL ); +#endif request->connect_timeout = 60000; request->send_timeout = 30000; request->receive_timeout = 30000; @@ -3369,8 +3616,17 @@ static void reset_request( struct winhttp_request *request ) request->bytes_available = 0; request->bytes_read = 0; request->error = ERROR_SUCCESS; + request->logon_policy = 0; + request->disable_feature = 0; request->async = FALSE; + request->connect_timeout = 60000; + request->send_timeout = 30000; + request->receive_timeout = 30000; request->url_codepage = CP_UTF8; + heap_free( request->proxy.lpszProxy ); + request->proxy.lpszProxy = NULL; + heap_free( request->proxy.lpszProxyBypass ); + request->proxy.lpszProxyBypass = NULL; VariantClear( &request->data ); request->state = REQUEST_STATE_INITIALIZED; } @@ -3404,11 +3660,10 @@ static HRESULT WINAPI winhttp_request_Open( uc.dwHostNameLength = ~0u; uc.dwUrlPathLength = ~0u; uc.dwExtraInfoLength = ~0u; - if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( get_last_error() ); + if (!WinHttpCrackUrl( url, 0, 0, &uc )) return HRESULT_FROM_WIN32( GetLastError() ); EnterCriticalSection( &request->cs ); - if (request->state < REQUEST_STATE_INITIALIZED) initialize_request( request ); - else reset_request( request ); + reset_request( request ); if (!(hostname = heap_alloc( (uc.dwHostNameLength + 1) * sizeof(WCHAR) ))) goto error; memcpy( hostname, uc.lpszHostName, uc.dwHostNameLength * sizeof(WCHAR) ); @@ -3427,31 +3682,31 @@ static HRESULT WINAPI winhttp_request_Open( if (!(request->hsession = WinHttpOpen( user_agentW, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, WINHTTP_FLAG_ASYNC ))) { - err = get_last_error(); + err = GetLastError(); goto error; } if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 ))) { WinHttpCloseHandle( request->hsession ); request->hsession = NULL; - err = get_last_error(); + err = GetLastError(); goto error; } } else if (!(request->hconnect = WinHttpConnect( request->hsession, hostname, uc.nPort, 0 ))) { - err = get_last_error(); + err = GetLastError(); goto error; } - len = sizeof(httpsW) / sizeof(WCHAR); + len = ARRAY_SIZE( httpsW ); if (uc.dwSchemeLength == len && !memcmp( uc.lpszScheme, httpsW, len * sizeof(WCHAR) )) { flags |= WINHTTP_FLAG_SECURE; } if (!(request->hrequest = WinHttpOpenRequest( request->hconnect, method, path, NULL, NULL, acceptW, flags ))) { - err = get_last_error(); + err = GetLastError(); goto error; } WinHttpSetOption( request->hrequest, WINHTTP_OPTION_CONTEXT_VALUE, &request, sizeof(request) ); @@ -3510,7 +3765,7 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader( if (!WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE )) { - err = get_last_error(); + err = GetLastError(); } heap_free( str ); @@ -3543,7 +3798,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader( size = 0; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, NULL, &size, NULL )) { - err = get_last_error(); + err = GetLastError(); if (err != ERROR_INSUFFICIENT_BUFFER) goto done; } if (!(*value = SysAllocStringLen( NULL, size / sizeof(WCHAR) ))) @@ -3554,7 +3809,7 @@ static HRESULT WINAPI winhttp_request_GetResponseHeader( err = ERROR_SUCCESS; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CUSTOM, header, *value, &size, NULL )) { - err = get_last_error(); + err = GetLastError(); SysFreeString( *value ); } done: @@ -3582,7 +3837,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders( size = 0; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL )) { - err = get_last_error(); + err = GetLastError(); if (err != ERROR_INSUFFICIENT_BUFFER) goto done; } if (!(*headers = SysAllocStringLen( NULL, size / sizeof(WCHAR) ))) @@ -3593,7 +3848,7 @@ static HRESULT WINAPI winhttp_request_GetAllResponseHeaders( err = ERROR_SUCCESS; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, *headers, &size, NULL )) { - err = get_last_error(); + err = GetLastError(); SysFreeString( *headers ); } done: @@ -3621,7 +3876,9 @@ static void CALLBACK wait_status_callback( HINTERNET handle, DWORD_PTR context, request->error = result->dwError; break; } - default: break; + default: + request->error = ERROR_SUCCESS; + break; } SetEvent( request->wait ); } @@ -3635,19 +3892,38 @@ static void wait_set_status_callback( struct winhttp_request *request, DWORD sta static DWORD wait_for_completion( struct winhttp_request *request ) { HANDLE handles[2] = { request->wait, request->cancel }; +#ifndef __REACTOS__ + DWORD ret; +#endif switch (WaitForMultipleObjects( 2, handles, FALSE, INFINITE )) { case WAIT_OBJECT_0: +#ifndef __REACTOS__ + ret = request->error; +#endif break; case WAIT_OBJECT_0 + 1: +#ifdef __REACTOS__ request->error = ERROR_CANCELLED; +#else + ret = request->error = ERROR_CANCELLED; + SetEvent( request->done ); +#endif break; default: - request->error = get_last_error(); +#ifdef __REACTOS__ + request->error = GetLastError(); +#else + ret = request->error = GetLastError(); +#endif break; } +#ifdef __REACTOS__ return request->error; +#else + return ret; +#endif } static HRESULT request_receive( struct winhttp_request *request ) @@ -3657,7 +3933,7 @@ static HRESULT request_receive( struct winhttp_request *request ) wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE ); if (!WinHttpReceiveResponse( request->hrequest, NULL )) { - return HRESULT_FROM_WIN32( get_last_error() ); + return HRESULT_FROM_WIN32( GetLastError() ); } if ((err = wait_for_completion( request ))) return HRESULT_FROM_WIN32( err ); if (!strcmpW( request->verb, headW )) @@ -3673,7 +3949,7 @@ static HRESULT request_receive( struct winhttp_request *request ) wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE ); if (!WinHttpQueryDataAvailable( request->hrequest, &request->bytes_available )) { - err = get_last_error(); + err = GetLastError(); goto error; } if ((err = wait_for_completion( request ))) goto error; @@ -3694,7 +3970,7 @@ static HRESULT request_receive( struct winhttp_request *request ) if (!WinHttpReadData( request->hrequest, request->buffer + request->offset, request->bytes_available, &request->bytes_read )) { - err = get_last_error(); + err = GetLastError(); goto error; } if ((err = wait_for_completion( request ))) goto error; @@ -3713,19 +3989,19 @@ error: static DWORD request_set_parameters( struct winhttp_request *request ) { if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_PROXY, &request->proxy, - sizeof(request->proxy) )) return get_last_error(); + sizeof(request->proxy) )) return GetLastError(); if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_AUTOLOGON_POLICY, &request->logon_policy, - sizeof(request->logon_policy) )) return get_last_error(); + sizeof(request->logon_policy) )) return GetLastError(); if (!WinHttpSetOption( request->hrequest, WINHTTP_OPTION_DISABLE_FEATURE, &request->disable_feature, - sizeof(request->disable_feature) )) return get_last_error(); + sizeof(request->disable_feature) )) return GetLastError(); if (!WinHttpSetTimeouts( request->hrequest, request->resolve_timeout, request->connect_timeout, request->send_timeout, - request->receive_timeout )) return get_last_error(); + request->receive_timeout )) return GetLastError(); return ERROR_SUCCESS; } @@ -3790,7 +4066,7 @@ static HRESULT request_send( struct winhttp_request *request ) wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT ); if (!WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 )) { - err = get_last_error(); + err = GetLastError(); goto error; } if ((err = wait_for_completion( request ))) goto error; @@ -3805,6 +4081,7 @@ error: return HRESULT_FROM_WIN32( err ); } +#ifdef __REACTOS__ static HRESULT request_send_and_receive( struct winhttp_request *request ) { HRESULT hr = request_send( request ); @@ -3817,15 +4094,31 @@ static DWORD CALLBACK send_and_receive_proc( void *arg ) struct winhttp_request *request = (struct winhttp_request *)arg; return request_send_and_receive( request ); } +#else +static void CALLBACK send_and_receive_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) +{ + struct winhttp_request *request = (struct winhttp_request *)ctx; + if (request_send( request ) == S_OK) request_receive( request ); + SetEvent( request->done ); +} +#endif /* critical section must be held */ static DWORD request_wait( struct winhttp_request *request, DWORD timeout ) { +#ifdef __REACTOS__ HANDLE thread = request->thread; +#else + HANDLE done = request->done; +#endif DWORD err, ret; LeaveCriticalSection( &request->cs ); +#ifdef __REACTOS__ while ((err = MsgWaitForMultipleObjects( 1, &thread, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1) +#else + while ((err = MsgWaitForMultipleObjects( 1, &done, FALSE, timeout, QS_ALLINPUT )) == WAIT_OBJECT_0 + 1) +#endif { MSG msg; while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE )) @@ -3837,17 +4130,19 @@ static DWORD request_wait( struct winhttp_request *request, DWORD timeout ) switch (err) { case WAIT_OBJECT_0: - ret = ERROR_SUCCESS; + ret = request->error; break; case WAIT_TIMEOUT: ret = ERROR_TIMEOUT; break; - case WAIT_FAILED: default: - ret = get_last_error(); + ret = GetLastError(); break; } EnterCriticalSection( &request->cs ); +#ifndef __REACTOS__ + if (err == WAIT_OBJECT_0) request->proc_running = FALSE; +#endif return ret; } @@ -3877,13 +4172,18 @@ static HRESULT WINAPI winhttp_request_Send( LeaveCriticalSection( &request->cs ); return hr; } +#ifdef __REACTOS__ if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0, NULL ))) +#else + if (!TrySubmitThreadpoolCallback( send_and_receive_proc, request, NULL )) +#endif { LeaveCriticalSection( &request->cs ); - return HRESULT_FROM_WIN32( get_last_error() ); + return HRESULT_FROM_WIN32( GetLastError() ); } - request->wait = CreateEventW( NULL, FALSE, FALSE, NULL ); - request->cancel = CreateEventW( NULL, FALSE, FALSE, NULL ); +#ifndef __REACTOS__ + request->proc_running = TRUE; +#endif if (!request->async) { hr = HRESULT_FROM_WIN32( request_wait( request, INFINITE ) ); @@ -3912,7 +4212,7 @@ static HRESULT WINAPI winhttp_request_get_Status( flags = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; if (!WinHttpQueryHeaders( request->hrequest, flags, NULL, &status_code, &len, &index )) { - err = get_last_error(); + err = GetLastError(); goto done; } *status = status_code; @@ -3941,7 +4241,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText( } if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, NULL, &len, &index )) { - err = get_last_error(); + err = GetLastError(); if (err != ERROR_INSUFFICIENT_BUFFER) goto done; } if (!(*status = SysAllocStringLen( NULL, len / sizeof(WCHAR) ))) @@ -3953,7 +4253,7 @@ static HRESULT WINAPI winhttp_request_get_StatusText( err = ERROR_SUCCESS; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_STATUS_TEXT, NULL, *status, &len, &index )) { - err = get_last_error(); + err = GetLastError(); SysFreeString( *status ); } done: @@ -3970,12 +4270,12 @@ static DWORD request_get_codepage( struct winhttp_request *request, UINT *codepa *codepage = CP_ACP; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL, NULL, &size, NULL ) && - get_last_error() == ERROR_INSUFFICIENT_BUFFER) + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { if (!(buffer = heap_alloc( size ))) return ERROR_OUTOFMEMORY; if (!WinHttpQueryHeaders( request->hrequest, WINHTTP_QUERY_CONTENT_TYPE, NULL, buffer, &size, NULL )) { - return get_last_error(); + return GetLastError(); } if ((p = strstrW( buffer, charsetW ))) { @@ -4372,11 +4672,9 @@ static HRESULT WINAPI winhttp_request_WaitForResponse( err = ERROR_SUCCESS; break; - case ERROR_SUCCESS: + default: if (succeeded) *succeeded = VARIANT_TRUE; break; - - default: break; } LeaveCriticalSection( &request->cs ); return HRESULT_FROM_WIN32( err ); @@ -4487,15 +4785,12 @@ HRESULT WinHttpRequest_create( void **obj ) TRACE("%p\n", obj); - if (!(request = heap_alloc( sizeof(*request) ))) return E_OUTOFMEMORY; + if (!(request = heap_alloc_zero( sizeof(*request) ))) return E_OUTOFMEMORY; request->IWinHttpRequest_iface.lpVtbl = &winhttp_request_vtbl; request->refs = 1; - request->state = REQUEST_STATE_UNINITIALIZED; - request->proxy.lpszProxy = NULL; - request->proxy.lpszProxyBypass = NULL; - request->url_codepage = CP_UTF8; InitializeCriticalSection( &request->cs ); request->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": winhttp_request.cs"); + initialize_request( request ); *obj = &request->IWinHttpRequest_iface; TRACE("returning iface %p\n", *obj); diff --git a/dll/win32/winhttp/session.c b/dll/win32/winhttp/session.c index 7cfc2407585..8e24de736dd 100644 --- a/dll/win32/winhttp/session.c +++ b/dll/win32/winhttp/session.c @@ -17,9 +17,6 @@ */ #include "config.h" -#include "wine/port.h" -#include "wine/debug.h" - #include <stdarg.h> #include <stdlib.h> @@ -29,46 +26,33 @@ #include <CoreServices/CoreServices.h> #undef GetCurrentThread #undef LoadResource -#undef DPRINTF #endif #include "windef.h" #include "winbase.h" -#ifndef __MINGW32__ -#define USE_WS_PREFIX -#endif #include "winsock2.h" #include "ws2ipdef.h" +#include "ws2tcpip.h" #include "winhttp.h" -#include "wincrypt.h" #include "winreg.h" +#include "wine/winternl.h" #define COBJMACROS #include "ole2.h" #include "dispex.h" #include "activscp.h" +#include "wine/debug.h" #include "winhttp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(winhttp); -#define DEFAULT_RESOLVE_TIMEOUT 0 -#define DEFAULT_CONNECT_TIMEOUT 20000 -#define DEFAULT_SEND_TIMEOUT 30000 -#define DEFAULT_RECEIVE_TIMEOUT 30000 - -void set_last_error( DWORD error ) -{ - /* FIXME */ - SetLastError( error ); -} - -DWORD get_last_error( void ) -{ - /* FIXME */ - return GetLastError(); -} +#define DEFAULT_RESOLVE_TIMEOUT 0 +#define DEFAULT_CONNECT_TIMEOUT 20000 +#define DEFAULT_SEND_TIMEOUT 30000 +#define DEFAULT_RECEIVE_TIMEOUT 30000 +#define DEFAULT_RECEIVE_RESPONSE_TIMEOUT ~0u -void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen ) +void send_callback( struct object_header *hdr, DWORD status, void *info, DWORD buflen ) { if (hdr->callback && (hdr->notify_mask & status)) { @@ -90,22 +74,17 @@ BOOL WINAPI WinHttpCheckPlatform( void ) /*********************************************************************** * session_destroy (internal) */ -static void session_destroy( object_header_t *hdr ) +static void session_destroy( struct object_header *hdr ) { - session_t *session = (session_t *)hdr; - struct list *item, *next; - domain_t *domain; + struct session *session = (struct session *)hdr; TRACE("%p\n", session); if (session->unload_event) SetEvent( session->unload_event ); - if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle ); + destroy_cookies( session ); - LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) - { - domain = LIST_ENTRY( item, domain_t, entry ); - delete_domain( domain ); - } + session->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &session->cs ); heap_free( session->agent ); heap_free( session->proxy_server ); heap_free( session->proxy_bypass ); @@ -114,9 +93,9 @@ static void session_destroy( object_header_t *hdr ) heap_free( session ); } -static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) +static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { - session_t *session = (session_t *)hdr; + struct session *session = (struct session *)hdr; switch (option) { @@ -125,7 +104,7 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(DWORD)) { *buflen = sizeof(DWORD); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -137,28 +116,37 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf *(DWORD *)buffer = session->resolve_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_CONNECT_TIMEOUT: *(DWORD *)buffer = session->connect_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_SEND_TIMEOUT: *(DWORD *)buffer = session->send_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_RECEIVE_TIMEOUT: - *(DWORD *)buffer = session->recv_timeout; + *(DWORD *)buffer = session->receive_timeout; + *buflen = sizeof(DWORD); + return TRUE; + + case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT: + *(DWORD *)buffer = session->receive_response_timeout; *buflen = sizeof(DWORD); return TRUE; + default: FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } } -static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) +static BOOL session_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen ) { - session_t *session = (session_t *)hdr; + struct session *session = (struct session *)hdr; switch (option) { @@ -175,7 +163,7 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe if (buflen != sizeof(policy)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -188,72 +176,81 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe { if (buflen != sizeof(session->secure_protocols)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } + EnterCriticalSection( &session->cs ); session->secure_protocols = *(DWORD *)buffer; + LeaveCriticalSection( &session->cs ); TRACE("0x%x\n", session->secure_protocols); return TRUE; } case WINHTTP_OPTION_DISABLE_FEATURE: - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; + case WINHTTP_OPTION_RESOLVE_TIMEOUT: session->resolve_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_CONNECT_TIMEOUT: session->connect_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_SEND_TIMEOUT: session->send_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_RECEIVE_TIMEOUT: - session->recv_timeout = *(DWORD *)buffer; + session->receive_timeout = *(DWORD *)buffer; return TRUE; + + case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT: + session->receive_response_timeout = *(DWORD *)buffer; + return TRUE; + case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: - FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer); + session->passport_flags = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer); session->unload_event = *(HANDLE *)buffer; return TRUE; + case WINHTTP_OPTION_MAX_CONNS_PER_SERVER: FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer); return TRUE; + case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer); return TRUE; + default: FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_WINHTTP_INVALID_OPTION ); + SetLastError( ERROR_WINHTTP_INVALID_OPTION ); return FALSE; } } -static const object_vtbl_t session_vtbl = +static const struct object_vtbl session_vtbl = { session_destroy, session_query_option, session_set_option }; -#ifdef __REACTOS__ -BOOL netconn_init_winsock(); -#endif /* __REACTOS__ */ /*********************************************************************** * WinHttpOpen (winhttp.@) */ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags ) { - session_t *session; + struct session *session; HINTERNET handle = NULL; -#ifdef __REACTOS__ - if (!netconn_init_winsock()) return NULL; -#endif TRACE("%s, %u, %s, %s, 0x%08x\n", debugstr_w(agent), access, debugstr_w(proxy), debugstr_w(bypass), flags); - if (!(session = heap_alloc_zero( sizeof(session_t) ))) return NULL; + if (!(session = heap_alloc_zero( sizeof(struct session) ))) return NULL; session->hdr.type = WINHTTP_HANDLE_TYPE_SESSION; session->hdr.vtbl = &session_vtbl; @@ -264,8 +261,11 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT; session->connect_timeout = DEFAULT_CONNECT_TIMEOUT; session->send_timeout = DEFAULT_SEND_TIMEOUT; - session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT; + session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT; + session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT; list_init( &session->cookie_cache ); + InitializeCriticalSection( &session->cs ); + session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs"); if (agent && !(session->agent = strdupW( agent ))) goto end; if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY) @@ -300,16 +300,16 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST end: release_object( &session->hdr ); TRACE("returning %p\n", handle); - if (handle) set_last_error( ERROR_SUCCESS ); + if (handle) SetLastError( ERROR_SUCCESS ); return handle; } /*********************************************************************** * connect_destroy (internal) */ -static void connect_destroy( object_header_t *hdr ) +static void connect_destroy( struct object_header *hdr ) { - connect_t *connect = (connect_t *)hdr; + struct connect *connect = (struct connect *)hdr; TRACE("%p\n", connect); @@ -322,9 +322,9 @@ static void connect_destroy( object_header_t *hdr ) heap_free( connect ); } -static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) +static BOOL connect_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { - connect_t *connect = (connect_t *)hdr; + struct connect *connect = (struct connect *)hdr; switch (option) { @@ -333,11 +333,11 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(HINTERNET)) { *buflen = sizeof(HINTERNET); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - *(HINTERNET *)buffer = ((object_header_t *)connect->session)->handle; + *(HINTERNET *)buffer = ((struct object_header *)connect->session)->handle; *buflen = sizeof(HINTERNET); return TRUE; } @@ -345,26 +345,35 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buf *(DWORD *)buffer = connect->session->resolve_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_CONNECT_TIMEOUT: *(DWORD *)buffer = connect->session->connect_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_SEND_TIMEOUT: *(DWORD *)buffer = connect->session->send_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_RECEIVE_TIMEOUT: - *(DWORD *)buffer = connect->session->recv_timeout; + *(DWORD *)buffer = connect->session->receive_timeout; *buflen = sizeof(DWORD); return TRUE; + + case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT: + *(DWORD *)buffer = connect->session->receive_response_timeout; + *buflen = sizeof(DWORD); + return TRUE; + default: FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } } -static const object_vtbl_t connect_vtbl = +static const struct object_vtbl connect_vtbl = { connect_destroy, connect_query_option, @@ -425,7 +434,7 @@ static BOOL domain_matches(LPCWSTR server, LPCWSTR domain) /* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */ #define MAX_HOST_NAME_LENGTH 256 -static BOOL should_bypass_proxy(session_t *session, LPCWSTR server) +static BOOL should_bypass_proxy(struct session *session, LPCWSTR server) { LPCWSTR ptr; BOOL ret = FALSE; @@ -456,9 +465,9 @@ static BOOL should_bypass_proxy(session_t *session, LPCWSTR server) return ret; } -BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port ) +BOOL set_server_for_hostname( struct connect *connect, const WCHAR *server, INTERNET_PORT port ) { - session_t *session = connect->session; + struct session *session = connect->session; BOOL ret = TRUE; if (session->proxy_server && !should_bypass_proxy(session, server)) @@ -523,29 +532,29 @@ end: */ HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved ) { - connect_t *connect; - session_t *session; + struct connect *connect; + struct session *session; HINTERNET hconnect = NULL; TRACE("%p, %s, %u, %x\n", hsession, debugstr_w(server), port, reserved); if (!server) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return NULL; } - if (!(session = (session_t *)grab_object( hsession ))) + if (!(session = (struct session *)grab_object( hsession ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return NULL; } if (session->hdr.type != WINHTTP_HANDLE_TYPE_SESSION) { release_object( &session->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return NULL; } - if (!(connect = heap_alloc_zero( sizeof(connect_t) ))) + if (!(connect = heap_alloc_zero( sizeof(struct connect) ))) { release_object( &session->hdr ); return NULL; @@ -577,32 +586,44 @@ end: release_object( &connect->hdr ); release_object( &session->hdr ); TRACE("returning %p\n", hconnect); - if (hconnect) set_last_error( ERROR_SUCCESS ); + if (hconnect) SetLastError( ERROR_SUCCESS ); return hconnect; } /*********************************************************************** * request_destroy (internal) */ -static void request_destroy( object_header_t *hdr ) +static void request_destroy( struct object_header *hdr ) { - request_t *request = (request_t *)hdr; + struct request *request = (struct request *)hdr; unsigned int i, j; TRACE("%p\n", request); +#ifdef __REACTOS__ if (request->task_thread) +#else + if (request->task_proc_running) +#endif { - /* Signal to the task proc to quit. It will call - this again when it does. */ + /* Signal to the task proc to quit. It will call this again when it does. */ +#ifdef __REACTOS__ HANDLE thread = request->task_thread; request->task_thread = 0; SetEvent( request->task_cancel ); CloseHandle( thread ); +#else + request->task_proc_running = FALSE; + SetEvent( request->task_cancel ); +#endif return; } release_object( &request->connect->hdr ); + if (request->cred_handle_initialized) FreeCredentialsHandle( &request->cred_handle ); + CertFreeCertificateContext( request->server_cert ); + CertFreeCertificateContext( request->client_cert ); + destroy_authinfo( request->authinfo ); destroy_authinfo( request->proxy_authinfo ); @@ -652,46 +673,8 @@ static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob ) return ret; } -static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage ) +static BOOL copy_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *addr_storage ) { -#if !defined(__MINGW32__) && !defined(_MSC_VER) - switch (addr->sa_family) - { - case AF_INET: - { - const struct sockaddr_in *addr_unix = (const struct sockaddr_in *)addr; - struct WS_sockaddr_in *addr_win = (struct WS_sockaddr_in *)addr_storage; - char *p; - - addr_win->sin_family = WS_AF_INET; - addr_win->sin_port = addr_unix->sin_port; - memcpy( &addr_win->sin_addr, &addr_unix->sin_addr, 4 ); - p = (char *)&addr_win->sin_addr + 4; - memset( p, 0, sizeof(*addr_storage) - (p - (char *)addr_win) ); - return TRUE; - } - case AF_INET6: - { - const struct sockaddr_in6 *addr_unix = (const struct sockaddr_in6 *)addr; - struct WS_sockaddr_in6 *addr_win = (struct WS_sockaddr_in6 *)addr_storage; - - addr_win->sin6_family = WS_AF_INET6; - addr_win->sin6_port = addr_unix->sin6_port; - addr_win->sin6_flowinfo = addr_unix->sin6_flowinfo; - memcpy( &addr_win->sin6_addr, &addr_unix->sin6_addr, 16 ); -#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID - addr_win->sin6_scope_id = addr_unix->sin6_scope_id; -#else - addr_win->sin6_scope_id = 0; -#endif - memset( addr_win + 1, 0, sizeof(*addr_storage) - sizeof(*addr_win) ); - return TRUE; - } - default: - ERR("unhandled family %u\n", addr->sa_family); - return FALSE; - } -#else switch (addr->sa_family) { case AF_INET: @@ -714,30 +697,27 @@ static BOOL convert_sockaddr( const struct sockaddr *addr, SOCKADDR_STORAGE *add ERR("unhandled family %u\n", addr->sa_family); return FALSE; } -#endif } -static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) +static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { - request_t *request = (request_t *)hdr; + struct request *request = (struct request *)hdr; switch (option) { case WINHTTP_OPTION_SECURITY_FLAGS: { - DWORD flags = 0; + DWORD flags; int bits; if (!buffer || *buflen < sizeof(flags)) { *buflen = sizeof(flags); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - flags = 0; - if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE; - flags |= request->security_flags; + flags = request->security_flags; if (request->netconn) { bits = netconn_get_cipher_strength( request->netconn ); @@ -759,18 +739,18 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(cert)) { *buflen = sizeof(cert); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; + if (!(cert = CertDuplicateCertificateContext( request->server_cert ))) return FALSE; *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert; *buflen = sizeof(cert); return TRUE; } case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT: { - const CERT_CONTEXT *cert; + const CERT_CONTEXT *cert = request->server_cert; const CRYPT_OID_INFO *oidInfo; WINHTTP_CERTIFICATE_INFO *ci = buffer; @@ -779,19 +759,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(*ci)) { *buflen = sizeof(*ci); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } - if (!request->netconn || !(cert = netconn_get_certificate( request->netconn ))) return FALSE; + if (!cert) return FALSE; ci->ftExpiry = cert->pCertInfo->NotAfter; ci->ftStart = cert->pCertInfo->NotBefore; ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject ); ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer ); ci->lpszProtocolName = NULL; - oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, - cert->pCertInfo->SignatureAlgorithm.pszObjId, - 0 ); + oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, cert->pCertInfo->SignatureAlgorithm.pszObjId, 0 ); if (oidInfo) ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName; else @@ -799,7 +777,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf ci->lpszEncryptionAlgName = NULL; ci->dwKeySize = request->netconn ? netconn_get_cipher_strength( request->netconn ) : 0; - CertFreeCertificateContext( cert ); *buflen = sizeof(*ci); return TRUE; } @@ -808,7 +785,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(DWORD)) { *buflen = sizeof(DWORD); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -826,17 +803,17 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf if (!buffer || *buflen < sizeof(*info)) { *buflen = sizeof(*info); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } if (!request->netconn) { - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); return FALSE; } if (getsockname( request->netconn->socket, &local, &len )) return FALSE; - if (!convert_sockaddr( &local, &info->LocalAddress )) return FALSE; - if (!convert_sockaddr( remote, &info->RemoteAddress )) return FALSE; + if (!copy_sockaddr( &local, &info->LocalAddress )) return FALSE; + if (!copy_sockaddr( remote, &info->RemoteAddress )) return FALSE; info->cbSize = sizeof(*info); return TRUE; } @@ -844,16 +821,24 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf *(DWORD *)buffer = request->resolve_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_CONNECT_TIMEOUT: *(DWORD *)buffer = request->connect_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_SEND_TIMEOUT: *(DWORD *)buffer = request->send_timeout; *buflen = sizeof(DWORD); return TRUE; + case WINHTTP_OPTION_RECEIVE_TIMEOUT: - *(DWORD *)buffer = request->recv_timeout; + *(DWORD *)buffer = request->receive_timeout; + *buflen = sizeof(DWORD); + return TRUE; + + case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT: + *(DWORD *)buffer = request->receive_response_timeout; *buflen = sizeof(DWORD); return TRUE; @@ -875,7 +860,7 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf default: FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } } @@ -889,13 +874,13 @@ static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen ) ret[buflen] = 0; return ret; } - set_last_error( ERROR_OUTOFMEMORY ); + SetLastError( ERROR_OUTOFMEMORY ); return NULL; } -static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) +static BOOL request_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen ) { - request_t *request = (request_t *)hdr; + struct request *request = (struct request *)hdr; switch (option) { @@ -912,7 +897,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe if (buflen != sizeof(DWORD)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -927,7 +912,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe if (buflen != sizeof(DWORD)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -942,7 +927,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe if (buflen != sizeof(DWORD)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -954,20 +939,21 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe case WINHTTP_OPTION_SECURITY_FLAGS: { DWORD flags; + static const DWORD accepted = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | + SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | + SECURITY_FLAG_IGNORE_UNKNOWN_CA | + SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; if (buflen < sizeof(DWORD)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } flags = *(DWORD *)buffer; TRACE("0x%x\n", flags); - if (!(flags & (SECURITY_FLAG_IGNORE_CERT_CN_INVALID | - SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | - SECURITY_FLAG_IGNORE_UNKNOWN_CA | - SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE))) + if (flags && (flags & ~accepted)) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } request->security_flags = flags; @@ -976,19 +962,26 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe case WINHTTP_OPTION_RESOLVE_TIMEOUT: request->resolve_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_CONNECT_TIMEOUT: request->connect_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_SEND_TIMEOUT: request->send_timeout = *(DWORD *)buffer; return TRUE; + case WINHTTP_OPTION_RECEIVE_TIMEOUT: - request->recv_timeout = *(DWORD *)buffer; + request->receive_timeout = *(DWORD *)buffer; + return TRUE; + + case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT: + request->receive_response_timeout = *(DWORD *)buffer; return TRUE; case WINHTTP_OPTION_USERNAME: { - connect_t *connect = request->connect; + struct connect *connect = request->connect; heap_free( connect->username ); if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE; @@ -996,7 +989,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe } case WINHTTP_OPTION_PASSWORD: { - connect_t *connect = request->connect; + struct connect *connect = request->connect; heap_free( connect->password ); if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE; @@ -1004,7 +997,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe } case WINHTTP_OPTION_PROXY_USERNAME: { - session_t *session = request->connect->session; + struct session *session = request->connect->session; heap_free( session->proxy_username ); if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE; @@ -1012,82 +1005,136 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe } case WINHTTP_OPTION_PROXY_PASSWORD: { - session_t *session = request->connect->session; + struct session *session = request->connect->session; heap_free( session->proxy_password ); if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE; return TRUE; } case WINHTTP_OPTION_CLIENT_CERT_CONTEXT: + { + const CERT_CONTEXT *cert; + if (!(hdr->flags & WINHTTP_FLAG_SECURE)) { SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_STATE ); return FALSE; } - FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n"); + if (!buffer) + { + CertFreeCertificateContext( request->client_cert ); + request->client_cert = NULL; + } + else if (buflen >= sizeof(cert)) + { + if (!(cert = CertDuplicateCertificateContext( buffer ))) return FALSE; + CertFreeCertificateContext( request->client_cert ); + request->client_cert = cert; + } + else + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (request->cred_handle_initialized) + { + FreeCredentialsHandle( &request->cred_handle ); + request->cred_handle_initialized = FALSE; + } + return TRUE; + } + case WINHTTP_OPTION_ENABLE_FEATURE: + if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION) + { + request->check_revocation = TRUE; + SetLastError( NO_ERROR ); + return TRUE; + } + else + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + case WINHTTP_OPTION_CONNECT_RETRIES: + FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n"); + return TRUE; + default: FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_WINHTTP_INVALID_OPTION ); + SetLastError( ERROR_WINHTTP_INVALID_OPTION ); return FALSE; } } -static const object_vtbl_t request_vtbl = +static const struct object_vtbl request_vtbl = { request_destroy, request_query_option, request_set_option }; -static BOOL store_accept_types( request_t *request, const WCHAR **accept_types ) +static BOOL add_accept_types_header( struct request *request, const WCHAR **types ) { - static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0}; + static const WCHAR acceptW[] = {'A','c','c','e','p','t',0}; static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA; - const WCHAR **types = accept_types; if (!types) return TRUE; while (*types) { - process_header( request, attr_accept, *types, flags, TRUE ); + if (!process_header( request, acceptW, *types, flags, TRUE )) return FALSE; types++; } return TRUE; } +static WCHAR *get_request_path( const WCHAR *object ) +{ + int len = object ? strlenW(object) : 0; + WCHAR *p, *ret; + + if (!object || object[0] != '/') len++; + if (!(p = ret = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return NULL; + if (!object || object[0] != '/') *p++ = '/'; + if (object) strcpyW( p, object ); + ret[len] = 0; + return ret; +} + /*********************************************************************** * WinHttpOpenRequest (winhttp.@) */ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version, LPCWSTR referrer, LPCWSTR *types, DWORD flags ) { - request_t *request; - connect_t *connect; + struct request *request; + struct connect *connect; HINTERNET hrequest = NULL; TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object), debugstr_w(version), debugstr_w(referrer), types, flags); - if(types && TRACE_ON(winhttp)) { + if (types && TRACE_ON(winhttp)) + { const WCHAR **iter; - TRACE("accept types:\n"); - for(iter = types; *iter; iter++) - TRACE(" %s\n", debugstr_w(*iter)); + for (iter = types; *iter; iter++) TRACE(" %s\n", debugstr_w(*iter)); } - if (!(connect = (connect_t *)grab_object( hconnect ))) + if (!(connect = (struct connect *)grab_object( hconnect ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return NULL; } if (connect->hdr.type != WINHTTP_HANDLE_TYPE_CONNECT) { release_object( &connect->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return NULL; } - if (!(request = heap_alloc_zero( sizeof(request_t) ))) + if (!(request = heap_alloc_zero( sizeof(struct request) ))) { release_object( &connect->hdr ); return NULL; @@ -1110,29 +1157,16 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o request->resolve_timeout = connect->session->resolve_timeout; request->connect_timeout = connect->session->connect_timeout; request->send_timeout = connect->session->send_timeout; - request->recv_timeout = connect->session->recv_timeout; + request->receive_timeout = connect->session->receive_timeout; + request->receive_response_timeout = connect->session->receive_response_timeout; if (!verb || !verb[0]) verb = getW; if (!(request->verb = strdupW( verb ))) goto end; - - if (object) - { - WCHAR *path, *p; - unsigned int len; - - len = strlenW( object ) + 1; - if (object[0] != '/') len++; - if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end; - - if (object[0] != '/') *p++ = '/'; - strcpyW( p, object ); - request->path = path; - } - else if (!(request->path = strdupW( slashW ))) goto end; + if (!(request->path = get_request_path( object ))) goto end; if (!version || !version[0]) version = http1_1; if (!(request->version = strdupW( version ))) goto end; - if (!(store_accept_types( request, types ))) goto end; + if (!(add_accept_types_header( request, types ))) goto end; if (!(hrequest = alloc_handle( &request->hdr ))) goto end; request->hdr.handle = hrequest; @@ -1143,7 +1177,7 @@ end: release_object( &request->hdr ); release_object( &connect->hdr ); TRACE("returning %p\n", hrequest); - if (hrequest) set_last_error( ERROR_SUCCESS ); + if (hrequest) SetLastError( ERROR_SUCCESS ); return hrequest; } @@ -1152,28 +1186,28 @@ end: */ BOOL WINAPI WinHttpCloseHandle( HINTERNET handle ) { - object_header_t *hdr; + struct object_header *hdr; TRACE("%p\n", handle); if (!(hdr = grab_object( handle ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } release_object( hdr ); free_handle( handle ); - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return TRUE; } -static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) +static BOOL query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { BOOL ret = FALSE; if (!buflen) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -1184,7 +1218,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD if (!buffer || *buflen < sizeof(DWORD_PTR)) { *buflen = sizeof(DWORD_PTR); - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -1197,7 +1231,7 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD else { FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } break; @@ -1211,30 +1245,30 @@ static BOOL query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPD BOOL WINAPI WinHttpQueryOption( HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen ) { BOOL ret = FALSE; - object_header_t *hdr; + struct object_header *hdr; TRACE("%p, %u, %p, %p\n", handle, option, buffer, buflen); if (!(hdr = grab_object( handle ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } ret = query_option( hdr, option, buffer, buflen ); release_object( hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } -static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) +static BOOL set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen ) { BOOL ret = TRUE; if (!buffer && buflen) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -1244,7 +1278,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD { if (buflen != sizeof(DWORD_PTR)) { - set_last_error( ERROR_INSUFFICIENT_BUFFER ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; } @@ -1256,7 +1290,7 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD else { FIXME("unimplemented option %u\n", option); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + SetLastError( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } break; @@ -1270,20 +1304,20 @@ static BOOL set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen ) { BOOL ret = FALSE; - object_header_t *hdr; + struct object_header *hdr; TRACE("%p, %u, %p, %u\n", handle, option, buffer, buflen); if (!(hdr = grab_object( handle ))) { - set_last_error( ERROR_INVALID_HANDLE ); + SetLastError( ERROR_INVALID_HANDLE ); return FALSE; } ret = set_option( hdr, option, buffer, buflen ); release_object( hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (ret) SetLastError( ERROR_SUCCESS ); return ret; } @@ -1308,17 +1342,13 @@ static BOOL is_domain_suffix( const char *domain, const char *suffix ) int len_domain = strlen( domain ), len_suffix = strlen( suffix ); if (len_suffix > len_domain) return FALSE; - if (!strcasecmp( domain + len_domain - len_suffix, suffix )) return TRUE; + if (!_strnicmp( domain + len_domain - len_suffix, suffix, -1 )) return TRUE; return FALSE; } static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len ) { - int ret = -1; -#ifdef HAVE_GETNAMEINFO - ret = getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); -#endif - return ret; + return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 ); } static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai ) @@ -1391,7 +1421,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url ) if (!flags || !url) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) )) @@ -1400,7 +1430,7 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url ) if (!(urlW = strdupAW( system_url ))) return FALSE; *url = urlW; - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return TRUE; } if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP) @@ -1410,7 +1440,6 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url ) } if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A) { -#ifdef HAVE_GETADDRINFO char *fqdn, *domain, *p; if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return FALSE; @@ -1452,16 +1481,13 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url ) } heap_free( domain ); heap_free( fqdn ); -#else - FIXME("getaddrinfo not found at build time\n"); -#endif } if (!ret) { - set_last_error( ERROR_WINHTTP_AUTODETECTION_FAILED ); + SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED ); *url = NULL; } - else set_last_error( ERROR_SUCCESS ); + else SetLastError( ERROR_SUCCESS ); return ret; } @@ -1620,7 +1646,7 @@ BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info ) info->lpszProxy = NULL; info->lpszProxyBypass = NULL; } - set_last_error( ERROR_SUCCESS ); + SetLastError( ERROR_SUCCESS ); return TRUE; } @@ -1640,7 +1666,7 @@ BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser( WINHTTP_CURRENT_USER_IE_PROXY if (!config) { - set_last_error( ERROR_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } memset( config, 0, sizeof(*config) ); @@ -1703,7 +1729,7 @@ done: GlobalFree( config->lpszProxyBypass ); config->lpszProxyBypass = NULL; } - else set_last_error( ERROR_SUCCESS ); + else SetLastError( ERROR_SUCCESS ); return ret; } @@ -1722,7 +1748,7 @@ static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info ) p = result; while (*p == ' ') p++; len = strlen( p ); - if (len >= 5 && !strncasecmp( p, "PROXY", sizeof("PROXY") - 1 )) + if (len >= 5 && !_strnicmp( p, "PROXY", sizeof("PROXY") - 1 )) { p += 5; while (*p == ' ') p++; @@ -1797,7 +1823,7 @@ done: ... 1269 lines suppressed ...
5 years
1
0
0
0
[reactos] 01/01: [WINEMP3.ACM] Sync with Wine Staging 4.18. CORE-16441
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=611eb5508c9e0d1f5f5c8…
commit 611eb5508c9e0d1f5f5c819208d8cba0532139a2 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Dec 7 13:05:25 2019 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Dec 7 13:05:25 2019 +0100 [WINEMP3.ACM] Sync with Wine Staging 4.18. CORE-16441 --- dll/win32/winemp3.acm/mpegl3.c | 19 ++++++++----------- media/doc/README.WINE | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/dll/win32/winemp3.acm/mpegl3.c b/dll/win32/winemp3.acm/mpegl3.c index b28519f835a..2e929371ae8 100644 --- a/dll/win32/winemp3.acm/mpegl3.c +++ b/dll/win32/winemp3.acm/mpegl3.c @@ -89,9 +89,6 @@ static const Format MPEG3_Formats[] = {1, 0, 48000}, {2, 0, 48000} }; -#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) -#define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0])) - /*********************************************************************** * MPEG3_GetFormatIndex */ @@ -103,12 +100,12 @@ static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx) switch (wfx->wFormatTag) { case WAVE_FORMAT_PCM: - hi = NUM_PCM_FORMATS; + hi = ARRAY_SIZE(PCM_Formats); fmts = PCM_Formats; break; case WAVE_FORMAT_MPEG: case WAVE_FORMAT_MPEGLAYER3: - hi = NUM_MPEG3_FORMATS; + hi = ARRAY_SIZE(MPEG3_Formats); fmts = MPEG3_Formats; break; default: @@ -692,13 +689,13 @@ static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add) add->cFilterTags = 0; add->hicon = NULL; MultiByteToWideChar( CP_ACP, 0, "MPEG Layer-3 Codec", -1, - add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); + add->szShortName, ARRAY_SIZE( add->szShortName )); MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1, - add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); + add->szLongName, ARRAY_SIZE( add->szLongName )); MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1, - add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); + add->szCopyright, ARRAY_SIZE( add->szCopyright )); MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, - add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); + add->szLicensing, ARRAY_SIZE( add->szLicensing )); add->szFeatures[0] = 0; return MMSYSERR_NOERROR; @@ -746,7 +743,7 @@ static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) case 0: aftd->dwFormatTag = WAVE_FORMAT_PCM; aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); - aftd->cStandardFormats = NUM_PCM_FORMATS; + aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats); lstrcpyW(aftd->szFormatTag, szPcm); break; case 1: @@ -781,7 +778,7 @@ static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) switch (afd->dwFormatTag) { case WAVE_FORMAT_PCM: - if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; + if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 876663af0de..7d41d927c6c 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -199,7 +199,7 @@ dll/win32/wbemdisp # Synced to WineStaging-4.18 dll/win32/wbemprox # Synced to WineStaging-4.18 dll/win32/windowscodecs # Synced to WineStaging-4.18 dll/win32/windowscodecsext # Synced to WineStaging-2.9 -dll/win32/winemp3.acm # Synced to WineStaging-3.3 +dll/win32/winemp3.acm # Synced to WineStaging-4.18 dll/win32/wing32 # Synced to WineStaging-3.3 dll/win32/winhttp # Synced to WineStaging-3.9 dll/win32/wininet # Synced to WineStaging-3.9
5 years
1
0
0
0
[reactos] 01/01: [WINDOWSCODECS_WINETEST] Sync with Wine Staging 4.18. CORE-16441
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cc48f9d4d6539e628a257…
commit cc48f9d4d6539e628a257d01329f2e80808718db Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Dec 7 13:05:00 2019 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Dec 7 13:05:00 2019 +0100 [WINDOWSCODECS_WINETEST] Sync with Wine Staging 4.18. CORE-16441 --- .../winetests/windowscodecs/CMakeLists.txt | 5 - modules/rostests/winetests/windowscodecs/bitmap.c | 222 +++++++++++++++++++++ .../rostests/winetests/windowscodecs/converter.c | 47 +++-- .../rostests/winetests/windowscodecs/metadata.c | 1 + modules/rostests/winetests/windowscodecs/palette.c | 4 +- modules/rostests/winetests/windowscodecs/stream.c | 2 +- .../rostests/winetests/windowscodecs/tiffformat.c | 3 +- 7 files changed, 260 insertions(+), 24 deletions(-) diff --git a/modules/rostests/winetests/windowscodecs/CMakeLists.txt b/modules/rostests/winetests/windowscodecs/CMakeLists.txt index 09cca9909aa..6bae33b8912 100644 --- a/modules/rostests/winetests/windowscodecs/CMakeLists.txt +++ b/modules/rostests/winetests/windowscodecs/CMakeLists.txt @@ -3,11 +3,6 @@ add_definitions( -DUSE_WINE_TODOS -DWINETEST_USE_DBGSTR_LONGLONG) -# to be removed after synching with newer Wine -if(GCC AND GCC_VERSION VERSION_GREATER 7) - add_compile_flags("-Wno-stringop-overflow") -endif() - list(APPEND SOURCE bitmap.c bmpformat.c diff --git a/modules/rostests/winetests/windowscodecs/bitmap.c b/modules/rostests/winetests/windowscodecs/bitmap.c index d4b597900db..6cb0c5665c2 100644 --- a/modules/rostests/winetests/windowscodecs/bitmap.c +++ b/modules/rostests/winetests/windowscodecs/bitmap.c @@ -30,6 +30,71 @@ #include "wincodec.h" #include "wine/test.h" +#include "initguid.h" +DEFINE_GUID(IID_IMILUnknown,0x0ccd7824,0xdc16,0x4d09,0xbc,0xa8,0x6b,0x09,0xc4,0xef,0x55,0x35); +DEFINE_GUID(IID_IMILBitmap,0xb1784d3f,0x8115,0x4763,0x13,0xaa,0x32,0xed,0xdb,0x68,0x29,0x4a); +DEFINE_GUID(IID_IMILBitmapSource,0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe); +DEFINE_GUID(IID_IMILBitmapLock,0xa67b2b53,0x8fa1,0x4155,0x8f,0x64,0x0c,0x24,0x7a,0x8f,0x84,0xcd); +DEFINE_GUID(IID_IMILBitmapScaler,0xa767b0f0,0x1c8c,0x4aef,0x56,0x8f,0xad,0xf9,0x6d,0xcf,0xd5,0xcb); +DEFINE_GUID(IID_IMILFormatConverter,0x7e2a746f,0x25c5,0x4851,0xb3,0xaf,0x44,0x3b,0x79,0x63,0x9e,0xc0); +DEFINE_GUID(IID_IMILPalette,0xca8e206f,0xf22c,0x4af7,0x6f,0xba,0x7b,0xed,0x5e,0xb1,0xc9,0x2f); + +#undef INTERFACE +#define INTERFACE IMILBitmapSource +DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) +{ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IMILBitmap +DECLARE_INTERFACE_(IMILBitmap,IMILBitmapSource) +{ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; + /*** IMILBitmap methods ***/ + STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; + STDMETHOD_(HRESULT,Lock)(THIS_ const WICRect *,DWORD,IWICBitmapLock **) PURE; + STDMETHOD_(HRESULT,Unlock)(THIS_ IWICBitmapLock *) PURE; + STDMETHOD_(HRESULT,SetPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,SetResolution)(THIS_ double,double) PURE; + STDMETHOD_(HRESULT,AddDirtyRect)(THIS_ const WICRect *) PURE; +}; + +#undef INTERFACE +#define INTERFACE IMILBitmapScaler +DECLARE_INTERFACE_(IMILBitmapScaler,IMILBitmapSource) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; + /*** IMILBitmapScaler methods ***/ + STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; + STDMETHOD_(HRESULT,Initialize)(THIS_ IMILBitmapSource *,UINT,UINT,WICBitmapInterpolationMode); +}; + static IWICImagingFactory *factory; static HRESULT WINAPI bitmapsource_QueryInterface(IWICBitmapSource *iface, REFIID iid, void **ppv) @@ -1088,6 +1153,7 @@ static void test_bitmap_scaler(void) double res_x, res_y; IWICBitmap *bitmap; UINT width, height; + BYTE buf[16]; HRESULT hr; hr = IWICImagingFactory_CreateBitmap(factory, 4, 2, &GUID_WICPixelFormat24bppBGR, WICBitmapCacheOnLoad, &bitmap); @@ -1165,6 +1231,9 @@ static void test_bitmap_scaler(void) hr = IWICBitmapScaler_GetSize(scaler, &width, &height); ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr); + hr = IWICBitmapScaler_CopyPixels(scaler, NULL, 1, sizeof(buf), buf); + ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr %#x.\n", hr); + hr = IWICBitmapScaler_Initialize(scaler, (IWICBitmapSource *)bitmap, 0, 2, WICBitmapInterpolationModeNearestNeighbor); ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); @@ -1245,6 +1314,158 @@ static void test_bitmap_scaler(void) IWICBitmap_Release(bitmap); } +static LONG obj_refcount(void *obj) +{ + IUnknown_AddRef((IUnknown *)obj); + return IUnknown_Release((IUnknown *)obj); +} + +static void test_IMILBitmap(void) +{ + HRESULT hr; + IWICBitmap *bitmap; + IWICBitmapScaler *scaler; + IMILBitmap *mil_bitmap; + IMILBitmapSource *mil_source; + IMILBitmapScaler *mil_scaler; + IUnknown *wic_unknown, *mil_unknown; + WICPixelFormatGUID format; + int MIL_format; + UINT width, height; + double dpix, dpiy; + BYTE buf[256]; + + /* Bitmap */ + hr = IWICImagingFactory_CreateBitmap(factory, 1, 1, &GUID_WICPixelFormat24bppBGR, + WICBitmapCacheOnDemand, &bitmap); + ok(hr == S_OK, "CreateBitmap error %#x\n", hr); + + ok(obj_refcount(bitmap) == 1, "ref count %d\n", obj_refcount(bitmap)); + + hr = IWICBitmap_GetPixelFormat(bitmap, &format); + ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); + ok(IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR), "wrong format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICBitmap_GetResolution(bitmap, &dpix, &dpiy); + ok(hr == S_OK, "GetResolution error %#x\n", hr); + ok(dpix == 0.0, "got %f, expected 0.0\n", dpix); + ok(dpiy == 0.0, "got %f, expected 0.0\n", dpiy); + + hr = IWICBitmap_SetResolution(bitmap, 12.0, 34.0); + ok(hr == S_OK, "SetResolution error %#x\n", hr); + + hr = IWICBitmap_GetResolution(bitmap, &dpix, &dpiy); + ok(hr == S_OK, "GetResolution error %#x\n", hr); + ok(dpix == 12.0, "got %f, expected 12.0\n", dpix); + ok(dpiy == 34.0, "got %f, expected 34.0\n", dpiy); + + hr = IWICBitmap_GetSize(bitmap, &width, &height); + ok(hr == S_OK, "GetSize error %#x\n", hr); + ok(width == 1, "got %u, expected 1\n", width); + ok(height == 1, "got %u, expected 1\n", height); + + hr = IWICBitmap_QueryInterface(bitmap, &IID_IMILBitmap, (void **)&mil_bitmap); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + + ok(obj_refcount(bitmap) == 2, "ref count %d\n", obj_refcount(bitmap)); + ok(obj_refcount(mil_bitmap) == 2, "ref count %d\n", obj_refcount(mil_bitmap)); + + hr = IWICBitmap_QueryInterface(bitmap, &IID_IUnknown, (void **)&wic_unknown); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + + hr = mil_bitmap->lpVtbl->QueryInterface(mil_bitmap, &IID_IUnknown, (void **)&mil_unknown); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + ok((void *)wic_unknown->lpVtbl == (void *)mil_unknown->lpVtbl, "wrong lpVtbl ptrs %p != %p\n", wic_unknown->lpVtbl, mil_unknown->lpVtbl); + + IUnknown_Release(wic_unknown); + IUnknown_Release(mil_unknown); + + hr = IWICBitmap_QueryInterface(bitmap, &IID_IMILBitmapSource, (void **)&mil_source); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + ok((void *)mil_source->lpVtbl == (void *)mil_bitmap->lpVtbl, "IMILBitmap->lpVtbl should be equal to IMILBitmapSource->lpVtbl\n"); + + ok(obj_refcount(bitmap) == 3, "ref count %d\n", obj_refcount(bitmap)); + ok(obj_refcount(mil_bitmap) == 3, "ref count %d\n", obj_refcount(mil_bitmap)); + ok(obj_refcount(mil_source) == 3, "ref count %d\n", obj_refcount(mil_source)); + + hr = mil_source->lpVtbl->GetPixelFormat(mil_source, &MIL_format); + ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); + ok(MIL_format == 0x0c, "wrong format %d\n", MIL_format); + + hr = mil_source->lpVtbl->GetResolution(mil_source, &dpix, &dpiy); + ok(hr == S_OK, "GetResolution error %#x\n", hr); + ok(dpix == 12.0, "got %f, expected 12.0\n", dpix); + ok(dpiy == 34.0, "got %f, expected 34.0\n", dpiy); + + hr = mil_source->lpVtbl->GetSize(mil_source, &width, &height); + ok(hr == S_OK, "GetSize error %#x\n", hr); + ok(width == 1, "got %u, expected 1\n", width); + ok(height == 1, "got %u, expected 1\n", height); + + /* Scaler */ + hr = IWICImagingFactory_CreateBitmapScaler(factory, &scaler); + ok(hr == S_OK, "CreateBitmapScaler error %#x\n", hr); + + ok(obj_refcount(scaler) == 1, "ref count %d\n", obj_refcount(scaler)); + + hr = IWICBitmapScaler_QueryInterface(scaler, &IID_IMILBitmapScaler, (void **)&mil_scaler); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + + ok(obj_refcount(scaler) == 2, "ref count %d\n", obj_refcount(scaler)); + ok(obj_refcount(mil_scaler) == 2, "ref count %d\n", obj_refcount(mil_scaler)); + + hr = IWICBitmapScaler_QueryInterface(scaler, &IID_IUnknown, (void **)&wic_unknown); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + + hr = mil_scaler->lpVtbl->QueryInterface(mil_scaler, &IID_IUnknown, (void **)&mil_unknown); + ok(hr == S_OK, "QueryInterface error %#x\n", hr); + ok((void *)wic_unknown->lpVtbl == (void *)mil_unknown->lpVtbl, "wrong lpVtbl ptrs %p != %p\n", wic_unknown->lpVtbl, mil_unknown->lpVtbl); + + IUnknown_Release(wic_unknown); + IUnknown_Release(mil_unknown); + + hr = mil_scaler->lpVtbl->GetPixelFormat(mil_scaler, &MIL_format); + ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetPixelFormat error %#x\n", hr); + + hr = mil_scaler->lpVtbl->GetResolution(mil_scaler, &dpix, &dpiy); + ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetResolution error %#x\n", hr); + + hr = mil_scaler->lpVtbl->GetSize(mil_scaler, &width, &height); + ok(hr == WINCODEC_ERR_NOTINITIALIZED, "GetSize error %#x\n", hr); + + memset(buf, 0xde, sizeof(buf)); + hr = mil_scaler->lpVtbl->CopyPixels(mil_scaler, NULL, 3, sizeof(buf), buf); + ok(hr == WINCODEC_ERR_NOTINITIALIZED, "CopyPixels error %#x\n", hr); + + hr = mil_scaler->lpVtbl->Initialize(mil_scaler, mil_source, 1, 1, 1); + ok(hr == S_OK, "Initialize error %#x\n", hr); + + hr = mil_scaler->lpVtbl->GetPixelFormat(mil_scaler, &MIL_format); + ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); + ok(MIL_format == 0x0c, "wrong format %d\n", MIL_format); + + hr = mil_scaler->lpVtbl->GetResolution(mil_scaler, &dpix, &dpiy); + ok(hr == S_OK, "GetResolution error %#x\n", hr); + ok(dpix == 12.0, "got %f, expected 12.0\n", dpix); + ok(dpiy == 34.0, "got %f, expected 34.0\n", dpiy); + + hr = mil_scaler->lpVtbl->GetSize(mil_scaler, &width, &height); + ok(hr == S_OK, "GetSize error %#x\n", hr); + ok(width == 1, "got %u, expected 1\n", width); + ok(height == 1, "got %u, expected 1\n", height); + + memset(buf, 0xde, sizeof(buf)); + hr = mil_scaler->lpVtbl->CopyPixels(mil_scaler, NULL, 3, sizeof(buf), buf); + ok(hr == S_OK, "CopyPixels error %#x\n", hr); + ok(buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0xde,"wrong data: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); + + mil_scaler->lpVtbl->Release(mil_scaler); + IWICBitmapScaler_Release(scaler); + mil_source->lpVtbl->Release(mil_source); + mil_bitmap->lpVtbl->Release(mil_bitmap); + IWICBitmap_Release(bitmap); +} + START_TEST(bitmap) { HRESULT hr; @@ -1255,6 +1476,7 @@ START_TEST(bitmap) &IID_IWICImagingFactory, (void**)&factory); ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + test_IMILBitmap(); test_createbitmap(); test_createbitmapfromsource(); test_CreateBitmapFromMemory(); diff --git a/modules/rostests/winetests/windowscodecs/converter.c b/modules/rostests/winetests/windowscodecs/converter.c index 8682f870619..348d5a8cb21 100644 --- a/modules/rostests/winetests/windowscodecs/converter.c +++ b/modules/rostests/winetests/windowscodecs/converter.c @@ -397,8 +397,8 @@ static const struct bitmap_data testdata_2bppIndexed = { /* some encoders (like BMP) require data to be 4-bytes aligned */ static const BYTE bits_4bpp[] = { - 0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23, - 0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67}; + 0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44}; static const struct bitmap_data testdata_4bppIndexed = { &GUID_WICPixelFormat4bppIndexed, 4, bits_4bpp, 32, 2, 96.0, 96.0}; @@ -416,8 +416,8 @@ static const struct bitmap_data testdata_8bppIndexed_4colors = { &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_4colors, 32, 2, 96.0, 96.0}; static const BYTE bits_8bpp[] = { - 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3, - 4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7}; + 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static const struct bitmap_data testdata_8bppIndexed = { &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 32, 2, 96.0, 96.0}; @@ -491,6 +491,18 @@ static const struct bitmap_data testdata_32bppPBGRA = { static const struct bitmap_data testdata_32bppPRGBA = { &GUID_WICPixelFormat32bppPRGBA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0}; +static const BYTE bits_64bppRGBA[] = { + 128,255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255,128, 255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255, + 128,255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255,128, 255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255, + 128,255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255,128, 255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255, + 128,255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255,128, 255,128,0,128,0,128,255,128, 0,128,255,128,0,128,255,128, 0,128,0,128,255,128,255,128, 0,128,0,128,0,128,255, + 128,0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255,128, 0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255, + 128,0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255,128, 0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255, + 128,0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255,128, 0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255, + 128,0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255,128, 0,128,255,128,255,128,255,128, 255,128,0,128,255,128,255,128, 255,128,255,128,0,128,255,128, 255,128,255,128,255,128,255}; +static const struct bitmap_data testdata_64bppRGBA = { + &GUID_WICPixelFormat64bppRGBA, 64, bits_64bppRGBA, 32, 2, 96.0, 96.0}; + /* XP and 2003 use linear color conversion, later versions use sRGB gamma */ static const float bits_32bppGrayFloat_xp[] = { 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f, @@ -863,7 +875,7 @@ static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format) ok(hr == S_OK, "GetCount error %#x\n", hr); ok(count != 0, "wrong count %u\n", count); - for (i = 0; i < sizeof(tag)/sizeof(tag[0]); i++) + for (i = 0; i < ARRAY_SIZE(tag); i++) { PropVariantInit(&id); PropVariantInit(&value); @@ -880,6 +892,8 @@ static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format) } else tag[i].value[0] = -1; + + PropVariantClear(&value); } IWICMetadataReader_Release(reader); @@ -1319,7 +1333,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls hr = IWICBitmapEncoderInfo_GetCLSID(info, &clsid); ok(hr == S_OK, "wrong error %#x\n", hr); - ok(!IsEqualGUID(&clsid_encoder, &clsid), "wrong CLSID %s (%s)\n", + ok(!IsEqualGUID(clsid_encoder, &clsid), "wrong CLSID %s (%s)\n", wine_dbgstr_guid(clsid_encoder), wine_dbgstr_guid(&clsid)); IWICBitmapEncoderInfo_Release(info); @@ -1408,8 +1422,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name); else ok(hr == S_OK || - (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) || - (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) || + (FAILED(hr) && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) /* XP */ || + (FAILED(hr) && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) /* XP */ || broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */, "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name); } @@ -1688,7 +1702,7 @@ static void test_converter_8bppIndexed(void) ok(hr == S_OK, "GetColorCount error %#x\n", hr); ok(count == 0, "expected 0, got %u\n", count); - /* NULL palette + Custom type*/ + /* NULL palette + Custom type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1701,7 +1715,7 @@ static void test_converter_8bppIndexed(void) ok(hr == S_OK, "CopyPixels error %#x\n", hr); IWICFormatConverter_Release(converter); - /* NULL palette + Custom type*/ + /* NULL palette + Custom type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1714,7 +1728,7 @@ static void test_converter_8bppIndexed(void) ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr); IWICFormatConverter_Release(converter); - /* empty palette + Custom type*/ + /* empty palette + Custom type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1736,7 +1750,7 @@ static void test_converter_8bppIndexed(void) ok(count == 0, "expected 0\n"); IWICFormatConverter_Release(converter); - /* NULL palette + Predefined type*/ + /* NULL palette + Predefined type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1757,7 +1771,7 @@ static void test_converter_8bppIndexed(void) ok(count != 0, "expected != 0\n"); IWICFormatConverter_Release(converter); - /* not empty palette + Predefined type*/ + /* not empty palette + Predefined type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1778,7 +1792,7 @@ static void test_converter_8bppIndexed(void) ok(count != 0, "expected != 0\n"); IWICFormatConverter_Release(converter); - /* not empty palette + MedianCut type*/ + /* not empty palette + MedianCut type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1799,7 +1813,7 @@ static void test_converter_8bppIndexed(void) ok(count != 0, "expected != 0\n"); IWICFormatConverter_Release(converter); - /* NULL palette + MedianCut type*/ + /* NULL palette + MedianCut type */ hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, @@ -1867,6 +1881,9 @@ START_TEST(converter) test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE); test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE); + test_conversion(&testdata_64bppRGBA, &testdata_32bppRGBA, "64bppRGBA -> 32bppRGBA", FALSE); + test_conversion(&testdata_64bppRGBA, &testdata_32bppRGB, "64bppRGBA -> 32bppRGB", FALSE); + test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE); test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE); diff --git a/modules/rostests/winetests/windowscodecs/metadata.c b/modules/rostests/winetests/windowscodecs/metadata.c index 91a5d20f377..58da19cee47 100644 --- a/modules/rostests/winetests/windowscodecs/metadata.c +++ b/modules/rostests/winetests/windowscodecs/metadata.c @@ -3032,6 +3032,7 @@ static void test_queryreader(void) ok(hr == E_INVALIDARG, "got %#x\n", hr); IWICMetadataQueryReader_Release(new_reader); + PropVariantClear(&value); } else if (value.vt == VT_LPSTR) ok(!lstrcmpA(U(value).pszVal, test_data[i].str_value), "%u: expected %s, got %s\n", diff --git a/modules/rostests/winetests/windowscodecs/palette.c b/modules/rostests/winetests/windowscodecs/palette.c index 5bb25fa4279..583fa66c80e 100644 --- a/modules/rostests/winetests/windowscodecs/palette.c +++ b/modules/rostests/winetests/windowscodecs/palette.c @@ -602,7 +602,7 @@ static void test_palette_from_bitmap(void) ok(hr == S_OK, "GetColorCount error %#x\n", hr); ok(count == 2, "expected 2, got %u\n", count); - /* without trasparent color */ + /* without transparent color */ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, FALSE); ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); type = -1; @@ -619,7 +619,7 @@ static void test_palette_from_bitmap(void) ok(ret == count, "expected %u, got %u\n", count, ret); ok(color[count - 1] != 0, "expected !0, got %08x\n", color[count - 1]); - /* with trasparent color */ + /* with transparent color */ hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, TRUE); ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); type = -1; diff --git a/modules/rostests/winetests/windowscodecs/stream.c b/modules/rostests/winetests/windowscodecs/stream.c index 3750c32f3c2..048f1326be0 100644 --- a/modules/rostests/winetests/windowscodecs/stream.c +++ b/modules/rostests/winetests/windowscodecs/stream.c @@ -765,7 +765,7 @@ static void test_StreamOnIStream(void) ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); hr = IWICStream_InitializeFromMemory(stream, memory, sizeof(memory)); - ok(hr == S_OK, "Failed to initialize stream, hr %#x.", hr); + ok(hr == S_OK, "Failed to initialize stream, hr %#x.\n", hr); hr = IWICImagingFactory_CreateStream(factory, &substream); ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); diff --git a/modules/rostests/winetests/windowscodecs/tiffformat.c b/modules/rostests/winetests/windowscodecs/tiffformat.c index 289e0611450..8cdc0047a21 100644 --- a/modules/rostests/winetests/windowscodecs/tiffformat.c +++ b/modules/rostests/winetests/windowscodecs/tiffformat.c @@ -750,7 +750,8 @@ static void test_tiff_24bpp(void) static const BYTE expected_data[] = { 0x33,0x22,0x11 }; hr = create_decoder(&tiff_24bpp_data, sizeof(tiff_24bpp_data), &decoder); - ok(hr == S_OK, "got %#x\n", hr); + ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr); + if (hr != S_OK) return; ok(decoder != NULL, "Failed to load TIFF image data\n"); hr = IWICBitmapDecoder_GetFrameCount(decoder, &count);
5 years
1
0
0
0
[reactos] 01/01: [WINDOWSCODECS] Sync with Wine Staging 4.18. CORE-16441
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f6a1733dafffe30252fdb…
commit f6a1733dafffe30252fdb50879c56fea27e2d42a Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Dec 7 13:04:33 2019 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Dec 7 13:04:33 2019 +0100 [WINDOWSCODECS] Sync with Wine Staging 4.18. CORE-16441 --- dll/win32/windowscodecs/bitmap.c | 92 ++++++++++++----------------- dll/win32/windowscodecs/converter.c | 91 ++++++++++++++++++++-------- dll/win32/windowscodecs/icnsformat.c | 1 - dll/win32/windowscodecs/metadataquery.c | 3 +- dll/win32/windowscodecs/msvc.h | 2 - dll/win32/windowscodecs/palette.c | 4 +- dll/win32/windowscodecs/pngformat.c | 13 +++- dll/win32/windowscodecs/precomp.h | 3 - dll/win32/windowscodecs/scaler.c | 42 +------------ dll/win32/windowscodecs/tiffformat.c | 1 + dll/win32/windowscodecs/typeof.h | 1 + dll/win32/windowscodecs/wincodecs_private.h | 39 ++++++------ media/doc/README.WINE | 2 +- 13 files changed, 145 insertions(+), 149 deletions(-) diff --git a/dll/win32/windowscodecs/bitmap.c b/dll/win32/windowscodecs/bitmap.c index a44f5bd7b39..7959da6911d 100644 --- a/dll/win32/windowscodecs/bitmap.c +++ b/dll/win32/windowscodecs/bitmap.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Vincent Povirk for CodeWeavers + * Copyright 2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +17,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#ifndef __REACTOS__ #include "config.h" +#endif #include <stdarg.h> @@ -28,6 +31,7 @@ #include "wincodecs_private.h" +#include "wine/asm.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); @@ -38,7 +42,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); typedef struct BitmapImpl { IMILUnknown1 IMILUnknown1_iface; LONG ref; - IMILBitmapSource IMILBitmapSource_iface; + IMILBitmap IMILBitmap_iface; IWICBitmap IWICBitmap_iface; IMILUnknown2 IMILUnknown2_iface; IWICPalette *palette; @@ -68,9 +72,9 @@ static inline BitmapImpl *impl_from_IWICBitmap(IWICBitmap *iface) return CONTAINING_RECORD(iface, BitmapImpl, IWICBitmap_iface); } -static inline BitmapImpl *impl_from_IMILBitmapSource(IMILBitmapSource *iface) +static inline BitmapImpl *impl_from_IMILBitmap(IMILBitmap *iface) { - return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmapSource_iface); + return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmap_iface); } static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface) @@ -254,7 +258,7 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid, else if (IsEqualIID(&IID_IMILBitmap, iid) || IsEqualIID(&IID_IMILBitmapSource, iid)) { - *ppv = &This->IMILBitmapSource_iface; + *ppv = &This->IMILBitmap_iface; } else { @@ -478,51 +482,30 @@ static const IWICBitmapVtbl BitmapImpl_Vtbl = { BitmapImpl_SetResolution }; -static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REFIID iid, +static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmap *iface, REFIID iid, void **ppv) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IMILBitmap, iid) || - IsEqualIID(&IID_IMILBitmapSource, iid)) - { - IUnknown_AddRef(&This->IMILBitmapSource_iface); - *ppv = &This->IMILBitmapSource_iface; - return S_OK; - } - else if (IsEqualIID(&IID_IWICBitmap, iid) || - IsEqualIID(&IID_IWICBitmapSource, iid)) - { - IUnknown_AddRef(&This->IWICBitmap_iface); - *ppv = &This->IWICBitmap_iface; - return S_OK; - } - - FIXME("unknown interface %s\n", debugstr_guid(iid)); - *ppv = NULL; - return E_NOINTERFACE; + return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv); } -static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmapSource *iface) +static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmap *iface) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); return IWICBitmap_AddRef(&This->IWICBitmap_iface); } -static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmapSource *iface) +static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmap *iface) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); return IWICBitmap_Release(&This->IWICBitmap_iface); } -static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface, +static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmap *iface, UINT *width, UINT *height) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p,%p)\n", iface, width, height); return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height); } @@ -556,10 +539,10 @@ static const struct { &GUID_WICPixelFormat32bppCMYK, 0x1c } }; -static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface, +static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmap *iface, int *format) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); int i; TRACE("(%p,%p)\n", iface, format); @@ -581,33 +564,33 @@ static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface, return S_OK; } -static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface, +static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmap *iface, double *dpix, double *dpiy) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy); } -static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface, +static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmap *iface, IWICPalette *palette) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p)\n", iface, palette); return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette); } -static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface, +static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmap *iface, const WICRect *rc, UINT stride, UINT size, BYTE *buffer) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer); } -static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv) +static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmap *iface, void **ppv) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p)\n", iface, ppv); @@ -619,41 +602,41 @@ static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **pp return S_OK; } -static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) +static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmap *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock); return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock); } -static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock) +static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmap *iface, IWICBitmapLock *lock) { TRACE("(%p,%p)\n", iface, lock); IWICBitmapLock_Release(lock); return S_OK; } -static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette) +static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmap *iface, IWICPalette *palette) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%p)\n", iface, palette); return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette); } -static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy) +static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmap *iface, double dpix, double dpiy) { - BitmapImpl *This = impl_from_IMILBitmapSource(iface); + BitmapImpl *This = impl_from_IMILBitmap(iface); TRACE("(%p,%f,%f)\n", iface, dpix, dpiy); return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy); } -static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc) +static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmap *iface, const WICRect *rc) { FIXME("(%p,%p): stub\n", iface, rc); return E_NOTIMPL; } -static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = +static const IMILBitmapVtbl IMILBitmapImpl_Vtbl = { IMILBitmapImpl_QueryInterface, IMILBitmapImpl_AddRef, @@ -674,6 +657,7 @@ static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid, void **ppv) { + /* It's not clear what interface should be returned here */ FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); *ppv = NULL; return E_NOINTERFACE; @@ -835,7 +819,7 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasiz } This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; - This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; + This->IMILBitmap_iface.lpVtbl = &IMILBitmapImpl_Vtbl; This->IMILUnknown1_iface.lpVtbl = &IMILUnknown1Impl_Vtbl; This->IMILUnknown2_iface.lpVtbl = &IMILUnknown2Impl_Vtbl; This->ref = 1; diff --git a/dll/win32/windowscodecs/converter.c b/dll/win32/windowscodecs/converter.c index c3476c3efa4..dcc2f05693f 100644 --- a/dll/win32/windowscodecs/converter.c +++ b/dll/win32/windowscodecs/converter.c @@ -85,14 +85,6 @@ typedef struct FormatConverter { } FormatConverter; /*
https://www.w3.org/Graphics/Color/srgb
*/ -#ifndef __REACTOS__ -static inline float from_sRGB_component(float f) -{ - if (f <= 0.04045f) return f / 12.92f; - return powf((f + 0.055f) / 1.055f, 2.4f); -} -#endif - static inline float to_sRGB_component(float f) { if (f <= 0.0031308f) return 12.92f * f; @@ -100,6 +92,12 @@ static inline float to_sRGB_component(float f) } #if 0 /* FIXME: enable once needed */ +static inline float from_sRGB_component(float f) +{ + if (f <= 0.04045f) return f / 12.92f; + return powf((f + 0.055f) / 1.055f, 2.4f); +} + static void from_sRGB(BYTE *bgr) { float r, g, b; @@ -460,8 +458,9 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe dstpixel=(DWORD*)dstrow; for (x=0; x<prc->Width; x++) { + srcbyte++; *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte; - srcbyte+=2; + srcbyte++; } srcrow += srcstride; dstrow += cbStride; @@ -778,9 +777,9 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe dstpixel=(DWORD*)dstrow; for (x=0; x<prc->Width; x++) { BYTE red, green, blue; - red = *srcpixel++; srcpixel++; - green = *srcpixel++; srcpixel++; - blue = *srcpixel++; srcpixel++; + srcpixel++; red = *srcpixel++; + srcpixel++; green = *srcpixel++; + srcpixel++; blue = *srcpixel++; *dstpixel++=0xff000000|red<<16|green<<8|blue; } srcrow += srcstride; @@ -822,10 +821,10 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe dstpixel=(DWORD*)dstrow; for (x=0; x<prc->Width; x++) { BYTE red, green, blue, alpha; - red = *srcpixel++; srcpixel++; - green = *srcpixel++; srcpixel++; - blue = *srcpixel++; srcpixel++; - alpha = *srcpixel++; srcpixel++; + srcpixel++; red = *srcpixel++; + srcpixel++; green = *srcpixel++; + srcpixel++; blue = *srcpixel++; + srcpixel++; alpha = *srcpixel++; *dstpixel++=alpha<<24|red<<16|green<<8|blue; } srcrow += srcstride; @@ -872,11 +871,47 @@ static HRESULT copypixels_to_32bppRGBA(struct FormatConverter *This, const WICRe switch (source_format) { case format_32bppRGB: + if (prc) + { + INT x, y; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + if (FAILED(hr)) return hr; + + /* set all alpha values to 255 */ + for (y=0; y<prc->Height; y++) + for (x=0; x<prc->Width; x++) + pbBuffer[cbStride*y+4*x+3] = 0xff; + } + return S_OK; + case format_32bppRGBA: - case format_32bppPRGBA: if (prc) return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); return S_OK; + + case format_32bppPRGBA: + if (prc) + { + INT x, y; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + if (FAILED(hr)) return hr; + + for (y=0; y<prc->Height; y++) + for (x=0; x<prc->Width; x++) + { + BYTE alpha = pbBuffer[cbStride*y+4*x+3]; + if (alpha != 0 && alpha != 255) + { + pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha; + pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha; + pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha; + } + } + } + return S_OK; + default: hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); if (SUCCEEDED(hr) && prc) @@ -1304,6 +1339,9 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec return hr; } + if (!prc) + return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format); + srcstride = 3 * prc->Width; srcdatasize = srcstride * prc->Height; @@ -1311,7 +1349,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec if (!srcdata) return E_OUTOFMEMORY; hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); - if (SUCCEEDED(hr) && prc) + if (SUCCEEDED(hr)) { INT x, y; BYTE *src = srcdata, *dst = pbBuffer; @@ -1337,7 +1375,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec return hr; } -static UINT rgb_to_palette_index(BYTE r, BYTE g, BYTE b, WICColor *colors, UINT count) +static UINT rgb_to_palette_index(BYTE bgr[3], WICColor *colors, UINT count) { UINT best_diff, best_index, i; @@ -1347,15 +1385,15 @@ static UINT rgb_to_palette_index(BYTE r, BYTE g, BYTE b, WICColor *colors, UINT for (i = 0; i < count; i++) { BYTE pal_r, pal_g, pal_b; - DWORD diff_r, diff_g, diff_b, diff; + UINT diff_r, diff_g, diff_b, diff; pal_r = colors[i] >> 16; pal_g = colors[i] >> 8; pal_b = colors[i]; - diff_r = r - pal_r; - diff_g = g - pal_g; - diff_b = b - pal_b; + diff_r = bgr[2] - pal_r; + diff_g = bgr[1] - pal_g; + diff_b = bgr[0] - pal_b; diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b; if (diff == 0) return i; @@ -1386,6 +1424,9 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC return S_OK; } + if (!prc) + return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format); + if (!This->palette) return WINCODEC_ERR_WRONGSTATE; hr = IWICPalette_GetColors(This->palette, 256, colors, &count); @@ -1398,7 +1439,7 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC if (!srcdata) return E_OUTOFMEMORY; hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); - if (SUCCEEDED(hr) && prc) + if (SUCCEEDED(hr)) { INT x, y; BYTE *src = srcdata, *dst = pbBuffer; @@ -1409,7 +1450,7 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC for (x = 0; x < prc->Width; x++) { - dst[x] = rgb_to_palette_index(bgr[2], bgr[1], bgr[0], colors, count); + dst[x] = rgb_to_palette_index(bgr, colors, count); bgr += 3; } src += srcstride; diff --git a/dll/win32/windowscodecs/icnsformat.c b/dll/win32/windowscodecs/icnsformat.c index 02e8ee97e6d..8194bc508a5 100644 --- a/dll/win32/windowscodecs/icnsformat.c +++ b/dll/win32/windowscodecs/icnsformat.c @@ -75,7 +75,6 @@ #undef SetRect #undef ShowCursor #undef UnionRect -#undef DPRINTF #endif #define COBJMACROS diff --git a/dll/win32/windowscodecs/metadataquery.c b/dll/win32/windowscodecs/metadataquery.c index c4c188d8c9d..79340427547 100644 --- a/dll/win32/windowscodecs/metadataquery.c +++ b/dll/win32/windowscodecs/metadataquery.c @@ -242,7 +242,6 @@ static HRESULT get_token(struct string_t *elem, PROPVARIANT *id, PROPVARIANT *sc bstr = next_token.u.bstrVal; end++; - p = end; while (*end && *end != '}' && end - start < elem->len) { if (*end == '\\') end++; @@ -925,7 +924,7 @@ HRESULT WINAPI WICMapSchemaToName(REFGUID format, LPWSTR schema, UINT len, WCHAR return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } - if (ret_len) *ret_len = lstrlenW(name2schema[i].name) + 1; + *ret_len = lstrlenW(name2schema[i].name) + 1; return S_OK; } } diff --git a/dll/win32/windowscodecs/msvc.h b/dll/win32/windowscodecs/msvc.h index a694b8601bb..6bb78f43af6 100644 --- a/dll/win32/windowscodecs/msvc.h +++ b/dll/win32/windowscodecs/msvc.h @@ -1,6 +1,4 @@ -#define __ASM_STDCALL_FUNC(name,args,code) - #define typeof(X_) __typeof_ ## X_ struct IMILUnknown1; diff --git a/dll/win32/windowscodecs/palette.c b/dll/win32/windowscodecs/palette.c index 1c1e85834b8..f99cbe00fd1 100644 --- a/dll/win32/windowscodecs/palette.c +++ b/dll/win32/windowscodecs/palette.c @@ -669,8 +669,8 @@ static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *palette, hr = IWICBitmapSource_GetPixelFormat(source, &format); if (hr != S_OK) return hr; - /* For interoperability with gdiplus where PixelFormat24bppRGB actully stored - * as BGR (and there is no a corresponding RGB format) we have to use 24bppBGR + /* For interoperability with gdiplus where PixelFormat24bppRGB is actually stored + * as BGR (and there is no corresponding RGB format), we have to use 24bppBGR * to avoid format conversions. */ if (!IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR)) diff --git a/dll/win32/windowscodecs/pngformat.c b/dll/win32/windowscodecs/pngformat.c index 7050c95121b..c0e272e86f0 100644 --- a/dll/win32/windowscodecs/pngformat.c +++ b/dll/win32/windowscodecs/pngformat.c @@ -332,6 +332,7 @@ MAKE_FUNCPTR(png_set_strip_16); MAKE_FUNCPTR(png_set_tRNS); MAKE_FUNCPTR(png_set_tRNS_to_alpha); MAKE_FUNCPTR(png_set_write_fn); +MAKE_FUNCPTR(png_set_swap); MAKE_FUNCPTR(png_read_end); MAKE_FUNCPTR(png_read_image); MAKE_FUNCPTR(png_read_info); @@ -398,6 +399,7 @@ static void *load_libpng(void) LOAD_FUNCPTR(png_set_tRNS); LOAD_FUNCPTR(png_set_tRNS_to_alpha); LOAD_FUNCPTR(png_set_write_fn); + LOAD_FUNCPTR(png_set_swap); LOAD_FUNCPTR(png_read_end); LOAD_FUNCPTR(png_read_image); LOAD_FUNCPTR(png_read_info); @@ -620,7 +622,6 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p if (setjmp(jmpbuf)) { ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info); - HeapFree(GetProcessHeap(), 0, row_pointers); This->png_ptr = NULL; hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT; goto end; @@ -643,6 +644,10 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p color_type = ppng_get_color_type(This->png_ptr, This->info_ptr); bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr); + /* PNGs with bit-depth greater than 8 are network byte order. Windows does not expect this. */ + if (bit_depth > 8) + ppng_set_swap(This->png_ptr); + /* check for color-keyed alpha */ transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values); @@ -816,6 +821,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p end: LeaveCriticalSection(&This->lock); + HeapFree(GetProcessHeap(), 0, row_pointers); + return hr; } @@ -1642,6 +1649,10 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, } } + /* Tell PNG we need to byte swap if writing a >8-bpp image */ + if (This->format->bit_depth > 8) + ppng_set_swap(This->png_ptr); + ppng_set_IHDR(This->png_ptr, This->info_ptr, This->width, This->height, This->format->bit_depth, This->format->color_type, This->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, diff --git a/dll/win32/windowscodecs/precomp.h b/dll/win32/windowscodecs/precomp.h index 144e085e442..0d0ac5c7af7 100644 --- a/dll/win32/windowscodecs/precomp.h +++ b/dll/win32/windowscodecs/precomp.h @@ -2,9 +2,6 @@ #ifndef WINCODECS_PRECOMP_H #define WINCODECS_PRECOMP_H -#include <wine/config.h> -#include <wine/port.h> - #include <stdarg.h> #define WIN32_NO_STATUS diff --git a/dll/win32/windowscodecs/scaler.c b/dll/win32/windowscodecs/scaler.c index d19e219feab..d6e56d096ea 100644 --- a/dll/win32/windowscodecs/scaler.c +++ b/dll/win32/windowscodecs/scaler.c @@ -1,5 +1,6 @@ /* * Copyright 2010 Vincent Povirk for CodeWeavers + * Copyright 2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -224,7 +225,7 @@ static HRESULT WINAPI BitmapScaler_CopyPixels(IWICBitmapScaler *iface, if (!This->source) { - hr = WINCODEC_ERR_WRONGSTATE; + hr = WINCODEC_ERR_NOTINITIALIZED; goto end; } @@ -395,30 +396,8 @@ static HRESULT WINAPI IMILBitmapScaler_QueryInterface(IMILBitmapScaler *iface, R void **ppv) { BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IMILBitmapScaler, iid) || - IsEqualIID(&IID_IMILBitmapSource, iid)) - { - IUnknown_AddRef(&This->IMILBitmapScaler_iface); - *ppv = &This->IMILBitmapScaler_iface; - return S_OK; - } - else if (IsEqualIID(&IID_IWICBitmapScaler, iid) || - IsEqualIID(&IID_IWICBitmapSource, iid)) - { - IUnknown_AddRef(&This->IWICBitmapScaler_iface); - *ppv = &This->IWICBitmapScaler_iface; - return S_OK; - } - - FIXME("unknown interface %s\n", debugstr_guid(iid)); - *ppv = NULL; - return E_NOINTERFACE; + return IWICBitmapScaler_QueryInterface(&This->IWICBitmapScaler_iface, iid, ppv); } static ULONG WINAPI IMILBitmapScaler_AddRef(IMILBitmapScaler *iface) @@ -437,12 +416,7 @@ static HRESULT WINAPI IMILBitmapScaler_GetSize(IMILBitmapScaler *iface, UINT *width, UINT *height) { BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - TRACE("(%p,%p,%p)\n", iface, width, height); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - return IWICBitmapScaler_GetSize(&This->IWICBitmapScaler_iface, width, height); } @@ -473,12 +447,7 @@ static HRESULT WINAPI IMILBitmapScaler_GetResolution(IMILBitmapScaler *iface, double *dpix, double *dpiy) { BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - return IWICBitmapScaler_GetResolution(&This->IWICBitmapScaler_iface, dpix, dpiy); } @@ -499,12 +468,7 @@ static HRESULT WINAPI IMILBitmapScaler_CopyPixels(IMILBitmapScaler *iface, const WICRect *rc, UINT stride, UINT size, BYTE *buffer) { BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - return IWICBitmapScaler_CopyPixels(&This->IWICBitmapScaler_iface, rc, stride, size, buffer); } diff --git a/dll/win32/windowscodecs/tiffformat.c b/dll/win32/windowscodecs/tiffformat.c index d9b7c4c6096..6f4f6d06b74 100644 --- a/dll/win32/windowscodecs/tiffformat.c +++ b/dll/win32/windowscodecs/tiffformat.c @@ -289,6 +289,7 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) decode_info->reverse_bgr = 0; decode_info->invert_grayscale = 0; decode_info->tiled = 0; + decode_info->source_bpp = 0; ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); if (!ret) diff --git a/dll/win32/windowscodecs/typeof.h b/dll/win32/windowscodecs/typeof.h index b20434b7cce..91995864ac2 100644 --- a/dll/win32/windowscodecs/typeof.h +++ b/dll/win32/windowscodecs/typeof.h @@ -81,6 +81,7 @@ typedef void (__cdecl typeof(png_set_crc_action))(struct png_struct_def *, int, typedef void (__cdecl typeof(png_set_PLTE))(struct png_struct_def *, struct png_info_def *, const struct png_color_struct *, int); typedef void (__cdecl typeof(png_set_tRNS))(struct png_struct_def *, struct png_info_def *, const unsigned char *, int, const struct png_color_16_struct *); typedef void (__cdecl typeof(png_set_filter))(struct png_struct_def *, int, int); +typedef void (__cdecl typeof(png_set_swap))(struct png_struct_def *); typedef void *thandle_t_1; typedef __typeof_intptr (*TIFFReadWriteProc_1)(thandle_t_1, void *, __typeof_intptr); typedef unsigned int (*TIFFSeekProc_1)(void *, unsigned int, int); diff --git a/dll/win32/windowscodecs/wincodecs_private.h b/dll/win32/windowscodecs/wincodecs_private.h index 22af9a12fbb..ff192c26399 100644 --- a/dll/win32/windowscodecs/wincodecs_private.h +++ b/dll/win32/windowscodecs/wincodecs_private.h @@ -53,7 +53,23 @@ DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; - /*** IMILBitmapSource methods ***/ +}; +#undef INTERFACE + +#define INTERFACE IMILBitmap +DECLARE_INTERFACE_(IMILBitmap,IMILBitmapSource) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IWICBitmapSource methods ***/ + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; + /*** IMILBitmap methods ***/ STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; STDMETHOD_(HRESULT,Lock)(THIS_ const WICRect *,DWORD,IWICBitmapLock **) PURE; STDMETHOD_(HRESULT,Unlock)(THIS_ IWICBitmapLock *) PURE; @@ -64,7 +80,7 @@ DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) #undef INTERFACE #define INTERFACE IMILBitmapScaler -DECLARE_INTERFACE_(IMILBitmapScaler,IUnknown) +DECLARE_INTERFACE_(IMILBitmapScaler,IMILBitmapSource) { /*** IUnknown methods ***/ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; @@ -78,26 +94,11 @@ DECLARE_INTERFACE_(IMILBitmapScaler,IUnknown) STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; /*** IMILBitmapScaler methods ***/ STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; - STDMETHOD_(HRESULT,Initialize)(THIS_ IMILBitmapSource *,UINT,UINT,WICBitmapInterpolationMode); + STDMETHOD_(HRESULT,Initialize)(THIS_ IMILBitmapSource *,UINT,UINT,WICBitmapInterpolationMode) PURE; }; #undef INTERFACE -#ifdef __i386__ /* thiscall functions are i386-specific */ - -#define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func,args) \ - extern typeof(func) THISCALL(func); \ - __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ - "popl %eax\n\t" \ - "pushl %ecx\n\t" \ - "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) -#else /* __i386__ */ - -#define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ - -#endif /* __i386__ */ +#define THISCALLMETHOD_(type,method) type (__thiscall *method) #define INTERFACE IMILUnknown1 DECLARE_INTERFACE_(IMILUnknown1,IUnknown) diff --git a/media/doc/README.WINE b/media/doc/README.WINE index def03896c75..876663af0de 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -197,7 +197,7 @@ dll/win32/version # Synced to WineStaging-4.18 dll/win32/vssapi # Synced to WineStaging-4.18 dll/win32/wbemdisp # Synced to WineStaging-4.18 dll/win32/wbemprox # Synced to WineStaging-4.18 -dll/win32/windowscodecs # Synced to WineStaging-4.0 +dll/win32/windowscodecs # Synced to WineStaging-4.18 dll/win32/windowscodecsext # Synced to WineStaging-2.9 dll/win32/winemp3.acm # Synced to WineStaging-3.3 dll/win32/wing32 # Synced to WineStaging-3.3
5 years
1
0
0
0
[reactos] 01/01: [REGEDIT] Improve arrow button visual (#2133)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4c5b21f06c545a3b5dcaf…
commit 4c5b21f06c545a3b5dcafb8dbf732e2787882089 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Sat Dec 7 10:09:44 2019 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Sat Dec 7 10:09:44 2019 +0900 [REGEDIT] Improve arrow button visual (#2133) Add IDI_ARROW resource icon and use it for the arrow button. --- base/applications/regedit/childwnd.c | 15 +++++++++++++-- base/applications/regedit/main.h | 1 + base/applications/regedit/regedit.rc | 1 + base/applications/regedit/res/arrow.ico | Bin 0 -> 542 bytes base/applications/regedit/resource.h | 1 + 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/base/applications/regedit/childwnd.c b/base/applications/regedit/childwnd.c index 836145dd0c7..d02fb2da14d 100644 --- a/base/applications/regedit/childwnd.c +++ b/base/applications/regedit/childwnd.c @@ -394,6 +394,7 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa WNDPROC oldproc; HFONT hFont; WCHAR buffer[MAX_PATH]; + DWORD style; /* Load "My Computer" string */ LoadStringW(hInst, IDS_MY_COMPUTER, buffer, COUNT_OF(buffer)); @@ -404,12 +405,21 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa wcsncpy(g_pChildWnd->szPath, buffer, MAX_PATH); g_pChildWnd->nSplitPos = 190; g_pChildWnd->hWnd = hWnd; - g_pChildWnd->hAddressBarWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP, + + style = WS_CHILD | WS_VISIBLE | WS_TABSTOP; + g_pChildWnd->hAddressBarWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)0, hInst, 0); - g_pChildWnd->hAddressBtnWnd = CreateWindowExW(0, L"Button", L"\x00BB", WS_CHILD | WS_VISIBLE | WS_CHILDWINDOW | WS_TABSTOP | BS_TEXT | BS_CENTER | BS_VCENTER | BS_FLAT | BS_DEFPUSHBUTTON, + + style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_ICON | BS_CENTER | + BS_VCENTER | BS_FLAT | BS_DEFPUSHBUTTON; + g_pChildWnd->hAddressBtnWnd = CreateWindowExW(0, L"Button", L"\x00BB", style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, (HMENU)0, hInst, 0); + g_pChildWnd->hArrowIcon = (HICON)LoadImageW(hInst, MAKEINTRESOURCEW(IDI_ARROW), + IMAGE_ICON, 12, 12, 0); + SendMessageW(g_pChildWnd->hAddressBtnWnd, BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_pChildWnd->hArrowIcon); + GetClientRect(hWnd, &rc); g_pChildWnd->hTreeWnd = CreateTreeView(hWnd, g_pChildWnd->szPath, (HMENU) TREE_WINDOW); g_pChildWnd->hListWnd = CreateListView(hWnd, (HMENU) LIST_WINDOW, rc.right - g_pChildWnd->nSplitPos); @@ -462,6 +472,7 @@ LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa DestroyListView(g_pChildWnd->hListWnd); DestroyTreeView(g_pChildWnd->hTreeWnd); DestroyMainMenu(); + DestroyIcon(g_pChildWnd->hArrowIcon); HeapFree(GetProcessHeap(), 0, g_pChildWnd); g_pChildWnd = NULL; PostQuitMessage(0); diff --git a/base/applications/regedit/main.h b/base/applications/regedit/main.h index e36600e1a20..084b62cf304 100644 --- a/base/applications/regedit/main.h +++ b/base/applications/regedit/main.h @@ -61,6 +61,7 @@ typedef struct HWND hListWnd; HWND hAddressBarWnd; HWND hAddressBtnWnd; + HICON hArrowIcon; int nFocusPanel; /* 0: left 1: right */ int nSplitPos; WINDOWPLACEMENT pos; diff --git a/base/applications/regedit/regedit.rc b/base/applications/regedit/regedit.rc index 216d4956bd8..58810fb3ced 100644 --- a/base/applications/regedit/regedit.rc +++ b/base/applications/regedit/regedit.rc @@ -40,6 +40,7 @@ IDI_STRING ICON "res/string.ico" IDI_BIN ICON "res/bin.ico" IDI_REGEDIT ICON "res/regedit.ico" IDI_REGFILE ICON "res/regfile.ico" +IDI_ARROW ICON "res/arrow.ico" /* UTF-8 */ #pragma code_page(65001) diff --git a/base/applications/regedit/res/arrow.ico b/base/applications/regedit/res/arrow.ico new file mode 100644 index 00000000000..0ad4359db42 Binary files /dev/null and b/base/applications/regedit/res/arrow.ico differ diff --git a/base/applications/regedit/resource.h b/base/applications/regedit/resource.h index c73c6aeae03..8ada616b95e 100644 --- a/base/applications/regedit/resource.h +++ b/base/applications/regedit/resource.h @@ -34,6 +34,7 @@ #define IDS_APP_TITLE 103 #define IDI_REGEDIT 100 #define IDI_REGFILE 101 +#define IDI_ARROW 102 #define IDI_SMALL 108 #define IDC_REGEDIT 109 #define IDC_REGEDIT_FRAME 110
5 years
1
0
0
0
[reactos] 01/01: [WIN32SS][WINSRV] Do CJK font choose workaround (#2134)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=007f32a22335963ce8197…
commit 007f32a22335963ce81979339ed788c1a4fdb0b8 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Fri Dec 6 22:18:51 2019 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Fri Dec 6 22:18:51 2019 +0900 [WIN32SS][WINSRV] Do CJK font choose workaround (#2134) Don't choose Asian charset font if there is no preferred font for CJK. CORE-12451 --- win32ss/user/winsrv/concfg/font.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/win32ss/user/winsrv/concfg/font.c b/win32ss/user/winsrv/concfg/font.c index 6aa75b074e0..1c3cbb4f191 100644 --- a/win32ss/user/winsrv/concfg/font.c +++ b/win32ss/user/winsrv/concfg/font.c @@ -69,7 +69,13 @@ CreateConsoleFontEx( ~(VARIABLE_PITCH | FF_DECORATIVE | FF_ROMAN | FF_SCRIPT | FF_SWISS)); if (!IsValidConsoleFont(FaceName, CodePage)) + { StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal"); + if (IsCJKCodePage(CodePage)) + { + lf.lfCharSet = ANSI_CHARSET; + } + } StringCchCopyNW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName, LF_FACESIZE);
5 years
1
0
0
0
[reactos] 01/01: [KERNEL32_APITEST] Adjust ConsoleCP testcase for Win10 JPN (#2131)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2f8d847c916ff9184f721…
commit 2f8d847c916ff9184f721b0f14a96db0aff5ae96 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Thu Dec 5 22:07:00 2019 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Thu Dec 5 22:07:00 2019 +0900 [KERNEL32_APITEST] Adjust ConsoleCP testcase for Win10 JPN (#2131) CORE-12451 --- modules/rostests/apitests/kernel32/ConsoleCP.c | 33 ++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/modules/rostests/apitests/kernel32/ConsoleCP.c b/modules/rostests/apitests/kernel32/ConsoleCP.c index 5580fc189b6..94fcdd3c8a0 100644 --- a/modules/rostests/apitests/kernel32/ConsoleCP.c +++ b/modules/rostests/apitests/kernel32/ConsoleCP.c @@ -21,8 +21,9 @@ static const WCHAR u0414[] = { 0x0414, 0 }; /* Д */ static const WCHAR u9580[] = { 0x9580, 0 }; /* 門 */ static const WCHAR ideograph_space = (WCHAR)0x3000; /* fullwidth space */ -LCID lcidJapanese = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), SORT_DEFAULT); -LCID lcidRussian = MAKELCID(MAKELANGID(LANG_RUSSIAN , SUBLANG_DEFAULT), SORT_DEFAULT); +static LCID lcidJapanese = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), SORT_DEFAULT); +static LCID lcidRussian = MAKELCID(MAKELANGID(LANG_RUSSIAN , SUBLANG_DEFAULT), SORT_DEFAULT); +static BOOL s_bIsVistaPlus; static BOOL IsCJKCodePage(void) { @@ -410,7 +411,10 @@ static void test_cp932(HANDLE hConOut) c.X = c.Y = 0; ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len); ok(ret, "FillConsoleOutputCharacterW failed\n"); - ok(len == csbi.dwSize.X * csbi.dwSize.Y, "len was: %ld\n", len); + if (s_bIsVistaPlus) + ok(len == csbi.dwSize.X * csbi.dwSize.Y / 2, "len was: %ld\n", len); + else + ok(len == csbi.dwSize.X * csbi.dwSize.Y, "len was: %ld\n", len); /* Read characters at (0,0) */ c.X = c.Y = 0; @@ -450,10 +454,20 @@ static void test_cp932(HANDLE hConOut) c.X = c.Y = 0; ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len); ok(ret, "ReadConsoleOutputCharacterW failed\n"); - ok(len == 4, "len was: %ld\n", len); - ok(str[0] == L' ', "str[0] was: 0x%04X\n", str[0]); - ok(str[1] == 0x9580, "str[1] was: 0x%04X\n", str[1]); - ok(str[2] == L' ', "str[2] was: 0x%04X\n", str[2]); + if (s_bIsVistaPlus) + { + ok(len == 3, "len was: %ld\n", len); + ok(str[0] == 0x3000, "str[0] was: 0x%04X\n", str[0]); + ok(str[1] == 0x9580, "str[1] was: 0x%04X\n", str[1]); + ok(str[2] == 0x3000, "str[2] was: 0x%04X\n", str[2]); + } + else + { + ok(len == 4, "len was: %ld\n", len); + ok(str[0] == L' ', "str[0] was: 0x%04X\n", str[0]); + ok(str[1] == 0x9580, "str[1] was: 0x%04X\n", str[1]); + ok(str[2] == L' ', "str[2] was: 0x%04X\n", str[2]); + } } /* Restore code page */ @@ -463,6 +477,11 @@ static void test_cp932(HANDLE hConOut) START_TEST(ConsoleCP) { HANDLE hConIn, hConOut; + OSVERSIONINFOA osver = { sizeof(osver) }; + + GetVersionExA(&osver); + s_bIsVistaPlus = (osver.dwMajorVersion >= 6); + FreeConsole(); ok(AllocConsole(), "Couldn't alloc console\n");
5 years
1
0
0
0
[reactos] 01/01: [WIN32SS][WINSRV] Optimize console background drawing (#2132)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1dcdb4c2d0298ee71822c…
commit 1dcdb4c2d0298ee71822c1d432a30604a82bbd21 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Thu Dec 5 20:19:00 2019 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Thu Dec 5 20:19:00 2019 +0900 [WIN32SS][WINSRV] Optimize console background drawing (#2132) Console needs speed. This PR will optimize drawing of console. - Set NULL to the background brush. - Skip WM_ERASEBKGND. --- win32ss/user/winsrv/consrv/frontends/gui/conwnd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c index 0d81e1d58b5..7676a99c22b 100644 --- a/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c +++ b/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c @@ -149,7 +149,7 @@ RegisterConWndClass(IN HINSTANCE hInstance) WndClass.hIcon = ghDefaultIcon; WndClass.hIconSm = ghDefaultIconSm; WndClass.hCursor = ghDefaultCursor; - WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // The color of a terminal when it is switched off. + WndClass.hbrBackground = NULL; WndClass.lpszMenuName = NULL; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = GWLP_CONWND_ALLOC; @@ -2214,6 +2214,9 @@ ConWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (OnClose(GuiData)) goto Default; break; + case WM_ERASEBKGND: + return TRUE; + case WM_PAINT: OnPaint(GuiData); break;
5 years
1
0
0
0
[reactos] 01/01: [SHELL32] Add 'm_' prefix to CFSFolder members (#2129)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2fad488a85477c08313ae…
commit 2fad488a85477c08313aea66db2025d3f0195ef7 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Thu Dec 5 05:35:25 2019 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Thu Dec 5 05:35:25 2019 +0900 [SHELL32] Add 'm_' prefix to CFSFolder members (#2129) CORE-7585 --- dll/win32/shell32/folders/CFSFolder.cpp | 118 ++++++++++++++++---------------- dll/win32/shell32/folders/CFSFolder.h | 6 +- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/dll/win32/shell32/folders/CFSFolder.cpp b/dll/win32/shell32/folders/CFSFolder.cpp index d0aee2faccf..cfba27e0008 100644 --- a/dll/win32/shell32/folders/CFSFolder.cpp +++ b/dll/win32/shell32/folders/CFSFolder.cpp @@ -437,9 +437,9 @@ HRESULT WINAPI CFileSysEnum::Initialize(LPWSTR lpszPath, DWORD dwFlags) CFSFolder::CFSFolder() { - pclsid = (CLSID *)&CLSID_ShellFSFolder; - sPathTarget = NULL; - pidlRoot = NULL; + m_pclsid = &CLSID_ShellFSFolder; + m_sPathTarget = NULL; + m_pidlRoot = NULL; m_bGroupPolicyActive = 0; } @@ -447,8 +447,8 @@ CFSFolder::~CFSFolder() { TRACE("-- destroying IShellFolder(%p)\n", this); - SHFree(pidlRoot); - SHFree(sPathTarget); + SHFree(m_pidlRoot); + SHFree(m_sPathTarget); } @@ -654,7 +654,7 @@ HRESULT WINAPI CFSFolder::ParseDisplayName(HWND hwndOwner, else { /* build the full pathname to the element */ - lstrcpynW(szPath, sPathTarget, MAX_PATH - 1); + lstrcpynW(szPath, m_sPathTarget, MAX_PATH - 1); PathAddBackslashW(szPath); len = wcslen(szPath); lstrcpynW(szPath + len, szElement, MAX_PATH - len); @@ -702,7 +702,7 @@ HRESULT WINAPI CFSFolder::EnumObjects( DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) { - return ShellObjectCreatorInit<CFileSysEnum>(sPathTarget, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList)); + return ShellObjectCreatorInit<CFileSysEnum>(m_sPathTarget, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList)); } /************************************************************************** @@ -725,7 +725,7 @@ HRESULT WINAPI CFSFolder::BindToObject( CComPtr<IShellFolder> pSF; HRESULT hr; - if (!pidlRoot || !ppvOut || !pidl || !pidl->mkid.cb) + if (!m_pidlRoot || !ppvOut || !pidl || !pidl->mkid.cb) { ERR("CFSFolder::BindToObject: Invalid parameters\n"); return E_INVALIDARG; @@ -747,7 +747,7 @@ HRESULT WINAPI CFSFolder::BindToObject( PERSIST_FOLDER_TARGET_INFO pfti = {0}; pfti.dwAttributes = -1; pfti.csidl = -1; - PathCombineW(pfti.szTargetParsingName, sPathTarget, pDataW->wszName); + PathCombineW(pfti.szTargetParsingName, m_sPathTarget, pDataW->wszName); /* Get the CLSID to bind to */ CLSID clsidFolder; @@ -767,7 +767,7 @@ HRESULT WINAPI CFSFolder::BindToObject( return hr; } - hr = SHELL32_BindToSF(pidlRoot, &pfti, pidl, &clsidFolder, riid, ppvOut); + hr = SHELL32_BindToSF(m_pidlRoot, &pfti, pidl, &clsidFolder, riid, ppvOut); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -876,19 +876,19 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner, if (bIsDropTarget || bIsShellView) { - DWORD dwDirAttributes = _ILGetFileAttributes(ILFindLastID(pidlRoot), NULL, 0); + DWORD dwDirAttributes = _ILGetFileAttributes(ILFindLastID(m_pidlRoot), NULL, 0); if ((dwDirAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) { CLSID clsidFolder; - hr = SHELL32_GetCLSIDForDirectory(sPathTarget, L"UICLSID", &clsidFolder); + hr = SHELL32_GetCLSIDForDirectory(m_sPathTarget, L"UICLSID", &clsidFolder); if (SUCCEEDED(hr)) { CComPtr<IPersistFolder> spFolder; hr = SHCoCreateInstance(NULL, &clsidFolder, NULL, IID_PPV_ARG(IPersistFolder, &spFolder)); if (!FAILED_UNEXPECTEDLY(hr)) { - hr = spFolder->Initialize(pidlRoot); + hr = spFolder->Initialize(m_pidlRoot); if (!FAILED_UNEXPECTEDLY(hr)) { @@ -909,7 +909,7 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner, // No UICLSID handler found, continue to the default handlers if (bIsDropTarget) { - hr = CFSDropTarget_CreateInstance(sPathTarget, riid, ppvOut); + hr = CFSDropTarget_CreateInstance(m_sPathTarget, riid, ppvOut); } else if (IsEqualIID (riid, IID_IContextMenu)) { @@ -920,7 +920,7 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner, DEFCONTEXTMENU dcm; dcm.hwnd = hwndOwner; dcm.pcmcb = this; - dcm.pidlFolder = pidlRoot; + dcm.pidlFolder = m_pidlRoot; dcm.psf = this; dcm.cidl = 0; dcm.apidl = NULL; @@ -968,7 +968,7 @@ HRESULT WINAPI CFSFolder::GetAttributesOf(UINT cidl, if(cidl == 0) { - LPCITEMIDLIST rpidl = ILFindLastID(pidlRoot); + LPCITEMIDLIST rpidl = ILFindLastID(m_pidlRoot); if (_ILIsFolder(rpidl) || _ILIsValue(rpidl)) { @@ -977,7 +977,7 @@ HRESULT WINAPI CFSFolder::GetAttributesOf(UINT cidl, else if (_ILIsDrive(rpidl)) { IShellFolder *psfParent = NULL; - hr = SHBindToParent(pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), NULL); + hr = SHBindToParent(m_pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), NULL); if(SUCCEEDED(hr)) { hr = psfParent->GetAttributesOf(1, &rpidl, (SFGAOF*)rgfInOut); @@ -1064,7 +1064,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, DEFCONTEXTMENU dcm; dcm.hwnd = hwndOwner; dcm.pcmcb = this; - dcm.pidlFolder = pidlRoot; + dcm.pidlFolder = m_pidlRoot; dcm.psf = this; dcm.cidl = cidl; dcm.apidl = apidl; @@ -1077,7 +1077,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, { if (cidl >= 1) { - hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); + hr = IDataObject_Constructor (hwndOwner, m_pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); } else { @@ -1096,7 +1096,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, /* only interested in attempting to bind to shell folders, not files (except exe), so if we fail, rebind to root */ if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj))) { - hr = CFSDropTarget_CreateInstance(sPathTarget, riid, (LPVOID*) &pObj); + hr = CFSDropTarget_CreateInstance(m_sPathTarget, riid, (LPVOID*) &pObj); } } else @@ -1198,9 +1198,9 @@ HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, /* If it is an empty pidl return only the path of the folder */ if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) && (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) && - sPathTarget) + m_sPathTarget) { - return SHSetStrRet(strRet, sPathTarget); + return SHSetStrRet(strRet, m_sPathTarget); } return E_INVALIDARG; } @@ -1212,9 +1212,9 @@ HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) && (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) && - sPathTarget) + m_sPathTarget) { - lstrcpynW(pszPath, sPathTarget, MAX_PATH); + lstrcpynW(pszPath, m_sPathTarget, MAX_PATH); PathAddBackslashW(pszPath); len = wcslen(pszPath); } @@ -1261,11 +1261,11 @@ HRESULT WINAPI CFSFolder::SetNameOf( } /* build source path */ - PathCombineW(szSrc, sPathTarget, pDataW->wszName); + PathCombineW(szSrc, m_sPathTarget, pDataW->wszName); /* build destination path */ if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) - PathCombineW(szDest, sPathTarget, lpName); + PathCombineW(szDest, m_sPathTarget, lpName); else lstrcpynW(szDest, lpName, MAX_PATH); @@ -1415,7 +1415,7 @@ HRESULT WINAPI CFSFolder::GetClassID(CLSID * lpClassId) if (!lpClassId) return E_POINTER; - *lpClassId = *pclsid; + *lpClassId = *m_pclsid; return S_OK; } @@ -1424,7 +1424,7 @@ HRESULT WINAPI CFSFolder::GetClassID(CLSID * lpClassId) * CFSFolder::Initialize * * NOTES - * sPathTarget is not set. Don't know how to handle in a non rooted environment. + * m_sPathTarget is not set. Don't know how to handle in a non rooted environment. */ HRESULT WINAPI CFSFolder::Initialize(PCIDLIST_ABSOLUTE pidl) { @@ -1432,23 +1432,23 @@ HRESULT WINAPI CFSFolder::Initialize(PCIDLIST_ABSOLUTE pidl) TRACE ("(%p)->(%p)\n", this, pidl); - SHFree (pidlRoot); /* free the old pidl */ - pidlRoot = ILClone (pidl); /* set my pidl */ + SHFree(m_pidlRoot); /* free the old pidl */ + m_pidlRoot = ILClone (pidl); /* set my pidl */ - SHFree (sPathTarget); - sPathTarget = NULL; + SHFree (m_sPathTarget); + m_sPathTarget = NULL; /* set my path */ if (SHGetPathFromIDListW (pidl, wszTemp)) { int len = wcslen(wszTemp); - sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); - if (!sPathTarget) + m_sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); + if (!m_sPathTarget) return E_OUTOFMEMORY; - memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); + memcpy(m_sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); } - TRACE ("--(%p)->(%s)\n", this, debugstr_w(sPathTarget)); + TRACE ("--(%p)->(%s)\n", this, debugstr_w(m_sPathTarget)); return S_OK; } @@ -1462,7 +1462,7 @@ HRESULT WINAPI CFSFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl) if (!pidl) return E_POINTER; - *pidl = ILClone(pidlRoot); + *pidl = ILClone(m_pidlRoot); return S_OK; } @@ -1487,15 +1487,15 @@ HRESULT WINAPI CFSFolder::InitializeEx(IBindCtx * pbc, LPCITEMIDLIST pidlRootx, if (ppfti && ppfti->pidlTargetFolder) pdump(ppfti->pidlTargetFolder); - if (pidlRoot) - __SHFreeAndNil(&pidlRoot); /* free the old */ - if (sPathTarget) - __SHFreeAndNil(&sPathTarget); + if (m_pidlRoot) + __SHFreeAndNil(&m_pidlRoot); /* free the old */ + if (m_sPathTarget) + __SHFreeAndNil(&m_sPathTarget); /* * Root path and pidl */ - pidlRoot = ILClone(pidlRootx); + m_pidlRoot = ILClone(pidlRootx); /* * the target folder is spezified in csidl OR pidlTargetFolder OR @@ -1508,19 +1508,19 @@ HRESULT WINAPI CFSFolder::InitializeEx(IBindCtx * pbc, LPCITEMIDLIST pidlRootx, if (SHGetSpecialFolderPathW(0, wszTemp, ppfti->csidl, ppfti->csidl & CSIDL_FLAG_CREATE)) { int len = wcslen(wszTemp); - sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); - if (!sPathTarget) + m_sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); + if (!m_sPathTarget) return E_OUTOFMEMORY; - memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); + memcpy(m_sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); } } else if (ppfti->szTargetParsingName[0]) { int len = wcslen(ppfti->szTargetParsingName); - sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); - if (!sPathTarget) + m_sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); + if (!m_sPathTarget) return E_OUTOFMEMORY; - memcpy(sPathTarget, ppfti->szTargetParsingName, + memcpy(m_sPathTarget, ppfti->szTargetParsingName, (len + 1) * sizeof(WCHAR)); } else if (ppfti->pidlTargetFolder) @@ -1528,17 +1528,17 @@ HRESULT WINAPI CFSFolder::InitializeEx(IBindCtx * pbc, LPCITEMIDLIST pidlRootx, if (SHGetPathFromIDListW(ppfti->pidlTargetFolder, wszTemp)) { int len = wcslen(wszTemp); - sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); - if (!sPathTarget) + m_sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); + if (!m_sPathTarget) return E_OUTOFMEMORY; - memcpy(sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); + memcpy(m_sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR)); } } } - TRACE("--(%p)->(target=%s)\n", this, debugstr_w(sPathTarget)); - pdump(pidlRoot); - return (sPathTarget) ? S_OK : E_FAIL; + TRACE("--(%p)->(target=%s)\n", this, debugstr_w(m_sPathTarget)); + pdump(m_pidlRoot); + return (m_sPathTarget) ? S_OK : E_FAIL; } HRESULT WINAPI CFSFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO * ppfti) @@ -1630,7 +1630,7 @@ HRESULT CFSFolder::_CreateShellExtInstance(const CLSID *pclsid, LPCITEMIDLIST pi return E_INVALIDARG; } - PathCombineW(wszPath, sPathTarget, pDataW->wszName); + PathCombineW(wszPath, m_sPathTarget, pDataW->wszName); CComPtr<IPersistFile> pp; hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IPersistFile, &pp)); @@ -1658,10 +1658,10 @@ HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObjec { if (uMsg == DFM_INVOKECOMMAND && wParam == 0) { - PUITEMID_CHILD pidlChild = ILClone(ILFindLastID(pidlRoot)); - LPITEMIDLIST pidlParent = ILClone(pidlRoot); + PUITEMID_CHILD pidlChild = ILClone(ILFindLastID(m_pidlRoot)); + LPITEMIDLIST pidlParent = ILClone(m_pidlRoot); ILRemoveLastID(pidlParent); - HRESULT hr = SH_ShowPropertiesDialog(sPathTarget, pidlParent, &pidlChild); + HRESULT hr = SH_ShowPropertiesDialog(m_sPathTarget, pidlParent, &pidlChild); if (FAILED(hr)) ERR("SH_ShowPropertiesDialog failed\n"); ILFree(pidlChild); @@ -1731,7 +1731,7 @@ HRESULT WINAPI CFSFolder::GetCustomViewInfo(ULONG unknown, SFVM_CUSTOMVIEWINFO_D WCHAR szPath[MAX_PATH], szIniFile[MAX_PATH]; // does the folder exists? - if (!SHGetPathFromIDListW(pidlRoot, szPath) || !PathIsDirectoryW(szPath)) + if (!SHGetPathFromIDListW(m_pidlRoot, szPath) || !PathIsDirectoryW(szPath)) { return E_INVALIDARG; } diff --git a/dll/win32/shell32/folders/CFSFolder.h b/dll/win32/shell32/folders/CFSFolder.h index 39b5c09ca2b..6c6f055a3f8 100644 --- a/dll/win32/shell32/folders/CFSFolder.h +++ b/dll/win32/shell32/folders/CFSFolder.h @@ -32,12 +32,12 @@ class CFSFolder : public IShellFolderViewCB { private: - CLSID *pclsid; + const CLSID *m_pclsid; /* both paths are parsible from the desktop */ - LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ + LPWSTR m_sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ - LPITEMIDLIST pidlRoot; /* absolute pidl */ + LPITEMIDLIST m_pidlRoot; /* absolute pidl */ DWORD m_bGroupPolicyActive; HRESULT _CreateShellExtInstance(const CLSID *pclsid, LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut);
5 years
1
0
0
0
← Newer
1
...
16
17
18
19
20
21
22
23
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
Results per page:
10
25
50
100
200