Compare commits

..

14 Commits
v10.0 ... v10.1

Author SHA1 Message Date
Alistair Leslie-Hughes
7b9777c23e Release v10.1 2025-02-09 18:37:10 +11:00
Alistair Leslie-Hughes
aed0bcfb83 Rebase against a1dddd902f21e3a5057a40cb9848351f0cbcfd82. 2025-02-09 18:37:05 +11:00
Alistair Leslie-Hughes
22f5ea5e4f Rebase against a47a9f39d1e9d19a7931cdc254a9cd68c1ed6fef. 2025-02-07 10:29:46 +11:00
Alistair Leslie-Hughes
7f5729fc14 Updated vkd3d-latest patchset 2025-02-04 10:23:08 +11:00
Alistair Leslie-Hughes
7fda13a16d Rebase against 40b0ede26e317bb994bf0b85ea37c7dab074e9f1. 2025-02-04 10:22:36 +11:00
Alistair Leslie-Hughes
667ee8a4ff Added oleaut32_VarAdd patchset 2025-01-24 20:23:21 +11:00
Alistair Leslie-Hughes
b45a0aead3 Added d2d1_ID2D1GeometryGroup patchset 2025-01-24 10:29:21 +11:00
Alistair Leslie-Hughes
36483a9c11 Added shell32_enumerableobejct patchset 2025-01-24 09:10:08 +11:00
Alistair Leslie-Hughes
28834e80f8 Added richedit20-ImportDataObject patchset 2025-01-24 08:51:23 +11:00
Alistair Leslie-Hughes
49770c6bc6 Added mf_http_support patchset 2025-01-24 07:45:00 +11:00
Alistair Leslie-Hughes
93f5b4f6a0 Added vbscript_join patchset 2025-01-24 07:44:13 +11:00
Alistair Leslie-Hughes
e452a6cbdc Added vbscript-classes patchset 2025-01-24 07:43:33 +11:00
Alistair Leslie-Hughes
23ccc2eef1 Rebase against ff2de2a73b830a601cfe26aca5feeafb309fbff5. 2025-01-23 09:01:50 +11:00
Alistair Leslie-Hughes
18f976c338 Updated vkd3d-latest patchset 2025-01-23 08:14:29 +11:00
31 changed files with 9434 additions and 2134 deletions

View File

@@ -0,0 +1,267 @@
From e4d55d451648b67c9269241efce8eee63faf70a4 Mon Sep 17 00:00:00 2001
From: Philipp Knechtges <philipp-dev@knechtges.com>
Date: Fri, 13 Sep 2024 11:16:44 +0200
Subject: [PATCH] d2d1: Add tests for drawing ID2D1GeometryGroup
The functionality to draw ID2D1GeometryGroup is currently missing.
Nothing is drawn. This causes the blank pages in the bug below.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139
---
dlls/d2d1/tests/d2d1.c | 219 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 219 insertions(+)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 40bcf5079b8..41b36ef0dd5 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -7061,6 +7061,7 @@ static void test_gradient(BOOL d3d11)
static void test_draw_geometry(BOOL d3d11)
{
ID2D1TransformedGeometry *transformed_geometry[4];
+ ID2D1GeometryGroup *geometry_group;
ID2D1RectangleGeometry *rect_geometry[2];
D2D1_POINT_2F point = {0.0f, 0.0f};
D2D1_ROUNDED_RECT rounded_rect;
@@ -7970,6 +7971,117 @@ static void test_draw_geometry(BOOL d3d11)
hr = ID2D1PathGeometry_Open(geometry, &sink);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ set_point(&point, -0.402914f, 0.915514f);
+ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
+ quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
+ quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
+ quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
+ quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
+ quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
+ quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
+ quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
+ quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
+ quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
+ quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
+ quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
+ quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
+ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
+
+ hr = ID2D1GeometrySink_Close(sink);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1GeometrySink_Release(sink);
+
+ set_matrix_identity(&matrix);
+ translate_matrix(&matrix, 40.0f, 160.0f);
+ scale_matrix(&matrix, 20.0f, 80.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ set_matrix_identity(&matrix);
+ translate_matrix(&matrix, 160.0f, 640.0f);
+ scale_matrix(&matrix, 40.0f, 160.0f);
+ rotate_matrix(&matrix, M_PI / -5.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1PathGeometry_Release(geometry);
+
+ set_matrix_identity(&matrix);
+ scale_matrix(&matrix, 0.5f, 1.0f);
+ translate_matrix(&matrix, -80.0f, 0.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ set_matrix_identity(&matrix);
+ rotate_matrix(&matrix, M_PI / 2.0f);
+ translate_matrix(&matrix, 80.0f, -320.0f);
+ scale_matrix(&matrix, 2.0f, 0.25f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ hr = ID2D1Factory_CreateGeometryGroup(factory, D2D1_FILL_MODE_WINDING,
+ (ID2D1Geometry**) &transformed_geometry, 4, &geometry_group);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1TransformedGeometry_Release(transformed_geometry[3]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[2]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[1]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[0]);
+
+ ID2D1RenderTarget_BeginDraw(rt);
+ ID2D1RenderTarget_Clear(rt, &color);
+ ID2D1RenderTarget_DrawGeometry(rt, (ID2D1Geometry *)geometry_group, (ID2D1Brush *)brush, 10.0f, NULL);
+ hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1GeometryGroup_Release(geometry_group);
+
+ match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 256,
+ "iTANiwEagQEkeSp0LnIWAhZyFAYUchQGFHIUBhRyFAYUchQGFHIUBhRyFAYUchQGFHIUBhRyFAYU"
+ "cxQFFHMUBRRzFAUUcxQFFHMUBRRzFAUUcxQFFHMUBRRzFAUUcxQFFHQUBBR0FAQUdBQDFHUUAxR1"
+ "FAMUdRQDFHUUAxR1FQIUdhQCFHYUAhR2FAIUdhQCFHYUAhR2FAIUdhQBFHgoeCh4KHkmeiZ7JHwk"
+ "fSJ+In8ggAEfggEeggEdhAEchQEbhQEahwEZhwEYiQEXiQEWigEWigEWigEWiwEViwEViwEViwEV"
+ "igEXiQEXiQEXiQEYhwEZhgEbgwEefyR5KXQvbxgEGG4VBxhtMnAudCp6IoMBGOMu");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 512,
+ "xpcBB7QCEqkCG6ACJJgCLI8CNYcCHgMc/gEeDBr4AR4UGPIBHR0W7AEdIxbmAR0pFt8BHTAV2gEd"
+ "MBrWARwuIdMBGiwi1gEYKiPZARYoJNwBFiQk4AEWHyWxAQQvFhsltgEKKBYWJrwBECBOwQEXF0rI"
+ "ARwOSM4Ba9UBYeABRf0BOIoCMZECLJYCKJoCJ5wCJp0CJJ8CIqICH6QCHagCGa4CFLoCB/yUAQAA");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 512,
+ "yWQBnQEEmQEHlgELkwENkAEQjgETiwEVigEXhwEZhgEahQEcgwEdggEfgAEgfyF+I30jfCR8JXom"
+ "eid4KHgodxQCFHYUAhR1FAMUdBUEFHMUBRRyFQUUchQHFHEUBxRwFAgUcBQJFG4UChRuFAoUbRUL"
+ "FGwUDBRsFAwUbBQNFGwUDBRsFAwUbRQMFGwUDBRsFAwUbRQLFWwUDBRtFAsUbRQLFG0VCxRtFAsU"
+ "bRQLFG4UCxRtFAsUbhQKFG4UCxRuFAoUbhQKFG4VCRRvFAoUbhQKFG8UCRRvFAoUbxQJFG8UCRRw"
+ "FAgVbxQJFHAUCBRwFAgUcBUIFHAUCBRwFAgUcRQHFHEUBxRyFAYUchQGFHMUBRRzFAUUdBQEFHQU"
+ "BBR1FAQUdBQEFHUUAxR1FAMUdhQCFHYUAhR2FQEUdxQBFHcpeCh4KHkneSd6JnoneiZ7JXwkfSN+"
+ "In8hgAEggQEfgwEdhAEdhAEchQEbhgEahwEZiAEYGAFwGBYCcRcUBHEXEgZyFhEHchcOCXMWDAtz"
+ "FgsMdBYIDnQWBhB1FgQQdhYCEnYqdyl3KXcpeCd5J3kneSd5JnomeyR8JHwkfCN9I30ifiF/IX4h"
+ "fyF/IH8ggAEgfyCAASCAAR+AAR+BAR6CAR6BAR6CAR2CAR2DARyEARuEARuFARqGARmGARiKARSR"
+ "AQqhYwAA");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 1024,
+ "ytABA7gCCbICD60CFKkCF6cCGqMCHqACIZ0CJJoCJpgCKZUCFgIUkgIWBBWPAhYHFI4CFQoUjAIV"
+ "DBSKAhUNFYgCFQ8UhwIVERSFAhUTFIMCFRQVgQIUFxSAAhQZFP4BFBoV/AEUHBT7ARQeFPkBFB8V"
+ "9wEUIRT2ARQjFPQBFSMV8gEVJRTxARUnFPABFCgV7gEUKhTtARQsFOwBFCwV7AEULBTsARUsFOwB"
+ "FSsV7AEULBTtARQsFO0BFCsU7QEVKxTtARUqFe0BFSoU7gEUKxTuARQqFe4BFCoU7wEUKhTuARUp"
+ "FO8BFSkU7wEVKBXvARUoFPABFCkU8AEUKBTxARQoFPEBFCcV8QEUJxTxARUnFPEBFSYU8gEVJhTy"
+ "ARUlFfIBFSUU8wEUJRXzARQlFPQBFCUU9AEUJBT1ARQkFPUBFCMU9gEUIhT2ARUhFPcBFSAU+AEV"
+ "HxT5ARUeFPoBFR4U+gEVHRT7ARUcFPwBFRsU/QEVGhT+ARUZFP8BFBkUgAIUGBSBAhQXFIICFBcU"
+ "ggIUFhSDAhQVFIQCFBQUhQIUExSGAhQSFIcCFBIUhwIUERSIAhUPFIkCFg0UigIXCxSNAhYJFI8C"
+ "FggUkAIXBRSSAhcDFJQCFwEUlgIrlwIpmgImnAIkngIjnwIhoQIfowIepAIcpgIbpgIaqAIZqAIZ"
+ "qAIYKwP7ARgnBf0BGCMI/QEZHgz+ARgbD/8BGBcSgAIYEhaAAhoNGIICGggcgwIaBB+DAjyEAjyF"
+ "AjqGAjmIAjiIAiECFIkCFAIIBBSKAhQNFIsCFAwUjAIUCxSNAhQKFI4CFAkUjwIUBxWQAhQGFZEC"
+ "FAUVkQIUBRWRAhQFFZECFQMVkwIUAxWTAhQDFZMCFAIVlAIVARWVAiqVAimWAimWAiiYAiaZAiaZ"
+ "AiWaAiScAiKdAiGeAh+hAhyjAhmuAg3GxgEA");
+ ok(match, "Figure does not match.\n");
+
+ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ hr = ID2D1PathGeometry_Open(geometry, &sink);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
set_point(&point, 20.0f, 80.0f);
ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
quadratic_to(sink, 20.0f, 160.0f, 60.0f, 160.0f);
@@ -8011,6 +8123,7 @@ static void test_draw_geometry(BOOL d3d11)
static void test_fill_geometry(BOOL d3d11)
{
ID2D1TransformedGeometry *transformed_geometry[4];
+ ID2D1GeometryGroup *geometry_group;
ID2D1RectangleGeometry *rect_geometry[2];
D2D1_POINT_2F point = {0.0f, 0.0f};
D2D1_ROUNDED_RECT rounded_rect;
@@ -8728,6 +8841,112 @@ static void test_fill_geometry(BOOL d3d11)
hr = ID2D1PathGeometry_Open(geometry, &sink);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ set_point(&point, -0.402914f, 0.915514f);
+ ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_FILLED);
+ quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
+ quadratic_to(sink, 0.008350f, 0.693614f, -0.052343f, 0.448886f);
+ quadratic_to(sink, -0.154236f, 0.246072f, -0.279229f, 0.025343f);
+ quadratic_to(sink, -0.370064f, -0.588586f, -0.383029f, -0.924114f);
+ quadratic_to(sink, -0.295479f, -0.958764f, -0.017086f, -0.988400f);
+ quadratic_to(sink, 0.208836f, -0.954157f, 0.272200f, -0.924114f);
+ quadratic_to(sink, 0.295614f, -0.569071f, 0.230143f, 0.022886f);
+ quadratic_to(sink, 0.101664f, 0.220643f, 0.012057f, 0.451571f);
+ quadratic_to(sink, -0.028764f, 0.709014f, 0.104029f, 0.833943f);
+ quadratic_to(sink, 0.319414f, 0.913057f, 0.403229f, 0.942628f);
+ quadratic_to(sink, 0.317721f, 1.023450f, -0.017086f, 1.021771f);
+ quadratic_to(sink, -0.310843f, 1.007472f, -0.402914f, 0.915514f);
+ ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
+
+ hr = ID2D1GeometrySink_Close(sink);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1GeometrySink_Release(sink);
+
+ set_matrix_identity(&matrix);
+ translate_matrix(&matrix, 40.0f, 160.0f);
+ scale_matrix(&matrix, 20.0f, 80.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[0]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ set_matrix_identity(&matrix);
+ translate_matrix(&matrix, 160.0f, 640.0f);
+ scale_matrix(&matrix, 40.0f, 160.0f);
+ rotate_matrix(&matrix, M_PI / -5.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)geometry, &matrix, &transformed_geometry[1]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1PathGeometry_Release(geometry);
+
+ set_matrix_identity(&matrix);
+ scale_matrix(&matrix, 0.5f, 1.0f);
+ translate_matrix(&matrix, -80.0f, 0.0f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)transformed_geometry[1], &matrix, &transformed_geometry[2]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ set_matrix_identity(&matrix);
+ rotate_matrix(&matrix, M_PI / 2.0f);
+ translate_matrix(&matrix, 80.0f, -320.0f);
+ scale_matrix(&matrix, 2.0f, 0.25f);
+ hr = ID2D1Factory_CreateTransformedGeometry(factory,
+ (ID2D1Geometry *)transformed_geometry[2], &matrix, &transformed_geometry[3]);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ hr = ID2D1Factory_CreateGeometryGroup(factory, D2D1_FILL_MODE_WINDING,
+ (ID2D1Geometry**) &transformed_geometry, 4, &geometry_group);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1TransformedGeometry_Release(transformed_geometry[3]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[2]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[1]);
+ ID2D1TransformedGeometry_Release(transformed_geometry[0]);
+
+ ID2D1RenderTarget_BeginDraw(rt);
+ ID2D1RenderTarget_Clear(rt, &color);
+ ID2D1RenderTarget_FillGeometry(rt, (ID2D1Geometry *)geometry_group, (ID2D1Brush *)brush, NULL);
+ hr = ID2D1RenderTarget_EndDraw(rt, NULL, NULL);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ ID2D1GeometryGroup_Release(geometry_group);
+
+ match = compare_figure(&ctx, 0, 0, 160, 160, 0xff652e89, 32,
+ "zzIBlwEOjQEXiAEahgEahgEahgEahgEahgEahgEahgEahgEahgEahgEahwEZhwEZhwEZhwEZhwEZ"
+ "hwEZhwEZhwEZhwEZhwEZiAEYiAEYiAEXiQEXiQEXiQEXiQEXiQEXigEWigEWigEWigEWigEWigEW"
+ "igEVjAEUjAEUjAEUjQESjgESjwEQkAEQkQEOkgENlAEMlAELlgEKlwEImAEImQEHmQEGmwEFmwEE"
+ "nQEDnQECngECngECngECnwEBnwEBnwEBnwEBngEDnQEDnQEDnQEEmwEFmgEHmQEHlwELkQERjAEX"
+ "hgEdhAEfgwEchwEWjwEMqTEA");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 160, 0, 320, 160, 0xff652e89, 32,
+ "h58BBrUCD6wCGKQCIJsCKZMCMIwCNoUCPf8BQ/kBSPQBTu0BTu4BTfEBSfUBRfkBQf0BPYECOYUC"
+ "NIoCMI4CK+UBAS0W/AEHIweQAgsZBpcCEAwIngIepAIZqQIWrAITsAIRswIOtQIMuAIJuwIHwAIB"
+ "ypwB");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 0, 160, 160, 320, 0xff652e89, 32,
+ "wW4DnAEEmwEFmgEHmAEIlwEKlQELlAEMkwEOkQEPkAEQkAERjgESjgESjQEUjAEUiwEWigEWiQEX"
+ "iQEYhwEZhwEZhgEbhQEbhAEchAEdggEeggEeggEfgAEggAEggAEhgAEggAEggQEggAEggAEggQEf"
+ "gQEggQEfgQEfggEfgQEfgQEfggEfgQEfggEeggEfggEeggEeggEegwEeggEegwEdgwEegwEdgwEd"
+ "hAEchAEdhAEchAEchAEdhAEchAEchQEbhQEbhgEahgEahwEZhwEZiAEYiAEYiQEYiAEYiQEXiQEX"
+ "igEWigEWiwEViwEVjAEUjAEUjAEUjQETjQETjgESjgETjgESjwERkAEQkgEOkwENlAEMlQELlgEK"
+ "lwEJmAEJmAEImQEHmgEGmwEFnAEEnQEEnQEDnQEDngECngEDngECngECnwECngECnwECngECngED"
+ "ngECEgGLAQMQAosBAw4EjAEDCwWNAQQJBo0BBQYIjQEHAgqNARKOARKPARCQARCQARCQAQ+RAQ6S"
+ "AQ6SAQ2TAQ2SAQ2TAQ2TAQyTAQyUAQyTAQyUAQuVAQuUAQuVAQqWAQmWAQqWAQmXAQiXAQiYAQeY"
+ "AQeZAQWbAQSDZwAA");
+ ok(match, "Figure does not match.\n");
+ match = compare_figure(&ctx, 160, 160, 320, 320, 0xff652e89, 32,
+ "g90BBLkCCLYCC7ICDrACEa0CFKoCF6cCGqQCHKMCHqECIJ8CIpwCJJsCJpkCKJcCKZYCK5QCLZIC"
+ "L5ACMI8CMo0CNIsCNYoCN4gCOYcCOYYCO4QCPYICPoECQIACQYACQIECQIACQIECQIECQIECP4IC"
+ "P4ICP4ECP4ICP4ICPoMCPoMCPoMCPYQCPYMCPYQCPYQCPYQCPIUCPIUCPIUCO4YCO4YCOoYCO4YC"
+ "OocCOocCOocCOYgCOYgCOIkCOIkCN4oCNosCNYwCNI0CM44CMo4CM44CMo8CMZACMJECL5ICLpMC"
+ "LZQCLJUCK5YCK5YCKpcCKZgCKJkCJ5oCJpsCJpsCJZwCJJ4CIqACIKICH6MCHaUCG6cCGakCF6wC"
+ "Fa0CE68CEbECD7MCDrQCDLYCCrgCCbkCB7sCBrsCBbwCBbwCBL0CBL0CBL0CBL0CA70CBL0CBL0C"
+ "BLwCBSUBlgIFIQSXAgYbCJcCBxcKmQIIEQ6ZAgoMEJoCDQUTnAIknAIjnQIingIhnwIgoAIfoQIe"
+ "ogIdowIcpAIbpQIapQIZpgIZpgIZpwIYpwIXqAIXqAIXqQIVqgIVqgIUqwITrQISrQIRrgIQsAIO"
+ "sQIMswILtQIIhs4B");
+ ok(match, "Figure does not match.\n");
+
+ hr = ID2D1Factory_CreatePathGeometry(factory, &geometry);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ hr = ID2D1PathGeometry_Open(geometry, &sink);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
set_point(&point, -0.402914f, 0.915514f);
ID2D1GeometrySink_BeginFigure(sink, point, D2D1_FIGURE_BEGIN_HOLLOW);
quadratic_to(sink, -0.310379f, 0.882571f, -0.116057f, 0.824000f);
--
2.45.2

