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
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
857466ad4c | ||
|
4378292a65 | ||
|
c2e4c17811 | ||
|
34a7d5e858 | ||
|
a4e8224bd8 | ||
|
1b224000ac | ||
|
2b9cd3663b | ||
|
4901d72e77 | ||
|
735225dbaa | ||
|
7042b486e2 | ||
|
4ef147fbe5 | ||
|
7b9777c23e | ||
|
aed0bcfb83 | ||
|
22f5ea5e4f | ||
|
7f5729fc14 | ||
|
7fda13a16d | ||
|
667ee8a4ff | ||
|
b45a0aead3 | ||
|
36483a9c11 | ||
|
28834e80f8 | ||
|
49770c6bc6 | ||
|
93f5b4f6a0 | ||
|
e452a6cbdc | ||
|
23ccc2eef1 | ||
|
18f976c338 | ||
|
05bc4b822f | ||
|
177488c071 |
8
.github/workflows/macOS.yml
vendored
8
.github/workflows/macOS.yml
vendored
@@ -20,7 +20,6 @@ jobs:
|
||||
bison \
|
||||
gphoto2 \
|
||||
gstreamer \
|
||||
gcenx/wine/libinotify-kqueue \
|
||||
mingw-w64 \
|
||||
molten-vk \
|
||||
sdl2
|
||||
@@ -44,10 +43,11 @@ jobs:
|
||||
cd wine
|
||||
$GITHUB_WORKSPACE/staging/patchinstall.py DESTDIR=. --all
|
||||
|
||||
- name: Configure wine64
|
||||
- name: Configure wine
|
||||
env:
|
||||
LDFLAGS: "-Wl,-rpath,/opt/X11/lib"
|
||||
# Avoid weird linker errors with Xcode 10 and later
|
||||
# We need to tell the linker to add brew & Xquarts to the rpath stack.
|
||||
LDFLAGS: "-Wl,-rpath,/usr/local/lib -Wl,-rpath,/opt/X11/lib"
|
||||
# Use an older deployment target to avoid new dyld behaviors.
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.14"
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE/wine
|
||||
|
@@ -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 c4694f8dfffa56648976c1a05bb4788262a8677b Mon Sep 17 00:00:00 2001
|
||||
From 5bcc58b53dd99c5d6d85141d5658a5d7e98d8253 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Tue, 8 Sep 2020 18:43:52 +0200
|
||||
Subject: [PATCH] msxml3: Implement FreeThreadedXMLHTTP60.
|
||||
@@ -27,10 +27,10 @@ index 7e59a223143..5044c4e2c79 100644
|
||||
|
||||
SOURCES = \
|
||||
diff --git a/dlls/msxml3/factory.c b/dlls/msxml3/factory.c
|
||||
index 218ba87c4a8..ed14bd63a87 100644
|
||||
index e35839db2a3..0e2482d61be 100644
|
||||
--- a/dlls/msxml3/factory.c
|
||||
+++ b/dlls/msxml3/factory.c
|
||||
@@ -281,6 +281,7 @@ static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv
|
||||
@@ -279,6 +279,7 @@ static HRESULT DOMClassFactory_Create(const GUID *clsid, REFIID riid, void **ppv
|
||||
|
||||
static ClassFactory xmldoccf = { { &ClassFactoryVtbl }, XMLDocument_create };
|
||||
static ClassFactory httpreqcf = { { &ClassFactoryVtbl }, XMLHTTPRequest_create };
|
||||
@@ -38,7 +38,7 @@ index 218ba87c4a8..ed14bd63a87 100644
|
||||
static ClassFactory serverhttp = { { &ClassFactoryVtbl }, ServerXMLHTTP_create };
|
||||
static ClassFactory xsltemplatecf = { { &ClassFactoryVtbl }, XSLTemplate_create };
|
||||
static ClassFactory mxnsmanagercf = { {&ClassFactoryVtbl }, MXNamespaceManager_create };
|
||||
@@ -342,6 +343,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
|
||||
@@ -340,6 +341,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
|
||||
{
|
||||
cf = &httpreqcf.IClassFactory_iface;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ index 218ba87c4a8..ed14bd63a87 100644
|
||||
IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP30 ) ||
|
||||
IsEqualCLSID( rclsid, &CLSID_ServerXMLHTTP40 ) ||
|
||||
diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c
|
||||
index 6e4ab4c6519..412958a2a40 100644
|
||||
index 90be57ebabf..15a591c90be 100644
|
||||
--- a/dlls/msxml3/httprequest.c
|
||||
+++ b/dlls/msxml3/httprequest.c
|
||||
@@ -37,10 +37,12 @@
|
||||
@@ -65,9 +65,9 @@ index 6e4ab4c6519..412958a2a40 100644
|
||||
-WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(xmlhttp);
|
||||
|
||||
static const WCHAR colspaceW[] = {':',' ',0};
|
||||
static const WCHAR crlfW[] = {'\r','\n',0};
|
||||
@@ -2054,6 +2056,468 @@ static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl =
|
||||
static const DWORD safety_supported_options =
|
||||
INTERFACESAFE_FOR_UNTRUSTED_CALLER |
|
||||
@@ -2044,6 +2046,468 @@ static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl =
|
||||
ServerXMLHTTPRequest_setOption
|
||||
};
|
||||
|
||||
@@ -536,7 +536,7 @@ index 6e4ab4c6519..412958a2a40 100644
|
||||
static void init_httprequest(httprequest *req)
|
||||
{
|
||||
req->IXMLHTTPRequest_iface.lpVtbl = &XMLHTTPRequestVtbl;
|
||||
@@ -2103,6 +2567,35 @@ HRESULT XMLHTTPRequest_create(void **obj)
|
||||
@@ -2093,6 +2557,35 @@ HRESULT XMLHTTPRequest_create(void **obj)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ index 6e4ab4c6519..412958a2a40 100644
|
||||
{
|
||||
serverhttp *req;
|
||||
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
|
||||
index 54f54995c76..6188414c5ce 100644
|
||||
index ea492bc6b36..c2827563884 100644
|
||||
--- a/dlls/msxml3/msxml_private.h
|
||||
+++ b/dlls/msxml3/msxml_private.h
|
||||
@@ -343,6 +343,7 @@ extern HRESULT XMLDocument_create(void**);
|
||||
@@ -1061,7 +1061,7 @@ index 7214d23c5dc..320a7e04fa3 100644
|
||||
/*
|
||||
* Note that because of a #define in msxml2.h, we end up initializing
|
||||
diff --git a/include/msxml6.idl b/include/msxml6.idl
|
||||
index 7396826a1f6..b2d8bd3b337 100644
|
||||
index bf7e0905057..a02f7b2db14 100644
|
||||
--- a/include/msxml6.idl
|
||||
+++ b/include/msxml6.idl
|
||||
@@ -1715,17 +1715,6 @@ interface ISAXDeclHandler : IUnknown
|
||||
@@ -1101,5 +1101,5 @@ index 7396826a1f6..b2d8bd3b337 100644
|
||||
helpstring("XML DOM Document 6.0"),
|
||||
progid("Msxml2.DOMDocument.6.0"),
|
||||
--
|
||||
2.43.0
|
||||
2.47.2
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From e93243e7863c239a1e4b2d91cb12dcd2cb373b36 Mon Sep 17 00:00:00 2001
|
||||
From 15c10643fa18d1159af85df3132ae3c2228d4488 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 30 May 2015 02:23:15 +0200
|
||||
Subject: [PATCH] ntdll: Add support for hiding wine version information from
|
||||
@@ -10,7 +10,7 @@ Subject: [PATCH] ntdll: Add support for hiding wine version information from
|
||||
2 files changed, 103 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
|
||||
index 9dcb475c148..9e61c38d773 100644
|
||||
index a292ba30774..60c72ffbb89 100644
|
||||
--- a/dlls/ntdll/loader.c
|
||||
+++ b/dlls/ntdll/loader.c
|
||||
@@ -88,6 +88,9 @@ const WCHAR system_dir[] = L"C:\\windows\\system32\\";
|
||||
@@ -32,7 +32,7 @@ index 9dcb475c148..9e61c38d773 100644
|
||||
struct ldr_notification
|
||||
{
|
||||
struct list entry;
|
||||
@@ -2022,6 +2027,96 @@ NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic )
|
||||
@@ -2012,6 +2017,96 @@ NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic )
|
||||
}
|
||||
|
||||
|
||||
@@ -129,16 +129,16 @@ index 9dcb475c148..9e61c38d773 100644
|
||||
/******************************************************************
|
||||
* LdrGetProcedureAddress (NTDLL.@)
|
||||
*/
|
||||
@@ -2042,7 +2137,7 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
|
||||
@@ -2032,7 +2127,7 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
|
||||
{
|
||||
void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL )
|
||||
: find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL );
|
||||
void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL, NULL )
|
||||
: find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL, NULL );
|
||||
- if (proc)
|
||||
+ if (proc && !is_hidden_export( proc ))
|
||||
{
|
||||
*address = proc;
|
||||
ret = STATUS_SUCCESS;
|
||||
@@ -2304,6 +2399,8 @@ static void build_ntdll_module(void)
|
||||
@@ -2294,6 +2389,8 @@ static void build_ntdll_module(void)
|
||||
wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
|
||||
node_ntdll = wm->ldr.DdagNode;
|
||||
if (TRACE_ON(relay)) RELAY_SetupDLL( module );
|
||||
@@ -164,5 +164,5 @@ index fb5fb311646..a342cbf7d26 100644
|
||||
static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
|
||||
{
|
||||
--
|
||||
2.45.2
|
||||
2.47.2
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -1,166 +0,0 @@
|
||||
From 1e6c40cf8a92d7873f1689d64936cd4dfd32f246 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Thu, 21 Apr 2016 14:40:58 +0800
|
||||
Subject: [PATCH] oleaut32: OleLoadPicture should create a DIB section for a
|
||||
being loaded bitmap. (v3)
|
||||
|
||||
Application in the bug 39474 depends on this (GetObject/bmBits should not be
|
||||
NULL, otherwise it crashes).
|
||||
---
|
||||
dlls/oleaut32/olepicture.c | 65 +++++++++++++-------------------
|
||||
dlls/oleaut32/tests/olepicture.c | 2 +-
|
||||
2 files changed, 27 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c
|
||||
index 8df0c22b6cf..b41668a4aeb 100644
|
||||
--- a/dlls/oleaut32/olepicture.c
|
||||
+++ b/dlls/oleaut32/olepicture.c
|
||||
@@ -983,23 +983,16 @@ static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
|
||||
{
|
||||
BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
|
||||
BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
|
||||
- HDC hdcref;
|
||||
+ void *bits;
|
||||
+ BITMAP bmp;
|
||||
|
||||
- /* Does not matter whether this is a coreheader or not, we only use
|
||||
- * components which are in both
|
||||
- */
|
||||
- hdcref = GetDC(0);
|
||||
- This->desc.bmp.hbitmap = CreateDIBitmap(
|
||||
- hdcref,
|
||||
- &(bi->bmiHeader),
|
||||
- CBM_INIT,
|
||||
- xbuf+bfh->bfOffBits,
|
||||
- bi,
|
||||
- DIB_RGB_COLORS
|
||||
- );
|
||||
- ReleaseDC(0, hdcref);
|
||||
+ This->desc.bmp.hbitmap = CreateDIBSection(0, bi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
if (This->desc.bmp.hbitmap == 0)
|
||||
return E_FAIL;
|
||||
+
|
||||
+ GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bmp), &bmp);
|
||||
+ memcpy(bits, xbuf + bfh->bfOffBits, bmp.bmHeight * bmp.bmWidthBytes);
|
||||
+
|
||||
This->desc.picType = PICTYPE_BITMAP;
|
||||
OLEPictureImpl_SetBitmap(This);
|
||||
return S_OK;
|
||||
@@ -1009,10 +1002,9 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour
|
||||
{
|
||||
HRESULT hr;
|
||||
BITMAPINFOHEADER bih;
|
||||
- HDC hdcref;
|
||||
UINT width, height;
|
||||
UINT stride, buffersize;
|
||||
- LPBYTE bits=NULL;
|
||||
+ BYTE *bits, *mask = NULL;
|
||||
WICRect rc;
|
||||
IWICBitmapSource *real_source;
|
||||
UINT x, y;
|
||||
@@ -1040,34 +1032,28 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour
|
||||
stride = 4 * width;
|
||||
buffersize = stride * height;
|
||||
|
||||
- bits = malloc(buffersize);
|
||||
- if (!bits)
|
||||
+ mask = malloc(buffersize);
|
||||
+ if (!mask)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
+ This->desc.bmp.hbitmap = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
|
||||
+ if (This->desc.bmp.hbitmap == 0)
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
rc.X = 0;
|
||||
rc.Y = 0;
|
||||
rc.Width = width;
|
||||
rc.Height = height;
|
||||
hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
|
||||
if (FAILED(hr))
|
||||
- goto end;
|
||||
-
|
||||
- hdcref = GetDC(0);
|
||||
- This->desc.bmp.hbitmap = CreateDIBitmap(
|
||||
- hdcref,
|
||||
- &bih,
|
||||
- CBM_INIT,
|
||||
- bits,
|
||||
- (BITMAPINFO*)&bih,
|
||||
- DIB_RGB_COLORS);
|
||||
-
|
||||
- if (This->desc.bmp.hbitmap == 0)
|
||||
{
|
||||
- hr = E_FAIL;
|
||||
- ReleaseDC(0, hdcref);
|
||||
+ DeleteObject(This->desc.bmp.hbitmap);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -1081,23 +1067,25 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour
|
||||
if((*pixel & 0x80000000) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
- *pixel = black;
|
||||
+ *(DWORD *)(mask + stride * y + 4 * x) = black;
|
||||
}
|
||||
else
|
||||
- *pixel = white;
|
||||
+ *(DWORD *)(mask + stride * y + 4 * x) = white;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
- HDC hdcBmp, hdcXor, hdcMask;
|
||||
+ HDC hdcref, hdcBmp, hdcXor, hdcMask;
|
||||
HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
|
||||
|
||||
+ hdcref = GetDC(0);
|
||||
+
|
||||
This->hbmXor = CreateDIBitmap(
|
||||
hdcref,
|
||||
&bih,
|
||||
CBM_INIT,
|
||||
- bits,
|
||||
+ mask,
|
||||
(BITMAPINFO*)&bih,
|
||||
DIB_RGB_COLORS
|
||||
);
|
||||
@@ -1122,12 +1110,11 @@ static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSour
|
||||
DeleteDC(hdcBmp);
|
||||
DeleteDC(hdcXor);
|
||||
DeleteDC(hdcMask);
|
||||
+ ReleaseDC(0, hdcref);
|
||||
}
|
||||
|
||||
- ReleaseDC(0, hdcref);
|
||||
-
|
||||
end:
|
||||
- free(bits);
|
||||
+ free(mask);
|
||||
IWICBitmapSource_Release(real_source);
|
||||
return hr;
|
||||
}
|
||||
diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c
|
||||
index 02d53404e32..98d081b745e 100644
|
||||
--- a/dlls/oleaut32/tests/olepicture.c
|
||||
+++ b/dlls/oleaut32/tests/olepicture.c
|
||||
@@ -239,7 +239,7 @@ test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
|
||||
{
|
||||
BITMAP bmp;
|
||||
GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
|
||||
- todo_wine ok(bmp.bmBits != 0, "not a dib\n");
|
||||
+ ok(bmp.bmBits != 0, "not a dib\n");
|
||||
}
|
||||
|
||||
width = 0;
|
||||
--
|
||||
2.40.1
|
||||
|
@@ -1,93 +0,0 @@
|
||||
From e72c3ef9b52c3b5b099907c017206f168cff419f Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Wed, 5 Apr 2017 12:03:19 +0800
|
||||
Subject: [PATCH] oleaut32: Make OleLoadPicture load DIBs using WIC decoder.
|
||||
|
||||
CreateDIBSection doesn't support RLE compressed bitmaps.
|
||||
|
||||
This patch fixes a regression with displaying images in a Wix based
|
||||
installer.
|
||||
---
|
||||
dlls/oleaut32/olepicture.c | 21 +--------------------
|
||||
dlls/oleaut32/tests/olepicture.c | 12 +++++++++++-
|
||||
2 files changed, 12 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c
|
||||
index 22a34d6e380..37c3983ed21 100644
|
||||
--- a/dlls/oleaut32/olepicture.c
|
||||
+++ b/dlls/oleaut32/olepicture.c
|
||||
@@ -979,25 +979,6 @@ static HRESULT WINAPI OLEPictureImpl_IsDirty(
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
-static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||
-{
|
||||
- BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
|
||||
- BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
|
||||
- void *bits;
|
||||
- BITMAP bmp;
|
||||
-
|
||||
- This->desc.bmp.hbitmap = CreateDIBSection(0, bi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||
- if (This->desc.bmp.hbitmap == 0)
|
||||
- return E_FAIL;
|
||||
-
|
||||
- GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bmp), &bmp);
|
||||
- memcpy(bits, xbuf + bfh->bfOffBits, bmp.bmHeight * bmp.bmWidthBytes);
|
||||
-
|
||||
- This->desc.picType = PICTYPE_BITMAP;
|
||||
- OLEPictureImpl_SetBitmap(This);
|
||||
- return S_OK;
|
||||
-}
|
||||
-
|
||||
static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
|
||||
{
|
||||
HRESULT hr;
|
||||
@@ -1478,7 +1459,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm)
|
||||
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
|
||||
break;
|
||||
case BITMAP_FORMAT_BMP: /* Bitmap */
|
||||
- hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
|
||||
+ hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICBmpDecoder, xbuf, xread);
|
||||
break;
|
||||
case BITMAP_FORMAT_PNG: /* PNG */
|
||||
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
|
||||
diff --git a/dlls/oleaut32/tests/olepicture.c b/dlls/oleaut32/tests/olepicture.c
|
||||
index fa7e8009cbd..a1c3ccf20c3 100644
|
||||
--- a/dlls/oleaut32/tests/olepicture.c
|
||||
+++ b/dlls/oleaut32/tests/olepicture.c
|
||||
@@ -97,7 +97,7 @@ static const unsigned char pngimage[285] = {
|
||||
0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
|
||||
};
|
||||
|
||||
-/* 1x1 pixel bmp */
|
||||
+/* 1bpp BI_RGB 1x1 pixel bmp */
|
||||
static const unsigned char bmpimage[66] = {
|
||||
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
|
||||
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
|
||||
@@ -106,6 +106,15 @@ static const unsigned char bmpimage[66] = {
|
||||
0x00,0x00
|
||||
};
|
||||
|
||||
+/* 8bpp BI_RLE8 1x1 pixel bmp */
|
||||
+static const unsigned char bmpimage_rle8[] = {
|
||||
+0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
|
||||
+0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,
|
||||
+0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
|
||||
+0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x01,
|
||||
+0x00,0x00
|
||||
+};
|
||||
+
|
||||
/* 2x2 pixel gif */
|
||||
static const unsigned char gif4pixel[42] = {
|
||||
0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
|
||||
@@ -1492,6 +1501,7 @@ START_TEST(olepicture)
|
||||
test_pic(gifimage, sizeof(gifimage));
|
||||
test_pic(jpgimage, sizeof(jpgimage));
|
||||
test_pic(bmpimage, sizeof(bmpimage));
|
||||
+ test_pic(bmpimage_rle8, sizeof(bmpimage_rle8));
|
||||
test_pic(gif4pixel, sizeof(gif4pixel));
|
||||
/* FIXME: No PNG support in Windows... */
|
||||
if (0) test_pic(pngimage, sizeof(pngimage));
|
||||
--
|
||||
2.40.1
|
||||
|
@@ -1 +0,0 @@
|
||||
Fixes: [39474] Create DIB section in OleLoadPicture
|
@@ -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 a3f14d043f05ff7cfaf00bc548d02f32dd85cc8f Mon Sep 17 00:00:00 2001
|
||||
From 1569189e4213b5df68680c56e18f397873bc19aa Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sun, 15 Mar 2015 01:05:48 +0100
|
||||
Subject: [PATCH] server: Fix handling of GetMessage after previous PeekMessage
|
||||
@@ -15,10 +15,10 @@ Changes in v3:
|
||||
2 files changed, 65 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
|
||||
index 398bb0a69ed..2aec627604c 100644
|
||||
index 9282896262e..d4749a1eb57 100644
|
||||
--- a/dlls/user32/tests/msg.c
|
||||
+++ b/dlls/user32/tests/msg.c
|
||||
@@ -14353,13 +14353,10 @@ static void test_PeekMessage3(void)
|
||||
@@ -14478,13 +14478,10 @@ static void test_PeekMessage3(void)
|
||||
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
|
||||
PostMessageA(hwnd, WM_USER, 0, 0);
|
||||
ret = PeekMessageA(&msg, hwnd, 0, 0, PM_NOREMOVE);
|
||||
@@ -32,7 +32,7 @@ index 398bb0a69ed..2aec627604c 100644
|
||||
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
|
||||
ret = PeekMessageA(&msg, hwnd, 0, 0, 0);
|
||||
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
|
||||
@@ -14369,10 +14366,8 @@ static void test_PeekMessage3(void)
|
||||
@@ -14494,10 +14491,8 @@ static void test_PeekMessage3(void)
|
||||
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
|
||||
PostMessageA(hwnd, WM_USER, 0, 0);
|
||||
ret = PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE);
|
||||
@@ -43,7 +43,7 @@ index 398bb0a69ed..2aec627604c 100644
|
||||
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
|
||||
ret = PeekMessageA(&msg, hwnd, 0, 0, 0);
|
||||
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
|
||||
@@ -14384,10 +14379,11 @@ static void test_PeekMessage3(void)
|
||||
@@ -14509,10 +14504,11 @@ static void test_PeekMessage3(void)
|
||||
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
|
||||
PostMessageA(hwnd, WM_USER, 0, 0);
|
||||
ret = GetMessageA(&msg, hwnd, 0, 0);
|
||||
@@ -57,7 +57,7 @@ index 398bb0a69ed..2aec627604c 100644
|
||||
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
|
||||
ret = PeekMessageA(&msg, hwnd, 0, 0, 0);
|
||||
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
|
||||
@@ -14415,14 +14411,32 @@ static void test_PeekMessage3(void)
|
||||
@@ -14540,14 +14536,32 @@ static void test_PeekMessage3(void)
|
||||
ret = GetMessageA(&msg, hwnd, 0, 0);
|
||||
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
|
||||
ret = GetMessageA(&msg, hwnd, 0, 0);
|
||||
@@ -93,10 +93,10 @@ index 398bb0a69ed..2aec627604c 100644
|
||||
* because both messages are in the same queue. */
|
||||
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 4f58b795b7e..3fa5c05214e 100644
|
||||
index 520659d377c..2d23fb0def8 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -143,6 +143,7 @@ struct msg_queue
|
||||
@@ -133,6 +133,7 @@ struct msg_queue
|
||||
timeout_t last_get_msg; /* time of last get message call */
|
||||
int keystate_lock; /* owns an input keystate lock */
|
||||
const queue_shm_t *shared; /* queue in session shared memory */
|
||||
@@ -104,7 +104,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
};
|
||||
|
||||
struct hotkey
|
||||
@@ -309,6 +310,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
||||
@@ -312,6 +313,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
||||
queue->hooks = NULL;
|
||||
queue->last_get_msg = current_time;
|
||||
queue->keystate_lock = 0;
|
||||
@@ -112,7 +112,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
list_init( &queue->send_result );
|
||||
list_init( &queue->callback_result );
|
||||
list_init( &queue->pending_timers );
|
||||
@@ -725,13 +727,21 @@ static inline struct msg_queue *get_current_queue(void)
|
||||
@@ -792,13 +794,21 @@ static inline struct msg_queue *get_current_queue(void)
|
||||
}
|
||||
|
||||
/* get a (pseudo-)unique id to tag hardware messages */
|
||||
@@ -132,10 +132,10 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
+ return id;
|
||||
+}
|
||||
+
|
||||
/* try to merge a WM_MOUSEMOVE message with the last in the list; return 1 if successful */
|
||||
static int merge_mousemove( struct thread_input *input, const struct message *msg )
|
||||
/* lookup an already queued mouse message that matches the message, window and type */
|
||||
static struct message *find_mouse_message( struct thread_input *input, const struct message *msg )
|
||||
{
|
||||
@@ -1042,7 +1052,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win )
|
||||
@@ -1144,7 +1154,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win )
|
||||
}
|
||||
|
||||
/* retrieve a posted message */
|
||||
@@ -144,7 +144,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
unsigned int first, unsigned int last, unsigned int flags,
|
||||
struct get_message_reply *reply )
|
||||
{
|
||||
@@ -1053,6 +1063,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win,
|
||||
@@ -1155,6 +1165,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win,
|
||||
{
|
||||
if (!match_window( win, msg->win )) continue;
|
||||
if (!check_msg_filter( msg->msg, first, last )) continue;
|
||||
@@ -152,15 +152,15 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
goto found; /* found one */
|
||||
}
|
||||
return 0;
|
||||
@@ -1676,6 +1687,7 @@ found:
|
||||
@@ -1835,6 +1846,7 @@ found:
|
||||
msg->msg = WM_HOTKEY;
|
||||
msg->wparam = hotkey->id;
|
||||
msg->lparam = ((hotkey->vkey & 0xffff) << 16) | modifiers;
|
||||
+ msg->unique_id = get_unique_post_id();
|
||||
+ msg->unique_id = get_unique_hw_id();
|
||||
|
||||
free( msg->data );
|
||||
msg->data = NULL;
|
||||
@@ -2646,7 +2658,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
|
||||
@@ -2821,7 +2833,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
|
||||
}
|
||||
|
||||
/* now we can return it */
|
||||
@@ -169,7 +169,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
reply->type = MSG_HARDWARE;
|
||||
reply->win = win;
|
||||
reply->msg = msg_code;
|
||||
@@ -2753,6 +2765,7 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
|
||||
@@ -2928,6 +2940,7 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
|
||||
msg->result = NULL;
|
||||
msg->data = NULL;
|
||||
msg->data_size = 0;
|
||||
@@ -177,7 +177,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
|
||||
get_message_defaults( thread->queue, &msg->x, &msg->y, &msg->time );
|
||||
|
||||
@@ -3070,6 +3083,7 @@ DECL_HANDLER(send_message)
|
||||
@@ -3245,6 +3258,7 @@ DECL_HANDLER(send_message)
|
||||
set_queue_bits( recv_queue, QS_SENDMESSAGE );
|
||||
break;
|
||||
case MSG_POSTED:
|
||||
@@ -185,7 +185,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
list_add_tail( &recv_queue->msg_list[POST_MESSAGE], &msg->entry );
|
||||
set_queue_bits( recv_queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
|
||||
if (msg->msg == WM_HOTKEY)
|
||||
@@ -3202,12 +3216,12 @@ DECL_HANDLER(get_message)
|
||||
@@ -3379,12 +3393,12 @@ DECL_HANDLER(get_message)
|
||||
|
||||
/* then check for posted messages */
|
||||
if ((filter & QS_POSTMESSAGE) &&
|
||||
@@ -200,7 +200,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
return;
|
||||
|
||||
/* only check for quit messages if not posted messages pending */
|
||||
@@ -3218,7 +3232,7 @@ DECL_HANDLER(get_message)
|
||||
@@ -3395,7 +3409,7 @@ DECL_HANDLER(get_message)
|
||||
if ((filter & QS_INPUT) &&
|
||||
filter_contains_hw_range( req->get_first, req->get_last ) &&
|
||||
get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, req->flags, reply ))
|
||||
@@ -209,7 +209,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
|
||||
/* now check for WM_PAINT */
|
||||
if ((filter & QS_PAINT) &&
|
||||
@@ -3231,7 +3245,7 @@ DECL_HANDLER(get_message)
|
||||
@@ -3408,7 +3422,7 @@ DECL_HANDLER(get_message)
|
||||
reply->wparam = 0;
|
||||
reply->lparam = 0;
|
||||
get_message_defaults( queue, &reply->x, &reply->y, &reply->time );
|
||||
@@ -218,7 +218,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
}
|
||||
|
||||
/* now check for timer */
|
||||
@@ -3247,9 +3261,19 @@ DECL_HANDLER(get_message)
|
||||
@@ -3424,9 +3438,19 @@ DECL_HANDLER(get_message)
|
||||
get_message_defaults( queue, &reply->x, &reply->y, &reply->time );
|
||||
if (!(req->flags & PM_NOYIELD) && current->process->idle_event)
|
||||
set_event( current->process->idle_event );
|
||||
@@ -239,7 +239,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
if (get_win == -1 && current->process->idle_event) set_event( current->process->idle_event );
|
||||
|
||||
SHARED_WRITE_BEGIN( queue_shm, queue_shm_t )
|
||||
@@ -3260,6 +3284,13 @@ DECL_HANDLER(get_message)
|
||||
@@ -3437,6 +3461,13 @@ DECL_HANDLER(get_message)
|
||||
SHARED_WRITE_END;
|
||||
|
||||
set_error( STATUS_PENDING ); /* FIXME */
|
||||
@@ -253,7 +253,7 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
}
|
||||
|
||||
|
||||
@@ -3277,7 +3308,10 @@ DECL_HANDLER(reply_message)
|
||||
@@ -3454,7 +3485,10 @@ DECL_HANDLER(reply_message)
|
||||
DECL_HANDLER(accept_hardware_message)
|
||||
{
|
||||
if (current->queue)
|
||||
@@ -265,5 +265,5 @@ index 4f58b795b7e..3fa5c05214e 100644
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
2.47.2
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user