You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7b9777c23e | ||
|
aed0bcfb83 | ||
|
22f5ea5e4f | ||
|
7f5729fc14 | ||
|
7fda13a16d | ||
|
667ee8a4ff | ||
|
b45a0aead3 | ||
|
36483a9c11 | ||
|
28834e80f8 | ||
|
49770c6bc6 | ||
|
93f5b4f6a0 | ||
|
e452a6cbdc | ||
|
23ccc2eef1 | ||
|
18f976c338 |
@@ -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
|
||||
|
@@ -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
|
||||
|
3
patches/d2d1_ID2D1GeometryGroup/definition
Normal file
3
patches/d2d1_ID2D1GeometryGroup/definition
Normal file
@@ -0,0 +1,3 @@
|
||||
Fixes: [51139] d2d1: Implement drawing of ID2D1GeometryGroup
|
||||
|
||||
# MR https://gitlab.winehq.org/wine/wine/-/merge_requests/6492
|
@@ -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
|
||||
|
@@ -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, ¶ms);
|
||||
+ todo_wine
|
||||
+ ok(hr == S_OK, "Got hr %#lx\n", hr);
|
||||
+
|
||||
+ params.cBuckets = 1;
|
||||
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, ¶ms);
|
||||
+ ok(hr == E_INVALIDARG, "Got hr %#lx\n", hr);
|
||||
+
|
||||
+ params.prgBuckets = &bucket;
|
||||
+ bucket.dwBitrate = 0;
|
||||
+ bucket.msBufferWindow = 0;
|
||||
+ hr = IMFByteStreamBuffering_SetBufferingParams(buffering, ¶ms);
|
||||
+ 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, ¶ms);
|
||||
+ 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
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
5
patches/mf_http_support/definition
Normal file
5
patches/mf_http_support/definition
Normal 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.
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
2
patches/oleaut32_VarAdd/definition
Normal file
2
patches/oleaut32_VarAdd/definition
Normal file
@@ -0,0 +1,2 @@
|
||||
Fixes: [56280] oleaut32: VarAnd use VT_I4 when converting VT_BSTR
|
||||
|
@@ -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
|
||||
|
1
patches/richedit20-ImportDataObject/definition
Normal file
1
patches/richedit20-ImportDataObject/definition
Normal file
@@ -0,0 +1 @@
|
||||
Fixes: [26302] richedit20: Implement IRichEditOle::ImportDataObject
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
4
patches/shell32_enumerableobejct/definition
Normal file
4
patches/shell32_enumerableobejct/definition
Normal 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
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
4
patches/vbscript-classes/definition
Normal file
4
patches/vbscript-classes/definition
Normal 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
Reference in New Issue
Block a user