View File

@@ -0,0 +1,279 @@
From be0fbef50483da8fe3fd0c4b74469d15a5c9f1ea Mon Sep 17 00:00:00 2001
From: Philipp Knechtges <philipp-dev@knechtges.com>
Date: Fri, 13 Sep 2024 16:37:31 +0200
Subject: [PATCH] d2d1: Implement drawing for ID2D1GeometryGroup
Drawing of ID2D1GeometryGroup was so far unimplemented and resulted in
blank drawing buffers. This partially fixes the rendering issues mentioned
in the bug below.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51139
---
dlls/d2d1/geometry.c | 236 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 235 insertions(+), 1 deletion(-)
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index 3da3ad2e65b..93925408077 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -5497,8 +5497,13 @@ static const struct ID2D1GeometryGroupVtbl d2d_geometry_group_vtbl =
HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
D2D1_FILL_MODE fill_mode, ID2D1Geometry **geometries, unsigned int geometry_count)
{
- unsigned int i;
+ unsigned int i, j;
+ struct d2d_geometry *other_geom;
+ D2D_MATRIX_3X2_F g, gplain;
+ size_t f_vertex_count, f_face_count, f_bezier_vertex_count, f_arc_vertex_count;
+ size_t o_vertex_count, o_face_count, o_bezier_count, o_bezier_face_count, o_arc_count, o_arc_face_count;
+ FIXME("Ignoring fill_mode=%#x!\n", fill_mode);
d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl);
if (!(geometry->u.group.src_geometries = calloc(geometry_count, sizeof(*geometries))))
@@ -5507,13 +5512,242 @@ HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *fac
return E_OUTOFMEMORY;
}
+ geometry->fill.vertex_count = 0;
+ geometry->fill.face_count = 0;
+ geometry->fill.bezier_vertex_count = 0;
+ geometry->fill.arc_vertex_count = 0;
+ geometry->outline.vertex_count = 0;
+ geometry->outline.face_count = 0;
+ geometry->outline.bezier_count = 0;
+ geometry->outline.bezier_face_count = 0;
+ geometry->outline.arc_count = 0;
+ geometry->outline.arc_face_count = 0;
for (i = 0; i < geometry_count; ++i)
{
ID2D1Geometry_AddRef(geometry->u.group.src_geometries[i] = geometries[i]);
+ other_geom = unsafe_impl_from_ID2D1Geometry(geometries[i]);
+ geometry->fill.vertex_count += other_geom->fill.vertex_count;
+ geometry->fill.face_count += other_geom->fill.face_count;
+ geometry->fill.bezier_vertex_count += other_geom->fill.bezier_vertex_count;
+ geometry->fill.arc_vertex_count += other_geom->fill.arc_vertex_count;
+ geometry->outline.vertex_count += other_geom->outline.vertex_count;
+ geometry->outline.face_count += other_geom->outline.face_count;
+ geometry->outline.bezier_count += other_geom->outline.bezier_count;
+ geometry->outline.bezier_face_count += other_geom->outline.bezier_face_count;
+ geometry->outline.arc_count += other_geom->outline.arc_count;
+ geometry->outline.arc_face_count += other_geom->outline.arc_face_count;
}
geometry->u.group.geometry_count = geometry_count;
geometry->u.group.fill_mode = fill_mode;
+ if (!(geometry->fill.vertices = calloc(geometry->fill.vertex_count, sizeof(D2D1_POINT_2F))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ if (!(geometry->fill.faces = calloc(geometry->fill.face_count, sizeof(struct d2d_face))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->fill.faces_size = geometry->fill.face_count;
+ if (!(geometry->fill.bezier_vertices = calloc(geometry->fill.bezier_vertex_count, sizeof(struct d2d_curve_vertex))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->fill.bezier_vertices_size = geometry->fill.bezier_vertex_count;
+ if (!(geometry->fill.arc_vertices = calloc(geometry->fill.arc_vertex_count, sizeof(struct d2d_curve_vertex))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->fill.arc_vertices_size = geometry->fill.arc_vertex_count;
+ if (!(geometry->outline.vertices = calloc(geometry->outline.vertex_count, sizeof(struct d2d_outline_vertex))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.vertices_size = geometry->outline.vertex_count;
+ if (!(geometry->outline.faces = calloc(geometry->outline.face_count, sizeof(struct d2d_face))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.faces_size = geometry->outline.face_count;
+ if (!(geometry->outline.beziers = calloc(geometry->outline.bezier_count, sizeof(struct d2d_curve_outline_vertex))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.beziers_size = geometry->outline.bezier_count;
+ if (!(geometry->outline.bezier_faces = calloc(geometry->outline.bezier_face_count, sizeof(struct d2d_face))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.bezier_faces_size = geometry->outline.bezier_face_count;
+ if (!(geometry->outline.arcs = calloc(geometry->outline.arc_count, sizeof(struct d2d_curve_outline_vertex))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.arcs_size = geometry->outline.arc_count;
+ if (!(geometry->outline.arc_faces = calloc(geometry->outline.arc_face_count, sizeof(struct d2d_face))))
+ {
+ for (i = 0; i < geometry->u.group.geometry_count; ++i)
+ ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
+ d2d_geometry_cleanup(geometry);
+ return E_OUTOFMEMORY;
+ }
+ geometry->outline.arc_faces_size = geometry->outline.arc_face_count;
+
+ f_vertex_count = 0;
+ f_face_count = 0;
+ f_bezier_vertex_count = 0;
+ f_arc_vertex_count = 0;
+ o_vertex_count = 0;
+ o_face_count = 0;
+ o_bezier_count = 0;
+ o_bezier_face_count = 0;
+ o_arc_count = 0;
+ o_arc_face_count = 0;
+ for (i = 0; i < geometry_count; ++i)
+ {
+ other_geom = unsafe_impl_from_ID2D1Geometry(geometries[i]);
+ g = other_geom->transform;
+ gplain = g;
+ gplain.dx = 0.0f;
+ gplain.dy = 0.0f;
+
+ for (j = 0; j < other_geom->fill.vertex_count; ++j) {
+ d2d_point_transform(&geometry->fill.vertices[j+f_vertex_count], &g,
+ other_geom->fill.vertices[j].x, other_geom->fill.vertices[j].y);
+ }
+ for (j = 0; j < other_geom->fill.face_count; ++j) {
+ geometry->fill.faces[f_face_count+j].v[0] = other_geom->fill.faces[j].v[0]
+ + (UINT16) f_vertex_count;
+ geometry->fill.faces[f_face_count+j].v[1] = other_geom->fill.faces[j].v[1]
+ + (UINT16) f_vertex_count;
+ geometry->fill.faces[f_face_count+j].v[2] = other_geom->fill.faces[j].v[2]
+ + (UINT16) f_vertex_count;
+ }
+ f_vertex_count += other_geom->fill.vertex_count;
+ f_face_count += other_geom->fill.face_count;
+
+ for (j = 0; j < other_geom->fill.bezier_vertex_count; ++j) {
+ d2d_point_transform(&geometry->fill.bezier_vertices[j+f_bezier_vertex_count].position,
+ &g, other_geom->fill.bezier_vertices[j].position.x,
+ other_geom->fill.bezier_vertices[j].position.y);
+ geometry->fill.bezier_vertices[j+f_bezier_vertex_count].texcoord
+ = other_geom->fill.bezier_vertices[j].texcoord;
+ }
+ f_bezier_vertex_count += other_geom->fill.bezier_vertex_count;
+
+ for (j = 0; j < other_geom->fill.arc_vertex_count; ++j) {
+ d2d_point_transform(&geometry->fill.arc_vertices[j+f_arc_vertex_count].position,
+ &g, other_geom->fill.arc_vertices[j].position.x,
+ other_geom->fill.arc_vertices[j].position.y);
+ geometry->fill.arc_vertices[j+f_arc_vertex_count].texcoord
+ = other_geom->fill.arc_vertices[j].texcoord;
+
+ }
+ f_arc_vertex_count += other_geom->fill.arc_vertex_count;
+
+ for (j = 0; j < other_geom->outline.vertex_count; ++j) {
+ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].position, &g,
+ other_geom->outline.vertices[j].position.x, other_geom->outline.vertices[j].position.y);
+ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].prev, &gplain,
+ other_geom->outline.vertices[j].prev.x, other_geom->outline.vertices[j].prev.y);
+ d2d_point_normalise(&geometry->outline.vertices[j+o_vertex_count].prev);
+ d2d_point_transform(&geometry->outline.vertices[j+o_vertex_count].next, &gplain,
+ other_geom->outline.vertices[j].next.x, other_geom->outline.vertices[j].next.y);
+ d2d_point_normalise(&geometry->outline.vertices[j+o_vertex_count].next);
+ }
+ for (j = 0; j < other_geom->outline.face_count; ++j) {
+ geometry->outline.faces[o_face_count+j].v[0] = other_geom->outline.faces[j].v[0]
+ + (UINT16) o_vertex_count;
+ geometry->outline.faces[o_face_count+j].v[1] = other_geom->outline.faces[j].v[1]
+ + (UINT16) o_vertex_count;
+ geometry->outline.faces[o_face_count+j].v[2] = other_geom->outline.faces[j].v[2]
+ + (UINT16) o_vertex_count;
+ }
+ o_vertex_count += other_geom->outline.vertex_count;
+ o_face_count += other_geom->outline.face_count;
+
+ for (j = 0; j < other_geom->outline.bezier_count; ++j) {
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].position, &g,
+ other_geom->outline.beziers[j].position.x, other_geom->outline.beziers[j].position.y);
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].prev, &gplain,
+ other_geom->outline.beziers[j].prev.x, other_geom->outline.beziers[j].prev.y);
+ d2d_point_normalise(&geometry->outline.beziers[j+o_bezier_count].prev);
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].next, &gplain,
+ other_geom->outline.beziers[j].next.x, other_geom->outline.beziers[j].next.y);
+ d2d_point_normalise(&geometry->outline.beziers[j+o_bezier_count].next);
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p0, &g,
+ other_geom->outline.beziers[j].p0.x, other_geom->outline.beziers[j].p0.y);
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p1, &g,
+ other_geom->outline.beziers[j].p1.x, other_geom->outline.beziers[j].p1.y);
+ d2d_point_transform(&geometry->outline.beziers[j+o_bezier_count].p2, &g,
+ other_geom->outline.beziers[j].p2.x, other_geom->outline.beziers[j].p2.y);
+ }
+ for (j = 0; j < other_geom->outline.bezier_face_count; ++j) {
+ geometry->outline.bezier_faces[o_bezier_face_count+j].v[0]
+ = other_geom->outline.bezier_faces[j].v[0] + (UINT16) o_bezier_count;
+ geometry->outline.bezier_faces[o_bezier_face_count+j].v[1]
+ = other_geom->outline.bezier_faces[j].v[1] + (UINT16) o_bezier_count;
+ geometry->outline.bezier_faces[o_bezier_face_count+j].v[2]
+ = other_geom->outline.bezier_faces[j].v[2] + (UINT16) o_bezier_count;
+ }
+ o_bezier_count += other_geom->outline.bezier_count;
+ o_bezier_face_count += other_geom->outline.bezier_face_count;
+
+ for (j = 0; j < other_geom->outline.arc_count; ++j) {
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].position, &g,
+ other_geom->outline.arcs[j].position.x, other_geom->outline.arcs[j].position.y);
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].prev, &gplain,
+ other_geom->outline.arcs[j].prev.x, other_geom->outline.arcs[j].prev.y);
+ d2d_point_normalise(&geometry->outline.arcs[j+o_arc_count].prev);
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].next, &gplain,
+ other_geom->outline.arcs[j].next.x, other_geom->outline.arcs[j].next.y);
+ d2d_point_normalise(&geometry->outline.arcs[j+o_arc_count].next);
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p0, &g,
+ other_geom->outline.arcs[j].p0.x, other_geom->outline.arcs[j].p0.y);
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p1, &g,
+ other_geom->outline.arcs[j].p1.x, other_geom->outline.arcs[j].p1.y);
+ d2d_point_transform(&geometry->outline.arcs[j+o_arc_count].p2, &g,
+ other_geom->outline.arcs[j].p2.x, other_geom->outline.arcs[j].p2.y);
+ }
+ for (j = 0; j < other_geom->outline.arc_face_count; ++j) {
+ geometry->outline.arc_faces[o_arc_face_count+j].v[0]
+ = other_geom->outline.arc_faces[j].v[0] + (UINT16) o_arc_count;
+ geometry->outline.arc_faces[o_arc_face_count+j].v[1]
+ = other_geom->outline.arc_faces[j].v[1] + (UINT16) o_arc_count;
+ geometry->outline.arc_faces[o_arc_face_count+j].v[2]
+ = other_geom->outline.arc_faces[j].v[2] + (UINT16) o_arc_count;
+ }
+ o_arc_count += other_geom->outline.arc_count;
+ o_arc_face_count += other_geom->outline.arc_face_count;
+ }
+
return S_OK;
}
--
2.45.2

