Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2018
- 68 participants
- 1149 messages
Re: [PATCH 2/5] mstask: Implement IEnumWorkItems::Next().
by Alexandre Julliard
Dmitry Timoshkov <dmitry(a)baikal.ru> writes:
> + if (is_file(&data))
> + {
> + LPWSTR *new_list;
> +
> + if (!list)
> + new_list = CoTaskMemAlloc((enumerated + 1) * sizeof(list[0]));
> + else
> + new_list = CoTaskMemRealloc(list, (enumerated + 1) * sizeof(list[0]));
It would be better to double the allocated size.
--
Alexandre Julliard
julliard(a)winehq.org
June 11, 2018
[PATCH] ntdll: Implement RtlReleaseRelativeName
by Stefan Leichter
For https://bugs.winehq.org/show_bug.cgi?id=45294
Signed-off-by: Stefan Leichter <sle85276(a)gmx.de>
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/path.c | 8 ++++++++
2 files changed, 9 insertions(+)
June 11, 2018
[PATCH 2/2] user32: Fix returned class name for other processes windows.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/user32/class.c | 18 ++++++++++--------
include/wine/server_protocol.h | 18 +++++++++++++++++-
server/atom.c | 25 +++++++++++++++++++++++++
server/class.c | 5 +++++
server/object.h | 1 +
server/protocol.def | 8 ++++++++
server/request.h | 5 +++++
server/trace.c | 13 +++++++++++++
server/user.h | 1 +
server/window.c | 17 +++++++++++++++++
10 files changed, 102 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index 2b2d07f888..69dc4477ca 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -1183,7 +1183,7 @@ INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
{
CLASS *class;
- INT ret;
+ INT ret = 0;
TRACE("%p %p %d\n", hwnd, buffer, count);
@@ -1193,15 +1193,17 @@ INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
if (class == CLASS_OTHER_PROCESS)
{
- WCHAR tmpbuf[MAX_ATOM_LEN + 1];
-
- ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), tmpbuf, MAX_ATOM_LEN + 1 );
- if (ret)
+ SERVER_START_REQ( get_class_name )
{
- ret = min(count - 1, ret);
- memcpy(buffer, tmpbuf, ret * sizeof(WCHAR));
- buffer[ret] = 0;
+ req->handle = wine_server_user_handle( hwnd );
+ wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
+ if (!wine_server_call_err( req ))
+ {
+ ret = wine_server_reply_size( reply );
+ buffer[ret / sizeof(WCHAR)] = 0;
+ }
}
+ SERVER_END_REQ;
}
else
{
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 5358af20b8..879d361ab2 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -3503,6 +3503,19 @@ struct set_window_owner_reply
+struct get_class_name_request
+{
+ struct request_header __header;
+ user_handle_t handle;
+};
+struct get_class_name_reply
+{
+ struct reply_header __header;
+ /* VARARG(name,unicode_str); */
+};
+
+
+
struct get_window_info_request
{
struct request_header __header;
@@ -5793,6 +5806,7 @@ enum request
REQ_destroy_window,
REQ_get_desktop_window,
REQ_set_window_owner,
+ REQ_get_class_name,
REQ_get_window_info,
REQ_set_window_info,
REQ_set_parent,
@@ -6089,6 +6103,7 @@ union generic_request
struct destroy_window_request destroy_window_request;
struct get_desktop_window_request get_desktop_window_request;
struct set_window_owner_request set_window_owner_request;
+ struct get_class_name_request get_class_name_request;
struct get_window_info_request get_window_info_request;
struct set_window_info_request set_window_info_request;
struct set_parent_request set_parent_request;
@@ -6383,6 +6398,7 @@ union generic_reply
struct destroy_window_reply destroy_window_reply;
struct get_desktop_window_reply get_desktop_window_reply;
struct set_window_owner_reply set_window_owner_reply;
+ struct get_class_name_reply get_class_name_reply;
struct get_window_info_reply get_window_info_reply;
struct set_window_info_reply set_window_info_reply;
struct set_parent_reply set_parent_reply;
@@ -6512,6 +6528,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
-#define SERVER_PROTOCOL_VERSION 554
+#define SERVER_PROTOCOL_VERSION 555
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/atom.c b/server/atom.c
index 3ff75407d9..7e79195973 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -381,6 +381,31 @@ void release_global_atom( struct winstation *winstation, atom_t atom )
}
}
+/* get atom name */
+int get_atom_string( atom_t atom, WCHAR *name, unsigned short len )
+{
+ struct atom_table *table = get_table( 0, 0 );
+ int ret = 0;
+
+ *name = 0;
+
+ if (table)
+ {
+ struct atom_entry *entry;
+
+ if ((entry = get_atom_entry( table, atom )))
+ {
+ ret = len = min(len, entry->len);
+ memcpy(name, entry->str, len);
+ name[len / sizeof(WCHAR)] = 0;
+ }
+
+ release_object( table );
+ }
+
+ return ret;
+}
+
/* add a global atom */
DECL_HANDLER(add_atom)
{
diff --git a/server/class.c b/server/class.c
index d5f6712006..4bb3aa1aad 100644
--- a/server/class.c
+++ b/server/class.c
@@ -142,6 +142,11 @@ atom_t get_class_atom( struct window_class *class )
return class->atom;
}
+atom_t get_base_class_atom( struct window_class *class )
+{
+ return class->base_atom;
+}
+
client_ptr_t get_class_client_ptr( struct window_class *class )
{
return class->client_ptr;
diff --git a/server/object.h b/server/object.h
index b5c50e1cee..4c8d1a58fd 100644
--- a/server/object.h
+++ b/server/object.h
@@ -224,6 +224,7 @@ extern atom_t add_global_atom( struct winstation *winstation, const struct unico
extern atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str );
extern int grab_global_atom( struct winstation *winstation, atom_t atom );
extern void release_global_atom( struct winstation *winstation, atom_t atom );
+extern int get_atom_string( atom_t atom, WCHAR *name, unsigned short len );
/* directory functions */
diff --git a/server/protocol.def b/server/protocol.def
index 032b03822b..9027312f46 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2515,6 +2515,14 @@ enum message_type
@END
+/* Get window class name */
+(a)REQ(get_class_name)
+ user_handle_t handle; /* handle to the window */
+(a)REPLY
+ VARARG(name,unicode_str); /* class name */
+(a)END
+
+
/* Get information from a window handle */
@REQ(get_window_info)
user_handle_t handle; /* handle to the window */
diff --git a/server/request.h b/server/request.h
index 9cf81a1f09..a693e2cf62 100644
--- a/server/request.h
+++ b/server/request.h
@@ -274,6 +274,7 @@ DECL_HANDLER(create_window);
DECL_HANDLER(destroy_window);
DECL_HANDLER(get_desktop_window);
DECL_HANDLER(set_window_owner);
+DECL_HANDLER(get_class_name);
DECL_HANDLER(get_window_info);
DECL_HANDLER(set_window_info);
DECL_HANDLER(set_parent);
@@ -569,6 +570,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_destroy_window,
(req_handler)req_get_desktop_window,
(req_handler)req_set_window_owner,
+ (req_handler)req_get_class_name,
(req_handler)req_get_window_info,
(req_handler)req_set_window_info,
(req_handler)req_set_parent,
@@ -1685,6 +1687,9 @@ C_ASSERT( sizeof(struct set_window_owner_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_window_owner_reply, full_owner) == 8 );
C_ASSERT( FIELD_OFFSET(struct set_window_owner_reply, prev_owner) == 12 );
C_ASSERT( sizeof(struct set_window_owner_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_class_name_request, handle) == 12 );
+C_ASSERT( sizeof(struct get_class_name_request) == 16 );
+C_ASSERT( sizeof(struct get_class_name_reply) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_request, handle) == 12 );
C_ASSERT( sizeof(struct get_window_info_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, full_handle) == 8 );
diff --git a/server/trace.c b/server/trace.c
index 999532a425..6b38896f4c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3082,6 +3082,16 @@ static void dump_set_window_owner_reply( const struct set_window_owner_reply *re
fprintf( stderr, ", prev_owner=%08x", req->prev_owner );
}
+static void dump_get_class_name_request( const struct get_class_name_request *req )
+{
+ fprintf( stderr, " handle=%08x", req->handle );
+}
+
+static void dump_get_class_name_reply( const struct get_class_name_reply *req )
+{
+ dump_varargs_unicode_str( " name=", cur_size );
+}
+
static void dump_get_window_info_request( const struct get_window_info_request *req )
{
fprintf( stderr, " handle=%08x", req->handle );
@@ -4693,6 +4703,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_destroy_window_request,
(dump_func)dump_get_desktop_window_request,
(dump_func)dump_set_window_owner_request,
+ (dump_func)dump_get_class_name_request,
(dump_func)dump_get_window_info_request,
(dump_func)dump_set_window_info_request,
(dump_func)dump_set_parent_request,
@@ -4985,6 +4996,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
(dump_func)dump_get_desktop_window_reply,
(dump_func)dump_set_window_owner_reply,
+ (dump_func)dump_get_class_name_reply,
(dump_func)dump_get_window_info_reply,
(dump_func)dump_set_window_info_reply,
(dump_func)dump_set_parent_reply,
@@ -5277,6 +5289,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"destroy_window",
"get_desktop_window",
"set_window_owner",
+ "get_class_name",
"get_window_info",
"set_window_info",
"set_parent",
diff --git a/server/user.h b/server/user.h
index e7eecd4c6a..11db294fbb 100644
--- a/server/user.h
+++ b/server/user.h
@@ -175,6 +175,7 @@ extern void release_class( struct window_class *class );
extern int is_desktop_class( struct window_class *class );
extern int is_hwnd_message_class( struct window_class *class );
extern atom_t get_class_atom( struct window_class *class );
+extern atom_t get_base_class_atom( struct window_class *class );
extern client_ptr_t get_class_client_ptr( struct window_class *class );
/* windows station functions */
diff --git a/server/window.c b/server/window.c
index 70812095d2..2223d38aeb 100644
--- a/server/window.c
+++ b/server/window.c
@@ -2049,6 +2049,23 @@ DECL_HANDLER(set_window_owner)
}
+/* get class name for a window handle */
+DECL_HANDLER(get_class_name)
+{
+ struct window *win = get_window( req->handle );
+ WCHAR name[256];
+ atom_t atom;
+ int len;
+
+ if (!win) return;
+
+ atom = win->class ? get_base_class_atom( win->class ) : DESKTOP_ATOM;
+ len = get_atom_string(atom, name, 256);
+
+ set_reply_data( name, min( len, get_reply_max_size() ));
+}
+
+
/* get information from a window handle */
DECL_HANDLER(get_window_info)
{
--
2.17.1
June 11, 2018
[PATCH 1/2] server: Use additional atom to keep base class name.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/user32/class.c | 1 +
include/wine/server_protocol.h | 4 +++-
server/class.c | 27 +++++++++++++++++++++++++--
server/protocol.def | 2 ++
server/request.h | 14 ++++++++------
server/trace.c | 2 ++
6 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c
index ce2830fe25..2b2d07f888 100644
--- a/dlls/user32/class.c
+++ b/dlls/user32/class.c
@@ -487,6 +487,7 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE
req->win_extra = winExtra;
req->client_ptr = wine_server_client_ptr( classPtr );
req->atom = classPtr->atomName;
+ req->name_offset = basename_offset;
if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) );
ret = !wine_server_call_err( req );
classPtr->atomName = reply->atom;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 98dbcb7e61..5358af20b8 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4475,6 +4475,8 @@ struct create_class_request
struct request_header __header;
int local;
atom_t atom;
+ int name_offset;
+ int _pad;
unsigned int style;
mod_handle_t instance;
int extra;
@@ -6510,6 +6512,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
-#define SERVER_PROTOCOL_VERSION 553
+#define SERVER_PROTOCOL_VERSION 554
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/class.c b/server/class.c
index cc6e52d9b1..d5f6712006 100644
--- a/server/class.c
+++ b/server/class.c
@@ -46,6 +46,7 @@ struct window_class
int count; /* reference count */
int local; /* local class? */
atom_t atom; /* class atom */
+ atom_t base_atom; /* base class atom for versioned class */
mod_handle_t instance; /* module instance */
unsigned int style; /* class style */
int win_extra; /* number of window extra bytes */
@@ -151,17 +152,35 @@ DECL_HANDLER(create_class)
{
struct window_class *class;
struct unicode_str name = get_req_unicode_str();
- atom_t atom;
+ atom_t atom, base_atom;
if (name.len)
{
atom = add_global_atom( NULL, &name );
if (!atom) return;
+ if (req->name_offset && req->name_offset < name.len / sizeof(WCHAR))
+ {
+ name.str += req->name_offset;
+ name.len -= req->name_offset * sizeof(WCHAR);
+
+ base_atom = add_global_atom( NULL, &name );
+ if (!base_atom)
+ {
+ release_global_atom( NULL, atom );
+ return;
+ }
+ }
+ else
+ {
+ base_atom = atom;
+ grab_global_atom( NULL, atom );
+ }
}
else
{
- atom = req->atom;
+ base_atom = atom = req->atom;
if (!grab_global_atom( NULL, atom )) return;
+ grab_global_atom( NULL, base_atom );
}
class = find_class( current->process, atom, req->instance );
@@ -169,6 +188,7 @@ DECL_HANDLER(create_class)
{
set_win32_error( ERROR_CLASS_ALREADY_EXISTS );
release_global_atom( NULL, atom );
+ release_global_atom( NULL, base_atom );
return;
}
if (req->extra < 0 || req->extra > 4096 || req->win_extra < 0 || req->win_extra > 4096)
@@ -176,15 +196,18 @@ DECL_HANDLER(create_class)
/* don't allow stupid values here */
set_error( STATUS_INVALID_PARAMETER );
release_global_atom( NULL, atom );
+ release_global_atom( NULL, base_atom );
return;
}
if (!(class = create_class( current->process, req->extra, req->local )))
{
release_global_atom( NULL, atom );
+ release_global_atom( NULL, base_atom );
return;
}
class->atom = atom;
+ class->base_atom = base_atom;
class->instance = req->instance;
class->style = req->style;
class->win_extra = req->win_extra;
diff --git a/server/protocol.def b/server/protocol.def
index 99e7221c4b..032b03822b 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3144,6 +3144,8 @@ enum caret_state
@REQ(create_class)
int local; /* is it a local class? */
atom_t atom; /* class atom */
+ int name_offset; /* base class name offset for specified atom */
+ int _pad;
unsigned int style; /* class style */
mod_handle_t instance; /* module instance */
int extra; /* number of extra class bytes */
diff --git a/server/request.h b/server/request.h
index 2d55dfbd98..9cf81a1f09 100644
--- a/server/request.h
+++ b/server/request.h
@@ -2031,12 +2031,14 @@ C_ASSERT( FIELD_OFFSET(struct get_hook_info_reply, unicode) == 32 );
C_ASSERT( sizeof(struct get_hook_info_reply) == 40 );
C_ASSERT( FIELD_OFFSET(struct create_class_request, local) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_class_request, atom) == 16 );
-C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 20 );
-C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 24 );
-C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 32 );
-C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 36 );
-C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 40 );
-C_ASSERT( sizeof(struct create_class_request) == 48 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, name_offset) == 20 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, _pad) == 24 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, style) == 28 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 32 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 40 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 44 );
+C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 48 );
+C_ASSERT( sizeof(struct create_class_request) == 56 );
C_ASSERT( FIELD_OFFSET(struct create_class_reply, atom) == 8 );
C_ASSERT( sizeof(struct create_class_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct destroy_class_request, atom) == 12 );
diff --git a/server/trace.c b/server/trace.c
index e2980a3e31..999532a425 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3753,6 +3753,8 @@ static void dump_create_class_request( const struct create_class_request *req )
{
fprintf( stderr, " local=%d", req->local );
fprintf( stderr, ", atom=%04x", req->atom );
+ fprintf( stderr, ", name_offset=%d", req->name_offset );
+ fprintf( stderr, ", _pad=%d", req->_pad );
fprintf( stderr, ", style=%08x", req->style );
dump_uint64( ", instance=", &req->instance );
fprintf( stderr, ", extra=%d", req->extra );
--
2.17.1
June 11, 2018
Re: [PATCH] winhttp: Store the server certificate context in the request.
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39055
Your paranoid android.
=== w2003std (32 bit winhttp) ===
winhttp.c:3908: Test failed: got 80072f0d
=== wvistau64_zh_CN (32 bit winhttp) ===
winhttp.c:3104: Test failed: failed to receive response 12152
winhttp.c:3109: Test failed: failed to query status code 12019
winhttp.c:3110: Test failed: request failed unexpectedly 3735928559
June 11, 2018
[PATCH] winhttp: Store the server certificate context in the request.
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/winhttp/net.c | 1 -
dlls/winhttp/request.c | 11 +++++++++++
dlls/winhttp/session.c | 14 ++++++--------
dlls/winhttp/tests/winhttp.c | 5 +++++
dlls/winhttp/winhttp_private.h | 2 ++
5 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c
index d0d02d535e..d577a64783 100644
--- a/dlls/winhttp/net.c
+++ b/dlls/winhttp/net.c
@@ -47,7 +47,6 @@
#include "windef.h"
#include "winbase.h"
#include "winhttp.h"
-#include "wincrypt.h"
#include "schannel.h"
#include "winhttp_private.h"
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 96a2c91de5..56ec910294 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1765,6 +1765,10 @@ static BOOL open_connection( request_t *request )
return FALSE;
}
}
+
+ CertFreeCertificateContext( request->server_cert );
+ request->server_cert = NULL;
+
if (!ensure_cred_handle( connect->session ) ||
!netconn_secure_connect( netconn, connect->hostname, request->security_flags,
&connect->session->cred_handle ))
@@ -1787,6 +1791,13 @@ static BOOL open_connection( request_t *request )
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;
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index e2b91fa513..fb815682c2 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -40,7 +40,6 @@
#include "winsock2.h"
#include "ws2ipdef.h"
#include "winhttp.h"
-#include "wincrypt.h"
#include "winreg.h"
#define COBJMACROS
#include "ole2.h"
@@ -597,6 +596,8 @@ static void request_destroy( object_header_t *hdr )
}
release_object( &request->connect->hdr );
+ CertFreeCertificateContext( request->server_cert );
+
destroy_authinfo( request->authinfo );
destroy_authinfo( request->proxy_authinfo );
@@ -759,14 +760,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
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;
@@ -778,16 +779,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
set_last_error( 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
@@ -795,7 +794,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;
}
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 4d8585be1a..2c22276899 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -1107,6 +1107,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);
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 0eb0dead87..d639a2deb2 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -46,6 +46,7 @@
#include "ole2.h"
#include "sspi.h"
+#include "wincrypt.h"
static const WCHAR getW[] = {'G','E','T',0};
static const WCHAR postW[] = {'P','O','S','T',0};
@@ -209,6 +210,7 @@ typedef struct
DWORD optional_len;
netconn_t *netconn;
DWORD security_flags;
+ const CERT_CONTEXT *server_cert;
int resolve_timeout;
int connect_timeout;
int send_timeout;
--
2.11.0
June 11, 2018
Re: [PATCH] webservices/tests: Use the available ARRAY_SIZE() macro
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
June 11, 2018
wine-3.0.2-rc1 Available
by Michael Stefaniuc
Hello guys,
I have pushed wine-3.0.2-rc1 (with tag) to
https://github.com/mstefani/wine-stable/tree/oldstable
http://static-winehq.193b.starter-ca-central-1.openshiftapps.com/stable/
Nothing fancy this time. The bulk of the changes is stuff from wine-3.5
to wine-3.7 with some older stuff that got deferred during 3.0.1.
The interesting parts from the ANNOUNCE file:
What's new in this release (see below for details):
- Various bug fixes
----------------------------------------------------------------
Bugs fixed in 3.0.2 (total 54):
13351 Empire Earth v. 1.00: mouse is not responsive
15350 wrong keyboard layout in Tomb Raider Anniversary / Legend
29842 IE4 crashes on showing certificate authorities, needs
wininet.dll.ParseX509EncodedCertificateForListBoxEntry
29999 Bloodrayne 2: text in the menus misplaced
30076 .NET Framework 4.x with WinVer setting "Windows 7" spams
terminal with "LocaleNameToLCID/LCIDToLocaleName unsupported flags
8000000" (LOCALE_ALLOW_NEUTRAL_NAMES)
30103 Static controls with bitmap do not display correct background.
30611 Lazarus browser sample fails, needs ieframe:ViewObject_Draw
implementation
31850 Age of Mythology needs pidgen.dll.PIDGenSimpA
34101 Need for Speed: Shift demo crashes in 'purist' mode (d3dx9_36)
(needs ID3DXEffect::FindNextValidTechnique method implementation)
36843 "Read only"checkbox on Save As dialog
37228 Cisco Jabber 11.x crashes on unimplemented function
ntdsapi.dll.DsCrackNamesW
37594 World of Warcraft in-game browser does not work (needs
advapi32.BuildSecurityDescriptorW() implementation)
38564 Rush for Berlin Gold crashes after starting
38836 SCM 'StartService' must wait for driver service entry point
execution before return (PunkBuster 'PnkBstrB' service failure, CPU-Z
randomly fails to load its driver, BattlEye 'BEDaisy' kernel service)
39209 Smart Diary Suite 4 crashes when updating options
('CLSID_AudioCompressorCategory',
'{33D9A761-90C8-11d0-BD43-00A0C911CE86}' must be treated as special
category)
39452 mpr.WNetGetUniversalName() return value (causes Intel MPI to fail)
39979 SupArc crashes inside msvcr110
40767 Indiana Jones and The Emperor's Tomb quits after the splash screen
41377 Windows 10 DISM fails to find its resources (kernel32
SetThreadUILanguage must return non-zero/best fit language identifier if
zero is passed)
42267 Rogue-Killer installer crashes on unimplemented function
ntdll.dll._aulldvrm
42446 Native Instruments 'Native Access' 1.1.x fails to start,
reports 'You cannot start Native Access from the mounted disk'
42686 Poedit crashes on start on unimplemented function
msvcp140.dll.?_IsNonBlockingThread(a)_Task_impl_base@details(a)Concurrency@@SA_NXZ
42768 Ys: The Ark of Napishtim (Ys 6) silently crashes playing
in-game videos
43351 x64dbg needs kernel32.dll CreateRemoteThreadEx in Win7+ mode
43831 Cuphead (Steam) crashes on startup (needs
setupapi.CM_Get_Parent stub to return CR_NO_SUCH_DEVNODE)
43930 iCopy 1.6.x (.NET 2.0 app) crashes on startup
(IWiaDevMgr::SelectDeviceDlg DeviceID pointer parameter can be NULL,
needs be declared 'unique' for RPC marshalling)
44135 Olive Tree Bible Software BibleStudySetup_6.0.23.exe fails to
install
44138 Native Access needs unimplemented function
iphlpapi.dll.if_indextoname
44278 Multiple applications crash on unimplemented function
msvcp140.dll.?uncaught_exceptions(a)std@@YAHXZ
44404 Several .Net apps (e.g. Remembear) throw errors/crash,caused by
msctf stubs TextStoreACPSink_{OnTextChange,OnSelectionChange,OnLayoutChange}
44466 PrtSc button crashes StarCraft
44496 Custom imports resolver used by multiple kernel drivers can't
cope with 'ntoskrnl.exe' low-level (wc)string/copy helpers being
forwarded to 'msvcrt.dll' (BattlEye 'BEDaisy', Sentinel HASP 'hardlock.sys')
44504 vlc 2.2.6: playback performance hampered
44530 64-bit Sentinel HASP hardlock.sys kernel driver tries to access
to DR7 (not handled in ntoskrnl emulate_instruction)
44693 Native Access crashes on unimplemented function
vcruntime140.dll.__current_exception
44742 Divinity: Original Sin 2 crashes due to unimplemented
IPHLPAPI.DLL.ConvertLengthToIpv4Mask
44744 Autodesk Fusion 360 need propsys.dll.PSGetPropertyKeyFromName
to be installed
44746 Running any command in MS PowerShell 6+ (.NET app) results in
advapi:EventActivityIdControl console spam
44770 ExpressPCB Plus 1.1 (.NET 3.5 SP1 app) throws
'System.NotImplementedException: Not implemented at
System.Drawing.Pen.TranslateTransform' (GdipTranslatePenTransform not
implemented)
44772 progecad 2018 installer does not start
44804 PCBWeb crashes: Call to unimplemented function
d3dx11_43.dll.D3DX11CreateTextureFromFileW
44811 BattlEye 'BEDaisy' kernel service crashes on unimplemented
function ntoskrnl.exe._chkstk
44818 ntdll.NtClose (kernel32.CloseHandle) should throw invalid
handle exception (EXCEPTION_INVALID_HANDLE) for invalid handles when run
under debugger
44864 Incoming crashes after the intro video
44874 Phonetools 9.x crashes on unimplemented function
KERNEL32.dll.RequestDeviceWakeup
44904 winebus blocks auto start up of scheduler service
44923 Failing kernel driver services can stall WINEPREFIX
bootstrapping/startup for a considerable time when configured as autostart
44924 StarForce v3 kernel drivers need
ntoskrnl.IoCreateSynchronizationEvent to return a non-NULL handle
44932 limited list of available printer's paper/page size
44944 Adobe Premiere Elements 14 fails to install: ERROR: Third party
payload installer pxengine5_08_13a.exe failed with exit code: -1
44971 HackShield for Banking Driver 'HSBDrvNt.sys' (part of Ahnlab
Safe Transaction) crashes on unimplemented function
ntoskrnl.exe.ExInterlockedPopEntrySList
44984 Maya 2018 LT Installer requires unimplemented function
api-ms-win-crt-time-l1-1-0.dll._timespec64_get
44993 Magic The Gathering Arena fails to install
45026 Windows File Manager (WinFile) fails to build in winelib
(LPDROPSTRUCT missing from winuser.h)
----------------------------------------------------------------
Changes since 3.0.1:
Alexander Morozov (1):
ntoskrnl.exe: Add stubs for ExAcquireFastMutexUnsafe and
ExReleaseFastMutexUnsafe.
Alexandre Julliard (7):
winex11: Use the correct colormap for the OpenGL parent window.
winex11: Store the visual info in the OpenGL pixel format.
winex11: Store only the pixmap size instead of the window
rectangle in the GL drawable.
winex11: Implement refcounting of GL drawables.
winex11: Hold a reference to the drawable from the GL context.
wininet/tests: Update the winehq.org certificate data.
ntoskrnl: Add emulation of CRn and DRn registers on x86-64.
Alistair Leslie-Hughes (9):
comctl32/treeview: Fix item icon background when using
TVS_FULLROWSELECT style.
pidgen: Add PIDGenSimpA stub.
winedevice: Wait until driver has started before returning.
ntoskrnl.exe: Dont forward some msvcrt functions.
propsys: Add PSGetPropertyKeyFromName stub.
ntoskrnl.exe: Implement _chkstk.
winedevice: Improve error handling when a driver fails to load.
maintainers: Update Staging branch.
maintainers: Remove previous wine-staging maintainers.
Andrew Eikum (1):
maintainers: Remove myself from a dmusic DLL.
Andrew Wesie (1):
advapi32: Implement BuildSecurityDescriptorW.
Andrey Gusev (1):
d3dx11: Add D3DX11CreateTextureFromFileA/W stub.
André Hentschel (3):
wininet: Fix negated check for drain_content result (clang).
gdiplus: Add stub for GdipSetPathGradientPath.
progman: Fix warning in PUT_SHORT macro (clang).
Austin English (4):
wininet: Add ParseX509EncodedCertificateForListBoxEntry stub.
ntdsapi: Add DsCrackNamesA/W stubs.
include/winuser.h: Add tagDROPSTRUCT struct.
include/wfext.h: Add miscellaneous FM_* defines.
Christian Inci (1):
wined3d: Recognize Titan V.
Dagfinn Reiakvam (1):
iphlpapi: Add support for ConvertLengthToIpv4Mask().
Dmitry Timoshkov (5):
avifil32: Correct threading model on interfaces.
services: Add a 3000 ms timeout to StartService.
winspool.drv: Add A0, A1 and A2 paper sizes to generic.ppd.
dinput: The DIK_ key code should match the scan code.
sspicli: Add forwards to secur32.
Gijs Vermeulen (1):
ntoskrnl.exe: Improve IoCreateSynchronizationEvent stub.
Hans Leidekker (2):
iphlpapi: Implement if_indextoname.
msi: Don't cache the base URL.
Henri Verbeet (1):
winex11: Restore the X11DRV_FLUSH_GL_DRAWABLE XFlush() for setups
without OML_sync_control.
Huw D. M. Davies (1):
winebuild: On x86_64, save xmm0 - 3 during the delayed import lookup.
Ivan Kalvachev (1):
kernel32: Add DECL_HOTPATCH to OutputDebugString functions.
Jarkko Korpi (1):
kernel32: Silence repeated LocaleNameToLCID unsupported flags.
Johann Frei (1):
dinput: Implement X/Y axis granularity and add test.
Louis Lenders (9):
ntdll: Update version resource.
kernel32/tests: Add simple test for SetThreadUILanguage.
kernel32: Improve stub for SetThreadUILanguage.
iexplore/iexplore.inf: Add svcVersion reg key and update to win7.
msctf: Return S_OK in TextStoreACPSink_OnTextChange.
msctf: Return S_OK in TextStoreACPSink_OnSelectionChange.
msctf: Return S_OK in TextStoreACPSink_OnLayoutChange.
wine.inf: Create catroot directory.
kernel32: Add stub for RequestDeviceWakeup.
Mark White (1):
kernel32: Fix forward slash path handling to GetVolumePathNameW.
Martin Storsjo (1):
ucrtbase: Hook up __intrinsic_setjmpex for x86_64 and arm64.
Matteo Bruni (2):
d3dx9: Implement FindNextValidTechnique().
d3d8: Forbid setting a viewport larger than the render target.
Michael Müller (3):
ieframe: Return S_OK in IViewObject::Draw stub.
mpr: Return correct error code for non network paths and
REMOTE_NAME_INFO_LEVEL in WNetGetUniversalName.
ntoskrnl: Implement ExInterlockedPopEntrySList.
Michael Stefaniuc (1):
maintainers: Add a DirectMusic section.
Nikolay Sivov (7):
comdlg32: Add a helper to test if file dialog hook is enabled.
comdlg32: Hide Read-only checkbox for Save dialogs.
gdiplus: Implement GdipTranslatePenTransform.
wincodecs: Use static array for property bag descriptions.
wincodecs: Encoder options are optional for CreateNewFrame().
user32/static: Use correct brush color for centered image background.
kernel32: Add CreateRemoteThreadEx().
Piotr Caban (6):
msvcrt: Optimize _strupr implementation in C locale.
msvcrt/tests: Add _strupr tests.
msvcp140: Add __uncaught_exceptions implementation.
ucrtbase: Add __current_exception() implementation.
msvcp140: Add _Task_impl_base::_IsNonBlockingThread stub.
ucrtbase: Add _timespec{32,64}_get implementation.
Sebastian Lackner (2):
ntdll: Throw exception if invalid handle is passed to NtClose and
debugger enabled.
advapi32/tests: Add basic tests for BuildSecurityDescriptor.
Stefan Dösinger (1):
ddraw: Don't read past the end of the executebuffer.
Stefan Leichter (2):
advapi32: Silence the fixme in EventActivityIdControl.
include: Fix declaration of SelectDeviceDlg.
Tim Wanders (1):
setupapi: Return CR_NO_SUCH_DEVNODE from CM_Get_Parent stub.
Zebediah Figura (5):
ntdll: Implement _alldvrm() and _aulldvrm().
devenum/tests: Test registering DirectShow filters.
devenum: More correctly handle device types.
devenum: Allow parsing display name without class ID.
devenum: Correctly implement IMoniker::GetDisplayName().
--
Michael Stefaniuc
mstefani(a)winehq.org
June 10, 2018
[PATCH] find: First simple implementation and tests
by Fabian Maurer
The message text is the same as on windows,
since the exit code doesn't seem reliable.
Currently only supports single line searching,
and not unicode aware. I'll add tests and if needed an implementation
for that sometime later.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
configure | 25 ++----
configure.ac | 1 +
programs/find/Makefile.in | 5 +-
programs/find/find.c | 112 +++++++++++++++++++++--
programs/find/resources.h | 27 ++++++
programs/find/rsrc.rc | 25 ++++++
programs/find/tests/Makefile.in | 4 +
programs/find/tests/find.c | 151 ++++++++++++++++++++++++++++++++
8 files changed, 326 insertions(+), 24 deletions(-)
create mode 100644 programs/find/resources.h
create mode 100644 programs/find/rsrc.rc
create mode 100644 programs/find/tests/Makefile.in
create mode 100644 programs/find/tests/find.c
diff --git a/configure b/configure
index 299fb407d8..56e7dde04c 100755
--- a/configure
+++ b/configure
@@ -800,7 +800,6 @@ infodir
docdir
oldincludedir
includedir
-runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -1862,7 +1861,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -2115,15 +2113,6 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
- -runstatedir | --runstatedir | --runstatedi | --runstated \
- | --runstate | --runstat | --runsta | --runst | --runs \
- | --run | --ru | --r)
- ac_prev=runstatedir ;;
- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
- | --run=* | --ru=* | --r=*)
- runstatedir=$ac_optarg ;;
-
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -2261,7 +2250,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir runstatedir
+ libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -2414,7 +2403,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -6626,7 +6614,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@@ -6672,7 +6660,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@@ -6696,7 +6684,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@@ -6741,7 +6729,7 @@ else
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@@ -6765,7 +6753,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
@@ -19379,6 +19367,7 @@ wine_fn_config_makefile programs/explorer enable_explorer
wine_fn_config_makefile programs/extrac32 enable_extrac32
wine_fn_config_makefile programs/fc enable_fc
wine_fn_config_makefile programs/find enable_find
+wine_fn_config_makefile programs/find/tests enable_tests
wine_fn_config_makefile programs/findstr enable_findstr
wine_fn_config_makefile programs/fsutil enable_fsutil
wine_fn_config_makefile programs/hh enable_hh
diff --git a/configure.ac b/configure.ac
index 469fa8d729..1d6a4cf1c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3878,6 +3878,7 @@ WINE_CONFIG_MAKEFILE(programs/explorer)
WINE_CONFIG_MAKEFILE(programs/extrac32)
WINE_CONFIG_MAKEFILE(programs/fc)
WINE_CONFIG_MAKEFILE(programs/find)
+WINE_CONFIG_MAKEFILE(programs/find/tests)
WINE_CONFIG_MAKEFILE(programs/findstr)
WINE_CONFIG_MAKEFILE(programs/fsutil)
WINE_CONFIG_MAKEFILE(programs/hh)
diff --git a/programs/find/Makefile.in b/programs/find/Makefile.in
index ef8d61b7ce..4a90905986 100644
--- a/programs/find/Makefile.in
+++ b/programs/find/Makefile.in
@@ -1,4 +1,7 @@
MODULE = find.exe
-APPMODE = -mconsole -municode
+APPMODE = -mconsole
+IMPORTS = user32 shlwapi
C_SRCS = find.c
+
+RC_SRCS = rsrc.rc
diff --git a/programs/find/find.c b/programs/find/find.c
index 9d7aecd402..937f773243 100644
--- a/programs/find/find.c
+++ b/programs/find/find.c
@@ -16,18 +16,120 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <windows.h>
+#include <stdlib.h>
+#include <shlwapi.h>
+
+#include "wine/heap.h"
#include "wine/debug.h"
+#include "resources.h"
WINE_DEFAULT_DEBUG_CHANNEL(find);
-int wmain(int argc, WCHAR *argv[])
+char* read_from_pipe(HANDLE handle)
+{
+ char buffer[4096];
+ DWORD bytes_read;
+ DWORD length = 0;
+ BOOL success;
+ char *ret = heap_alloc_zero(1);
+
+ for (;;)
+ {
+ success = ReadFile(handle, buffer, sizeof(buffer), &bytes_read, NULL);
+ if (!success || !bytes_read)
+ break;
+ ret = heap_realloc(ret, length + bytes_read);
+ memcpy((char *)ret + length, buffer, bytes_read);
+ length += bytes_read;
+ }
+
+ ret[length] = 0;
+ return ret;
+}
+
+void write_to_pipe(HANDLE handle, const char *str)
+{
+ DWORD bytes_written_sum = 0;
+ DWORD length = lstrlenA(str);
+ do
+ {
+ DWORD bytes_written;
+ WriteFile(handle, str, length * sizeof(char), &bytes_written, NULL);
+ bytes_written_sum += bytes_written;
+ } while (bytes_written_sum < length);
+}
+
+void find_printf(const char *str)
+{
+ write_to_pipe(GetStdHandle(STD_OUTPUT_HANDLE), str);
+}
+
+int do_find(const char *text, const char* tofind)
{
+ void *found;
+
+ if (lstrlenA(text) == 0)
+ return 1;
+
+ found = StrStrA(text, tofind);
+
+ if (found)
+ {
+ find_printf(text);
+ find_printf("\r\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ char *text_stdin;
+ char *tofind = NULL;
+ char message_parameter_invalid[64];
+ char message_switch_invalid[64];
int i;
+ int exitcode;
- WINE_FIXME("stub:");
+ TRACE("running find:");
for (i = 0; i < argc; i++)
- WINE_FIXME(" %s", wine_dbgstr_w(argv[i]));
- WINE_FIXME("\n");
+ {
+ TRACE(" %s", argv[i]);
+ }
+ TRACE("\n");
+
+ LoadStringA(GetModuleHandleW(NULL), IDS_INVALID_PARAMETER, message_parameter_invalid, sizeof(message_parameter_invalid));
+ LoadStringA(GetModuleHandleW(NULL), IDS_INVALID_SWITCH, message_switch_invalid, sizeof(message_switch_invalid));
+
+ /* We read the complete input at once, for simplicity */
+ text_stdin = read_from_pipe(GetStdHandle(STD_INPUT_HANDLE));
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '/')
+ {
+ find_printf(message_switch_invalid);
+ exitcode = 2;
+ goto cleanup;
+ }
+ else if(tofind == NULL)
+ {
+ tofind = argv[i];
+ }
+ }
+
+ if (tofind == NULL)
+ {
+ find_printf(message_parameter_invalid);
+ exitcode = 2;
+ goto cleanup;
+ }
+
+ exitcode = do_find(text_stdin, tofind);
- return 0;
+cleanup:
+ heap_free(text_stdin);
+ return exitcode;
}
diff --git a/programs/find/resources.h b/programs/find/resources.h
new file mode 100644
index 0000000000..8712d91e36
--- /dev/null
+++ b/programs/find/resources.h
@@ -0,0 +1,27 @@
+/*
+ * Resource IDs
+ *
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_FIND_RESOURCES_H
+#define __WINE_FIND_RESOURCES_H
+
+#define IDS_INVALID_PARAMETER 1000
+#define IDS_INVALID_SWITCH 1001
+
+#endif /* __WINE_FIND_RESOURCES_H */
diff --git a/programs/find/rsrc.rc b/programs/find/rsrc.rc
new file mode 100644
index 0000000000..f10fb6285f
--- /dev/null
+++ b/programs/find/rsrc.rc
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "resources.h"
+
+STRINGTABLE
+{
+ IDS_INVALID_PARAMETER "FIND: Parameter format not correct\r\n"
+ IDS_INVALID_SWITCH "FIND: Invalid switch\r\n"
+}
diff --git a/programs/find/tests/Makefile.in b/programs/find/tests/Makefile.in
new file mode 100644
index 0000000000..ad88243ede
--- /dev/null
+++ b/programs/find/tests/Makefile.in
@@ -0,0 +1,4 @@
+TESTDLL = find.exe
+
+C_SRCS = \
+ find.c
diff --git a/programs/find/tests/find.c b/programs/find/tests/find.c
new file mode 100644
index 0000000000..2dce343965
--- /dev/null
+++ b/programs/find/tests/find.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "wine/heap.h"
+#include "wine/test.h"
+
+/* Copied from find.exe implementation */
+char* read_from_pipe(HANDLE handle)
+{
+ char buffer[4096];
+ DWORD bytes_read;
+ DWORD length = 0;
+ BOOL success;
+ char *ret = heap_alloc_zero(1);
+
+ for (;;)
+ {
+ success = ReadFile(handle, buffer, sizeof(buffer), &bytes_read, NULL);
+ if (!success || !bytes_read)
+ break;
+ ret = heap_realloc(ret, length + bytes_read);
+ memcpy((char *)ret + length, buffer, bytes_read);
+ length += bytes_read;
+ }
+
+ ret[length] = 0;
+ return ret;
+}
+
+/* Copied from find.exe implementation */
+void write_to_pipe(HANDLE handle, const char *str)
+{
+ DWORD bytes_written_sum = 0;
+ DWORD length = lstrlenA(str);
+ do
+ {
+ DWORD bytes_written;
+ WriteFile(handle, str, length * sizeof(char), &bytes_written, NULL);
+ bytes_written_sum += bytes_written;
+ } while (bytes_written_sum < length);
+}
+
+#define run_find(commandline, input, out_expected, exitcode_expected) \
+ run_find_(commandline, input, out_expected, exitcode_expected, __FILE__, __LINE__)
+
+static void run_find_(const char *commandline, const char *input, const char *out_expected, int exitcode_expected, const char *file, int line)
+{
+ HANDLE child_stdin_read;
+ HANDLE child_stdout_write;
+ HANDLE parent_stdin_write;
+ HANDLE parent_stdout_read;
+ STARTUPINFOA startup_info = {0};
+ SECURITY_ATTRIBUTES security_attributes;
+ PROCESS_INFORMATION process_info = {0};
+ char *child_output = NULL;
+ char cmd[4096];
+ int comparison;
+ DWORD exitcode;
+
+ security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ security_attributes.bInheritHandle = TRUE;
+ security_attributes.lpSecurityDescriptor = NULL;
+
+ CreatePipe(&parent_stdout_read, &child_stdout_write, &security_attributes, 0);
+ CreatePipe(&child_stdin_read, &parent_stdin_write, &security_attributes, 0);
+
+ SetHandleInformation(parent_stdout_read, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation(parent_stdin_write, HANDLE_FLAG_INHERIT, 0);
+
+ startup_info.cb = sizeof(STARTUPINFOW);
+ startup_info.hStdInput = child_stdin_read;
+ startup_info.hStdOutput = child_stdout_write;
+ startup_info.hStdError = NULL;
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ sprintf(cmd, "find.exe %s", commandline);
+ CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info);
+ CloseHandle(child_stdin_read);
+ CloseHandle(child_stdout_write);
+
+ write_to_pipe(parent_stdin_write, input);
+ CloseHandle(parent_stdin_write);
+
+ child_output = read_from_pipe(parent_stdout_read);
+ CloseHandle(parent_stdout_read);
+
+ GetExitCodeProcess(process_info.hProcess, &exitcode);
+ CloseHandle(process_info.hProcess);
+ CloseHandle(process_info.hThread);
+
+ comparison = lstrcmpA(child_output, out_expected);
+
+ ok_(file, line)(comparison == 0, "\n#################### Expected:\n"
+ "%s\n"
+ "#################### But got:\n"
+ "%s\n"
+ "####################\n",
+ out_expected, child_output);
+ ok_(file, line)(exitcode == exitcode_expected, "Expected exitcode %d, got %d\n", exitcode_expected, exitcode);
+
+ heap_free(child_output);
+}
+
+static void test_errors(void)
+{
+ run_find("", "", "FIND: Parameter format not correct\r\n", 2);
+ todo_wine
+ run_find("test", "", "FIND: Parameter format not correct\r\n", 2);
+ todo_wine
+ run_find("\"test", "", "FIND: Parameter format not correct\r\n", 2);
+ run_find("\"test\" /XYZ", "", "FIND: Invalid switch\r\n", 2);
+}
+
+static void test_singleline_without_switches(void)
+{
+ run_find("\"\"", "test", "", 1);
+ run_find("\"test\"", "", "", 1);
+ run_find("\"test\"", "test", "test\r\n", 0);
+ run_find("\"test\"", "test2", "test2\r\n", 0);
+ run_find("\"test2\"", "test", "", 1);
+}
+
+START_TEST(find)
+{
+ if (PRIMARYLANGID(GetUserDefaultUILanguage()) != LANG_ENGLISH)
+ {
+ skip("Tests only work with english locale.\n");
+ return;
+ }
+
+ test_errors();
+ test_singleline_without_switches();
+}
--
2.17.1
June 10, 2018
[PATCH] po: Update Norwegian translation.
by Kim Malmo
Signed-off-by: Kim Malmo <berencamlost(a)msn.com>
---
po/nb_NO.po | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 2021f0d18a..d6999c1043 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: Wine\n"
"Report-Msgid-Bugs-To: https://bugs.winehq.org\n"
"POT-Creation-Date: N/A\n"
-"PO-Revision-Date: 2018-05-18 13:47+0200\n"
+"PO-Revision-Date: 2018-06-09 23:18+0200\n"
"Last-Translator: Kim Malmo <berencamlost(a)msn.com>\n"
"Language-Team: Norwegian Bokmål <alexsornes(a)gmail.com>\n"
"Language: nb_NO\n"
@@ -12800,10 +12800,8 @@ msgid "Confirm Value Delete"
msgstr "Bekreft sletting av verdi"
#: regedit.rc:210
-#, fuzzy
-#| msgid "Are you sure you want to delete the registry value '%1'?"
msgid "Are you sure you want to delete the selected registry value?"
-msgstr "Virkelig slette registerverdien \"%1\"?"
+msgstr "Virkelig slette den valgte registerverdien?"
#: regedit.rc:216
msgid "Search complete. The string '%1' was not found."
--
2.17.1
June 9, 2018
Re: [PATCH v2] shellpath.c: Fix creation of HOME directory symbolic links
by Bob Wya
On 8 June 2018 at 12:52, Huw Davies <huw(a)codeweavers.com> wrote:
> On Fri, Jun 08, 2018 at 10:58:23AM +0100, Rob Walker wrote:
> > Fixes: https://bugs.winehq.org/show_bug.cgi?id=41668
> >
> > The Shell Folders, that Wine symlinks to the user's HOME directory, are
> > only re-created on each Wine boot if they: do not pre-exist or are broken
> > symbolic links.
> >
> > Handling the DESKTOP Shell Folder is a special case as this is created
> twice
> > (during a standard boot), early in the Wine boot process. This is
> handled by
> > 2 separate processes, loading shell32.dll, in sequence. This makes it
> hard to determine
> > if the DESKTOP folder was created before the Wine boot (either from a
> previous Wine boot
> > or by the end user).
> >
> > The final (implemented) solution determines the exact start time of the
> Wine boot process
> > (using the current system time and tick-count). If the DESKTOP directory
> was last written
> > after this Wine boot time, we can assume that "we" (Wine) automatically
> created the
> > directory. Only in this instance do we attempt to set a symlink to the
> DESKTOP directory
> > (subdirectory of HOME).
>
> There's still too much going on here.
>
> Do you really need to refactor the code to make your change?
> If not, then just send in the change to the current code.
> If you need to refactor, then do the refactoring first
> (I could imagine taking 3-4 patches to do the refactoring[1])
> then make the change as a final patch in the series.
>
> The file-time / boot-time thing seems hacky, I'm not exactly
> sure what you're trying do to, but this doesn't sound right.
> Hopefully that will become clearer as you tidy things up.
>
> Huw.
>
> [1] For example move the creation of My Pictures/My Videos/etc
> first, then move My Documents and finally Desktop. These
> final two are special cases in the current code, we'd need
> to see that in any new code.
>
Sorry I forgot to update the commit message! I'd updated the code (in the
v2 patch), for handling the
special case of the User profile Desktop directory, without testing file
times / boot times (the latter
didn't work as GetTickTime64 was returning the host system uptime anyway).
--------------------------------------------------------------------------------------------------------------------------------
I have a number of concerns with the existing implementation of
_SHCreateSymbolicLinks():
1) The function is far too long, in it's present form - it's currently 165
lines long!
2) The comments should be far more terse and precise.
3) Using infinite while (1) loops to de-mark code blocks only serves to
obscure the functionality of the code.
4)
4487- /* '$HOME' doesn't exist. Create 'My Pictures', 'My Videos'
and 'My Music' subdirs
4488- * in '%USERPROFILE%\\My Documents' or fail silently if they
already exist. */
4489- pszHome = NULL;
4490- strcpy(szPersonalTarget, pszPersonal);
4491- for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
4492- strcpy(szMyStuffTarget, szPersonalTarget);
4493- if (_SHAppendToUnixPath(szMyStuffTarget,
MAKEINTRESOURCEW(aidsMyStuff[i])))
4494- mkdir(szMyStuffTarget, 0777);
4495- }
Windows Vista (and newer) do not nest the User profile directories. Since
Wine is targeting Windows 7 by default - this
legacy behaviour should be removed. (As an end user, who used to use
Windows XP, this was simply an annoying default
layout anyway.)
5)
4447- /* '$HOME/My Documents' exists. Create 'My Pictures',
4448- * 'My Videos' and 'My Music' subfolders or fail
silently if
4449- * they already exist.
4450- */
4451- for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
4452- {
4453- strcpy(szMyStuffTarget, szPersonalTarget);
4454- if (_SHAppendToUnixPath(szMyStuffTarget,
MAKEINTRESOURCEW(aidsMyStuff[i])))
4455- mkdir(szMyStuffTarget, 0777);
4456- }
4457- break;
Ditto as per (4). This is an obsolete User Profile directory layout
(pre-Vista).
Also if "${HOME}/My Documents" exists then this block of code will start
creating subdirectories in this
folder. I don't think that Wine should be making the rather arbitrary
assumption that a Wine user wants
their "${HOME}" directory spammed with new subdirectories.
I often read online, comments from Wine users, complaining about this sort
of behaviour...
6)
4543- /* Last but not least, the Desktop folder */
4544- if (pszHome)
4545- strcpy(szDesktopTarget, pszHome);
4546- else
4547- strcpy(szDesktopTarget, pszPersonal);
4548- heap_free(pszPersonal);
4549-
4550- xdg_desktop_dir = xdg_results ? xdg_results[num - 1] : NULL;
4551- if (xdg_desktop_dir ||
4552- (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
4553- !stat(szDesktopTarget, &statFolder) &&
S_ISDIR(statFolder.st_mode)))
4554- {
4555- hr = SHGetFolderPathW(NULL,
CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE,
NULL,
4556- SHGFP_TYPE_DEFAULT, wszTempPath);
4557- if (SUCCEEDED(hr) && (pszDesktop =
wine_get_unix_file_name(wszTempPath)))
4558- {
4559- remove(pszDesktop);
4560- if (xdg_desktop_dir)
4561- symlink(xdg_desktop_dir, pszDesktop);
4562- else
4563- symlink(szDesktopTarget, pszDesktop);
4564- heap_free(pszDesktop);
4565- }
4566- }
This code uses pszPersonal as a fallback target for when HOME is unset.
This will be the equivalent of:
"${WINEPREFIX}/dosdevices/c:/users/${USER}/My Documents"
Say the XDG_DESKTOP_DIR check fails. Then Wine tries to find the directory:
"${WINEPREFIX}/dosdevices/c:/users/${USER}/My Documents/Desktop"
as a symlink target. Which never succeeds because Wine never creates this
directory...
This extra path appears to be redundant (HOME unset / XDG_DESKTOP_DIR
unset).
--------------------------------------------------------------------------------------------------------------------------------
I can of course leave the variable names unchanged and the function name.
I was "told off" for not using snake case on a previous Wine commit - so I
assumed
I had to follow this standard if I wanted to refactor existing code. :-)
I'd like to tidy this function up and make it more readable (including the
comments).
Which I can do in staged patches, as you suggested.
But obviously I'd like to feel that we are both on the "same page" about
the changes
I discussed (above). Before I email in a v3 staged patchset.
June 8, 2018
Re: [PATCH] d3dcompiler/tests: Use the available ARRAY_SIZE() macro
by Matteo Bruni
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
June 8, 2018
[PATCH] ntprint/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/ntprint/tests/ntprint.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/ntprint/tests/ntprint.c b/dlls/ntprint/tests/ntprint.c
index 1710220def..57caa49ab2 100644
--- a/dlls/ntprint/tests/ntprint.c
+++ b/dlls/ntprint/tests/ntprint.c
@@ -67,7 +67,7 @@ static void test_PSetupCreateMonitorInfo(VOID)
{
HANDLE mi;
WCHAR buffer[1024] = {'\\','\\'};
- UINT len = sizeof(buffer) / sizeof(buffer[0]) - 2;
+ UINT len = ARRAY_SIZE(buffer) - 2;
GetComputerNameW(buffer + 2, &len);
SetLastError(0xdeadbeef);
@@ -155,7 +155,7 @@ static void test_PSetupEnumMonitor(VOID)
"and '> 0')\n", res, GetLastError(), minsize);
- size = sizeof(buffer) / sizeof(buffer[0]);
+ size = ARRAY_SIZE(buffer);
if ((minsize + 1) > size) {
skip("overflow: %u\n", minsize);
pPSetupDestroyMonitorInfo(mi);
@@ -165,7 +165,7 @@ static void test_PSetupEnumMonitor(VOID)
if (0) {
/* XP: ERROR_INVALID_PARAMETER, w2k: Crash */
SetLastError(0xdeadbeef);
- size = sizeof(buffer) / sizeof(buffer[0]);
+ size = ARRAY_SIZE(buffer);
res = pPSetupEnumMonitor(NULL, 0, buffer, &size);
ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
"got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
@@ -175,7 +175,7 @@ static void test_PSetupEnumMonitor(VOID)
if (0) {
/* XP: Crash, w2k: Success (how can that work?) */
SetLastError(0xdeadbeef);
- size = sizeof(buffer) / sizeof(buffer[0]);
+ size = ARRAY_SIZE(buffer);
res = pPSetupEnumMonitor(mi, 0, NULL, &size);
trace("got %u with %u and %u\n", res, GetLastError(), size);
}
@@ -213,7 +213,7 @@ static void test_PSetupEnumMonitor(VOID)
while (res && (index < 20)) {
SetLastError(0xdeadbeef);
buffer[0] = '\0';
- size = sizeof(buffer) / sizeof(buffer[0]);
+ size = ARRAY_SIZE(buffer);
res = pPSetupEnumMonitor(mi, index, buffer, &size);
ok( res || (GetLastError() == ERROR_NO_MORE_ITEMS),
"(%u) got %u with %u and %u (expected '!=0' or: '0' with "
--
2.14.4
June 8, 2018
[PATCH] oleacc/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/oleacc/tests/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/oleacc/tests/main.c b/dlls/oleacc/tests/main.c
index 7a0737caff..c62fa79556 100644
--- a/dlls/oleacc/tests/main.c
+++ b/dlls/oleacc/tests/main.c
@@ -410,7 +410,7 @@ static void test_getroletext(void)
memset(buff2W, 0, sizeof(buff2W));
ret = GetRoleTextW(role, NULL, 0);
- GetRoleTextW(role, buff2W, sizeof(buff2W)/sizeof(WCHAR));
+ GetRoleTextW(role, buff2W, ARRAY_SIZE(buff2W));
ok(ret == lstrlenW(buff2W),
"GetRoleTextW: returned length doesn't match returned buffer for role %d\n", role);
}
--
2.14.4
June 8, 2018
[PATCH] psapi/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/psapi/tests/psapi_main.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 4adc82619b..0ff212c766 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -536,12 +536,12 @@ todo_wine {
}
SetLastError(0xdeadbeef);
- ret = pGetMappedFileNameW(GetCurrentProcess(), base, map_nameW, sizeof(map_nameW)/sizeof(map_nameW[0]));
+ ret = pGetMappedFileNameW(GetCurrentProcess(), base, map_nameW, ARRAY_SIZE(map_nameW));
todo_wine {
ok(ret, "GetMappedFileNameW error %d\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
}
- if (nt_get_mapped_file_name(GetCurrentProcess(), base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0])))
+ if (nt_get_mapped_file_name(GetCurrentProcess(), base, nt_map_name, ARRAY_SIZE(nt_map_name)))
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
@@ -658,7 +658,7 @@ static void test_GetProcessImageFileName(void)
/* correct call */
memset(szImgPathW, 0xff, sizeof(szImgPathW));
- ret = pGetProcessImageFileNameW(hpQI, szImgPathW, sizeof(szImgPathW)/sizeof(WCHAR));
+ ret = pGetProcessImageFileNameW(hpQI, szImgPathW, ARRAY_SIZE(szImgPathW));
ok(ret > 0, "GetProcessImageFileNameW should have succeeded.\n");
ok(szImgPathW[0] == '\\', "GetProcessImageFileNameW should have returned an NT path.\n");
ok(lstrlenW(szImgPathW) == ret, "Expected length to be %d, got %d\n", ret, lstrlenW(szImgPathW));
--
2.14.4
June 8, 2018
[PATCH] quartz/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/quartz/tests/avisplitter.c | 4 ++--
dlls/quartz/tests/filtergraph.c | 6 +++---
dlls/quartz/tests/misc.c | 8 ++++----
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/quartz/tests/avisplitter.c b/dlls/quartz/tests/avisplitter.c
index 8bafb14157..bc933d148d 100644
--- a/dlls/quartz/tests/avisplitter.c
+++ b/dlls/quartz/tests/avisplitter.c
@@ -210,7 +210,7 @@ static void test_filesourcefilter(void)
ret = GetTempFileNameW(temp, prefix, 0, path);
ok(ret, "GetTempFileNameW failed with error %u\n", GetLastError());
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
trace("Running test for %s\n", tests[i].label);
@@ -280,7 +280,7 @@ static WCHAR *load_resource(const WCHAR *name)
HRSRC res;
void *ptr;
- GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
lstrcatW(pathW, name);
file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index a1ece9489f..85079d982d 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -50,7 +50,7 @@ static WCHAR *load_resource(const WCHAR *name)
HRSRC res;
void *ptr;
- GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+ GetTempPathW(ARRAY_SIZE(pathW), pathW);
lstrcatW(pathW, name);
file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
@@ -1500,14 +1500,14 @@ static HRESULT createtestfilter(const CLSID* pClsid, const TestFilterPinData *pi
pinInfo.pFilter = &pTestFilter->IBaseFilter_iface;
if (pinInfo.dir == PINDIR_INPUT)
{
- lstrcpynW(pinInfo.achName, wcsInputPinName, sizeof(pinInfo.achName) / sizeof(pinInfo.achName[0]));
+ lstrcpynW(pinInfo.achName, wcsInputPinName, ARRAY_SIZE(pinInfo.achName));
hr = TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
&pTestFilter->ppPins[i]);
}
else
{
- lstrcpynW(pinInfo.achName, wcsOutputPinName, sizeof(pinInfo.achName) / sizeof(pinInfo.achName[0]));
+ lstrcpynW(pinInfo.achName, wcsOutputPinName, ARRAY_SIZE(pinInfo.achName));
hr = TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
&pTestFilter->ppPins[i]);
}
diff --git a/dlls/quartz/tests/misc.c b/dlls/quartz/tests/misc.c
index 748c0f2cfd..16b6d40ce4 100644
--- a/dlls/quartz/tests/misc.c
+++ b/dlls/quartz/tests/misc.c
@@ -169,7 +169,7 @@ static void test_null_renderer_aggregations(void)
};
int i;
- for (i = 0; i < sizeof(iids) / sizeof(iids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iids); i++)
{
test_aggregation(CLSID_SystemClock, CLSID_NullRenderer, IID_IReferenceClock, *iids[i]);
}
@@ -182,7 +182,7 @@ static void test_video_renderer_aggregations(void)
};
int i;
- for (i = 0; i < sizeof(iids) / sizeof(iids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iids); i++)
{
test_aggregation(CLSID_SystemClock, CLSID_VideoRenderer,
IID_IReferenceClock, *iids[i]);
@@ -199,7 +199,7 @@ static void test_filter_graph_aggregations(void)
};
int i;
- for (i = 0; i < sizeof(iids) / sizeof(iids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iids); i++)
{
test_aggregation(CLSID_SystemClock, CLSID_FilterGraph,
IID_IReferenceClock, *iids[i]);
@@ -213,7 +213,7 @@ static void test_filter_mapper_aggregations(void)
};
int i;
- for (i = 0; i < sizeof(iids) / sizeof(iids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iids); i++)
{
test_aggregation(CLSID_SystemClock, CLSID_FilterMapper2,
IID_IReferenceClock, *iids[i]);
--
2.14.4
June 8, 2018
[PATCH] rpcrt4/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/rpcrt4/tests/cstub.c | 2 +-
dlls/rpcrt4/tests/rpc.c | 6 ++----
dlls/rpcrt4/tests/server.c | 2 +-
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/rpcrt4/tests/cstub.c b/dlls/rpcrt4/tests/cstub.c
index 606107fcfd..7bed308807 100644
--- a/dlls/rpcrt4/tests/cstub.c
+++ b/dlls/rpcrt4/tests/cstub.c
@@ -596,7 +596,7 @@ static IPSFactoryBuffer *test_NdrDllGetClassObject(void)
#undef VTBL_PROXY_TEST
#undef VTBL_PROXY_TEST_NOT_ZERO
- for (i = 0; i < sizeof(interfaces)/sizeof(interfaces[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(interfaces); i++)
ok( proxy_vtbl[i]->header.piid == interfaces[i],
"wrong proxy %u iid %p/%p\n", i, proxy_vtbl[i]->header.piid, interfaces[i] );
diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c
index f026e99de2..c9f2a4b721 100644
--- a/dlls/rpcrt4/tests/rpc.c
+++ b/dlls/rpcrt4/tests/rpc.c
@@ -149,10 +149,8 @@ static void TestDceErrorInqText (void)
*/
DWORD dwCount;
- dwCount = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, RPC_S_NOT_RPC_ERROR, 0, bufferInvalid,
- sizeof(bufferInvalid)/sizeof(bufferInvalid[0]), NULL);
+ dwCount = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
+ RPC_S_NOT_RPC_ERROR, 0, bufferInvalid, ARRAY_SIZE(bufferInvalid), NULL);
/* A random sample of DceErrorInqText */
/* 0 is success */
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index dfad1ed0f3..b35b71bcfd 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -313,7 +313,7 @@ void __cdecl s_get_number_array(int x[20], int *n)
{
int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(x, c, sizeof(c));
- *n = sizeof(c)/sizeof(c[0]);
+ *n = ARRAY_SIZE(c);
}
int __cdecl s_sum_cs(cs_t *cs)
--
2.14.4
June 8, 2018
[PATCH] webservices/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/webservices/tests/channel.c | 12 ++++++------
dlls/webservices/tests/msg.c | 2 +-
dlls/webservices/tests/proxy.c | 8 ++++----
dlls/webservices/tests/reader.c | 20 ++++++++++----------
dlls/webservices/tests/url.c | 4 ++--
dlls/webservices/tests/writer.c | 38 +++++++++++++++++++-------------------
6 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c
index 17a0b58ac8..c995a08829 100644
--- a/dlls/webservices/tests/channel.c
+++ b/dlls/webservices/tests/channel.c
@@ -134,7 +134,7 @@ static void test_WsOpenChannel(void)
ok( hr == E_INVALIDARG, "got %08x\n", hr );
memset( &addr, 0, sizeof(addr) );
- addr.url.length = sizeof(url)/sizeof(url[0]);
+ addr.url.length = ARRAY_SIZE( url );
addr.url.chars = url;
hr = WsOpenChannel( NULL, &addr, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
@@ -179,7 +179,7 @@ static void test_WsResetChannel(void)
ok( hr == S_OK, "got %08x\n", hr );
memset( &addr, 0, sizeof(addr) );
- addr.url.length = sizeof(url)/sizeof(url[0]);
+ addr.url.length = ARRAY_SIZE( url );
addr.url.chars = url;
hr = WsOpenChannel( channel, &addr, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -301,7 +301,7 @@ static void test_WsOpenListener(void)
hr = WsOpenListener( listener, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
- url.length = sizeof(str)/sizeof(str[0]);
+ url.length = ARRAY_SIZE( str );
url.chars = str;
hr = WsOpenListener( NULL, &url, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
@@ -320,7 +320,7 @@ static void test_WsOpenListener(void)
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- url.length = sizeof(str2)/sizeof(str2[0]);
+ url.length = ARRAY_SIZE( str2 );
url.chars = str2;
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -333,7 +333,7 @@ static void test_WsOpenListener(void)
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- url.length = sizeof(str3)/sizeof(str3[0]);
+ url.length = ARRAY_SIZE( str3 );
url.chars = str3;
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -387,7 +387,7 @@ static void test_WsResetListener(void)
{
WCHAR str[] =
{'n','e','t','.','t','c','p',':','/','/','+',':','2','0','1','7','/','p','a','t','h'};
- WS_STRING url = { sizeof(str)/sizeof(str[0]), str };
+ WS_STRING url = { ARRAY_SIZE( str ), str };
WS_LISTENER *listener;
WS_LISTENER_STATE state;
WS_LISTENER_PROPERTY prop;
diff --git a/dlls/webservices/tests/msg.c b/dlls/webservices/tests/msg.c
index 550ae1dd0d..22d69ece2c 100644
--- a/dlls/webservices/tests/msg.c
+++ b/dlls/webservices/tests/msg.c
@@ -258,7 +258,7 @@ static void test_WsAddressMessage(void)
memset( &endpoint, 0, sizeof(endpoint) );
endpoint.url.chars = localhost;
- endpoint.url.length = sizeof(localhost)/sizeof(localhost[0]);
+ endpoint.url.length = ARRAY_SIZE( localhost );
hr = WsAddressMessage( msg, &endpoint, NULL );
ok( hr == S_OK, "got %08x\n", hr );
diff --git a/dlls/webservices/tests/proxy.c b/dlls/webservices/tests/proxy.c
index 95f980a2ff..f5297796b3 100644
--- a/dlls/webservices/tests/proxy.c
+++ b/dlls/webservices/tests/proxy.c
@@ -164,7 +164,7 @@ static void test_WsOpenServiceProxy(void)
ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
memset( &addr, 0, sizeof(addr) );
- addr.url.length = sizeof(url)/sizeof(url[0]);
+ addr.url.length = ARRAY_SIZE( url );
addr.url.chars = url;
hr = WsOpenServiceProxy( proxy, &addr, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -206,7 +206,7 @@ static void test_WsResetServiceProxy(void)
ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
memset( &addr, 0, sizeof(addr) );
- addr.url.length = sizeof(url)/sizeof(url[0]);
+ addr.url.length = ARRAY_SIZE( url );
addr.url.chars = url;
hr = WsOpenServiceProxy( proxy, &addr, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -385,7 +385,7 @@ static HRESULT create_proxy( int port, WS_SERVICE_PROXY **ret )
*ret = NULL;
hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL,
- 0, prop, sizeof(prop)/sizeof(prop[0]), &proxy, NULL );
+ 0, prop, ARRAY_SIZE( prop ), &proxy, NULL );
if (hr != S_OK) return hr;
memset( &addr, 0, sizeof(addr) );
@@ -687,7 +687,7 @@ static DWORD CALLBACK server_proc( void *arg )
}
buf[i] = 0;
- for (j = 0; j < sizeof(tests)/sizeof(tests[0]); j++)
+ for (j = 0; j < ARRAY_SIZE( tests ); j++)
{
if (strstr( buf, tests[j].req_action ))
{
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index bd8a37cc52..b21e8396be 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -479,7 +479,7 @@ static void test_WsSetInput(void)
enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
enc.charSet = WS_CHARSET_AUTO;
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
input.encodedData = tests[i].data;
input.encodedDataSize = tests[i].size;
@@ -1174,7 +1174,7 @@ static void test_WsReadNode(void)
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_input( reader, tests[i].text, strlen(tests[i].text) );
ok( hr == S_OK, "got %08x\n", hr );
@@ -1644,7 +1644,7 @@ static void test_WsReadType(void)
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
enum_desc.values = enum_values;
- enum_desc.valueCount = sizeof(enum_values)/sizeof(enum_values[0]);
+ enum_desc.valueCount = ARRAY_SIZE( enum_values );
enum_desc.maxByteCount = 3;
enum_desc.nameIndices = NULL;
@@ -3526,7 +3526,7 @@ static void test_datetime(void)
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
memset( &date, 0, sizeof(date) );
prepare_type_test( reader, tests[i].str, strlen(tests[i].str) );
@@ -3578,7 +3578,7 @@ static void test_WsDateTimeToFileTime(void)
hr = WsDateTimeToFileTime( NULL, &ft, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
memset( &ft, 0, sizeof(ft) );
hr = WsDateTimeToFileTime( &tests[i].dt, &ft, NULL );
@@ -3716,7 +3716,7 @@ static void test_double(void)
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
val = 0;
prepare_type_test( reader, tests[i].str, strlen(tests[i].str) );
@@ -4064,7 +4064,7 @@ static void test_entities(void)
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_input( reader, tests[i].str, strlen(tests[i].str) );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -4628,7 +4628,7 @@ static void test_WsReadQualifiedName(void)
hr = WsReadQualifiedName( reader, heap, NULL, &localname, NULL, NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_input( reader, tests[i].str, strlen(tests[i].str) );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -5647,7 +5647,7 @@ static void test_dictionary(void)
UuidCreate( &dict.guid );
dict.strings = strings;
- dict.stringCount = sizeof(strings)/sizeof(strings[0]);
+ dict.stringCount = ARRAY_SIZE( strings );
dict.isConst = TRUE;
/* short dictionary element */
@@ -6385,7 +6385,7 @@ static void test_float(void)
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
val = 0;
prepare_type_test( reader, tests[i].str, strlen(tests[i].str) );
diff --git a/dlls/webservices/tests/url.c b/dlls/webservices/tests/url.c
index 82059a02bf..2b8dda482e 100644
--- a/dlls/webservices/tests/url.c
+++ b/dlls/webservices/tests/url.c
@@ -131,7 +131,7 @@ static void test_WsDecodeUrl(void)
hr = WsDecodeUrl( &str, 0, NULL, (WS_URL **)&url, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
static const WCHAR netpipe[] = {'n','e','t','.','p','i','p','e'};
@@ -271,7 +271,7 @@ static void test_WsEncodeUrl(void)
hr = WsEncodeUrl( (const WS_URL *)&url, 0, heap, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
memset( &url, 0, sizeof(url) );
url.url.scheme = tests[i].scheme;
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 15d4569662..e33c38951e 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -710,7 +710,7 @@ static void test_basic_type(void)
ok( hr == S_OK, "got %08x\n", hr );
/* element content type mapping */
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
prepare_basic_type_test( writer );
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
@@ -723,7 +723,7 @@ static void test_basic_type(void)
}
/* element type mapping is the same as element content type mapping for basic types */
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
const INT64 *ptr = &tests[i].val;
@@ -738,7 +738,7 @@ static void test_basic_type(void)
}
/* attribute type mapping */
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
prepare_basic_type_test( writer );
hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
@@ -1103,7 +1103,7 @@ static void test_WsWriteValue(void)
ok( hr == E_INVALIDARG, "got %08x\n", hr );
/* element type mapping */
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
@@ -1120,7 +1120,7 @@ static void test_WsWriteValue(void)
}
/* attribute type mapping */
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
@@ -2170,7 +2170,7 @@ static void test_text_types(void)
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
@@ -2257,7 +2257,7 @@ static void test_double(void)
ok( hr == S_OK, "got %08x\n", hr );
text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
@@ -2772,7 +2772,7 @@ static void test_escapes(void)
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests_elem)/sizeof(tests_elem[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests_elem ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -2789,7 +2789,7 @@ static void test_escapes(void)
check_output( writer, tests_elem[i].result, __LINE__ );
}
- for (i = 0; i < sizeof(tests_attr)/sizeof(tests_attr[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests_attr ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -2812,7 +2812,7 @@ static void test_escapes(void)
check_output( writer, tests_attr[i].result, __LINE__ );
}
- for (i = 0; i < sizeof(tests_cdata)/sizeof(tests_cdata[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests_cdata ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -2835,7 +2835,7 @@ static void test_escapes(void)
check_output( writer, tests_cdata[i].result, __LINE__ );
}
- for (i = 0; i < sizeof(tests_comment)/sizeof(tests_comment[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests_comment ); i++)
{
WS_XML_COMMENT_NODE comment = {{WS_XML_NODE_TYPE_COMMENT}};
@@ -2954,7 +2954,7 @@ static void test_write_option(void)
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -3041,7 +3041,7 @@ static void test_datetime(void)
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
@@ -3231,7 +3231,7 @@ static void test_WsWriteQualifiedName(void)
hr = WsWriteQualifiedName( writer, NULL, NULL, NULL, NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( tests ); i++)
{
WS_XML_STRING prefix2, localname2, ns2;
const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
@@ -3551,7 +3551,7 @@ static void test_binary_encoding(void)
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
- for (i = 0; i < sizeof(elem_tests)/sizeof(elem_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( elem_tests ); i++)
{
hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -3574,7 +3574,7 @@ static void test_binary_encoding(void)
if (hr == S_OK) check_output_bin( writer, elem_tests[i].result, elem_tests[i].len_result, __LINE__ );
}
- for (i = 0; i < sizeof(attr_tests)/sizeof(attr_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( attr_tests ); i++)
{
hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -3778,12 +3778,12 @@ static void test_dictionary(void)
UuidCreate( &dict.guid );
dict.strings = strings;
- dict.stringCount = sizeof(strings)/sizeof(strings[0]);
+ dict.stringCount = ARRAY_SIZE( strings );
dict.isConst = TRUE;
bin.staticDictionary = &dict;
- for (i = 0; i < sizeof(elem_tests)/sizeof(elem_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( elem_tests ); i++)
{
hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -3799,7 +3799,7 @@ static void test_dictionary(void)
if (hr == S_OK) check_output_bin( writer, elem_tests[i].result, elem_tests[i].len_result, __LINE__ );
}
- for (i = 0; i < sizeof(attr_tests)/sizeof(attr_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE( attr_tests ); i++)
{
hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
--
2.14.4
June 8, 2018
[PATCH] windowscodecs/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/windowscodecs/tests/info.c | 10 ++++----
dlls/windowscodecs/tests/metadata.c | 46 +++++++++++++++++------------------
dlls/windowscodecs/tests/palette.c | 2 +-
dlls/windowscodecs/tests/pngformat.c | 2 +-
dlls/windowscodecs/tests/tiffformat.c | 2 +-
5 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/dlls/windowscodecs/tests/info.c b/dlls/windowscodecs/tests/info.c
index d00e9d8338..b647601495 100644
--- a/dlls/windowscodecs/tests/info.c
+++ b/dlls/windowscodecs/tests/info.c
@@ -119,7 +119,7 @@ static void test_decoder_info(void)
UINT num_formats, count;
int i, j;
- for (i = 0; i < sizeof(decoder_info_tests)/sizeof(decoder_info_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(decoder_info_tests); i++)
{
struct decoder_info_test *test = &decoder_info_tests[i];
IWICBitmapDecoder *decoder, *decoder2;
@@ -149,8 +149,8 @@ static void test_decoder_info(void)
}
IWICBitmapDecoder_Release(decoder);
- MultiByteToWideChar(CP_ACP, 0, test->mimetype, -1, mimetypeW, sizeof(mimetypeW)/sizeof(mimetypeW[0]));
- MultiByteToWideChar(CP_ACP, 0, test->extensions, -1, extensionsW, sizeof(extensionsW)/sizeof(extensionsW[0]));
+ MultiByteToWideChar(CP_ACP, 0, test->mimetype, -1, mimetypeW, ARRAY_SIZE(mimetypeW));
+ MultiByteToWideChar(CP_ACP, 0, test->extensions, -1, extensionsW, ARRAY_SIZE(extensionsW));
hr = get_component_info(test->clsid, &info);
ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr);
@@ -234,8 +234,8 @@ static void test_decoder_info(void)
ok(hr == E_INVALIDARG, "GetPixelFormats failed, hr=%x\n", hr);
count = 0xdeadbeef;
- hr = IWICBitmapDecoderInfo_GetPixelFormats(decoder_info, sizeof(pixelformats)/sizeof(pixelformats[0]),
- pixelformats, &count);
+ hr = IWICBitmapDecoderInfo_GetPixelFormats(decoder_info, ARRAY_SIZE(pixelformats),
+ pixelformats, &count);
ok(hr == S_OK, "GetPixelFormats failed, hr=%x\n", hr);
ok(count == num_formats, "got %d formats, expected %d\n", count, num_formats);
diff --git a/dlls/windowscodecs/tests/metadata.c b/dlls/windowscodecs/tests/metadata.c
index c54d7dfe18..eb846db0b8 100644
--- a/dlls/windowscodecs/tests/metadata.c
+++ b/dlls/windowscodecs/tests/metadata.c
@@ -816,7 +816,7 @@ static void test_metadata_IFD(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -832,7 +832,7 @@ static void test_metadata_IFD(void)
load_stream((IUnknown *)reader, IFD_data_swapped, sizeof(IFD_data), persist_options);
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
HeapFree(GetProcessHeap(), 0, IFD_data_swapped);
@@ -1271,7 +1271,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(gif_LSD)/sizeof(gif_LSD[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(gif_LSD), "unexpected count %u\n", count);
compare_metadata(reader, gif_LSD, count);
@@ -1320,7 +1320,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(gif_IMD)/sizeof(gif_IMD[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(gif_IMD), "unexpected count %u\n", count);
compare_metadata(reader, gif_IMD, count);
@@ -1374,7 +1374,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_LSD)/sizeof(animated_gif_LSD[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_LSD), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_LSD, count);
@@ -1393,7 +1393,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_APE)/sizeof(animated_gif_APE[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_APE), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_APE, count);
@@ -1412,7 +1412,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_comment_1)/sizeof(animated_gif_comment_1[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_comment_1), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_comment_1, count);
@@ -1431,7 +1431,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_plain_1)/sizeof(animated_gif_plain_1[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_plain_1), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_plain_1, count);
@@ -1480,7 +1480,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_IMD)/sizeof(animated_gif_IMD[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_IMD), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_IMD, count);
@@ -1499,7 +1499,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_comment_2)/sizeof(animated_gif_comment_2[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_comment_2), "unexpected count %u\n", count);
if (count == 1)
compare_metadata(reader, animated_gif_comment_2, count);
@@ -1519,7 +1519,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_plain_2)/sizeof(animated_gif_plain_2[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_plain_2), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_plain_2, count);
@@ -1538,7 +1538,7 @@ static void test_metadata_gif(void)
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(animated_gif_GCE)/sizeof(animated_gif_GCE[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(animated_gif_GCE), "unexpected count %u\n", count);
compare_metadata(reader, animated_gif_GCE, count);
@@ -1599,7 +1599,7 @@ static void test_metadata_gif(void)
ok(len == 2, "expected 2, got %u\n", len);
ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
- for (i = 0; i < sizeof(decoder_data)/sizeof(decoder_data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(decoder_data); i++)
{
WCHAR queryW[256];
@@ -1622,7 +1622,7 @@ static void test_metadata_gif(void)
ok(len == lstrlenW(queryW) + 1, "expected %u, got %u\n", lstrlenW(queryW) + 1, len);
ok(!lstrcmpW(name, queryW), "expected %s, got %s\n", wine_dbgstr_w(queryW), wine_dbgstr_w(name));
- for (j = 0; j < sizeof(decoder_data)/sizeof(decoder_data[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(decoder_data); j++)
{
MultiByteToWideChar(CP_ACP, 0, decoder_data[j].query, -1, queryW, 256);
@@ -1698,7 +1698,7 @@ static void test_metadata_gif(void)
ok(len == 2, "expected 2, got %u\n", len);
ok(!lstrcmpW(name, rootW), "expected '/', got %s\n", wine_dbgstr_w(name));
- for (i = 0; i < sizeof(frame_data)/sizeof(frame_data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(frame_data); i++)
{
if (winetest_debug > 1)
trace("query: %s\n", frame_data[i].query);
@@ -1812,7 +1812,7 @@ static void test_metadata_LSD(void)
{
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -1890,7 +1890,7 @@ static void test_metadata_IMD(void)
{
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -1965,7 +1965,7 @@ static void test_metadata_GCE(void)
{
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -2038,7 +2038,7 @@ static void test_metadata_APE(void)
{
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -2122,7 +2122,7 @@ static void test_metadata_GIF_comment(void)
{
hr = IWICMetadataReader_GetCount(reader, &count);
ok(hr == S_OK, "GetCount error %#x\n", hr);
- ok(count == sizeof(td)/sizeof(td[0]), "unexpected count %u\n", count);
+ ok(count == ARRAY_SIZE(td), "unexpected count %u\n", count);
compare_metadata(reader, td, count);
@@ -2425,9 +2425,9 @@ static void test_WICMapSchemaToName(void)
return;
}
- for (i = 0; i < sizeof(guid_list)/sizeof(guid_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(guid_list); i++)
{
- for (j = 0; j < sizeof(schema_list)/sizeof(schema_list[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(schema_list); j++)
{
hr = WICMapSchemaToName(guid_list[i], schema_list[j], 0, NULL, &len);
if (IsEqualGUID(guid_list[i], &GUID_MetadataFormatXMP) ||
@@ -2959,7 +2959,7 @@ static void test_queryreader(void)
hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &mdbr, &reader);
ok(hr == S_OK, "CreateQueryReaderFromBlockReader error %#x\n", hr);
- for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_data); i++)
{
current_metadata = test_data[i].data;
diff --git a/dlls/windowscodecs/tests/palette.c b/dlls/windowscodecs/tests/palette.c
index e3b9a313f6..27bf7c80d1 100644
--- a/dlls/windowscodecs/tests/palette.c
+++ b/dlls/windowscodecs/tests/palette.c
@@ -473,7 +473,7 @@ static void test_predefined_palette(void)
ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
IWICPalette_Release(palette);
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
hr = IWICImagingFactory_CreatePalette(factory, &palette);
ok(hr == S_OK, "%u: CreatePalette error %#x\n", i, hr);
diff --git a/dlls/windowscodecs/tests/pngformat.c b/dlls/windowscodecs/tests/pngformat.c
index 4b84ccebb1..c798ea438d 100644
--- a/dlls/windowscodecs/tests/pngformat.c
+++ b/dlls/windowscodecs/tests/pngformat.c
@@ -717,7 +717,7 @@ static void test_color_formats(void)
* with tEXt id.
*/
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
/* with the tRNS and PLTE chunks */
memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
diff --git a/dlls/windowscodecs/tests/tiffformat.c b/dlls/windowscodecs/tests/tiffformat.c
index a7b6f5b594..c6ec21ada1 100644
--- a/dlls/windowscodecs/tests/tiffformat.c
+++ b/dlls/windowscodecs/tests/tiffformat.c
@@ -454,7 +454,7 @@ static void test_tiff_resolution(void)
double dpi_x, dpi_y;
int i;
- for (i = 0; i < sizeof(tiff_resolution_test_data)/sizeof(tiff_resolution_test_data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tiff_resolution_test_data); i++)
{
const struct tiff_resolution_test_data *test_data = &tiff_resolution_test_data[i];
tiff_resolution_image_data.resx = test_data->resx;
--
2.14.4
June 8, 2018
Re: [PATCH] gdiplus/tests: Use the available ARRAY_SIZE() macro
by Vincent Povirk
Signed-off-by: Vincent Povirk <vincent(a)codeweavers.com>
June 8, 2018
Re: [PATCH v2] shellpath.c: Fix creation of HOME directory symbolic links
by Huw Davies
On Fri, Jun 08, 2018 at 10:58:23AM +0100, Rob Walker wrote:
> Fixes: https://bugs.winehq.org/show_bug.cgi?id=41668
>
> The Shell Folders, that Wine symlinks to the user's HOME directory, are
> only re-created on each Wine boot if they: do not pre-exist or are broken
> symbolic links.
>
> Handling the DESKTOP Shell Folder is a special case as this is created twice
> (during a standard boot), early in the Wine boot process. This is handled by
> 2 separate processes, loading shell32.dll, in sequence. This makes it hard to determine
> if the DESKTOP folder was created before the Wine boot (either from a previous Wine boot
> or by the end user).
>
> The final (implemented) solution determines the exact start time of the Wine boot process
> (using the current system time and tick-count). If the DESKTOP directory was last written
> after this Wine boot time, we can assume that "we" (Wine) automatically created the
> directory. Only in this instance do we attempt to set a symlink to the DESKTOP directory
> (subdirectory of HOME).
There's still too much going on here.
Do you really need to refactor the code to make your change?
If not, then just send in the change to the current code.
If you need to refactor, then do the refactoring first
(I could imagine taking 3-4 patches to do the refactoring[1])
then make the change as a final patch in the series.
The file-time / boot-time thing seems hacky, I'm not exactly
sure what you're trying do to, but this doesn't sound right.
Hopefully that will become clearer as you tidy things up.
Huw.
[1] For example move the creation of My Pictures/My Videos/etc
first, then move My Documents and finally Desktop. These
final two are special cases in the current code, we'd need
to see that in any new code.
June 8, 2018
[PATCH v2] shellpath.c: Fix creation of HOME directory symbolic links
by Rob Walker
Fixes: https://bugs.winehq.org/show_bug.cgi?id=41668
The Shell Folders, that Wine symlinks to the user's HOME directory, are
only re-created on each Wine boot if they: do not pre-exist or are broken
symbolic links.
Handling the DESKTOP Shell Folder is a special case as this is created twice
(during a standard boot), early in the Wine boot process. This is handled by
2 separate processes, loading shell32.dll, in sequence. This makes it hard to determine
if the DESKTOP folder was created before the Wine boot (either from a previous Wine boot
or by the end user).
The final (implemented) solution determines the exact start time of the Wine boot process
(using the current system time and tick-count). If the DESKTOP directory was last written
after this Wine boot time, we can assume that "we" (Wine) automatically created the
directory. Only in this instance do we attempt to set a symlink to the DESKTOP directory
(subdirectory of HOME).
Test on Gentoo GNU/Linux.
Signed-off-by: Rob Walker <bob.mt.wya(a)gmail.com>
---
dlls/shell32/shellpath.c | 325 ++++++++++++++++++---------------------
1 file changed, 151 insertions(+), 174 deletions(-)
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
index a551e93aa8..c87c73846b 100644
--- a/dlls/shell32/shellpath.c
+++ b/dlls/shell32/shellpath.c
@@ -58,6 +58,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
static const BOOL is_win64 = sizeof(void *) > sizeof(int);
+static LONG register_shell_folders = 0;
/*
########## Combining and Constructing paths ##########
@@ -4098,6 +4099,15 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
goto end;
}
+ /* Allow function create_homedir_symbolic_link create this directory
+ (or a HOME directory symlink) for us, later in the boot process. */
+ if (!InterlockedCompareExchange(®ister_shell_folders, -1, -1) && (folder == CSIDL_DESKTOPDIRECTORY))
+ {
+ TRACE("Faking successful creation of system directory %s (%#x)\n", debugstr_w(szBuildPath), folder);
+ hr = S_OK;
+ goto end;
+ }
+
/* create directory/directories */
ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
if (ret && ret != ERROR_ALREADY_EXISTS)
@@ -4107,7 +4117,7 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
goto end;
}
- TRACE("Created missing system directory %s\n", debugstr_w(szBuildPath));
+ TRACE("Created missing system directory %s (%#x)\n", debugstr_w(szBuildPath), folder);
end:
TRACE("returning 0x%08x (final path is %s)\n", hr, debugstr_w(szBuildPath));
return hr;
@@ -4385,193 +4395,111 @@ static inline BOOL _SHAppendToUnixPath(char *szBasePath, LPCWSTR pwszSubPath) {
}
/******************************************************************************
- * _SHCreateSymbolicLinks [Internal]
- *
- * Sets up symbol links for various shell folders to point into the users home
- * directory. We do an educated guess about what the user would probably want:
- * - If there is a 'My Documents' directory in $HOME, the user probably wants
- * wine's 'My Documents' to point there. Furthermore, we imply that the user
- * is a Windows lover and has no problem with wine creating 'My Pictures',
- * 'My Music' and 'My Videos' subfolders under '$HOME/My Documents', if those
- * do not already exits. We put appropriate symbolic links in place for those,
- * too.
- * - If there is no 'My Documents' directory in $HOME, we let 'My Documents'
- * point directly to $HOME. We assume the user to be a unix hacker who does not
- * want wine to create anything anywhere besides the .wine directory. So, if
- * there already is a 'My Music' directory in $HOME, we symlink the 'My Music'
- * shell folder to it. But if not, then we check XDG_MUSIC_DIR - "well known"
- * directory, and try to link to that. If that fails, then we symlink to
- * $HOME directly. The same holds fo 'My Pictures' and 'My Videos'.
- * - The Desktop shell folder is symlinked to XDG_DESKTOP_DIR. If that does not
- * exist, then we try '$HOME/Desktop'. If that does not exist, then we leave
- * it alone.
- * ('My Music',... above in fact means LoadString(IDS_MYMUSIC))
+ * create_homedir_symbolic_link [Internal]
+ *
+ * Creates a symbolic link from the current Wineprefix to an appropriate
+ * HOME subdirectory (if one is found).
+ *
+ * Creates 'XXXX' directory in Wineprefix.
+ * Then create a 'My XXXX' symbolic link in Wineprefix:
+ * 1) If '$HOME/XXXX' (IDS directory) exists then target this.
+ * 2) If '$HOME/XXXX' (XDG_XXXX_DIR) exists then target this.
+ * 3) If '$HOME/XXXX' (MacOS XXXX media directory) exists then target this.
+ *
+ * PARAMS
+ * ids_dir [I] Windows Resource Identifier code for current Shell Folder.
+ * csidl_dir [I] Constant Special Item ID List identifier for current Shell Folder.
+ * xdg_dir [I] Full path of external Unix XDG directory corresponding to current Shell Folder.
+ * ws_osx_dir [I] Fallback directory name to use, corresponding to current Shell Folder (OSX specific).
+ *
*/
-static void _SHCreateSymbolicLinks(void)
-{
- UINT aidsMyStuff[] = { IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC }, i;
- const WCHAR* MyOSXStuffW[] = { PicturesW, MoviesW, MusicW };
- int acsidlMyStuff[] = { CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_MYMUSIC };
- static const char * const xdg_dirs[] = { "PICTURES", "VIDEOS", "MUSIC", "DOCUMENTS", "DESKTOP" };
- static const unsigned int num = ARRAY_SIZE(xdg_dirs);
- WCHAR wszTempPath[MAX_PATH];
- char szPersonalTarget[FILENAME_MAX], *pszPersonal;
- char szMyStuffTarget[FILENAME_MAX], *pszMyStuff;
- char szDesktopTarget[FILENAME_MAX], *pszDesktop;
- struct stat statFolder;
- const char *pszHome;
+void create_homedir_symbolic_link(UINT ids_dir,
+ int csidl_dir,
+ const char * xdg_dir,
+ const WCHAR * ws_osx_dir)
+{
+ static const char * env_homedir = NULL;
+ WCHAR ws_temp_path[MAX_PATH];
+ char home_target[FILENAME_MAX], * prefix_dir;
+ struct stat stat_folder, stat_home_folder;
HRESULT hr;
- char ** xdg_results;
- char * xdg_desktop_dir;
-
- /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */
- hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_DEFAULT, wszTempPath);
- if (FAILED(hr)) return;
- pszPersonal = wine_get_unix_file_name(wszTempPath);
- if (!pszPersonal) return;
+ BOOL target_ok;
- hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
- if (FAILED(hr)) xdg_results = NULL;
-
- pszHome = getenv("HOME");
- if (pszHome && !stat(pszHome, &statFolder) && S_ISDIR(statFolder.st_mode))
+ hr = SHGetFolderPathW(NULL, csidl_dir, NULL,
+ SHGFP_TYPE_DEFAULT, ws_temp_path);
+ if (SUCCEEDED(hr))
{
- while (1)
- {
- /* Check if there's already a Wine-specific 'My Documents' folder */
- strcpy(szPersonalTarget, pszHome);
- if (_SHAppendToUnixPath(szPersonalTarget, MAKEINTRESOURCEW(IDS_PERSONAL)) &&
- !stat(szPersonalTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
- {
- /* '$HOME/My Documents' exists. Create 'My Pictures',
- * 'My Videos' and 'My Music' subfolders or fail silently if
- * they already exist.
- */
- for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
- {
- strcpy(szMyStuffTarget, szPersonalTarget);
- if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
- mkdir(szMyStuffTarget, 0777);
- }
- break;
- }
-
- /* Try to point to the XDG Documents folder */
- if (xdg_results && xdg_results[num-2] &&
- !stat(xdg_results[num-2], &statFolder) &&
- S_ISDIR(statFolder.st_mode))
- {
- strcpy(szPersonalTarget, xdg_results[num-2]);
- break;
- }
-
- /* Or the hardcoded / OS X Documents folder */
- strcpy(szPersonalTarget, pszHome);
- if (_SHAppendToUnixPath(szPersonalTarget, DocumentsW) &&
- !stat(szPersonalTarget, &statFolder) &&
- S_ISDIR(statFolder.st_mode))
- break;
-
- /* As a last resort point to $HOME. */
- strcpy(szPersonalTarget, pszHome);
- break;
- }
-
- /* Replace 'My Documents' directory with a symlink or fail silently if not empty. */
- remove(pszPersonal);
- symlink(szPersonalTarget, pszPersonal);
+ TRACE("%s directory already exists\n",
+ debugstr_w(ws_temp_path));
+ return;
+ }
+ else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
+ {
+ hr = SHGetFolderPathW(NULL, csidl_dir|CSIDL_FLAG_CREATE, NULL,
+ SHGFP_TYPE_DEFAULT, ws_temp_path);
+ if (FAILED(hr)) return;
}
else
{
- /* '$HOME' doesn't exist. Create 'My Pictures', 'My Videos' and 'My Music' subdirs
- * in '%USERPROFILE%\\My Documents' or fail silently if they already exist. */
- pszHome = NULL;
- strcpy(szPersonalTarget, pszPersonal);
- for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
- strcpy(szMyStuffTarget, szPersonalTarget);
- if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
- mkdir(szMyStuffTarget, 0777);
- }
+ ERR("Failed to get Wineprefix path corresponding to %d CSIDL\n",
+ csidl_dir);
+ return;
}
- /* Create symbolic links for 'My Pictures', 'My Videos' and 'My Music'. */
- for (i=0; i < ARRAY_SIZE(aidsMyStuff); i++)
+ prefix_dir = wine_get_unix_file_name(ws_temp_path);
+ if (!prefix_dir)
{
- /* Create the current 'My Whatever' folder and get its unix path. */
- hr = SHGetFolderPathW(NULL, acsidlMyStuff[i]|CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_DEFAULT, wszTempPath);
- if (FAILED(hr)) continue;
-
- pszMyStuff = wine_get_unix_file_name(wszTempPath);
- if (!pszMyStuff) continue;
-
- while (1)
- {
- /* Check for the Wine-specific '$HOME/My Documents' subfolder */
- strcpy(szMyStuffTarget, szPersonalTarget);
- if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])) &&
- !stat(szMyStuffTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
- break;
-
- /* Try the XDG_XXX_DIR folder */
- if (xdg_results && xdg_results[i])
- {
- strcpy(szMyStuffTarget, xdg_results[i]);
- break;
- }
-
- /* Or the OS X folder (these are never localized) */
- if (pszHome)
- {
- strcpy(szMyStuffTarget, pszHome);
- if (_SHAppendToUnixPath(szMyStuffTarget, MyOSXStuffW[i]) &&
- !stat(szMyStuffTarget, &statFolder) &&
- S_ISDIR(statFolder.st_mode))
- break;
- }
+ ERR("Failed to get Unix Wineprefix directory for: %s\n",
+ debugstr_w(ws_temp_path));
+ return;
+ }
- /* As a last resort point to the same location as 'My Documents' */
- strcpy(szMyStuffTarget, szPersonalTarget);
- break;
- }
- remove(pszMyStuff);
- symlink(szMyStuffTarget, pszMyStuff);
- heap_free(pszMyStuff);
+ if (!env_homedir) env_homedir = getenv("HOME");
+ if (!(env_homedir
+ && (stat(env_homedir, &stat_home_folder) != 1)
+ && S_ISDIR(stat_home_folder.st_mode)))
+ {
+ if (prefix_dir) heap_free(prefix_dir);
+ return;
}
- /* Last but not least, the Desktop folder */
- if (pszHome)
- strcpy(szDesktopTarget, pszHome);
+ /* Check for:
+ * '$HOME/XXXX' (IDS directory)
+ * or '$HOME/XXXX' (XDG directory)
+ * or '$HOME/XXXX' (MacOS directory)
+ */
+ target_ok = FALSE;
+ strcpy(home_target, env_homedir);
+ if (_SHAppendToUnixPath(home_target, MAKEINTRESOURCEW(ids_dir))
+ && (stat(home_target, &stat_folder) != -1)
+ && S_ISDIR(stat_folder.st_mode))
+ {
+ target_ok = TRUE;
+ }
+ else if (xdg_dir)
+ {
+ strcpy(home_target, xdg_dir);
+ /* Only link to the XDG directory, if it does not point directly
+ * to the user's HOME directory (XDG specification fallback path). */
+ target_ok = TRUE;
+ }
else
- strcpy(szDesktopTarget, pszPersonal);
- heap_free(pszPersonal);
-
- xdg_desktop_dir = xdg_results ? xdg_results[num - 1] : NULL;
- if (xdg_desktop_dir ||
- (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
- !stat(szDesktopTarget, &statFolder) && S_ISDIR(statFolder.st_mode)))
{
- hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, NULL,
- SHGFP_TYPE_DEFAULT, wszTempPath);
- if (SUCCEEDED(hr) && (pszDesktop = wine_get_unix_file_name(wszTempPath)))
- {
- remove(pszDesktop);
- if (xdg_desktop_dir)
- symlink(xdg_desktop_dir, pszDesktop);
- else
- symlink(szDesktopTarget, pszDesktop);
- heap_free(pszDesktop);
- }
+ strcpy(home_target, env_homedir);
+ target_ok = _SHAppendToUnixPath(home_target, ws_osx_dir)
+ && (stat(home_target, &stat_folder) != -1)
+ && S_ISDIR(stat_folder.st_mode);
}
- /* Free resources allocated by XDG_UserDirLookup() */
- if (xdg_results)
+ if (target_ok)
{
- for (i = 0; i < num; i++)
- heap_free(xdg_results[i]);
- heap_free(xdg_results);
+ TRACE("Delete path: %s\n", debugstr_a(prefix_dir));
+ remove(prefix_dir);
+ TRACE("Symlink: %s -> %s\n", debugstr_a(prefix_dir), debugstr_a(home_target));
+ symlink(home_target, prefix_dir);
}
+
+ if (prefix_dir) heap_free(prefix_dir);
}
/******************************************************************************
@@ -6126,15 +6054,61 @@ static void register_system_knownfolders(void)
}
}
+/******************************************************************************
+ * create_homedir_symbolic_links [Internal]
+ *
+ * Parse WINESYMLINK env variable, for each XDG directory argument. To test if symlinking is
+ * enabled for that XDG directory / Wine Profile Folder.
+ * Then calls the function create_homedir_symbolic_link to potentially symlink from a Shell Folder,
+ * in the current Wineprefix, to a subdirectory of the current user's HOME directory.
+ *
+ * PARAMS
+ * xdg_dirnames [I] Pointer to an array of Unix XDG directory names
+ * (without "XDG_" prefix and "_DIR" suffix).
+ * xdg_dir_count [I] Item count of array (above).
+ *
+ */
+static void create_homedir_symbolic_links(const char * const xdg_dirnames[], const UINT xdg_dir_count)
+{
+ char ** xdg_dirs_array;
+ char * xdg_dir;
+ HRESULT hr;
+ UINT i;
+
+ if (!xdg_dirnames) return;
+
+ hr = XDG_UserDirLookup(xdg_dirnames, xdg_dir_count, &xdg_dirs_array);
+ if (FAILED(hr)) xdg_dirs_array = NULL;
+
+ for (i = 0; i < xdg_dir_count; ++i)
+ {
+ xdg_dir = xdg_dirs_array ? xdg_dirs_array[i] : NULL;
+ if (!strcmp(xdg_dirnames[i],"DOCUMENTS"))
+ create_homedir_symbolic_link(IDS_PERSONAL, CSIDL_PERSONAL, xdg_dir, DocumentsW);
+ else if (!strcmp(xdg_dirnames[i],"PICTURES"))
+ create_homedir_symbolic_link(IDS_MYPICTURES, CSIDL_MYPICTURES, xdg_dir, PicturesW);
+ else if (!strcmp(xdg_dirnames[i],"VIDEOS"))
+ create_homedir_symbolic_link(IDS_MYVIDEOS, CSIDL_MYVIDEO, xdg_dir, MoviesW);
+ else if (!strcmp(xdg_dirnames[i],"MUSIC"))
+ create_homedir_symbolic_link(IDS_MYMUSIC, CSIDL_MYMUSIC, xdg_dir, MusicW);
+ else if (!strcmp(xdg_dirnames[i],"DESKTOP"))
+ create_homedir_symbolic_link(IDS_DESKTOPDIRECTORY, CSIDL_DESKTOPDIRECTORY, xdg_dir, DesktopW);
+ else
+ ERR("XDG directory name specifier invalid: %s\n", debugstr_a(xdg_dirnames[i]));
+ if (xdg_dir) heap_free(xdg_dirs_array[i]);
+ }
+ if (xdg_dirs_array) heap_free(xdg_dirs_array);
+}
+
HRESULT SHELL_RegisterShellFolders(void)
{
+ static const char * const xdg_dirnames[] = { "DOCUMENTS", "PICTURES", "VIDEOS", "MUSIC", "DESKTOP" };
+ const UINT xdg_dir_count = 5;
HRESULT hr;
- /* Set up '$HOME' targeted symlinks for 'My Documents', 'My Pictures',
- * 'My Videos', 'My Music' and 'Desktop' in advance, so that the
- * _SHRegister*ShellFolders() functions will find everything nice and clean
- * and thus will not attempt to create them in the profile directory. */
- _SHCreateSymbolicLinks();
+ /* Early setup of symlinks from specific User Shell Folders, in
+ * current Wineprefix, to subdirecties of the user's HOME directory. */
+ create_homedir_symbolic_links(xdg_dirnames, xdg_dir_count);
hr = _SHRegisterUserShellFolders(TRUE);
if (SUCCEEDED(hr))
@@ -6147,5 +6121,8 @@ HRESULT SHELL_RegisterShellFolders(void)
hr = set_folder_attributes();
if (SUCCEEDED(hr))
register_system_knownfolders();
+
+ (void) InterlockedExchange(®ister_shell_folders, 1);
+
return hr;
}
--
2.17.1
June 8, 2018
Re: [PATCH 4/4] wsdapi: Add initial support for reading messages; identify Probe message.
by Owen Rudge
> It's mainly just for consistency. I don't feel particularly strongly
> about it in these cases, however in previous patch-sets I let similar
> things go, only for it later to become apparent that I shouldn't have.
Although these functions are not used in my upcoming patches, I suppose it's feasible that one day they could be used by callers that could make use of the result, so I'll look at amending that.
> It certainly can't be left like this at the end of the patch-set. It
> might be ok (since this isn't exactly a core dll) to include the next
> patch so that the implementation doesn't regress as far as the tests
> are concerned.
OK, I can include the patch that will fix the TODO in the patchset, which I think would likely be the simplest way of resolving this.
Thanks,
Owen
June 8, 2018
Re: [PATCH 4/4] wsdapi: Add initial support for reading messages; identify Probe message.
by Huw Davies
On Thu, Jun 07, 2018 at 09:15:02PM +0100, Owen Rudge wrote:
> On 07/06/2018 08:56, Huw Davies wrote:
>
> >> +static BOOL move_to_element(WS_XML_READER *reader, const char
> *element_name, WS_XML_STRING *uri)
> >
> > return HRESULT
> >
> >> +static BOOL ws_element_to_wsdxml_element(WS_XML_READER *reader,
> IWSDXMLContext *context, WSDXML_ELEMENT *parent_element)
> >
> > and here.
> >
> >> int read_message(const char *xml, int xml_length, WSD_SOAP_MESSAGE
> **out_msg)
> >
> > This is also looking like a good contender to return HRESULT and
> > take an [out] int *type parameter.
>
> As per the previous patch, the HRESULT is not ultimately used, and I can't
> see that there's a great benefit in passing it along. I do understand it for
> the other functions that ultimately return a value to the caller, but these
> functions are all called by the listener thread, and a simple identification
> of the message type is all we require.
>
> If you think it would be beneficial, I can modify these functions to return
> HRESULT, but it would be good to understand the benefits of doing so.
It's mainly just for consistency. I don't feel particularly strongly
about it in these cases, however in previous patch-sets I let similar
things go, only for it later to become apparent that I shouldn't have.
One way to look at it is that conceptually the function has no idea
that the caller cannot use the failure status, so it should return
it regardless.
> >> - ok(any != NULL, "%s: any == NULL\n", debug_prefix);
> >> + todo_wine ok(any != NULL, "%s: any == NULL\n", debug_prefix);
> >
> > You'll need to have a really good reason for doing this. Can you
> > re-order things so you don't break the tests?
>
> This will be fixed in the next patchset; I didn't want to include any more
> code in what's already quite a large patch. There's probably an extra 40 or
> so lines of code needed to avoid this breakage. There's not really a way I
> can re-order this that I can think of.
>
> If preferred though, I can submit the patch that will fix this as part of
> this patchset, so the net result once the set is committed involves no extra
> todos.
It certainly can't be left like this at the end of the patch-set. It
might be ok (since this isn't exactly a core dll) to include the next
patch so that the implementation doesn't regress as far as the tests
are concerned.
Huw.
June 8, 2018
[PATCH 5/5] mstask/tests: Add more tests for IEnumWorkItems interface.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/tests/task_scheduler.c | 75 +++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/dlls/mstask/tests/task_scheduler.c b/dlls/mstask/tests/task_scheduler.c
index d4766382ec..f61022575d 100644
--- a/dlls/mstask/tests/task_scheduler.c
+++ b/dlls/mstask/tests/task_scheduler.c
@@ -212,23 +212,88 @@ done:
static void test_Enum(void)
{
+ static const WCHAR Task1[] = { 'w','i','n','e','t','a','s','k','1',0 };
ITaskScheduler *scheduler;
+ ITask *task;
IEnumWorkItems *tasks;
+ WCHAR **names;
+ ULONG fetched;
HRESULT hr;
hr = CoCreateInstance(&CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER,
&IID_ITaskScheduler, (void **)&scheduler);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ /* cleanup after previous runs */
+ ITaskScheduler_Delete(scheduler, Task1);
+
+ hr = ITaskScheduler_NewWorkItem(scheduler, Task1, &CLSID_CTask, &IID_ITask, (IUnknown **)&task);
+ ok(hr == S_OK, "got %#x\n", hr);
+ hr = ITaskScheduler_AddWorkItem(scheduler, Task1, (IScheduledWorkItem *)task);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ ITask_Release(task);
-if (0) { /* crashes on win2k */
hr = ITaskScheduler_Enum(scheduler, NULL);
- ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-}
+ ok(hr == E_INVALIDARG, "got %#x\n", hr);
hr = ITaskScheduler_Enum(scheduler, &tasks);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ names = (void *)0xdeadbeef;
+ fetched = 0xdeadbeef;
+ hr = IEnumWorkItems_Next(tasks, 0, &names, &fetched);
+ ok(hr == E_INVALIDARG, "got %#x\n", hr);
+ ok(names == (void *)0xdeadbeef, "got %p\n", names);
+ ok(fetched == 0xdeadbeef, "got %#x\n", fetched);
+
+ hr = IEnumWorkItems_Next(tasks, 1, NULL, NULL);
+ ok(hr == E_INVALIDARG, "got %#x\n", hr);
+
+ names = NULL;
+ hr = IEnumWorkItems_Next(tasks, 1, &names, NULL);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(names != NULL, "got NULL\n");
+ ok(names[0] != NULL, "got NULL\n");
+ CoTaskMemFree(names[0]);
+ CoTaskMemFree(names);
+
+ names = (void *)0xdeadbeef;
+ hr = IEnumWorkItems_Next(tasks, 2, &names, NULL);
+ ok(hr == E_INVALIDARG, "got %#x\n", hr);
+ ok(names == (void *)0xdeadbeef, "got %p\n", names);
+
+ hr = IEnumWorkItems_Reset(tasks);
+ ok(hr == S_OK, "got %#x\n", hr);
+
+ names = NULL;
+ fetched = 0xdeadbeef;
+ hr = IEnumWorkItems_Next(tasks, 1, &names, &fetched);
+ ok(hr == S_OK, "got %#x\n", hr);
+ ok(names != NULL, "got NULL\n");
+ ok(names[0] != NULL, "got NULL\n");
+ ok(fetched == 1, "got %u\n", fetched);
+ CoTaskMemFree(names[0]);
+ CoTaskMemFree(names);
+
+ while (IEnumWorkItems_Skip(tasks, 1) == S_OK)
+ /* do nothing*/;
+
+ hr = IEnumWorkItems_Skip(tasks, 1);
+ ok(hr == S_FALSE, "got %#x\n", hr);
+
+ names = (void *)0xdeadbeef;
+ fetched = 0xdeadbeef;
+ hr = IEnumWorkItems_Next(tasks, 1, &names, &fetched);
+ ok(hr == S_FALSE, "got %#x\n", hr);
+ ok(names == NULL, "got %p\n", names);
+ ok(fetched == 0, "got %u\n", fetched);
+
IEnumWorkItems_Release(tasks);
+ hr = ITaskScheduler_Delete(scheduler, Task1);
+ ok(hr == S_OK, "got %#x\n", hr);
+
ITaskScheduler_Release(scheduler);
}
--
2.16.3
June 8, 2018
[PATCH 4/5] mstask: Implement IEnumWorkItems::Skip().
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task_scheduler.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index ccb6d6c078..262dd0c49f 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -206,9 +206,17 @@ static HRESULT WINAPI EnumWorkItems_Next(IEnumWorkItems *iface, ULONG count, LPW
static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count)
{
- EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
- FIXME("(%p)->(%u): stub\n", This, count);
- return E_NOTIMPL;
+ LPWSTR *names;
+ ULONG fetched;
+ HRESULT hr;
+
+ TRACE("(%p)->(%u)\n", iface, count);
+
+ hr = EnumWorkItems_Next(iface, count, &names, &fetched);
+ if (SUCCEEDED(hr))
+ free_list(names, fetched);
+
+ return hr;
}
static HRESULT WINAPI EnumWorkItems_Reset(IEnumWorkItems *iface)
--
2.16.3
June 8, 2018
[PATCH 3/5] mstask: Implement IEnumWorkItems::Reset().
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task_scheduler.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index 8db6e28b5e..ccb6d6c078 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -214,8 +214,16 @@ static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count)
static HRESULT WINAPI EnumWorkItems_Reset(IEnumWorkItems *iface)
{
EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
- FIXME("(%p): stub\n", This);
- return E_NOTIMPL;
+
+ TRACE("(%p)\n", This);
+
+ if (This->handle != INVALID_HANDLE_VALUE)
+ {
+ FindClose(This->handle);
+ This->handle = INVALID_HANDLE_VALUE;
+ }
+
+ return S_OK;
}
static HRESULT WINAPI EnumWorkItems_Clone(IEnumWorkItems *iface, IEnumWorkItems **cloned)
--
2.16.3
June 8, 2018
[PATCH 2/5] mstask: Implement IEnumWorkItems::Next().
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task_scheduler.c | 98 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 96 insertions(+), 2 deletions(-)
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index 416a3218d0..8db6e28b5e 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -43,6 +43,7 @@ typedef struct
{
IEnumWorkItems IEnumWorkItems_iface;
LONG ref;
+ HANDLE handle;
} EnumWorkItemsImpl;
static inline TaskSchedulerImpl *impl_from_ITaskScheduler(ITaskScheduler *iface)
@@ -97,6 +98,8 @@ static ULONG WINAPI EnumWorkItems_Release(IEnumWorkItems *iface)
if (ref == 0)
{
+ if (This->handle != INVALID_HANDLE_VALUE)
+ FindClose(This->handle);
heap_free(This);
InterlockedDecrement(&dll_ref);
}
@@ -104,11 +107,101 @@ static ULONG WINAPI EnumWorkItems_Release(IEnumWorkItems *iface)
return ref;
}
+static void free_list(LPWSTR *list, LONG count)
+{
+ LONG i;
+
+ for (i = 0; i < count; i++)
+ CoTaskMemFree(list[i]);
+
+ CoTaskMemFree(list);
+}
+
+static inline BOOL is_file(const WIN32_FIND_DATAW *data)
+{
+ return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
static HRESULT WINAPI EnumWorkItems_Next(IEnumWorkItems *iface, ULONG count, LPWSTR **names, ULONG *fetched)
{
+ static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\','*',0 };
EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface);
- FIXME("(%p)->(%u %p %p): stub\n", This, count, names, fetched);
- return E_NOTIMPL;
+ WCHAR path[MAX_PATH];
+ WIN32_FIND_DATAW data;
+ ULONG enumerated, dummy;
+ LPWSTR *list;
+ HRESULT hr = S_FALSE;
+
+ TRACE("(%p)->(%u %p %p)\n", This, count, names, fetched);
+
+ if (!count || !names || (!fetched && count > 1)) return E_INVALIDARG;
+
+ if (!fetched) fetched = &dummy;
+
+ *names = NULL;
+ *fetched = 0;
+ enumerated = 0;
+ list = NULL;
+
+ if (This->handle == INVALID_HANDLE_VALUE)
+ {
+ GetWindowsDirectoryW(path, MAX_PATH);
+ lstrcatW(path, tasksW);
+ This->handle = FindFirstFileW(path, &data);
+ if (This->handle == INVALID_HANDLE_VALUE)
+ return S_FALSE;
+ }
+ else
+ {
+ if (!FindNextFileW(This->handle, &data))
+ return S_FALSE;
+ }
+
+ do
+ {
+ if (is_file(&data))
+ {
+ LPWSTR *new_list;
+
+ if (!list)
+ new_list = CoTaskMemAlloc((enumerated + 1) * sizeof(list[0]));
+ else
+ new_list = CoTaskMemRealloc(list, (enumerated + 1) * sizeof(list[0]));
+ if (!new_list)
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ list = new_list;
+
+ list[enumerated] = CoTaskMemAlloc((lstrlenW(data.cFileName) + 1) * sizeof(WCHAR));
+ if (!list[enumerated])
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ lstrcpyW(list[enumerated], data.cFileName);
+ enumerated++;
+
+ if (enumerated >= count)
+ {
+ hr = S_OK;
+ break;
+ }
+ }
+ } while (FindNextFileW(This->handle, &data));
+
+ if (FAILED(hr))
+ free_list(list, enumerated);
+ else
+ {
+ *fetched = enumerated;
+ *names = list;
+ }
+
+ return hr;
}
static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count)
@@ -154,6 +247,7 @@ static HRESULT create_task_enum(IEnumWorkItems **ret)
tasks->IEnumWorkItems_iface.lpVtbl = &EnumWorkItemsVtbl;
tasks->ref = 1;
+ tasks->handle = INVALID_HANDLE_VALUE;
*ret = &tasks->IEnumWorkItems_iface;
InterlockedIncrement(&dll_ref);
--
2.16.3
June 8, 2018
[PATCH 1/5] mstask: Implement ITask::GetExitCode().
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index 266029a58e..7499826937 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -685,8 +685,14 @@ static HRESULT WINAPI MSTASK_ITask_GetExitCode(ITask *iface, DWORD *exit_code)
TRACE("(%p, %p)\n", iface, exit_code);
+ if (This->status == SCHED_S_TASK_NOT_SCHEDULED)
+ {
+ *exit_code = 0;
+ return SCHED_S_TASK_HAS_NOT_RUN;
+ }
+
*exit_code = This->exit_code;
- return SCHED_S_TASK_HAS_NOT_RUN; /* FIXME */
+ return S_OK;
}
static HRESULT WINAPI MSTASK_ITask_SetComment(ITask *iface, LPCWSTR comment)
--
2.16.3
June 8, 2018
[PATCH 3/3] schedsvc: Add support for running missed tasks at the service start.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 24 ++++++++++++++++++++++++
dlls/schedsvc/schedsvc_private.h | 1 +
dlls/schedsvc/svc_main.c | 1 +
3 files changed, 26 insertions(+)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index b5b8317ded..f6ea0f0e23 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -1039,6 +1039,30 @@ void check_task_time(void)
LeaveCriticalSection(&at_job_list_section);
}
+void check_missed_task_time(void)
+{
+ FILETIME current_ft, last_ft;
+ struct job_t *job;
+
+ GetSystemTimeAsFileTime(¤t_ft);
+ FileTimeToLocalFileTime(¤t_ft, ¤t_ft);
+
+ EnterCriticalSection(&at_job_list_section);
+
+ LIST_FOR_EACH_ENTRY(job, &at_job_list, struct job_t, entry)
+ {
+ if (SystemTimeToFileTime(&job->data.last_runtime, &last_ft))
+ {
+ if (job_runs_at(job, &last_ft, ¤t_ft))
+ {
+ run_job(job);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&at_job_list_section);
+}
+
void remove_job(const WCHAR *name)
{
struct job_t *job;
diff --git a/dlls/schedsvc/schedsvc_private.h b/dlls/schedsvc/schedsvc_private.h
index 10892d55ca..117c6f51ed 100644
--- a/dlls/schedsvc/schedsvc_private.h
+++ b/dlls/schedsvc/schedsvc_private.h
@@ -31,6 +31,7 @@ void update_process_status(DWORD pid) DECLSPEC_HIDDEN;
BOOL get_next_runtime(LARGE_INTEGER *rt) DECLSPEC_HIDDEN;
void check_task_time(void) DECLSPEC_HIDDEN;
void load_at_tasks(void) DECLSPEC_HIDDEN;
+void check_missed_task_time(void) DECLSPEC_HIDDEN;
static inline WCHAR *heap_strdupW(const WCHAR *src)
{
diff --git a/dlls/schedsvc/svc_main.c b/dlls/schedsvc/svc_main.c
index 2bba674b07..8e23a049db 100644
--- a/dlls/schedsvc/svc_main.c
+++ b/dlls/schedsvc/svc_main.c
@@ -54,6 +54,7 @@ static DWORD WINAPI tasks_monitor_thread(void *arg)
TRACE("Starting...\n");
load_at_tasks();
+ check_missed_task_time();
htimer = CreateWaitableTimerW(NULL, FALSE, NULL);
if (htimer == NULL)
--
2.16.3
June 8, 2018
[PATCH 2/3] schedsvc: Load job files at the service start up.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 41 ++++++++++++++++++++++++++++++++++++++++
dlls/schedsvc/schedsvc_private.h | 1 +
dlls/schedsvc/svc_main.c | 2 ++
3 files changed, 44 insertions(+)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index 597df34f2a..b5b8317ded 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -623,6 +623,47 @@ void add_job(const WCHAR *name)
LeaveCriticalSection(&at_job_list_section);
}
+static inline BOOL is_file(const WIN32_FIND_DATAW *data)
+{
+ return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+void load_at_tasks(void)
+{
+ static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
+ static const WCHAR allW[] = { '*',0 };
+ WCHAR windir[MAX_PATH], path[MAX_PATH];
+ WIN32_FIND_DATAW data;
+ HANDLE handle;
+
+ GetWindowsDirectoryW(windir, MAX_PATH);
+ lstrcpyW(path, windir);
+ lstrcatW(path, tasksW);
+ lstrcatW(path, allW);
+
+ handle = FindFirstFileW(path, &data);
+ if (handle == INVALID_HANDLE_VALUE) return;
+
+ do
+ {
+ if (is_file(&data))
+ {
+ lstrcpyW(path, windir);
+ lstrcatW(path, tasksW);
+
+ if (lstrlenW(path) + lstrlenW(data.cFileName) < MAX_PATH)
+ {
+ lstrcatW(path, data.cFileName);
+ add_job(path);
+ }
+ else
+ FIXME("too long file name %s\n", debugstr_w(data.cFileName));
+ }
+ } while (FindNextFileW(handle, &data));
+
+ FindClose(handle);
+}
+
static BOOL write_signature(HANDLE hfile)
{
struct
diff --git a/dlls/schedsvc/schedsvc_private.h b/dlls/schedsvc/schedsvc_private.h
index d601030e78..10892d55ca 100644
--- a/dlls/schedsvc/schedsvc_private.h
+++ b/dlls/schedsvc/schedsvc_private.h
@@ -30,6 +30,7 @@ void add_process_to_queue(HANDLE hproc) DECLSPEC_HIDDEN;
void update_process_status(DWORD pid) DECLSPEC_HIDDEN;
BOOL get_next_runtime(LARGE_INTEGER *rt) DECLSPEC_HIDDEN;
void check_task_time(void) DECLSPEC_HIDDEN;
+void load_at_tasks(void) DECLSPEC_HIDDEN;
static inline WCHAR *heap_strdupW(const WCHAR *src)
{
diff --git a/dlls/schedsvc/svc_main.c b/dlls/schedsvc/svc_main.c
index 0dfac818fd..2bba674b07 100644
--- a/dlls/schedsvc/svc_main.c
+++ b/dlls/schedsvc/svc_main.c
@@ -53,6 +53,8 @@ static DWORD WINAPI tasks_monitor_thread(void *arg)
TRACE("Starting...\n");
+ load_at_tasks();
+
htimer = CreateWaitableTimerW(NULL, FALSE, NULL);
if (htimer == NULL)
{
--
2.16.3
June 8, 2018
[PATCH 1/3] schedsvc: Add a sanity check when loading a .job file.
by Dmitry Timoshkov
There was no problem with this patchset, however I had a file in the c:\windows\tasks
directory (dump_job.exe) that was leading to a crash in the job file loading code,
this patch fixes it.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index 91ef3edca0..597df34f2a 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -394,6 +394,12 @@ static BOOL load_job_data(const char *data, DWORD size, struct job_t *info)
TRACE("file_version %04x\n", fixed->file_version);
TRACE("uuid %s\n", wine_dbgstr_guid(&fixed->uuid));
+ if (fixed->file_version != 0x0001)
+ {
+ TRACE("invalid file version\n");
+ return FALSE;
+ }
+
TRACE("name_size_offset %04x\n", fixed->name_size_offset);
TRACE("trigger_offset %04x\n", fixed->trigger_offset);
TRACE("error_retry_count %u\n", fixed->error_retry_count);
--
2.16.3
June 8, 2018
[PATCH] cdosys: Prefer native version.
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/cdosys/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dlls/cdosys/main.c b/dlls/cdosys/main.c
index 1a9affe..4728229 100644
--- a/dlls/cdosys/main.c
+++ b/dlls/cdosys/main.c
@@ -41,6 +41,8 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD reason, LPVOID lpv)
switch (reason)
{
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
case DLL_PROCESS_ATTACH:
instance = hInstDLL;
DisableThreadLibraryCalls(hInstDLL);
--
1.9.1
June 8, 2018
Re: [PATCH] kernel32/tests: Add tests for job object accounting
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39044
Your paranoid android.
=== w1064 (64 bit process) ===
process.c:2532: Test failed: Expected NumberOfAssignedProcesses to be 0 (expected_count) is 1
process.c:2532: Test failed: Expected NumberOfProcessIdsInList to be 0 (expected_count) is 1
process.c:2533: Test failed: Expected basic_accounting.ActiveProcesses to be 0 (active_proc) is 1
June 8, 2018
[PATCH] kernel32/tests: Add tests for job object accounting
by Alistair Leslie-Hughes
From: Mark Jansen <mark.jansen(a)reactos.org>
Signed-off-by: Mark Jansen <mark.jansen(a)reactos.org>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/kernel32/tests/process.c | 95 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index b1a4539..5324894 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2394,6 +2394,69 @@ static void _create_process(int line, const char *command, LPPROCESS_INFORMATION
ok_(__FILE__, line)(ret, "CreateProcess error %u\n", GetLastError());
}
+#define test_assigned_proc(job, ...) _test_assigned_proc(__LINE__, job, __VA_ARGS__)
+static void _test_assigned_proc(int line, HANDLE job, int expected_count, ...)
+{
+ char buf[sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + sizeof(ULONG_PTR) * 20];
+ PJOBOBJECT_BASIC_PROCESS_ID_LIST pid_list = (JOBOBJECT_BASIC_PROCESS_ID_LIST *)buf;
+ DWORD ret_len, pid;
+ va_list valist;
+ int n;
+ BOOL ret;
+
+ memset(buf, 0, sizeof(buf));
+ ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
+ ok_(__FILE__, line)(ret, "QueryInformationJobObject error %u\n", GetLastError());
+ if (ret)
+ {
+ todo_wine_if(expected_count)
+ ok_(__FILE__, line)(expected_count == pid_list->NumberOfAssignedProcesses,
+ "Expected NumberOfAssignedProcesses to be %d (expected_count) is %d\n",
+ expected_count, pid_list->NumberOfAssignedProcesses);
+ todo_wine_if(expected_count)
+ ok_(__FILE__, line)(expected_count == pid_list->NumberOfProcessIdsInList,
+ "Expected NumberOfProcessIdsInList to be %d (expected_count) is %d\n",
+ expected_count, pid_list->NumberOfProcessIdsInList);
+
+ va_start(valist, expected_count);
+ for (n = 0; n < min(expected_count, pid_list->NumberOfProcessIdsInList); ++n)
+ {
+ pid = va_arg(valist, DWORD);
+ ok_(__FILE__, line)(pid == pid_list->ProcessIdList[n],
+ "Expected pid_list->ProcessIdList[%d] to be %x is %lx\n",
+ n, pid, pid_list->ProcessIdList[n]);
+ }
+ va_end(valist);
+ }
+}
+
+#define test_accounting(job, total_proc, active_proc, terminated_proc) _test_accounting(__LINE__, job, total_proc, active_proc, terminated_proc)
+static void _test_accounting(int line, HANDLE job, int total_proc, int active_proc, int terminated_proc)
+{
+ JOBOBJECT_BASIC_ACCOUNTING_INFORMATION basic_accounting;
+ DWORD ret_len;
+ BOOL ret;
+
+ memset(&basic_accounting, 0, sizeof(basic_accounting));
+ ret = pQueryInformationJobObject(job, JobObjectBasicAccountingInformation, &basic_accounting, sizeof(basic_accounting), &ret_len);
+ ok_(__FILE__, line)(ret, "QueryInformationJobObject error %u\n", GetLastError());
+ if (ret)
+ {
+ /* Not going to check process times or page faults */
+
+ todo_wine_if(total_proc)
+ ok_(__FILE__, line)(total_proc == basic_accounting.TotalProcesses,
+ "Expected basic_accounting.TotalProcesses to be %d (total_proc) is %d\n",
+ total_proc, basic_accounting.TotalProcesses);
+ todo_wine_if(active_proc)
+ ok_(__FILE__, line)(active_proc == basic_accounting.ActiveProcesses,
+ "Expected basic_accounting.ActiveProcesses to be %d (active_proc) is %d\n",
+ active_proc, basic_accounting.ActiveProcesses);
+ ok_(__FILE__, line)(terminated_proc == basic_accounting.TotalTerminatedProcesses,
+ "Expected basic_accounting.TotalTerminatedProcesses to be %d (terminated_proc) is %d\n",
+ terminated_proc, basic_accounting.TotalTerminatedProcesses);
+ }
+}
static void test_IsProcessInJob(void)
{
@@ -2420,11 +2483,15 @@ static void test_IsProcessInJob(void)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 0);
+ test_accounting(job, 0, 0, 0);
out = TRUE;
ret = pIsProcessInJob(pi.hProcess, job2, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job2, 0);
+ test_accounting(job2, 0, 0, 0);
out = TRUE;
ret = pIsProcessInJob(pi.hProcess, NULL, &out);
@@ -2438,11 +2505,15 @@ static void test_IsProcessInJob(void)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 1, pi.dwProcessId);
+ test_accounting(job, 1, 1, 0);
out = TRUE;
ret = pIsProcessInJob(pi.hProcess, job2, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job2, 0);
+ test_accounting(job2, 0, 0, 0);
out = FALSE;
ret = pIsProcessInJob(pi.hProcess, NULL, &out);
@@ -2458,6 +2529,8 @@ static void test_IsProcessInJob(void)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 0);
+ test_accounting(job, 1, 0, 0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@@ -2474,11 +2547,15 @@ static void test_TerminateJobObject(void)
job = pCreateJobObjectW(NULL, NULL);
ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
+ test_assigned_proc(job, 0);
+ test_accounting(job, 0, 0, 0);
create_process("wait", &pi);
ret = pAssignProcessToJobObject(job, pi.hProcess);
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+ test_assigned_proc(job, 1, pi.dwProcessId);
+ test_accounting(job, 1, 1, 0);
ret = pTerminateJobObject(job, 123);
ok(ret, "TerminateJobObject error %u\n", GetLastError());
@@ -2486,6 +2563,8 @@ static void test_TerminateJobObject(void)
dwret = WaitForSingleObject(pi.hProcess, 1000);
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
+ test_assigned_proc(job, 0);
+ test_accounting(job, 1, 0, 0);
ret = GetExitCodeProcess(pi.hProcess, &dwret);
ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
@@ -2505,6 +2584,8 @@ static void test_TerminateJobObject(void)
ret = pAssignProcessToJobObject(job, pi.hProcess);
ok(!ret, "AssignProcessToJobObject unexpectedly succeeded\n");
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
+ test_assigned_proc(job, 0);
+ test_accounting(job, 1, 0, 0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@@ -2691,11 +2772,15 @@ static void test_KillOnJobClose(void)
return;
}
ok(ret, "SetInformationJobObject error %u\n", GetLastError());
+ test_assigned_proc(job, 0);
+ test_accounting(job, 0, 0, 0);
create_process("wait", &pi);
ret = pAssignProcessToJobObject(job, pi.hProcess);
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+ test_assigned_proc(job, 1, pi.dwProcessId);
+ test_accounting(job, 1, 1, 0);
CloseHandle(job);
@@ -2799,6 +2884,8 @@ static HANDLE test_AddSelfToJob(void)
ret = pAssignProcessToJobObject(job, GetCurrentProcess());
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+ test_assigned_proc(job, 1, GetCurrentProcessId());
+ test_accounting(job, 1, 1, 0);
return job;
}
@@ -2826,6 +2913,8 @@ static void test_jobInheritance(HANDLE job)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 2, GetCurrentProcessId(), pi.dwProcessId);
+ test_accounting(job, 2, 2, 0);
dwret = WaitForSingleObject(pi.hProcess, 1000);
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
@@ -2854,6 +2943,8 @@ static void test_BreakawayOk(HANDLE job)
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
ok(!ret, "CreateProcessA expected failure\n");
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
+ test_assigned_proc(job, 1, GetCurrentProcessId());
+ test_accounting(job, 2, 1, 0);
if (ret)
{
@@ -2876,6 +2967,8 @@ static void test_BreakawayOk(HANDLE job)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 1, GetCurrentProcessId());
+ test_accounting(job, 2, 1, 0);
dwret = WaitForSingleObject(pi.hProcess, 1000);
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
@@ -2893,6 +2986,8 @@ static void test_BreakawayOk(HANDLE job)
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ test_assigned_proc(job, 1, GetCurrentProcessId());
+ test_accounting(job, 2, 1, 0);
dwret = WaitForSingleObject(pi.hProcess, 1000);
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
--
1.9.1
June 8, 2018
[PATCH] msxml3: Accept NormalizeAttributeValues property
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msxml3/domdoc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index ddd7565..0b917c1 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -73,6 +73,7 @@ static const WCHAR PropValueXSLPatternW[] = {'X','S','L','P','a','t','t','e','r'
static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E','x','t','e','r','n','a','l','s',0};
static const WCHAR PropertyAllowXsltScriptW[] = {'A','l','l','o','w','X','s','l','t','S','c','r','i','p','t',0};
static const WCHAR PropertyAllowDocumentFunctionW[] = {'A','l','l','o','w','D','o','c','u','m','e','n','t','F','u','n','c','t','i','o','n',0};
+static const WCHAR PropertyNormalizeAttributeValuesW[] = {'N','o','r','m','a','l','i','z','e','A','t','t','r','i','b','u','t','e','V','a','l','u','e','s',0};
/* Anything that passes the test_get_ownerDocument()
* tests can go here (data shared between all instances).
@@ -3108,6 +3109,7 @@ static HRESULT WINAPI domdoc_setProperty(
lstrcmpiW(p, PropertyNewParserW) == 0 ||
lstrcmpiW(p, PropertyResolveExternalsW) == 0 ||
lstrcmpiW(p, PropertyAllowXsltScriptW) == 0 ||
+ lstrcmpiW(p, PropertyNormalizeAttributeValuesW) == 0 ||
lstrcmpiW(p, PropertyAllowDocumentFunctionW) == 0)
{
/* Ignore */
--
1.9.1
June 8, 2018
[PATCH] include: Updated enum AutomationIdentifierType values
by Alistair Leslie-Hughes
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
include/uiautomationcoreapi.h | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/uiautomationcoreapi.h b/include/uiautomationcoreapi.h
index 12c509f..1898fe9 100644
--- a/include/uiautomationcoreapi.h
+++ b/include/uiautomationcoreapi.h
@@ -45,7 +45,11 @@ enum AutomationIdentifierType
AutomationIdentifierType_Pattern,
AutomationIdentifierType_Event,
AutomationIdentifierType_ControlType,
- AutomationIdentifierType_TextAttribute
+ AutomationIdentifierType_TextAttribute,
+ AutomationIdentifierType_LandmarkType,
+ AutomationIdentifierType_Annotation,
+ AutomationIdentifierType_Changes,
+ AutomationIdentifierType_Style
};
HRESULT WINAPI UiaGetReservedMixedAttributeValue(IUnknown **value);
--
1.9.1
June 8, 2018
Re: [PATCH 1/3] user32: Make RegisterPointerDeviceNotifications return TRUE to fake success
by Fabian Maurer
Thanks for your feedback,
I updated my GetPointerDevices stub to return FALSE when the application tries to load
devices - now we only success if it queries the number of devices - and then we return 0.
This should be alright.
I made a small testcase to test if windows returns success for
RegisterTouchHitTestingWindow when the system doesn't have a pointer device - it does.
Since there is no touch device, it should be fine if we just never send the message - even if
the window is "registered".
I'd add a testcase, but I'm not sure how to go about that - since it's not guaranteed that
every machine the test runs one has 0 pointer devices. An idea how I could go about that?
Regards,
Fabian Maurer
####################################
#define _WIN32_WINNT _WIN32_WINNT_WIN8
#include <windows.h>
#include <stdio.h>
static LRESULT WINAPI WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
return DefWindowProcA(hwnd, message, wParam, lParam);
}
int main(void)
{
BOOL success;
UINT32 count;
WNDCLASSA cls = {0};
HANDLE hwnd;
POINTER_DEVICE_INFO devices[1];
cls.lpfnWndProc = WndProc;
cls.hInstance = GetModuleHandleA(0);
cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
cls.lpszClassName = "testclass";
RegisterClassA(&cls);
hwnd = CreateWindowA("testclass", "Test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10,
10, 300, 300, NULL, NULL, NULL, 0);
printf("Handle: %p\n", hwnd);
success = GetPointerDevices(&count, NULL);
printf("success: %d, count: %d\n", success, count);
success = RegisterTouchHitTestingWindow(hwnd, TOUCH_HIT_TESTING_CLIENT);
printf("success: %d\n", success);
count = 1;
success = GetPointerDevices(&count, devices);
printf("success: %d, count: %d\n", success, count);
return 0;
}
####################################
output from testbot:
Handle: 00070234
success: 1, count: 0
success: 1
success: 0, count: 1
June 7, 2018
[PATCH v2 3/3] user32: Add RegisterTouchHitTestingWindow stub
by Fabian Maurer
Fixes bug 45303.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/misc.c | 9 +++++++++
dlls/user32/user32.spec | 1 +
2 files changed, 10 insertions(+)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index dfdd599299..b1b2c61aa0 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -863,6 +863,15 @@ BOOL WINAPI GetPointerDevices(UINT32 *device_count, POINTER_DEVICE_INFO *devices
return TRUE;
}
+/**********************************************************************
+ * RegisterTouchHitTestingWindow [USER32.@]
+ */
+BOOL WINAPI RegisterTouchHitTestingWindow(HWND hwnd, ULONG value)
+{
+ FIXME("(%p %d): stub\n", hwnd, value);
+ return TRUE;
+}
+
static const WCHAR imeW[] = {'I','M','E',0};
const struct builtin_class_descr IME_builtin_class =
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 7f652ee722..61e0e4e8cc 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -606,6 +606,7 @@
@ stdcall RegisterShellHookWindow (long)
@ stdcall RegisterSystemThread(long long)
@ stdcall RegisterTasklist (long)
+@ stdcall RegisterTouchHitTestingWindow(long long)
@ stdcall RegisterTouchWindow(long long)
# @ stub RegisterUserApiHook
@ stdcall RegisterWindowMessageA(str)
--
2.17.1
June 7, 2018
[PATCH v2 2/3] user32: Add stub for GetPointerDevices
by Fabian Maurer
Fixes bug 45302.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
...ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec | 2 +-
dlls/user32/misc.c | 18 +++++++++++++++++
dlls/user32/user32.spec | 1 +
include/winuser.h | 20 +++++++++++++++++++
4 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec b/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
index 72cfe3d954..3a043dc9c2 100644
--- a/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
+++ b/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
@@ -4,7 +4,7 @@
@ stub GetPointerDevice
@ stub GetPointerDeviceProperties
@ stub GetPointerDeviceRects
-@ stub GetPointerDevices
+@ stdcall GetPointerDevices(ptr ptr) user32.GetPointerDevices
@ stub GetPointerFrameInfo
@ stub GetPointerFrameInfoHistory
@ stub GetPointerFramePenInfo
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index c3f4030a90..dfdd599299 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -846,6 +846,24 @@ BOOL WINAPI RegisterPointerDeviceNotifications(HWND hwnd, BOOL notifyrange)
return TRUE;
}
+/**********************************************************************
+ * GetPointerDevices [USER32.@]
+ */
+BOOL WINAPI GetPointerDevices(UINT32 *device_count, POINTER_DEVICE_INFO *devices)
+{
+ FIXME("(%p %p): partial stub\n", device_count, devices);
+
+ if (!device_count)
+ return FALSE;
+
+ if (devices)
+ return FALSE;
+
+ *device_count = 0;
+ return TRUE;
+}
+
+
static const WCHAR imeW[] = {'I','M','E',0};
const struct builtin_class_descr IME_builtin_class =
{
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 2e5b203a85..7f652ee722 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -354,6 +354,7 @@
@ stdcall GetOpenClipboardWindow()
@ stdcall GetParent(long)
@ stdcall GetPhysicalCursorPos(ptr)
+@ stdcall GetPointerDevices(ptr ptr)
@ stdcall GetPriorityClipboardFormat(ptr long)
@ stdcall GetProcessDefaultLayout(ptr)
@ stdcall GetProcessDpiAwarenessInternal(long ptr)
diff --git a/include/winuser.h b/include/winuser.h
index 648efbe0e2..f546a4a1f3 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -3357,6 +3357,26 @@ typedef struct tagGESTUREINFO {
} GESTUREINFO, *PGESTUREINFO;
typedef GESTUREINFO const * PCGESTUREINFO;
+#define POINTER_DEVICE_PRODUCT_STRING_MAX 520
+
+typedef enum tagPOINTER_DEVICE_TYPE {
+ POINTER_DEVICE_TYPE_INTEGRATED_PEN = 0x00000001,
+ POINTER_DEVICE_TYPE_EXTERNAL_PEN = 0x00000002,
+ POINTER_DEVICE_TYPE_TOUCH = 0x00000003,
+ POINTER_DEVICE_TYPE_TOUCH_PAD = 0x00000004,
+ POINTER_DEVICE_TYPE_MAX = 0xFFFFFFFF
+} POINTER_DEVICE_TYPE;
+
+typedef struct tagPOINTER_DEVICE_INFO {
+ DWORD displayOrientation;
+ HANDLE device;
+ POINTER_DEVICE_TYPE pointerDeviceType;
+ HMONITOR monitor;
+ ULONG startingCursorId;
+ USHORT maxActiveContacts;
+ WCHAR productString[POINTER_DEVICE_PRODUCT_STRING_MAX];
+} POINTER_DEVICE_INFO;
+
#if defined(_WINGDI_) && !defined(NOGDI)
WINUSERAPI LONG WINAPI ChangeDisplaySettingsA(LPDEVMODEA,DWORD);
WINUSERAPI LONG WINAPI ChangeDisplaySettingsW(LPDEVMODEW,DWORD);
--
2.17.1
June 7, 2018
[PATCH v2 1/3] user32: Make RegisterPointerDeviceNotifications return TRUE to fake success
by Fabian Maurer
Fixes bug 45284.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/misc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index be4b71a4bc..c3f4030a90 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -843,7 +843,7 @@ LONG WINAPI GetDisplayConfigBufferSizes(UINT32 flags, UINT32 *num_path_info, UIN
BOOL WINAPI RegisterPointerDeviceNotifications(HWND hwnd, BOOL notifyrange)
{
FIXME("(%p %d): stub\n", hwnd, notifyrange);
- return FALSE;
+ return TRUE;
}
static const WCHAR imeW[] = {'I','M','E',0};
--
2.17.1
June 7, 2018
[PATCH] mshtml/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/mshtml/tests/dom.c | 59 ++++++++++++++--------------
dlls/mshtml/tests/htmldoc.c | 16 ++++----
dlls/mshtml/tests/htmllocation.c | 4 +-
dlls/mshtml/tests/protocol.c | 78 ++++++++++++++++++--------------------
dlls/mshtml/tests/script.c | 4 +-
dlls/mshtml/tests/xmlhttprequest.c | 4 +-
6 files changed, 80 insertions(+), 85 deletions(-)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index efdd856318..b120b47453 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -2704,7 +2704,7 @@ static void _test_elem_collection(unsigned line, IUnknown *unk,
memset(vs, 0, sizeof(vs));
fetched = 0;
- hres = IEnumVARIANT_Next(enum_var, sizeof(vs)/sizeof(*vs), vs, &fetched);
+ hres = IEnumVARIANT_Next(enum_var, ARRAY_SIZE(vs), vs, &fetched);
ok_(__FILE__,line)(hres == S_FALSE, "Next failed: %08x\n", hres);
ok_(__FILE__,line)(fetched == (len > 2 ? 2 : len), "fetched = %d\n", fetched);
if(len) {
@@ -6188,7 +6188,7 @@ static void _test_language_string(unsigned line, const WCHAR *lang, LCID lcid)
int res;
if(pLCIDToLocaleName) {
- res = pLCIDToLocaleName(lcid, buf, sizeof(buf)/sizeof(WCHAR), 0);
+ res = pLCIDToLocaleName(lcid, buf, ARRAY_SIZE(buf), 0);
ok_(__FILE__,line)(res, "LCIDToLocaleName failed: %u\n", GetLastError());
ok_(__FILE__,line)(!lstrcmpW(lang, buf), "lang = %s, expected %s\n", wine_dbgstr_w(lang), wine_dbgstr_w(buf));
}else {
@@ -6486,17 +6486,17 @@ static void test_unique_id(IHTMLDocument2 *doc, IHTMLElement *elem)
hres = IHTMLDocument3_get_uniqueID(doc3, &id);
ok(hres == S_OK, "get_uniqueID failed: %08x\n", hres);
- ok(SysStringLen(id) >= sizeof(prefixW)/sizeof(*prefixW), "id %s too short\n", wine_dbgstr_w(id));
+ ok(SysStringLen(id) >= ARRAY_SIZE(prefixW), "id %s too short\n", wine_dbgstr_w(id));
hres = IHTMLDocument3_get_uniqueID(doc3, &id2);
ok(hres == S_OK, "get_uniqueID failed: %08x\n", hres);
- ok(SysStringLen(id2) >= sizeof(prefixW)/sizeof(*prefixW), "id %s too short\n", wine_dbgstr_w(id2));
+ ok(SysStringLen(id2) >= ARRAY_SIZE(prefixW), "id %s too short\n", wine_dbgstr_w(id2));
ok(lstrcmpW(id, id2), "same unique ids %s\n", wine_dbgstr_w(id));
- id[sizeof(prefixW)/sizeof(*prefixW)-1] = 0;
+ id[ARRAY_SIZE(prefixW)-1] = 0;
ok(!lstrcmpW(id, prefixW), "unexpected prefix %s\n", wine_dbgstr_w(id));
- id2[sizeof(prefixW)/sizeof(*prefixW)-1] = 0;
+ id2[ARRAY_SIZE(prefixW)-1] = 0;
ok(!lstrcmpW(id2, prefixW), "unexpected prefix %s\n", wine_dbgstr_w(id2));
SysFreeString(id);
@@ -7267,7 +7267,7 @@ static void test_tr_elem(IHTMLElement *elem)
ok(hres == S_OK, "get_cells failed: %08x\n", hres);
ok(col != NULL, "get_cells returned NULL\n");
- test_elem_collection((IUnknown*)col, cell_types, sizeof(cell_types)/sizeof(*cell_types));
+ test_elem_collection((IUnknown*)col, cell_types, ARRAY_SIZE(cell_types));
IHTMLElementCollection_Release(col);
bstr = a2bstr("left");
@@ -7591,14 +7591,14 @@ static void test_table_elem(IHTMLElement *elem)
ok(hres == S_OK, "get_rows failed: %08x\n", hres);
ok(col != NULL, "get_rows returned NULL\n");
- test_elem_collection((IUnknown*)col, row_types, sizeof(row_types)/sizeof(*row_types));
+ test_elem_collection((IUnknown*)col, row_types, ARRAY_SIZE(row_types));
IHTMLElementCollection_Release(col);
- test_elem_all((IUnknown*)table, all_types, sizeof(all_types)/sizeof(*all_types));
+ test_elem_all((IUnknown*)table, all_types, ARRAY_SIZE(all_types));
node = clone_node((IUnknown*)table, VARIANT_TRUE);
test_elem_tag((IUnknown*)node, "TABLE");
- test_elem_all((IUnknown*)node, all_types, sizeof(all_types)/sizeof(*all_types));
+ test_elem_all((IUnknown*)node, all_types, ARRAY_SIZE(all_types));
IHTMLDOMNode_Release(node);
node = clone_node((IUnknown*)table, VARIANT_FALSE);
@@ -7611,7 +7611,7 @@ static void test_table_elem(IHTMLElement *elem)
ok(hres == S_OK, "get_tBodies failed: %08x\n", hres);
ok(col != NULL, "get_tBodies returned NULL\n");
- test_elem_collection((IUnknown*)col, tbodies_types, sizeof(tbodies_types)/sizeof(*tbodies_types));
+ test_elem_collection((IUnknown*)col, tbodies_types, ARRAY_SIZE(tbodies_types));
IHTMLElementCollection_Release(col);
test_table_cell_spacing(table, NULL);
@@ -7994,7 +7994,7 @@ static void test_iframe_elem(IHTMLElement *elem)
hres = IHTMLDocument2_get_all(content_doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
IHTMLElementCollection_Release(col);
body = doc_get_body(content_doc);
@@ -8302,7 +8302,7 @@ static void test_elemsbyclass(IHTMLElement *div)
hres = IHTMLElement6_getElementsByClassName(elem, str, &collection);
ok(hres == S_OK, "getElementsByClassName failed: %08x\n", hres);
ok(collection != NULL, "collection == NULL\n");
- test_elem_collection((IUnknown*)collection, types, sizeof(types)/sizeof(*types));
+ test_elem_collection((IUnknown*)collection, types, ARRAY_SIZE(types));
IHTMLElementCollection_Release(collection);
SysFreeString(str);
@@ -8364,8 +8364,8 @@ static void test_elems(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
- test_elem_col_item(col, "x", item_types, sizeof(item_types)/sizeof(item_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
+ test_elem_col_item(col, "x", item_types, ARRAY_SIZE(item_types));
elem = get_elem_col_item_idx(col, 0);
test_elem_source_index(elem, 0);
@@ -8419,7 +8419,7 @@ static void test_elems(IHTMLDocument2 *doc)
elem = get_doc_elem(doc);
test_elem_istextedit(elem, VARIANT_FALSE);
- test_elem_all((IUnknown*)elem, all_types+1, sizeof(all_types)/sizeof(all_types[0])-1);
+ test_elem_all((IUnknown*)elem, all_types+1, ARRAY_SIZE(all_types)-1);
IHTMLElement_Release(elem);
get_elem_by_id(doc, "xxx", FALSE);
@@ -8964,7 +8964,7 @@ static void test_elems(IHTMLDocument2 *doc)
static const elem_type_t select_types[] = { ET_OPTION, ET_OPTION, ET_OPTION };
test_select_put_length((IUnknown*)elem, 3);
- test_elem_all((IUnknown*)elem, select_types, sizeof(select_types)/sizeof(*select_types));
+ test_elem_all((IUnknown*)elem, select_types, ARRAY_SIZE(select_types));
test_select_put_length((IUnknown*)elem, 1);
test_elem_all((IUnknown*)elem, select_types, 1);
IHTMLElement_Release(elem);
@@ -9204,7 +9204,7 @@ static void test_elem_names(IHTMLDocument2 *doc)
test_elem_set_innerhtml((IUnknown*)body,
"<input name=\"test\"><a name=\"test\"></a><a name=\"xxx\"></a><div id=\"test\"></div>");
col = doc_get_elems_by_name(doc, "test");
- test_elem_collection((IUnknown*)col, test1_types, sizeof(test1_types)/sizeof(*test1_types));
+ test_elem_collection((IUnknown*)col, test1_types, ARRAY_SIZE(test1_types));
IHTMLElementCollection_Release(col);
col = doc_get_elems_by_name(doc, "yyy");
@@ -9252,7 +9252,7 @@ static void test_elems2(IHTMLDocument2 *doc)
elem2 = get_doc_elem_by_id(doc, "innerid");
ok(elem2 != NULL, "elem2 == NULL\n");
test_elem_set_outerhtml((IUnknown*)elem2, "<br><a href=\"about:blank\" id=\"aid\">a</a>");
- test_elem_all((IUnknown*)div, outer_types, sizeof(outer_types)/sizeof(*outer_types));
+ test_elem_all((IUnknown*)div, outer_types, ARRAY_SIZE(outer_types));
IHTMLElement_Release(elem2);
elem2 = get_doc_elem_by_id(doc, "aid");
@@ -9407,8 +9407,7 @@ static void test_form_element(IHTMLDocument2 *doc, IHTMLElement *parent)
test_form_put_encoding((IUnknown*)elem, S_OK, "multipart/form-data");
test_form_put_encoding((IUnknown*)elem, E_INVALIDARG, "image/png");
test_form_encoding((IUnknown*)elem, "multipart/form-data");
- test_form_elements((IUnknown*)elem, elems_textarea_input,
- sizeof(elems_textarea_input)/sizeof(*elems_textarea_input));
+ test_form_elements((IUnknown*)elem, elems_textarea_input, ARRAY_SIZE(elems_textarea_input));
test_form_reset((IUnknown*)elem);
test_form_target((IUnknown*)elem);
@@ -9495,7 +9494,7 @@ static void test_create_elems(IHTMLDocument2 *doc)
hres = IHTMLElement_get_all(body, &disp);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)disp, types1, sizeof(types1)/sizeof(types1[0]));
+ test_elem_collection((IUnknown*)disp, types1, ARRAY_SIZE(types1));
IDispatch_Release(disp);
test_node_remove_child((IUnknown*)body, node);
@@ -9636,12 +9635,12 @@ static void test_noscript(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
IHTMLElementCollection_Release(col);
body = doc_get_body(doc);
test_elem_set_innerhtml((IUnknown*)body, "<div>test</div><noscript><a href=\"about:blank\">A</a></noscript>");
- test_elem_all((IUnknown*)body, body_all_types, sizeof(body_all_types)/sizeof(*body_all_types));
+ test_elem_all((IUnknown*)body, body_all_types, ARRAY_SIZE(body_all_types));
IHTMLElement_Release(body);
}
@@ -9703,12 +9702,12 @@ static void test_create_stylesheet(IHTMLDocument2 *doc)
ET_DIV
};
- test_doc_all(doc, all_types, sizeof(all_types)/sizeof(*all_types));
+ test_doc_all(doc, all_types, ARRAY_SIZE(all_types));
hres = IHTMLDocument2_createStyleSheet(doc, NULL, -1, &stylesheet);
ok(hres == S_OK, "createStyleSheet failed: %08x\n", hres);
- test_doc_all(doc, all_types2, sizeof(all_types2)/sizeof(*all_types2));
+ test_doc_all(doc, all_types2, ARRAY_SIZE(all_types2));
doc_elem = get_doc_elem(doc);
@@ -9773,7 +9772,7 @@ static void test_indent(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
IHTMLElementCollection_Release(col);
range = test_create_body_range(doc);
@@ -9782,7 +9781,7 @@ static void test_indent(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, indent_types, sizeof(indent_types)/sizeof(indent_types[0]));
+ test_elem_collection((IUnknown*)col, indent_types, ARRAY_SIZE(indent_types));
IHTMLElementCollection_Release(col);
}
@@ -9801,7 +9800,7 @@ static void test_cond_comment(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
IHTMLElementCollection_Release(col);
}
@@ -10116,7 +10115,7 @@ static void test_docfrag(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_all(doc, &col);
ok(hres == S_OK, "get_all failed: %08x\n", hres);
- test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+ test_elem_collection((IUnknown*)col, all_types, ARRAY_SIZE(all_types));
IHTMLElementCollection_Release(col);
div = test_create_elem(frag, "div");
diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c
index a03d0105a9..1f40fed4e7 100644
--- a/dlls/mshtml/tests/htmldoc.c
+++ b/dlls/mshtml/tests/htmldoc.c
@@ -6456,7 +6456,7 @@ static void test_MSHTML_QueryStatus(IHTMLDocument2 *doc, DWORD cmdf)
static void test_OleCommandTarget(IHTMLDocument2 *doc)
{
IOleCommandTarget *cmdtrg;
- OLECMD cmds[sizeof(expect_cmds)/sizeof(*expect_cmds)-1];
+ OLECMD cmds[ARRAY_SIZE(expect_cmds)-1];
int i;
HRESULT hres;
@@ -6465,19 +6465,19 @@ static void test_OleCommandTarget(IHTMLDocument2 *doc)
if(FAILED(hres))
return;
- for(i=0; i < sizeof(cmds)/sizeof(*cmds); i++) {
+ for(i=0; i < ARRAY_SIZE(cmds); i++) {
cmds[i].cmdID = i+1;
cmds[i].cmdf = 0xf0f0;
}
SET_EXPECT(QueryStatus_OPEN);
SET_EXPECT(QueryStatus_NEW);
- hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, sizeof(cmds)/sizeof(cmds[0]), cmds, NULL);
+ hres = IOleCommandTarget_QueryStatus(cmdtrg, NULL, ARRAY_SIZE(cmds), cmds, NULL);
ok(hres == S_OK, "QueryStatus failed: %08x\n", hres);
CHECK_CALLED(QueryStatus_OPEN);
CHECK_CALLED(QueryStatus_NEW);
- for(i=0; i < sizeof(cmds)/sizeof(*cmds); i++) {
+ for(i=0; i < ARRAY_SIZE(cmds); i++) {
ok(cmds[i].cmdID == i+1, "cmds[%d].cmdID canged to %x\n", i, cmds[i].cmdID);
if(i+1 == OLECMDID_FIND)
continue;
@@ -7332,7 +7332,7 @@ static void test_enum_objects(IOleContainer *container)
ok(enum_unknown != NULL, "enum_unknown == NULL\n");
fetched = 0xdeadbeef;
- hres = IEnumUnknown_Next(enum_unknown, sizeof(buf)/sizeof(*buf), buf, &fetched);
+ hres = IEnumUnknown_Next(enum_unknown, ARRAY_SIZE(buf), buf, &fetched);
ok(hres == S_FALSE, "Next returned %08x\n", hres);
ok(!fetched, "fetched = %d\n", fetched);
ok(buf[0] == (void*)0xdeadbeef, "buf[0] = %p\n", buf[0]);
@@ -7764,7 +7764,7 @@ static void test_cookies(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_cookie(doc, &str);
ok(hres == S_OK, "get_cookie failed: %08x\n", hres);
if(str) {
- size = sizeof(buf)/sizeof(WCHAR);
+ size = ARRAY_SIZE(buf);
b = InternetGetCookieW(http_urlW, NULL, buf, &size);
ok(b, "InternetGetCookieW failed: %08x\n", GetLastError());
ok(!lstrcmpW(buf, str), "cookie = %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buf));
@@ -7779,7 +7779,7 @@ static void test_cookies(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_cookie(doc, &str2);
ok(hres == S_OK, "get_cookie failed: %08x\n", hres);
ok(str2 != NULL, "cookie = NULL\n");
- size = sizeof(buf)/sizeof(WCHAR);
+ size = ARRAY_SIZE(buf);
b = InternetGetCookieW(http_urlW, NULL, buf, &size);
ok(b, "InternetGetCookieW failed: %08x\n", GetLastError());
ok(!lstrcmpW(buf, str2), "cookie = %s, expected %s\n", wine_dbgstr_w(str2), wine_dbgstr_w(buf));
@@ -7796,7 +7796,7 @@ static void test_cookies(IHTMLDocument2 *doc)
hres = IHTMLDocument2_get_cookie(doc, &str2);
ok(hres == S_OK, "get_cookie failed: %08x\n", hres);
ok(str2 != NULL, "cookie = NULL\n");
- size = sizeof(buf)/sizeof(WCHAR);
+ size = ARRAY_SIZE(buf);
b = InternetGetCookieW(http_urlW, NULL, buf, &size);
ok(b, "InternetGetCookieW failed: %08x\n", GetLastError());
ok(!lstrcmpW(buf, str2), "cookie = %s, expected %s\n", wine_dbgstr_w(str2), wine_dbgstr_w(buf));
diff --git a/dlls/mshtml/tests/htmllocation.c b/dlls/mshtml/tests/htmllocation.c
index 458960a8d3..4781de9681 100644
--- a/dlls/mshtml/tests/htmllocation.c
+++ b/dlls/mshtml/tests/htmllocation.c
@@ -300,7 +300,7 @@ static void perform_test(const struct location_test* test)
if(FAILED(hres))
return;
- MultiByteToWideChar(CP_ACP, 0, test->url, -1, url, sizeof(url)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, test->url, -1, url, ARRAY_SIZE(url));
hres = CreateURLMoniker(NULL, url, &url_mon);
ok(hres == S_OK, "%s: CreateURLMoniker failed: 0x%08x\n", test->name, hres);
if(FAILED(hres)){
@@ -381,7 +381,7 @@ START_TEST(htmllocation)
CoInitialize(NULL);
- for(i=0; i < sizeof(location_tests)/sizeof(*location_tests); i++)
+ for(i=0; i < ARRAY_SIZE(location_tests); i++)
perform_test(location_tests+i);
CoUninitialize();
diff --git a/dlls/mshtml/tests/protocol.c b/dlls/mshtml/tests/protocol.c
index 62bda5c75f..80e356344d 100644
--- a/dlls/mshtml/tests/protocol.c
+++ b/dlls/mshtml/tests/protocol.c
@@ -271,7 +271,7 @@ static void test_res_url(const char *url_suffix)
HRESULT hres;
memcpy(url, res_url_base, res_url_base_len*sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, url_suffix, -1, url+res_url_base_len, sizeof(url)/sizeof(WCHAR)-res_url_base_len);
+ MultiByteToWideChar(CP_ACP, 0, url_suffix, -1, url+res_url_base_len, ARRAY_SIZE(url)-res_url_base_len);
hres = CoCreateInstance(&CLSID_ResProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void**)&protocol);
ok(hres == S_OK, "Could not create ResProtocol instance: %08x\n", hres);
@@ -296,13 +296,13 @@ static void res_sec_url_cmp(LPCWSTR url, DWORD size, LPCWSTR file)
static const WCHAR fileW[] = {'f','i','l','e',':','/','/'};
- if(size < sizeof(fileW)/sizeof(WCHAR) || memcmp(url, fileW, sizeof(fileW))) {
+ if(size < ARRAY_SIZE(fileW) || memcmp(url, fileW, sizeof(fileW))) {
ok(0, "wrong URL protocol\n");
return;
}
SetLastError(0xdeadbeef);
- len = SearchPathW(NULL, file, NULL, sizeof(buf)/sizeof(WCHAR), buf, NULL);
+ len = SearchPathW(NULL, file, NULL, ARRAY_SIZE(buf), buf, NULL);
if(!len) {
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
win_skip("SearchPathW is not implemented\n");
@@ -311,9 +311,9 @@ static void res_sec_url_cmp(LPCWSTR url, DWORD size, LPCWSTR file)
return;
}
- len += sizeof(fileW)/sizeof(WCHAR)+1;
+ len += ARRAY_SIZE(fileW)+1;
ok(len == size, "wrong size %u, expected %u\n", size, len);
- ok(!lstrcmpW(url + sizeof(fileW)/sizeof(WCHAR), buf), "wrong file part %s\n", wine_dbgstr_w(url));
+ ok(!lstrcmpW(url + ARRAY_SIZE(fileW), buf), "wrong file part %s\n", wine_dbgstr_w(url));
}
static void test_res_protocol(void)
@@ -355,14 +355,14 @@ static void test_res_protocol(void)
for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
}
}
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
res_sec_url_cmp(buf, size, mshtml_dllW);
ok(size == lstrlenW(buf)+1, "size = %d\n", size);
@@ -381,36 +381,32 @@ static void test_res_protocol(void)
ok(size == expected_size, "size = %d\n", size);
hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == MK_E_SYNTAX || hres == E_INVALIDARG,
"ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url5, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url6, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
size = 0xdeadbeef;
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
- ok(size == sizeof(blank_url)/sizeof(WCHAR) ||
- size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
- "size=%d\n", size);
+ ok(size == ARRAY_SIZE(blank_url) || size == ARRAY_SIZE(buf), /* IE8 */ "size=%d\n", size);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
- ok(size == sizeof(wrong_url1)/sizeof(WCHAR) ||
- size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
- "size=%d\n", size);
+ ok(size == ARRAY_SIZE(wrong_url1) || size == ARRAY_SIZE(buf), /* IE8 */ "size=%d\n", size);
if (0)
{
@@ -418,40 +414,40 @@ static void test_res_protocol(void)
size = 0xdeadbeef;
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
ok(size == 1, "size=%u, expected 1\n", size);
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), NULL, 0);
+ ARRAY_SIZE(buf), NULL, 0);
ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), NULL, 0);
+ ARRAY_SIZE(buf), NULL, 0);
ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
}
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
ok(buf[0] == '?', "buf changed\n");
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
- 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ 0, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
- URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ URL_FILE_USE_PATHURL, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
@@ -693,14 +689,14 @@ static void test_about_protocol(void)
for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, i, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
}
}
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
ok(!lstrcmpW(about_blank_url, buf), "buf != blank_url\n");
@@ -711,7 +707,7 @@ static void test_about_protocol(void)
ok(size == 12, "size = %d\n", size);
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_test_url, PARSE_SECURITY_URL, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
ok(!lstrcmpW(about_test_url, buf), "buf != test_url\n");
ok(size == 11, "size = %d\n", size);
@@ -719,13 +715,12 @@ static void test_about_protocol(void)
size = 0xdeadbeef;
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?' || buf[0] == '\0' /* Win10 */,
"Expected buf to be unchanged or empty, got %s\n",
wine_dbgstr_w(buf));
- ok(size == sizeof(about_blank_url)/sizeof(WCHAR) ||
- size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
+ ok(size == ARRAY_SIZE(about_blank_url) || size == ARRAY_SIZE(buf), /* IE8 */
"size=%d\n", size);
if (0)
@@ -734,44 +729,44 @@ static void test_about_protocol(void)
size = 0xdeadbeef;
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
ok(size == 1, "size=%u, expected 1\n", size);
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), NULL, 0);
+ ARRAY_SIZE(buf), NULL, 0);
ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
buf[0] = '?';
hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
- sizeof(buf)/sizeof(buf[0]), NULL, 0);
+ ARRAY_SIZE(buf), NULL, 0);
ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
ok(buf[0] == '?', "buf changed\n");
}
hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_UNESCAPE+1, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
- 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ 0, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
- URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ URL_FILE_USE_PATHURL, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, NULL, NULL,
- URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ URL_FILE_USE_PATHURL, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
@@ -870,20 +865,20 @@ static void test_javascript_protocol(void)
for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
hres = IInternetProtocolInfo_ParseUrl(protocol_info, javascript_test_url, i, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
}
}
hres = IInternetProtocolInfo_ParseUrl(protocol_info, javascript_test_url, PARSE_UNESCAPE+1, 0, buf,
- sizeof(buf)/sizeof(buf[0]), &size, 0);
+ ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_DEFAULT_ACTION,
"ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
size = 0xdeadbeef;
hres = IInternetProtocolInfo_CombineUrl(protocol_info, javascript_test_url, javascript_test_url,
- 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
+ 0, buf, ARRAY_SIZE(buf), &size, 0);
ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
ok(size == 0xdeadbeef, "size=%d\n", size);
@@ -1007,7 +1002,8 @@ static void test_com_aggregation(const CLSID *clsid)
START_TEST(protocol)
{
- res_url_base_len = 6 + GetModuleFileNameW(NULL, res_url_base + 6 /* strlen("res://") */, sizeof(res_url_base)/sizeof(WCHAR)-6);
+ res_url_base_len = 6 + GetModuleFileNameW(NULL, res_url_base + 6 /* strlen("res://") */,
+ ARRAY_SIZE(res_url_base)-6);
OleInitialize(NULL);
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index 3decb8690b..2e13f9b236 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -3378,9 +3378,9 @@ static void run_js_script(const char *test_name)
trace("running %s...\n", test_name);
ptr = url + lstrlenW(url);
- ptr += GetModuleFileNameW(NULL, ptr, url + sizeof(url)/sizeof(WCHAR) - ptr);
+ ptr += GetModuleFileNameW(NULL, ptr, url + ARRAY_SIZE(url) - ptr);
*ptr++ = '/';
- MultiByteToWideChar(CP_ACP, 0, test_name, -1, ptr, url + sizeof(url)/sizeof(WCHAR) - ptr);
+ MultiByteToWideChar(CP_ACP, 0, test_name, -1, ptr, url + ARRAY_SIZE(url) - ptr);
hres = CreateURLMoniker(NULL, url, &mon);
ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c
index 733987fce0..2be817914d 100644
--- a/dlls/mshtml/tests/xmlhttprequest.c
+++ b/dlls/mshtml/tests/xmlhttprequest.c
@@ -747,7 +747,7 @@ static void test_sync_xhr(IHTMLDocument2 *doc, const char *xml_url, const char *
SysFreeString(text);
if(expect_text)
- test_header(expect_headers, sizeof(expect_headers)/sizeof(expect_headers[0]));
+ test_header(expect_headers, ARRAY_SIZE(expect_headers));
val = 0xdeadbeef;
hres = IHTMLXMLHttpRequest_get_status(xhr, &val);
@@ -905,7 +905,7 @@ static void test_async_xhr(IHTMLDocument2 *doc, const char *xml_url, const char
SysFreeString(text);
if(expect_text)
- test_header(expect_headers, sizeof(expect_headers)/sizeof(expect_headers[0]));
+ test_header(expect_headers, ARRAY_SIZE(expect_headers));
val = 0xdeadbeef;
hres = IHTMLXMLHttpRequest_get_status(xhr, &val);
--
2.14.4
June 7, 2018
[PATCH] dinput/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/dinput/tests/device.c | 4 ++--
dlls/dinput/tests/dinput.c | 20 ++++++++++----------
dlls/dinput/tests/joystick.c | 8 +++-----
dlls/dinput/tests/keyboard.c | 10 +++++-----
4 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/dlls/dinput/tests/device.c b/dlls/dinput/tests/device.c
index 74940248ff..fa9b6f1436 100644
--- a/dlls/dinput/tests/device.c
+++ b/dlls/dinput/tests/device.c
@@ -51,7 +51,7 @@ static const DIDATAFORMAT data_format = {
sizeof(DIOBJECTDATAFORMAT),
DIDF_ABSAXIS,
32,
- sizeof(obj_data_format) / sizeof(obj_data_format[0]),
+ ARRAY_SIZE(obj_data_format),
(LPDIOBJECTDATAFORMAT)obj_data_format
};
@@ -94,7 +94,7 @@ static void test_object_info(IDirectInputDeviceA *device, HWND hwnd)
ok(cnt == cnt1, "Enum count changed from %d to %d\n", cnt, cnt1);
/* Testing EnumObjects with different types of device objects */
- for (type_index=0; type_index < sizeof(obj_types)/sizeof(obj_types[0]); type_index++)
+ for (type_index=0; type_index < ARRAY_SIZE(obj_types); type_index++)
{
hr = IDirectInputDevice_EnumObjects(device, enum_type_callback, &obj_types[type_index], obj_types[type_index]);
ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
diff --git a/dlls/dinput/tests/dinput.c b/dlls/dinput/tests/dinput.c
index a5f7c0cfce..7e2da9ff32 100644
--- a/dlls/dinput/tests/dinput.c
+++ b/dlls/dinput/tests/dinput.c
@@ -106,7 +106,7 @@ static void test_preinitialization(void)
return;
}
- for (i = 0; i < sizeof(create_device_tests)/sizeof(create_device_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(create_device_tests); i++)
{
if (create_device_tests[i].pdev) pDID = (void *)0xdeadbeef;
hr = IDirectInput_CreateDevice(pDI, create_device_tests[i].rguid,
@@ -117,7 +117,7 @@ static void test_preinitialization(void)
ok(pDID == NULL, "[%d] Output interface pointer is %p\n", i, pDID);
}
- for (i = 0; i < sizeof(enum_devices_tests)/sizeof(enum_devices_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(enum_devices_tests); i++)
{
hr = IDirectInput_EnumDevices(pDI, enum_devices_tests[i].dwDevType,
enum_devices_tests[i].lpCallback,
@@ -217,7 +217,7 @@ static void test_DirectInputCreateEx(void)
return;
}
- for (i = 0; i < sizeof(invalid_param_list)/sizeof(invalid_param_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(invalid_param_list); i++)
{
if (invalid_param_list[i].ppdi) pUnk = (void *)0xdeadbeef;
hr = pDirectInputCreateEx(invalid_param_list[i].hinst ? hInstance : NULL,
@@ -230,7 +230,7 @@ static void test_DirectInputCreateEx(void)
ok(pUnk == invalid_param_list[i].expected_ppdi, "[%d] Output interface pointer is %p\n", i, pUnk);
}
- for (i = 0; i < sizeof(no_interface_list)/sizeof(no_interface_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
{
pUnk = (void *)0xdeadbeef;
hr = pDirectInputCreateEx(hInstance, DIRECTINPUT_VERSION, no_interface_list[i], (void **)&pUnk, NULL);
@@ -238,7 +238,7 @@ static void test_DirectInputCreateEx(void)
ok(pUnk == (void *)0xdeadbeef, "[%d] Output interface pointer is %p\n", i, pUnk);
}
- for (i = 0; i < sizeof(iid_list)/sizeof(iid_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iid_list); i++)
{
pUnk = NULL;
hr = pDirectInputCreateEx(hInstance, DIRECTINPUT_VERSION, iid_list[i], (void **)&pUnk, NULL);
@@ -249,9 +249,9 @@ static void test_DirectInputCreateEx(void)
}
/* Examine combinations of requested interfaces and version numbers. */
- for (i = 0; i < sizeof(directinput_version_list)/sizeof(directinput_version_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(directinput_version_list); i++)
{
- for (j = 0; j < sizeof(iid_list)/sizeof(iid_list[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(iid_list); j++)
{
pUnk = NULL;
hr = pDirectInputCreateEx(hInstance, directinput_version_list[i], iid_list[j], (void **)&pUnk, NULL);
@@ -311,7 +311,7 @@ static void test_QueryInterface(void)
hr = IDirectInput_QueryInterface(pDI, &IID_IUnknown, NULL);
ok(hr == E_POINTER, "IDirectInput_QueryInterface returned 0x%08x\n", hr);
- for (i = 0; i < sizeof(iid_list)/sizeof(iid_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iid_list); i++)
{
pUnk = NULL;
hr = IDirectInput_QueryInterface(pDI, iid_list[i], (void **)&pUnk);
@@ -320,7 +320,7 @@ static void test_QueryInterface(void)
if (pUnk) IUnknown_Release(pUnk);
}
- for (i = 0; i < sizeof(no_interface_list)/sizeof(no_interface_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
{
pUnk = (void *)0xdeadbeef;
hr = IDirectInput_QueryInterface(pDI, no_interface_list[i].riid, (void **)&pUnk);
@@ -512,7 +512,7 @@ static void test_Initialize(void)
hr = IDirectInput_Initialize(pDI, hInstance, 0xcafe);
ok(hr == DIERR_OLDDIRECTINPUTVERSION, "IDirectInput_Initialize returned 0x%08x\n", hr);
- for (i = 0; i < sizeof(directinput_version_list)/sizeof(directinput_version_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(directinput_version_list); i++)
{
hr = IDirectInput_Initialize(pDI, hInstance, directinput_version_list[i]);
ok(hr == DI_OK, "IDirectInput_Initialize returned 0x%08x\n", hr);
diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c
index b4ffba5c5d..69e95d0c2d 100644
--- a/dlls/dinput/tests/joystick.c
+++ b/dlls/dinput/tests/joystick.c
@@ -30,8 +30,6 @@
#include "wingdi.h"
#include "dinput.h"
-#define numObjects(x) (sizeof(x) / sizeof(x[0]))
-
typedef struct tagUserData {
IDirectInputA *pDI;
DWORD version;
@@ -62,7 +60,7 @@ static const DIDATAFORMAT c_dfDIJoystickTest = {
sizeof(DIOBJECTDATAFORMAT),
DIDF_ABSAXIS,
sizeof(DIJOYSTATE2),
- numObjects(dfDIJoystickTest),
+ ARRAY_SIZE(dfDIJoystickTest),
(LPDIOBJECTDATAFORMAT)dfDIJoystickTest
};
@@ -178,7 +176,7 @@ static const struct effect_id
static const struct effect_id* effect_from_guid(const GUID *guid)
{
unsigned int i;
- for (i = 0; i < sizeof(effect_conversion) / sizeof(effect_conversion[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(effect_conversion); i++)
if (IsEqualGUID(guid, effect_conversion[i].guid))
return &effect_conversion[i];
return NULL;
@@ -504,7 +502,7 @@ static BOOL CALLBACK EnumJoysticks(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
effect_data.eff.dwDuration = INFINITE;
effect_data.eff.dwGain = DI_FFNOMINALMAX;
effect_data.eff.dwTriggerButton = DIEB_NOTRIGGER;
- effect_data.eff.cAxes = sizeof(axes) / sizeof(axes[0]);
+ effect_data.eff.cAxes = ARRAY_SIZE(axes);
effect_data.eff.rgdwAxes = axes;
effect_data.eff.rglDirection = direction;
diff --git a/dlls/dinput/tests/keyboard.c b/dlls/dinput/tests/keyboard.c
index 576a94cc7d..59411cbfa5 100644
--- a/dlls/dinput/tests/keyboard.c
+++ b/dlls/dinput/tests/keyboard.c
@@ -101,7 +101,7 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
df.dwObjSize = sizeof( DIOBJECTDATAFORMAT );
df.dwFlags = DIDF_RELAXIS;
df.dwDataSize = sizeof( custom_state );
- df.dwNumObjs = sizeof( dodf )/sizeof( dodf[0] );
+ df.dwNumObjs = ARRAY_SIZE(dodf);
df.rgodf = dodf;
hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL);
@@ -139,7 +139,7 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
memset(custom_state, 0x56, sizeof(custom_state));
IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
- for (i = 0; i < sizeof(custom_state) / sizeof(custom_state[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(custom_state); i++)
ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]);
/* simulate some keyboard input */
@@ -160,7 +160,7 @@ static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState failed: %08x\n", hr);
- for (i = 0; i < sizeof(custom_state) / sizeof(custom_state[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(custom_state); i++)
ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]);
}
keybd_event('Q', 0, KEYEVENTF_KEYUP, 0);
@@ -316,7 +316,7 @@ static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid)
HKL hkl, hkl_orig;
MSG msg;
- for (i = 0; i < sizeof(expected)/sizeof(expected[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(expected); i++)
{
if (expected[i].langid == langid)
{
@@ -340,7 +340,7 @@ static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid)
SetFocus(hwnd);
pump_messages();
- for (i = 0; i < sizeof(key2dik_en)/sizeof(key2dik_en[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(key2dik_en); i++)
{
BYTE kbd_state[256];
UINT n;
--
2.14.4
June 7, 2018
[PATCH] dinput8/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/dinput8/tests/device.c | 12 ++++++------
dlls/dinput8/tests/dinput.c | 18 +++++++++---------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 2b06f624c2..aaeddd9b7b 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -317,8 +317,8 @@ static void test_action_mapping(void)
memset (&af, 0, sizeof(af));
af.dwSize = sizeof(af);
af.dwActionSize = sizeof(DIACTIONA);
- af.dwDataSize = 4 * sizeof(actionMapping) / sizeof(actionMapping[0]);
- af.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
+ af.dwDataSize = 4 * ARRAY_SIZE(actionMapping);
+ af.dwNumActions = ARRAY_SIZE(actionMapping);
af.rgoAction = actionMapping;
af.guidActionMap = ACTION_MAPPING_GUID;
af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
@@ -357,8 +357,8 @@ static void test_action_mapping(void)
hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
ok (hr == DI_NOEFFECT, "SetActionMap should have no effect with no actions to map hr=%08x\n", hr);
- af.dwDataSize = 4 * sizeof(actionMapping) / sizeof(actionMapping[0]);
- af.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
+ af.dwDataSize = 4 * ARRAY_SIZE(actionMapping);
+ af.dwNumActions = ARRAY_SIZE(actionMapping);
/* test DIDSAM_NOUSER */
dps.diph.dwSize = sizeof(dps);
@@ -448,8 +448,8 @@ static void test_save_settings(void)
memset (&af, 0, sizeof(af));
af.dwSize = sizeof(af);
af.dwActionSize = sizeof(DIACTIONA);
- af.dwDataSize = 4 * sizeof(actions) / sizeof(actions[0]);
- af.dwNumActions = sizeof(actions) / sizeof(actions[0]);
+ af.dwDataSize = 4 * ARRAY_SIZE(actions);
+ af.dwNumActions = ARRAY_SIZE(actions);
af.rgoAction = actions;
af.guidActionMap = mapping_guid;
af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
diff --git a/dlls/dinput8/tests/dinput.c b/dlls/dinput8/tests/dinput.c
index e16542ab13..b093437096 100644
--- a/dlls/dinput8/tests/dinput.c
+++ b/dlls/dinput8/tests/dinput.c
@@ -82,7 +82,7 @@ static void test_preinitialization(void)
return;
}
- for (i = 0; i < sizeof(create_device_tests)/sizeof(create_device_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(create_device_tests); i++)
{
if (create_device_tests[i].pdev) pDID = (void *)0xdeadbeef;
hr = IDirectInput8_CreateDevice(pDI, create_device_tests[i].rguid,
@@ -93,7 +93,7 @@ static void test_preinitialization(void)
ok(pDID == NULL, "[%d] Output interface pointer is %p\n", i, pDID);
}
- for (i = 0; i < sizeof(enum_devices_tests)/sizeof(enum_devices_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(enum_devices_tests); i++)
{
hr = IDirectInput8_EnumDevices(pDI, enum_devices_tests[i].dwDevType,
enum_devices_tests[i].lpCallback,
@@ -186,7 +186,7 @@ static void test_DirectInput8Create(void)
IUnknown *pUnk;
HRESULT hr;
- for (i = 0; i < sizeof(invalid_param_list)/sizeof(invalid_param_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(invalid_param_list); i++)
{
if (invalid_param_list[i].ppdi) pUnk = (void *)0xdeadbeef;
hr = DirectInput8Create(invalid_param_list[i].hinst ? hInstance : NULL,
@@ -199,7 +199,7 @@ static void test_DirectInput8Create(void)
ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk);
}
- for (i = 0; i < sizeof(no_interface_list)/sizeof(no_interface_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
{
pUnk = (void *)0xdeadbeef;
hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, no_interface_list[i], (void **)&pUnk, NULL);
@@ -207,7 +207,7 @@ static void test_DirectInput8Create(void)
ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk);
}
- for (i = 0; i < sizeof(iid_list)/sizeof(iid_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iid_list); i++)
{
pUnk = NULL;
hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, iid_list[i], (void **)&pUnk, NULL);
@@ -268,7 +268,7 @@ static void test_QueryInterface(void)
hr = IDirectInput8_QueryInterface(pDI, &IID_IUnknown, NULL);
ok(hr == E_POINTER, "IDirectInput8_QueryInterface returned 0x%08x\n", hr);
- for (i = 0; i < sizeof(iid_list)/sizeof(iid_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iid_list); i++)
{
pUnk = NULL;
hr = IDirectInput8_QueryInterface(pDI, iid_list[i], (void **)&pUnk);
@@ -277,7 +277,7 @@ static void test_QueryInterface(void)
if (pUnk)
{
int j;
- for (j = 0; j < sizeof(iid_list)/sizeof(iid_list[0]); j++)
+ for (j = 0; j < ARRAY_SIZE(iid_list); j++)
{
IUnknown *pUnk1 = NULL;
hr = IDirectInput8_QueryInterface(pUnk, iid_list[j], (void **)&pUnk1);
@@ -289,7 +289,7 @@ static void test_QueryInterface(void)
}
}
- for (i = 0; i < sizeof(no_interface_list)/sizeof(no_interface_list[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
{
pUnk = (void *)0xdeadbeef;
hr = IDirectInput8_QueryInterface(pDI, no_interface_list[i].riid, (void **)&pUnk);
@@ -527,7 +527,7 @@ static void test_EnumDevicesBySemantics(void)
memset (&diaf, 0, sizeof(diaf));
diaf.dwSize = sizeof(diaf);
diaf.dwActionSize = sizeof(DIACTIONA);
- diaf.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
+ diaf.dwNumActions = ARRAY_SIZE(actionMapping);
diaf.dwDataSize = 4 * diaf.dwNumActions;
diaf.rgoAction = actionMapping;
diaf.guidActionMap = ACTION_MAPPING_GUID;
--
2.14.4
June 7, 2018
[PATCH] ieframe/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/ieframe/tests/intshcut.c | 2 +-
dlls/ieframe/tests/webbrowser.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/ieframe/tests/intshcut.c b/dlls/ieframe/tests/intshcut.c
index 0959a61880..803e7ec60e 100644
--- a/dlls/ieframe/tests/intshcut.c
+++ b/dlls/ieframe/tests/intshcut.c
@@ -331,7 +331,7 @@ static void test_Load(void)
GetTempPathW(MAX_PATH, file_path);
lstrcatW(file_path, test_urlW);
- for(test = load_tests; test < load_tests + sizeof(load_tests)/sizeof(*load_tests); test++) {
+ for(test = load_tests; test < load_tests + ARRAY_SIZE(load_tests); test++) {
IPropertySetStorage *propsetstorage;
IPropertyStorage *propstorage;
PROPVARIANT v;
diff --git a/dlls/ieframe/tests/webbrowser.c b/dlls/ieframe/tests/webbrowser.c
index ca2a13162b..706d5071a9 100644
--- a/dlls/ieframe/tests/webbrowser.c
+++ b/dlls/ieframe/tests/webbrowser.c
@@ -2167,7 +2167,7 @@ static void test_EnumVerbs(IWebBrowser2 *wb)
fetched = 0xdeadbeef;
memset(verbs, 0xa, sizeof(verbs));
verbs[1].lVerb = 0xdeadbeef;
- hres = IEnumOLEVERB_Next(enum_verbs, sizeof(verbs)/sizeof(*verbs), verbs, &fetched);
+ hres = IEnumOLEVERB_Next(enum_verbs, ARRAY_SIZE(verbs), verbs, &fetched);
ok(hres == S_OK, "Next failed: %08x\n", hres);
ok(!fetched, "fetched = %d\n", fetched);
/* Although fetched==0, an element is returned. */
@@ -2184,12 +2184,12 @@ static void test_EnumVerbs(IWebBrowser2 *wb)
fetched = 0xdeadbeef;
memset(verbs, 0xa, sizeof(verbs));
verbs[0].lVerb = 0xdeadbeef;
- hres = IEnumOLEVERB_Next(enum_verbs, sizeof(verbs)/sizeof(*verbs), verbs, &fetched);
+ hres = IEnumOLEVERB_Next(enum_verbs, ARRAY_SIZE(verbs), verbs, &fetched);
todo_wine ok(hres == S_OK, "Next failed: %08x\n", hres);
todo_wine ok(fetched == 1, "fetched = %d\n", fetched);
todo_wine ok(verbs[0].lVerb != 0xdeadbeef, "verbs[0].lVerb = %x\n", verbs[0].lVerb);
- hres = IEnumOLEVERB_Next(enum_verbs, sizeof(verbs)/sizeof(*verbs), verbs, &fetched);
+ hres = IEnumOLEVERB_Next(enum_verbs, ARRAY_SIZE(verbs), verbs, &fetched);
ok(hres == S_FALSE, "Next failed: %08x\n", hres);
ok(!fetched, "fetched = %d\n", fetched);
--
2.14.4
June 7, 2018
[PATCH] gdiplus/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/gdiplus/tests/graphics.c | 10 +++----
dlls/gdiplus/tests/graphicspath.c | 58 +++++++++++++++++++--------------------
dlls/gdiplus/tests/image.c | 40 +++++++++++++--------------
3 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 6acc656c8f..ae75c0efc1 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -3721,7 +3721,7 @@ static void test_GdipMeasureString(void)
expect(Ok, status);
expect(UnitPixel, font_unit);
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
GpImage *image;
@@ -3799,7 +3799,7 @@ todo_wine
expect(Ok, status);
expect(unit, font_unit);
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
REAL unit_scale;
GpImage *image;
@@ -3883,7 +3883,7 @@ todo_wine
}
/* Font with units = UnitWorld */
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
GpPointF pt = {0.0, 100.0};
GpImage* image;
@@ -3972,7 +3972,7 @@ static void test_transform(void)
GpPointF ptf[2];
UINT i;
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
graphics = create_graphics(td[i].res_x, td[i].res_y, td[i].unit, td[i].scale, &image);
ptf[0].X = td[i].in[0].X;
@@ -4032,7 +4032,7 @@ static void test_pen_thickness(void)
BitmapData bd;
INT min, max, size;
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
status = GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat24bppRGB, NULL, &u.bitmap);
expect(Ok, status);
diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c
index c5403cbe0e..096fbc600a 100644
--- a/dlls/gdiplus/tests/graphicspath.c
+++ b/dlls/gdiplus/tests/graphicspath.c
@@ -207,7 +207,7 @@ static void test_line2(void)
status = GdipAddPathLine2(path, &(line2_points[6]), 3);
expect(Ok, status);
- ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, line2_path, ARRAY_SIZE(line2_path), FALSE);
GdipDeletePath(path);
}
@@ -278,7 +278,7 @@ static void test_arc(void)
status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
expect(Ok, status);
- ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, arc_path, ARRAY_SIZE(arc_path), FALSE);
GdipDeletePath(path);
}
@@ -458,7 +458,7 @@ static void test_pathpath(void)
status = GdipAddPathPath(path1, path2, TRUE);
expect(Ok, status);
- ok_path(path1, pathpath_path, sizeof(pathpath_path)/sizeof(path_test_t), FALSE);
+ ok_path(path1, pathpath_path, ARRAY_SIZE(pathpath_path), FALSE);
GdipDeletePath(path1);
GdipDeletePath(path2);
@@ -529,7 +529,7 @@ static void test_ellipse(void)
status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
expect(Ok, status);
- ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, ellipse_path, ARRAY_SIZE(ellipse_path), FALSE);
GdipDeletePath(path);
}
@@ -565,7 +565,7 @@ static void test_linei(void)
status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
expect(Ok, status);
- ok_path(path, linei_path, sizeof(linei_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, linei_path, ARRAY_SIZE(linei_path), FALSE);
GdipDeletePath(path);
}
@@ -614,7 +614,7 @@ static void test_polygon(void)
status = GdipAddPathPolygon(path, points, 5);
expect(Ok, status);
/* check resulting path */
- ok_path(path, poly_path, sizeof(poly_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, poly_path, ARRAY_SIZE(poly_path), FALSE);
GdipDeletePath(path);
}
@@ -643,7 +643,7 @@ static void test_rect(void)
status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
expect(Ok, status);
- ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
GdipDeletePath(path);
@@ -661,7 +661,7 @@ static void test_rect(void)
status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
expect(Ok, status);
- ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
GdipDeletePath(path);
}
@@ -756,7 +756,7 @@ static void test_addcurve(void)
/* add to empty path */
status = GdipAddPathCurve2(path, points, 4, 1.0);
expect(Ok, status);
- ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
GdipDeletePath(path);
/* add to notempty path and opened figure */
@@ -764,7 +764,7 @@ static void test_addcurve(void)
GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
status = GdipAddPathCurve2(path, points, 4, 1.0);
expect(Ok, status);
- ok_path(path, addcurve_path2, sizeof(addcurve_path2)/sizeof(path_test_t), FALSE);
+ ok_path(path, addcurve_path2, ARRAY_SIZE(addcurve_path2), FALSE);
/* NULL args */
GdipResetPath(path);
@@ -789,12 +789,12 @@ static void test_addcurve(void)
/* use all points */
status = GdipAddPathCurve3(path, points, 4, 0, 3, 1.0);
expect(Ok, status);
- ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
GdipResetPath(path);
status = GdipAddPathCurve3(path, points, 4, 1, 2, 1.0);
expect(Ok, status);
- ok_path(path, addcurve_path3, sizeof(addcurve_path3)/sizeof(path_test_t), FALSE);
+ ok_path(path, addcurve_path3, ARRAY_SIZE(addcurve_path3), FALSE);
GdipDeletePath(path);
}
@@ -844,7 +844,7 @@ static void test_addclosedcurve(void)
/* add to empty path */
status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
expect(Ok, status);
- ok_path(path, addclosedcurve_path, sizeof(addclosedcurve_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, addclosedcurve_path, ARRAY_SIZE(addclosedcurve_path), FALSE);
GdipDeletePath(path);
}
@@ -886,7 +886,7 @@ static void test_reverse(void)
status = GdipReversePath(path);
expect(Ok, status);
- ok_path(path, reverse_path, sizeof(reverse_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, reverse_path, ARRAY_SIZE(reverse_path), FALSE);
GdipDeletePath(path);
}
@@ -917,21 +917,21 @@ static void test_addpie(void)
status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
expect(Ok, status);
- ok_path(path, addpie_path, sizeof(addpie_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, addpie_path, ARRAY_SIZE(addpie_path), FALSE);
status = GdipResetPath(path);
expect(Ok, status);
/* zero width base ellipse */
status = GdipAddPathPie(path, 0.0, 0.0, 0.0, 60.0, -90.0, 24.0);
expect(InvalidParameter, status);
- ok_path(path, addpie_path2, sizeof(addpie_path2)/sizeof(path_test_t), FALSE);
+ ok_path(path, addpie_path2, ARRAY_SIZE(addpie_path2), FALSE);
status = GdipResetPath(path);
expect(Ok, status);
/* zero height base ellipse */
status = GdipAddPathPie(path, 0.0, 0.0, 60.0, 0.0 , -90.0, 24.0);
expect(InvalidParameter, status);
- ok_path(path, addpie_path3, sizeof(addpie_path3)/sizeof(path_test_t), FALSE);
+ ok_path(path, addpie_path3, ARRAY_SIZE(addpie_path3), FALSE);
GdipDeletePath(path);
}
@@ -1020,7 +1020,7 @@ static void test_flatten(void)
status = GdipFlattenPath(path, NULL, 1.0);
expect(Ok, status);
- ok_path(path, flattenellipse_path, sizeof(flattenellipse_path)/sizeof(path_test_t), TRUE);
+ ok_path(path, flattenellipse_path, ARRAY_SIZE(flattenellipse_path), TRUE);
status = GdipResetPath(path);
expect(Ok, status);
@@ -1028,7 +1028,7 @@ static void test_flatten(void)
expect(Ok, status);
status = GdipFlattenPath(path, NULL, 1.0);
expect(Ok, status);
- ok_path(path, flattenline_path, sizeof(flattenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, flattenline_path, ARRAY_SIZE(flattenline_path), FALSE);
status = GdipResetPath(path);
expect(Ok, status);
@@ -1036,7 +1036,7 @@ static void test_flatten(void)
expect(Ok, status);
status = GdipFlattenPath(path, NULL, 1.0);
expect(Ok, status);
- ok_path(path, flattenarc_path, sizeof(flattenarc_path)/sizeof(path_test_t), TRUE);
+ ok_path(path, flattenarc_path, ARRAY_SIZE(flattenarc_path), TRUE);
/* easy case - quater of a full circle */
status = GdipResetPath(path);
@@ -1045,7 +1045,7 @@ static void test_flatten(void)
expect(Ok, status);
status = GdipFlattenPath(path, NULL, 1.0);
expect(Ok, status);
- ok_path(path, flattenquater_path, sizeof(flattenquater_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, flattenquater_path, ARRAY_SIZE(flattenquater_path), FALSE);
GdipDeleteMatrix(m);
GdipDeletePath(path);
@@ -1119,7 +1119,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
/* horizontal 2x stretch */
status = GdipResetPath(path);
@@ -1132,7 +1132,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
/* vertical 2x stretch */
status = GdipResetPath(path);
@@ -1145,7 +1145,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
expect(Ok, status);
@@ -1161,7 +1161,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_dash_path, sizeof(widenline_dash_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_dash_path, ARRAY_SIZE(widenline_dash_path), FALSE);
status = GdipSetPenDashStyle(pen, DashStyleSolid);
expect(Ok, status);
@@ -1178,7 +1178,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
/* horizontal 2x stretch */
status = GdipResetPath(path);
@@ -1191,7 +1191,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
/* vertical 2x stretch */
status = GdipResetPath(path);
@@ -1204,7 +1204,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_wide_path, sizeof(widenline_wide_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_wide_path, ARRAY_SIZE(widenline_wide_path), FALSE);
status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
expect(Ok, status);
@@ -1221,7 +1221,7 @@ static void test_widen(void)
status = GdipWidenPath(path, pen, m, 1.0);
expect(Ok, status);
- ok_path(path, widenline_path, sizeof(widenline_path)/sizeof(path_test_t), FALSE);
+ ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
/* pen width = 0 pixels - native fails to widen but can draw with this pen */
GdipDeletePen(pen);
diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c
index 4fd2744132..88d195f6c9 100644
--- a/dlls/gdiplus/tests/image.c
+++ b/dlls/gdiplus/tests/image.c
@@ -55,10 +55,10 @@ static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
char buffer[39];
char buffer2[39];
- StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
- WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
- StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
- WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
+ StringFromGUID2(got, bufferW, ARRAY_SIZE(bufferW));
+ WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer, sizeof(buffer), NULL, NULL);
+ StringFromGUID2(expected, bufferW, ARRAY_SIZE(bufferW));
+ WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer2, sizeof(buffer2), NULL, NULL);
todo_wine_if (todo)
ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
}
@@ -3311,7 +3311,7 @@ static void test_image_properties(void)
char buf[256];
} item;
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
image = load_image(td[i].image_data, td[i].image_size);
if (!image)
@@ -3629,9 +3629,9 @@ static void test_tiff_properties(void)
prop_count = 0xdeadbeef;
status = GdipGetPropertyCount(image, &prop_count);
expect(Ok, status);
- ok(prop_count == sizeof(td)/sizeof(td[0]) ||
- broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
- "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
+ ok(prop_count == ARRAY_SIZE(td) ||
+ broken(prop_count == ARRAY_SIZE(td) - 1) /* Win7 SP0 */,
+ "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
@@ -3739,8 +3739,8 @@ static void test_GdipGetAllPropertyItems(void)
prop_count = 0xdeadbeef;
status = GdipGetPropertyCount(image, &prop_count);
expect(Ok, status);
- ok(prop_count == sizeof(td)/sizeof(td[0]),
- "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
+ ok(prop_count == ARRAY_SIZE(td),
+ "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
@@ -4014,7 +4014,7 @@ static void test_bitmapbits(void)
} palette;
ARGB *entries = palette.pal.Entries;
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
BYTE pixels[sizeof(pixels_24)];
memcpy(pixels, pixels_24, sizeof(pixels_24));
@@ -4283,7 +4283,7 @@ static void test_image_format(void)
BitmapData data;
UINT i, ret;
- for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(fmt); i++)
{
status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
@@ -4435,7 +4435,7 @@ static void test_DrawImage_scale(void)
status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
expect(Ok, status);
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
expect(Ok, status);
@@ -4541,10 +4541,10 @@ static void test_gif_properties(void)
status = GdipGetPropertyCount(image, &prop_count);
expect(Ok, status);
- ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
- "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
+ ok(prop_count == ARRAY_SIZE(td) || broken(prop_count == 1) /* before win7 */,
+ "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
- if (prop_count != sizeof(td)/sizeof(td[0]))
+ if (prop_count != ARRAY_SIZE(td))
{
GdipDisposeImage(image);
return;
@@ -4818,7 +4818,7 @@ static void test_supported_encoders(void)
status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
ret = get_encoder_clsid(td[i].mime, &format, &clsid);
ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
@@ -4868,7 +4868,7 @@ static void test_createeffect(void)
stat = pGdipCreateEffect(noneffect, &effect);
todo_wine expect(Win32Error, stat);
- for(i=0; i < sizeof(effectlist) / sizeof(effectlist[0]); i++)
+ for(i=0; i < ARRAY_SIZE(effectlist); i++)
{
stat = pGdipCreateEffect(*effectlist[i], &effect);
todo_wine expect(Ok, stat);
@@ -4981,7 +4981,7 @@ static void test_histogram(void)
expect(Ok, stat);
expect(256, num);
- for (i = 0; i < sizeof(test_formats)/sizeof(test_formats[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_formats); i++)
{
num = 0;
stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
@@ -5131,7 +5131,7 @@ static void test_png_color_formats(void)
UINT flags;
int i;
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
buf[24] = td[i].bit_depth;
--
2.14.4
June 7, 2018
[PATCH] d3dcompiler/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/d3dcompiler_43/tests/asm.c | 27 ++++++++++++++-------------
dlls/d3dcompiler_43/tests/blob.c | 18 +++++++++---------
dlls/d3dcompiler_43/tests/hlsl.c | 14 +++++++-------
dlls/d3dcompiler_43/tests/reflection.c | 18 +++++++++---------
4 files changed, 39 insertions(+), 38 deletions(-)
diff --git a/dlls/d3dcompiler_43/tests/asm.c b/dlls/d3dcompiler_43/tests/asm.c
index 6fd78c186e..f077369ba8 100644
--- a/dlls/d3dcompiler_43/tests/asm.c
+++ b/dlls/d3dcompiler_43/tests/asm.c
@@ -108,7 +108,7 @@ static void preproc_test(void) {
},
};
- exec_tests("preproc", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("preproc", tests, ARRAY_SIZE(tests));
}
static void ps_1_1_test(void) {
@@ -134,7 +134,7 @@ static void ps_1_1_test(void) {
},
};
- exec_tests("ps_1_1", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_1_1", tests, ARRAY_SIZE(tests));
}
static void vs_1_1_test(void) {
@@ -277,7 +277,7 @@ static void vs_1_1_test(void) {
},
};
- exec_tests("vs_1_1", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("vs_1_1", tests, ARRAY_SIZE(tests));
}
static void ps_1_3_test(void) {
@@ -517,7 +517,7 @@ static void ps_1_3_test(void) {
},
};
- exec_tests("ps_1_3", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_1_3", tests, ARRAY_SIZE(tests));
}
static void ps_1_4_test(void) {
@@ -627,7 +627,7 @@ static void ps_1_4_test(void) {
},
};
- exec_tests("ps_1_4", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_1_4", tests, ARRAY_SIZE(tests));
}
static void vs_2_0_test(void) {
@@ -818,7 +818,7 @@ static void vs_2_0_test(void) {
},
};
- exec_tests("vs_2_0", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("vs_2_0", tests, ARRAY_SIZE(tests));
}
static void vs_2_x_test(void) {
@@ -879,7 +879,7 @@ static void vs_2_x_test(void) {
},
};
- exec_tests("vs_2_x", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("vs_2_x", tests, ARRAY_SIZE(tests));
}
static void ps_2_0_test(void) {
@@ -952,7 +952,7 @@ static void ps_2_0_test(void) {
},
};
- exec_tests("ps_2_0", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_2_0", tests, ARRAY_SIZE(tests));
}
static void ps_2_x_test(void) {
@@ -1090,7 +1090,7 @@ static void ps_2_x_test(void) {
},
};
- exec_tests("ps_2_x", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_2_x", tests, ARRAY_SIZE(tests));
}
static void vs_3_0_test(void) {
@@ -1175,7 +1175,7 @@ static void vs_3_0_test(void) {
};
- exec_tests("vs_3_0", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("vs_3_0", tests, ARRAY_SIZE(tests));
}
static void ps_3_0_test(void) {
@@ -1261,7 +1261,7 @@ static void ps_3_0_test(void) {
},
};
- exec_tests("ps_3_0", tests, sizeof(tests) / sizeof(tests[0]));
+ exec_tests("ps_3_0", tests, ARRAY_SIZE(tests));
}
static void failure_test(void) {
@@ -1408,7 +1408,8 @@ static void failure_test(void) {
unsigned int i;
ID3DBlob *shader, *messages;
- for(i = 0; i < (sizeof(tests) / sizeof(tests[0])); i++) {
+ for(i = 0; i < ARRAY_SIZE(tests); i++)
+ {
shader = NULL;
messages = NULL;
hr = D3DAssemble(tests[i], strlen(tests[i]), NULL,
@@ -1689,7 +1690,7 @@ static void d3dpreprocess_test(void)
/* pInclude tests */
include.ID3DInclude_iface.lpVtbl = &D3DInclude_Vtbl;
- for (i = 0; i < sizeof(include_test_shaders) / sizeof(include_test_shaders[0]); ++i)
+ for (i = 0; i < ARRAY_SIZE(include_test_shaders); ++i)
{
shader = NULL;
messages = NULL;
diff --git a/dlls/d3dcompiler_43/tests/blob.c b/dlls/d3dcompiler_43/tests/blob.c
index ba69abfb60..d99df825ee 100644
--- a/dlls/d3dcompiler_43/tests/blob.c
+++ b/dlls/d3dcompiler_43/tests/blob.c
@@ -171,7 +171,7 @@ static void test_get_blob_part(void)
ok(TAG_DXBC == *dword, "DXBC got %#x, expected %#x.\n", *dword, TAG_DXBC);
ok(TAG_ISGN == *(dword+9), "ISGN got %#x, expected %#x.\n", *(dword+9), TAG_ISGN);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -202,7 +202,7 @@ static void test_get_blob_part(void)
ok(TAG_DXBC == *dword, "DXBC got %#x, expected %#x.\n", *dword, TAG_DXBC);
ok(TAG_OSGN == *(dword+9), "OSGN got %#x, expected %#x.\n", *(dword+9), TAG_OSGN);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -234,7 +234,7 @@ static void test_get_blob_part(void)
ok(TAG_ISGN == *(dword+10), "ISGN got %#x, expected %#x.\n", *(dword+10), TAG_ISGN);
ok(TAG_OSGN == *(dword+32), "OSGN got %#x, expected %#x.\n", *(dword+32), TAG_OSGN);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -278,7 +278,7 @@ static void test_get_blob_part(void)
dword = ((DWORD*)ID3D10Blob_GetBufferPointer(blob));
ok(test_blob_part[0] != *dword, "DXBC failed got %#x.\n", *dword);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
/* There isn't a full DXBC blob returned for D3D_BLOB_LEGACY_SHADER */
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -298,7 +298,7 @@ static void test_get_blob_part(void)
dword = ((DWORD*)ID3D10Blob_GetBufferPointer(blob));
ok(test_blob_part[0] != *dword, "DXBC failed got %#x.\n", *dword);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
/* There isn't a full DXBC blob returned for D3D_BLOB_XNA_PREPASS_SHADER */
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -318,7 +318,7 @@ static void test_get_blob_part(void)
dword = ((DWORD*)ID3D10Blob_GetBufferPointer(blob));
ok(test_blob_part[0] != *dword, "DXBC failed got %#x.\n", *dword);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
/* There isn't a full DXBC blob returned for D3D_BLOB_XNA_SHADER */
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -606,7 +606,7 @@ static void test_get_blob_part2(void)
ok(TAG_DXBC == *dword, "DXBC got %#x, expected %#x.\n", *dword, TAG_DXBC);
ok(TAG_PCSG == *(dword+9), "PCSG got %#x, expected %#x.\n", *(dword+9), TAG_PCSG);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -639,7 +639,7 @@ static void test_get_blob_part2(void)
ok(TAG_OSGN == *(dword+24), "OSGN got %#x, expected %#x.\n", *(dword+24), TAG_OSGN);
ok(TAG_PCSG == *(dword+37), "PCSG got %#x, expected %#x.\n", *(dword+37), TAG_PCSG);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
@@ -673,7 +673,7 @@ static void test_get_blob_part2(void)
dword = ((DWORD*)ID3D10Blob_GetBufferPointer(blob));
ok(TAG_DXBC != *dword, "DXBC failed got %#x.\n", *dword);
- for (i = 0; i < sizeof(parts) / sizeof(parts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(parts); i++)
{
/* There isn't a full DXBC blob returned for D3D_BLOB_DEBUG_INFO */
hr = D3DGetBlobPart(dword, size, parts[i], 0, &blob2);
diff --git a/dlls/d3dcompiler_43/tests/hlsl.c b/dlls/d3dcompiler_43/tests/hlsl.c
index 856a09c2c5..546a0e5d2e 100644
--- a/dlls/d3dcompiler_43/tests/hlsl.c
+++ b/dlls/d3dcompiler_43/tests/hlsl.c
@@ -320,7 +320,7 @@ static void test_swizzle(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_
set_float4_d3d9(device, constants, "color", 0.0303f, 0.0f, 0.0f, 0.0202f);
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry,
- probes, sizeof(probes) / sizeof(*probes), 1, 1, __LINE__);
+ probes, ARRAY_SIZE(probes), 1, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -363,7 +363,7 @@ static void test_math(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geo
ID3DXConstantTable_SetFloat(constants, device, "$z", z);
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry,
- probes, sizeof(probes) / sizeof(*probes), 1, 1, __LINE__);
+ probes, ARRAY_SIZE(probes), 1, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -417,7 +417,7 @@ static void test_conditionals(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *
if (pshader != NULL)
{
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, if_greater_probes,
- sizeof(if_greater_probes) / sizeof(*if_greater_probes), 32, 1, __LINE__);
+ ARRAY_SIZE(if_greater_probes), 32, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -427,7 +427,7 @@ static void test_conditionals(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *
if (pshader != NULL)
{
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, ternary_operator_probes,
- sizeof(ternary_operator_probes) / sizeof(*ternary_operator_probes), 8, 1, __LINE__);
+ ARRAY_SIZE(ternary_operator_probes), 8, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -476,7 +476,7 @@ static void test_float_vectors(IDirect3DDevice9 *device, IDirect3DVertexBuffer9
if (pshader != NULL)
{
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, vec4_indexing_test1_probes,
- sizeof(vec4_indexing_test1_probes) / sizeof(*vec4_indexing_test1_probes), 1, 1, __LINE__);
+ ARRAY_SIZE(vec4_indexing_test1_probes), 1, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -488,7 +488,7 @@ static void test_float_vectors(IDirect3DDevice9 *device, IDirect3DVertexBuffer9
ID3DXConstantTable_SetInt(constants, device, "i", 2);
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, vec4_indexing_test2_probes,
- sizeof(vec4_indexing_test2_probes) / sizeof(*vec4_indexing_test2_probes), 32, 1, __LINE__);
+ ARRAY_SIZE(vec4_indexing_test2_probes), 32, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
@@ -550,7 +550,7 @@ static void test_trig(IDirect3DDevice9 *device, IDirect3DVertexBuffer9 *quad_geo
if (pshader != NULL)
{
compute_shader_probe9(device, vshader_passthru, pshader, quad_geometry, sincos_probes,
- sizeof(sincos_probes) / sizeof(*sincos_probes), 32, 1, __LINE__);
+ ARRAY_SIZE(sincos_probes), 32, 1, __LINE__);
ID3DXConstantTable_Release(constants);
IDirect3DPixelShader9_Release(pshader);
diff --git a/dlls/d3dcompiler_43/tests/reflection.c b/dlls/d3dcompiler_43/tests/reflection.c
index 9d77d47938..5ca734e6bd 100644
--- a/dlls/d3dcompiler_43/tests/reflection.c
+++ b/dlls/d3dcompiler_43/tests/reflection.c
@@ -356,7 +356,7 @@ static void test_reflection_desc_vs(void)
ok(ret == 0, "GetMovcInstructionCount failed, got %u, expected %u\n", ret, 0);
/* GetIn/OutputParameterDesc */
- for (i = 0; i < sizeof(test_reflection_desc_vs_resultin)/sizeof(*test_reflection_desc_vs_resultin); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_desc_vs_resultin); ++i)
{
pdesc = &test_reflection_desc_vs_resultin[i];
@@ -381,7 +381,7 @@ static void test_reflection_desc_vs(void)
i, desc.Stream, pdesc->ReadWriteMask);
}
- for (i = 0; i < sizeof(test_reflection_desc_vs_resultout)/sizeof(*test_reflection_desc_vs_resultout); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_desc_vs_resultout); ++i)
{
pdesc = &test_reflection_desc_vs_resultout[i];
@@ -656,7 +656,7 @@ static void test_reflection_desc_ps(void)
ok(hr == E_INVALIDARG, "GetPatchConstantParameterDesc failed, got %x, expected %x\n", hr, E_INVALIDARG);
/* GetIn/OutputParameterDesc */
- for (i = 0; i < sizeof(test_reflection_desc_ps_resultin)/sizeof(*test_reflection_desc_ps_resultin); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_desc_ps_resultin); ++i)
{
pdesc = &test_reflection_desc_ps_resultin[i];
@@ -681,7 +681,7 @@ static void test_reflection_desc_ps(void)
i, desc.Stream, pdesc->ReadWriteMask);
}
- for (i = 0; i < sizeof(test_reflection_desc_ps_resultout)/sizeof(*test_reflection_desc_ps_resultout); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_desc_ps_resultout); ++i)
{
pdesc = &test_reflection_desc_ps_resultout[i];
@@ -899,7 +899,7 @@ static void test_reflection_desc_ps_output(void)
const D3D11_SIGNATURE_PARAMETER_DESC *pdesc;
unsigned int i;
- for (i = 0; i < sizeof(test_reflection_desc_ps_output_result)/sizeof(*test_reflection_desc_ps_output_result); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_desc_ps_output_result); ++i)
{
hr = D3DReflect(test_reflection_desc_ps_output_blob[i], test_reflection_desc_ps_output_blob[i][6], &IID_ID3D11ShaderReflection, (void **)&ref11);
ok(hr == S_OK, "(%u): D3DReflect failed %x\n", i, hr);
@@ -1036,7 +1036,7 @@ static void test_reflection_bound_resources(void)
ok(hr == E_INVALIDARG, "GetResourceBindingDescByName failed, got %x, expected %x\n", hr, E_INVALIDARG);
/* GetResourceBindingDesc */
- for (i = 0; i < sizeof(test_reflection_bound_resources_result)/sizeof(*test_reflection_bound_resources_result); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_bound_resources_result); ++i)
{
pdesc = &test_reflection_bound_resources_result[i];
@@ -1062,7 +1062,7 @@ static void test_reflection_bound_resources(void)
}
/* GetResourceBindingDescByName */
- for (i = 0; i < sizeof(test_reflection_bound_resources_result)/sizeof(*test_reflection_bound_resources_result); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_bound_resources_result); ++i)
{
pdesc = &test_reflection_bound_resources_result[i];
@@ -1393,7 +1393,7 @@ static void test_reflection_constant_buffer(void)
ok(hr == S_OK, "IsEqual failed, got %x, expected %x\n", hr, S_OK);
/* constant buffers */
- for (i = 0; i < sizeof(test_reflection_constant_buffer_cb_result)/sizeof(*test_reflection_constant_buffer_cb_result); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_constant_buffer_cb_result); ++i)
{
pcbdesc = &test_reflection_constant_buffer_cb_result[i];
@@ -1416,7 +1416,7 @@ static void test_reflection_constant_buffer(void)
}
/* variables */
- for (i = 0; i < sizeof(test_reflection_constant_buffer_variable_result)/sizeof(*test_reflection_constant_buffer_variable_result); ++i)
+ for (i = 0; i < ARRAY_SIZE(test_reflection_constant_buffer_variable_result); ++i)
{
pvdesc = &test_reflection_constant_buffer_variable_result[i].desc;
--
2.14.4
June 7, 2018
[PATCH] advpack/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/advpack/tests/advpack.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/advpack/tests/advpack.c b/dlls/advpack/tests/advpack.c
index d5958769ab..8d7c5ebb48 100644
--- a/dlls/advpack/tests/advpack.c
+++ b/dlls/advpack/tests/advpack.c
@@ -134,8 +134,8 @@ static void delnode_test(void)
/* Native DelNode apparently does not support relative paths, so we use
absolute paths for testing */
- currDirLen = GetCurrentDirectoryA(sizeof(currDir) / sizeof(CHAR), currDir);
- assert(currDirLen > 0 && currDirLen < sizeof(currDir) / sizeof(CHAR));
+ currDirLen = GetCurrentDirectoryA(ARRAY_SIZE(currDir), currDir);
+ assert(currDirLen > 0 && currDirLen < ARRAY_SIZE(currDir));
if(currDir[currDirLen - 1] == '\\')
currDir[--currDirLen] = 0;
--
2.14.4
June 7, 2018
Re: [PATCH 1/5] wined3d: Declare the correct number and type of fragment shader color outputs.
by Matteo Bruni
2018-06-07 17:07 GMT+02:00 Henri Verbeet <hverbeet(a)gmail.com>:
> On 6 June 2018 at 00:32, Matteo Bruni <mbruni(a)codeweavers.com> wrote:
>> Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
>> ---
>> dlls/wined3d/glsl_shader.c | 116 ++++++++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 109 insertions(+), 7 deletions(-)
>>
> This fails the tests here:
>
> ../../../../../src/wine-git/tools/runtest -q -P wine -T ../../.. -M
> d3d10core.dll -p d3d10core_test.exe.so device && touch device.ok
> device.c:11300: Test failed: Got 0xff0000ff, expected 0xff00ff00 at
> (0, 0), sub-resource 0.
> device.c:11307: Test failed: Got 0xff0000ff, expected 0xff00ff00 at
> (0, 0), sub-resource 0.
>
> ../../../../../src/wine-git/tools/runtest -q -P wine -T ../../.. -M
> d3d11.dll -p d3d11_test.exe.so d3d11 && touch d3d11.ok
> d3d11.c:14777: Test failed: Got 0xff0000ff, expected 0xff00ff00 at (0,
> 0, 0), sub-resource 0.
> d3d11.c:14784: Test failed: Got 0xff0000ff, expected 0xff00ff00 at (0,
> 0, 0), sub-resource 0.
> d3d11.c:20644: Tests skipped: Raw buffers are not supported.
> d3d11.c:20644: Tests skipped: Raw buffers are not supported.
:/
This time I know why I missed these (didn't notice them in the midst
of other test failures), still not great... I have a fix coming.
June 7, 2018
[PATCH 3/3] user32: Add RegisterTouchHitTestingWindow stub
by Fabian Maurer
Fixes bug 45303.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/misc.c | 9 +++++++++
dlls/user32/user32.spec | 1 +
2 files changed, 10 insertions(+)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index 4cc54df412..b91aa3c7cc 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -862,6 +862,15 @@ BOOL WINAPI GetPointerDevices(UINT32 *device_count, POINTER_DEVICE_INFO *devices
return TRUE;
}
+/**********************************************************************
+ * RegisterTouchHitTestingWindow [USER32.@]
+ */
+BOOL WINAPI RegisterTouchHitTestingWindow(HWND hwnd, ULONG value)
+{
+ FIXME("(%p %d): stub\n", hwnd, value);
+ return TRUE;
+}
+
static const WCHAR imeW[] = {'I','M','E',0};
const struct builtin_class_descr IME_builtin_class =
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 7f652ee722..61e0e4e8cc 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -606,6 +606,7 @@
@ stdcall RegisterShellHookWindow (long)
@ stdcall RegisterSystemThread(long long)
@ stdcall RegisterTasklist (long)
+@ stdcall RegisterTouchHitTestingWindow(long long)
@ stdcall RegisterTouchWindow(long long)
# @ stub RegisterUserApiHook
@ stdcall RegisterWindowMessageA(str)
--
2.17.1
June 7, 2018
[PATCH 2/3] user32: Add stub for GetPointerDevices
by Fabian Maurer
Fixes bug 45302.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
...ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec | 2 +-
dlls/user32/misc.c | 17 ++++++++++++++++
dlls/user32/user32.spec | 1 +
include/winuser.h | 20 +++++++++++++++++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec b/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
index 72cfe3d954..3a043dc9c2 100644
--- a/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
+++ b/dlls/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0/api-ms-win-rtcore-ntuser-wmpointer-l1-1-0.spec
@@ -4,7 +4,7 @@
@ stub GetPointerDevice
@ stub GetPointerDeviceProperties
@ stub GetPointerDeviceRects
-@ stub GetPointerDevices
+@ stdcall GetPointerDevices(ptr ptr) user32.GetPointerDevices
@ stub GetPointerFrameInfo
@ stub GetPointerFrameInfoHistory
@ stub GetPointerFramePenInfo
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index c3f4030a90..4cc54df412 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -846,6 +846,23 @@ BOOL WINAPI RegisterPointerDeviceNotifications(HWND hwnd, BOOL notifyrange)
return TRUE;
}
+/**********************************************************************
+ * GetPointerDevices [USER32.@]
+ */
+BOOL WINAPI GetPointerDevices(UINT32 *device_count, POINTER_DEVICE_INFO *devices)
+{
+ FIXME("(%p %p): stub\n", device_count, devices);
+
+ if (!device_count)
+ return FALSE;
+
+ if (!devices)
+ *device_count = 0;
+
+ return TRUE;
+}
+
+
static const WCHAR imeW[] = {'I','M','E',0};
const struct builtin_class_descr IME_builtin_class =
{
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 2e5b203a85..7f652ee722 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -354,6 +354,7 @@
@ stdcall GetOpenClipboardWindow()
@ stdcall GetParent(long)
@ stdcall GetPhysicalCursorPos(ptr)
+@ stdcall GetPointerDevices(ptr ptr)
@ stdcall GetPriorityClipboardFormat(ptr long)
@ stdcall GetProcessDefaultLayout(ptr)
@ stdcall GetProcessDpiAwarenessInternal(long ptr)
diff --git a/include/winuser.h b/include/winuser.h
index 648efbe0e2..f546a4a1f3 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -3357,6 +3357,26 @@ typedef struct tagGESTUREINFO {
} GESTUREINFO, *PGESTUREINFO;
typedef GESTUREINFO const * PCGESTUREINFO;
+#define POINTER_DEVICE_PRODUCT_STRING_MAX 520
+
+typedef enum tagPOINTER_DEVICE_TYPE {
+ POINTER_DEVICE_TYPE_INTEGRATED_PEN = 0x00000001,
+ POINTER_DEVICE_TYPE_EXTERNAL_PEN = 0x00000002,
+ POINTER_DEVICE_TYPE_TOUCH = 0x00000003,
+ POINTER_DEVICE_TYPE_TOUCH_PAD = 0x00000004,
+ POINTER_DEVICE_TYPE_MAX = 0xFFFFFFFF
+} POINTER_DEVICE_TYPE;
+
+typedef struct tagPOINTER_DEVICE_INFO {
+ DWORD displayOrientation;
+ HANDLE device;
+ POINTER_DEVICE_TYPE pointerDeviceType;
+ HMONITOR monitor;
+ ULONG startingCursorId;
+ USHORT maxActiveContacts;
+ WCHAR productString[POINTER_DEVICE_PRODUCT_STRING_MAX];
+} POINTER_DEVICE_INFO;
+
#if defined(_WINGDI_) && !defined(NOGDI)
WINUSERAPI LONG WINAPI ChangeDisplaySettingsA(LPDEVMODEA,DWORD);
WINUSERAPI LONG WINAPI ChangeDisplaySettingsW(LPDEVMODEW,DWORD);
--
2.17.1
June 7, 2018
[PATCH 1/3] user32: Make RegisterPointerDeviceNotifications return TRUE to fake success
by Fabian Maurer
Fixes bug 45284.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/user32/misc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index be4b71a4bc..c3f4030a90 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -843,7 +843,7 @@ LONG WINAPI GetDisplayConfigBufferSizes(UINT32 flags, UINT32 *num_path_info, UIN
BOOL WINAPI RegisterPointerDeviceNotifications(HWND hwnd, BOOL notifyrange)
{
FIXME("(%p %d): stub\n", hwnd, notifyrange);
- return FALSE;
+ return TRUE;
}
static const WCHAR imeW[] = {'I','M','E',0};
--
2.17.1
June 7, 2018
Re: [PATCH 4/4] wsdapi: Add initial support for reading messages; identify Probe message.
by Owen Rudge
On 07/06/2018 08:56, Huw Davies wrote:
>> +static BOOL move_to_element(WS_XML_READER *reader, const char
*element_name, WS_XML_STRING *uri)
>
> return HRESULT
>
>> +static BOOL ws_element_to_wsdxml_element(WS_XML_READER *reader,
IWSDXMLContext *context, WSDXML_ELEMENT *parent_element)
>
> and here.
>
>> int read_message(const char *xml, int xml_length, WSD_SOAP_MESSAGE
**out_msg)
>
> This is also looking like a good contender to return HRESULT and
> take an [out] int *type parameter.
As per the previous patch, the HRESULT is not ultimately used, and I
can't see that there's a great benefit in passing it along. I do
understand it for the other functions that ultimately return a value to
the caller, but these functions are all called by the listener thread,
and a simple identification of the message type is all we require.
If you think it would be beneficial, I can modify these functions to
return HRESULT, but it would be good to understand the benefits of doing so.
>> - ok(any != NULL, "%s: any == NULL\n", debug_prefix);
>> + todo_wine ok(any != NULL, "%s: any == NULL\n", debug_prefix);
>
> You'll need to have a really good reason for doing this. Can you
> re-order things so you don't break the tests?
This will be fixed in the next patchset; I didn't want to include any
more code in what's already quite a large patch. There's probably an
extra 40 or so lines of code needed to avoid this breakage. There's not
really a way I can re-order this that I can think of.
If preferred though, I can submit the patch that will fix this as part
of this patchset, so the net result once the set is committed involves
no extra todos.
Thanks,
Owen
June 7, 2018
Re: [PATCH 3/4] wsdapi: Add stub for Probe message parsing, prepare notification sink message.
by Owen Rudge
On 07/06/2018 08:45, Huw Davies wrote:
>> +static void process_received_message(listener_thread_params
*params, char *message, int message_len,
>> + SOCKADDR_STORAGE *source_addr)
>
> This should return HRESULT.
There's not really anything that can be done with that result. If an
unknown message is received, I can add a trace for it, but an error
reading the message is not a reason to, for instance, stop listening on
the socket, so I'm not sure what purpose having a return value here
would serve.
Cheers,
Owen
June 7, 2018
[PATCH] po: Update Finnish translation.
by Lauri Kenttä
Signed-off-by: Lauri Kenttä <lauri.kentta(a)gmail.com>
---
po/fi.po | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/po/fi.po b/po/fi.po
index fce90dcccf..d654e904f2 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -12782,10 +12782,8 @@ msgid "Confirm Value Delete"
msgstr "Vahvista arvon tuhoaminen"
#: regedit.rc:210
-#, fuzzy
-#| msgid "Are you sure you want to delete the registry value '%1'?"
msgid "Are you sure you want to delete the selected registry value?"
-msgstr "Haluatko varmasti tuhota rekisteristä arvon '%1'?"
+msgstr "Haluatko varmasti tuhota rekisteristä valitun arvon?"
#: regedit.rc:216
msgid "Search complete. The string '%1' was not found."
--
2.17.1
June 7, 2018
Re: [PATCH] shellpath.c: Fix creation of HOME directory symbolic links
by Huw Davies
On 7 Jun 2018, at 16:11, Bob Wya <bob.mt.wya(a)gmail.com> wrote:
> Thanks for the valuable feedback! I think I spent quite a bit of time fiddling with this,
> so I've probably "lost the wood for the trees" a bit... :-)
>
> Just to clarify a style point, for the re-factored patches...
>
> If I still want to split the _SHCreateSymbolicLinks() function into a re-factored
> implementation that has an iterative wrapper function, is it OK to call them:
>
> _SHCreateSymbolicLink()
> _SHCreateSymbolicLinks()
>
> ??
> This would introduce a new "Camel Case" style function name... But would obviously
> be more consistent...
For new functions you’d avoid CamelCase and use something like
create_symbolic_link(). If might be ok to rename existing
functions if the patch is small enough. The problem at the
moment is that the patch is much too large.
Huw.
June 7, 2018
Re: [PATCH] shellpath.c: Fix creation of HOME directory symbolic links
by Bob Wya
On 7 June 2018 at 11:57, Huw Davies <huw(a)codeweavers.com> wrote:
> On Wed, Jun 06, 2018 at 08:46:49AM +0100, Rob Walker wrote:
> > Fixes: https://bugs.winehq.org/show_bug.cgi?id=41668 (1)
> > https://bugs.winehq.org/show_bug.cgi?id=28216 (2)
> >
> > (1) Introduces a "WINESYMLINK" env variable that allows a user to
> > control what shell folder links are created to the HOME folder, when
> > a WINEPREFIX is initially created.
> > The Wineprefix Shell Folders, that Wine symlinks to the user's HOME
> directory,
> > are only (re-)created on each Wine boot if they: do not pre-exist or
> are broken
> > symbolic links.
> >
> > (2) The XDG Directory specification automatically falls back to the user
> HOME
> > directory for any XDG_*_DIR that does not exist
> (xdg-user-dirs-update).
> > The implemented solution is to block Wine from symlinking directly
> > to HOME directory.
>
> Hi Rob,
>
> There's an awful lot going on in this patch which makes it very
> difficult to review. Please avoid re-naming and re-indenting
> existing functions so that we can actually see the real changes.
>
> Then please split the changes into separate patches. A clue
> that you're not doing this is that you have a list of two
> items in the commit message. If the patch is doing two
> things, it should be two patches.
>
> Huw.
>
>
Hi Huw,
Thanks for the valuable feedback! I think I spent quite a bit of time
fiddling with this,
so I've probably "lost the wood for the trees" a bit... :-)
Just to clarify a style point, for the re-factored patches...
If I still want to split the _SHCreateSymbolicLinks() function into a
re-factored
implementation that has an iterative wrapper function, is it OK to call
them:
_SHCreateSymbolicLink()
_SHCreateSymbolicLinks()
??
This would introduce a new "Camel Case" style function name... But would
obviously
be more consistent...
Thanks
Rob
> >
> > Test on Gentoo GNU/Linux.
> >
> > Signed-off-by: Rob Walker <bob.mt.wya(a)gmail.com>
> > ---
> > dlls/shell32/shellpath.c | 554 ++++++++++++++++++++++++---------------
> > 1 file changed, 343 insertions(+), 211 deletions(-)
> >
> > diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
> > index a551e93aa8..b8c74273c6 100644
> > --- a/dlls/shell32/shellpath.c
> > +++ b/dlls/shell32/shellpath.c
> > @@ -4326,252 +4326,259 @@ static HRESULT _SHRegisterCommonShellFolders(
> void)
> > }
> >
> > /***********************************************************
> *******************
> > - * _SHAppendToUnixPath [Internal]
> > + * append_to_unix_path [Internal]
> > *
> > - * Helper function for _SHCreateSymbolicLinks. Appends pwszSubPath (or
> the
> > - * corresponding resource, if IS_INTRESOURCE) to the unix base path
> 'szBasePath'
> > - * and replaces backslashes with slashes.
> > + * Helper function for create_home_subdir_symbolic_link.
> > + * Appends 'subpath', or the corresponding resource (if it is a
> > + * resource identifier), to the Unix base path 'base_dir'.
> > + * Replace backslashes with forward slashes.
> > *
> > * PARAMS
> > - * szBasePath [IO] The unix base path, which will be appended to
> (CP_UNXICP).
> > - * pwszSubPath [I] Sub-path or resource id (use MAKEINTRESOURCEW).
> > + * base_dir [IO] The Unix base path, which will be appended to
> (CP_UNXICP).
> > + * subpath [I] Sub-path or resource id (use MAKEINTRESOURCEW,
> pre-call).
> > *
> > * RETURNS
> > - * Success: TRUE,
> > + * Success: TRUE
> > * Failure: FALSE
> > */
> > -static inline BOOL _SHAppendToUnixPath(char *szBasePath, LPCWSTR
> pwszSubPath) {
> > - WCHAR wszSubPath[MAX_PATH];
> > - int cLen = strlen(szBasePath);
> > - char *pBackslash;
> > -
> > - if (IS_INTRESOURCE(pwszSubPath)) {
> > - if (!LoadStringW(shell32_hInstance, LOWORD(pwszSubPath),
> wszSubPath, MAX_PATH)) {
> > - /* Fall back to hard coded defaults. */
> > - switch (LOWORD(pwszSubPath)) {
> > - case IDS_PERSONAL:
> > - lstrcpyW(wszSubPath, DocumentsW);
> > - break;
> > - case IDS_MYMUSIC:
> > - lstrcpyW(wszSubPath, My_MusicW);
> > - break;
> > - case IDS_MYPICTURES:
> > - lstrcpyW(wszSubPath, My_PicturesW);
> > - break;
> > - case IDS_MYVIDEOS:
> > - lstrcpyW(wszSubPath, My_VideosW);
> > - break;
> > - default:
> > - ERR("LoadString(%d) failed!\n",
> LOWORD(pwszSubPath));
> > - return FALSE;
> > - }
> > +static inline BOOL append_to_unix_path(char *base_dir, LPCWSTR subpath)
> > +{
> > + WCHAR ws_subpath[MAX_PATH];
> > + int cLen = strlen(base_dir);
> > + char *back_slash;
> > +
> > + if (!IS_INTRESOURCE(subpath))
> > + {
> > + lstrcpyW(ws_subpath, subpath);
> > + }
> > + else if (!LoadStringW(shell32_hInstance, LOWORD(subpath),
> ws_subpath, MAX_PATH))
> > + {
> > + /* Fall back to hard coded defaults. */
> > + switch (LOWORD(subpath)) {
> > + case IDS_PERSONAL:
> > + lstrcpyW(ws_subpath, DocumentsW);
> > + break;
> > + case IDS_MYMUSIC:
> > + lstrcpyW(ws_subpath, My_MusicW);
> > + break;
> > + case IDS_MYPICTURES:
> > + lstrcpyW(ws_subpath, My_PicturesW);
> > + break;
> > + case IDS_MYVIDEOS:
> > + lstrcpyW(ws_subpath, My_VideosW);
> > + break;
> > + case IDS_DESKTOP:
> > + lstrcpyW(ws_subpath, DesktopW);
> > + break;
> > + default:
> > + ERR("LoadString(%d) failed!\n", LOWORD(subpath));
> > + return FALSE;
> > }
> > - } else {
> > - lstrcpyW(wszSubPath, pwszSubPath);
> > }
> > -
> > - if (szBasePath[cLen-1] != '/') szBasePath[cLen++] = '/';
> > -
> > - if (!WideCharToMultiByte(CP_UNIXCP, 0, wszSubPath, -1, szBasePath
> + cLen,
> > +
> > + if (!cLen || (base_dir[cLen-1] != '/')) base_dir[cLen++] = '/';
> > +
> > + if (!WideCharToMultiByte(CP_UNIXCP, 0, ws_subpath, -1, base_dir +
> cLen,
> > FILENAME_MAX - cLen, NULL, NULL))
> > {
> > return FALSE;
> > }
> > -
> > - pBackslash = szBasePath + cLen;
> > - while ((pBackslash = strchr(pBackslash, '\\'))) *pBackslash = '/';
> > -
> > +
> > + back_slash = base_dir + cLen;
> > + while ((back_slash = strchr(back_slash, '\\'))) *back_slash = '/';
> > +
> > return TRUE;
> > }
> >
> > /***********************************************************
> *******************
> > - * _SHCreateSymbolicLinks [Internal]
> > + * compare_pathft_to_bootft [Internal]
> > *
> > - * Sets up symbol links for various shell folders to point into the
> users home
> > - * directory. We do an educated guess about what the user would
> probably want:
> > - * - If there is a 'My Documents' directory in $HOME, the user probably
> wants
> > - * wine's 'My Documents' to point there. Furthermore, we imply that
> the user
> > - * is a Windows lover and has no problem with wine creating 'My
> Pictures',
> > - * 'My Music' and 'My Videos' subfolders under '$HOME/My Documents',
> if those
> > - * do not already exits. We put appropriate symbolic links in place
> for those,
> > - * too.
> > - * - If there is no 'My Documents' directory in $HOME, we let 'My
> Documents'
> > - * point directly to $HOME. We assume the user to be a unix hacker
> who does not
> > - * want wine to create anything anywhere besides the .wine directory.
> So, if
> > - * there already is a 'My Music' directory in $HOME, we symlink the
> 'My Music'
> > - * shell folder to it. But if not, then we check XDG_MUSIC_DIR -
> "well known"
> > - * directory, and try to link to that. If that fails, then we symlink
> to
> > - * $HOME directly. The same holds fo 'My Pictures' and 'My Videos'.
> > - * - The Desktop shell folder is symlinked to XDG_DESKTOP_DIR. If that
> does not
> > - * exist, then we try '$HOME/Desktop'. If that does not exist, then
> we leave
> > - * it alone.
> > - * ('My Music',... above in fact means LoadString(IDS_MYMUSIC))
> > + * Function to compare the FILETIME of ws_path (a Windows path) to the
> (estimated)
> > + * Wine System boot time.
> > + *
> > + * PARAMS
> > + * ws_path [I] The Windows path, for which provides the FS
> write time.
> > + * time_difference [O] -1 Windows path last written before time of
> Wine boot.
> > + * 0 Windows path last written at time of Wine
> boot.
> > + * +1 Windows path last written after time of
> Wine boot.
> > + * RETURNS
> > + * Success: S_OK
> > + * Failure: E_FAIL
> > + *
> > + * NOTES
> > + * Pre-allocate storage for time_difference pointer variable
> externally.
> > */
> > -static void _SHCreateSymbolicLinks(void)
> > -{
> > - UINT aidsMyStuff[] = { IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC },
> i;
> > - const WCHAR* MyOSXStuffW[] = { PicturesW, MoviesW, MusicW };
> > - int acsidlMyStuff[] = { CSIDL_MYPICTURES, CSIDL_MYVIDEO,
> CSIDL_MYMUSIC };
> > - static const char * const xdg_dirs[] = { "PICTURES", "VIDEOS",
> "MUSIC", "DOCUMENTS", "DESKTOP" };
> > - static const unsigned int num = ARRAY_SIZE(xdg_dirs);
> > - WCHAR wszTempPath[MAX_PATH];
> > - char szPersonalTarget[FILENAME_MAX], *pszPersonal;
> > - char szMyStuffTarget[FILENAME_MAX], *pszMyStuff;
> > - char szDesktopTarget[FILENAME_MAX], *pszDesktop;
> > - struct stat statFolder;
> > - const char *pszHome;
> > - HRESULT hr;
> > - char ** xdg_results;
> > - char * xdg_desktop_dir;
> > -
> > - /* Create all necessary profile sub-dirs up to 'My Documents' and
> get the unix path. */
> > - hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
> > - SHGFP_TYPE_DEFAULT, wszTempPath);
> > - if (FAILED(hr)) return;
> > - pszPersonal = wine_get_unix_file_name(wszTempPath);
> > - if (!pszPersonal) return;
> > +static HRESULT compare_pathft_to_bootft(const WCHAR * ws_path, int *
> time_difference)
> > +{
> > + static ULONG64 time_system_start = 0;
> > + SYSTEMTIME system_time_st;
> > + FILETIME dummy_ft, system_time_ft, last_write_ft;
> > + ULONG64 tick_count, time_last_write;
> > + HANDLE fhandle;
> > + DWORD ft_errorc = 0;
> >
> > - hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
> > - if (FAILED(hr)) xdg_results = NULL;
> > + if (!time_difference) return E_FAIL;
> >
> > - pszHome = getenv("HOME");
> > - if (pszHome && !stat(pszHome, &statFolder) &&
> S_ISDIR(statFolder.st_mode))
> > + if (!time_system_start)
> > {
> > - while (1)
> > + tick_count = (ULONG64) GetTickCount64();
> > + GetSystemTime(&system_time_st);
> > + if (!SystemTimeToFileTime( &system_time_st, &system_time_ft))
> > {
> > - /* Check if there's already a Wine-specific 'My Documents'
> folder */
> > - strcpy(szPersonalTarget, pszHome);
> > - if (_SHAppendToUnixPath(szPersonalTarget,
> MAKEINTRESOURCEW(IDS_PERSONAL)) &&
> > - !stat(szPersonalTarget, &statFolder) &&
> S_ISDIR(statFolder.st_mode))
> > - {
> > - /* '$HOME/My Documents' exists. Create 'My Pictures',
> > - * 'My Videos' and 'My Music' subfolders or fail
> silently if
> > - * they already exist.
> > - */
> > - for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
> > - {
> > - strcpy(szMyStuffTarget, szPersonalTarget);
> > - if (_SHAppendToUnixPath(szMyStuffTarget,
> MAKEINTRESOURCEW(aidsMyStuff[i])))
> > - mkdir(szMyStuffTarget, 0777);
> > - }
> > - break;
> > - }
> > -
> > - /* Try to point to the XDG Documents folder */
> > - if (xdg_results && xdg_results[num-2] &&
> > - !stat(xdg_results[num-2], &statFolder) &&
> > - S_ISDIR(statFolder.st_mode))
> > - {
> > - strcpy(szPersonalTarget, xdg_results[num-2]);
> > - break;
> > - }
> > -
> > - /* Or the hardcoded / OS X Documents folder */
> > - strcpy(szPersonalTarget, pszHome);
> > - if (_SHAppendToUnixPath(szPersonalTarget, DocumentsW) &&
> > - !stat(szPersonalTarget, &statFolder) &&
> > - S_ISDIR(statFolder.st_mode))
> > - break;
> > -
> > - /* As a last resort point to $HOME. */
> > - strcpy(szPersonalTarget, pszHome);
> > - break;
> > + ERR("SystemTimeToFileTime call failed (%d)\n",
> GetLastError());
> > + return E_FAIL;
> > }
> > -
> > - /* Replace 'My Documents' directory with a symlink or fail
> silently if not empty. */
> > - remove(pszPersonal);
> > - symlink(szPersonalTarget, pszPersonal);
> > + time_system_start = (((ULONG64)system_time_ft.dwHighDateTime)
> << 32)
> > + + system_time_ft.dwLowDateTime
> > + - (tick_count * 10000);
> > }
> > - else
> > + fhandle = CreateFileW( ws_path, 0, FILE_SHARE_READ, NULL,
> > + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
> NULL);
> > + if (fhandle == INVALID_HANDLE_VALUE)
> > {
> > - /* '$HOME' doesn't exist. Create 'My Pictures', 'My Videos' and
> 'My Music' subdirs
> > - * in '%USERPROFILE%\\My Documents' or fail silently if they
> already exist. */
> > - pszHome = NULL;
> > - strcpy(szPersonalTarget, pszPersonal);
> > - for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
> > - strcpy(szMyStuffTarget, szPersonalTarget);
> > - if (_SHAppendToUnixPath(szMyStuffTarget,
> MAKEINTRESOURCEW(aidsMyStuff[i])))
> > - mkdir(szMyStuffTarget, 0777);
> > - }
> > + ERR("Open file handle failed for path: %s (%d)\n",
> > + debugstr_w(ws_path), GetLastError());
> > + return E_FAIL;
> > }
> > -
> > - /* Create symbolic links for 'My Pictures', 'My Videos' and 'My
> Music'. */
> > - for (i=0; i < ARRAY_SIZE(aidsMyStuff); i++)
> > + if (!GetFileTime(fhandle, &dummy_ft, &dummy_ft, &last_write_ft))
> > + ft_errorc = GetLastError();
> > + if (!CloseHandle(fhandle))
> > {
> > - /* Create the current 'My Whatever' folder and get its unix
> path. */
> > - hr = SHGetFolderPathW(NULL, acsidlMyStuff[i]|CSIDL_FLAG_CREATE,
> NULL,
> > - SHGFP_TYPE_DEFAULT, wszTempPath);
> > - if (FAILED(hr)) continue;
> > -
> > - pszMyStuff = wine_get_unix_file_name(wszTempPath);
> > - if (!pszMyStuff) continue;
> > -
> > - while (1)
> > - {
> > - /* Check for the Wine-specific '$HOME/My Documents'
> subfolder */
> > - strcpy(szMyStuffTarget, szPersonalTarget);
> > - if (_SHAppendToUnixPath(szMyStuffTarget,
> MAKEINTRESOURCEW(aidsMyStuff[i])) &&
> > - !stat(szMyStuffTarget, &statFolder) &&
> S_ISDIR(statFolder.st_mode))
> > - break;
> > + ERR("Close file handle failed: %p (%d)\n",
> > + fhandle, GetLastError());
> > + return E_FAIL;
> > + }
> > + if (ft_errorc)
> > + {
> > + ERR("Get file time failed: %p (%d)\n",
> > + fhandle, ft_errorc);
> > + return E_FAIL;
> > + }
> > + time_last_write = (((ULONG64)last_write_ft.dwHighDateTime) << 32)
> > + + last_write_ft.dwLowDateTime;
> > + *time_difference = ((time_last_write > time_system_start) ? 1 :
> > + ((time_last_write < time_system_start) ? -1 :
> > + 0));
> >
> > - /* Try the XDG_XXX_DIR folder */
> > - if (xdg_results && xdg_results[i])
> > - {
> > - strcpy(szMyStuffTarget, xdg_results[i]);
> > - break;
> > - }
> > + return S_OK;
> > +}
> >
> > - /* Or the OS X folder (these are never localized) */
> > - if (pszHome)
> > - {
> > - strcpy(szMyStuffTarget, pszHome);
> > - if (_SHAppendToUnixPath(szMyStuffTarget,
> MyOSXStuffW[i]) &&
> > - !stat(szMyStuffTarget, &statFolder) &&
> > - S_ISDIR(statFolder.st_mode))
> > - break;
> > - }
> > +/**********************************************************
> ********************
> > + * create_homedir_symbolic_link [Internal]
> > + *
> > + * Creates a symbolic link from the current Wineprefix to an appropriate
> > + * HOME subdirectory (if one is found).
> > + *
> > + * Creates 'XXXX' directory in Wineprefix.
> > + * Then create a 'My XXXX' symbolic link in Wineprefix:
> > + * 1) If '$HOME/XXXX' (IDS directory) exists then target this.
> > + * 2) If '$HOME/XXXX' (XDG_XXXX_DIR) exists then target this.
> > + * 3) If '$HOME/XXXX' (MacOS XXXX media directory) exists then target
> this.
> > + *
> > + * PARAMS
> > + * env_enabled [I]
> > + * TRUE The user has enabled this Shell Folder to be
> symlinked (default).
> > + * FALSE The user has chosen to disable symlinking this
> Shell Folder.
> > + * The Shell Folder will be created, in the current
> Wineprefix (if not pre-existing).
> > + * ids_dir [I] Windows Resource Identifier code for current Shell
> Folder.
> > + * csidl_dir [I] Constant Special Item ID List identifier for
> current Shell Folder.
> > + * xdg_dir [I] Full path of external Unix XDG directory
> corresponding to current Shell Folder.
> > + * ws_osx_dir [I] Fallback directory name to use, corresponding to
> current Shell Folder (OSX specific).
> > + *
> > + */
> > +void create_homedir_symbolic_link(BOOL env_enabled,
> > + UINT ids_dir,
> > + int csidl_dir,
> > + const char * xdg_dir,
> > + const WCHAR * ws_osx_dir)
> > +{
> > + static const char * env_homedir = NULL;
> > + WCHAR ws_temp_path[MAX_PATH];
> > + char home_target[FILENAME_MAX], * prefix_dir;
> > + struct stat stat_folder, stat_home_folder;
> > + HRESULT hr;
> > + BOOL target_ok;
> > + int time_difference;
> >
> > - /* As a last resort point to the same location as 'My
> Documents' */
> > - strcpy(szMyStuffTarget, szPersonalTarget);
> > - break;
> > + hr = SHGetFolderPathW(NULL, csidl_dir, NULL,
> > + SHGFP_TYPE_DEFAULT, ws_temp_path);
> > + if (SUCCEEDED(hr))
> > + {
> > + if (ids_dir != IDS_DESKTOPDIRECTORY) return;
> > +
> > + if ((compare_pathft_to_bootft(ws_temp_path, &time_difference)
> == S_OK)
> > + && (time_difference < 0))
> > + {
> > + TRACE("%s directory created before wineboot\n",
> > + debugstr_w(ws_temp_path));
> > + return;
> > }
> > - remove(pszMyStuff);
> > - symlink(szMyStuffTarget, pszMyStuff);
> > - heap_free(pszMyStuff);
> > }
> > -
> > - /* Last but not least, the Desktop folder */
> > - if (pszHome)
> > - strcpy(szDesktopTarget, pszHome);
> > + else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
> > + {
> > + hr = SHGetFolderPathW(NULL, csidl_dir|CSIDL_FLAG_CREATE, NULL,
> > + SHGFP_TYPE_DEFAULT, ws_temp_path);
> > + if (FAILED(hr)) return;
> > + }
> > else
> > - strcpy(szDesktopTarget, pszPersonal);
> > - heap_free(pszPersonal);
> > + {
> > + ERR("Failed to get Wineprefix path corresponding to %d CSIDL\n",
> > + csidl_dir);
> > + return;
> > + }
> > + if (!env_enabled) return;
> > + prefix_dir = wine_get_unix_file_name(ws_temp_path);
> > + if (!prefix_dir)
> > + {
> > + ERR("Failed to get Unix Wineprefix directory for: %s\n",
> > + debugstr_w(ws_temp_path));
> > + return;
> > + }
> > + if (!env_homedir) env_homedir = getenv("HOME");
> > + if (!(env_homedir
> > + && (stat(env_homedir, &stat_home_folder) != 1)
> > + && S_ISDIR(stat_home_folder.st_mode)))
> > + {
> > + if (prefix_dir) heap_free(prefix_dir);
> > + return;
> > + }
> >
> > - xdg_desktop_dir = xdg_results ? xdg_results[num - 1] : NULL;
> > - if (xdg_desktop_dir ||
> > - (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
> > - !stat(szDesktopTarget, &statFolder) &&
> S_ISDIR(statFolder.st_mode)))
> > + /* Check for:
> > + * '$HOME/XXXX' (IDS directory)
> > + * or '$HOME/XXXX' (XDG directory)
> > + * or '$HOME/XXXX' (MacOS directory)
> > + */
> > + target_ok = FALSE;
> > + strcpy(home_target, env_homedir);
> > + if (append_to_unix_path(home_target, MAKEINTRESOURCEW(ids_dir))
> > + && (stat(home_target, &stat_folder) != -1)
> > + && S_ISDIR(stat_folder.st_mode))
> > {
> > - hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE,
> NULL,
> > - SHGFP_TYPE_DEFAULT, wszTempPath);
> > - if (SUCCEEDED(hr) && (pszDesktop =
> wine_get_unix_file_name(wszTempPath)))
> > - {
> > - remove(pszDesktop);
> > - if (xdg_desktop_dir)
> > - symlink(xdg_desktop_dir, pszDesktop);
> > - else
> > - symlink(szDesktopTarget, pszDesktop);
> > - heap_free(pszDesktop);
> > - }
> > + target_ok = TRUE;
> > + }
> > + else if (xdg_dir && stat(xdg_dir, &stat_folder))
> > + {
> > + strcpy(home_target, xdg_dir);
> > + /* Only link to the XDG directory, if it does not point directly
> > + * to the user's HOME directory (XDG specification fallback
> path). */
> > + target_ok = (stat_folder.st_ino != stat_home_folder.st_ino);
> > + }
> > + else
> > + {
> > + strcpy(home_target, env_homedir);
> > + target_ok = append_to_unix_path(home_target, ws_osx_dir)
> > + && (stat(home_target, &stat_folder) != -1)
> > + && S_ISDIR(stat_folder.st_mode);
> > }
> >
> > - /* Free resources allocated by XDG_UserDirLookup() */
> > - if (xdg_results)
> > + if (target_ok)
> > {
> > - for (i = 0; i < num; i++)
> > - heap_free(xdg_results[i]);
> > - heap_free(xdg_results);
> > + remove(prefix_dir);
> > + symlink(home_target, prefix_dir);
> > }
> > +
> > +
> > + if (prefix_dir) heap_free(prefix_dir);
> > }
> >
> > /***********************************************************
> *******************
> > @@ -6126,15 +6133,139 @@ static void register_system_knownfolders(void)
> > }
> > }
> >
> > +/**********************************************************
> ********************
> > + * parse_symlinks_env_variable [Internal]
> > + *
> > + * PARAMS
> > + * xdg_dir [I] Unix XDG directory name (without "XDG_" prefix and
> "_DIR" suffix).
> > + *
> > + * RETURNS
> > + * TRUE "WINESYMLINK" contains the specified XDG directory string.
> > + * FALSE "WINESYMLINK" does not contain the specified XDG directory
> string.
> > + * Any error condition.
> > + *
> > + * Note: "WINESYMLINK", defaults to "ALL", when unset. This enables all
> symlinks.
> > + * "WINESYMLINK" can also be manually set to "ALL", enabling all
> symlinks.
> > + *
> > + */
> > +static BOOL parse_symlinks_env_variable(const char * xdg_dir)
> > +{
> > + static const char * matchall_env_var = "ALL";
> > + static char env_var[MAX_PATH+1];
> > + static char * env_winesymlink = NULL;
> > + char * sstr, * sstr_stop, * tstr, * word_start = NULL;
> > + char seperator_ch = '\0';
> > + BOOL end_string, in_word = FALSE, matched = FALSE;
> > + size_t slength = 0, matchall_length, xdg_dir_slength;
> > +
> > + if (!xdg_dir) return matched;
> > +
> > + if (!env_winesymlink)
> > + {
> > + env_winesymlink = getenv("WINESYMLINK");
> > + if (!env_winesymlink) env_winesymlink = (char*)
> matchall_env_var;
> > + tstr = env_var;
> > + sstr_stop = env_winesymlink + MAX_PATH;
> > + for (sstr = env_winesymlink; *sstr && (sstr != sstr_stop);
> ++sstr)
> > + {
> > + if (!seperator_ch && (ispunct(*sstr) || isspace(*sstr)))
> > + seperator_ch = *sstr;
> > + if (!isalpha(*sstr)) continue;
> > +
> > + if (seperator_ch && in_word)
> > + {
> > + *tstr++ = seperator_ch;
> > + ++slength;
> > + }
> > + in_word = TRUE;
> > + seperator_ch = '\0';
> > + *tstr++ = toupper(*sstr);
> > + ++slength;
> > + }
> > + env_var[slength] = '\0';
> > + }
> > +
> > + TRACE("processed env variable: %s\n", debugstr_a(&env_var[0]));
> > + matchall_length = strlen(matchall_env_var);
> > + xdg_dir_slength = strlen(xdg_dir);
> > + end_string = !(env_var[0]);
> > + for (sstr = &env_var[0]; !end_string; ++sstr)
> > + {
> > + end_string = !(*(sstr+1));
> > + in_word = isalpha(*sstr);
> > + if (in_word && !word_start) word_start = sstr;
> > + in_word = in_word && !end_string;
> > + if (in_word || !word_start) continue;
> > +
> > + slength = ((size_t) (sstr-word_start))+(end_string ? 1 : 0);
> > + matched = ( (slength == xdg_dir_slength) &&
> (strncmp(word_start, xdg_dir, slength) == 0) )
> > + || ( (slength == matchall_length) &&
> (strncmp(word_start, "ALL", slength) == 0) );
> > + if (matched) break;
> > +
> > + word_start = NULL;
> > + }
> > + TRACE("%s symlinking for %s\n", matched ? "Enabled" : "Disabled",
> debugstr_a(xdg_dir));
> > +
> > + return matched;
> > +}
> > +
> > +/**********************************************************
> ********************
> > + * create_homedir_symbolic_links [Internal]
> > + *
> > + * Parse WINESYMLINK env variable, for each XDG directory argument. To
> test if symlinking is
> > + * enabled for that XDG directory / Wine Profile Folder.
> > + * Then calls the function create_homedir_symbolic_link to potentially
> symlink from a Shell Folder,
> > + * in the current Wineprefix, to a subdirectory of the current user's
> HOME directory.
> > + *
> > + * PARAMS
> > + * xdg_dirnames [I] Pointer to an array of Unix XDG directory names
> > + * (without "XDG_" prefix and "_DIR" suffix).
> > + * xdg_dir_count [I] Item count of array (above).
> > + *
> > + */
> > +static void create_homedir_symbolic_links(const char * const
> xdg_dirnames[], const UINT xdg_dir_count)
> > +{
> > + char ** xdg_dirs_array;
> > + char * xdg_dir;
> > + HRESULT hr;
> > + UINT i;
> > + BOOL env_enabled;
> > +
> > + if (!xdg_dirnames) return;
> > +
> > + hr = XDG_UserDirLookup(xdg_dirnames, xdg_dir_count,
> &xdg_dirs_array);
> > + if (FAILED(hr)) xdg_dirs_array = NULL;
> > +
> > + for (i = 0; i < xdg_dir_count; ++i)
> > + {
> > + env_enabled = parse_symlinks_env_variable(xdg_dirnames[i]);
> > + xdg_dir = xdg_dirs_array ? xdg_dirs_array[i] : NULL;
> > + if (!strcmp(xdg_dirnames[i],"DOCUMENTS"))
> > + create_homedir_symbolic_link(env_enabled, IDS_PERSONAL,
> CSIDL_PERSONAL, xdg_dir, DocumentsW);
> > + else if (!strcmp(xdg_dirnames[i],"PICTURES"))
> > + create_homedir_symbolic_link(env_enabled, IDS_MYPICTURES,
> CSIDL_MYPICTURES, xdg_dir, PicturesW);
> > + else if (!strcmp(xdg_dirnames[i],"VIDEOS"))
> > + create_homedir_symbolic_link(env_enabled, IDS_MYVIDEOS,
> CSIDL_MYVIDEO, xdg_dir, MoviesW);
> > + else if (!strcmp(xdg_dirnames[i],"MUSIC"))
> > + create_homedir_symbolic_link(env_enabled, IDS_MYMUSIC,
> CSIDL_MYMUSIC, xdg_dir, MusicW);
> > + else if (!strcmp(xdg_dirnames[i],"DESKTOP"))
> > + create_homedir_symbolic_link(env_enabled,
> IDS_DESKTOPDIRECTORY, CSIDL_DESKTOPDIRECTORY, xdg_dir, DesktopW);
> > + else
> > + ERR("XDG directory name specifier invalid: %s\n",
> debugstr_a(xdg_dirnames[i]));
> > + if (xdg_dir) heap_free(xdg_dirs_array[i]);
> > + }
> > + if (xdg_dirs_array) heap_free(xdg_dirs_array);
> > +}
> > +
> > HRESULT SHELL_RegisterShellFolders(void)
> > {
> > + static const char * const xdg_dirnames[] = { "DOCUMENTS",
> "PICTURES", "VIDEOS", "MUSIC", "DESKTOP" };
> > + const UINT xdg_dir_count = 5;
> > HRESULT hr;
> >
> > - /* Set up '$HOME' targeted symlinks for 'My Documents', 'My
> Pictures',
> > - * 'My Videos', 'My Music' and 'Desktop' in advance, so that the
> > - * _SHRegister*ShellFolders() functions will find everything nice
> and clean
> > - * and thus will not attempt to create them in the profile
> directory. */
> > - _SHCreateSymbolicLinks();
> > + /* Early setup of symlinks from specific User Shell Folders, in
> > + * current Wineprefix, to subdirecties of the user's HOME
> directory. */
> > + create_homedir_symbolic_links(xdg_dirnames, xdg_dir_count);
> >
> > hr = _SHRegisterUserShellFolders(TRUE);
> > if (SUCCEEDED(hr))
> > @@ -6147,5 +6278,6 @@ HRESULT SHELL_RegisterShellFolders(void)
> > hr = set_folder_attributes();
> > if (SUCCEEDED(hr))
> > register_system_knownfolders();
> > +
> > return hr;
> > }
> > --
> > 2.17.1
> >
> >
> >
>
June 7, 2018
Re: [PATCH 1/5] wined3d: Declare the correct number and type of fragment shader color outputs.
by Henri Verbeet
On 6 June 2018 at 00:32, Matteo Bruni <mbruni(a)codeweavers.com> wrote:
> Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
> ---
> dlls/wined3d/glsl_shader.c | 116 ++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 109 insertions(+), 7 deletions(-)
>
This fails the tests here:
../../../../../src/wine-git/tools/runtest -q -P wine -T ../../.. -M
d3d10core.dll -p d3d10core_test.exe.so device && touch device.ok
device.c:11300: Test failed: Got 0xff0000ff, expected 0xff00ff00 at
(0, 0), sub-resource 0.
device.c:11307: Test failed: Got 0xff0000ff, expected 0xff00ff00 at
(0, 0), sub-resource 0.
../../../../../src/wine-git/tools/runtest -q -P wine -T ../../.. -M
d3d11.dll -p d3d11_test.exe.so d3d11 && touch d3d11.ok
d3d11.c:14777: Test failed: Got 0xff0000ff, expected 0xff00ff00 at (0,
0, 0), sub-resource 0.
d3d11.c:14784: Test failed: Got 0xff0000ff, expected 0xff00ff00 at (0,
0, 0), sub-resource 0.
d3d11.c:20644: Tests skipped: Raw buffers are not supported.
d3d11.c:20644: Tests skipped: Raw buffers are not supported.
June 7, 2018
Re: [PATCH vkd3d] libs/vkd3d: Use VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT only if array size is >= 6.
by Henri Verbeet
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
June 7, 2018
Re: [PATCH vkd3d] libs/vkd3d: Use VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT only if array size is >= 6.
by Józef Kucia
On Thu, Jun 7, 2018 at 4:03 PM, Henri Verbeet <hverbeet(a)gmail.com> wrote:
> On 7 June 2018 at 15:52, Józef Kucia <joseph.kucia(a)gmail.com> wrote:
>> + if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
>> + && desc->Width == desc->Height && desc->DepthOrArraySize >= 6)
>> image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
> Should that be a multiple of 6? I.e., are partial cubemap arrays a
> thing in Direct3D 12?
I think you can create a cube shader resource view for 2D textures,
even if the array size is not a multiple of 6. At least, it works that
way in Direct3D 11. We have some tests in
test_create_shader_resource_view().
June 7, 2018
Re: [PATCH vkd3d] libs/vkd3d: Use VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT only if array size is >= 6.
by Henri Verbeet
On 7 June 2018 at 15:52, Józef Kucia <joseph.kucia(a)gmail.com> wrote:
> + if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
> + && desc->Width == desc->Height && desc->DepthOrArraySize >= 6)
> image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
Should that be a multiple of 6? I.e., are partial cubemap arrays a
thing in Direct3D 12?
June 7, 2018
[PATCH vkd3d] libs/vkd3d: Use VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT only if array size is >= 6.
by Józef Kucia
From: Józef Kucia <jkucia(a)codeweavers.com>
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
libs/vkd3d/resource.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index acd3bada63ec..2ccb84797514 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -132,7 +132,8 @@ static HRESULT vkd3d_create_image(struct d3d12_resource *resource, struct d3d12_
image_info.flags = 0;
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) && dxgi_format_is_typeless(desc->Format))
image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
- if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc->Width == desc->Height)
+ if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
+ && desc->Width == desc->Height && desc->DepthOrArraySize >= 6)
image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
image_info.imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension);
--
2.16.4
June 7, 2018
Re: [PATCH v2 1/4] kernel32: Return BIOS info from GetSystemFirmwareTable on Linux
by Huw Davies
On Mon, May 28, 2018 at 10:05:26PM -0600, Alex Henrie wrote:
> /***********************************************************************
> * GetSystemFirmwareTable (KERNEL32.@)
> */
> UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size)
> {
> - FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
> + FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
This should probably be forwarded to
NtQuerySystemInformation(SystemFirmwareTableInformation, ...).
Huw.
June 7, 2018
Re: [PATCH] shellpath.c: Fix creation of HOME directory symbolic links
by Huw Davies
On Wed, Jun 06, 2018 at 08:46:49AM +0100, Rob Walker wrote:
> Fixes: https://bugs.winehq.org/show_bug.cgi?id=41668 (1)
> https://bugs.winehq.org/show_bug.cgi?id=28216 (2)
>
> (1) Introduces a "WINESYMLINK" env variable that allows a user to
> control what shell folder links are created to the HOME folder, when
> a WINEPREFIX is initially created.
> The Wineprefix Shell Folders, that Wine symlinks to the user's HOME directory,
> are only (re-)created on each Wine boot if they: do not pre-exist or are broken
> symbolic links.
>
> (2) The XDG Directory specification automatically falls back to the user HOME
> directory for any XDG_*_DIR that does not exist (xdg-user-dirs-update).
> The implemented solution is to block Wine from symlinking directly
> to HOME directory.
Hi Rob,
There's an awful lot going on in this patch which makes it very
difficult to review. Please avoid re-naming and re-indenting
existing functions so that we can actually see the real changes.
Then please split the changes into separate patches. A clue
that you're not doing this is that you have a list of two
items in the commit message. If the patch is doing two
things, it should be two patches.
Huw.
>
> Test on Gentoo GNU/Linux.
>
> Signed-off-by: Rob Walker <bob.mt.wya(a)gmail.com>
> ---
> dlls/shell32/shellpath.c | 554 ++++++++++++++++++++++++---------------
> 1 file changed, 343 insertions(+), 211 deletions(-)
>
> diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
> index a551e93aa8..b8c74273c6 100644
> --- a/dlls/shell32/shellpath.c
> +++ b/dlls/shell32/shellpath.c
> @@ -4326,252 +4326,259 @@ static HRESULT _SHRegisterCommonShellFolders(void)
> }
>
> /******************************************************************************
> - * _SHAppendToUnixPath [Internal]
> + * append_to_unix_path [Internal]
> *
> - * Helper function for _SHCreateSymbolicLinks. Appends pwszSubPath (or the
> - * corresponding resource, if IS_INTRESOURCE) to the unix base path 'szBasePath'
> - * and replaces backslashes with slashes.
> + * Helper function for create_home_subdir_symbolic_link.
> + * Appends 'subpath', or the corresponding resource (if it is a
> + * resource identifier), to the Unix base path 'base_dir'.
> + * Replace backslashes with forward slashes.
> *
> * PARAMS
> - * szBasePath [IO] The unix base path, which will be appended to (CP_UNXICP).
> - * pwszSubPath [I] Sub-path or resource id (use MAKEINTRESOURCEW).
> + * base_dir [IO] The Unix base path, which will be appended to (CP_UNXICP).
> + * subpath [I] Sub-path or resource id (use MAKEINTRESOURCEW, pre-call).
> *
> * RETURNS
> - * Success: TRUE,
> + * Success: TRUE
> * Failure: FALSE
> */
> -static inline BOOL _SHAppendToUnixPath(char *szBasePath, LPCWSTR pwszSubPath) {
> - WCHAR wszSubPath[MAX_PATH];
> - int cLen = strlen(szBasePath);
> - char *pBackslash;
> -
> - if (IS_INTRESOURCE(pwszSubPath)) {
> - if (!LoadStringW(shell32_hInstance, LOWORD(pwszSubPath), wszSubPath, MAX_PATH)) {
> - /* Fall back to hard coded defaults. */
> - switch (LOWORD(pwszSubPath)) {
> - case IDS_PERSONAL:
> - lstrcpyW(wszSubPath, DocumentsW);
> - break;
> - case IDS_MYMUSIC:
> - lstrcpyW(wszSubPath, My_MusicW);
> - break;
> - case IDS_MYPICTURES:
> - lstrcpyW(wszSubPath, My_PicturesW);
> - break;
> - case IDS_MYVIDEOS:
> - lstrcpyW(wszSubPath, My_VideosW);
> - break;
> - default:
> - ERR("LoadString(%d) failed!\n", LOWORD(pwszSubPath));
> - return FALSE;
> - }
> +static inline BOOL append_to_unix_path(char *base_dir, LPCWSTR subpath)
> +{
> + WCHAR ws_subpath[MAX_PATH];
> + int cLen = strlen(base_dir);
> + char *back_slash;
> +
> + if (!IS_INTRESOURCE(subpath))
> + {
> + lstrcpyW(ws_subpath, subpath);
> + }
> + else if (!LoadStringW(shell32_hInstance, LOWORD(subpath), ws_subpath, MAX_PATH))
> + {
> + /* Fall back to hard coded defaults. */
> + switch (LOWORD(subpath)) {
> + case IDS_PERSONAL:
> + lstrcpyW(ws_subpath, DocumentsW);
> + break;
> + case IDS_MYMUSIC:
> + lstrcpyW(ws_subpath, My_MusicW);
> + break;
> + case IDS_MYPICTURES:
> + lstrcpyW(ws_subpath, My_PicturesW);
> + break;
> + case IDS_MYVIDEOS:
> + lstrcpyW(ws_subpath, My_VideosW);
> + break;
> + case IDS_DESKTOP:
> + lstrcpyW(ws_subpath, DesktopW);
> + break;
> + default:
> + ERR("LoadString(%d) failed!\n", LOWORD(subpath));
> + return FALSE;
> }
> - } else {
> - lstrcpyW(wszSubPath, pwszSubPath);
> }
> -
> - if (szBasePath[cLen-1] != '/') szBasePath[cLen++] = '/';
> -
> - if (!WideCharToMultiByte(CP_UNIXCP, 0, wszSubPath, -1, szBasePath + cLen,
> +
> + if (!cLen || (base_dir[cLen-1] != '/')) base_dir[cLen++] = '/';
> +
> + if (!WideCharToMultiByte(CP_UNIXCP, 0, ws_subpath, -1, base_dir + cLen,
> FILENAME_MAX - cLen, NULL, NULL))
> {
> return FALSE;
> }
> -
> - pBackslash = szBasePath + cLen;
> - while ((pBackslash = strchr(pBackslash, '\\'))) *pBackslash = '/';
> -
> +
> + back_slash = base_dir + cLen;
> + while ((back_slash = strchr(back_slash, '\\'))) *back_slash = '/';
> +
> return TRUE;
> }
>
> /******************************************************************************
> - * _SHCreateSymbolicLinks [Internal]
> + * compare_pathft_to_bootft [Internal]
> *
> - * Sets up symbol links for various shell folders to point into the users home
> - * directory. We do an educated guess about what the user would probably want:
> - * - If there is a 'My Documents' directory in $HOME, the user probably wants
> - * wine's 'My Documents' to point there. Furthermore, we imply that the user
> - * is a Windows lover and has no problem with wine creating 'My Pictures',
> - * 'My Music' and 'My Videos' subfolders under '$HOME/My Documents', if those
> - * do not already exits. We put appropriate symbolic links in place for those,
> - * too.
> - * - If there is no 'My Documents' directory in $HOME, we let 'My Documents'
> - * point directly to $HOME. We assume the user to be a unix hacker who does not
> - * want wine to create anything anywhere besides the .wine directory. So, if
> - * there already is a 'My Music' directory in $HOME, we symlink the 'My Music'
> - * shell folder to it. But if not, then we check XDG_MUSIC_DIR - "well known"
> - * directory, and try to link to that. If that fails, then we symlink to
> - * $HOME directly. The same holds fo 'My Pictures' and 'My Videos'.
> - * - The Desktop shell folder is symlinked to XDG_DESKTOP_DIR. If that does not
> - * exist, then we try '$HOME/Desktop'. If that does not exist, then we leave
> - * it alone.
> - * ('My Music',... above in fact means LoadString(IDS_MYMUSIC))
> + * Function to compare the FILETIME of ws_path (a Windows path) to the (estimated)
> + * Wine System boot time.
> + *
> + * PARAMS
> + * ws_path [I] The Windows path, for which provides the FS write time.
> + * time_difference [O] -1 Windows path last written before time of Wine boot.
> + * 0 Windows path last written at time of Wine boot.
> + * +1 Windows path last written after time of Wine boot.
> + * RETURNS
> + * Success: S_OK
> + * Failure: E_FAIL
> + *
> + * NOTES
> + * Pre-allocate storage for time_difference pointer variable externally.
> */
> -static void _SHCreateSymbolicLinks(void)
> -{
> - UINT aidsMyStuff[] = { IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC }, i;
> - const WCHAR* MyOSXStuffW[] = { PicturesW, MoviesW, MusicW };
> - int acsidlMyStuff[] = { CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_MYMUSIC };
> - static const char * const xdg_dirs[] = { "PICTURES", "VIDEOS", "MUSIC", "DOCUMENTS", "DESKTOP" };
> - static const unsigned int num = ARRAY_SIZE(xdg_dirs);
> - WCHAR wszTempPath[MAX_PATH];
> - char szPersonalTarget[FILENAME_MAX], *pszPersonal;
> - char szMyStuffTarget[FILENAME_MAX], *pszMyStuff;
> - char szDesktopTarget[FILENAME_MAX], *pszDesktop;
> - struct stat statFolder;
> - const char *pszHome;
> - HRESULT hr;
> - char ** xdg_results;
> - char * xdg_desktop_dir;
> -
> - /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */
> - hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
> - SHGFP_TYPE_DEFAULT, wszTempPath);
> - if (FAILED(hr)) return;
> - pszPersonal = wine_get_unix_file_name(wszTempPath);
> - if (!pszPersonal) return;
> +static HRESULT compare_pathft_to_bootft(const WCHAR * ws_path, int * time_difference)
> +{
> + static ULONG64 time_system_start = 0;
> + SYSTEMTIME system_time_st;
> + FILETIME dummy_ft, system_time_ft, last_write_ft;
> + ULONG64 tick_count, time_last_write;
> + HANDLE fhandle;
> + DWORD ft_errorc = 0;
>
> - hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
> - if (FAILED(hr)) xdg_results = NULL;
> + if (!time_difference) return E_FAIL;
>
> - pszHome = getenv("HOME");
> - if (pszHome && !stat(pszHome, &statFolder) && S_ISDIR(statFolder.st_mode))
> + if (!time_system_start)
> {
> - while (1)
> + tick_count = (ULONG64) GetTickCount64();
> + GetSystemTime(&system_time_st);
> + if (!SystemTimeToFileTime( &system_time_st, &system_time_ft))
> {
> - /* Check if there's already a Wine-specific 'My Documents' folder */
> - strcpy(szPersonalTarget, pszHome);
> - if (_SHAppendToUnixPath(szPersonalTarget, MAKEINTRESOURCEW(IDS_PERSONAL)) &&
> - !stat(szPersonalTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
> - {
> - /* '$HOME/My Documents' exists. Create 'My Pictures',
> - * 'My Videos' and 'My Music' subfolders or fail silently if
> - * they already exist.
> - */
> - for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
> - {
> - strcpy(szMyStuffTarget, szPersonalTarget);
> - if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
> - mkdir(szMyStuffTarget, 0777);
> - }
> - break;
> - }
> -
> - /* Try to point to the XDG Documents folder */
> - if (xdg_results && xdg_results[num-2] &&
> - !stat(xdg_results[num-2], &statFolder) &&
> - S_ISDIR(statFolder.st_mode))
> - {
> - strcpy(szPersonalTarget, xdg_results[num-2]);
> - break;
> - }
> -
> - /* Or the hardcoded / OS X Documents folder */
> - strcpy(szPersonalTarget, pszHome);
> - if (_SHAppendToUnixPath(szPersonalTarget, DocumentsW) &&
> - !stat(szPersonalTarget, &statFolder) &&
> - S_ISDIR(statFolder.st_mode))
> - break;
> -
> - /* As a last resort point to $HOME. */
> - strcpy(szPersonalTarget, pszHome);
> - break;
> + ERR("SystemTimeToFileTime call failed (%d)\n", GetLastError());
> + return E_FAIL;
> }
> -
> - /* Replace 'My Documents' directory with a symlink or fail silently if not empty. */
> - remove(pszPersonal);
> - symlink(szPersonalTarget, pszPersonal);
> + time_system_start = (((ULONG64)system_time_ft.dwHighDateTime) << 32)
> + + system_time_ft.dwLowDateTime
> + - (tick_count * 10000);
> }
> - else
> + fhandle = CreateFileW( ws_path, 0, FILE_SHARE_READ, NULL,
> + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
> + if (fhandle == INVALID_HANDLE_VALUE)
> {
> - /* '$HOME' doesn't exist. Create 'My Pictures', 'My Videos' and 'My Music' subdirs
> - * in '%USERPROFILE%\\My Documents' or fail silently if they already exist. */
> - pszHome = NULL;
> - strcpy(szPersonalTarget, pszPersonal);
> - for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
> - strcpy(szMyStuffTarget, szPersonalTarget);
> - if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
> - mkdir(szMyStuffTarget, 0777);
> - }
> + ERR("Open file handle failed for path: %s (%d)\n",
> + debugstr_w(ws_path), GetLastError());
> + return E_FAIL;
> }
> -
> - /* Create symbolic links for 'My Pictures', 'My Videos' and 'My Music'. */
> - for (i=0; i < ARRAY_SIZE(aidsMyStuff); i++)
> + if (!GetFileTime(fhandle, &dummy_ft, &dummy_ft, &last_write_ft))
> + ft_errorc = GetLastError();
> + if (!CloseHandle(fhandle))
> {
> - /* Create the current 'My Whatever' folder and get its unix path. */
> - hr = SHGetFolderPathW(NULL, acsidlMyStuff[i]|CSIDL_FLAG_CREATE, NULL,
> - SHGFP_TYPE_DEFAULT, wszTempPath);
> - if (FAILED(hr)) continue;
> -
> - pszMyStuff = wine_get_unix_file_name(wszTempPath);
> - if (!pszMyStuff) continue;
> -
> - while (1)
> - {
> - /* Check for the Wine-specific '$HOME/My Documents' subfolder */
> - strcpy(szMyStuffTarget, szPersonalTarget);
> - if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])) &&
> - !stat(szMyStuffTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
> - break;
> + ERR("Close file handle failed: %p (%d)\n",
> + fhandle, GetLastError());
> + return E_FAIL;
> + }
> + if (ft_errorc)
> + {
> + ERR("Get file time failed: %p (%d)\n",
> + fhandle, ft_errorc);
> + return E_FAIL;
> + }
> + time_last_write = (((ULONG64)last_write_ft.dwHighDateTime) << 32)
> + + last_write_ft.dwLowDateTime;
> + *time_difference = ((time_last_write > time_system_start) ? 1 :
> + ((time_last_write < time_system_start) ? -1 :
> + 0));
>
> - /* Try the XDG_XXX_DIR folder */
> - if (xdg_results && xdg_results[i])
> - {
> - strcpy(szMyStuffTarget, xdg_results[i]);
> - break;
> - }
> + return S_OK;
> +}
>
> - /* Or the OS X folder (these are never localized) */
> - if (pszHome)
> - {
> - strcpy(szMyStuffTarget, pszHome);
> - if (_SHAppendToUnixPath(szMyStuffTarget, MyOSXStuffW[i]) &&
> - !stat(szMyStuffTarget, &statFolder) &&
> - S_ISDIR(statFolder.st_mode))
> - break;
> - }
> +/******************************************************************************
> + * create_homedir_symbolic_link [Internal]
> + *
> + * Creates a symbolic link from the current Wineprefix to an appropriate
> + * HOME subdirectory (if one is found).
> + *
> + * Creates 'XXXX' directory in Wineprefix.
> + * Then create a 'My XXXX' symbolic link in Wineprefix:
> + * 1) If '$HOME/XXXX' (IDS directory) exists then target this.
> + * 2) If '$HOME/XXXX' (XDG_XXXX_DIR) exists then target this.
> + * 3) If '$HOME/XXXX' (MacOS XXXX media directory) exists then target this.
> + *
> + * PARAMS
> + * env_enabled [I]
> + * TRUE The user has enabled this Shell Folder to be symlinked (default).
> + * FALSE The user has chosen to disable symlinking this Shell Folder.
> + * The Shell Folder will be created, in the current Wineprefix (if not pre-existing).
> + * ids_dir [I] Windows Resource Identifier code for current Shell Folder.
> + * csidl_dir [I] Constant Special Item ID List identifier for current Shell Folder.
> + * xdg_dir [I] Full path of external Unix XDG directory corresponding to current Shell Folder.
> + * ws_osx_dir [I] Fallback directory name to use, corresponding to current Shell Folder (OSX specific).
> + *
> + */
> +void create_homedir_symbolic_link(BOOL env_enabled,
> + UINT ids_dir,
> + int csidl_dir,
> + const char * xdg_dir,
> + const WCHAR * ws_osx_dir)
> +{
> + static const char * env_homedir = NULL;
> + WCHAR ws_temp_path[MAX_PATH];
> + char home_target[FILENAME_MAX], * prefix_dir;
> + struct stat stat_folder, stat_home_folder;
> + HRESULT hr;
> + BOOL target_ok;
> + int time_difference;
>
> - /* As a last resort point to the same location as 'My Documents' */
> - strcpy(szMyStuffTarget, szPersonalTarget);
> - break;
> + hr = SHGetFolderPathW(NULL, csidl_dir, NULL,
> + SHGFP_TYPE_DEFAULT, ws_temp_path);
> + if (SUCCEEDED(hr))
> + {
> + if (ids_dir != IDS_DESKTOPDIRECTORY) return;
> +
> + if ((compare_pathft_to_bootft(ws_temp_path, &time_difference) == S_OK)
> + && (time_difference < 0))
> + {
> + TRACE("%s directory created before wineboot\n",
> + debugstr_w(ws_temp_path));
> + return;
> }
> - remove(pszMyStuff);
> - symlink(szMyStuffTarget, pszMyStuff);
> - heap_free(pszMyStuff);
> }
> -
> - /* Last but not least, the Desktop folder */
> - if (pszHome)
> - strcpy(szDesktopTarget, pszHome);
> + else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
> + {
> + hr = SHGetFolderPathW(NULL, csidl_dir|CSIDL_FLAG_CREATE, NULL,
> + SHGFP_TYPE_DEFAULT, ws_temp_path);
> + if (FAILED(hr)) return;
> + }
> else
> - strcpy(szDesktopTarget, pszPersonal);
> - heap_free(pszPersonal);
> + {
> + ERR("Failed to get Wineprefix path corresponding to %d CSIDL\n",
> + csidl_dir);
> + return;
> + }
> + if (!env_enabled) return;
> + prefix_dir = wine_get_unix_file_name(ws_temp_path);
> + if (!prefix_dir)
> + {
> + ERR("Failed to get Unix Wineprefix directory for: %s\n",
> + debugstr_w(ws_temp_path));
> + return;
> + }
> + if (!env_homedir) env_homedir = getenv("HOME");
> + if (!(env_homedir
> + && (stat(env_homedir, &stat_home_folder) != 1)
> + && S_ISDIR(stat_home_folder.st_mode)))
> + {
> + if (prefix_dir) heap_free(prefix_dir);
> + return;
> + }
>
> - xdg_desktop_dir = xdg_results ? xdg_results[num - 1] : NULL;
> - if (xdg_desktop_dir ||
> - (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
> - !stat(szDesktopTarget, &statFolder) && S_ISDIR(statFolder.st_mode)))
> + /* Check for:
> + * '$HOME/XXXX' (IDS directory)
> + * or '$HOME/XXXX' (XDG directory)
> + * or '$HOME/XXXX' (MacOS directory)
> + */
> + target_ok = FALSE;
> + strcpy(home_target, env_homedir);
> + if (append_to_unix_path(home_target, MAKEINTRESOURCEW(ids_dir))
> + && (stat(home_target, &stat_folder) != -1)
> + && S_ISDIR(stat_folder.st_mode))
> {
> - hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, NULL,
> - SHGFP_TYPE_DEFAULT, wszTempPath);
> - if (SUCCEEDED(hr) && (pszDesktop = wine_get_unix_file_name(wszTempPath)))
> - {
> - remove(pszDesktop);
> - if (xdg_desktop_dir)
> - symlink(xdg_desktop_dir, pszDesktop);
> - else
> - symlink(szDesktopTarget, pszDesktop);
> - heap_free(pszDesktop);
> - }
> + target_ok = TRUE;
> + }
> + else if (xdg_dir && stat(xdg_dir, &stat_folder))
> + {
> + strcpy(home_target, xdg_dir);
> + /* Only link to the XDG directory, if it does not point directly
> + * to the user's HOME directory (XDG specification fallback path). */
> + target_ok = (stat_folder.st_ino != stat_home_folder.st_ino);
> + }
> + else
> + {
> + strcpy(home_target, env_homedir);
> + target_ok = append_to_unix_path(home_target, ws_osx_dir)
> + && (stat(home_target, &stat_folder) != -1)
> + && S_ISDIR(stat_folder.st_mode);
> }
>
> - /* Free resources allocated by XDG_UserDirLookup() */
> - if (xdg_results)
> + if (target_ok)
> {
> - for (i = 0; i < num; i++)
> - heap_free(xdg_results[i]);
> - heap_free(xdg_results);
> + remove(prefix_dir);
> + symlink(home_target, prefix_dir);
> }
> +
> +
> + if (prefix_dir) heap_free(prefix_dir);
> }
>
> /******************************************************************************
> @@ -6126,15 +6133,139 @@ static void register_system_knownfolders(void)
> }
> }
>
> +/******************************************************************************
> + * parse_symlinks_env_variable [Internal]
> + *
> + * PARAMS
> + * xdg_dir [I] Unix XDG directory name (without "XDG_" prefix and "_DIR" suffix).
> + *
> + * RETURNS
> + * TRUE "WINESYMLINK" contains the specified XDG directory string.
> + * FALSE "WINESYMLINK" does not contain the specified XDG directory string.
> + * Any error condition.
> + *
> + * Note: "WINESYMLINK", defaults to "ALL", when unset. This enables all symlinks.
> + * "WINESYMLINK" can also be manually set to "ALL", enabling all symlinks.
> + *
> + */
> +static BOOL parse_symlinks_env_variable(const char * xdg_dir)
> +{
> + static const char * matchall_env_var = "ALL";
> + static char env_var[MAX_PATH+1];
> + static char * env_winesymlink = NULL;
> + char * sstr, * sstr_stop, * tstr, * word_start = NULL;
> + char seperator_ch = '\0';
> + BOOL end_string, in_word = FALSE, matched = FALSE;
> + size_t slength = 0, matchall_length, xdg_dir_slength;
> +
> + if (!xdg_dir) return matched;
> +
> + if (!env_winesymlink)
> + {
> + env_winesymlink = getenv("WINESYMLINK");
> + if (!env_winesymlink) env_winesymlink = (char*) matchall_env_var;
> + tstr = env_var;
> + sstr_stop = env_winesymlink + MAX_PATH;
> + for (sstr = env_winesymlink; *sstr && (sstr != sstr_stop); ++sstr)
> + {
> + if (!seperator_ch && (ispunct(*sstr) || isspace(*sstr)))
> + seperator_ch = *sstr;
> + if (!isalpha(*sstr)) continue;
> +
> + if (seperator_ch && in_word)
> + {
> + *tstr++ = seperator_ch;
> + ++slength;
> + }
> + in_word = TRUE;
> + seperator_ch = '\0';
> + *tstr++ = toupper(*sstr);
> + ++slength;
> + }
> + env_var[slength] = '\0';
> + }
> +
> + TRACE("processed env variable: %s\n", debugstr_a(&env_var[0]));
> + matchall_length = strlen(matchall_env_var);
> + xdg_dir_slength = strlen(xdg_dir);
> + end_string = !(env_var[0]);
> + for (sstr = &env_var[0]; !end_string; ++sstr)
> + {
> + end_string = !(*(sstr+1));
> + in_word = isalpha(*sstr);
> + if (in_word && !word_start) word_start = sstr;
> + in_word = in_word && !end_string;
> + if (in_word || !word_start) continue;
> +
> + slength = ((size_t) (sstr-word_start))+(end_string ? 1 : 0);
> + matched = ( (slength == xdg_dir_slength) && (strncmp(word_start, xdg_dir, slength) == 0) )
> + || ( (slength == matchall_length) && (strncmp(word_start, "ALL", slength) == 0) );
> + if (matched) break;
> +
> + word_start = NULL;
> + }
> + TRACE("%s symlinking for %s\n", matched ? "Enabled" : "Disabled", debugstr_a(xdg_dir));
> +
> + return matched;
> +}
> +
> +/******************************************************************************
> + * create_homedir_symbolic_links [Internal]
> + *
> + * Parse WINESYMLINK env variable, for each XDG directory argument. To test if symlinking is
> + * enabled for that XDG directory / Wine Profile Folder.
> + * Then calls the function create_homedir_symbolic_link to potentially symlink from a Shell Folder,
> + * in the current Wineprefix, to a subdirectory of the current user's HOME directory.
> + *
> + * PARAMS
> + * xdg_dirnames [I] Pointer to an array of Unix XDG directory names
> + * (without "XDG_" prefix and "_DIR" suffix).
> + * xdg_dir_count [I] Item count of array (above).
> + *
> + */
> +static void create_homedir_symbolic_links(const char * const xdg_dirnames[], const UINT xdg_dir_count)
> +{
> + char ** xdg_dirs_array;
> + char * xdg_dir;
> + HRESULT hr;
> + UINT i;
> + BOOL env_enabled;
> +
> + if (!xdg_dirnames) return;
> +
> + hr = XDG_UserDirLookup(xdg_dirnames, xdg_dir_count, &xdg_dirs_array);
> + if (FAILED(hr)) xdg_dirs_array = NULL;
> +
> + for (i = 0; i < xdg_dir_count; ++i)
> + {
> + env_enabled = parse_symlinks_env_variable(xdg_dirnames[i]);
> + xdg_dir = xdg_dirs_array ? xdg_dirs_array[i] : NULL;
> + if (!strcmp(xdg_dirnames[i],"DOCUMENTS"))
> + create_homedir_symbolic_link(env_enabled, IDS_PERSONAL, CSIDL_PERSONAL, xdg_dir, DocumentsW);
> + else if (!strcmp(xdg_dirnames[i],"PICTURES"))
> + create_homedir_symbolic_link(env_enabled, IDS_MYPICTURES, CSIDL_MYPICTURES, xdg_dir, PicturesW);
> + else if (!strcmp(xdg_dirnames[i],"VIDEOS"))
> + create_homedir_symbolic_link(env_enabled, IDS_MYVIDEOS, CSIDL_MYVIDEO, xdg_dir, MoviesW);
> + else if (!strcmp(xdg_dirnames[i],"MUSIC"))
> + create_homedir_symbolic_link(env_enabled, IDS_MYMUSIC, CSIDL_MYMUSIC, xdg_dir, MusicW);
> + else if (!strcmp(xdg_dirnames[i],"DESKTOP"))
> + create_homedir_symbolic_link(env_enabled, IDS_DESKTOPDIRECTORY, CSIDL_DESKTOPDIRECTORY, xdg_dir, DesktopW);
> + else
> + ERR("XDG directory name specifier invalid: %s\n", debugstr_a(xdg_dirnames[i]));
> + if (xdg_dir) heap_free(xdg_dirs_array[i]);
> + }
> + if (xdg_dirs_array) heap_free(xdg_dirs_array);
> +}
> +
> HRESULT SHELL_RegisterShellFolders(void)
> {
> + static const char * const xdg_dirnames[] = { "DOCUMENTS", "PICTURES", "VIDEOS", "MUSIC", "DESKTOP" };
> + const UINT xdg_dir_count = 5;
> HRESULT hr;
>
> - /* Set up '$HOME' targeted symlinks for 'My Documents', 'My Pictures',
> - * 'My Videos', 'My Music' and 'Desktop' in advance, so that the
> - * _SHRegister*ShellFolders() functions will find everything nice and clean
> - * and thus will not attempt to create them in the profile directory. */
> - _SHCreateSymbolicLinks();
> + /* Early setup of symlinks from specific User Shell Folders, in
> + * current Wineprefix, to subdirecties of the user's HOME directory. */
> + create_homedir_symbolic_links(xdg_dirnames, xdg_dir_count);
>
> hr = _SHRegisterUserShellFolders(TRUE);
> if (SUCCEEDED(hr))
> @@ -6147,5 +6278,6 @@ HRESULT SHELL_RegisterShellFolders(void)
> hr = set_folder_attributes();
> if (SUCCEEDED(hr))
> register_system_knownfolders();
> +
> return hr;
> }
> --
> 2.17.1
>
>
>
June 7, 2018
Re: [PATCH] ntoskrnl: Have MmIsAddressValid use IsBadReadPtr.
by Thomas Faber
On 2018-06-06 17:11, Derek Lesho wrote:
> Hi Thomas, in your example, does &Base refer to the base of
> ntoskrnl.exe? If so, why are you allocating a buffer there, wouldn't
> that corrupt the memory of ntoskrnl, or am I misunderstanding what
> your code is doing. On windows, do drivers have access to change the
> memory of ntoskrnl?
My intention was to simply make a user mode memory allocation, so there
should be a "Base = NULL;" before the call to ZwAllocateVirtualMemory.
This function cannot allocate kernel address space (or overwrite loaded
modules), so it wouldn't do anything unexpected. I was just suggesting
it to demonstrate behavior with NOACCESS/READONLY/READWRITE pages.
As for your actual use case, I'd assume ntoskrnl's code is most likely
write-protected on Windows as well, much like you encountered on Wine,
but I haven't verified.
Since your patch was committed I don't know if you're still interested
in adding the test. If you are, I'd suggest to go with the simpler
second version, since like I said the "full test" won't be very useful
in Wine.
> On Wed, Jun 6, 2018 at 3:51 AM, Thomas Faber <thomas.faber(a)reactos.org> wrote:
>> void test_function()
>> {
>> ok(MmIsAddressValid((void*)test_function), ...); // fails in master, succeeds with patch?
>> ptr = ExAllocatePoolWithTag(NonPagedPool, ...)
>> ok(MmIsAddressValid(ptr), ...);
>> ExFreePoolWithTag...
>> ok(!MmIsAddressValid(NULL), ...);
>> }
Perhaps also
ok(MmIsAddressValid((void*)MmIsAddressValid), ...);
to specifically test ntoskrnl instead of the test driver's binary.
-Thomas
June 7, 2018
Re: [PATCH 3/4 v5] riched20: Support external HDC in ME_WrapMarkedParagraphs().
by Huw Davies
On Wed, Jun 06, 2018 at 05:24:31PM +0800, Jactry Zeng wrote:
> Superseded patch 146572.
>
> Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
> ---
> dlls/riched20/editor.c | 13 +++++++------
> dlls/riched20/editor.h | 2 +-
> dlls/riched20/editstr.h | 1 +
> dlls/riched20/paint.c | 10 +++++-----
> dlls/riched20/table.c | 4 ++--
> dlls/riched20/wrap.c | 11 +++++++++--
> 6 files changed, 25 insertions(+), 16 deletions(-)
>
> diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
> index 820b0380c7..82132761f0 100644
> --- a/dlls/riched20/editor.c
> +++ b/dlls/riched20/editor.c
> @@ -3028,6 +3028,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
>
> ed->hWnd = NULL;
> ed->hwndParent = NULL;
> + ed->hdcDraw = NULL;
> ed->sizeWindow.cx = ed->sizeWindow.cy = 0;
> ed->texthost = texthost;
> ed->reOle = NULL;
> @@ -3494,7 +3495,7 @@ static LRESULT ME_WmCreate(ME_TextEditor *editor, LPARAM lParam, BOOL unicode)
> }
>
> ME_CommitUndo(editor);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_MoveCaret(editor);
> return 0;
> }
> @@ -3645,7 +3646,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
> cf.yHeight = size * 20; /* convert twips to points */
> ME_SetSelectionCharFormat(editor, &cf);
> ME_CommitUndo(editor);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> ME_Repaint(editor);
>
> @@ -3934,7 +3935,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
> ME_CommitUndo(editor);
> if (bRepaint)
> {
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> ME_Repaint(editor);
> }
> @@ -3959,7 +3960,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
> case EM_SETPARAFORMAT:
> {
> BOOL result = ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> ME_Repaint(editor);
> ME_CommitUndo(editor);
> @@ -4054,7 +4055,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
>
> ME_CommitUndo(editor);
> ME_MarkAllForWrapping(editor);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> if (bRepaint)
> ME_Repaint(editor);
> @@ -4714,7 +4715,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
> editor->bDefaultFormatRect = TRUE;
> }
> ME_MarkAllForWrapping(editor);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> if (msg != EM_SETRECTNP)
> ME_Repaint(editor);
> diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
> index 0f0e56ecd1..425a34f0c2 100644
> --- a/dlls/riched20/editor.h
> +++ b/dlls/riched20/editor.h
> @@ -182,7 +182,7 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) DECLSPEC_HIDD
> void ME_DestroyContext(ME_Context *c) DECLSPEC_HIDDEN;
>
> /* wrap.c */
> -BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) DECLSPEC_HIDDEN;
> +BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor, HDC hdc) DECLSPEC_HIDDEN;
> void ME_InvalidateParagraphRange(ME_TextEditor *editor, ME_DisplayItem *start_para, ME_DisplayItem *last_para) DECLSPEC_HIDDEN;
> void ME_SendRequestResize(ME_TextEditor *editor, BOOL force) DECLSPEC_HIDDEN;
>
> diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
> index 206ce85287..1d811e1c2a 100644
> --- a/dlls/riched20/editstr.h
> +++ b/dlls/riched20/editstr.h
> @@ -383,6 +383,7 @@ typedef struct tagME_InStream ME_InStream;
> typedef struct tagME_TextEditor
> {
> HWND hWnd, hwndParent;
> + HDC hdcDraw;
> ITextHost *texthost;
> IRichEditOle *reOle;
> BOOL bEmulateVersion10;
> diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
> index fcc4e105a3..f2429081fc 100644
> --- a/dlls/riched20/paint.c
> +++ b/dlls/riched20/paint.c
> @@ -105,7 +105,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate)
>
> void ME_Repaint(ME_TextEditor *editor)
> {
> - if (ME_WrapMarkedParagraphs(editor))
> + if (ME_WrapMarkedParagraphs(editor, NULL))
> {
> ME_UpdateScrollBar(editor);
> FIXME("ME_Repaint had to call ME_WrapMarkedParagraphs\n");
> @@ -118,7 +118,7 @@ void ME_UpdateRepaint(ME_TextEditor *editor, BOOL update_now)
> /* Should be called whenever the contents of the control have changed */
> BOOL wrappedParagraphs;
>
> - wrappedParagraphs = ME_WrapMarkedParagraphs(editor);
> + wrappedParagraphs = ME_WrapMarkedParagraphs(editor, NULL);
> if (wrappedParagraphs)
> ME_UpdateScrollBar(editor);
>
> @@ -145,7 +145,7 @@ ME_RewrapRepaint(ME_TextEditor *editor)
> * looks, but not content. Like resizing. */
>
> ME_MarkAllForWrapping(editor);
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_UpdateScrollBar(editor);
> ME_Repaint(editor);
> }
> @@ -1163,7 +1163,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor)
> SCROLLINFO si;
> BOOL bScrollBarWasVisible, bScrollBarWillBeVisible;
>
> - if (ME_WrapMarkedParagraphs(editor))
> + if (ME_WrapMarkedParagraphs(editor, NULL))
> FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n");
>
> si.cbSize = sizeof(si);
> @@ -1336,7 +1336,7 @@ ME_InvalidateSelection(ME_TextEditor *editor)
> there's no (inverted) area to be repainted, neither old nor new */
> if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd)
> return;
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> ME_GetSelectionParas(editor, &sel_start, &sel_end);
> assert(sel_start->type == diParagraph);
> assert(sel_end->type == diParagraph);
> diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c
> index 4cd77eb399..5457935dfa 100644
> --- a/dlls/riched20/table.c
> +++ b/dlls/riched20/table.c
> @@ -499,7 +499,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
> editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
> editor->pCursors[0].nOffset = 0;
> editor->pCursors[1] = editor->pCursors[0];
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> return;
> }
> }
> @@ -544,7 +544,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
> editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
> editor->pCursors[0].nOffset = 0;
> editor->pCursors[1] = editor->pCursors[0];
> - ME_WrapMarkedParagraphs(editor);
> + ME_WrapMarkedParagraphs(editor, NULL);
> return;
> }
> }
> diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c
> index e3a70f07d1..4c92252547 100644
> --- a/dlls/riched20/wrap.c
> +++ b/dlls/riched20/wrap.c
> @@ -980,14 +980,21 @@ static void ME_MarkRepaintEnd(ME_DisplayItem *para,
> *repaint_end = para;
> }
>
> -BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
> +BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor, HDC hdc)
> {
> ME_DisplayItem *item;
> ME_Context c;
> int totalWidth = 0;
> ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL;
>
> - ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
> + if (!hdc)
> + hdc = ITextHost_TxGetDC(editor->texthost);
> + if (hdc != editor->hdcDraw)
> + {
> + ME_MarkAllForWrapping(editor);
> + editor->hdcDraw = hdc;
> + }
> + ME_InitContext(&c, editor, hdc);
> c.pt.x = 0;
> item = editor->pBuffer->pFirst->next;
> while(item != editor->pBuffer->pLast) {
Unfortunately it's more complicated than this because
the styles cache font metrics and uniscribe data. These
will need to be recalculated for a new hdc.
We'll probably also want to re-think how the windowed and window-less
controls handle hdcs in general.
Huw.
June 7, 2018
Re: [PATCH 1/4 v5] riched20/tests: Rewrite tests for ITextServices_TxGetNaturalSize().
by Huw Davies
On Thu, Jun 07, 2018 at 05:21:25PM +0800, Jactry Zeng wrote:
> Huw Davies <huw(a)codeweavers.com> 于2018年6月7日周四 下午4:54写道:
> >
> > On Wed, Jun 06, 2018 at 05:24:13PM +0800, Jactry Zeng wrote:
> > > Superseded patch 146570.
> > >
>
> > > + LONG expected_width, expected_height;
> > > +
> > > + GetClientRect(WindowFromDC(hdc), &rect);
> > > + DrawTextW(hdc, string, -1, &rect, DT_LEFT | DT_CALCRECT | DT_NOCLIP | DT_EDITCONTROL | DT_WORDBREAK);
> >
> > Why can't you use GetTextExtentPointW() here? This would avoid the
> > GetClientRect() call too.
> >
>
> In 0003 there are some tests about multiline support. It seems that
> using DrawText can make it more simple or we will need to compute
> a max width of it by ourselves.
Ok, then please pass the client rect to CHECK_TXGETNATURALSIZE so that
it doesn't need to be queried from there.
Also, this patch series seems out-of-order. Perhaps move 0001 after
0002 and 0003 (or put 0004 before 0002 and 0003).
Huw.
June 7, 2018
Re: [PATCH 2/4 v5] riched20: Call ITextHost_TxGetCharFormat() for setting default charformat.
by Huw Davies
On Wed, Jun 06, 2018 at 05:24:22PM +0800, Jactry Zeng wrote:
> Superseded patch 146571.
>
> ChangeLog:
> v5:
> - Remove an unnecessary newline.
>
> Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
> ---
> dlls/riched20/para.c | 5 ++++
> dlls/riched20/tests/txtsrv.c | 58 +++++++++++++++++++++++++++++++++++-
> 2 files changed, 62 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
> index f2a70e5746..ffb017c123 100644
> --- a/dlls/riched20/para.c
> +++ b/dlls/riched20/para.c
> @@ -36,6 +36,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
> {
> ME_Context c;
> CHARFORMAT2W cf;
> + const CHARFORMATW *host_cf;
> LOGFONTW lf;
> HFONT hf;
> ME_TextBuffer *text = editor->pBuffer;
> @@ -44,6 +45,7 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
> ME_Style *style;
> int eol_len;
> WCHAR cr_lf[] = {'\r','\n',0};
> + HRESULT hr;
>
> ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
>
> @@ -73,6 +75,9 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
> cf.bCharSet = lf.lfCharSet;
> cf.lcid = GetSystemDefaultLCID();
>
> + hr = ITextHost_TxGetCharFormat(editor->texthost, (const CHARFORMATW **)&host_cf);
> + if (hr == S_OK && (host_cf->cbSize >= sizeof(CHARFORMATW)))
> + ME_ToCF2W(&cf, (CHARFORMAT2W *)host_cf);
Hmm, you need to use the return value of ME_ToCF2W() is this case.
However, ME_ToCF2W() and ME_ToCFAny() should be cleaned up. They
should both do the copy even if the from argument is of the
correct type (basically what ME_CopyToCFAny() does).
Something like:
BOOL cfany_to_cf2w(CHARFORMAT2W *dst, const *CHARFORMAT2W *src);
BOOL cf2w_to_cfany(CHARFORMAT2W *dst, const *CHARFORMAT2W *src);
> style = ME_MakeStyle(&cf);
> text->pDefaultStyle = style;
>
> diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
> index 6e61392dc5..ac06aa868e 100644
> --- a/dlls/riched20/tests/txtsrv.c
> +++ b/dlls/riched20/tests/txtsrv.c
> @@ -85,6 +85,7 @@ typedef struct ITextHostTestImpl
> {
> ITextHost ITextHost_iface;
> LONG refCount;
> + CHARFORMATW char_format;
> } ITextHostTestImpl;
>
> static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface)
> @@ -330,7 +331,8 @@ static HRESULT WINAPI ITextHostImpl_TxGetCharFormat(ITextHost *iface,
> {
> ITextHostTestImpl *This = impl_from_ITextHost(iface);
> TRACECALL("Call to TxGetCharFormat(%p, ppCF=%p)\n", This, ppCF);
> - return E_NOTIMPL;
> + *ppCF = &This->char_format;
> + return S_OK;
> }
>
> static HRESULT WINAPI ITextHostImpl_TxGetParaFormat(ITextHost *iface,
> @@ -609,6 +611,8 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret)
> ITextHostTestImpl *dummyTextHost;
> IUnknown *init;
> HRESULT result;
> + LOGFONTW lf;
> + HFONT hf;
>
> dummyTextHost = CoTaskMemAlloc(sizeof(*dummyTextHost));
> if (dummyTextHost == NULL) {
> @@ -617,6 +621,19 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret)
> }
> dummyTextHost->ITextHost_iface.lpVtbl = &itextHostVtbl;
> dummyTextHost->refCount = 1;
> + memset(&dummyTextHost->char_format, 0, sizeof(dummyTextHost->char_format));
> + dummyTextHost->char_format.cbSize = sizeof(dummyTextHost->char_format);
> + dummyTextHost->char_format.dwMask = CFM_FACE | CFM_SIZE | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT;
> + hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
No cast.
> + GetObjectW(hf, sizeof(LOGFONTW), &lf);
> + lstrcpyW(dummyTextHost->char_format.szFaceName, lf.lfFaceName);
> + dummyTextHost->char_format.yHeight = MulDiv(abs(lf.lfHeight), 1440, GetDeviceCaps(GetDC(NULL), LOGPIXELSY));
> + if (lf.lfWeight > FW_NORMAL) dummyTextHost->char_format.dwEffects |= CFE_BOLD;
> + if (lf.lfItalic) dummyTextHost->char_format.dwEffects |= CFE_ITALIC;
> + if (lf.lfUnderline) dummyTextHost->char_format.dwEffects |= CFE_UNDERLINE;
> + if (lf.lfStrikeOut) dummyTextHost->char_format.dwEffects |= CFE_SUBSCRIPT;
> + dummyTextHost->char_format.bPitchAndFamily = lf.lfPitchAndFamily;
> + dummyTextHost->char_format.bCharSet = lf.lfCharSet;
You do the same thing in the previous patch, so this should be a
helper function.
> /* MSDN states that an IUnknown object is returned by
> CreateTextServices which is then queried to obtain a
> @@ -947,6 +964,44 @@ static void test_QueryInterface(void)
> ITextHost_Release(host);
> }
>
> +static void test_default_format(void)
> +{
> + ITextServices *txtserv;
> + ITextHost *host;
> + HRESULT result;
> + LRESULT lresult;
> + CHARFORMAT2W cf2;
> + HFONT hf;
> + LOGFONTW lf;
> + LONG expected_height;
> +
> + if (!init_texthost(&txtserv, &host))
> + return;
> +
> + cf2.cbSize = sizeof(CHARFORMAT2W);
> + result = ITextServices_TxSendMessage(txtserv, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf2, &lresult);
> + ok(result == S_OK, "ITextServices_TxSendMessage failed: 0x%08x.\n", result);
> + hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
> + GetObjectW(hf, sizeof(LOGFONTW), &lf);
Rather than getting the font here, why not call ITextHost_GetCharFormat() ?
> + expected_height = MulDiv(abs(lf.lfHeight), 1440, GetDeviceCaps(GetDC(NULL), LOGPIXELSY));
> + ok(!lstrcmpW(lf.lfFaceName, cf2.szFaceName), "got wrong font name: %s.\n", wine_dbgstr_w(cf2.szFaceName));
> + ok(cf2.yHeight == expected_height, "got wrong yHeight: %d, expetced %d.\n", cf2.yHeight, expected_height);
> + if (lf.lfWeight > FW_NORMAL)
> + ok(cf2.dwEffects & CFE_BOLD, "got dwEffects without CFE_BOLD: %x.\n", cf2.dwEffects);
> + if (lf.lfItalic)
> + ok(cf2.dwEffects & CFE_ITALIC, "got dwEffects without CFE_ITALIC: %x.\n", cf2.dwEffects);
> + if (lf.lfUnderline)
> + ok(cf2.dwEffects & CFE_UNDERLINE, "got dwEffects without CFE_UNDERLINE: %x.\n", cf2.dwEffects);
> + if (lf.lfStrikeOut)
> + ok(cf2.dwEffects & CFE_STRIKEOUT, "got dwEffects without CFE_STRIKEOUT: %x.\n", cf2.dwEffects);
> + ok(cf2.bPitchAndFamily == lf.lfPitchAndFamily, "got wrong bPitchAndFamily: %x, expected %x.\n",
> + cf2.bPitchAndFamily, lf.lfPitchAndFamily);
> + ok(cf2.bCharSet == lf.lfCharSet, "got wrong bCharSet: %x, expected %x.\n", cf2.bCharSet, lf.lfCharSet);
> +
> + ITextServices_Release(txtserv);
> + ITextHost_Release(host);
> +}
> +
> START_TEST( txtsrv )
> {
> ITextServices *txtserv;
> @@ -977,6 +1032,7 @@ START_TEST( txtsrv )
> test_TxGetNaturalSize();
> test_TxDraw();
> test_QueryInterface();
> + test_default_format();
> }
> if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
> }
> --
> 2.17.1
>
>
>
>
June 7, 2018
Re: [PATCH 1/4 v5] riched20/tests: Rewrite tests for ITextServices_TxGetNaturalSize().
by Jactry Zeng
Jactry Zeng <jactry92(a)gmail.com> 于2018年6月7日周四 下午5:21写道:
>
>
> In 0003 there are some tests about multiline support. It seems that
> using DrawText can make it more simple or we will need to compute
> a max width of it by ourselves.
Sorry, it is in 0004.
> --
> Regards,
> Jactry Zeng
--
Regards,
Jactry Zeng
June 7, 2018
Re: [PATCH 1/4 v5] riched20/tests: Rewrite tests for ITextServices_TxGetNaturalSize().
by Jactry Zeng
Huw Davies <huw(a)codeweavers.com> 于2018年6月7日周四 下午4:54写道:
>
> On Wed, Jun 06, 2018 at 05:24:13PM +0800, Jactry Zeng wrote:
> > Superseded patch 146570.
> >
> > + LONG expected_width, expected_height;
> > +
> > + GetClientRect(WindowFromDC(hdc), &rect);
> > + DrawTextW(hdc, string, -1, &rect, DT_LEFT | DT_CALCRECT | DT_NOCLIP | DT_EDITCONTROL | DT_WORDBREAK);
>
> Why can't you use GetTextExtentPointW() here? This would avoid the
> GetClientRect() call too.
>
In 0003 there are some tests about multiline support. It seems that
using DrawText can make it more simple or we will need to compute
a max width of it by ourselves.
--
Regards,
Jactry Zeng
June 7, 2018
Re: [PATCH 1/2] schedsvc: Load job files at the service start up.
by Dmitry Timoshkov
There is a problem with this patchset, please ignore it for now.
--
Dmitry.
June 7, 2018
Re: [PATCH 1/4 v5] riched20/tests: Rewrite tests for ITextServices_TxGetNaturalSize().
by Huw Davies
On Wed, Jun 06, 2018 at 05:24:13PM +0800, Jactry Zeng wrote:
> Superseded patch 146570.
>
> ChangeLog:
> v5:
> - Use DrawTextW for calculating expected values;
> - Simplify format setting with EM_SETCHARFORMAT.
>
> Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
> ---
> dlls/riched20/tests/txtsrv.c | 125 +++++++++++++++++------------------
> 1 file changed, 61 insertions(+), 64 deletions(-)
>
> diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
> index 88b5adf13c..6e61392dc5 100644
> --- a/dlls/riched20/tests/txtsrv.c
> +++ b/dlls/riched20/tests/txtsrv.c
> @@ -697,81 +697,78 @@ static void test_TxSetText(void)
> ITextHost_Release(host);
> }
>
> +#define CHECK_TXGETNATURALSIZE(res,width,height,hdc,string) \
> + _check_txgetnaturalsize(res, width, height, hdc, string, __LINE__)
> +static void _check_txgetnaturalsize(HRESULT res, LONG width, LONG height, HDC hdc, LPCWSTR string, int line)
> +{
> + RECT rect;
> + LONG expected_width, expected_height;
> +
> + GetClientRect(WindowFromDC(hdc), &rect);
> + DrawTextW(hdc, string, -1, &rect, DT_LEFT | DT_CALCRECT | DT_NOCLIP | DT_EDITCONTROL | DT_WORDBREAK);
Why can't you use GetTextExtentPointW() here? This would avoid the
GetClientRect() call too.
> + expected_width = rect.right - rect.left;
> + expected_height = rect.bottom - rect.top;
> + ok_(__FILE__,line)(res == S_OK, "ITextServices_TxGetNaturalSize failed: 0x%08x.\n", res);
> + ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1,
> + "got wrong width: %d, expected: %d {+1}.\n", width, expected_width);
> + ok_(__FILE__,line)(height == expected_height, "got wrong height: %d, expected: %d.\n",
> + height, expected_height);
> +}
> +
> static void test_TxGetNaturalSize(void)
> {
> ITextServices *txtserv;
> ITextHost *host;
> HRESULT result;
> - BOOL ret;
> -
> - /* This value is used when calling TxGetNaturalSize. MSDN says
> - that this is not supported however a null pointer cannot be
> - used as it will cause a segmentation violation. The values in
> - the structure being pointed to are required to be INT_MAX
> - otherwise calculations can give wrong values. */
> - const SIZEL psizelExtent = {INT_MAX,INT_MAX};
> -
> - static const WCHAR oneA[] = {'A',0};
> -
> - /* Results of measurements */
> - LONG xdim, ydim;
> -
> - /* The device context to do the tests in */
> + SIZEL psizelExtent = {-1,-1};
Let's just call this 'extent';
> + static const WCHAR test_text[] = {'T','e','s','t','S','o','m','e','T','e','x','t',0};
> + LONG width, height;
> HDC hdcDraw;
> -
> - /* Variables with the text metric information */
> - INT charwidth_caps_text[26];
> - TEXTMETRICA tmInfo_text;
> + HWND hwnd;
> + RECT rect;
> + CHARFORMAT2W cf;
> + LRESULT lresult;
> + HFONT hf;
> + LOGFONTW lf;
>
> if (!init_texthost(&txtserv, &host))
> return;
>
> - hdcDraw = GetDC(NULL);
> - SaveDC(hdcDraw);
> -
> - /* Populate the metric strucs */
> - SetMapMode(hdcDraw,MM_TEXT);
> - GetTextMetricsA(hdcDraw, &tmInfo_text);
> - SetLastError(0xdeadbeef);
> - ret = GetCharWidth32A(hdcDraw,'A','Z',charwidth_caps_text);
> - if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
> - win_skip("GetCharWidth32 is not available\n");
> - goto cleanup;
> - }
> -
> - /* Make measurements in MM_TEXT */
> + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
> + 0, 0, 100, 100, 0, 0, 0, NULL);
> + hdcDraw = GetDC(hwnd);
> SetMapMode(hdcDraw,MM_TEXT);
> - xdim = 0; ydim = 0;
> -
> - result = ITextServices_TxSetText(txtserv, oneA);
> - ok(result == S_OK, "ITextServices_TxSetText failed (result = %x)\n", result);
> - if (result != S_OK) {
> - skip("Could not set text\n");
> - goto cleanup;
> - }
> -
> - SetLastError(0xdeadbeef);
> - result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT,
> - hdcDraw, NULL, NULL,
> - TXTNS_FITTOCONTENT, &psizelExtent,
> - &xdim, &ydim);
> - todo_wine ok(result == S_OK || broken(result == E_FAIL), /* WINXP Arabic Language */
> - "TxGetNaturalSize gave unexpected return value (result = %x)\n", result);
> - if (result == S_OK) {
> - todo_wine ok(ydim == tmInfo_text.tmHeight,
> - "Height calculated incorrectly (expected %d, got %d)\n",
> - tmInfo_text.tmHeight, ydim);
> - /* The native DLL adds one pixel extra when calculating widths. */
> - todo_wine ok(xdim >= charwidth_caps_text[0] && xdim <= charwidth_caps_text[0] + 1,
> - "Width calculated incorrectly (expected %d {+1}, got %d)\n",
> - charwidth_caps_text[0], xdim);
> - } else
> - skip("TxGetNaturalSize measurements not performed (xdim = %d, ydim = %d, result = %x, error = %x)\n",
> - xdim, ydim, result, GetLastError());
> -
> -cleanup:
> - RestoreDC(hdcDraw,1);
> - ReleaseDC(NULL,hdcDraw);
> + GetClientRect(hwnd, &rect);
> +
> + memset(&cf, 0, sizeof(cf));
> + cf.cbSize = sizeof(cf);
> + cf.dwMask = CFM_ALL2;
> + hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
No need for cast.
> + GetObjectW(hf, sizeof(LOGFONTW), &lf);
> + lstrcpyW(cf.szFaceName, lf.lfFaceName);
> + cf.yHeight = MulDiv(abs(lf.lfHeight), 1440, GetDeviceCaps(GetDC(NULL), LOGPIXELSY));
> + if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD;
> + if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC;
> + if (lf.lfUnderline) cf.dwEffects |= CFE_UNDERLINE;
> + if (lf.lfStrikeOut) cf.dwEffects |= CFE_SUBSCRIPT;
> + cf.bPitchAndFamily = lf.lfPitchAndFamily;
> + cf.bCharSet = lf.lfCharSet;
> + result = ITextServices_TxSendMessage(txtserv, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf, &lresult);
> + ok(result == S_OK, "ITextServices_TxSendMessage failed: 0x%08x.\n", result);
> + SelectObject(hdcDraw, hf);
> +
> + result = ITextServices_TxSetText(txtserv, test_text);
> + ok(result == S_OK, "ITextServices_TxSetText failed: 0x%08x.\n", result);
> +
> + psizelExtent.cx = -1; psizelExtent.cy = -1;
This is already initialised.
> + width = rect.right - rect.left;
> + height = 0;
> + result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL,
> + TXTNS_FITTOCONTENT, &psizelExtent, &width, &height);
> + todo_wine CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, test_text);
> +
> + ReleaseDC(hwnd, hdcDraw);
> + DestroyWindow(hwnd);
> ITextServices_Release(txtserv);
> ITextHost_Release(host);
> }
> --
> 2.17.1
>
>
>
>
June 7, 2018
Re: [PATCH 4/4] wsdapi: Add initial support for reading messages; identify Probe message.
by Huw Davies
On Wed, Jun 06, 2018 at 09:58:52PM +0100, Owen Rudge wrote:
> Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
> ---
> dlls/wsdapi/soap.c | 340
> +++++++++++++++++++++++++++++++++++++++++-
> dlls/wsdapi/tests/discovery.c | 6 +-
> 2 files changed, 341 insertions(+), 5 deletions(-)
>
>
> diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c
> index 4e191a5c82..2bc974f111 100644
> --- a/dlls/wsdapi/soap.c
> +++ b/dlls/wsdapi/soap.c
> @@ -45,6 +45,13 @@ static const WCHAR actionHello[] = {
> 'd','i','s','c','o','v','e','r','y','/',
> 'H','e','l','l','o', 0 };
>
> +static const WCHAR actionProbe[] = {
> + 'h','t','t','p',':','/','/',
> + 's','c','h','e','m','a','s','.','x','m','l','s','o','a','p','.','o','r','g','/',
> + 'w','s','/','2','0','0','5','/','0','4','/',
> + 'd','i','s','c','o','v','e','r','y','/',
> + 'P','r','o','b','e', 0 };
> +
> static const WCHAR actionBye[] = {
> 'h','t','t','p',':','/','/',
> 's','c','h','e','m','a','s','.','x','m','l','s','o','a','p','.','o','r','g','/',
> @@ -98,6 +105,27 @@ struct discovered_namespace
> LPCWSTR uri;
> };
>
> +static LPWSTR utf8_to_wide(void *parent, const char *utf8_str, int length)
> +{
> + int utf8_str_len = 0, chars_needed = 0, bytes_needed = 0;
> + LPWSTR new_str = NULL;
> +
> + if (utf8_str == NULL) return NULL;
> +
> + utf8_str_len = (length < 0) ? lstrlenA(utf8_str) : length;
> + chars_needed = MultiByteToWideChar(CP_UTF8, 0, utf8_str, utf8_str_len, NULL, 0);
> +
> + if (chars_needed <= 0) return NULL;
> +
> + bytes_needed = sizeof(WCHAR) * (chars_needed + 1);
> + new_str = WSDAllocateLinkedMemory(parent, bytes_needed);
> +
> + MultiByteToWideChar(CP_UTF8, 0, utf8_str, utf8_str_len, new_str, chars_needed);
> + new_str[chars_needed] = 0;
> +
> + return new_str;
> +}
> +
> static char *wide_to_utf8(LPCWSTR wide_string, int *length)
> {
> char *new_string = NULL;
> @@ -1081,8 +1109,316 @@ cleanup:
> return ret;
> }
>
> +static LPWSTR xml_text_to_wide_string(void *parent_memory, WS_XML_TEXT *text)
> +{
> + if (text->textType == WS_XML_TEXT_TYPE_UTF8)
> + {
> + WS_XML_UTF8_TEXT *utf8_text = (WS_XML_UTF8_TEXT *) text;
> + return utf8_to_wide(parent_memory, (const char *) utf8_text->value.bytes, utf8_text->value.length);
> + }
> + else if (text->textType == WS_XML_TEXT_TYPE_UTF16)
> + {
> + WS_XML_UTF16_TEXT *utf_16_text = (WS_XML_UTF16_TEXT *) text;
> + return duplicate_string(parent_memory, (LPCWSTR) utf_16_text->bytes);
> + }
> +
> + FIXME("Support for text type %d not implemented.\n", text->textType);
> + return NULL;
> +}
> +
> +static BOOL move_to_element(WS_XML_READER *reader, const char *element_name, WS_XML_STRING *uri)
return HRESULT
> +{
> + WS_XML_STRING envelope;
> + BOOL found = FALSE;
> +
> + envelope.bytes = (BYTE *) element_name;
> + envelope.length = strlen(element_name);
> + envelope.dictionary = NULL;
> + envelope.id = 0;
> +
> + return SUCCEEDED(WsReadToStartElement(reader, &envelope, uri, &found, NULL)) && found;
> +}
> +
> +static BOOL ws_element_to_wsdxml_element(WS_XML_READER *reader, IWSDXMLContext *context, WSDXML_ELEMENT *parent_element)
and here.
> +{
> + WSDXML_ATTRIBUTE *cur_wsd_attrib = NULL, *new_wsd_attrib = NULL;
> + const WS_XML_ELEMENT_NODE *element_node = NULL;
> + WSDXML_ELEMENT *cur_element = parent_element;
> + const WS_XML_TEXT_NODE *text_node = NULL;
> + LPWSTR uri = NULL, element_name = NULL;
> + WS_XML_STRING *ns_string = NULL;
> + WS_XML_ATTRIBUTE *attrib = NULL;
> + WSDXML_ELEMENT *element = NULL;
> + const WS_XML_NODE *node = NULL;
> + WSDXML_NAME *name = NULL;
> + WSDXML_TEXT *text = NULL;
> + HRESULT ret;
> + int i;
> +
> + for (;;)
> + {
> + if (cur_element == NULL) break;
> +
> + ret = WsReadNode(reader, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + ret = WsGetReaderNode(reader, &node, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + switch (node->nodeType)
> + {
> + case WS_XML_NODE_TYPE_ELEMENT:
> + element_node = (const WS_XML_ELEMENT_NODE *) node;
> +
> + uri = utf8_to_wide(NULL, (const char *) element_node->ns->bytes, element_node->ns->length);
> + if (uri == NULL) goto cleanup;
> +
> + /* Link element_name to uri so they will be freed at the same time */
> + element_name = utf8_to_wide(uri, (const char *) element_node->localName->bytes,
> + element_node->localName->length);
> + if (element_name == NULL) goto cleanup;
> +
> + if (FAILED(IWSDXMLContext_AddNameToNamespace(context, uri, element_name, &name))) goto cleanup;
> +
> + WSDFreeLinkedMemory(uri);
> + uri = NULL;
> +
> + if (FAILED(WSDXMLBuildAnyForSingleElement(name, NULL, &element))) goto cleanup;
> + WSDXMLAddChild(cur_element, element);
> +
> + cur_wsd_attrib = NULL;
> +
> + /* Add attributes */
> + for (i = 0; i < element_node->attributeCount; i++)
> + {
> + attrib = element_node->attributes[i];
> + if (attrib->isXmlNs) continue;
> +
> + new_wsd_attrib = WSDAllocateLinkedMemory(element, sizeof(WSDXML_ATTRIBUTE));
> + if (new_wsd_attrib == NULL) goto cleanup;
> +
> + ns_string = attrib->ns;
> + if (ns_string->length == 0) ns_string = element_node->ns;
> +
> + uri = utf8_to_wide(NULL, (const char *) ns_string->bytes, ns_string->length);
> + if (uri == NULL) goto cleanup;
> +
> + /* Link element_name to uri so they will be freed at the same time */
> + element_name = utf8_to_wide(uri, (const char *) attrib->localName->bytes, attrib->localName->length);
> + if (element_name == NULL) goto cleanup;
> +
> + if (FAILED(IWSDXMLContext_AddNameToNamespace(context, uri, element_name, &name))) goto cleanup;
> +
> + WSDFreeLinkedMemory(uri);
> + uri = NULL;
> +
> + new_wsd_attrib->Value = xml_text_to_wide_string(new_wsd_attrib, attrib->value);
> + if (new_wsd_attrib->Value == NULL) goto cleanup;
> +
> + new_wsd_attrib->Name = name;
> + new_wsd_attrib->Element = cur_element;
> + new_wsd_attrib->Next = NULL;
> +
> + if (cur_wsd_attrib == NULL)
> + element->FirstAttribute = new_wsd_attrib;
> + else
> + cur_wsd_attrib->Next = new_wsd_attrib;
> +
> + cur_wsd_attrib = new_wsd_attrib;
> + }
> +
> + cur_element = element;
> + break;
> +
> + case WS_XML_NODE_TYPE_TEXT:
> + text_node = (const WS_XML_TEXT_NODE *) node;
> +
> + if (cur_element == NULL)
> + {
> + WARN("No parent element open but encountered text element!\n");
> + continue;
> + }
> +
> + if (cur_element->FirstChild != NULL)
> + {
> + WARN("Text node encountered but parent already has child!\n");
> + continue;
> + }
> +
> + text = WSDAllocateLinkedMemory(element, sizeof(WSDXML_TEXT));
> + if (text == NULL) goto cleanup;
> +
> + text->Node.Parent = element;
> + text->Node.Next = NULL;
> + text->Node.Type = TextType;
> + text->Text = xml_text_to_wide_string(text, text_node->text);
> +
> + if (text->Text == NULL)
> + {
> + WARN("Text node returned null string.\n");
> + WSDFreeLinkedMemory(text);
> + continue;
> + }
> +
> + cur_element->FirstChild = (WSDXML_NODE *) text;
> + break;
> +
> + case WS_XML_NODE_TYPE_END_ELEMENT:
> + /* Go up a level to the parent element */
> + cur_element = cur_element->Node.Parent;
> + break;
> +
> + default:
> + break;
> + }
> + }
> +
> + return TRUE;
> +
> +cleanup:
> + /* Free uri and element_name if applicable */
> + WSDFreeLinkedMemory(uri);
> + return FALSE;
> +}
> +
> +static WSDXML_ELEMENT *find_element(WSDXML_ELEMENT *parent, LPCWSTR name, LPCWSTR ns_uri)
> +{
> + WSDXML_ELEMENT *cur = (WSDXML_ELEMENT *) parent->FirstChild;
> +
> + while (cur != NULL)
> + {
> + if ((lstrcmpW(cur->Name->LocalName, name) == 0) && (lstrcmpW(cur->Name->Space->Uri, ns_uri) == 0))
> + return cur;
> +
> + cur = (WSDXML_ELEMENT *) cur->Node.Next;
> + }
> +
> + return NULL;
> +}
> +
> int read_message(const char *xml, int xml_length, WSD_SOAP_MESSAGE **out_msg)
This is also looking like a good contender to return HRESULT and
take an [out] int *type parameter.
> {
> - /* TODO: Parse and read message */
> - return MSGTYPE_UNKNOWN;
> + WSDXML_ELEMENT *envelope = NULL, *header_element, *body_element;
> + WS_XML_READER_TEXT_ENCODING encoding;
> + WS_XML_ELEMENT_NODE *envelope_node;
> + WSD_SOAP_MESSAGE *soap_msg = NULL;
> + WS_XML_READER_BUFFER_INPUT input;
> + WS_XML_ATTRIBUTE *attrib = NULL;
> + IWSDXMLContext *context = NULL;
> + WS_XML_STRING *soap_uri = NULL;
> + const WS_XML_NODE *node;
> + WS_XML_READER *reader;
> + LPCWSTR value = NULL;
> + int i, message_type;
> + LPWSTR uri, prefix;
> + WS_HEAP *heap;
> + HRESULT ret;
> +
> + message_type = MSGTYPE_UNKNOWN;
> +
> + ret = WsCreateHeap(16384, 4096, NULL, 0, &heap, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + ret = WsCreateReader(NULL, 0, &reader, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + encoding.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
> + encoding.charSet = WS_CHARSET_AUTO;
> +
> + input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
> + input.encodedData = (char *) xml;
> + input.encodedDataSize = xml_length;
> +
> + ret = WsSetInput(reader, (WS_XML_READER_ENCODING *) &encoding, (WS_XML_READER_INPUT *) &input, NULL, 0, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + soap_uri = populate_xml_string(envelopeNsUri);
> + if (soap_uri == NULL) goto cleanup;
> +
> + if (!move_to_element(reader, "Envelope", soap_uri)) goto cleanup;
> +
> + ret = WsGetReaderNode(reader, &node, NULL);
> + if (FAILED(ret)) goto cleanup;
> +
> + if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) goto cleanup;
> +
> + envelope_node = (WS_XML_ELEMENT_NODE *) node;
> +
> + if (FAILED(WSDXMLCreateContext(&context))) goto cleanup;
> +
> + /* Find XML namespaces from the envelope element's attributes */
> + for (i = 0; i < envelope_node->attributeCount; i++)
> + {
> + attrib = envelope_node->attributes[i];
> +
> + if (attrib->isXmlNs)
> + {
> + uri = utf8_to_wide(NULL, (const char *) attrib->ns->bytes, attrib->ns->length);
> + if (uri == NULL) continue;
> +
> + prefix = utf8_to_wide(uri, (const char *) attrib->localName->bytes, attrib->localName->length);
> +
> + if (prefix == NULL)
> + {
> + WSDFreeLinkedMemory(uri);
> + continue;
> + }
> +
> + IWSDXMLContext_AddNamespace(context, uri, prefix, NULL);
> + WSDFreeLinkedMemory(uri);
> + }
> + }
> +
> + /* Create the SOAP message to return to the caller */
> + soap_msg = WSDAllocateLinkedMemory(NULL, sizeof(WSD_SOAP_MESSAGE));
> + if (soap_msg == NULL) goto cleanup;
> +
> + ZeroMemory(soap_msg, sizeof(WSD_SOAP_MESSAGE));
> +
> + envelope = WSDAllocateLinkedMemory(soap_msg, sizeof(WSDXML_ELEMENT));
> + if (envelope == NULL) goto cleanup;
> +
> + ZeroMemory(envelope, sizeof(WSDXML_ELEMENT));
> +
> + if (!ws_element_to_wsdxml_element(reader, context, envelope)) goto cleanup;
> +
> + /* Find the header element */
> + header_element = find_element(envelope, headerString, envelopeNsUri);
> + if (header_element == NULL) goto cleanup;
> +
> + if (FAILED(WSDXMLGetValueFromAny(addressingNsUri, actionString, (WSDXML_ELEMENT *) header_element->FirstChild,
> + &value))) goto cleanup;
> + soap_msg->Header.Action = duplicate_string(soap_msg, value);
> + if (soap_msg->Header.Action == NULL) goto cleanup;
> +
> + if (FAILED(WSDXMLGetValueFromAny(addressingNsUri, toString, (WSDXML_ELEMENT *) header_element->FirstChild,
> + &value))) goto cleanup;
> + soap_msg->Header.To = duplicate_string(soap_msg, value);
> + if (soap_msg->Header.To == NULL) goto cleanup;
> +
> + if (FAILED(WSDXMLGetValueFromAny(addressingNsUri, messageIdString, (WSDXML_ELEMENT *) header_element->FirstChild,
> + &value))) goto cleanup;
> + soap_msg->Header.MessageID = duplicate_string(soap_msg, value);
> + if (soap_msg->Header.MessageID == NULL) goto cleanup;
> +
> + /* Find the body element */
> + body_element = find_element(envelope, bodyString, envelopeNsUri);
> + if (body_element == NULL) goto cleanup;
> +
> + /* Now figure out which message we've been sent */
> + if (lstrcmpW(soap_msg->Header.Action, actionProbe) == 0)
> + {
> + /* TODO: Parse the Probe message */
> +
> + *out_msg = soap_msg;
> + soap_msg = NULL; /* caller will clean this up */
> + message_type = MSGTYPE_PROBE;
> + }
> +
> +cleanup:
> + free_xml_string(soap_uri);
> + WSDFreeLinkedMemory(soap_msg);
> + if (context != NULL) IWSDXMLContext_Release(context);
> +
> + return message_type;
> }
> diff --git a/dlls/wsdapi/tests/discovery.c b/dlls/wsdapi/tests/discovery.c
> index 96c2ead7f9..0599123a46 100644
> --- a/dlls/wsdapi/tests/discovery.c
> +++ b/dlls/wsdapi/tests/discovery.c
> @@ -491,7 +491,7 @@ static void verify_wsdxml_any_text(const char *debug_prefix, WSDXML_ELEMENT *any
> {
> WSDXML_TEXT *child;
>
> - ok(any != NULL, "%s: any == NULL\n", debug_prefix);
> + todo_wine ok(any != NULL, "%s: any == NULL\n", debug_prefix);
You'll need to have a really good reason for doing this. Can you
re-order things so you don't break the tests?
> if (any == NULL) return;
>
> child = (WSDXML_TEXT *) any->FirstChild;
> @@ -534,7 +534,7 @@ static HRESULT WINAPI IWSDiscoveryPublisherNotifyImpl_ProbeHandler(IWSDiscoveryP
> static const WCHAR extra_info[] = {'E','x','t','r','a','I','n','f','o',0};
> WSD_PROBE *probe_msg = (WSD_PROBE *) pSoap->Body;
>
> - ok(pSoap->Body != NULL, "pSoap->Body == NULL\n");
> + todo_wine ok(pSoap->Body != NULL, "pSoap->Body == NULL\n");
> ok(pSoap->Header.To != NULL && lstrcmpW(pSoap->Header.To, discoveryTo) == 0,
> "pSoap->Header.To == '%s'\n", wine_dbgstr_w(pSoap->Header.To));
> ok(pSoap->Header.Action != NULL && lstrcmpW(pSoap->Header.Action, actionProbe) == 0,
> @@ -939,7 +939,7 @@ after_publish_test:
> sprintf(probe_message, testProbeMessage, probe_uuid_str);
>
> ok(send_udp_multicast_of_type(probe_message, strlen(probe_message), AF_INET) == TRUE, "Sending Probe message failed\n");
> - todo_wine ok(WaitForSingleObject(probe_event, 2000) == WAIT_OBJECT_0, "Probe message not received\n");
> + ok(WaitForSingleObject(probe_event, 2000) == WAIT_OBJECT_0, "Probe message not received\n");
>
> RpcStringFreeA(&probe_uuid_str);
> }
>
>
June 7, 2018
Re: [PATCH 3/4] wsdapi: Add stub for Probe message parsing, prepare notification sink message.
by Huw Davies
On Wed, Jun 06, 2018 at 09:58:49PM +0100, Owen Rudge wrote:
> Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
> ---
> dlls/wsdapi/network.c | 52
> ++++++++++++++++++++++++++++++++++++++++++-
> dlls/wsdapi/soap.c | 6 +++++
> dlls/wsdapi/wsdapi_internal.h | 5 +++++
> 3 files changed, 62 insertions(+), 1 deletion(-)
>
>
> diff --git a/dlls/wsdapi/network.c b/dlls/wsdapi/network.c
> index 3e7509bfa3..7f6cee3ab0 100644
> --- a/dlls/wsdapi/network.c
> +++ b/dlls/wsdapi/network.c
> @@ -292,6 +292,56 @@ typedef struct listener_thread_params
> BOOL ipv6;
> } listener_thread_params;
>
> +static void process_received_message(listener_thread_params *params, char *message, int message_len,
> + SOCKADDR_STORAGE *source_addr)
This should return HRESULT.
> +{
> + IWSDUdpMessageParameters *msg_params = NULL;
> + IWSDUdpAddress *remote_addr = NULL;
> + struct notificationSink *sink;
> + WSD_SOAP_MESSAGE *msg = NULL;
> + int msg_type;
> +
> + msg_type = read_message(message, message_len, &msg);
> +
> + switch (msg_type)
> + {
> + case MSGTYPE_PROBE:
> + TRACE("Received probe message\n");
> +
> + if (FAILED(WSDCreateUdpMessageParameters(&msg_params)))
> + {
> + ERR("Unable to create IWSDUdpMessageParameters, not processing message.\n");
> + goto cleanup;
> + }
> +
> + if (FAILED(WSDCreateUdpAddress(&remote_addr)))
> + {
> + ERR("Unable to create IWSDUdpAddress, not processing message.\n");
> + goto cleanup;
> + }
> +
> + IWSDUdpAddress_SetSockaddr(remote_addr, source_addr);
> + IWSDUdpMessageParameters_SetRemoteAddress(msg_params, (IWSDAddress *)remote_addr);
> +
> + EnterCriticalSection(¶ms->impl->notification_sink_critical_section);
> +
> + LIST_FOR_EACH_ENTRY(sink, ¶ms->impl->notificationSinks, struct notificationSink, entry)
> + {
> + IWSDiscoveryPublisherNotify_ProbeHandler(sink->notificationSink, msg, (IWSDMessageParameters *)msg_params);
> + }
> +
> + LeaveCriticalSection(¶ms->impl->notification_sink_critical_section);
> +
> + break;
> + }
> +
> +cleanup:
> + WSDFreeLinkedMemory(msg);
> +
> + if (remote_addr != NULL) IWSDUdpAddress_Release(remote_addr);
> + if (msg_params != NULL) IWSDUdpMessageParameters_Release(msg_params);
> +}
> +
> #define RECEIVE_BUFFER_SIZE 65536
>
> static DWORD WINAPI listening_thread(LPVOID params)
> @@ -321,7 +371,7 @@ static DWORD WINAPI listening_thread(LPVOID params)
> }
> else
> {
> - /* TODO: Process received message */
> + process_received_message(parameter, buffer, bytes_received, &source_addr);
> }
> }
>
> diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c
> index d0fb0afb0c..4e191a5c82 100644
> --- a/dlls/wsdapi/soap.c
> +++ b/dlls/wsdapi/soap.c
> @@ -1080,3 +1080,9 @@ cleanup:
>
> return ret;
> }
> +
> +int read_message(const char *xml, int xml_length, WSD_SOAP_MESSAGE **out_msg)
> +{
> + /* TODO: Parse and read message */
> + return MSGTYPE_UNKNOWN;
> +}
> diff --git a/dlls/wsdapi/wsdapi_internal.h b/dlls/wsdapi/wsdapi_internal.h
> index 3e5e163f3a..5c62627bba 100644
> --- a/dlls/wsdapi/wsdapi_internal.h
> +++ b/dlls/wsdapi/wsdapi_internal.h
> @@ -72,6 +72,11 @@ HRESULT send_bye_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR id, ULONGLONG
>
> HRESULT register_namespaces(IWSDXMLContext *xml_context);
>
> +int read_message(const char *xml, int xml_length, WSD_SOAP_MESSAGE **out_msg);
> +
> +#define MSGTYPE_UNKNOWN 0
> +#define MSGTYPE_PROBE 1
> +
> /* xml.c */
>
> LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value);
>
>
June 7, 2018
Re: [PATCH 1/4] wsdapi: Add support for listening for UDP multicast broadcasts.
by Huw Davies
On Wed, Jun 06, 2018 at 09:58:45PM +0100, Owen Rudge wrote:
> Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
> ---
> dlls/wsdapi/network.c | 278
> +++++++++++++++++++++++++++++++++++++++++-
> dlls/wsdapi/wsdapi_internal.h | 4 +
> 2 files changed, 281 insertions(+), 1 deletion(-)
>
>
> diff --git a/dlls/wsdapi/network.c b/dlls/wsdapi/network.c
> index f86b3b4a3e..3e7509bfa3 100644
> --- a/dlls/wsdapi/network.c
> +++ b/dlls/wsdapi/network.c
> @@ -231,11 +231,278 @@ BOOL send_udp_multicast(IWSDiscoveryPublisherImpl *impl, char *data, int length,
> return TRUE;
> }
>
> +static int join_multicast_group(SOCKET s, SOCKADDR_STORAGE *group, SOCKADDR_STORAGE *iface)
> +{
> + int level, optname, optlen;
> + struct ipv6_mreq mreqv6;
> + struct ip_mreq mreqv4;
> + char *optval;
> +
> + if (iface->ss_family == AF_INET6)
> + {
> + level = IPPROTO_IPV6;
> + optname = IPV6_ADD_MEMBERSHIP;
> + optval = (char *)&mreqv6;
> + optlen = sizeof(mreqv6);
> +
> + mreqv6.ipv6mr_multiaddr = ((SOCKADDR_IN6 *)group)->sin6_addr;
> + mreqv6.ipv6mr_interface = ((SOCKADDR_IN6 *)iface)->sin6_scope_id;
> + }
> + else
> + {
> + level = IPPROTO_IP;
> + optname = IP_ADD_MEMBERSHIP;
> + optval = (char *)&mreqv4;
> + optlen = sizeof(mreqv4);
> +
> + mreqv4.imr_multiaddr.s_addr = ((SOCKADDR_IN *)group)->sin_addr.s_addr;
> + mreqv4.imr_interface.s_addr = ((SOCKADDR_IN *)iface)->sin_addr.s_addr;
> + }
> +
> + return setsockopt(s, level, optname, optval, optlen);
> +}
> +
> +static int set_send_interface(SOCKET s, SOCKADDR_STORAGE *iface)
> +{
> + int level, optname, optlen;
> + char *optval = NULL;
> +
> + if (iface->ss_family == AF_INET6)
> + {
> + level = IPPROTO_IPV6;
> + optname = IPV6_MULTICAST_IF;
> + optval = (char *) &((SOCKADDR_IN6 *)iface)->sin6_scope_id;
> + optlen = sizeof(((SOCKADDR_IN6 *)iface)->sin6_scope_id);
> + }
> + else
> + {
> + level = IPPROTO_IP;
> + optname = IP_MULTICAST_IF;
> + optval = (char *) &((SOCKADDR_IN *)iface)->sin_addr.s_addr;
> + optlen = sizeof(((SOCKADDR_IN *)iface)->sin_addr.s_addr);
> + }
> +
> + return setsockopt(s, level, optname, optval, optlen);
> +}
> +
> +typedef struct listener_thread_params
> +{
> + IWSDiscoveryPublisherImpl *impl;
> + SOCKET listening_socket;
> + BOOL ipv6;
> +} listener_thread_params;
> +
> +#define RECEIVE_BUFFER_SIZE 65536
> +
> +static DWORD WINAPI listening_thread(LPVOID params)
> +{
> + listener_thread_params *parameter = (listener_thread_params *)params;
> + int bytes_received, address_len, err;
> + SOCKADDR_STORAGE source_addr;
> + char *buffer;
> +
> + buffer = heap_alloc(RECEIVE_BUFFER_SIZE);
> + address_len = parameter->ipv6 ? sizeof(SOCKADDR_IN6) : sizeof(SOCKADDR_IN);
> +
> + while (parameter->impl->publisherStarted)
> + {
> + bytes_received = recvfrom(parameter->listening_socket, buffer, RECEIVE_BUFFER_SIZE, 0,
> + (LPSOCKADDR) &source_addr, &address_len);
> +
> + if (bytes_received == SOCKET_ERROR)
> + {
> + err = WSAGetLastError();
> +
> + if (err != WSAETIMEDOUT)
> + {
> + WARN("Received error when trying to read from socket: %d. Stopping listener.\n", err);
> + return 0;
> + }
> + }
> + else
> + {
> + /* TODO: Process received message */
> + }
> + }
> +
> + /* The publisher has been stopped */
> + closesocket(parameter->listening_socket);
> +
> + heap_free(buffer);
> + heap_free(parameter);
> +
> + return 0;
> +}
> +
> +static void start_listening(IWSDiscoveryPublisherImpl *impl, SOCKADDR_STORAGE *bind_address)
This should probably return an indication of success (even if it's not
possible for the caller to do something sensible with the result).
> +{
> + SOCKADDR_STORAGE multicast_addr, bind_addr, interface_addr;
> + listener_thread_params *parameter = NULL;
> + const DWORD receive_timeout = 5000;
> + const UINT reuse_addr = 1;
> + HANDLE thread_handle;
> + int address_length;
> + SOCKET s = 0;
> +
> + TRACE("(%p, %p) family %d\n", impl, bind_address, bind_address->ss_family);
> +
> + /* Populate the multicast address */
> + ZeroMemory(&multicast_addr, sizeof(SOCKADDR_STORAGE));
> +
> + if (bind_address->ss_family == AF_INET)
> + {
> + SOCKADDR_IN *sockaddr4 = (SOCKADDR_IN *)&multicast_addr;
> +
> + sockaddr4->sin_port = htons(SEND_PORT);
> + sockaddr4->sin_addr.S_un.S_addr = htonl(SEND_ADDRESS_IPV4);
> + address_length = sizeof(SOCKADDR_IN);
> + }
> + else
> + {
> + SOCKADDR_IN6 *sockaddr6 = (SOCKADDR_IN6 *)&multicast_addr;
> +
> + sockaddr6->sin6_port = htons(SEND_PORT);
> + memcpy(&sockaddr6->sin6_addr, &send_address_ipv6, sizeof(send_address_ipv6));
> + address_length = sizeof(SOCKADDR_IN6);
> + }
> +
> + /* Update the port for the binding address */
> + memcpy(&bind_addr, bind_address, address_length);
> + ((SOCKADDR_IN *)&bind_addr)->sin_port = htons(SEND_PORT);
> +
> + /* Update the port for the interface address */
> + memcpy(&interface_addr, bind_address, address_length);
> + ((SOCKADDR_IN *)&interface_addr)->sin_port = htons(0);
> +
> + /* Create the socket */
> + s = socket(bind_address->ss_family, SOCK_DGRAM, IPPROTO_UDP);
> +
> + if (s == INVALID_SOCKET)
> + {
> + WARN("socket() failed (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Ensure the socket can be reused */
> + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)) == SOCKET_ERROR)
> + {
> + WARN("setsockopt(SO_REUSEADDR) failed (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Bind the socket to the local interface so we can receive data */
> + if (bind(s, (struct sockaddr *)&bind_addr, address_length) == SOCKET_ERROR)
> + {
> + WARN("bind() failed (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Join the multicast group */
> + if (join_multicast_group(s, &multicast_addr, &interface_addr) == SOCKET_ERROR)
> + {
> + WARN("Unable to join multicast group (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Set the outgoing interface */
> + if (set_send_interface(s, &interface_addr) == SOCKET_ERROR)
> + {
> + WARN("Unable to set outgoing interface (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Set a 5-second receive timeout */
> + if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&receive_timeout, sizeof(receive_timeout)) == SOCKET_ERROR)
> + {
> + WARN("setsockopt(SO_RCVTIME0) failed (error %d)\n", WSAGetLastError());
> + goto cleanup;
> + }
> +
> + /* Allocate memory for thread parameters */
> + parameter = heap_alloc(sizeof(listener_thread_params));
> +
> + parameter->impl = impl;
> + parameter->listening_socket = s;
> + parameter->ipv6 = (bind_address->ss_family == AF_INET6);
> +
> + thread_handle = CreateThread(NULL, 0, listening_thread, parameter, 0, NULL);
> +
> + if (thread_handle == NULL)
> + {
> + WARN("CreateThread failed (error %d)\n", GetLastError());
> + goto cleanup;
> + }
> +
> + impl->thread_handles[impl->num_thread_handles] = thread_handle;
> + impl->num_thread_handles++;
> +
> + return;
> +
> +cleanup:
> + closesocket(s);
> + heap_free(parameter);
> +}
> +
> +static BOOL start_listening_on_all_addresses(IWSDiscoveryPublisherImpl *impl, ULONG family)
> +{
> + IP_ADAPTER_ADDRESSES *adapter_addresses = NULL, *adapter_address;
> + ULONG bufferSize = 0;
> + ULONG ret;
> +
> + ret = GetAdaptersAddresses(family, 0, NULL, NULL, &bufferSize); /* family should be AF_INET or AF_INET6 */
> +
> + if (ret != ERROR_BUFFER_OVERFLOW)
> + {
> + WARN("GetAdaptorsAddresses failed with error %08x\n", ret);
> + return FALSE;
> + }
> +
> + /* Get size of buffer for adapters */
> + adapter_addresses = (IP_ADAPTER_ADDRESSES *)heap_alloc(bufferSize);
> +
> + if (adapter_addresses == NULL)
> + {
> + WARN("Out of memory allocating space for adapter information\n");
> + return FALSE;
> + }
> +
> + /* Get list of adapters */
> + ret = GetAdaptersAddresses(family, 0, NULL, adapter_addresses, &bufferSize);
> +
> + if (ret != ERROR_SUCCESS)
> + {
> + WARN("GetAdaptorsAddresses failed with error %08x\n", ret);
> + goto cleanup;
> + }
> +
> + for (adapter_address = adapter_addresses; adapter_address != NULL; adapter_address = adapter_address->Next)
> + {
> + if (impl->num_thread_handles >= MAX_WSD_THREADS)
> + {
> + WARN("Exceeded maximum number of supported listener threads; too many network interfaces.");
> + goto cleanup;
> + }
> +
> + if (adapter_address->FirstUnicastAddress == NULL)
> + {
> + TRACE("No address found for adaptor '%s' (%p)\n", adapter_address->AdapterName, adapter_address);
> + continue;
> + }
> +
> + start_listening(impl, (SOCKADDR_STORAGE *)adapter_address->FirstUnicastAddress->Address.lpSockaddr);
> + }
> +
> +cleanup:
> + heap_free(adapter_addresses);
> + return ret == ERROR_SUCCESS;
> +}
> +
> void terminate_networking(IWSDiscoveryPublisherImpl *impl)
> {
> BOOL needsCleanup = impl->publisherStarted;
>
> impl->publisherStarted = FALSE;
> + WaitForMultipleObjects(impl->num_thread_handles, impl->thread_handles, TRUE, INFINITE);
>
> if (needsCleanup)
> WSACleanup();
> @@ -254,6 +521,15 @@ BOOL init_networking(IWSDiscoveryPublisherImpl *impl)
>
> impl->publisherStarted = TRUE;
>
> - /* TODO: Start listening */
> + if ((impl->addressFamily & WSDAPI_ADDRESSFAMILY_IPV4) && (!start_listening_on_all_addresses(impl, AF_INET)))
> + goto cleanup;
> +
> + if ((impl->addressFamily & WSDAPI_ADDRESSFAMILY_IPV6) && (!start_listening_on_all_addresses(impl, AF_INET6)))
> + goto cleanup;
> +
> return TRUE;
> +
> +cleanup:
> + terminate_networking(impl);
> + return FALSE;
> }
> diff --git a/dlls/wsdapi/wsdapi_internal.h b/dlls/wsdapi/wsdapi_internal.h
> index 45d54c2ef1..f88822d5ef 100644
> --- a/dlls/wsdapi/wsdapi_internal.h
> +++ b/dlls/wsdapi/wsdapi_internal.h
> @@ -40,6 +40,8 @@ struct notificationSink
> IWSDiscoveryPublisherNotify *notificationSink;
> };
>
> +#define MAX_WSD_THREADS 20
> +
> typedef struct IWSDiscoveryPublisherImpl {
> IWSDiscoveryPublisher IWSDiscoveryPublisher_iface;
> LONG ref;
> @@ -47,6 +49,8 @@ typedef struct IWSDiscoveryPublisherImpl {
> DWORD addressFamily;
> struct list notificationSinks;
> BOOL publisherStarted;
> + HANDLE thread_handles[MAX_WSD_THREADS];
> + int num_thread_handles;
> } IWSDiscoveryPublisherImpl;
>
> /* network.c */
>
>
June 7, 2018
[PATCH 2/2] schedsvc: Add support for running missed tasks at the service start.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 24 ++++++++++++++++++++++++
dlls/schedsvc/schedsvc_private.h | 1 +
dlls/schedsvc/svc_main.c | 1 +
3 files changed, 26 insertions(+)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index da837d8a8e..6c6e3e109e 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -1033,6 +1033,30 @@ void check_task_time(void)
LeaveCriticalSection(&at_job_list_section);
}
+void check_missed_task_time(void)
+{
+ FILETIME current_ft, last_ft;
+ struct job_t *job;
+
+ GetSystemTimeAsFileTime(¤t_ft);
+ FileTimeToLocalFileTime(¤t_ft, ¤t_ft);
+
+ EnterCriticalSection(&at_job_list_section);
+
+ LIST_FOR_EACH_ENTRY(job, &at_job_list, struct job_t, entry)
+ {
+ if (SystemTimeToFileTime(&job->data.last_runtime, &last_ft))
+ {
+ if (job_runs_at(job, &last_ft, ¤t_ft))
+ {
+ run_job(job);
+ }
+ }
+ }
+
+ LeaveCriticalSection(&at_job_list_section);
+}
+
void remove_job(const WCHAR *name)
{
struct job_t *job;
diff --git a/dlls/schedsvc/schedsvc_private.h b/dlls/schedsvc/schedsvc_private.h
index 10892d55ca..117c6f51ed 100644
--- a/dlls/schedsvc/schedsvc_private.h
+++ b/dlls/schedsvc/schedsvc_private.h
@@ -31,6 +31,7 @@ void update_process_status(DWORD pid) DECLSPEC_HIDDEN;
BOOL get_next_runtime(LARGE_INTEGER *rt) DECLSPEC_HIDDEN;
void check_task_time(void) DECLSPEC_HIDDEN;
void load_at_tasks(void) DECLSPEC_HIDDEN;
+void check_missed_task_time(void) DECLSPEC_HIDDEN;
static inline WCHAR *heap_strdupW(const WCHAR *src)
{
diff --git a/dlls/schedsvc/svc_main.c b/dlls/schedsvc/svc_main.c
index 2bba674b07..8e23a049db 100644
--- a/dlls/schedsvc/svc_main.c
+++ b/dlls/schedsvc/svc_main.c
@@ -54,6 +54,7 @@ static DWORD WINAPI tasks_monitor_thread(void *arg)
TRACE("Starting...\n");
load_at_tasks();
+ check_missed_task_time();
htimer = CreateWaitableTimerW(NULL, FALSE, NULL);
if (htimer == NULL)
--
2.16.3
June 7, 2018
[PATCH 1/2] schedsvc: Load job files at the service start up.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 41 ++++++++++++++++++++++++++++++++++++++++
dlls/schedsvc/schedsvc_private.h | 1 +
dlls/schedsvc/svc_main.c | 2 ++
3 files changed, 44 insertions(+)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index 91ef3edca0..da837d8a8e 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -617,6 +617,47 @@ void add_job(const WCHAR *name)
LeaveCriticalSection(&at_job_list_section);
}
+static inline BOOL is_file(const WIN32_FIND_DATAW *data)
+{
+ return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+void load_at_tasks(void)
+{
+ static const WCHAR tasksW[] = { '\\','T','a','s','k','s','\\',0 };
+ static const WCHAR allW[] = { '*',0 };
+ WCHAR windir[MAX_PATH], path[MAX_PATH];
+ WIN32_FIND_DATAW data;
+ HANDLE handle;
+
+ GetWindowsDirectoryW(windir, MAX_PATH);
+ lstrcpyW(path, windir);
+ lstrcatW(path, tasksW);
+ lstrcatW(path, allW);
+
+ handle = FindFirstFileW(path, &data);
+ if (handle == INVALID_HANDLE_VALUE) return;
+
+ do
+ {
+ if (is_file(&data))
+ {
+ lstrcpyW(path, windir);
+ lstrcatW(path, tasksW);
+
+ if (lstrlenW(path) + lstrlenW(data.cFileName) < MAX_PATH)
+ {
+ lstrcatW(path, data.cFileName);
+ add_job(path);
+ }
+ else
+ FIXME("too long file name %s\n", debugstr_w(data.cFileName));
+ }
+ } while (FindNextFileW(handle, &data));
+
+ FindClose(handle);
+}
+
static BOOL write_signature(HANDLE hfile)
{
struct
diff --git a/dlls/schedsvc/schedsvc_private.h b/dlls/schedsvc/schedsvc_private.h
index d601030e78..10892d55ca 100644
--- a/dlls/schedsvc/schedsvc_private.h
+++ b/dlls/schedsvc/schedsvc_private.h
@@ -30,6 +30,7 @@ void add_process_to_queue(HANDLE hproc) DECLSPEC_HIDDEN;
void update_process_status(DWORD pid) DECLSPEC_HIDDEN;
BOOL get_next_runtime(LARGE_INTEGER *rt) DECLSPEC_HIDDEN;
void check_task_time(void) DECLSPEC_HIDDEN;
+void load_at_tasks(void) DECLSPEC_HIDDEN;
static inline WCHAR *heap_strdupW(const WCHAR *src)
{
diff --git a/dlls/schedsvc/svc_main.c b/dlls/schedsvc/svc_main.c
index 0dfac818fd..2bba674b07 100644
--- a/dlls/schedsvc/svc_main.c
+++ b/dlls/schedsvc/svc_main.c
@@ -53,6 +53,8 @@ static DWORD WINAPI tasks_monitor_thread(void *arg)
TRACE("Starting...\n");
+ load_at_tasks();
+
htimer = CreateWaitableTimerW(NULL, FALSE, NULL);
if (htimer == NULL)
{
--
2.16.3
June 7, 2018
[PATCH 4/4] testbot: Switch Patches::Submit() to the new job staging standard.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/Patches.pm | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/testbot/lib/WineTestBot/Patches.pm b/testbot/lib/WineTestBot/Patches.pm
index 4f428133f..e349dfe88 100644
--- a/testbot/lib/WineTestBot/Patches.pm
+++ b/testbot/lib/WineTestBot/Patches.pm
@@ -166,7 +166,6 @@ sub Submit($$$)
# Create a new job for this patch
my $NewJob = $Jobs->Add();
- $NewJob->Status("queued");
$NewJob->User($User);
$NewJob->Priority(6);
my $PropertyDescriptor = $Jobs->GetPropertyDescriptorByName("Remarks");
@@ -181,11 +180,9 @@ sub Submit($$$)
# Add build step to the job
my $Steps = $NewJob->Steps;
my $NewStep = $Steps->Add();
- # Create a link to the patch file in the staging dir
- my $StagingFileName = CreateNewLink($PatchFileName, "$DataDir/staging", "_patch.diff");
- $NewStep->FileName(basename($StagingFileName));
+ $NewStep->FileName("patch.diff");
$NewStep->FileType($TestInfo->{Type});
- $NewStep->InStaging(1);
+ $NewStep->InStaging(!1);
$NewStep->Type("build");
$NewStep->DebugLevel(0);
@@ -198,7 +195,7 @@ sub Submit($$$)
$Task->VM($BuildVM);
$Task->Timeout($BuildTimeout);
- # Save this step (&job+task) so the others can reference it
+ # Save the build step so other steps can reference it
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined($ErrMessage))
{
@@ -206,6 +203,13 @@ sub Submit($$$)
return $ErrMessage;
}
+ # Stage the patch so it can be picked up by the job
+ if (!link($PatchFileName, "$DataDir/staging/job". $NewJob->Id ."_patch.diff"))
+ {
+ $self->Disposition("Failed to prepare patch file");
+ return $!;
+ }
+
foreach my $Unit (sort keys %{$TestInfo->{Units}})
{
# Add 32 and 64-bit tasks
@@ -217,7 +221,7 @@ sub Submit($$$)
if (@{$VMs->GetKeys()})
{
# Create the corresponding Step
- $NewStep = $Steps->Add();
+ my $NewStep = $Steps->Add();
$NewStep->PreviousNo(1);
my $FileName = $TestInfo->{ExeBase};
$FileName .= "64" if ($Bits eq "64");
@@ -240,13 +244,23 @@ sub Submit($$$)
}
}
+ # Save it all
($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
- if (defined($ErrMessage))
+ if (defined $ErrMessage)
{
$self->Disposition("Failed to submit job");
return $ErrMessage;
}
+ # Switch Status to staging to indicate we are done setting up the job
+ $NewJob->Status("staging");
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
+ {
+ $self->Disposition("Failed to submit job (staging)");
+ return $ErrMessage;
+ }
+
if ($First)
{
$First = !1;
--
2.17.0
June 6, 2018
[PATCH 3/4] testbot/web: Switch Submit to the new job staging standard.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/Submit.pl | 63 ++++++++++++++++++++-----------------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/testbot/web/Submit.pl b/testbot/web/Submit.pl
index 8e22621fd..d5265a3b3 100644
--- a/testbot/web/Submit.pl
+++ b/testbot/web/Submit.pl
@@ -753,28 +753,11 @@ sub OnSubmit($)
my $BaseName = $self->ValidateAndGetFileName("FileName");
return !1 if (!$BaseName);
- # Store the file in the staging directory until the relevant Job and Step
- # IDs are known and it can be moved to the jobs directory tree. But rename
- # it so it does not get overwritten if the user submits another one before
- # the Engine gets around to doing so.
- my $StagingFileName = CreateNewFile("$DataDir/staging", "_$BaseName");
-
- my $TmpStagingFullPath = $self->GetTmpStagingFullPath($BaseName);
- if ($StagingFileName and !rename($TmpStagingFullPath, $StagingFileName))
- {
- $self->{ErrMessage} = "Could not rename '$TmpStagingFullPath' to '$StagingFileName': $!\n";
- unlink($StagingFileName);
- $StagingFileName = undef;
- }
- # If needed fall back to the existing staging file and hope for the best.
- $StagingFileName = basename($StagingFileName || $TmpStagingFullPath);
-
# See also Patches::Submit() in lib/WineTestBot/Patches.pm
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
- $NewJob->Status("queued");
$NewJob->User($self->GetCurrentSession()->User);
$NewJob->Priority(5);
if ($self->GetParam("Remarks"))
@@ -792,15 +775,15 @@ sub OnSubmit($)
}
my $Steps = $NewJob->Steps;
+ my $BuildStep;
my $FileType = $self->GetParam("FileType");
- my $BuildStepNo;
if ($FileType eq "patchdlls" || $FileType eq "patchprograms")
{
# This is a patch so add a build step...
- my $BuildStep = $Steps->Add();
- $BuildStep->FileName($StagingFileName);
+ $BuildStep = $Steps->Add();
+ $BuildStep->FileName($BaseName);
$BuildStep->FileType($FileType);
- $BuildStep->InStaging(1);
+ $BuildStep->InStaging(!1);
$BuildStep->Type("build");
$BuildStep->DebugLevel(0);
@@ -813,14 +796,13 @@ sub OnSubmit($)
$Task->VM($BuildVM);
$Task->Timeout($BuildTimeout);
- # Save this step (&job+task) so the others can reference it
+ # Save the build step so the others can reference it
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined($ErrMessage))
{
$self->{ErrMessage} = $ErrMessage;
return !1;
}
- $BuildStepNo = 1;
}
# Add steps and tasks for the 32 and 64-bit tests
@@ -844,22 +826,18 @@ sub OnSubmit($)
{
# First create the test step
my $TestStep = $Steps->Add();
- $TestStep->PreviousNo($BuildStepNo);
if ($FileType eq "patchdlls" || $FileType eq "patchprograms")
{
- my $FileName=$self->GetParam("TestExecutable");
- if ($Bits eq "64")
- {
- $FileName =~ s/_test\.exe$/_test64.exe/;
- }
- $TestStep->FileName($FileName);
- $TestStep->InStaging(!1);
+ $TestStep->PreviousNo($BuildStep->No);
+ my $TestExe = basename($self->GetParam("TestExecutable"));
+ $TestExe =~ s/_test\.exe$/_test64.exe/ if ($Bits eq "64");
+ $TestStep->FileName($TestExe);
}
else
{
- $TestStep->FileName($StagingFileName);
- $TestStep->InStaging(1);
+ $TestStep->FileName($BaseName);
}
+ $TestStep->InStaging(!1);
$TestStep->FileType("exe$Bits");
$TestStep->Type("single");
$TestStep->DebugLevel($self->GetParam("DebugLevel"));
@@ -875,7 +853,7 @@ sub OnSubmit($)
}
}
- # Now save the whole thing (or whatever's left to save)
+ # Now save it all (or whatever's left to save)
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined($ErrMessage))
{
@@ -883,6 +861,23 @@ sub OnSubmit($)
return !1;
}
+ # Stage the test patch/executable so the job can pick it up
+ my $TmpStagingFullPath = $self->GetTmpStagingFullPath($BaseName);
+ if (!rename($TmpStagingFullPath, "$DataDir/staging/job". $NewJob->Id ."_$BaseName"))
+ {
+ $self->{ErrMessage} = "Could not stage '$BaseName': $!\n";
+ return !1;
+ }
+
+ # Switch Status to staging to indicate we are done setting up the job
+ $NewJob->Status("staging");
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined($ErrMessage))
+ {
+ $self->{ErrMessage} = $ErrMessage;
+ return !1;
+ }
+
# Notify engine
my $ErrMessage = RescheduleJobs();
if (defined $ErrMessage)
--
2.17.0
June 6, 2018
[PATCH 2/4] testbot: Switch CheckForWinetestUpdate.pl to the new job staging standard.
by Francois Gouget
The new approach ensures there is no race condition with the TestBot
Engine between saving the job and saving the steps.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/CheckForWinetestUpdate.pl | 46 +++++++++++++++++++--------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/testbot/bin/CheckForWinetestUpdate.pl b/testbot/bin/CheckForWinetestUpdate.pl
index 17dab8236..137db572c 100755
--- a/testbot/bin/CheckForWinetestUpdate.pl
+++ b/testbot/bin/CheckForWinetestUpdate.pl
@@ -192,15 +192,9 @@ sub AddJob($$$)
return 1;
}
- # Create a hard link in staging so it can then be moved into the job
- # directory. This is ok because the latest file is never overwritten.
- my $StagingFileName = CreateNewLink("$DataDir/latest/$LatestBaseName",
- "$DataDir/staging", "_$LatestBaseName");
-
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
- $NewJob->Status("queued");
$NewJob->User(GetBatchUser());
$NewJob->Priority($BaseJob && $Bits == 32 ? 8 : 9);
$NewJob->Remarks($Remarks);
@@ -210,9 +204,9 @@ sub AddJob($$$)
my $NewStep = $Steps->Add();
my $BitsSuffix = ($Bits == 64 ? "64" : "");
$NewStep->Type("suite");
- $NewStep->FileName(basename($StagingFileName));
+ $NewStep->FileName($LatestBaseName);
$NewStep->FileType($Bits == 64 ? "exe64" : "exe32");
- $NewStep->InStaging(1);
+ $NewStep->InStaging(!1);
# Add a task for each VM
my $Tasks = $NewStep->Tasks;
@@ -224,12 +218,28 @@ sub AddJob($$$)
$Task->Timeout($SuiteTimeout);
}
- # Now save the whole thing
+ # Save it all
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined $ErrMessage)
{
- Error "Failed to save job: $ErrMessage\n";
- unlink($StagingFileName);
+ LogMsg "Failed to save the $LatestBaseName job: $ErrMessage\n";
+ return 0;
+ }
+
+ # Stage the test file so it can be picked up by the job
+ if (!link("$DataDir/latest/$LatestBaseName",
+ "$DataDir/staging/job". $NewJob->Id ."_$LatestBaseName"))
+ {
+ Error "Failed to stage $LatestBaseName: $!\n";
+ return 0;
+ }
+
+ # Switch Status to staging to indicate we are done setting up the job
+ $NewJob->Status("staging");
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
+ {
+ Error "Failed to save the $LatestBaseName job (staging): $ErrMessage\n";
return 0;
}
@@ -244,7 +254,6 @@ sub AddReconfigJob()
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
- $NewJob->Status("queued");
$NewJob->User(GetBatchUser());
$NewJob->Priority(3);
$NewJob->Remarks($Remarks);
@@ -266,11 +275,20 @@ sub AddReconfigJob()
$Task->VM($BuildVM);
$Task->Timeout($ReconfigTimeout);
- # Now save the whole thing
+ # Save it all
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined $ErrMessage)
{
- Error "Failed to save reconfig job: $ErrMessage\n";
+ Error "Failed to save the Reconfig job: $ErrMessage\n";
+ return 0;
+ }
+
+ # Switch Status to staging to indicate we are done setting up the job
+ $NewJob->Status("staging");
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
+ {
+ Error "Failed to save the Reconfig job (staging): $ErrMessage\n";
return 0;
}
}
--
2.17.0
June 6, 2018
[PATCH 1/4] testbot: Handle staging at the Job level and avoid race conditions.
by Francois Gouget
When a patch or executable is submitted for testing it is stored in the
staging directory for two reasons, first because the corresponding Job
does not exist yet, and second because the process may not have write
permissions to the Job directory.
So far transfering the file to the Job directory was the responsibility
of the Step that needs it. However this breaks down when more than one
Step needs that file (e.g. a Windows executable build Step and a Wine
testing one).
There is also a (very unlikely) race condition between the scheduler
and the Job creation: the Scheduler could run the first saved Task, mark
it and the Job as completed before the Job's other Steps and Tasks get
saved to the database. Those would then never get run since the Jobs
has completed.
So this patch makes staging the responsibility of the Job and introduces
a staging Status for it.
It also introduces a new Status which indicates the Job is still being
set up to avoid race conditions.
Note that this patch preserves the Step-based staging mechanism for
backward compatibility during the transition.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
Note:
* This requires updating the database schema and restarting the TestBot
Engine and web server.
* The following patches switch each Job creator to the new scheme.
testbot/bin/CheckForWinetestUpdate.pl | 2 ++
testbot/ddl/update36.sql | 4 +++
testbot/ddl/winetestbot.sql | 2 +-
testbot/lib/WineTestBot/Engine/Scheduler.pm | 30 ++++++++++++++++++++-
testbot/lib/WineTestBot/Jobs.pm | 20 +++++++++++---
testbot/lib/WineTestBot/Patches.pm | 1 +
testbot/web/Submit.pl | 1 +
7 files changed, 54 insertions(+), 6 deletions(-)
create mode 100644 testbot/ddl/update36.sql
diff --git a/testbot/bin/CheckForWinetestUpdate.pl b/testbot/bin/CheckForWinetestUpdate.pl
index f41148f12..17dab8236 100755
--- a/testbot/bin/CheckForWinetestUpdate.pl
+++ b/testbot/bin/CheckForWinetestUpdate.pl
@@ -200,6 +200,7 @@ sub AddJob($$$)
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
+ $NewJob->Status("queued");
$NewJob->User(GetBatchUser());
$NewJob->Priority($BaseJob && $Bits == 32 ? 8 : 9);
$NewJob->Remarks($Remarks);
@@ -243,6 +244,7 @@ sub AddReconfigJob()
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
+ $NewJob->Status("queued");
$NewJob->User(GetBatchUser());
$NewJob->Priority(3);
$NewJob->Remarks($Remarks);
diff --git a/testbot/ddl/update36.sql b/testbot/ddl/update36.sql
new file mode 100644
index 000000000..2f4bf7fa2
--- /dev/null
+++ b/testbot/ddl/update36.sql
@@ -0,0 +1,4 @@
+USE winetestbot;
+
+ALTER TABLE Jobs
+ MODIFY Status ENUM('new', 'staging', 'queued', 'running', 'completed', 'badpatch', 'badbuild', 'boterror', 'canceled') NOT NULL;
diff --git a/testbot/ddl/winetestbot.sql b/testbot/ddl/winetestbot.sql
index 9a28385a9..1e7b1edd1 100644
--- a/testbot/ddl/winetestbot.sql
+++ b/testbot/ddl/winetestbot.sql
@@ -113,7 +113,7 @@ CREATE TABLE Jobs
BranchName VARCHAR(20) NOT NULL,
UserName VARCHAR(40) NOT NULL,
Priority INT(1) NOT NULL,
- Status ENUM('queued', 'running', 'completed', 'badpatch', 'badbuild', 'boterror', 'canceled') NOT NULL,
+ Status ENUM('new', 'staging', 'queued', 'running', 'completed', 'badpatch', 'badbuild', 'boterror', 'canceled') NOT NULL,
Remarks VARCHAR(128) NULL,
Submitted DATETIME NOT NULL,
Ended DATETIME NULL,
diff --git a/testbot/lib/WineTestBot/Engine/Scheduler.pm b/testbot/lib/WineTestBot/Engine/Scheduler.pm
index 10c0b70ed..85bc0f397 100644
--- a/testbot/lib/WineTestBot/Engine/Scheduler.pm
+++ b/testbot/lib/WineTestBot/Engine/Scheduler.pm
@@ -30,6 +30,8 @@ WineTestBot::Engine::Scheduler - Schedules the TestBot tasks
use Exporter 'import';
our @EXPORT = qw(ScheduleJobs CheckJobs);
+use File::Copy;
+
use WineTestBot::Config;
use WineTestBot::Engine::Events;
use WineTestBot::Jobs;
@@ -524,11 +526,37 @@ sub _ScheduleTasks($)
# Process the jobs in decreasing priority order
my $JobRank;
my $Jobs = CreateJobs($Sched->{VMs});
- $Jobs->AddFilter("Status", ["queued", "running"]);
+ $Jobs->AddFilter("Status", ["staging", "queued", "running"]);
foreach my $Job (sort CompareJobPriority @{$Jobs->GetItems()})
{
$JobRank++;
+ if ($Job->Status eq "staging")
+ {
+ # Move the file(s) from the staging directory to the job directory
+ my %Staged;
+ my $JobDir = $Job->CreateDir();
+ foreach my $Step (@{$Job->Steps->Clone()->GetItems()})
+ {
+ # Ignore steps that need a file provided by the previous step
+ next if ($Step->PreviousNo or !defined $Step->FileName);
+ # Skip the step if its file has already been staged
+ next if ($Staged{$Step->FileName});
+
+ my $StagingFile = "job". $Job->Id ."_". $Step->FileName;
+ if (move("$DataDir/staging/$StagingFile", "$JobDir/". $Step->FileName))
+ {
+ $Staged{$Step->FileName} = 1;
+ }
+ else
+ {
+ LogMsg "Could not move the '$StagingFile' staging file: $!";
+ }
+ }
+ $Job->Status("queued");
+ $Job->Save();
+ }
+
# The per-step lists of VMs that should be getting ready to run
# before we prepare the next step
my %StepVMs = ("" => []); # no dependency for the first step
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index 13a389586..3fd78aaa2 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -1,6 +1,6 @@
# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
# Copyright 2009 Ge van Geldorp
-# Copyright 2012-2017 Francois Gouget
+# Copyright 2012-2018 Francois Gouget
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -52,7 +52,19 @@ A Job's lifecycle is as follows:
=over
=item *
-A Job is created with Status set to queued which means it is ready to run.
+A Job is created with Status set to new. During this time the process setting
+up the Job can add new Steps and Tasks to it. It can also put the required
+input files into place in the staging directory with a name of the form
+'job<JobID>_<FileName>' where <JobId> is the Id of the new Job, and FileName is
+the name of a file a Step depends on.
+
+=item *
+Once the Job set up is complete its Status is set to staging. This indicates
+that the TestBot Engine can retrieve the files it depends on from the staging
+directory and move them to the Job's directory.
+
+=item *
+Then the Status is set to queued which indicates the Job is ready to run.
=item *
As soon as one of the Step starts running, the Job's Status field is set to
@@ -93,7 +105,7 @@ sub InitializeNew($$)
my ($self, $Collection) = @_;
$self->Branch(CreateBranches()->GetDefaultBranch());
- $self->Status("queued");
+ $self->Status("new");
$self->Submitted(time());
$self->SUPER::InitializeNew($Collection);
@@ -446,7 +458,7 @@ my @PropertyDescriptors = (
CreateItemrefPropertyDescriptor("Branch", "Branch", !1, 1, \&CreateBranches, ["BranchName"]),
CreateItemrefPropertyDescriptor("User", "Author", !1, 1, \&CreateUsers, ["UserName"]),
CreateBasicPropertyDescriptor("Priority", "Priority", !1, 1, "N", 1),
- CreateEnumPropertyDescriptor("Status", "Status", !1, 1, ['queued', 'running', 'completed', 'badpatch', 'badbuild', 'boterror', 'canceled']),
+ CreateEnumPropertyDescriptor("Status", "Status", !1, 1, ['new', 'staging', 'queued', 'running', 'completed', 'badpatch', 'badbuild', 'boterror', 'canceled']),
CreateBasicPropertyDescriptor("Remarks", "Remarks", !1, !1, "A", 128),
CreateBasicPropertyDescriptor("Submitted", "Submitted", !1, !1, "DT", 19),
CreateBasicPropertyDescriptor("Ended", "Ended", !1, !1, "DT", 19),
diff --git a/testbot/lib/WineTestBot/Patches.pm b/testbot/lib/WineTestBot/Patches.pm
index d5be1b355..4f428133f 100644
--- a/testbot/lib/WineTestBot/Patches.pm
+++ b/testbot/lib/WineTestBot/Patches.pm
@@ -166,6 +166,7 @@ sub Submit($$$)
# Create a new job for this patch
my $NewJob = $Jobs->Add();
+ $NewJob->Status("queued");
$NewJob->User($User);
$NewJob->Priority(6);
my $PropertyDescriptor = $Jobs->GetPropertyDescriptorByName("Remarks");
diff --git a/testbot/web/Submit.pl b/testbot/web/Submit.pl
index ae69e7ce5..8e22621fd 100644
--- a/testbot/web/Submit.pl
+++ b/testbot/web/Submit.pl
@@ -774,6 +774,7 @@ sub OnSubmit($)
# First create a new job
my $Jobs = CreateJobs();
my $NewJob = $Jobs->Add();
+ $NewJob->Status("queued");
$NewJob->User($self->GetCurrentSession()->User);
$NewJob->Priority(5);
if ($self->GetParam("Remarks"))
--
2.17.0
June 6, 2018
[PATCH] testbot: Also mark the VM for maintenance if the reverts get stuck.
by Francois Gouget
When a VM takes a long time to revert the LibvirtTool.pl process
typically remains stuck in the Sys::Virt::DomainSnapshot::revert_to()
call and cannot enforce the timeout itself, thus causing the timeout to
be detected at the TestBot Engine level.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
Live QEmu snapshots are still unusable when when the clock is set to the
LibVirt default, that is:
<clock offset='utc'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
</clock>
testbot/lib/WineTestBot/Engine/Scheduler.pm | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/testbot/lib/WineTestBot/Engine/Scheduler.pm b/testbot/lib/WineTestBot/Engine/Scheduler.pm
index a191f0e1c..10c0b70ed 100644
--- a/testbot/lib/WineTestBot/Engine/Scheduler.pm
+++ b/testbot/lib/WineTestBot/Engine/Scheduler.pm
@@ -267,8 +267,15 @@ sub _CheckAndClassifyVMs()
{
# The child process got stuck!
$FoundVMErrors = 1;
+ my $NewStatus = "dirty";
+ if ($VM->Status eq "reverting" or $VM->Status eq "sleeping")
+ {
+ my $Errors = ($VM->Errors || 0) + 1;
+ $VM->Errors($Errors);
+ $NewStatus = "maintenance" if ($Errors >= $MaxVMErrors);
+ }
+ $VM->Status($NewStatus);
$VM->KillChild();
- $VM->Status("dirty");
$VM->Save();
$VM->RecordResult($Sched->{records}, "boterror stuck process");
$Sched->{lambvms}->{$VMKey} = 1;
--
2.17.0
June 6, 2018
[PATCH 4/4] wsdapi: Add initial support for reading messages; identify Probe message.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/soap.c | 340
+++++++++++++++++++++++++++++++++++++++++-
dlls/wsdapi/tests/discovery.c | 6 +-
2 files changed, 341 insertions(+), 5 deletions(-)
June 6, 2018
[PATCH 3/4] wsdapi: Add stub for Probe message parsing, prepare notification sink message.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/network.c | 52
++++++++++++++++++++++++++++++++++++++++++-
dlls/wsdapi/soap.c | 6 +++++
dlls/wsdapi/wsdapi_internal.h | 5 +++++
3 files changed, 62 insertions(+), 1 deletion(-)
June 6, 2018
[PATCH 2/4] wsdapi: Add critical section around notification sinks.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/discovery.c | 9 +++++++++
dlls/wsdapi/wsdapi_internal.h | 1 +
2 files changed, 10 insertions(+)
June 6, 2018
[PATCH 1/4] wsdapi: Add support for listening for UDP multicast broadcasts.
by Owen Rudge
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/network.c | 278
+++++++++++++++++++++++++++++++++++++++++-
dlls/wsdapi/wsdapi_internal.h | 4 +
2 files changed, 281 insertions(+), 1 deletion(-)
June 6, 2018
Re: [PATCH] comctl32/tests: Use the available ARRAY_SIZE() macro
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39020
Your paranoid android.
=== wvistau64_zh_CN (32 bit ipaddress) ===
TestBot process got stuck or died unexpectedly
The previous 1 run(s) terminated abnormally
=== wvistau64 (32 bit listbox) ===
listbox.c:939: Test failed: SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err 18
=== wvistau64_zh_CN (32 bit listbox) ===
listbox.c:939: Test failed: SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err 18
=== wvistau64_fr (32 bit listbox) ===
listbox.c:939: Test failed: SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err 18
=== wvistau64_he (32 bit listbox) ===
listbox.c:939: Test failed: SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err 18
=== wvistau64 (64 bit listbox) ===
listbox.c:939: Test failed: SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err 18
=== wvistau64_zh_CN (32 bit edit) ===
edit.c:1542: Test failed: 0: got 2, 1
edit.c:1563: Test failed: 0: got 2, 1
edit.c:1577: Test failed: 0: got 2, 1
edit.c:1591: Test failed: 0: got 2, 1
edit.c:1717: Test failed: got 1
edit.c:1718: Test failed: got 1
edit.c:1724: Test failed: got 1
edit.c:1740: Test failed: got 2
edit.c:1763: Test failed: got 1
June 6, 2018
Re: [PATCH] comctl32/taskdialog/tests: Add a basic taskdialog creator as interactive test
by Fabian Maurer
> Personally I don't think this is useful, because it won't run
> automatically and detect any problems.
I figured it'd be useful for interactive testing, I mean all interactive tests don't run
automatically. And I don't see a better way for visual testing here.
> If you want to see what it looks
> like or interact with it, it's trivial to make any taskdialog test not
> to close the dialog automatically.
That sounds hacky, I'd prefer real tests for that. Isn't that what interactvie tests are for?
I mean sure, we could add a bunch of special tests that we then pause when we want to
see what it looks like, but it's a lot easier to do visual checks with the creator I proposed -
without having to edit any code.
Regards,
Fabian Maurer
June 6, 2018
Re: [PATCH v2] comctl32/edit/tests: Add interactive test showing a rendering glitch
by Fabian Maurer
On Mittwoch, 6. Juni 2018 12:23:48 CEST Nikolay Sivov wrote:
> Do you know what's going on there? Is this about Edit painting
logic, or
> about Edit being used in a dialog?
I don't know what exactly causes this issue, but it seems comctl32
specific. Probably unrelated to a dialog, but I noticed it while
working on my interactive taskdialog-creator.
Regards,
Fabian Maurer
June 6, 2018
[PATCH 2/2] kernel32/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
Just format_msg.c for now as the diff is huge.
Same object is generated with or without this patch when adding
"-g0 -DWINETEST_NO_LINE_NUMBERS" to the CFLAGS.
dlls/kernel32/tests/format_msg.c | 408 ++++++++++++++++-----------------------
1 file changed, 164 insertions(+), 244 deletions(-)
diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c
index 43e4d35c8a..57ee78af9e 100644
--- a/dlls/kernel32/tests/format_msg.c
+++ b/dlls/kernel32/tests/format_msg.c
@@ -136,8 +136,7 @@ static void test_message_from_string_wide(void)
DWORD r, error;
/* the basics */
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4, "failed: r=%d\n", r);
@@ -146,15 +145,13 @@ static void test_message_from_string_wide(void)
{
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0, 0, out, ARRAY_SIZE(out), NULL);
}
/* empty string */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, empty, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, empty, 0, 0, out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(!lstrcmpW(empty, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==0, "succeeded: r=%d\n", r);
@@ -163,8 +160,7 @@ static void test_message_from_string_wide(void)
/* format placeholder with no specifier */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_null, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_null, 0, 0, out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the buffer to be unchanged\n");
@@ -174,8 +170,7 @@ static void test_message_from_string_wide(void)
/* test string with format placeholder with no specifier */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_tnull, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_tnull, 0, 0, out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
broken(!memcmp(out, broken_buf, sizeof(broken_buf))), /* W2K3+ */
@@ -186,8 +181,7 @@ static void test_message_from_string_wide(void)
/* insertion with no variadic arguments */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0, 0, out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the buffer to be unchanged\n");
@@ -197,7 +191,7 @@ static void test_message_from_string_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ 0, out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the buffer to be unchanged\n");
@@ -205,86 +199,72 @@ static void test_message_from_string_wide(void)
ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
/* using the format feature */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1s, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1s, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* no format */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* two pieces */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_12, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), te, st);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_12, 0, 0, out, ARRAY_SIZE(out), te, st);
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* three pieces */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), t, s, e);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123, 0, 0, out, ARRAY_SIZE(out), t, s, e);
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* s doesn't seem to work in format strings */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_s, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_s, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(&fmt_s[1], out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==3, "failed: r=%d\n", r);
/* nor ls */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ls, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ls, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(&fmt_ls[1], out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4, "failed: r=%d\n", r);
/* nor S */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_S, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_S, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(&fmt_S[1], out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==3, "failed: r=%d\n", r);
/* nor ws */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ws, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), test);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_ws, 0, 0, out, ARRAY_SIZE(out), test);
ok(!lstrcmpW(&fmt_ws[1], out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4, "failed: r=%d\n", r);
/* as characters */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123c, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123c, 0, 0, out, ARRAY_SIZE(out), 't', 'e', 's');
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* lc is unicode */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123lc, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123lc, 0, 0, out, ARRAY_SIZE(out), 't', 'e', 's');
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* wc is unicode */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123wc, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123wc, 0, 0, out, ARRAY_SIZE(out), 't', 'e', 's');
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* C is unicode */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123C, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 't', 'e', 's');
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123C, 0, 0, out, ARRAY_SIZE(out), 't', 'e', 's');
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* some numbers */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123d, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 1, 2, 3);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_123d, 0, 0, out, ARRAY_SIZE(out), 1, 2, 3);
ok(!lstrcmpW(s_123d, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==3,"failed: r=%d\n", r);
/* a single digit with some spacing */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 1);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0, 0, out, ARRAY_SIZE(out), 1);
ok(!lstrcmpW(s_14d, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
@@ -294,125 +274,105 @@ static void test_message_from_string_wide(void)
ok(r==4,"failed: r=%d\n", r);
/* two digit decimal number */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 11);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0, 0, out, ARRAY_SIZE(out), 11);
ok(!lstrcmpW(s_14d2, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* a hex number */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14x, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 11);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14x, 0, 0, out, ARRAY_SIZE(out), 11);
ok(!lstrcmpW(s_14x, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* a hex number, upper case */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 11);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0, 0, out, ARRAY_SIZE(out), 11);
ok(!lstrcmpW(s_14X, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* a hex number, upper case, left justified */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4X, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 11);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4X, 0, 0, out, ARRAY_SIZE(out), 11);
ok(!lstrcmpW(s_1_4X, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* a long hex number, upper case */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 0x1ab);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14X, 0, 0, out, ARRAY_SIZE(out), 0x1ab);
ok(!lstrcmpW(s_1AB, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* two percent... */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2pct, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2pct, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_2pct, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* periods are special cases */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2dot1d, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), 0x1ab);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_2dot1d, 0, 0, out, ARRAY_SIZE(out), 0x1ab);
ok(!lstrcmpW(s_2dot147, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==8,"failed: r=%d\n", r);
/* %0 ends the line */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_t0t, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_t0t, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* %! prints an exclamation */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_yah, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_yah, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_yah, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* %space */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_space, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_space, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_space, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* %n yields \r\n, %r yields \r, %t yields \t */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_nrt, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_nrt, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_nrt, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* line feed */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_lf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_lf, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_hi_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* carriage return line feed */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_crlf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_hi_crlf, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_hi_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* carriage return */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_cr, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_cr, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_crlf, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==2,"failed: r=%d\n", r);
/* double carriage return line feed */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_crcrlf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_crcrlf, 0, 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_crlfcrlf, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
/* null string as argument */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
- 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!lstrcmpW(s_null, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==6,"failed: r=%d\n",r);
/* precision and width */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_13s,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), t );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_13s, 0, 0, out, ARRAY_SIZE(out), t );
ok(!lstrcmpW(s_spt, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==3, "failed: r=%d\n",r);
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1os,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), 4, t );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1os, 0, 0, out, ARRAY_SIZE(out), 4, t );
ok(!lstrcmpW( s_sp3t, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n",r);
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_142u,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), 3 );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_142u, 0, 0, out, ARRAY_SIZE(out), 3 );
ok(!lstrcmpW( s_sp03, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n",r);
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1 );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou, 0, 0, out, ARRAY_SIZE(out), 5, 3, 1 );
ok(!lstrcmpW( s_sp001, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==5,"failed: r=%d\n",r);
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou1oou,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1, 4, 2 );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou1oou, 0, 0, out, ARRAY_SIZE(out),
+ 5, 3, 1, 4, 2 );
ok(!lstrcmpW( s_sp001002, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==11,"failed: r=%d\n",r);
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou3oou,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), 5, 3, 1, 6, 4, 2 );
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1oou3oou, 0, 0, out, ARRAY_SIZE(out),
+ 5, 3, 1, 6, 4, 2 );
ok(!lstrcmpW( s_sp001sp002, out) ||
broken(!lstrcmpW(s_sp001004, out)), /* NT4/Win2k */
"failed out=[%s]\n", wine_dbgstr_w(out));
@@ -421,11 +381,11 @@ static void test_message_from_string_wide(void)
{
ULONG_PTR args[] = { 6, 4, 2, 5, 3, 1 };
r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1oou1oou,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), (__ms_va_list *)args );
+ 0, 0, out, ARRAY_SIZE(out), (__ms_va_list *)args );
ok(!lstrcmpW(s_sp002sp003, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==13,"failed: r=%d\n",r);
r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1oou4oou,
- 0, 0, out, sizeof(out)/sizeof(WCHAR), (__ms_va_list *)args );
+ 0, 0, out, ARRAY_SIZE(out), (__ms_va_list *)args );
ok(!lstrcmpW(s_sp002sp001, out),"failed out=[%s]\n", wine_dbgstr_w(out));
ok(r==12,"failed: r=%d\n",r);
}
@@ -434,25 +394,25 @@ static void test_message_from_string_wide(void)
/* line feed */
r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_lf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_hi_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==3,"failed: r=%d\n", r);
/* carriage return line feed */
r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_crlf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_hi_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==3,"failed: r=%d\n", r);
/* carriage return */
r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_cr, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_sp, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==1,"failed: r=%d\n", r);
/* double carriage return line feed */
r = doitW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_crcrlf, 0,
- 0, out, sizeof(out)/sizeof(WCHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!lstrcmpW(s_2sp, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==2,"failed: r=%d\n", r);
}
@@ -465,8 +425,7 @@ static void test_message_from_string(void)
static const WCHAR szwTest[] = { 't','e','s','t',0};
/* the basics */
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0,
- 0, out, sizeof(out)/sizeof(CHAR),NULL);
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, ARRAY_SIZE(out),NULL);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
@@ -475,15 +434,13 @@ static void test_message_from_string(void)
{
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- FormatMessageA(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ FormatMessageA(FORMAT_MESSAGE_FROM_STRING, NULL, 0, 0, out, ARRAY_SIZE(out), NULL);
}
/* empty string */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
ok(GetLastError()==0xdeadbeef,
@@ -492,8 +449,7 @@ static void test_message_from_string(void)
/* format placeholder with no specifier */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
@@ -503,8 +459,7 @@ static void test_message_from_string(void)
/* test string with format placeholder with no specifier */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test%", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test%", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
@@ -514,8 +469,7 @@ static void test_message_from_string(void)
/* insertion with no variadic arguments */
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
ok(GetLastError()==ERROR_INVALID_PARAMETER, "last error %u\n", GetLastError());
@@ -523,194 +477,167 @@ static void test_message_from_string(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "%1", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ 0, out, ARRAY_SIZE(out), NULL);
ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
ok(GetLastError()==ERROR_INVALID_PARAMETER, "last error %u\n", GetLastError());
/* using the format feature */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), "test");
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0, 0, out, ARRAY_SIZE(out), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* no format */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
- 0, out, sizeof(out)/sizeof(CHAR), "test");
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0, 0, out, ARRAY_SIZE(out), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* two pieces */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%2", 0,
- 0, out, sizeof(out)/sizeof(CHAR), "te","st");
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%2", 0, 0, out, ARRAY_SIZE(out), "te","st");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* three pieces */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%3%2%1", 0,
- 0, out, sizeof(out)/sizeof(CHAR), "t","s","e");
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%3%2%1", 0, 0, out, ARRAY_SIZE(out), "t","s","e");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* s doesn't seem to work in format strings */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%!s!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), "test");
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%!s!", 0, 0, out, ARRAY_SIZE(out), "test");
ok(!strcmp("!s!", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%d\n",r);
/* ls is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ls!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), szwTest);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ls!", 0, 0, out, ARRAY_SIZE(out), szwTest);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* S is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!S!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), szwTest);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!S!", 0, 0, out, ARRAY_SIZE(out), szwTest);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* ws is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ws!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), szwTest);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!ws!", 0, 0, out, ARRAY_SIZE(out), szwTest);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* as characters */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!c!%2!c!%3!c!%1!c!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!c!%2!c!%3!c!%1!c!", 0, 0, out, ARRAY_SIZE(out),
+ 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* lc is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!lc!%2!lc!%3!lc!%1!lc!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!lc!%2!lc!%3!lc!%1!lc!", 0, 0, out, ARRAY_SIZE(out),
+ 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* wc is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!wc!%2!wc!%3!wc!%1!wc!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!wc!%2!wc!%3!wc!%1!wc!", 0, 0, out, ARRAY_SIZE(out),
+ 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* C is unicode */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!C!%2!C!%3!C!%1!C!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!C!%2!C!%3!C!%1!C!", 0, 0, out, ARRAY_SIZE(out),
+ 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* some numbers */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!d!%2!d!%3!d!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 1,2,3);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!d!%2!d!%3!d!", 0, 0, out, ARRAY_SIZE(out), 1,2,3);
ok(!strcmp("123", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%d\n",r);
/* a single digit with some spacing */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 1);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0, 0, out, ARRAY_SIZE(out), 1);
ok(!strcmp(" 1", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* a single digit, left justified */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4d!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 1);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4d!", 0, 0, out, ARRAY_SIZE(out), 1);
ok(!strcmp("1 ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* two digit decimal number */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 11);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0, 0, out, ARRAY_SIZE(out), 11);
ok(!strcmp(" 11", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* a hex number */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4x!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 11);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4x!", 0, 0, out, ARRAY_SIZE(out), 11);
ok(!strcmp(" b", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* a hex number, upper case */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 11);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0, 0, out, ARRAY_SIZE(out), 11);
ok(!strcmp(" B", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* a hex number, upper case, left justified */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4X!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 11);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4X!", 0, 0, out, ARRAY_SIZE(out), 11);
ok(!strcmp("B ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* a long hex number, upper case */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0, 0, out, ARRAY_SIZE(out), 0x1ab);
ok(!strcmp(" 1AB", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* two percent... */
- r = doit(FORMAT_MESSAGE_FROM_STRING, " %%%% ", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, " %%%% ", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp(" %% ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* periods are special cases */
- r = doit(FORMAT_MESSAGE_FROM_STRING, " %.%. %1!d!", 0,
- 0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, " %.%. %1!d!", 0, 0, out, ARRAY_SIZE(out), 0x1ab);
ok(!strcmp(" .. 427", out),"failed out=[%s]\n",out);
ok(r==7,"failed: r=%d\n",r);
/* %0 ends the line */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "test%0test", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "test%0test", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* %! prints an exclamation */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "yah%!%0 ", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "yah%!%0 ", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("yah!", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* %space */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "% % ", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "% % ", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* %n yields \r\n, %r yields \r, %t yields \t */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%n%r%t", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%n%r%t", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("\r\n\r\t", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* line feed */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\n", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* carriage return line feed */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\r\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\r\n", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* carriage return */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "\r", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "\r", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("\r\n", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%d\n",r);
/* double carriage return line feed */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "\r\r\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "\r\r\n", 0, 0, out, ARRAY_SIZE(out));
ok(!strcmp("\r\n\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%d\n",r);
/* null string as argument */
- r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
- 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!strcmp("(null)", out),"failed out=[%s]\n",out);
ok(r==6,"failed: r=%d\n",r);
@@ -765,25 +692,25 @@ static void test_message_from_string(void)
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!strcmp("hi ", out), "failed out=[%s]\n",out);
ok(r==3, "failed: r=%d\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!strcmp("hi ", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%d\n",r);
/* carriage return */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==1,"failed: r=%d\n",r);
/* double carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0,
- 0, out, sizeof(out)/sizeof(CHAR));
+ 0, out, ARRAY_SIZE(out));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%d\n",r);
}
@@ -796,18 +723,18 @@ static void test_message_ignore_inserts(void)
CHAR out[256];
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
/* The %0 escape sequence is handled. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%0", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%0test", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("test", out), "Expected output string \"test\", got %s\n", out);
@@ -815,71 +742,67 @@ static void test_message_ignore_inserts(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%0test", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %d\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the output buffer to be untouched\n");
ok(GetLastError() == 0xdeadbeef, "Expected GetLastError() to return 0xdeadbeef, got %u\n", GetLastError());
/* Insert sequences are ignored. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "test%1%2!*.*s!%99", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 17, "Expected FormatMessageA to return 17, got %d\n", ret);
ok(!strcmp("test%1%2!*.*s!%99", out), "Expected output string \"test%%1%%2!*.*s!%%99\", got %s\n", out);
/* Only the "%n", "%r", and "%t" escape sequences are processed. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%%% %.%!", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 8, "Expected FormatMessageA to return 8, got %d\n", ret);
ok(!strcmp("%%% %.%!", out), "Expected output string \"%%%%%% %%.%%!\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%n%r%t", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("\r\n\r\t", out), "Expected output string \"\\r\\n\\r\\t\", got %s\n", out);
/* CRLF characters are processed normally. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "hi\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("hi\r\n", out), "Expected output string \"hi\\r\\n\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "hi\r\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("hi\r\n", out), "Expected output string \"hi\\r\\n\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "\r", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 2, "Expected FormatMessageA to return 2, got %d\n", ret);
ok(!strcmp("\r\n", out), "Expected output string \"\\r\\n\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "\r\r\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %d\n", ret);
ok(!strcmp("\r\n\r\n", out), "Expected output string \"\\r\\n\\r\\n\", got %s\n", out);
/* The width parameter is handled the same also. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(!strcmp("hi ", out), "Expected output string \"hi \", got %s\n", out);
ok(ret == 3, "Expected FormatMessageA to return 3, got %d\n", ret);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 3, "Expected FormatMessageA to return 3, got %d\n", ret);
ok(!strcmp("hi ", out), "Expected output string \"hi \", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 1, "Expected FormatMessageA to return 1, got %d\n", ret);
ok(!strcmp(" ", out), "Expected output string \" \", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 2, "Expected FormatMessageA to return 2, got %d\n", ret);
ok(!strcmp(" ", out), "Expected output string \" \", got %s\n", out);
}
@@ -911,89 +834,88 @@ static void test_message_ignore_inserts_wide(void)
WCHAR out[256];
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, test, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
/* The %0 escape sequence is handled. */
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t0, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t0t, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(test, out), "Expected output string \"test\", got %s\n", wine_dbgstr_w(out));
/* While FormatMessageA returns 0 in this case, no last error code is set. */
SetLastError(0xdeadbeef);
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_0t, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageW to return 0, got %d\n", ret);
ok(!lstrcmpW(empty, out), "Expected the output buffer to be the empty string, got %s\n", wine_dbgstr_w(out));
ok(GetLastError() == 0xdeadbeef, "Expected GetLastError() to return 0xdeadbeef, got %u\n", GetLastError());
/* Insert sequences are ignored. */
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_t12oos99, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 17, "Expected FormatMessageW to return 17, got %d\n", ret);
ok(!lstrcmpW(fmt_t12oos99, out), "Expected output string \"test%%1%%2!*.*s!%%99\", got %s\n", wine_dbgstr_w(out));
/* Only the "%n", "%r", and "%t" escape sequences are processed. */
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_pctspacedot, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 8, "Expected FormatMessageW to return 8, got %d\n", ret);
ok(!lstrcmpW(fmt_pctspacedot, out), "Expected output string \"%%%%%% %%.%%!\", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_nrt, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(s_nrt, out), "Expected output string \"\\r\\n\\r\\t\", got %s\n", wine_dbgstr_w(out));
/* CRLF characters are processed normally. */
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_hi_lf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(s_hi_crlf, out), "Expected output string \"hi\\r\\n\", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_hi_crlf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(s_hi_crlf, out), "Expected output string \"hi\\r\\n\", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_cr, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 2, "Expected FormatMessageW to return 2, got %d\n", ret);
ok(!lstrcmpW(s_crlf, out), "Expected output string \"\\r\\n\", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, fmt_crcrlf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %d\n", ret);
ok(!lstrcmpW(s_crlfcrlf, out), "Expected output string \"\\r\\n\\r\\n\", got %s\n", wine_dbgstr_w(out));
/* The width parameter is handled the same also. */
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_lf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 3, "Expected FormatMessageW to return 3, got %d\n", ret);
ok(!lstrcmpW(s_hi_sp, out), "Expected output string \"hi \", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_hi_crlf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 3, "Expected FormatMessageW to return 3, got %d\n", ret);
ok(!lstrcmpW(s_hi_sp, out), "Expected output string \"hi \", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_cr, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_cr, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 1, "Expected FormatMessageW to return 1, got %d\n", ret);
ok(!lstrcmpW(s_sp, out), "Expected output string \" \", got %s\n", wine_dbgstr_w(out));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, fmt_crcrlf, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ ARRAY_SIZE(out), NULL);
ok(ret == 2, "Expected FormatMessageW to return 2, got %d\n", ret);
ok(!lstrcmpW(s_2sp, out), "Expected output string \" \", got %s\n", wine_dbgstr_w(out));
}
@@ -1216,7 +1138,7 @@ static void test_message_insufficient_buffer(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, sizeof(out)/sizeof(out[0]) - 1, NULL);
+ ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0, 0, out, ARRAY_SIZE(out) - 1, NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
@@ -1261,7 +1183,7 @@ static void test_message_insufficient_buffer_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, sizeof(out)/sizeof(out[0]) - 1, NULL);
+ ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, test, 0, 0, out, ARRAY_SIZE(out) - 1, NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected GetLastError() to return ERROR_INSUFFICIENT_BUFFER, got %u\n",
@@ -1487,7 +1409,7 @@ static void test_message_allocate_buffer_wide(void)
buf = (WCHAR *)0xdeadbeef;
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR) - 1, NULL);
+ test, 0, 0, (WCHAR *)&buf, ARRAY_SIZE(test) - 1, NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
"Expected output buffer pointer to be valid\n");
@@ -1500,7 +1422,7 @@ static void test_message_allocate_buffer_wide(void)
buf = (WCHAR *)0xdeadbeef;
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR), NULL);
+ test, 0, 0, (WCHAR *)&buf, ARRAY_SIZE(test), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
"Expected output buffer pointer to be valid\n");
@@ -1513,7 +1435,7 @@ static void test_message_allocate_buffer_wide(void)
buf = (WCHAR *)0xdeadbeef;
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- test, 0, 0, (WCHAR *)&buf, sizeof(test)/sizeof(WCHAR) + 1, NULL);
+ test, 0, 0, (WCHAR *)&buf, ARRAY_SIZE(test) + 1, NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(buf != NULL && buf != (WCHAR *)0xdeadbeef,
"Expected output buffer pointer to be valid\n");
@@ -1550,53 +1472,53 @@ static void test_message_from_hmodule(void)
/*Test existing messageID; as the message strings from wine's kernel32 differ from windows' kernel32 we don't compare
the strings but only test that FormatMessage doesn't return 0*/
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 7/*=ERROR_ARENA_TRASHED*/,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
/* Test HRESULT. It's not documented but in practice _com_error::ErrorMessage relies on this. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 0x80070005 /* E_ACCESSDENIED */,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, TRUST_E_NOSIGNATURE,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
/* Test a message string with an insertion without passing any variadic arguments. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "FormatMessageA returned non-zero\n");
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_ARGUMENT_ARRAY, h, 193 /* ERROR_BAD_EXE_FORMAT */,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "FormatMessageA returned non-zero\n");
/*Test nonexistent messageID with varying language IDs Note: FormatMessageW behaves the same*/
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_FOUND, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_LOADED, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
ok(error == ERROR_MR_MID_NOT_FOUND || error == ERROR_MUI_FILE_NOT_LOADED, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
ok(error == ERROR_RESOURCE_LANG_NOT_FOUND ||
@@ -1607,7 +1529,7 @@ static void test_message_from_hmodule(void)
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), out, sizeof(out)/sizeof(CHAR), NULL);
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), out, ARRAY_SIZE(out), NULL);
error = GetLastError();
ok(ret == 0, "FormatMessageA returned %u instead of 0\n", ret);
ok(error == ERROR_RESOURCE_LANG_NOT_FOUND ||
@@ -1627,7 +1549,7 @@ static void test_message_invalid_flags(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageA(0, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ret = FormatMessageA(0, "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1646,7 +1568,7 @@ static void test_message_invalid_flags(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ret = FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS, "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1656,7 +1578,7 @@ static void test_message_invalid_flags(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ret = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY, "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1666,7 +1588,7 @@ static void test_message_invalid_flags(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageA(FORMAT_MESSAGE_MAX_WIDTH_MASK, "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ret = FormatMessageA(FORMAT_MESSAGE_MAX_WIDTH_MASK, "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1680,22 +1602,21 @@ static void test_message_invalid_flags(void)
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_SYSTEM,
- "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(!strcmp("test", out),
"Expected the output buffer to be untouched\n");
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE,
- "test", 0, 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(!strcmp("test", out),
"Expected the output buffer to be untouched\n");
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE |
- FORMAT_MESSAGE_FROM_SYSTEM, "test", 0, 0, out,
- sizeof(out)/sizeof(CHAR), NULL);
+ FORMAT_MESSAGE_FROM_SYSTEM, "test", 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageA to return 4, got %u\n", ret);
ok(!strcmp("test", out),
"Expected the output buffer to be untouched\n");
@@ -1712,7 +1633,7 @@ static void test_message_invalid_flags_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageW(0, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ ret = FormatMessageW(0, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1731,7 +1652,7 @@ static void test_message_invalid_flags_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ ret = FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1741,7 +1662,7 @@ static void test_message_invalid_flags_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageW(FORMAT_MESSAGE_ARGUMENT_ARRAY, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ ret = FormatMessageW(FORMAT_MESSAGE_ARGUMENT_ARRAY, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1751,7 +1672,7 @@ static void test_message_invalid_flags_wide(void)
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- ret = FormatMessageW(FORMAT_MESSAGE_MAX_WIDTH_MASK, test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ ret = FormatMessageW(FORMAT_MESSAGE_MAX_WIDTH_MASK, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 0, "Expected FormatMessageW to return 0, got %u\n", ret);
ok(!memcmp(out, init_buf, sizeof(init_buf)),
"Expected the output buffer to be untouched\n");
@@ -1765,22 +1686,21 @@ static void test_message_invalid_flags_wide(void)
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_SYSTEM,
- test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
ok(!lstrcmpW(test, out),
"Expected the output buffer to be untouched\n");
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE,
- test, 0, 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
ok(!lstrcmpW(test, out),
"Expected the output buffer to be untouched\n");
memcpy(out, init_buf, sizeof(init_buf));
ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_FROM_HMODULE |
- FORMAT_MESSAGE_FROM_SYSTEM, test, 0, 0, out,
- sizeof(out)/sizeof(WCHAR), NULL);
+ FORMAT_MESSAGE_FROM_SYSTEM, test, 0, 0, out, ARRAY_SIZE(out), NULL);
ok(ret == 4, "Expected FormatMessageW to return 4, got %u\n", ret);
ok(!lstrcmpW(test, out),
"Expected the output buffer to be untouched\n");
@@ -1821,11 +1741,11 @@ static void test_message_from_64bit_number(void)
};
int i;
- for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(unsigned_tests); i++)
{
- r = doitW(FORMAT_MESSAGE_FROM_STRING, I64u,
- 0, 0, outW, sizeof(outW) / sizeof(WCHAR), unsigned_tests[i].number);
- MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, sizeof(expW) / sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, I64u, 0, 0, outW, ARRAY_SIZE(outW),
+ unsigned_tests[i].number);
+ MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, ARRAY_SIZE(expW));
todo_wine {
ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
unsigned_tests[i].expected, wine_dbgstr_w(outW));
@@ -1840,11 +1760,11 @@ todo_wine {
}
}
- for (i = 0; i < sizeof(signed_tests) / sizeof(signed_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(signed_tests); i++)
{
- r = doitW(FORMAT_MESSAGE_FROM_STRING, I64d,
- 0, 0, outW, sizeof(outW) / sizeof(WCHAR), signed_tests[i].number);
- MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, sizeof(expW) / sizeof(WCHAR));
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, I64d, 0, 0, outW, ARRAY_SIZE(outW),
+ signed_tests[i].number);
+ MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, ARRAY_SIZE(expW));
todo_wine {
ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
signed_tests[i].expected, wine_dbgstr_w(outW));
--
2.14.4
June 6, 2018
[PATCH 1/2] kernel32/tests: Correct the buffer size passed to FormatMessageW()
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
dlls/kernel32/tests/format_msg.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c
index 290bce9f71..43e4d35c8a 100644
--- a/dlls/kernel32/tests/format_msg.c
+++ b/dlls/kernel32/tests/format_msg.c
@@ -289,8 +289,7 @@ static void test_message_from_string_wide(void)
ok(r==4,"failed: r=%d\n", r);
/* a single digit, left justified */
- r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4d, 0,
- 0, out, sizeof(out)/sizeof(CHAR), 1);
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4d, 0, 0, out, ARRAY_SIZE(out), 1);
ok(!lstrcmpW(s_1_4d, out), "failed out=%s\n", wine_dbgstr_w(out));
ok(r==4,"failed: r=%d\n", r);
--
2.14.4
June 6, 2018
[PATCH] comctl32/tests: Use the available ARRAY_SIZE() macro
by Michael Stefaniuc
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
Same object is generated with or without this patch when adding
"-g0 -DNDEBUG -DWINETEST_NO_LINE_NUMBERS" to the CFLAGS.
dlls/comctl32/tests/combo.c | 4 ++--
dlls/comctl32/tests/edit.c | 6 +++---
dlls/comctl32/tests/header.c | 4 ++--
dlls/comctl32/tests/imagelist.c | 2 +-
dlls/comctl32/tests/ipaddress.c | 4 ++--
dlls/comctl32/tests/listbox.c | 2 +-
dlls/comctl32/tests/listview.c | 14 +++++++-------
dlls/comctl32/tests/monthcal.c | 7 +++----
dlls/comctl32/tests/mru.c | 4 ++--
dlls/comctl32/tests/progress.c | 2 +-
dlls/comctl32/tests/rebar.c | 4 ++--
dlls/comctl32/tests/status.c | 2 +-
dlls/comctl32/tests/taskdialog.c | 3 +--
dlls/comctl32/tests/toolbar.c | 16 ++++++++--------
dlls/comctl32/tests/tooltips.c | 4 ++--
dlls/comctl32/tests/treeview.c | 14 +++++++-------
dlls/comctl32/tests/updown.c | 12 ++++++------
17 files changed, 51 insertions(+), 53 deletions(-)
diff --git a/dlls/comctl32/tests/combo.c b/dlls/comctl32/tests/combo.c
index 83b36f212f..5fee206fd1 100644
--- a/dlls/comctl32/tests/combo.c
+++ b/dlls/comctl32/tests/combo.c
@@ -264,7 +264,7 @@ static void test_comboex_WM_LBUTTONDOWN(void)
WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, 0, 0, 200, 150,
hComboExParentWnd, NULL, hMainHinst, NULL);
- for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){
+ for (i = 0; i < ARRAY_SIZE(choices); i++){
COMBOBOXEXITEMW cbexItem;
wsprintfW(buffer, stringFormat, choices[i]);
@@ -1169,7 +1169,7 @@ static void test_combo_dropdown_size(DWORD style)
{15, 50, 3},
};
- for (test = 0; test < sizeof(info_height) / sizeof(info_height[0]); test++)
+ for (test = 0; test < ARRAY_SIZE(info_height); test++)
{
const struct list_size_info *info_test = &info_height[test];
int height_item; /* Height of a list item */
diff --git a/dlls/comctl32/tests/edit.c b/dlls/comctl32/tests/edit.c
index 7e9e7e7634..a5097d1cbb 100644
--- a/dlls/comctl32/tests/edit.c
+++ b/dlls/comctl32/tests/edit.c
@@ -2969,7 +2969,7 @@ static void test_EM_GETLINE(void)
hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
- for (i = 0; i < sizeof(hwnd)/sizeof(hwnd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(hwnd); i++)
{
static const WCHAR strW[] = {'t','e','x','t',0};
static const char *str = "text";
@@ -2994,13 +2994,13 @@ static void test_EM_GETLINE(void)
ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
diff --git a/dlls/comctl32/tests/header.c b/dlls/comctl32/tests/header.c
index 7ea80519a6..3428936cd7 100644
--- a/dlls/comctl32/tests/header.c
+++ b/dlls/comctl32/tests/header.c
@@ -1130,7 +1130,7 @@ static void test_hdm_index_messages(HWND hParent)
ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
"adder header control to parent", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
- for (i = 0; i < sizeof(item_texts)/sizeof(item_texts[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(item_texts); i++)
{
hdItem.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT;
hdItem.pszText = (char*)item_texts[i];
@@ -1170,7 +1170,7 @@ static void test_hdm_index_messages(HWND hParent)
hdItem.mask = HDI_TEXT | HDI_WIDTH;
hdItem.pszText = buffA;
- hdItem.cchTextMax = sizeof(buffA)/sizeof(buffA[0]);
+ hdItem.cchTextMax = ARRAY_SIZE(buffA);
retVal = SendMessageA(hChild, HDM_GETITEMA, 0, (LPARAM) &hdItem);
ok(retVal == TRUE, "Getting the 1st header item should return TRUE, got %d\n", retVal);
diff --git a/dlls/comctl32/tests/imagelist.c b/dlls/comctl32/tests/imagelist.c
index 1c307e4ed3..3bb7902a13 100644
--- a/dlls/comctl32/tests/imagelist.c
+++ b/dlls/comctl32/tests/imagelist.c
@@ -1096,7 +1096,7 @@ static void image_list_init(HIMAGELIST himl, INT grow)
check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
- for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(td); i++)
{
image_list_add_bitmap(himl, td[i].grey, i + 1);
check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp, td[i].comment);
diff --git a/dlls/comctl32/tests/ipaddress.c b/dlls/comctl32/tests/ipaddress.c
index 52581899a7..cc79b7bf11 100644
--- a/dlls/comctl32/tests/ipaddress.c
+++ b/dlls/comctl32/tests/ipaddress.c
@@ -50,12 +50,12 @@ static void test_get_set_text(void)
}
/* check text just after creation */
- r = GetWindowTextA(hwnd, ip, sizeof(ip)/sizeof(CHAR));
+ r = GetWindowTextA(hwnd, ip, ARRAY_SIZE(ip));
expect(7, r);
ok(strcmp(ip, "0.0.0.0") == 0, "Expected null IP address, got %s\n", ip);
SendMessageA(hwnd, IPM_SETADDRESS, 0, MAKEIPADDRESS(127, 0, 0, 1));
- r = GetWindowTextA(hwnd, ip, sizeof(ip)/sizeof(CHAR));
+ r = GetWindowTextA(hwnd, ip, ARRAY_SIZE(ip));
expect(9, r);
ok(strcmp(ip, "127.0.0.1") == 0, "Expected 127.0.0.1, got %s\n", ip);
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c
index 1513bea7f5..f44fdff77f 100644
--- a/dlls/comctl32/tests/listbox.c
+++ b/dlls/comctl32/tests/listbox.c
@@ -48,7 +48,7 @@ static int strcmp_aw(LPCWSTR strw, const char *stra)
WCHAR buf[1024];
if (!stra) return 1;
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
return lstrcmpW(strw, buf);
}
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index c2d33c41f5..e9b715ee41 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -2328,7 +2328,7 @@ static void test_multiselect(void)
r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
ok(r == 0, "got %d\n", r);
- for (i = 0; i < sizeof(task_list)/sizeof(task_list[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(task_list); i++) {
DWORD selected_count;
LVITEMA item;
@@ -3481,7 +3481,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 0;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, res);
ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
@@ -3495,7 +3495,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 1;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
@@ -3520,7 +3520,7 @@ static void test_norecompute(void)
item.mask = LVIF_TEXT | LVIF_NORECOMPUTE;
item.iItem = 0;
item.pszText = buff;
- item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, res);
@@ -4662,7 +4662,7 @@ static void test_canceleditlabel(void)
ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
memset(&itema, 0, sizeof(itema));
itema.pszText = buff;
- itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
+ itema.cchTextMax = ARRAY_SIZE(buff);
ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema);
expect(5, ret);
ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
@@ -5658,7 +5658,7 @@ static void test_dispinfo(void)
g_disp_A_to_W = TRUE;
item.pszText = (char*)buff;
- item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
+ item.cchTextMax = ARRAY_SIZE(buff);
ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
g_disp_A_to_W = FALSE;
@@ -6177,7 +6177,7 @@ static void test_state_image(void)
};
int i;
- for (i = 0; i < sizeof(styles)/sizeof(styles[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
{
static char text[] = "Item";
static char subtext[] = "Subitem";
diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c
index 85822a320c..7c78540333 100644
--- a/dlls/comctl32/tests/monthcal.c
+++ b/dlls/comctl32/tests/monthcal.c
@@ -1216,7 +1216,7 @@ if (0)
} else {
title_index++;
- if (sizeof(title_hits) / sizeof(title_hits[0]) <= title_index)
+ if (ARRAY_SIZE(title_hits) <= title_index)
break;
todo_wine_if(title_hits[title_index].todo)
@@ -1241,8 +1241,7 @@ if (0)
todo_wine ok(month_count + year_count >= 1, "Not enough month and year items\n");
- ok(r.right <= x && title_index + 1 == sizeof(title_hits) / sizeof(title_hits[0]),
- "Wrong title layout\n");
+ ok(r.right <= x && title_index + 1 == ARRAY_SIZE(title_hits), "Wrong title layout\n");
DestroyWindow(hwnd);
}
@@ -2016,7 +2015,7 @@ static void test_sel_notify(void)
};
int i;
- for(i = 0; i < sizeof styles / sizeof styles[0]; i++)
+ for(i = 0; i < ARRAY_SIZE(styles); i++)
{
hwnd = create_monthcal_control(styles[i].val);
SetWindowLongPtrA(hwnd, GWLP_ID, SEL_NOTIFY_TEST_ID);
diff --git a/dlls/comctl32/tests/mru.c b/dlls/comctl32/tests/mru.c
index dfad6f859d..b3d3e7a265 100644
--- a/dlls/comctl32/tests/mru.c
+++ b/dlls/comctl32/tests/mru.c
@@ -118,7 +118,7 @@ static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
dwMaxSubkeyLen++;
dwMaxValueLen++;
dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
- if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
+ if (dwMaxLen > ARRAY_SIZE(szNameBuf))
{
/* Name too big: alloc a buffer for it */
if (!(lpszName = heap_alloc(dwMaxLen * sizeof(CHAR))))
@@ -480,7 +480,7 @@ static void test_CreateMRUListLazyA(void)
return;
}
- for (i = 0; i < sizeof(create_lazyA)/sizeof(create_lazya_t); i++)
+ for (i = 0; i < ARRAY_SIZE(create_lazyA); i++)
{
const create_lazya_t *ptr = &create_lazyA[i];
HANDLE hMRU;
diff --git a/dlls/comctl32/tests/progress.c b/dlls/comctl32/tests/progress.c
index b911021be0..497cb47d3c 100644
--- a/dlls/comctl32/tests/progress.c
+++ b/dlls/comctl32/tests/progress.c
@@ -258,7 +258,7 @@ static void test_PBM_STEPIT(void)
HWND progress;
int i, j;
- for (i = 0; i < sizeof(stepit_tests)/sizeof(stepit_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
{
struct stepit_test *test = &stepit_tests[i];
LRESULT ret;
diff --git a/dlls/comctl32/tests/rebar.c b/dlls/comctl32/tests/rebar.c
index 7dae3a7dbe..3b1be77497 100644
--- a/dlls/comctl32/tests/rebar.c
+++ b/dlls/comctl32/tests/rebar.c
@@ -826,7 +826,7 @@ static DWORD resize_numtests = 0;
RECT r; \
int value; \
const rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
- assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
+ assert(resize_numtests <= ARRAY_SIZE(resize_results)); \
GetWindowRect(hRebar, &r); \
MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
@@ -853,7 +853,7 @@ static void test_resize(void)
CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
CCS_NOMOVEY | WS_BORDER};
- const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
+ const int styles_count = ARRAY_SIZE(dwStyles);
int i;
for (i = 0; i < styles_count; i++)
diff --git a/dlls/comctl32/tests/status.c b/dlls/comctl32/tests/status.c
index 2308974761..d78bd20262 100644
--- a/dlls/comctl32/tests/status.c
+++ b/dlls/comctl32/tests/status.c
@@ -127,7 +127,7 @@ static int CALLBACK check_height_font_enumproc(ENUMLOGFONTEXA *enumlf, NEWTEXTME
if (type != TRUETYPE_FONTTYPE)
facename = enumlf->elfLogFont.lfFaceName;
- for (i = 0; i < sizeof(sizes)/sizeof(sizes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(sizes); i++)
{
HFONT hFont;
TEXTMETRICA tm;
diff --git a/dlls/comctl32/tests/taskdialog.c b/dlls/comctl32/tests/taskdialog.c
index 432b89bd15..cca700cd18 100644
--- a/dlls/comctl32/tests/taskdialog.c
+++ b/dlls/comctl32/tests/taskdialog.c
@@ -152,8 +152,7 @@ static void init_test_message(UINT message, WPARAM wParam, LPARAM lParam, struct
}
#define run_test(info, expect_button, seq, context) \
- run_test_(info, expect_button, seq, context, \
- sizeof(seq)/sizeof(seq[0]) - 1, __FILE__, __LINE__)
+ run_test_(info, expect_button, seq, context, ARRAY_SIZE(seq) - 1, __FILE__, __LINE__)
static void run_test_(TASKDIALOGCONFIG *info, int expect_button, const struct message_info *test_messages,
const char *context, int test_messages_len, const char *file, int line)
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c
index 5fd6133e1f..41807258f4 100644
--- a/dlls/comctl32/tests/toolbar.c
+++ b/dlls/comctl32/tests/toolbar.c
@@ -387,7 +387,7 @@ static void basic_test(void)
WS_CHILD | TBSTYLE_LIST,
100,
0, NULL, 0,
- buttons, sizeof(buttons)/sizeof(buttons[0]),
+ buttons, ARRAY_SIZE(buttons),
0, 0, 20, 16, sizeof(TBBUTTON));
ok(hToolbar != NULL, "Toolbar creation\n");
SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"test\000");
@@ -1315,7 +1315,7 @@ static DWORD tbsize_alt_numtests = 0;
compare(buttonCount, res->nButtons, "%d"); \
for (i=0; i<min(buttonCount, res->nButtons); i++) { \
ok(SendMessageA(hToolbar, TB_GETITEMRECT, i, (LPARAM)&rc) == 1, "TB_GETITEMRECT\n"); \
- if (broken(tbsize_alt_numtests < sizeof(tbsize_alt_results)/sizeof(tbsize_alt_results[0]) && \
+ if (broken(tbsize_alt_numtests < ARRAY_SIZE(tbsize_alt_results) && \
EqualRect(&rc, &tbsize_alt_results[tbsize_alt_numtests].rcButton))) { \
win_skip("Alternate rect found\n"); \
tbsize_alt_numtests++; \
@@ -1939,13 +1939,13 @@ static void test_setrows(void)
| CCS_NOMOVEY | CCS_TOP,
0,
0, NULL, 0,
- buttons, sizeof(buttons)/sizeof(buttons[0]),
+ buttons, ARRAY_SIZE(buttons),
20, 20, 0, 0, sizeof(TBBUTTON));
ok(hToolbar != NULL, "Toolbar creation\n");
ok(SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
/* test setting rows to each of 1-10 with bLarger true and false */
- for (i=0; i<(sizeof(tbrows_results) / sizeof(tbrows_result_t)); i++) {
+ for (i=0; i<ARRAY_SIZE(tbrows_results); i++) {
RECT rc;
int rows;
@@ -2058,7 +2058,7 @@ static void test_get_set_style(void)
WS_CHILD | TBSTYLE_LIST,
100,
0, NULL, 0,
- buttons, sizeof(buttons)/sizeof(buttons[0]),
+ buttons, ARRAY_SIZE(buttons),
0, 0, 20, 16, sizeof(TBBUTTON));
ok(hToolbar != NULL, "Toolbar creation\n");
SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"test\000");
@@ -2276,7 +2276,7 @@ static void test_TB_GET_SET_EXTENDEDSTYLE(void)
return;
}
- for (i = 0; i < sizeof(extended_style_test)/sizeof(extended_style_t); i++)
+ for (i = 0; i < ARRAY_SIZE(extended_style_test); i++)
{
ptr = &extended_style_test[i];
@@ -2397,7 +2397,7 @@ static void test_save(void)
params.pszValueName = value;
rebuild_toolbar_with_buttons( &wnd );
- SendMessageW( wnd, TB_ADDBUTTONSW, sizeof(more_btns) / sizeof(more_btns[0]), (LPARAM)more_btns );
+ SendMessageW(wnd, TB_ADDBUTTONSW, ARRAY_SIZE(more_btns), (LPARAM)more_btns);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
res = SendMessageW( wnd, TB_SAVERESTOREW, TRUE, (LPARAM)¶ms );
@@ -2423,7 +2423,7 @@ static void test_save(void)
ok( res, "restoring failed\n" );
ok_sequence(sequences, PARENT_SEQ_INDEX, restore_parent_seq, "restore", FALSE);
count = SendMessageW( wnd, TB_BUTTONCOUNT, 0, 0 );
- ok( count == sizeof(expect_btns) / sizeof(expect_btns[0]), "got %d\n", count );
+ ok( count == ARRAY_SIZE(expect_btns), "got %d\n", count );
for (i = 0; i < count; i++)
{
diff --git a/dlls/comctl32/tests/tooltips.c b/dlls/comctl32/tests/tooltips.c
index af95a569bb..0cb7afd688 100644
--- a/dlls/comctl32/tests/tooltips.c
+++ b/dlls/comctl32/tests/tooltips.c
@@ -183,7 +183,7 @@ static void test_customdraw(void) {
GetCursorPos(&orig_pos);
for (iterationNumber = 0;
- iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]);
+ iterationNumber < ARRAY_SIZE(expectedResults);
iterationNumber++) {
HWND parent, hwndTip;
@@ -821,7 +821,7 @@ static void test_longtextW(void)
toolinfoW.hinst = GetModuleHandleW(NULL);
toolinfoW.uFlags = 0;
toolinfoW.uId = 0x1234ABCD;
- MultiByteToWideChar(CP_ACP, 0, longtextA, -1, bufW, sizeof(bufW)/sizeof(bufW[0]));
+ MultiByteToWideChar(CP_ACP, 0, longtextA, -1, bufW, ARRAY_SIZE(bufW));
lenW = lstrlenW(bufW);
toolinfoW.lpszText = bufW;
toolinfoW.lParam = 0xdeadbeef;
diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c
index 5cf397f3af..33edaaf4b4 100644
--- a/dlls/comctl32/tests/treeview.c
+++ b/dlls/comctl32/tests/treeview.c
@@ -527,7 +527,7 @@ static void test_callback(void)
tvi.hItem = hRoot;
tvi.mask = TVIF_TEXT;
tvi.pszText = buf;
- tvi.cchTextMax = sizeof(buf)/sizeof(buf[0]);
+ tvi.cchTextMax = ARRAY_SIZE(buf);
ret = TreeView_GetItemA(hTree, &tvi);
expect(TRUE, ret);
ok(strcmp(tvi.pszText, TEST_CALLBACK_TEXT) == 0, "Callback item text mismatch %s vs %s\n",
@@ -706,7 +706,7 @@ static void test_getitemtext(void)
HWND hTree;
CHAR szBuffer[80] = "Blah";
- int nBufferSize = sizeof(szBuffer)/sizeof(CHAR);
+ int nBufferSize = ARRAY_SIZE(szBuffer);
hTree = create_treeview_control(0);
fill_tree(hTree);
@@ -1630,7 +1630,7 @@ static void test_itemedit(void)
item.mask = TVIF_TEXT;
item.hItem = hRoot;
item.pszText = buffA;
- item.cchTextMax = sizeof(buffA)/sizeof(CHAR);
+ item.cchTextMax = ARRAY_SIZE(buffA);
r = SendMessageA(hTree, TVM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, r);
ok(!strcmp("x", buffA), "Expected item text to change\n");
@@ -1664,7 +1664,7 @@ static void test_itemedit(void)
ok(IsWindow(edit), "Expected valid handle\n");
g_beginedit_alter_text = FALSE;
- GetWindowTextA(edit, buffA, sizeof(buffA)/sizeof(CHAR));
+ GetWindowTextA(edit, buffA, ARRAY_SIZE(buffA));
ok(!strcmp(buffA, "<edittextaltered>"), "got string %s\n", buffA);
DestroyWindow(hTree);
@@ -1991,7 +1991,7 @@ static void test_TVS_SINGLEEXPAND(void)
SetWindowLongA(hTree, GWL_STYLE, GetWindowLongA(hTree, GWL_STYLE) | TVS_SINGLEEXPAND);
/* to avoid painting related notifications */
ShowWindow(hTree, SW_HIDE);
- for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(items); i++)
{
ins.hParent = items[i].parent ? *items[i].parent : TVI_ROOT;
ins.hInsertAfter = TVI_FIRST;
@@ -2000,7 +2000,7 @@ static void test_TVS_SINGLEEXPAND(void)
*items[i].handle = TreeView_InsertItemA(hTree, &ins);
}
- for (i = 0; i < sizeof(sequence_tests)/sizeof(sequence_tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(sequence_tests); i++)
{
flush_sequences(sequences, NUM_MSG_SEQUENCES);
ret = SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)(*sequence_tests[i].select));
@@ -2009,7 +2009,7 @@ static void test_TVS_SINGLEEXPAND(void)
ok_sequence(sequences, PARENT_SEQ_INDEX, sequence_tests[i].sequence, context, FALSE);
}
- for (i = 0; i < sizeof(items)/sizeof(items[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(items); i++)
{
ret = SendMessageA(hTree, TVM_GETITEMSTATE, (WPARAM)(*items[i].handle), 0xFFFF);
ok(ret == items[i].final_state, "singleexpand items[%d]: expected state 0x%x got 0x%x\n",
diff --git a/dlls/comctl32/tests/updown.c b/dlls/comctl32/tests/updown.c
index f549c41583..1f4e38f0eb 100644
--- a/dlls/comctl32/tests/updown.c
+++ b/dlls/comctl32/tests/updown.c
@@ -697,13 +697,13 @@ static void test_updown_base(void)
r = SendMessageA(updown, UDM_SETPOS, 0, 10);
expect(50, r);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
ok(lstrcmpA(text, "10") == 0, "Expected '10', got '%s'\n", text);
r = SendMessageA(updown, UDM_SETBASE, 16, 0);
expect(10, r);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
/* FIXME: currently hex output isn't properly formatted, but for this
test only change from initial text matters */
ok(lstrcmpA(text, "10") != 0, "Expected '0x000A', got '%s'\n", text);
@@ -837,20 +837,20 @@ static void test_UDS_SETBUDDYINT(void)
style = GetWindowLongA(updown, GWL_STYLE);
ok(style & UDS_SETBUDDYINT, "Expected UDS_SETBUDDY to be set\n");
SendMessageA(updown, UDM_SETPOS, 0, 20);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
ok(lstrlenA(text) == 0, "Expected empty string\n");
DestroyWindow(updown);
/* creating with UDS_SETBUDDYINT */
updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
/* 50 is initial value here */
ok(lstrcmpA(text, "50") == 0, "Expected '50', got '%s'\n", text);
/* now remove style flag */
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style & ~UDS_SETBUDDYINT);
SendMessageA(updown, UDM_SETPOS, 0, 20);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
ok(lstrcmpA(text, "20") == 0, "Expected '20', got '%s'\n", text);
/* set edit text directly, check position */
strcpy(text, "10");
@@ -872,7 +872,7 @@ static void test_UDS_SETBUDDYINT(void)
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
SendMessageA(updown, UDM_SETPOS, 0, 30);
- GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
+ GetWindowTextA(g_edit, text, ARRAY_SIZE(text));
ok(lstrcmpA(text, "30") == 0, "Expected '30', got '%s'\n", text);
DestroyWindow(updown);
}
--
2.14.4
June 6, 2018
[PATCH] include: Add an option to disable line numbers in the tests
by Michael Stefaniuc
Two use cases for this:
- No-op changes that change the line count will generate now the exact
same object file.
- While writing new tests that change the line count this allows for an
easier diff between the two test runs.
Signed-off-by: Michael Stefaniuc <mstefani(a)winehq.org>
---
include/wine/test.h | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/wine/test.h b/include/wine/test.h
index 476b4d9847..e73f40d575 100644
--- a/include/wine/test.h
+++ b/include/wine/test.h
@@ -113,10 +113,17 @@ extern void __winetest_cdecl winetest_skip( const char *msg, ... ) WINETEST_PRIN
extern void __winetest_cdecl winetest_win_skip( const char *msg, ... ) WINETEST_PRINTF_ATTR(1,2);
extern void __winetest_cdecl winetest_trace( const char *msg, ... ) WINETEST_PRINTF_ATTR(1,2);
-#define ok_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ok
-#define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip
-#define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip
-#define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace
+#ifdef WINETEST_NO_LINE_NUMBERS
+# define ok_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_ok
+# define skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_skip
+# define win_skip_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_win_skip
+# define trace_(file, line) (winetest_set_location(file, 0), 0) ? (void)0 : winetest_trace
+#else
+# define ok_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_ok
+# define skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_skip
+# define win_skip_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_win_skip
+# define trace_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : winetest_trace
+#endif
#define ok ok_(__FILE__, __LINE__)
#define skip skip_(__FILE__, __LINE__)
--
2.14.4
June 6, 2018
[PATCH v3 5/5] kernel32: Implement Wow64SetThreadContext().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/thread.c | 17 +++++++++++++++++
include/winbase.h | 1 +
include/winternl.h | 1 +
4 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 1cb0b54..de6f007 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1603,7 +1603,7 @@
@ stdcall Wow64GetThreadContext(long ptr)
# @ stub Wow64GetThreadSelectorEntry
@ stdcall Wow64RevertWow64FsRedirection(ptr)
-# @ stub Wow64SetThreadContext
+@ stdcall Wow64SetThreadContext(long ptr)
# @ stub Wow64SuspendThread
@ stdcall WriteConsoleA(long ptr long ptr ptr)
@ stdcall WriteConsoleInputA(long ptr long ptr)
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
index 3aa2887..eb304dc 100644
--- a/dlls/kernel32/thread.c
+++ b/dlls/kernel32/thread.c
@@ -236,6 +236,23 @@ BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread
/***********************************************************************
+ * Wow64SetThreadContext [KERNEL32.@]
+ */
+BOOL WINAPI Wow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context)
+{
+#ifdef __i386__
+ NTSTATUS status = NtSetContextThread( handle, (const CONTEXT *)context );
+#elif defined(_WIN64)
+ NTSTATUS status = RtlWow64SetThreadContext( handle, context );
+#else
+ NTSTATUS status = STATUS_NOT_IMPLEMENTED;
+ FIXME("not implemented on this platform\n");
+#endif
+ if (status) SetLastError( RtlNtStatusToDosError(status) );
+ return !status;
+}
+
+/***********************************************************************
* GetThreadContext [KERNEL32.@] Retrieves context of thread.
*
* RETURNS
diff --git a/include/winbase.h b/include/winbase.h
index f7239b8..667df96 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2708,6 +2708,7 @@ WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*);
WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN);
WINBASEAPI BOOL WINAPI Wow64GetThreadContext(HANDLE, WOW64_CONTEXT *);
WINBASEAPI BOOL WINAPI Wow64RevertWow64FsRedirection(PVOID);
+WINBASEAPI BOOL WINAPI Wow64SetThreadContext(HANDLE, const WOW64_CONTEXT *);
WINADVAPI DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC,PVOID,PVOID);
WINBASEAPI BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED);
WINBASEAPI BOOL WINAPI WriteFileEx(HANDLE,LPCVOID,DWORD,LPOVERLAPPED,LPOVERLAPPED_COMPLETION_ROUTINE);
diff --git a/include/winternl.h b/include/winternl.h
index 9361825..9341c40 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2838,6 +2838,7 @@ NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN);
NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*);
#ifdef _WIN64
NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE, WOW64_CONTEXT *);
+NTSYSAPI NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE, const WOW64_CONTEXT *);
#endif
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG);
NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE);
--
2.7.4
June 6, 2018
[PATCH v3 4/5] kernel32: Implement Wow64GetThreadContext().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/thread.c | 18 ++++++++++++++++++
include/winbase.h | 1 +
include/winternl.h | 3 +++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 9ed5dfb..1cb0b54 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1600,7 +1600,7 @@
@ stdcall WinExec(str long)
@ stdcall Wow64EnableWow64FsRedirection(long)
@ stdcall Wow64DisableWow64FsRedirection(ptr)
-# @ stub Wow64GetThreadContext
+@ stdcall Wow64GetThreadContext(long ptr)
# @ stub Wow64GetThreadSelectorEntry
@ stdcall Wow64RevertWow64FsRedirection(ptr)
# @ stub Wow64SetThreadContext
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
index b6ca9f260..3aa2887 100644
--- a/dlls/kernel32/thread.c
+++ b/dlls/kernel32/thread.c
@@ -251,6 +251,24 @@ BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with
}
+/***********************************************************************
+ * Wow64GetThreadContext [KERNEL32.@]
+ */
+BOOL WINAPI Wow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context)
+{
+#ifdef __i386__
+ NTSTATUS status = NtGetContextThread( handle, (CONTEXT *)context );
+#elif defined(_WIN64)
+ NTSTATUS status = RtlWow64GetThreadContext( handle, context );
+#else
+ NTSTATUS status = STATUS_NOT_IMPLEMENTED;
+ FIXME("not implemented on this platform\n");
+#endif
+ if (status) SetLastError( RtlNtStatusToDosError(status) );
+ return !status;
+}
+
+
/**********************************************************************
* SuspendThread [KERNEL32.@] Suspends a thread.
*
diff --git a/include/winbase.h b/include/winbase.h
index 4ddc1d3..f7239b8 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2706,6 +2706,7 @@ WINBASEAPI VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE);
WINBASEAPI UINT WINAPI WinExec(LPCSTR,UINT);
WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*);
WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN);
+WINBASEAPI BOOL WINAPI Wow64GetThreadContext(HANDLE, WOW64_CONTEXT *);
WINBASEAPI BOOL WINAPI Wow64RevertWow64FsRedirection(PVOID);
WINADVAPI DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC,PVOID,PVOID);
WINBASEAPI BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED);
diff --git a/include/winternl.h b/include/winternl.h
index 3ecd068..9361825 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2836,6 +2836,9 @@ NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *);
NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID);
NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN);
NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*);
+#ifdef _WIN64
+NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE, WOW64_CONTEXT *);
+#endif
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG);
NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE);
NTSYSAPI NTSTATUS WINAPI RtlpNtCreateKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG);
--
2.7.4
June 6, 2018
[PATCH v3 3/5] ntdll: Implement RtlWow64SetThreadContext().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/tests/exception.c | 6 +++
dlls/ntdll/thread.c | 96 +++++++++++++++++++++++++++++++++++++++-----
3 files changed, 93 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index f1dd6ed..77cc1ae 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -978,6 +978,7 @@
@ stdcall RtlWow64EnableFsRedirection(long)
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
@ stdcall -arch=win64 RtlWow64GetThreadContext(long ptr)
+@ stdcall -arch=win64 RtlWow64SetThreadContext(long ptr)
@ stub RtlWriteMemoryStream
@ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
@ stub RtlZeroHeap
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 9310297..e30cd59 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -150,6 +150,7 @@ static EXCEPTION_DISPOSITION (WINAPI *p__C_specific_handler)(EXCEPTION_RECORD*,
static VOID (WINAPI *pRtlCaptureContext)(CONTEXT*);
static VOID (CDECL *pRtlRestoreContext)(CONTEXT*, EXCEPTION_RECORD*);
static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE, WOW64_CONTEXT *);
+static NTSTATUS (WINAPI *pRtlWow64SetThreadContext)(HANDLE, const WOW64_CONTEXT *);
static VOID (CDECL *pRtlUnwindEx)(VOID*, VOID*, EXCEPTION_RECORD*, VOID*, CONTEXT*, UNWIND_HISTORY_TABLE*);
static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
#endif
@@ -2520,6 +2521,9 @@ static void test_wow64_context(void)
ok(*(WORD *)ctx.ExtendedRegisters == 0x27f, "got SSE control word %04x\n",
*(WORD *)ctx.ExtendedRegisters);
+ ret = pRtlWow64SetThreadContext( pi.hThread, &ctx );
+ ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+
pNtTerminateProcess(pi.hProcess, 0);
}
@@ -3163,6 +3167,8 @@ START_TEST(exception)
"RtlUnwindEx" );
pRtlWow64GetThreadContext = (void *)GetProcAddress( hntdll,
"RtlWow64GetThreadContext" );
+ pRtlWow64SetThreadContext = (void *)GetProcAddress( hntdll,
+ "RtlWow64SetThreadContext" );
p_setjmp = (void *)GetProcAddress( hmsvcrt,
"_setjmp" );
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index df04b33..52c7953 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -851,23 +851,16 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void)
return NtCurrentTeb()->ActiveFrame;
}
-
-/***********************************************************************
- * set_thread_context
- */
-NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
+static NTSTATUS set_server_context( HANDLE handle, const context_t *context, BOOL *self )
{
NTSTATUS ret;
DWORD dummy, i;
- context_t server_context;
-
- context_to_server( &server_context, context );
SERVER_START_REQ( set_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 1;
- wine_server_add_data( req, &server_context, sizeof(server_context) );
+ wine_server_add_data( req, context, sizeof(*context) );
ret = wine_server_call( req );
*self = reply->self;
}
@@ -881,7 +874,7 @@ NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 0;
- wine_server_add_data( req, &server_context, sizeof(server_context) );
+ wine_server_add_data( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
@@ -900,6 +893,12 @@ NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
return ret;
}
+NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
+{
+ context_t server_context;
+ context_to_server( &server_context, context );
+ return set_server_context( handle, &server_context, self );
+}
/* convert CPU-specific flags to generic server flags */
static inline unsigned int get_server_context_flags( DWORD flags )
@@ -978,6 +977,83 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self)
}
#ifdef _WIN64
+static NTSTATUS wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from )
+{
+ DWORD flags = from->ContextFlags & ~WOW64_CONTEXT_i386; /* get rid of CPU id */
+
+ memset( to, 0, sizeof(*to) );
+ to->cpu = CPU_x86;
+
+ if (flags & WOW64_CONTEXT_CONTROL)
+ {
+ to->flags |= SERVER_CTX_CONTROL;
+ to->ctl.i386_regs.ebp = from->Ebp;
+ to->ctl.i386_regs.esp = from->Esp;
+ to->ctl.i386_regs.eip = from->Eip;
+ to->ctl.i386_regs.cs = from->SegCs;
+ to->ctl.i386_regs.ss = from->SegSs;
+ to->ctl.i386_regs.eflags = from->EFlags;
+ }
+ if (flags & WOW64_CONTEXT_INTEGER)
+ {
+ to->flags |= SERVER_CTX_INTEGER;
+ to->integer.i386_regs.eax = from->Eax;
+ to->integer.i386_regs.ebx = from->Ebx;
+ to->integer.i386_regs.ecx = from->Ecx;
+ to->integer.i386_regs.edx = from->Edx;
+ to->integer.i386_regs.esi = from->Esi;
+ to->integer.i386_regs.edi = from->Edi;
+ }
+ if (flags & WOW64_CONTEXT_SEGMENTS)
+ {
+ to->flags |= SERVER_CTX_SEGMENTS;
+ to->seg.i386_regs.ds = from->SegDs;
+ to->seg.i386_regs.es = from->SegEs;
+ to->seg.i386_regs.fs = from->SegFs;
+ to->seg.i386_regs.gs = from->SegGs;
+ }
+ if (flags & WOW64_CONTEXT_FLOATING_POINT)
+ {
+ to->flags |= SERVER_CTX_FLOATING_POINT;
+ to->fp.i386_regs.ctrl = from->FloatSave.ControlWord;
+ to->fp.i386_regs.status = from->FloatSave.StatusWord;
+ to->fp.i386_regs.tag = from->FloatSave.TagWord;
+ to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset;
+ to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector;
+ to->fp.i386_regs.data_off = from->FloatSave.DataOffset;
+ to->fp.i386_regs.data_sel = from->FloatSave.DataSelector;
+ to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState;
+ memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) );
+ }
+ if (flags & WOW64_CONTEXT_DEBUG_REGISTERS)
+ {
+ to->flags |= SERVER_CTX_DEBUG_REGISTERS;
+ to->debug.i386_regs.dr0 = from->Dr0;
+ to->debug.i386_regs.dr1 = from->Dr1;
+ to->debug.i386_regs.dr2 = from->Dr2;
+ to->debug.i386_regs.dr3 = from->Dr3;
+ to->debug.i386_regs.dr6 = from->Dr6;
+ to->debug.i386_regs.dr7 = from->Dr7;
+ }
+ if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS)
+ {
+ to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
+ memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
+ }
+ return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * RtlWow64SetThreadContext (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context )
+{
+ BOOL self;
+ context_t server_context;
+ wow64_context_to_server( &server_context, context );
+ return set_server_context( handle, &server_context, &self );
+}
+
/* convert CPU-specific flags to generic server flags */
static inline unsigned int wow64_get_server_context_flags( DWORD flags )
{
--
2.7.4
June 6, 2018
[PATCH v3 2/5] ntdll: Implement RtlWow64GetThreadContext().
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v3: fix test failures on Vista
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/tests/exception.c | 36 ++++++++++++++
dlls/ntdll/thread.c | 114 ++++++++++++++++++++++++++++++++++++++++---
3 files changed, 143 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index c0f5d6f..f1dd6ed 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -977,6 +977,7 @@
@ stdcall RtlWalkHeap(long ptr)
@ stdcall RtlWow64EnableFsRedirection(long)
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
+@ stdcall -arch=win64 RtlWow64GetThreadContext(long ptr)
@ stub RtlWriteMemoryStream
@ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
@ stub RtlZeroHeap
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index c47c8cb..9310297 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -149,6 +149,7 @@ static PRUNTIME_FUNCTION (WINAPI *pRtlLookupFunctionEntry)(ULONG64, ULONG64*, UN
static EXCEPTION_DISPOSITION (WINAPI *p__C_specific_handler)(EXCEPTION_RECORD*, ULONG64, CONTEXT*, DISPATCHER_CONTEXT*);
static VOID (WINAPI *pRtlCaptureContext)(CONTEXT*);
static VOID (CDECL *pRtlRestoreContext)(CONTEXT*, EXCEPTION_RECORD*);
+static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE, WOW64_CONTEXT *);
static VOID (CDECL *pRtlUnwindEx)(VOID*, VOID*, EXCEPTION_RECORD*, VOID*, CONTEXT*, UNWIND_HISTORY_TABLE*);
static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
#endif
@@ -2490,6 +2491,38 @@ static void test_dpe_exceptions(void)
pRtlRemoveVectoredExceptionHandler(handler);
}
+static void test_wow64_context(void)
+{
+ char cmdline[] = "C:\\windows\\syswow64\\notepad.exe";
+ PROCESS_INFORMATION pi;
+ STARTUPINFOA si = {0};
+ WOW64_CONTEXT ctx;
+ NTSTATUS ret;
+
+ memset(&ctx, 0x55, sizeof(ctx));
+ ctx.ContextFlags = WOW64_CONTEXT_ALL;
+ ret = pRtlWow64GetThreadContext( GetCurrentThread(), &ctx );
+ ok(ret == STATUS_INVALID_PARAMETER || broken(ret == STATUS_PARTIAL_COPY), "got %#x\n", ret);
+
+ CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
+
+ ret = pRtlWow64GetThreadContext( pi.hThread, &ctx );
+ ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+ ok(ctx.ContextFlags == WOW64_CONTEXT_ALL, "got context flags %#x\n", ctx.ContextFlags);
+ ok(!ctx.Ebp, "got ebp %08x\n", ctx.Ebp);
+ ok(!ctx.Ecx, "got ecx %08x\n", ctx.Ecx);
+ ok(!ctx.Edx, "got edx %08x\n", ctx.Edx);
+ ok(!ctx.Esi, "got esi %08x\n", ctx.Esi);
+ ok(!ctx.Edi, "got edi %08x\n", ctx.Edi);
+ ok((ctx.EFlags & ~2) == 0x200, "got eflags %08x\n", ctx.EFlags);
+ ok((WORD) ctx.FloatSave.ControlWord == 0x27f, "got control word %08x\n",
+ ctx.FloatSave.ControlWord);
+ ok(*(WORD *)ctx.ExtendedRegisters == 0x27f, "got SSE control word %04x\n",
+ *(WORD *)ctx.ExtendedRegisters);
+
+ pNtTerminateProcess(pi.hProcess, 0);
+}
+
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
@@ -3128,6 +3161,8 @@ START_TEST(exception)
"RtlRestoreContext" );
pRtlUnwindEx = (void *)GetProcAddress( hntdll,
"RtlUnwindEx" );
+ pRtlWow64GetThreadContext = (void *)GetProcAddress( hntdll,
+ "RtlWow64GetThreadContext" );
p_setjmp = (void *)GetProcAddress( hmsvcrt,
"_setjmp" );
@@ -3143,6 +3178,7 @@ START_TEST(exception)
test_restore_context();
test_prot_fault();
test_dpe_exceptions();
+ test_wow64_context();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
test_dynamic_unwind();
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 35e23d2..df04b33 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -924,22 +924,18 @@ static inline unsigned int get_server_context_flags( DWORD flags )
return ret;
}
-/***********************************************************************
- * get_thread_context
- */
-NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
+static NTSTATUS get_server_context( HANDLE handle, unsigned int server_flags,
+ context_t *context, BOOL *self )
{
NTSTATUS ret;
DWORD dummy, i;
- unsigned int server_flags = get_server_context_flags( context->ContextFlags );
- context_t server_context;
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 1;
- wine_server_set_reply( req, &server_context, sizeof(server_context) );
+ wine_server_set_reply( req, context, sizeof(*context) );
ret = wine_server_call( req );
*self = reply->self;
}
@@ -954,7 +950,7 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 0;
- wine_server_set_reply( req, &server_context, sizeof(server_context) );
+ wine_server_set_reply( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
@@ -969,10 +965,112 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
+ return ret;
+}
+
+NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self)
+{
+ context_t server_context;
+ unsigned int server_flags = get_server_context_flags( context->ContextFlags );
+ NTSTATUS ret = get_server_context( handle, server_flags, &server_context, self);
if (!ret) ret = context_from_server( context, &server_context );
return ret;
}
+#ifdef _WIN64
+/* convert CPU-specific flags to generic server flags */
+static inline unsigned int wow64_get_server_context_flags( DWORD flags )
+{
+ unsigned int ret = 0;
+
+ flags &= 0x3f; /* mask CPU id flags */
+ if (flags & WOW64_CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
+ if (flags & WOW64_CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
+ if (flags & WOW64_CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
+ if (flags & WOW64_CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
+ if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
+ if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS;
+ return ret;
+}
+
+static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *from )
+{
+ if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER;
+
+ to->ContextFlags = WOW64_CONTEXT_i386;
+ if (from->flags & SERVER_CTX_CONTROL)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_CONTROL;
+ to->Ebp = from->ctl.i386_regs.ebp;
+ to->Esp = from->ctl.i386_regs.esp;
+ to->Eip = from->ctl.i386_regs.eip;
+ to->SegCs = from->ctl.i386_regs.cs;
+ to->SegSs = from->ctl.i386_regs.ss;
+ to->EFlags = from->ctl.i386_regs.eflags;
+ }
+ if (from->flags & SERVER_CTX_INTEGER)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_INTEGER;
+ to->Eax = from->integer.i386_regs.eax;
+ to->Ebx = from->integer.i386_regs.ebx;
+ to->Ecx = from->integer.i386_regs.ecx;
+ to->Edx = from->integer.i386_regs.edx;
+ to->Esi = from->integer.i386_regs.esi;
+ to->Edi = from->integer.i386_regs.edi;
+ }
+ if (from->flags & SERVER_CTX_SEGMENTS)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_SEGMENTS;
+ to->SegDs = from->seg.i386_regs.ds;
+ to->SegEs = from->seg.i386_regs.es;
+ to->SegFs = from->seg.i386_regs.fs;
+ to->SegGs = from->seg.i386_regs.gs;
+ }
+ if (from->flags & SERVER_CTX_FLOATING_POINT)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_FLOATING_POINT;
+ to->FloatSave.ControlWord = from->fp.i386_regs.ctrl;
+ to->FloatSave.StatusWord = from->fp.i386_regs.status;
+ to->FloatSave.TagWord = from->fp.i386_regs.tag;
+ to->FloatSave.ErrorOffset = from->fp.i386_regs.err_off;
+ to->FloatSave.ErrorSelector = from->fp.i386_regs.err_sel;
+ to->FloatSave.DataOffset = from->fp.i386_regs.data_off;
+ to->FloatSave.DataSelector = from->fp.i386_regs.data_sel;
+ to->FloatSave.Cr0NpxState = from->fp.i386_regs.cr0npx;
+ memcpy( to->FloatSave.RegisterArea, from->fp.i386_regs.regs, sizeof(to->FloatSave.RegisterArea) );
+ }
+ if (from->flags & SERVER_CTX_DEBUG_REGISTERS)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS;
+ to->Dr0 = from->debug.i386_regs.dr0;
+ to->Dr1 = from->debug.i386_regs.dr1;
+ to->Dr2 = from->debug.i386_regs.dr2;
+ to->Dr3 = from->debug.i386_regs.dr3;
+ to->Dr6 = from->debug.i386_regs.dr6;
+ to->Dr7 = from->debug.i386_regs.dr7;
+ }
+ if (from->flags & SERVER_CTX_EXTENDED_REGISTERS)
+ {
+ to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS;
+ memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) );
+ }
+ return STATUS_SUCCESS;
+}
+
+
+/******************************************************************************
+ * RtlWow64GetThreadContext (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context )
+{
+ BOOL self;
+ context_t server_context;
+ unsigned int server_flags = wow64_get_server_context_flags( context->ContextFlags );
+ NTSTATUS ret = get_server_context( handle, server_flags, &server_context, &self );
+ if (!ret) ret = wow64_context_from_server( context, &server_context );
+ return ret;
+}
+#endif
/******************************************************************************
* NtQueryInformationThread (NTDLL.@)
--
2.7.4
June 6, 2018
[PATCH v3 1/5] winnt.h: Add some WOW64 definitions.
by Zebediah Figura
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
include/winnt.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/include/winnt.h b/include/winnt.h
index 54bf11d..c41eff4 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -2112,6 +2112,96 @@ typedef CONTEXT *PCONTEXT;
NTSYSAPI void WINAPI RtlCaptureContext(CONTEXT*);
+#define WOW64_CONTEXT_i386 0x00010000
+#define WOW64_CONTEXT_i486 0x00010000
+#define WOW64_CONTEXT_CONTROL (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000001))
+#define WOW64_CONTEXT_INTEGER (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000002))
+#define WOW64_CONTEXT_SEGMENTS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000004))
+#define WOW64_CONTEXT_FLOATING_POINT (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000008))
+#define WOW64_CONTEXT_DEBUG_REGISTERS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000010))
+#define WOW64_CONTEXT_EXTENDED_REGISTERS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000020))
+#define WOW64_CONTEXT_FULL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)
+#define WOW64_CONTEXT_ALL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | \
+ WOW64_CONTEXT_SEGMENTS | WOW64_CONTEXT_FLOATING_POINT | \
+ WOW64_CONTEXT_DEBUG_REGISTERS | WOW64_CONTEXT_EXTENDED_REGISTERS)
+
+#define WOW64_CONTEXT_XSTATE (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000040))
+
+#define WOW64_CONTEXT_EXCEPTION_ACTIVE 0x08000000
+#define WOW64_CONTEXT_SERVICE_ACTIVE 0x10000000
+#define WOW64_CONTEXT_EXCEPTION_REQUEST 0x40000000
+#define WOW64_CONTEXT_EXCEPTION_REPORTING 0x80000000
+
+#define WOW64_SIZE_OF_80387_REGISTERS 80
+#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512
+
+typedef struct _WOW64_FLOATING_SAVE_AREA {
+ DWORD ControlWord;
+ DWORD StatusWord;
+ DWORD TagWord;
+ DWORD ErrorOffset;
+ DWORD ErrorSelector;
+ DWORD DataOffset;
+ DWORD DataSelector;
+ BYTE RegisterArea[WOW64_SIZE_OF_80387_REGISTERS];
+ DWORD Cr0NpxState;
+} WOW64_FLOATING_SAVE_AREA, *PWOW64_FLOATING_SAVE_AREA;
+
+#include "pshpack4.h"
+typedef struct _WOW64_CONTEXT {
+ DWORD ContextFlags;
+ DWORD Dr0;
+ DWORD Dr1;
+ DWORD Dr2;
+ DWORD Dr3;
+ DWORD Dr6;
+ DWORD Dr7;
+ WOW64_FLOATING_SAVE_AREA FloatSave;
+ DWORD SegGs;
+ DWORD SegFs;
+ DWORD SegEs;
+ DWORD SegDs;
+ DWORD Edi;
+ DWORD Esi;
+ DWORD Ebx;
+ DWORD Edx;
+ DWORD Ecx;
+ DWORD Eax;
+ DWORD Ebp;
+ DWORD Eip;
+ DWORD SegCs;
+ DWORD EFlags;
+ DWORD Esp;
+ DWORD SegSs;
+ BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
+} WOW64_CONTEXT, *PWOW64_CONTEXT;
+#include "poppack.h"
+
+typedef struct _WOW64_LDT_ENTRY {
+ WORD LimitLow;
+ WORD BaseLow;
+ union {
+ struct {
+ BYTE BaseMid;
+ BYTE Flags1;
+ BYTE Flags2;
+ BYTE BaseHi;
+ } Bytes;
+ struct {
+ DWORD BaseMid : 8;
+ DWORD Type : 5;
+ DWORD Dpl : 2;
+ DWORD Pres : 1;
+ DWORD LimitHi : 4;
+ DWORD Sys : 1;
+ DWORD Reserved_0 : 1;
+ DWORD Default_Big : 1;
+ DWORD Granularity : 1;
+ DWORD BaseHi : 8;
+ } Bits;
+ } HighWord;
+} WOW64_LDT_ENTRY, *PWOW64_LDT_ENTRY;
+
/*
* Product types
*/
--
2.7.4
June 6, 2018
Re: [PATCH v2 3/5] ntdll: Implement RtlWow64SetThreadContext().
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39017
Your paranoid android.
=== wvistau64 (64 bit exception) ===
exception.c:2506: Test failed: got 0x8000000d
=== w2008s64 (64 bit exception) ===
exception.c:2506: Test failed: got 0x8000000d
June 6, 2018
Re: [PATCH v2 2/5] ntdll: Implement RtlWow64GetThreadContext().
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=39016
Your paranoid android.
=== wvistau64 (64 bit exception) ===
exception.c:2505: Test failed: got 0x8000000d
=== w2008s64 (64 bit exception) ===
exception.c:2505: Test failed: got 0x8000000d
June 6, 2018