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 2022
- 68 participants
- 3274 messages
[PATCH vkd3d v4 5/9] vkd3d-shader/hlsl: Introduce add_cast() helper.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
There is another call to hlsl_new_cast() in hlsl.y that I didn't redirect
to add_cast(), because it doesn't require the upcoming matrix conversion
patch. I don't know if you want it to be redirected too.
v3:
* add back some mistakenly removed lines
---
libs/vkd3d-shader/hlsl.y | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index faac562a..23c48cdc 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -266,7 +266,7 @@ static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_typ
return false;
}
-static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct list *instrs,
+static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs,
struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
{
struct hlsl_type *src_type = node->data_type;
@@ -275,6 +275,17 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct
if (hlsl_types_are_equal(src_type, dst_type))
return node;
+ if (!(cast = hlsl_new_cast(ctx, node, dst_type, loc)))
+ return NULL;
+ list_add_tail(instrs, &cast->node.entry);
+ return &cast->node;
+}
+
+static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct list *instrs,
+ struct hlsl_ir_node *node, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_type *src_type = node->data_type;
+
if (!implicit_compatible_data_types(src_type, dst_type))
{
struct vkd3d_string_buffer *src_string, *dst_string;
@@ -293,10 +304,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct
hlsl_warning(ctx, loc, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION, "Implicit truncation of %s type.",
src_type->type == HLSL_CLASS_VECTOR ? "vector" : "matrix");
- if (!(cast = hlsl_new_cast(ctx, node, dst_type, loc)))
- return NULL;
- list_add_tail(instrs, &cast->node.entry);
- return &cast->node;
+ return add_cast(ctx, instrs, node, dst_type, loc);
}
static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod, const struct vkd3d_shader_location loc)
@@ -3718,7 +3726,6 @@ unary_expr:
{
struct hlsl_type *src_type = node_from_list($6)->data_type;
struct hlsl_type *dst_type;
- struct hlsl_ir_expr *cast;
unsigned int i;
if ($2)
@@ -3746,12 +3753,11 @@ unary_expr:
YYABORT;
}
- if (!(cast = hlsl_new_cast(ctx, node_from_list($6), dst_type, &@3)))
+ if (!add_cast(ctx, $6, node_from_list($6), dst_type, &@3))
{
hlsl_free_instr_list($6);
YYABORT;
}
- list_add_tail($6, &cast->node.entry);
$$ = $6;
}
--
2.36.1
June 7, 2022
[PATCH vkd3d v4 4/9] vkd3d-shader/hlsl: Allocate enough space for temporary matrices.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
If this is reverted on top of "Lower numeric casts", then the shader
runner crashes with:
shader_runner: ../vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h:1165: vkd3d_write_mask_component_count: Assertion `1 <= count && count <= VKD3D_VEC4_SIZE' failed.
While the HLSL copiler is expected to output correct programs, the DXBC
parser should not crash on malformed inputs anyway, so there is a bug
to be fixed there too.
v2:
* Use hlsl_type_component_count()
---
libs/vkd3d-shader/hlsl_codegen.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 6f524744..1a5e9055 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -1378,7 +1378,7 @@ static void allocate_variable_temp_register(struct hlsl_ctx *ctx, struct hlsl_ir
var->last_read, var->data_type->reg_size);
else
var->reg = allocate_register(ctx, liveness, var->first_write,
- var->last_read, var->data_type->dimx);
+ var->last_read, hlsl_type_component_count(var->data_type));
TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name,
debug_register('r', var->reg, var->data_type), var->first_write, var->last_read);
}
--
2.36.1
June 7, 2022
[PATCH vkd3d v4 3/9] tests: Test how matrix types interact with semantics.
by Giovanni Mascellani
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
v2:
* Use the new single component syntax
---
Makefile.am | 1 +
tests/matrix-semantics.shader_test | 71 ++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+)
create mode 100644 tests/matrix-semantics.shader_test
diff --git a/Makefile.am b/Makefile.am
index dd3ce1ff..74c23b2b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -108,6 +108,7 @@ vkd3d_shader_tests = \
tests/hlsl-vector-indexing-uniform.shader_test \
tests/logic-operations.shader_test \
tests/math.shader_test \
+ tests/matrix-semantics.shader_test \
tests/nointerpolation.shader_test \
tests/pow.shader_test \
tests/preproc-if.shader_test \
diff --git a/tests/matrix-semantics.shader_test b/tests/matrix-semantics.shader_test
new file mode 100644
index 00000000..6a089683
--- /dev/null
+++ b/tests/matrix-semantics.shader_test
@@ -0,0 +1,71 @@
+[pixel shader]
+float4x1 main() : sv_target
+{
+ return float4(1.0, 2.0, 3.0, 4.0);
+}
+
+[test]
+todo draw quad
+probe all rgba (1.0, 2.0, 3.0, 4.0)
+
+[pixel shader]
+row_major float1x4 main() : sv_target
+{
+ return float4(1.0, 2.0, 3.0, 4.0);
+}
+
+[test]
+todo draw quad
+probe all rgba (1.0, 2.0, 3.0, 4.0)
+
+[require]
+shader model >= 4.0
+
+[pixel shader]
+row_major float4x1 main() : sv_target
+{
+ return float4(1.0, 2.0, 3.0, 4.0);
+}
+
+[test]
+todo draw quad
+probe all r (1.0)
+
+[pixel shader]
+float1x4 main() : sv_target
+{
+ return float4(1.0, 2.0, 3.0, 4.0);
+}
+
+[test]
+todo draw quad
+probe all r (1.0)
+
+[pixel shader]
+void main(out row_major float1x4 x : sv_target0, out float1x4 y : sv_target1)
+{
+ x = float4(1.0, 2.0, 3.0, 4.0);
+ y = float4(5.0, 6.0, 7.0, 8.0);
+}
+
+[test]
+todo draw quad
+probe all rgba (1.0, 2.0, 3.0, 4.0)
+
+[pixel shader fail todo]
+void main(out float1x4 x : sv_target0, out float1x4 y : sv_target1)
+{
+ x = float4(1.0, 2.0, 3.0, 4.0);
+ y = float4(5.0, 6.0, 7.0, 8.0);
+}
+
+[pixel shader]
+void main(out float1x4 x : sv_target0, out float1x4 y : sv_target4)
+{
+ x = float4(1.0, 2.0, 3.0, 4.0);
+ y = float4(5.0, 6.0, 7.0, 8.0);
+}
+
+[test]
+todo draw quad
+probe all r (1.0)
--
2.36.1
June 7, 2022
[PATCH vkd3d v4 2/9] vkd3d-shader/hlsl: Split matrices into multiple variables in prepend_input_copy().
by Giovanni Mascellani
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_codegen.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index b4fcfd27..6f524744 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -84,6 +84,21 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
struct hlsl_ir_load *load;
struct hlsl_ir_var *input;
+ if (type->type == HLSL_CLASS_MATRIX)
+ {
+ struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type));
+ struct hlsl_semantic vector_semantic = *semantic;
+ unsigned int i;
+
+ for (i = 0; i < major_size(type); ++i)
+ {
+ prepend_input_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic);
+ ++vector_semantic.index;
+ }
+
+ return;
+ }
+
if (!(name = hlsl_get_string_buffer(ctx)))
return;
vkd3d_string_buffer_printf(name, "<input-%s%u>", semantic->name, semantic->index);
--
2.36.1
June 7, 2022
[PATCH vkd3d v4 1/9] vkd3d-shader/hlsl: Split matrices into multiple variables in append_output_copy().
by Giovanni Mascellani
From: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_codegen.c | 47 +++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 78b22910..b4fcfd27 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -21,6 +21,22 @@
#include "hlsl.h"
#include <stdio.h>
+static unsigned int minor_size(const struct hlsl_type *type)
+{
+ if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
+ return type->dimx;
+ else
+ return type->dimy;
+}
+
+static unsigned int major_size(const struct hlsl_type *type)
+{
+ if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
+ return type->dimy;
+ else
+ return type->dimx;
+}
+
/* Split uniforms into two variables representing the constant and temp
* registers, and copy the former to the latter, so that writes to uniforms
* work. */
@@ -141,6 +157,21 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct list *instrs, struct
struct hlsl_ir_var *output;
struct hlsl_ir_load *load;
+ if (type->type == HLSL_CLASS_MATRIX)
+ {
+ struct hlsl_type *vector_type = hlsl_get_vector_type(ctx, type->base_type, minor_size(type));
+ struct hlsl_semantic vector_semantic = *semantic;
+ unsigned int i;
+
+ for (i = 0; i < major_size(type); ++i)
+ {
+ append_output_copy(ctx, instrs, var, vector_type, 4 * i, modifiers, &vector_semantic);
+ ++vector_semantic.index;
+ }
+
+ return;
+ }
+
if (!(name = hlsl_get_string_buffer(ctx)))
return;
vkd3d_string_buffer_printf(name, "<output-%s%u>", semantic->name, semantic->index);
@@ -847,22 +878,6 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr
return true;
}
-static unsigned int minor_size(const struct hlsl_type *type)
-{
- if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
- return type->dimx;
- else
- return type->dimy;
-}
-
-static unsigned int major_size(const struct hlsl_type *type)
-{
- if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR)
- return type->dimy;
- else
- return type->dimx;
-}
-
static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
const struct hlsl_ir_node *rhs;
--
2.36.1
June 7, 2022
Re: [PATCH 2/5] d2d1: Partially implement RegisterEffectFromStream().
by Nikolay Sivov
On 6/7/22 06:43, Ziqing Hui wrote:
>>>> +Â Â Â reg->info->default_input_count = input_count;
>>>> +Â Â Â reg->info->min_inputs = input_count;
>>>> +Â Â Â reg->info->max_inputs = input_count;
>>> Is this supposed to be subproperties of an Input? Maybe we should have basic property support first, and store it there. Is min/max/default expressible in effect xml? <Input> attributes maybe?
>> It is likely that they can be expressed in xml as properties of <Effect> like "DisplayName"/"Author", tests are still needed.
>> And according to the current test, if I don't explicitly express them in xml, they will be equal to the number of <Input> nodes inside <Inputs>.
>>
> I did some tests today. I didn't find a way to express min/max/default input count in XML.
>
> I tried these ways:
>
> * Property of <Effect>:
>
> <Effect>
> ...
> <Property name='MinInputs' type='uint32' value='1'/>
> </Effect>
>
> * Sub property of <Inputs>:
>
> <Effect>
> ...
> <Inputs>
> <Property name='Min' type='uint32' value='1'/>
> </Inputs>
> <Effect>
>
> * Attribute of <Inputs>:
>
> <Effect>
> ...
> <Inputs min='1'/>
> <Effect/>
>
> Unfortunately, none of them work.
>
I see. It's easier to assume it's consistent with returned name, so it
should be using MinInputs name. If it doesn't work, let's ignore that
for now.
Structurally, I was thinking that each <Property/> would trigger some
add_property() helper that would simply append to some array. That could
use some structure of { index, name, type, value }, for system
properties name could be empty. It doesn't have to be exactly like that,
but the point is that it should be easy to use when parsing description,
and when instantiating effects objects. I haven't looked that closely,
but I imaging a new instance will use initial values from 'value'
attributes + set getter/setter functions, which means that instance
properties are essentially cloned from the description.
June 7, 2022
Re: [PATCH 7/7] winhttp/tests: Add tests for closing web socket with pending operations.
by Marvin
Hi,
While running your changed tests, 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=116370
Your paranoid android.
=== w1064 (64 bit report) ===
winhttp:
notification.c:122: Test failed: 1198: expected callback to be called from the same thread
=== w1064_adm (64 bit report) ===
winhttp:
notification.c:122: Test failed: 1179: expected callback to be called from the same thread
=== w10pro64_ja (64 bit report) ===
winhttp:
notification.c:122: Test failed: 1179: expected callback to be called from the same thread
=== w10pro64_zh_CN (64 bit report) ===
winhttp:
notification.c:122: Test failed: 1179: expected callback to be called from the same thread
=== debian11 (32 bit German report) ===
winhttp:
notification.c:127: Test failed: 1266: expected callback to be called from the other thread
June 7, 2022
Re: [PATCH 0/7] MR195: winhttp: Abort web socket receive operations when the socket handle is closed
by Paul Gofman
On 6/6/22 23:02, Paul Gofman (@gofman) wrote:
> I think somewhat similar should happen with normal winhttp requests (I was doing some brief tests around that back then) and that should hopefully be easy to add incrementally after this patchset.
>
> Then, sends for websockets should most likely also be cancelled the same way although that is a bit harder to test as most of the time sends are processed right away before returing from WinHttpWebSocketSend (although should be possible as out of tree test which might be flaky).
>
> The patches here address cancelling web socket receive operation (including receiving web socket close status).
>
Eh, I am missing sign-off and also test in notification.c line 1179 is
flaky (would comment out the other thread requirement, the same comment
as for the next nest on line 1213 applies), but I will probably wait for
some initial feedback before resending the whole series.
June 7, 2022
[PATCH 7/7] winhttp/tests: Add tests for closing web socket with pending operations.
by Paul Gofman
From: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/winhttp/tests/notification.c | 238 ++++++++++++++++++++++++++++--
1 file changed, 229 insertions(+), 9 deletions(-)
diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c
index 50874a49a07..7f2f741fef5 100644
--- a/dlls/winhttp/tests/notification.c
+++ b/dlls/winhttp/tests/notification.c
@@ -59,11 +59,12 @@ struct notification
DWORD flags; /* a combination of NF_* flags */
};
-#define NF_ALLOW 0x0001 /* notification may or may not happen */
-#define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
-#define NF_SIGNAL 0x0004 /* signal wait handle when notified */
-#define NF_MAIN_THREAD 0x0008 /* the operation completes synchronously and callback is called from the main thread */
-#define NF_SAVE_BUFFER 0x0010 /* save buffer data when notified */
+#define NF_ALLOW 0x0001 /* notification may or may not happen */
+#define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
+#define NF_SIGNAL 0x0004 /* signal wait handle when notified */
+#define NF_MAIN_THREAD 0x0008 /* the operation completes synchronously and callback is called from the main thread */
+#define NF_OTHER_THREAD 0x0010 /* callback is called from the other thread */
+#define NF_SAVE_BUFFER 0x0020 /* save buffer data when notified */
struct info
{
@@ -121,6 +122,11 @@ static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DW
ok(GetCurrentThreadId() == info->main_thread_id, "%u: expected callback to be called from the same thread\n",
info->line);
}
+ if (info->test[info->index].flags & NF_OTHER_THREAD)
+ {
+ ok(GetCurrentThreadId() != info->main_thread_id, "%u: expected callback to be called from the other thread\n",
+ info->line);
+ }
if (info->test[info->index].flags & NF_SAVE_BUFFER)
{
info->buflen = buflen;
@@ -704,14 +710,63 @@ static const struct notification websocket_test2[] =
{ winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
{ winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_MAIN_THREAD | NF_SAVE_BUFFER},
- { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE, NF_SIGNAL },
- { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE, NF_SIGNAL | NF_OTHER_THREAD },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_MAIN_THREAD },
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
};
-static const struct notification websocket_test3[] =
+static struct notification websocket_test3[] =
+{
+ { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
+ { winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
+ { winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
+
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_MAIN_THREAD },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_SAVE_BUFFER },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL | NF_OTHER_THREAD },
+
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL | NF_MAIN_THREAD },
+};
+
+static struct notification websocket_test4[] =
+{
+ { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
+ { winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
+ { winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
+
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_SAVE_BUFFER },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL | NF_OTHER_THREAD },
+
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL/* | NF_MAIN_THREAD*/ },
+};
+
+static const struct notification websocket_test5[] =
{
{ winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
@@ -1065,11 +1120,176 @@ static void test_websocket(BOOL secure)
WaitForSingleObject( info.wait, INFINITE );
end_test( &info, __LINE__ );
- /* Test socket shutdown while receive is pending. */
+
+ /* Test socket handle close while web socket close is pending. */
info.test = websocket_test3;
info.count = ARRAY_SIZE( websocket_test3 );
info.index = 0;
+ for (i = 0; websocket_test3[i].function != winhttp_websocket_close; ++i)
+ ;
+
+ if (secure)
+ websocket_test3[i + 1].flags = (websocket_test3[i + 1].flags & ~NF_OTHER_THREAD) | NF_MAIN_THREAD;
+ else
+ websocket_test3[i + 1].flags = (websocket_test3[i + 1].flags & ~NF_MAIN_THREAD) | NF_OTHER_THREAD;
+
+ setup_test( &info, winhttp_open_request, __LINE__ );
+ request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, secure ? WINHTTP_FLAG_SECURE : 0);
+ ok( request != NULL, "got %lu\n", err );
+
+ if (secure)
+ {
+ flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+ ret = WinHttpSetOption(request, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+ ok( ret, "failed to set security flags %lu\n", GetLastError() );
+ }
+
+ ret = WinHttpSetOption( request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+
+ setup_test( &info, winhttp_send_request, __LINE__ );
+ ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_receive_response, __LINE__ );
+ ret = WinHttpReceiveResponse( request, NULL );
+ ok( ret, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ size = sizeof(status);
+ ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+ ok( ret, "failed unexpectedly %lu\n", err );
+ ok( status == 101, "got %lu\n", status );
+
+ setup_test( &info, winhttp_websocket_complete_upgrade, __LINE__ );
+ socket = pWinHttpWebSocketCompleteUpgrade( request, (DWORD_PTR)context );
+ ok( socket != NULL, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_websocket_receive, __LINE__ );
+ buffer[0] = 0;
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+ ok( buffer[0] == 'R', "unexpected data\n" );
+
+ setup_test( &info, winhttp_websocket_close, __LINE__ );
+
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ err = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ info.buflen = 0xdeadbeef;
+ WinHttpCloseHandle( socket );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ ok( info.buflen == sizeof(*result), "got %u\n", info.buflen );
+ result = (WINHTTP_WEB_SOCKET_ASYNC_RESULT *)info.buffer;
+ ok( result->Operation == WINHTTP_WEB_SOCKET_CLOSE_OPERATION, "got %u\n", result->Operation );
+ todo_wine ok( !result->AsyncResult.dwResult, "got %Iu\n", result->AsyncResult.dwResult );
+ todo_wine_if( !secure )
+ ok( result->AsyncResult.dwError == ERROR_WINHTTP_OPERATION_CANCELLED, "got %lu\n", result->AsyncResult.dwError );
+
+ setup_test( &info, winhttp_close_handle, __LINE__ );
+ WinHttpCloseHandle( request );
+ WaitForSingleObject( info.wait, INFINITE );
+ end_test( &info, __LINE__ );
+
+ /* Test socket handle close while receive is pending. */
+ info.test = websocket_test4;
+ info.count = ARRAY_SIZE( websocket_test4 );
+ info.index = 0;
+
+ for (i = 0; websocket_test4[i].function != winhttp_websocket_close; ++i)
+ ;
+
+ if (secure)
+ {
+ /* Sometimes (rarely) Windows calls the callback from the async receive thread, so don't set
+ * NF_MAIN_THREAD here to avoid flaky test. Maybe it cancels the socket IO first and aborts the
+ * completion next so sometimes the async thread is fast enough to send the notification
+ * before it is done by the main thread. */
+ websocket_test4[i].flags = (websocket_test4[i].flags & ~NF_OTHER_THREAD)/* | NF_MAIN_THREAD*/;
+ }
+ else
+ {
+ websocket_test4[i].flags = (websocket_test4[i].flags & ~NF_MAIN_THREAD) | NF_OTHER_THREAD;
+ }
+
+ setup_test( &info, winhttp_open_request, __LINE__ );
+ request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, secure ? WINHTTP_FLAG_SECURE : 0);
+ ok( request != NULL, "got %lu\n", err );
+
+ if (secure)
+ {
+ flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+ ret = WinHttpSetOption(request, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+ ok( ret, "failed to set security flags %lu\n", GetLastError() );
+ }
+
+ ret = WinHttpSetOption( request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+
+ setup_test( &info, winhttp_send_request, __LINE__ );
+ ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_receive_response, __LINE__ );
+ ret = WinHttpReceiveResponse( request, NULL );
+ ok( ret, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ size = sizeof(status);
+ ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+ ok( ret, "failed unexpectedly %lu\n", err );
+ ok( status == 101, "got %lu\n", status );
+
+ setup_test( &info, winhttp_websocket_complete_upgrade, __LINE__ );
+ socket = pWinHttpWebSocketCompleteUpgrade( request, (DWORD_PTR)context );
+ ok( socket != NULL, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_websocket_receive, __LINE__ );
+ buffer[0] = 0;
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+ ok( buffer[0] == 'R', "unexpected data\n" );
+
+ setup_test( &info, winhttp_websocket_close, __LINE__ );
+
+ info.buflen = 0xdeadbeef;
+
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ WinHttpCloseHandle( socket );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ ok( info.buflen == sizeof(*result), "got %u\n", info.buflen );
+ result = (WINHTTP_WEB_SOCKET_ASYNC_RESULT *)info.buffer;
+ ok( result->Operation == WINHTTP_WEB_SOCKET_RECEIVE_OPERATION, "got %u\n", result->Operation );
+ ok( !result->AsyncResult.dwResult, "got %Iu\n", result->AsyncResult.dwResult );
+ todo_wine_if( !secure )
+ ok( result->AsyncResult.dwError == ERROR_WINHTTP_OPERATION_CANCELLED, "got %lu\n", result->AsyncResult.dwError );
+
+ setup_test( &info, winhttp_close_handle, __LINE__ );
+ WinHttpCloseHandle( request );
+ WaitForSingleObject( info.wait, INFINITE );
+ end_test( &info, __LINE__ );
+
+ /* Test socket shutdown while receive is pending. */
+ info.test = websocket_test5;
+ info.count = ARRAY_SIZE( websocket_test5 );
+ info.index = 0;
+
setup_test( &info, winhttp_open_request, __LINE__ );
request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, secure ? WINHTTP_FLAG_SECURE : 0);
ok( request != NULL, "got %lu\n", err );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/195
June 7, 2022
[PATCH 6/7] winhttp: Support abort in task_socket_close().
by Paul Gofman
From: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/winhttp/request.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 3a239966c69..397421ebcd0 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -4153,13 +4153,18 @@ static void task_socket_close( void *ctx, BOOL abort )
struct socket *socket = (struct socket *)s->task_hdr.obj;
DWORD ret;
- if (abort) return;
+ if (abort)
+ {
+ socket_close_complete( socket, ERROR_WINHTTP_OPERATION_CANCELLED );
+ return;
+ }
TRACE("running %p\n", ctx);
ret = socket_close( socket );
receive_io_complete( socket );
- socket_close_complete( socket, ret );
+ if (task_needs_completion( &s->task_hdr ))
+ socket_close_complete( socket, ret );
}
DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reason, DWORD len )
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/195
June 7, 2022