View File

@@ -0,0 +1,3 @@
Fixes: [51139] d2d1: Implement drawing of ID2D1GeometryGroup
# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6492

View File

@@ -0,0 +1,24 @@
From 252a1d6bb99c83ce8a0289fbd1f4fe135e2c55cd Mon Sep 17 00:00:00 2001
From: Torge Matthies <tmatthies@codeweavers.com>
Date: Fri, 25 Oct 2024 13:19:02 +0200
Subject: [PATCH] include: Add MFNETSOURCE_STATISTICS_SERVICE definition.
---
include/mfidl.idl | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/mfidl.idl b/include/mfidl.idl
index 666af53c6e3..a8c5af05e68 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -1626,6 +1626,7 @@ cpp_quote("EXTERN_GUID(MR_STREAM_VOLUME_SERVICE, 0xf8b5fa2f, 0x32ef, 0x46f5, 0xb
cpp_quote("EXTERN_GUID(MR_AUDIO_POLICY_SERVICE, 0x911fd737, 0x6775, 0x4ab0, 0xa6, 0x14, 0x29, 0x78, 0x62, 0xfd, 0xac, 0x88);")
cpp_quote("EXTERN_GUID(MF_PROPERTY_HANDLER_SERVICE, 0xa3face02, 0x32b8, 0x41dd, 0x90, 0xe7, 0x5f, 0xef, 0x7c, 0x89, 0x91, 0xb5);")
cpp_quote("EXTERN_GUID(MF_WORKQUEUE_SERVICES, 0x8e37d489, 0x41e0, 0x413a, 0x90, 0x68, 0x28, 0x7c, 0x88, 0x6d, 0x8d, 0xda);")
+cpp_quote("EXTERN_GUID(MFNETSOURCE_STATISTICS_SERVICE, 0x3cb1f275, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1);")
cpp_quote("EXTERN_GUID(MF_PROGRESSIVE_CODING_CONTENT, 0x8f020eea, 0x1508, 0x471f, 0x9d, 0xa6, 0x50, 0x7d, 0x7c, 0xfa, 0x40, 0xdb);")
cpp_quote("EXTERN_GUID(MF_NALU_LENGTH_SET, 0xa7911d53, 0x12a4, 0x4965, 0xae, 0x70, 0x6e, 0xad, 0xd6, 0xff, 0x05, 0x51);")
--
2.45.2

View File

@@ -0,0 +1,383 @@
From 0d4a7cf6b9bb3a57a098762113ca1750c43a810e Mon Sep 17 00:00:00 2001
From: Torge Matthies <tmatthies@codeweavers.com>
Date: Fri, 25 Oct 2024 10:47:30 +0200
Subject: [PATCH] mf/tests: Add network bytestream tests.
---
dlls/mf/tests/mf.c | 347 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 347 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index d0f1f1cf0a4..61daaf35741 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -4726,6 +4726,7 @@ static void test_evr(void)
hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ if (!sink) return;
check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
check_interface(sink, &IID_IMFVideoRenderer, TRUE);
@@ -6803,6 +6804,351 @@ static void test_media_session_Close(void)
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
}
+static void test_network_bytestream(void)
+{
+ static const WCHAR *URL = L"http://test.winehq.org/tests/test.mp3";
+ static const WCHAR *EFFECTIVE_URL = L"http://test.winehq.org:80/tests/test.mp3";
+ static const WCHAR *CONTENT_TYPE = L"audio/mpeg";
+ static const BYTE LAST_MODIFIED_TIME[] = { 0x00, 0x3b, 0x4b, 0xbf, 0x05, 0x80, 0xd8, 0x01 };
+
+ IMFSourceResolver *resolver;
+ IUnknown *object = NULL, *bs = NULL;
+ MF_OBJECT_TYPE obj_type;
+ HRESULT hr;
+ void *ptr;
+
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
+
+ hr = MFCreateSourceResolver(&resolver);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+
+ if (object) IUnknown_Release(object);
+
+ obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
+ object = NULL;
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://nonexistent.url/file.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object);
+ todo_wine
+ ok(hr == NS_E_SERVER_NOT_FOUND, "Got hr %#lx.\n", hr);
+ ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type);
+ if (object) IUnknown_Release(object);
+
+ obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
+ object = NULL;
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object);
+ todo_wine
+ ok(hr == NS_E_FILE_NOT_FOUND, "Got hr %#lx.\n", hr);
+ todo_wine
+ ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type);
+ if (object) IUnknown_Release(object);
+
+ obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
+ object = NULL;
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, URL, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(obj_type == MF_OBJECT_BYTESTREAM, "Unexpected obj_type %#x.\n", obj_type);
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IMFAttributes, &ptr);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ IMFAttributes *attr = ptr;
+ UINT32 count = 0;
+ PROPVARIANT var;
+ GUID key = {0};
+
+ hr = IMFAttributes_GetCount(attr, &count);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ todo_wine
+ ok(count == 3, "count = %u\n", count);
+
+ PropVariantInit(&var);
+
+ hr = IMFAttributes_GetItemByIndex(attr, 0, &key, &var);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ ok(IsEqualGUID(&key, &MF_BYTESTREAM_EFFECTIVE_URL), "Got key %s\n", debugstr_guid(&key));
+ ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt);
+ todo_wine
+ ok(!lstrcmpW(var.pwszVal, EFFECTIVE_URL), "Got value %s\n", var.pszVal);
+ memset(&key, 0, sizeof(key));
+ PropVariantClear(&var);
+
+ hr = IMFAttributes_GetItemByIndex(attr, 1, &key, &var);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ ok(IsEqualGUID(&key, &MF_BYTESTREAM_CONTENT_TYPE), "Got key %s\n", debugstr_guid(&key));
+ ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt);
+ todo_wine
+ ok(!lstrcmpW(var.pwszVal, CONTENT_TYPE), "Got value %s\n", var.pszVal);
+ memset(&key, 0, sizeof(key));
+ PropVariantClear(&var);
+
+ hr = IMFAttributes_GetItemByIndex(attr, 2, &key, &var);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ todo_wine
+ ok(IsEqualGUID(&key, &MF_BYTESTREAM_LAST_MODIFIED_TIME), "Got key %s\n", debugstr_guid(&key));
+ todo_wine
+ ok(var.vt == (VT_VECTOR | VT_I1 | VT_NULL), "Got type %d\n", var.vt);
+ todo_wine
+ ok(var.blob.cbSize == sizeof(LAST_MODIFIED_TIME), "Got size %lu\n", var.blob.cbSize);
+ todo_wine
+ ok(var.blob.pBlobData != NULL, "Got NULL value\n");
+ if (var.blob.cbSize == sizeof(LAST_MODIFIED_TIME) && var.blob.pBlobData)
+ ok(!memcmp(var.blob.pBlobData, LAST_MODIFIED_TIME, sizeof(LAST_MODIFIED_TIME)), "Got wrong value\n");
+ memset(&key, 0, sizeof(key));
+ PropVariantClear(&var);
+
+ hr = IMFAttributes_GetItemByIndex(attr, 3, &key, &var);
+ ok(hr == E_INVALIDARG, "Got hr %#lx\n", hr);
+ ok(IsEqualGUID(&key, &GUID_NULL), "Got key %s\n", debugstr_guid(&key));
+ ok(var.vt == VT_EMPTY, "Got type %d\n", var.vt);
+ memset(&key, 0, sizeof(key));
+ PropVariantClear(&var);
+
+ IUnknown_Release((IUnknown *)ptr);
+ }
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamCacheControl, &ptr);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ todo_wine
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ IMFByteStreamCacheControl *ctrl = ptr;
+ HRESULT hr;
+
+ hr = IMFByteStreamCacheControl_StopBackgroundTransfer(ctrl);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ IMFByteStreamCacheControl_Release(ctrl);
+ }
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamBuffering, &ptr);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ todo_wine
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ MFBYTESTREAM_BUFFERING_PARAMS params = {0};
+ IMFByteStreamBuffering *buffering = ptr;
+ MF_LEAKY_BUCKET_PAIR bucket = {0};
+ HRESULT hr;
+
+ hr = IMFByteStreamBuffering_StopBuffering(buffering);
+ ok(hr == S_FALSE, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamBuffering_EnableBuffering(buffering, FALSE);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamBuffering_EnableBuffering(buffering, TRUE);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamBuffering_StopBuffering(buffering);
+ ok(hr == S_OK || hr == S_FALSE, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, NULL);
+ ok(hr == E_INVALIDARG, "Got hr %#lx\n", hr);
+
+ params.cbTotalFileSize = -1;
+ params.cbPlayableDataSize = -1;
+ params.prgBuckets = NULL;
+ params.cBuckets = 0;
+ params.qwNetBufferingTime = 0;
+ params.qwExtraBufferingTimeDuringSeek = 0;
+ params.qwPlayDuration = 0;
+ params.dRate = 1.0f;
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, &params);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ params.cBuckets = 1;
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, &params);
+ ok(hr == E_INVALIDARG, "Got hr %#lx\n", hr);
+
+ params.prgBuckets = &bucket;
+ bucket.dwBitrate = 0;
+ bucket.msBufferWindow = 0;
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, &params);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ params.cbTotalFileSize = 0xdeadbeef;
+ params.cbPlayableDataSize = 0xdeadbeef;
+ bucket.dwBitrate = 0xdeadbeef;
+ bucket.msBufferWindow = 0xdeadbeef;
+ params.qwNetBufferingTime = 0xdeadbeef;
+ params.qwExtraBufferingTimeDuringSeek = 0xdeadbeef;
+ params.qwPlayDuration = 0xdeadbeef;
+ params.dRate = 12345.0f;
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, &params);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamBuffering_EnableBuffering(buffering, TRUE);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+
+ IMFByteStreamBuffering_Release(buffering);
+ }
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamTimeSeek, &ptr);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ todo_wine
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ QWORD start_time = 0xdeadbeef, stop_time = 0xdeadbef0, duration = 0xdeadbef1;
+ IMFByteStreamTimeSeek *seek = ptr;
+ BOOL b = 0xdeadbeef;
+ HRESULT hr;
+
+ hr = IMFByteStreamTimeSeek_GetTimeSeekResult(seek, NULL, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamTimeSeek_GetTimeSeekResult(seek, &start_time, &stop_time, &duration);
+ ok(hr == MF_E_INVALIDREQUEST, "Got hr %#lx\n", hr);
+ ok(start_time == 0, "start_time = %I64u\n", start_time);
+ ok(stop_time == 0, "stop_time = %I64u\n", stop_time);
+ ok(duration == 0, "duration = %I64u\n", duration);
+
+ hr = IMFByteStreamTimeSeek_IsTimeSeekSupported(seek, NULL);
+ ok(hr == S_FALSE, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamTimeSeek_IsTimeSeekSupported(seek, &b);
+ ok(hr == S_FALSE, "Got hr %#lx\n", hr);
+ ok(!b, "supported = %x\n", b);
+
+ hr = IMFByteStreamTimeSeek_TimeSeek(seek, 0);
+ ok(hr == MF_E_INVALIDREQUEST, "Got hr %#lx\n", hr);
+
+ hr = IMFByteStreamTimeSeek_GetTimeSeekResult(seek, &start_time, &stop_time, &duration);
+ ok(hr == MF_E_INVALIDREQUEST, "Got hr %#lx\n", hr);
+ ok(start_time == 0, "start_time = %I64u\n", start_time);
+ ok(stop_time == 0, "stop_time = %I64u\n", stop_time);
+ ok(duration == 0, "duration = %I64u\n", duration);
+
+ IMFByteStreamTimeSeek_Release(seek);
+ }
+
+ {
+ BYTE *tmp = malloc(8192);
+ ULONG read = 0, written = 0;
+ QWORD len = 0;
+
+ hr = IMFByteStream_SetLength((IMFByteStream*)object, 1000);
+ ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
+
+ hr = IMFByteStream_SetCurrentPosition((IMFByteStream*)object, 1000);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IMFByteStream_Read((IMFByteStream*)object, tmp, 8192, &read);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(read == 3365, "read = %lu\n", read);
+
+ hr = IMFByteStream_SetCurrentPosition((IMFByteStream*)object, 1000);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ hr = IMFByteStream_Write((IMFByteStream*)object, tmp, 1000, &written);
+ ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
+ ok(written == 0, "written = %lu\n", written);
+
+ free(tmp);
+
+ hr = IMFByteStream_GetLength((IMFByteStream*)object, &len);
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ ok(len != 0, "len = %I64u\n", len);
+
+ hr = IMFByteStream_Flush((IMFByteStream*)object);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
+ }
+
+ ptr = NULL;
+ hr = MFGetService(object, &MFNETSOURCE_STATISTICS_SERVICE, &IID_IPropertyStore, &ptr);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ IPropertyStore *pstore = ptr;
+ DWORD count = 0;
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IPropertyStore, &ptr);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(ptr == (void *)pstore, "Got different IPropertyStore: %p != %p.\n", ptr, pstore);
+ IPropertyStore_Release((IPropertyStore *)ptr);
+
+ hr = IPropertyStore_GetCount(pstore, &count);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ ok(count == 0, "Got count %lu.\n", count);
+
+ IPropertyStore_Release(pstore);
+ }
+
+ ptr = NULL;
+ hr = IUnknown_QueryInterface(object, &IID_IMFMediaEventGenerator, &ptr);
+ todo_wine
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ todo_wine
+ ok(ptr != NULL, "Got NULL ptr.\n");
+ if (SUCCEEDED(hr) && ptr)
+ {
+ IMFMediaEvent *evt = (void *)(DWORD_PTR)0xdeadbeef;
+ BOOL seen_caps_changed = FALSE, buffering = FALSE;
+ IMFMediaEventGenerator *gen = ptr;
+ MediaEventType type;
+ HRESULT hr;
+
+ while (SUCCEEDED(hr = IMFMediaEventGenerator_GetEvent(gen, MF_EVENT_FLAG_NO_WAIT, &evt)))
+ {
+ type = (MediaEventType)0xdeadbeef;
+ hr = IMFMediaEvent_GetType(evt, &type);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+
+ if (type == MEByteStreamCharacteristicsChanged)
+ {
+ ok(!seen_caps_changed, "got multiple MEByteStreamCharacteristicsChanged events\n");
+ seen_caps_changed = TRUE;
+ }
+ else if (type == MEBufferingStarted)
+ {
+ ok(!buffering, "got MEBufferingStopped without MEBufferingStarted\n");
+ buffering = TRUE;
+ }
+ else if (type == MEBufferingStopped)
+ buffering = FALSE;
+ else
+ ok(0, "Unexpected event type %#lx\n", type);
+
+ IMFMediaEvent_Release(evt);
+ }
+ ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Got hr %#lx.\n", hr);
+
+ IMFMediaEventGenerator_Release(gen);
+ }
+
+ obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
+ bs = NULL;
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, (void *)object, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, &obj_type, &bs);
+ ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ ok(obj_type == MF_OBJECT_MEDIASOURCE, "Unexpected obj_type %#x.\n", obj_type);
+
+ if (bs) IUnknown_Release(bs);
+ if (object) IUnknown_Release(object);
+
+ IMFSourceResolver_Release(resolver);
+
+ hr = MFShutdown();
+ ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
+}
+
START_TEST(mf)
{
init_functions();
@@ -6838,5 +7184,6 @@ START_TEST(mf)
test_media_session_Start();
test_MFEnumDeviceSources();
test_media_session_Close();
+ test_network_bytestream();
test_media_session_source_shutdown();
}
--
2.45.2

View File

@@ -0,0 +1,346 @@
From 68227ee19646a7c98f1b1e6eed72a7a6a2a21fc1 Mon Sep 17 00:00:00 2001
From: Torge Matthies <tmatthies@codeweavers.com>
Date: Fri, 25 Oct 2024 10:47:31 +0200
Subject: [PATCH] mf: Implement and use HttpSchemePlugin.
---
dlls/mf/main.c | 2 ++
dlls/mf/mf.idl | 6 ++++++
dlls/mf/mf.rgs | 16 ++++++++++++++--
dlls/mf/mf_private.h | 1 +
dlls/mf/scheme_handler.c | 33 +++++++++++++++++++++++++++++++++
dlls/mf/tests/mf.c | 38 ++++----------------------------------
dlls/mfplat/mfplat.spec | 3 +++
dlls/mfplat/network.c | 5 +++++
8 files changed, 68 insertions(+), 36 deletions(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c
index e74a4ae8e4c..120343a1be2 100644
--- a/dlls/mf/main.c
+++ b/dlls/mf/main.c
@@ -549,6 +549,7 @@ static const IClassFactoryVtbl class_factory_vtbl =
};
static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
+static struct class_factory http_scheme_handler_factory = { { &class_factory_vtbl }, http_scheme_handler_construct };
static struct class_factory urlmon_scheme_handler_factory = { { &class_factory_vtbl }, urlmon_scheme_handler_construct };
static const struct class_object
@@ -559,6 +560,7 @@ static const struct class_object
class_objects[] =
{
{ &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
+ { &CLSID_HttpSchemePlugin, &http_scheme_handler_factory.IClassFactory_iface },
{ &CLSID_UrlmonSchemePlugin, &urlmon_scheme_handler_factory.IClassFactory_iface },
};
diff --git a/dlls/mf/mf.idl b/dlls/mf/mf.idl
index 4f5ef36c965..ca05a991ca9 100644
--- a/dlls/mf/mf.idl
+++ b/dlls/mf/mf.idl
@@ -25,6 +25,12 @@
]
coclass FileSchemePlugin { }
+[
+ threading(both),
+ uuid(44cb442b-9da9-49df-b3fd-023777b16e50)
+]
+coclass HttpSchemePlugin {}
+
[
threading(both),
uuid(9ec4b4f9-3029-45ad-947b-344de2a249e2)
diff --git a/dlls/mf/mf.rgs b/dlls/mf/mf.rgs
index f06576baccb..778b07e65ed 100644
--- a/dlls/mf/mf.rgs
+++ b/dlls/mf/mf.rgs
@@ -14,11 +14,23 @@ HKLM
}
'http:'
{
- val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler'
+ val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler'
}
'https:'
{
- val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler'
+ val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler'
+ }
+ 'httpd:'
+ {
+ val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler'
+ }
+ 'httpsd:'
+ {
+ val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler'
+ }
+ 'mms:'
+ {
+ val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler'
}
}
}
diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h
index 1f2ef17a8c9..adb35e14194 100644
--- a/dlls/mf/mf_private.h
+++ b/dlls/mf/mf_private.h
@@ -114,6 +114,7 @@ static inline const char *debugstr_propvar(const PROPVARIANT *v)
}
extern HRESULT file_scheme_handler_construct(REFIID riid, void **obj);
+extern HRESULT http_scheme_handler_construct(REFIID riid, void **obj);
extern HRESULT urlmon_scheme_handler_construct(REFIID riid, void **obj);
extern BOOL mf_is_sample_copier_transform(IMFTransform *transform);
diff --git a/dlls/mf/scheme_handler.c b/dlls/mf/scheme_handler.c
index 7e92748aeb9..3cd16319b2a 100644
--- a/dlls/mf/scheme_handler.c
+++ b/dlls/mf/scheme_handler.c
@@ -483,6 +483,39 @@ HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
return hr;
}
+WINAPI HRESULT __wine_create_http_bytestream(const WCHAR *url, void **out);
+
+static HRESULT http_stream_create(const WCHAR *url, DWORD flags, IMFByteStream **out)
+{
+ if (flags & MF_RESOLUTION_WRITE)
+ return E_INVALIDARG;
+
+ return __wine_create_http_bytestream(url, (void **)out);
+}
+
+HRESULT http_scheme_handler_construct(REFIID riid, void **obj)
+{
+ struct scheme_handler *handler;
+ HRESULT hr;
+
+ TRACE("%s, %p.\n", debugstr_guid(riid), obj);
+
+ if (!(handler = calloc(1, sizeof(*handler))))
+ return E_OUTOFMEMORY;
+
+ handler->IMFSchemeHandler_iface.lpVtbl = &scheme_handler_vtbl;
+ handler->IMFAsyncCallback_iface.lpVtbl = &scheme_handler_callback_vtbl;
+ handler->refcount = 1;
+ list_init(&handler->results);
+ InitializeCriticalSection(&handler->cs);
+ handler->create_stream = http_stream_create;
+
+ hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
+ IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
+
+ return hr;
+}
+
static HRESULT urlmon_stream_create(const WCHAR *url, DWORD flags, IMFByteStream **out)
{
IMFAttributes *attributes;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 61daaf35741..39dfe3ca1b2 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -5384,7 +5384,6 @@ static void test_scheme_resolvers(void)
for (i = 0; i < ARRAY_SIZE(urls); i++)
{
hr = IMFSourceResolver_CreateObjectFromURL(resolver, urls[i], MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine_if(i >= 2)
ok(hr == S_OK, "got hr %#lx\n", hr);
if (hr != S_OK)
continue;
@@ -5408,7 +5407,6 @@ static void test_scheme_resolvers(void)
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_CONTENT_TYPE, NULL);
ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_LAST_MODIFIED_TIME, NULL);
- todo_wine
ok(hr == S_OK, "got hr %#lx\n", hr);
IMFAttributes_Release(attributes);
@@ -5416,8 +5414,7 @@ static void test_scheme_resolvers(void)
ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFByteStream_GetCapabilities(byte_stream, &caps);
ok(hr == S_OK, "got hr %#lx\n", hr);
- todo_wine
- ok(caps == (expect_caps | MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED)
+ ok(caps == expect_caps || caps == (expect_caps | MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED)
|| caps == (expect_caps | MFBYTESTREAM_DOES_NOT_USE_NETWORK),
"got caps %#lx\n", caps);
hr = IMFByteStream_GetLength(byte_stream, &length);
@@ -5436,35 +5433,25 @@ static void test_scheme_resolvers(void)
ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == NS_E_SERVER_NOT_FOUND, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"https://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpsd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"mms://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"https://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpsd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr);
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"mms://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
- todo_wine
ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got hr %#lx\n", hr);
IMFSourceResolver_Release(resolver);
@@ -6828,7 +6815,6 @@ static void test_network_bytestream(void)
obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
object = NULL;
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://nonexistent.url/file.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object);
- todo_wine
ok(hr == NS_E_SERVER_NOT_FOUND, "Got hr %#lx.\n", hr);
ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type);
if (object) IUnknown_Release(object);
@@ -6836,9 +6822,7 @@ static void test_network_bytestream(void)
obj_type = (MF_OBJECT_TYPE)0xdeadbeef;
object = NULL;
hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object);
- todo_wine
ok(hr == NS_E_FILE_NOT_FOUND, "Got hr %#lx.\n", hr);
- todo_wine
ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type);
if (object) IUnknown_Release(object);
@@ -6861,7 +6845,6 @@ static void test_network_bytestream(void)
hr = IMFAttributes_GetCount(attr, &count);
ok(hr == S_OK, "Got hr %#lx\n", hr);
- todo_wine
ok(count == 3, "count = %u\n", count);
PropVariantInit(&var);
@@ -6870,7 +6853,6 @@ static void test_network_bytestream(void)
ok(hr == S_OK, "Got hr %#lx\n", hr);
ok(IsEqualGUID(&key, &MF_BYTESTREAM_EFFECTIVE_URL), "Got key %s\n", debugstr_guid(&key));
ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt);
- todo_wine
ok(!lstrcmpW(var.pwszVal, EFFECTIVE_URL), "Got value %s\n", var.pszVal);
memset(&key, 0, sizeof(key));
PropVariantClear(&var);
@@ -6879,21 +6861,15 @@ static void test_network_bytestream(void)
ok(hr == S_OK, "Got hr %#lx\n", hr);
ok(IsEqualGUID(&key, &MF_BYTESTREAM_CONTENT_TYPE), "Got key %s\n", debugstr_guid(&key));
ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt);
- todo_wine
ok(!lstrcmpW(var.pwszVal, CONTENT_TYPE), "Got value %s\n", var.pszVal);
memset(&key, 0, sizeof(key));
PropVariantClear(&var);
hr = IMFAttributes_GetItemByIndex(attr, 2, &key, &var);
- todo_wine
ok(hr == S_OK, "Got hr %#lx\n", hr);
- todo_wine
ok(IsEqualGUID(&key, &MF_BYTESTREAM_LAST_MODIFIED_TIME), "Got key %s\n", debugstr_guid(&key));
- todo_wine
ok(var.vt == (VT_VECTOR | VT_I1 | VT_NULL), "Got type %d\n", var.vt);
- todo_wine
ok(var.blob.cbSize == sizeof(LAST_MODIFIED_TIME), "Got size %lu\n", var.blob.cbSize);
- todo_wine
ok(var.blob.pBlobData != NULL, "Got NULL value\n");
if (var.blob.cbSize == sizeof(LAST_MODIFIED_TIME) && var.blob.pBlobData)
ok(!memcmp(var.blob.pBlobData, LAST_MODIFIED_TIME, sizeof(LAST_MODIFIED_TIME)), "Got wrong value\n");
@@ -6912,9 +6888,7 @@ static void test_network_bytestream(void)
ptr = NULL;
hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamCacheControl, &ptr);
- todo_wine
ok(hr == S_OK, "Got hr %#lx.\n", hr);
- todo_wine
ok(ptr != NULL, "Got NULL ptr.\n");
if (SUCCEEDED(hr) && ptr)
{
@@ -6929,9 +6903,7 @@ static void test_network_bytestream(void)
ptr = NULL;
hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamBuffering, &ptr);
- todo_wine
ok(hr == S_OK, "Got hr %#lx.\n", hr);
- todo_wine
ok(ptr != NULL, "Got NULL ptr.\n");
if (SUCCEEDED(hr) && ptr)
{
@@ -6998,9 +6970,7 @@ static void test_network_bytestream(void)
ptr = NULL;
hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamTimeSeek, &ptr);
- todo_wine
ok(hr == S_OK, "Got hr %#lx.\n", hr);
- todo_wine
ok(ptr != NULL, "Got NULL ptr.\n");
if (SUCCEEDED(hr) && ptr)
{
@@ -7059,6 +7029,9 @@ static void test_network_bytestream(void)
ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
ok(written == 0, "written = %lu\n", written);
+ hr = IMFByteStream_BeginWrite((IMFByteStream*)object, tmp, 1000, (void *)(DWORD_PTR)0xdeadbeef, NULL);
+ ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
+
free(tmp);
hr = IMFByteStream_GetLength((IMFByteStream*)object, &len);
@@ -7066,7 +7039,6 @@ static void test_network_bytestream(void)
ok(len != 0, "len = %I64u\n", len);
hr = IMFByteStream_Flush((IMFByteStream*)object);
- todo_wine
ok(hr == S_OK, "Got hr %#lx\n", hr);
}
@@ -7094,9 +7066,7 @@ static void test_network_bytestream(void)
ptr = NULL;
hr = IUnknown_QueryInterface(object, &IID_IMFMediaEventGenerator, &ptr);
- todo_wine
ok(hr == S_OK, "Got hr %#lx.\n", hr);
- todo_wine
ok(ptr != NULL, "Got NULL ptr.\n");
if (SUCCEEDED(hr) && ptr)
{
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 7b356f9f457..f55f49b7e8c 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -181,3 +181,6 @@
@ stdcall -ret64 MFllMulDiv(int64 int64 int64 int64)
@ stub PropVariantFromStream
@ stub PropVariantToStream
+
+# Wine extension
+@ stdcall __wine_create_http_bytestream(wstr ptr)
diff --git a/dlls/mfplat/network.c b/dlls/mfplat/network.c
index d9a2981f5a7..2369dbf31fd 100644
--- a/dlls/mfplat/network.c
+++ b/dlls/mfplat/network.c
@@ -2012,3 +2012,8 @@ error:
hr = MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
return hr;
}
+
+WINAPI HRESULT __wine_create_http_bytestream(const WCHAR *url, void **out)
+{
+ return create_http_bytestream(url, out);
+}
--
2.45.2

View File

@@ -0,0 +1,5 @@
Fixes: [52769] mf: Add HTTP/HTTPS IMFByteStream implementation.
# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6733
# Game: The good life.

View File

@@ -1,4 +1,4 @@
From e062c6f139f716fe0e95a26e5016aa4f94087146 Mon Sep 17 00:00:00 2001
From db45e866f5d465e7da2e283e0fa97594fff7d6e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 17 Jan 2016 00:50:50 +0100
Subject: [PATCH] ntdll/tests: Add basic tests for RtlQueryPackageIdentity.
@@ -20,10 +20,10 @@ index 3742968c415..084469a2820 100644
SOURCES = \
atom.c \
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index d013848c07a..f239575d13e 100644
index eaee2768c6a..544744dd8e6 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -37,6 +37,9 @@
@@ -38,6 +38,9 @@
#include "wine/test.h"
#include "wine/asm.h"
#include "wine/rbtree.h"
@@ -33,9 +33,9 @@ index d013848c07a..f239575d13e 100644
#ifndef __WINE_WINTERNL_H
@@ -105,6 +108,9 @@ static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION
static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG);
static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char *);
@@ -118,6 +121,9 @@ static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char *);
static void * (WINAPI *pRtlLookupElementGenericTable)(PRTL_GENERIC_TABLE, void *);
static ULONG (WINAPI *pRtlNumberGenericTableElements)(PRTL_GENERIC_TABLE);
static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *);
+static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*);
+static NTSTATUS (WINAPI *pRtlMakeSelfRelativeSD)(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,LPDWORD);
@@ -43,9 +43,9 @@ index d013848c07a..f239575d13e 100644
static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **);
static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
static VOID (WINAPI *pRtlGetDeviceFamilyInfoEnum)(ULONGLONG *,DWORD *,DWORD *);
@@ -152,6 +158,9 @@ static void InitFunctionPtrs(void)
pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx");
pRtlFindExportedRoutineByName = (void *)GetProcAddress(hntdll, "RtlFindExportedRoutineByName");
@@ -185,6 +191,9 @@ static void InitFunctionPtrs(void)
pRtlLookupElementGenericTable = (void *)GetProcAddress(hntdll, "RtlLookupElementGenericTable");
pRtlNumberGenericTableElements = (void *)GetProcAddress(hntdll, "RtlNumberGenericTableElements");
pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules");
+ pRtlQueryPackageIdentity = (void *)GetProcAddress(hntdll, "RtlQueryPackageIdentity");
+ pRtlMakeSelfRelativeSD = (void *)GetProcAddress(hntdll, "RtlMakeSelfRelativeSD");
@@ -53,7 +53,7 @@ index d013848c07a..f239575d13e 100644
pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification");
pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification");
pRtlGetDeviceFamilyInfoEnum = (void *)GetProcAddress(hntdll, "RtlGetDeviceFamilyInfoEnum");
@@ -3714,6 +3723,76 @@ static void test_RtlFirstFreeAce(void)
@@ -3756,6 +3765,76 @@ static void test_RtlFirstFreeAce(void)
HeapFree(GetProcessHeap(), 0, acl);
}
@@ -130,7 +130,7 @@ index d013848c07a..f239575d13e 100644
static void test_RtlInitializeSid(void)
{
SID_IDENTIFIER_AUTHORITY sid_ident = { SECURITY_NT_AUTHORITY };
@@ -3970,6 +4049,7 @@ START_TEST(rtl)
@@ -5189,6 +5268,7 @@ START_TEST(rtl)
test_RtlInitializeCriticalSectionEx();
test_RtlLeaveCriticalSection();
test_LdrEnumerateLoadedModules();
@@ -139,5 +139,5 @@ index d013848c07a..f239575d13e 100644
test_LdrRegisterDllNotification();
test_DbgPrint();
--
2.45.2
2.47.2

View File

@@ -0,0 +1,26 @@
From e27947e6cd77f408bf8586456b19c1ff2e41eea4 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Fri, 24 Jan 2025 20:15:24 +1100
Subject: [PATCH] oleaut32: VarAnd use VT_I4 when converting VT_BSTR
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56280
---
dlls/oleaut32/variant.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index bb1e83e9b7e..ba6db0adf62 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -3114,7 +3114,7 @@ HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
hres = VariantChangeType(&varLeft,&varLeft,
VARIANT_LOCALBOOL, VT_BOOL);
if (SUCCEEDED(hres) && V_VT(&varLeft) != resvt)
- hres = VariantChangeType(&varLeft,&varLeft,0,resvt);
+ hres = VariantChangeType(&varLeft,&varLeft,0, VT_I4);
if (FAILED(hres)) goto VarAnd_Exit;
}
--
2.45.2

View File

@@ -0,0 +1,2 @@
Fixes: [56280] oleaut32: VarAnd use VT_I4 when converting VT_BSTR

View File

@@ -0,0 +1,489 @@
From 852060d5a6f4b665482898855924608c3c995eed Mon Sep 17 00:00:00 2001
From: Damjan Jovanovic <damjan.jov@gmail.com>
Date: Mon, 6 Jan 2025 16:22:52 +1100
Subject: [PATCH] riched20: Implement IRichEditOle::ImportDataObject
---
dlls/riched20/richole.c | 67 ++++++-
dlls/riched20/tests/richole.c | 361 ++++++++++++++++++++++++++++++++++
2 files changed, 426 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 51ae41d2fe7..5771c97cd77 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -1345,13 +1345,76 @@ IRichEditOle_fnHandsOffStorage(IRichEditOle *iface, LONG iob)
return E_NOTIMPL;
}
+static HRESULT import_dataobject(struct text_services *services, LPDATAOBJECT lpdataobj, CLIPFORMAT cf)
+{
+ HRESULT hr;
+ IDataObject *dataobject;
+ FORMATETC fmtetc;
+ STGMEDIUM medium;
+
+ if (lpdataobj != NULL)
+ dataobject = lpdataobj;
+ else
+ {
+ hr = OleGetClipboard(&dataobject);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ fmtetc.cfFormat = cf;
+ fmtetc.ptd = NULL;
+ fmtetc.dwAspect = DVASPECT_CONTENT;
+ fmtetc.lindex = -1;
+ fmtetc.tymed = TYMED_HGLOBAL;
+ hr = IDataObject_GetData(dataobject, &fmtetc, &medium);
+ if (SUCCEEDED(hr))
+ {
+ void *text = GlobalLock(medium.hGlobal);
+ if (text != NULL)
+ {
+ SETTEXTEX settextex;
+ settextex.flags = ST_KEEPUNDO | ST_SELECTION;
+ settextex.codepage = CP_ACP;
+ if (cf == CF_UNICODETEXT)
+ settextex.codepage = CP_UNICODE;
+ hr = ITextServices_TxSendMessage(&services->ITextServices_iface, EM_SETTEXTEX, (WPARAM)&settextex, (LPARAM)text, NULL);
+ GlobalUnlock(medium.hGlobal);
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ ReleaseStgMedium(&medium);
+ }
+
+ if (lpdataobj == NULL)
+ IDataObject_Release(dataobject);
+ return hr;
+}
+
static HRESULT WINAPI
IRichEditOle_fnImportDataObject(IRichEditOle *iface, LPDATAOBJECT lpdataobj,
CLIPFORMAT cf, HGLOBAL hMetaPict)
{
+ CLIPFORMAT cfRTF;
+ HRESULT hr;
struct text_services *services = impl_from_IRichEditOle( iface );
- FIXME("stub %p\n", services);
- return E_NOTIMPL;
+ TRACE("(%p, %p, %hu, %p)\n", services, lpdataobj, cf, hMetaPict);
+
+ cfRTF = RegisterClipboardFormatA("Rich Text Format");
+ if (cf == cfRTF)
+ hr = import_dataobject(services, lpdataobj, cf);
+ else if (cf == CF_TEXT || cf == CF_UNICODETEXT)
+ hr = import_dataobject(services, lpdataobj, cf);
+ else if (cf == 0)
+ {
+ hr = import_dataobject(services, lpdataobj, cfRTF);
+ if (hr == DV_E_FORMATETC)
+ hr = import_dataobject(services, lpdataobj, CF_UNICODETEXT);
+ if (hr == DV_E_FORMATETC)
+ hr = import_dataobject(services, lpdataobj, CF_TEXT);
+ }
+ else
+ hr = DV_E_FORMATETC;
+ return hr;
}
static HRESULT WINAPI
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index fb5177b83e9..1365acfdda5 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -33,6 +33,7 @@
#include <tom.h>
#include <imm.h>
#include <textserv.h>
+#include <ntuser.h>
#include <wine/test.h>
#define EXPECT_TODO_WINE 0x80000000UL
@@ -604,6 +605,304 @@ static HRESULT testoleobj_Create( struct testoleobj **objptr )
return S_OK;
}
+struct reole_dataobject
+{
+ IDataObject IDataObject_iface;
+ LONG ref;
+
+ struct format_entry **entries;
+ DWORD entry_count;
+};
+
+struct reole_fmt_iterator
+{
+ IEnumFORMATETC IEnumFORMATETC_iface;
+ LONG ref;
+
+ struct reole_dataobject *dataobject;
+ DWORD current_entry;
+};
+
+static inline struct reole_fmt_iterator *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
+{
+ return CONTAINING_RECORD(iface, struct reole_fmt_iterator, IEnumFORMATETC_iface);
+}
+
+static inline struct reole_dataobject *impl_from_IDataObject(IDataObject *iface)
+{
+ return CONTAINING_RECORD(iface, struct reole_dataobject, IDataObject_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE reole_fmt_iterator_QueryInterface(IEnumFORMATETC *iface, REFIID iid, void **obj)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumFORMATETC))
+ {
+ IEnumFORMATETC_AddRef(&This->IEnumFORMATETC_iface);
+ *obj = &This->IEnumFORMATETC_iface;
+ return S_OK;
+ }
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE reole_fmt_iterator_AddRef(IEnumFORMATETC *iface)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ return ref;
+}
+
+static ULONG STDMETHODCALLTYPE reole_fmt_iterator_Release(IEnumFORMATETC *iface)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ if (!ref)
+ {
+ IDataObject_Release(&This->dataobject->IDataObject_iface);
+ free(This);
+ }
+ return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_fmt_iterator_Next(IEnumFORMATETC *iface, ULONG count, FORMATETC *formats, ULONG *ret)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+ UINT i;
+
+ for (i = 0; i < count && (This->current_entry + i) < This->dataobject->entry_count; i++)
+ {
+ formats[i].cfFormat = This->dataobject->entries[This->current_entry + i]->format;
+ formats[i].ptd = NULL;
+ formats[i].dwAspect = DVASPECT_CONTENT;
+ formats[i].lindex = -1;
+ formats[i].tymed = TYMED_HGLOBAL;
+ }
+
+ This->current_entry += i;
+ if (ret) *ret = i;
+ return (i == count) ? S_OK : S_FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_fmt_iterator_Skip(IEnumFORMATETC *iface, ULONG count)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+
+ if (This->current_entry + count < This->dataobject->entry_count)
+ {
+ This->current_entry += count;
+ return S_OK;
+ }
+ else
+ {
+ This->current_entry = This->dataobject->entry_count;
+ return S_FALSE;
+ }
+}
+
+static HRESULT STDMETHODCALLTYPE reole_fmt_iterator_Reset(IEnumFORMATETC *iface)
+{
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+ This->current_entry = 0;
+ return S_OK;
+}
+
+static HRESULT reole_fmt_iterator_Create(struct reole_dataobject *dataobject, struct reole_fmt_iterator **iterator);
+
+static HRESULT STDMETHODCALLTYPE reole_fmt_iterator_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **out)
+{
+ HRESULT hr;
+ struct reole_fmt_iterator *cloned;
+ struct reole_fmt_iterator *This = impl_from_IEnumFORMATETC(iface);
+ hr = reole_fmt_iterator_Create(This->dataobject, &cloned);
+ if (SUCCEEDED(hr))
+ {
+ cloned->current_entry = This->current_entry;
+ *out = &cloned->IEnumFORMATETC_iface;
+ }
+ return hr;
+}
+
+static const IEnumFORMATETCVtbl reole_fmt_iterator_vtbl =
+{
+ reole_fmt_iterator_QueryInterface,
+ reole_fmt_iterator_AddRef,
+ reole_fmt_iterator_Release,
+ reole_fmt_iterator_Next,
+ reole_fmt_iterator_Skip,
+ reole_fmt_iterator_Reset,
+ reole_fmt_iterator_Clone,
+};
+
+static HRESULT reole_fmt_iterator_Create(struct reole_dataobject *dataobject, struct reole_fmt_iterator **iterator)
+{
+ struct reole_fmt_iterator *it;
+ if (!(it = calloc(sizeof(struct reole_fmt_iterator), 1))) return E_OUTOFMEMORY;
+ it->IEnumFORMATETC_iface.lpVtbl = &reole_fmt_iterator_vtbl;
+ it->ref = 1;
+ it->dataobject = dataobject;
+ IDataObject_AddRef(&dataobject->IDataObject_iface);
+ it->current_entry = 0;
+ *iterator = it;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_QueryInterface(IDataObject *iface, REFIID riid, void **obj)
+{
+ if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
+ IDataObject_AddRef(iface);
+ *obj = iface;
+ return S_OK;
+ }
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE reole_dataobject_AddRef(IDataObject *iface)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ return ref;
+}
+
+static ULONG STDMETHODCALLTYPE reole_dataobject_Release(IDataObject *iface)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ if (!ref) free(This);
+ return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_GetData(IDataObject *iface, FORMATETC *format, STGMEDIUM *medium)
+{
+ UINT i;
+ HRESULT hr;
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ if (FAILED(hr = IDataObject_QueryGetData(iface, format))) return hr;
+ for (i = 0; i < This->entry_count; i++)
+ {
+ if (format->cfFormat == This->entries[i]->format)
+ {
+ medium->tymed = TYMED_HGLOBAL;
+ medium->hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, This->entries[i]->size);
+ if (medium->hGlobal == NULL) return E_OUTOFMEMORY;
+ memcpy(GlobalLock(medium->hGlobal), This->entries[i]->data, This->entries[i]->size);
+ GlobalUnlock(medium->hGlobal);
+ medium->pUnkForRelease = 0;
+ return S_OK;
+ }
+ }
+ return DATA_E_FORMATETC;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_GetDataHere(IDataObject *iface, FORMATETC *format, STGMEDIUM *medium)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("this %p, format %p, medium %p stub!\n", This, format, medium);
+ return DATA_E_FORMATETC;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_QueryGetData(IDataObject *iface, FORMATETC *format)
+{
+ UINT i;
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ if (format->tymed && !(format->tymed & TYMED_HGLOBAL))
+ {
+ trace("only HGLOBAL medium types supported right now\n");
+ return DV_E_TYMED;
+ }
+ for (i = 0; i < This->entry_count; i++)
+ {
+ if (format->cfFormat == This->entries[i]->format)
+ return S_OK;
+ }
+ return DV_E_FORMATETC;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_GetCanonicalFormatEtc(IDataObject *iface, FORMATETC *format, FORMATETC *out)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("this %p, format %p, out %p stub!\n", This, format, out);
+ out->ptd = NULL;
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_SetData(IDataObject *iface, FORMATETC *format, STGMEDIUM *medium, BOOL release)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("this %p, format %p, medium %p, release %u stub!\n", This, format, medium, release);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_EnumFormatEtc(IDataObject *iface, DWORD direction, IEnumFORMATETC **out)
+{
+ HRESULT hr;
+ struct reole_fmt_iterator *it;
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ if (direction != DATADIR_GET)
+ {
+ trace("only the get direction is implemented\n");
+ return E_NOTIMPL;
+ }
+ hr = reole_fmt_iterator_Create(This, &it);
+ if (SUCCEEDED(hr))
+ *out = &it->IEnumFORMATETC_iface;
+ return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_DAdvise(IDataObject *iface, FORMATETC *format, DWORD flags,
+ IAdviseSink *sink, DWORD *connection)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("dataobject %p, format %p, flags %#lx, sink %p, connection %p stub!\n",
+ This, format, flags, sink, connection);
+ return OLE_E_ADVISENOTSUPPORTED;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_DUnadvise(IDataObject *iface, DWORD connection)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("this %p, connection %lu stub!\n", This, connection);
+ return OLE_E_ADVISENOTSUPPORTED;
+}
+
+static HRESULT STDMETHODCALLTYPE reole_dataobject_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **advise)
+{
+ struct reole_dataobject *This = impl_from_IDataObject(iface);
+ trace("this %p, advise %p stub!\n", This, advise);
+ return OLE_E_ADVISENOTSUPPORTED;
+}
+
+static IDataObjectVtbl reole_dataobject_vtbl =
+{
+ reole_dataobject_QueryInterface,
+ reole_dataobject_AddRef,
+ reole_dataobject_Release,
+ reole_dataobject_GetData,
+ reole_dataobject_GetDataHere,
+ reole_dataobject_QueryGetData,
+ reole_dataobject_GetCanonicalFormatEtc,
+ reole_dataobject_SetData,
+ reole_dataobject_EnumFormatEtc,
+ reole_dataobject_DAdvise,
+ reole_dataobject_DUnadvise,
+ reole_dataobject_EnumDAdvise,
+};
+
+static HRESULT reole_dataobject_Create(struct reole_dataobject **dataobject, struct format_entry **entries, DWORD entry_count)
+{
+ struct reole_dataobject *This;
+ if (!(This = calloc(sizeof(struct reole_dataobject), 1))) return E_OUTOFMEMORY;
+ This->IDataObject_iface.lpVtbl = &reole_dataobject_vtbl;
+ This->ref = 1;
+ This->entries = entries;
+ This->entry_count = entry_count;
+ *dataobject = This;
+ return S_OK;
+}
+
static HMODULE hmoduleRichEdit;
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -5035,6 +5334,67 @@ static void test_clipboard(void)
ITextRange_Release(range);
}
+static struct format_entry* alloc_format_entry(UINT format, UINT size, const char *data)
+{
+ struct format_entry *entry = calloc(1, sizeof(struct format_entry) + size);
+ if (entry == NULL)
+ return NULL;
+ entry->format = format;
+ entry->size = size;
+ memcpy(&entry->data, data, size);
+ return entry;
+}
+
+static void test_import_data(void)
+{
+ static const char text_abc[] = "abc";
+ IRichEditOle *reole = NULL;
+ ITextDocument *doc = NULL;
+ ITextSelection *selection;
+ HRESULT hr;
+ HWND hwnd;
+ char buffer[1024] = "";
+ struct format_entry *text_entry;
+ struct reole_dataobject *dataobject;
+
+ text_entry = alloc_format_entry(CF_TEXT, 3, "cd");
+ ok(text_entry != NULL, "failed to create text_entry\n");
+ hr = reole_dataobject_Create(&dataobject, &text_entry, 1);
+ ok(hr == S_OK, "reole_dataobject_Create failed\n");
+ create_interfaces(&hwnd, &reole, &doc, &selection);
+
+ /* Test our IDataObject */
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ hr = IRichEditOle_ImportDataObject(reole, &dataobject->IDataObject_iface, 0, NULL);
+ ok(hr == S_OK, "got hr 0x%08lx\n", hr);
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, "cd") == 0, "text shouldn't be %s", buffer);
+
+ /* Try import CF_BITMAP which doesn't exist in our IDataObject */
+ hr = IRichEditOle_ImportDataObject(reole, &dataobject->IDataObject_iface, CF_BITMAP, NULL);
+ ok(hr == DV_E_FORMATETC, "got hr 0x%08lx\n", hr);
+
+ /* When IDataObject is NULL, IRichEditOle::ImportDataObject() will import from the clipboard */
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text_abc);
+ hr = ITextSelection_SetStart(selection, 0);
+ ok(SUCCEEDED(hr), "got hr 0x%08lx\n", hr);
+ hr = ITextSelection_SetEnd(selection, 3);
+ ok(SUCCEEDED(hr), "got hr 0x%08lx\n", hr);
+ hr = ITextSelection_Copy(selection, NULL);
+ ok(hr == S_OK, "couldn't copy to clipboard: 0x%08lx\n", hr);
+ hr = ITextSelection_SetEnd(selection, 0);
+ ok(SUCCEEDED(hr), "got hr 0x%08lx\n", hr);
+ hr = IRichEditOle_ImportDataObject(reole, NULL, 0, NULL);
+ ok(hr == S_OK, "got 0x%08lx\n", hr);
+ memset(buffer, 0, ARRAY_SIZE(buffer));
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, "abcabc") == 0, "text shouldn't be %s", buffer);
+
+ release_interfaces(&hwnd, &reole, &doc, &selection);
+ IDataObject_Release(&dataobject->IDataObject_iface);
+ free(text_entry);
+}
+
static void subtest_undo(const char *dummy_text)
{
static const char *text_seq[] = {
@@ -5606,6 +5966,7 @@ START_TEST(richole)
test_MoveEnd_story();
test_character_movement();
test_clipboard();
+ test_import_data();
test_undo();
test_undo_control();
test_freeze();
--
2.45.2

View File

@@ -0,0 +1 @@
Fixes: [26302] richedit20: Implement IRichEditOle::ImportDataObject

View File

@@ -1,4 +1,4 @@
From 1bc2f932ec013b83fdc798ce42dd8f50ea9a2b3c Mon Sep 17 00:00:00 2001
From cec945f2849da0cc40b6301885cb02e23f5c364e Mon Sep 17 00:00:00 2001
From: Joakim Hernberg <jhernberg@alchemy.lu>
Date: Tue, 31 Mar 2015 20:58:20 +0200
Subject: [PATCH] wineserver: Draft to implement priority levels through POSIX
@@ -13,16 +13,16 @@ Changes by Sebastian Lackner <sebastian@fds-team.de>:
server/Makefile.in | 1 +
server/main.c | 1 +
server/scheduler.c | 166 +++++++++++++++++++++++++++++++++++++++++++++
server/thread.c | 3 +
server/thread.c | 1 +
server/thread.h | 5 ++
5 files changed, 176 insertions(+)
5 files changed, 174 insertions(+)
create mode 100644 server/scheduler.c
diff --git a/server/Makefile.in b/server/Makefile.in
index c62edbdb892..3b9446fe224 100644
index 7e571ac2ba6..4468ff018c4 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -30,6 +30,7 @@ C_SRCS = \
@@ -30,6 +30,7 @@ SOURCES = \
region.c \
registry.c \
request.c \
@@ -31,7 +31,7 @@ index c62edbdb892..3b9446fe224 100644
serial.c \
signal.c \
diff --git a/server/main.c b/server/main.c
index 1248b92f24d..ddda5f4e86e 100644
index e014ec535ff..e556bea3a4b 100644
--- a/server/main.c
+++ b/server/main.c
@@ -231,6 +231,7 @@ int main( int argc, char *argv[] )
@@ -215,25 +215,22 @@ index 00000000000..4a5d82b208d
+
+#endif
diff --git a/server/thread.c b/server/thread.c
index 83ae381d5c5..f2de29a2852 100644
index 88b953709ef..2cbaa69ee7d 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -622,7 +622,10 @@ static void set_thread_info( struct thread *thread,
if ((req->priority >= min && req->priority <= max) ||
req->priority == THREAD_PRIORITY_IDLE ||
req->priority == THREAD_PRIORITY_TIME_CRITICAL)
+ {
thread->priority = req->priority;
+ set_scheduler_priority( thread );
+ }
else
set_error( STATUS_INVALID_PARAMETER );
}
@@ -686,6 +686,7 @@ unsigned int set_thread_priority( struct thread *thread, int priority_class, int
return STATUS_THREAD_IS_TERMINATING;
thread->priority = priority;
+ set_scheduler_priority( thread );
/* if thread is gone or hasn't started yet, this will be called again from init_thread with a unix_tid */
if (thread->unix_tid != -1) apply_thread_priority( thread, get_base_priority( priority_class, priority ));
diff --git a/server/thread.h b/server/thread.h
index 8dcf966a90a..18b2d0a8bb8 100644
index 2b256be322f..972d98b6520 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -142,4 +142,9 @@ static inline void set_win32_error( unsigned int err ) { set_error( 0xc0010000 |
@@ -146,4 +146,9 @@ static inline void set_win32_error( unsigned int err ) { set_error( 0xc0010000 |
static inline thread_id_t get_thread_id( struct thread *thread ) { return thread->id; }
@@ -244,5 +241,5 @@ index 8dcf966a90a..18b2d0a8bb8 100644
+
#endif /* __WINE_SERVER_THREAD_H */
--
2.42.0
2.47.2

View File

@@ -0,0 +1,288 @@
From 0a60f26b0ee4664ea253d1155ff943a85f5ba434 Mon Sep 17 00:00:00 2001
From: Kevin Martinez <kevinrmartinezj@gmail.com>
Date: Wed, 17 Jul 2024 15:10:49 -0400
Subject: [PATCH] shell32: Added stub for IEnumObjects interface.
---
dlls/actxprxy/usrmarshal.c | 17 ++++
dlls/shell32/Makefile.in | 1 +
dlls/shell32/enumobjects.c | 166 +++++++++++++++++++++++++++++++
dlls/shell32/shell32_classes.idl | 5 +
dlls/shell32/shell32_main.h | 1 +
dlls/shell32/shellole.c | 1 +
include/shobjidl.idl | 14 +++
7 files changed, 205 insertions(+)
create mode 100644 dlls/shell32/enumobjects.c
diff --git a/dlls/actxprxy/usrmarshal.c b/dlls/actxprxy/usrmarshal.c
index e4eada6848f..43b72e0b002 100644
--- a/dlls/actxprxy/usrmarshal.c
+++ b/dlls/actxprxy/usrmarshal.c
@@ -247,3 +247,20 @@ HRESULT __RPC_STUB IParentAndItem_GetParentAndItem_Proxy(
TRACE("(%p)->(%p %p %p)\n", This, parent, folder, child);
return IParentAndItem_RemoteGetParentAndItem_Proxy(This, parent, folder, child);
}
+
+HRESULT CALLBACK IEnumObjects_Next_Proxy(IEnumObjects *This, ULONG celt, REFIID riid, void **rgelt, ULONG *pceltFetched)
+{
+ ULONG fetched;
+ TRACE("(%p)->(%ld, %p, %p, %p)\n", This, celt, debugstr_guid(riid), rgelt, pceltFetched);
+ if (!pceltFetched) pceltFetched = &fetched;
+ return IEnumObjects_RemoteNext_Proxy(This, celt, riid, rgelt, pceltFetched);
+}
+
+HRESULT __RPC_STUB IEnumObjects_Next_Stub(IEnumObjects *This, ULONG celt, REFIID riid, void **rgelt, ULONG *pceltFetched)
+{
+ HRESULT hr;
+ TRACE("(%p)->(%ld, %p, %p, %p)\n", This, celt, debugstr_guid(riid), rgelt, pceltFetched);
+ *pceltFetched = 0;
+ hr = IEnumObjects_Next(This, celt, riid, rgelt, pceltFetched);
+ return hr;
+}
\ No newline at end of file
diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in
index 828d8e82e2d..e071ed6a45d 100644
--- a/dlls/shell32/Makefile.in
+++ b/dlls/shell32/Makefile.in
@@ -21,6 +21,7 @@ SOURCES = \
dragdrophelper.c \
ebrowser.c \
enumidlist.c \
+ enumobjects.c \
folders.c \
iconcache.c \
new_menu.c \
diff --git a/dlls/shell32/enumobjects.c b/dlls/shell32/enumobjects.c
new file mode 100644
index 00000000000..16ad52168d8
--- /dev/null
+++ b/dlls/shell32/enumobjects.c
@@ -0,0 +1,166 @@
+/*
+ * EnumerableObjectCollection
+ *
+ * Copyright 2024 Kevin Martinez
+ *
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define COBJMACROS
+
+#include "wine/debug.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "shlwapi.h"
+
+#include "shell32_main.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+struct enum_objects
+{
+ IEnumObjects IEnumObjects_iface;
+ LONG ref;
+};
+
+static inline struct enum_objects *impl_from_IEnumObjects(IEnumObjects *iface)
+{
+ return CONTAINING_RECORD(iface, struct enum_objects, IEnumObjects_iface);
+}
+
+static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID riid, void **obj)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
+
+ *obj = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumObjects))
+ {
+ *obj = &This->IEnumObjects_iface;
+ }
+
+ if (*obj)
+ {
+ IUnknown_AddRef((IUnknown*)*obj);
+ return S_OK;
+ }
+
+ WARN("no interface for %s.\n", debugstr_guid(riid));
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI enum_objects_AddRef(IEnumObjects *iface)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+ ULONG refcount = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p): increasing refcount to %lu.\n", This, refcount);
+
+ return refcount;
+}
+
+ static ULONG WINAPI enum_objects_Release(IEnumObjects *iface)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+ ULONG refcount = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p): decreasing refcount to %lu.\n", This, refcount);
+
+ if (!refcount)
+ {
+ free(This);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI enum_objects_Next(IEnumObjects *iface, ULONG celt, REFIID riid, void **rgelt, ULONG *celtFetched)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+
+ FIXME("(%p %ld, %p)->(%p, %p): stub!\n", This, celt, debugstr_guid(riid), rgelt, celtFetched);
+
+ if (celtFetched)
+ *celtFetched = 0;
+
+ return S_FALSE;
+}
+
+static HRESULT WINAPI enum_objects_Skip(IEnumObjects *iface, ULONG celt)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+
+ FIXME("(%p %ld): stub!\n", This, celt);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI enum_objects_Reset(IEnumObjects *iface)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+
+ FIXME("(%p): stub!\n", This);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI enum_objects_Clone(IEnumObjects *iface, IEnumObjects **ppenum)
+{
+ struct enum_objects *This = impl_from_IEnumObjects(iface);
+
+ FIXME("(%p)->(%p): stub!\n", This, ppenum);
+
+ return E_NOTIMPL;
+}
+
+static const IEnumObjectsVtbl enum_objects_vtbl =
+{
+ enum_objects_QueryInterface,
+ enum_objects_AddRef,
+ enum_objects_Release,
+ enum_objects_Next,
+ enum_objects_Skip,
+ enum_objects_Reset,
+ enum_objects_Clone,
+};
+
+HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj)
+{
+ struct enum_objects *This;
+ HRESULT hr;
+
+ TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), obj);
+
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ if (!(This = heap_alloc(sizeof(*This))))
+ return E_OUTOFMEMORY;
+
+ This->ref = 1;
+ This->IEnumObjects_iface.lpVtbl = &enum_objects_vtbl;
+
+ hr = IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj);
+ IEnumObjects_Release(&This->IEnumObjects_iface);
+ return hr;
+}
diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl
index 932b6f395b2..9e2df630940 100644
--- a/dlls/shell32/shell32_classes.idl
+++ b/dlls/shell32/shell32_classes.idl
@@ -194,3 +194,8 @@ coclass NewMenu {}
threading(apartment),
uuid(9ac9fbe1-e0a2-4ad6-b4ee-e212013ea917)
] coclass ShellItem { interface IShellItem2; }
+
+[
+ threading(apartment),
+ uuid(2d3468c1-36a7-43b6-ac24-d3f02fd9607a)
+] coclass EnumerableObjectCollection {}
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index 766c7c23adc..ab3187fd24a 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -104,6 +104,7 @@ HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, LPV
HRESULT WINAPI KnownFolderManager_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv);
HRESULT WINAPI IFileOperation_Constructor(IUnknown *outer, REFIID riid, void **out);
HRESULT WINAPI ActiveDesktop_Constructor(IUnknown *outer, REFIID riid, void **out);
+HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj);
extern HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST, LPWSTR, UINT, int*);
HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c
index aa9bd3e0f3e..fc3f6b032cd 100644
--- a/dlls/shell32/shellole.c
+++ b/dlls/shell32/shellole.c
@@ -87,6 +87,7 @@ static const struct {
{&CLSID_ShellImageDataFactory, ShellImageDataFactory_Constructor},
{&CLSID_FileOperation, IFileOperation_Constructor},
{&CLSID_ActiveDesktop, ActiveDesktop_Constructor},
+ {&CLSID_EnumerableObjectCollection, EnumerableObjectCollection_Constructor},
{NULL, NULL}
};
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index 4118e3d9ba2..aa393225db1 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -4134,3 +4134,17 @@ interface IFileOperation : IUnknown
HRESULT PerformOperations();
HRESULT GetAnyOperationsAborted([out] BOOL *aborted);
}
+
+[
+ object,
+ uuid(2c1c7e2e-2d0e-4059-831e-1e6f82335c2e),
+ pointer_default(unique)
+]
+interface IEnumObjects : IUnknown
+{
+ [local] HRESULT Next([in] ULONG celt, [in] REFIID riid, [out, iid_is(riid)] void **rgelt, [out, optional] ULONG *pceltFetched);
+ [call_as(Next)] HRESULT RemoteNext([in] ULONG celt, [in] REFIID riid, [out, size_is(celt), length_is(*pceltFetched), iid_is(riid)] void **rgelt, [out] ULONG *pceltFetched);
+ HRESULT Skip([in] ULONG celt);
+ HRESULT Reset();
+ HRESULT Clone([out] IEnumObjects **ppenum);
+}
--
2.45.2

View File

@@ -0,0 +1,147 @@
From d3b76c01d434b774c7de82ae8c1e05b566f108b8 Mon Sep 17 00:00:00 2001
From: Kevin Martinez <kevinrmartinezj@gmail.com>
Date: Wed, 24 Jul 2024 17:22:57 -0400
Subject: [PATCH] shell32: Added stub for IObjectCollection interface.
---
dlls/shell32/enumobjects.c | 96 ++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/dlls/shell32/enumobjects.c b/dlls/shell32/enumobjects.c
index 16ad52168d8..233919738bf 100644
--- a/dlls/shell32/enumobjects.c
+++ b/dlls/shell32/enumobjects.c
@@ -37,6 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
struct enum_objects
{
IEnumObjects IEnumObjects_iface;
+ IObjectCollection IObjectCollection_iface;
LONG ref;
};
@@ -45,6 +46,11 @@ static inline struct enum_objects *impl_from_IEnumObjects(IEnumObjects *iface)
return CONTAINING_RECORD(iface, struct enum_objects, IEnumObjects_iface);
}
+static inline struct enum_objects *impl_from_IObjectCollection(IObjectCollection *iface)
+{
+ return CONTAINING_RECORD(iface, struct enum_objects, IObjectCollection_iface);
+}
+
static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID riid, void **obj)
{
struct enum_objects *This = impl_from_IEnumObjects(iface);
@@ -57,6 +63,10 @@ static HRESULT WINAPI enum_objects_QueryInterface(IEnumObjects *iface, REFIID ri
{
*obj = &This->IEnumObjects_iface;
}
+ else if (IsEqualIID(riid, &IID_IObjectCollection) || IsEqualIID(riid, &IID_IObjectArray))
+ {
+ *obj = &This->IObjectCollection_iface;
+ }
if (*obj)
{
@@ -144,6 +154,91 @@ static const IEnumObjectsVtbl enum_objects_vtbl =
enum_objects_Clone,
};
+static HRESULT WINAPI object_collection_QueryInterface(IObjectCollection *iface, REFIID riid, void **obj)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+ return IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj);
+}
+
+static ULONG WINAPI object_collection_AddRef(IObjectCollection *iface)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+ return IEnumObjects_AddRef(&This->IEnumObjects_iface);
+}
+
+static ULONG WINAPI object_collection_Release(IObjectCollection *iface)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+ return IEnumObjects_Release(&This->IEnumObjects_iface);
+}
+
+static HRESULT WINAPI object_collection_GetCount(IObjectCollection *iface, UINT *count)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p)->(%p): stub!\n", This, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI object_collection_GetAt(IObjectCollection *iface, UINT index, REFIID riid, void **obj)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p %u, %s)->(%p): stub!\n", This, index, debugstr_guid(riid), obj);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI object_collection_AddObject(IObjectCollection *iface, IUnknown *obj)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p %p): stub!\n", This, obj);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI object_collection_AddFromArray(IObjectCollection *iface, IObjectArray *source_array)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p %p): stub!\n", This, source_array);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI object_collection_RemoveObjectAt(IObjectCollection *iface, UINT index)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p %u): stub!\n", This, index);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI object_collection_Clear(IObjectCollection *iface)
+{
+ struct enum_objects *This = impl_from_IObjectCollection(iface);
+
+ FIXME("(%p): stub!\n", This);
+
+ return E_NOTIMPL;
+}
+
+static const IObjectCollectionVtbl object_collection_vtbl =
+{
+ object_collection_QueryInterface,
+ object_collection_AddRef,
+ object_collection_Release,
+ object_collection_GetCount,
+ object_collection_GetAt,
+ object_collection_AddObject,
+ object_collection_AddFromArray,
+ object_collection_RemoveObjectAt,
+ object_collection_Clear
+};
+
HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID riid, void **obj)
{
struct enum_objects *This;
@@ -159,6 +254,7 @@ HRESULT WINAPI EnumerableObjectCollection_Constructor(IUnknown *outer, REFIID ri
This->ref = 1;
This->IEnumObjects_iface.lpVtbl = &enum_objects_vtbl;
+ This->IObjectCollection_iface.lpVtbl = &object_collection_vtbl;
hr = IEnumObjects_QueryInterface(&This->IEnumObjects_iface, riid, obj);
IEnumObjects_Release(&This->IEnumObjects_iface);
--
2.45.2

View File

@@ -0,0 +1,4 @@
Fixes: [53620] err:ole:com_get_class_object class IEnumObjects not registered.
Fixes: [56891] Visual novel Mebae (Tanuki Soft) crashes on startup
# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6130

View File

@@ -1,14 +1,14 @@
From 7e889b2ef650e4805128220aa3b56fbf5a0514b1 Mon Sep 17 00:00:00 2001
From 213514e0cfc73abd3be2f9707f53688fbf28669e Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 6 Mar 2024 20:21:36 +1100
Subject: [PATCH 2/2] user32/msgbox: Use a windows hook to trap Ctrl+C
Subject: [PATCH] user32/msgbox: Use a windows hook to trap Ctrl+C
---
dlls/user32/msgbox.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/dlls/user32/msgbox.c b/dlls/user32/msgbox.c
index 6b5d867eb1f..bf28413f39d 100644
index e7fd704ea28..8d9adce8bd6 100644
--- a/dlls/user32/msgbox.c
+++ b/dlls/user32/msgbox.c
@@ -391,6 +391,22 @@ static void MSGBOX_CopyToClipbaord( HWND hwnd )
@@ -35,7 +35,7 @@ index 6b5d867eb1f..bf28413f39d 100644
* MSGBOX_DlgProc
*
@@ -406,6 +422,7 @@ static INT_PTR CALLBACK MSGBOX_DlgProc( HWND hwnd, UINT message,
SetWindowContextHelpId(hwnd, mbp->dwContextHelpId);
NtUserSetWindowContextHelpId(hwnd, mbp->dwContextHelpId);
MSGBOX_OnInit(hwnd, mbp);
SetPropA(hwnd, "WINE_MSGBOX_HELPCALLBACK", mbp->lpfnMsgBoxCallback);
+ msghook_handle = SetWindowsHookExA(WH_MSGFILTER, msg_hook_proc, NULL, GetCurrentThreadId());
@@ -53,5 +53,5 @@ index 6b5d867eb1f..bf28413f39d 100644
case WM_COMMAND:
switch (LOWORD(wParam))
--
2.43.0
2.47.2

View File

@@ -0,0 +1,190 @@
From fb57e3e8a5f16dc50f29e089595132c3c8b1b1a6 Mon Sep 17 00:00:00 2001
From: Francis De Brabandere <francisdb@gmail.com>
Date: Mon, 23 Dec 2024 18:34:04 +0100
Subject: [PATCH 1/3] vbscript: redim without dim
---
dlls/vbscript/compile.c | 7 +++++++
dlls/vbscript/interp.c | 25 ++++++++++++++++++++++---
dlls/vbscript/tests/lang.vbs | 27 +++++++++++++++++++++++++++
dlls/vbscript/vbscript_defs.h | 1 +
4 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/compile.c b/dlls/vbscript/compile.c
index baddc51d7e4..d2260aedb6e 100644
--- a/dlls/vbscript/compile.c
+++ b/dlls/vbscript/compile.c
@@ -1173,6 +1173,13 @@ static HRESULT compile_redim_statement(compile_ctx_t *ctx, redim_statement_t *st
HRESULT hres;
while(1) {
+ for (function_decl_t *func = ctx->func_decls; func; func = func->next) {
+ if (!wcsicmp(func->name, decl->identifier)) {
+ /* compilation error: Name redefined */
+ return MAKE_VBSERROR(VBS_COMPILE_ERROR);
+ }
+ }
+
hres = compile_args(ctx, decl->dims, &arg_cnt);
if(FAILED(hres))
return hres;
diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c
index 937cdaf1c8c..32cf90971a7 100644
--- a/dlls/vbscript/interp.c
+++ b/dlls/vbscript/interp.c
@@ -1316,9 +1316,28 @@ static HRESULT interp_redim(exec_ctx_t *ctx)
return hres;
}
- if(ref.type != REF_VAR) {
- FIXME("got ref.type = %d\n", ref.type);
- return E_FAIL;
+ switch(ref.type) {
+ case REF_DISP:
+ case REF_OBJ:
+ case REF_CONST:
+ return MAKE_VBSERROR(VBSE_ILLEGAL_ASSIGNMENT);
+
+ case REF_FUNC:
+ /* Unreachable: Compiler should have thrown a compilation error: Name redefined */
+ return E_FAIL;
+
+ case REF_NONE:
+ ref.type = REF_VAR;
+ hres = add_dynamic_var(ctx, identifier, FALSE, &ref.u.v);
+ /* Fall through to REF_VAR case */
+
+ case REF_VAR:
+ /* all ok */
+ break;
+
+ default:
+ FIXME("!!!!!!got ref.type = %d\n", ref.type);
+ return E_FAIL;
}
v = ref.u.v;
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index 3c6ce656f1c..023af27f939 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -1701,6 +1701,33 @@ e = err.number
on error goto 0
ok e = 9, "e = " & e ' VBSE_OUT_OF_BOUNDS, can only change rightmost dimension
+' Redim without Dim should work, even in explicit mode
+redim toCreateArr(3)
+ok ubound(toCreateArr) = 3, "ubound(toCreateArr) = " & ubound(toCreateArr)
+toCreateArr(3) = 10
+ok toCreateArr(3) = 10, "toCreateArr(3) = " & toCreateArr(3)
+
+on error resume next
+const redimConst = 3
+redim redimConst(3)
+' REF_CONST -> runtime error: Type mismatch: 'redimConst'
+ok err.number = 501, "redim <const> err.number = " & err.number
+err.clear
+redim err(3)
+' REF_DISP -> runtime error: Object doesn't support this property or method
+ok err.number = 501, "redim <err> err.number = " & err.number
+err.clear
+' TODO where should we put this compilation error test?
+' Sub redimSub
+' End Sub
+' redim redimSub(3)
+' ' REF_FUNC -> compilation error: Name redefined
+' todo_wine_ok err.number = -1, "redim <sub> err.number = " & err.number
+' err.clear
+' ' TODO how do we test the REF_OBJ case?
+on error goto 0
+
+
sub TestReDimFixed
on error resume next
diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h
index 139b71255a0..c32a94c7e85 100644
--- a/dlls/vbscript/vbscript_defs.h
+++ b/dlls/vbscript/vbscript_defs.h
@@ -267,6 +267,7 @@
#define VBSE_INVALID_DLL_FUNCTION_NAME 453
#define VBSE_INVALID_TYPELIB_VARIABLE 458
#define VBSE_SERVER_NOT_FOUND 462
+#define VBSE_ILLEGAL_ASSIGNMENT 501
#define VBSE_UNQUALIFIED_REFERENCE 505
#define VBS_COMPILE_ERROR 4096
--
GitLab
From 39b5672f5b4f41097229ddf9ba72061b56537a70 Mon Sep 17 00:00:00 2001
From: Francis De Brabandere <francisdb@gmail.com>
Date: Wed, 8 Jan 2025 17:59:49 +0100
Subject: [PATCH 2/3] vbscript: trying test the compile error
---
dlls/vbscript/tests/run.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c
index 8aaafbedf54..3d2ad2a6e7b 100644
--- a/dlls/vbscript/tests/run.c
+++ b/dlls/vbscript/tests/run.c
@@ -2765,6 +2765,18 @@ static void test_parse_errors(void)
" throwInt &h87001234&\n"
"end if\n",
2, 1
+ },
+ {
+ /* redim of sub on windows fails with
+ compilation error: Name redefined
+ TODO how can we validate that this code throws a "compilation error: Name redefined"?
+ TODO this code fails even without the compile.c redim collision check???
+ but somehow the commented part in lang.vbs would not fail???
+ */
+ "sub redimSub\n"
+ "end sub\n"
+ L"redim redimSub(3)\n",
+ 2, 0
}
};
HRESULT hres;
--
GitLab
From 9b72ec47965d17d93475651f0d2dafa598133c1f Mon Sep 17 00:00:00 2001
From: Francis De Brabandere <francisdb@gmail.com>
Date: Wed, 8 Jan 2025 18:01:48 +0100
Subject: [PATCH 3/3] vbscript: trying test the compile error
---
dlls/vbscript/tests/run.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c
index 3d2ad2a6e7b..89c73d51fdb 100644
--- a/dlls/vbscript/tests/run.c
+++ b/dlls/vbscript/tests/run.c
@@ -2767,12 +2767,12 @@ static void test_parse_errors(void)
2, 1
},
{
- /* redim of sub on windows fails with
+ /* redim of sub on windows fails with
compilation error: Name redefined
- TODO how can we validate that this code throws a "compilation error: Name redefined"?
- TODO this code fails even without the compile.c redim collision check???
- but somehow the commented part in lang.vbs would not fail???
- */
+ TODO how can we validate that this code throws a "compilation error: Name redefined"?
+ TODO this code fails even without the compile.c redim collision check???
+ but somehow the commented part in lang.vbs would not fail???
+ */
"sub redimSub\n"
"end sub\n"
L"redim redimSub(3)\n",
--
GitLab

View File

@@ -0,0 +1,4 @@
Fixes: [53644] vbscript: class single line multivar.
# MR
# https://gitlab.winehq.org/wine/wine/-/merge_requests/7068

Some files were not shown because too many files have changed in this diff Show More