Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH v8 0/9] MR6: Avoid performance degradation due to vDSO unmapping (BZ#52313)
by Jinoh Kang (@iamahuman)
> at least that it should at least refuse a MAP_FIXED mmap that would overwrite things the JIT is using.
Unfortunately, there are a few problems in this approach of refusing to overwrite memory mappings used by the QEMU Linux user-mode emulator:
1. **Emulator detection**. We cannot reliably detect presence of QEMU in a way that is guaranteed to work in past and current *as well as* future QEMU versions. Any method of qemu-user detection would rely on the fact that the environment provided by QEMU is different in some way from a native one. As QEMU gets closer and closer to perfectly emulating the real thing, the discrepancies used to detect QEMU will become fewer and fewer, possibly rendering our detection method unusuable.
2. **Bug detection**. In the event that the bug is eventually fixed in a future QEMU version, it's not certain that there will be a way to detect this. For example, the SIGSEGV signal due to vDSO unmapping is not currently forwarded to the guest, so there's no way for the preloader to detect presence of the bug, or absence thereof.
I don't know if there is a significant portion of Wine user base that uses QEMU to run x86 apps on other architectures. If this is the case, though, we could implement a (possibly hacky) way to warn the user of such occasion, in a separate patch set.
> But changing from a strategy where wine wants to clobber it to one where wine just wants to move it might give qemu-user some better options. I haven't put enough thought into it yet to have a specific idea, just that this PR seemed like it would be helpful.
Now, here's the good news: with this patch set, you can elect to avoid unmapping or remapping the vDSO *entirely*. Simply specify the `WINEPRELOADREMAPVDSO=never` environment variable.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/6#note_2875
June 28, 2022
[PATCH v3 1/1] riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/tests/richole.c | 477 ++++++++++++++++++++++++++++++++++
1 file changed, 477 insertions(+)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 6a361bc3fa4..542de075bc6 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4955,6 +4955,481 @@ static void test_clipboard(void)
ITextRange_Release(range);
}
+static void subtest_undo(const char *dummy_text)
+{
+ static const char *text_seq[] = {
+ "",
+ "1-alpha",
+ "2-beta",
+ "3-gamma",
+ "4-delta",
+ "5-epsilon",
+ "6-zeta",
+ "7-eta",
+ };
+ static LONG seq[] = { -1, -2, -3, -1, 1, 2, 3, 1, -5, 2, -1, 3, 1, 0 };
+ LONG i = 0, stack_pos = 0;
+ IRichEditOle *reole = NULL;
+ ITextDocument *doc = NULL;
+ ITextSelection *selection;
+ char buffer[1024] = "";
+ HRESULT hr;
+ HWND hwnd;
+ LONG count = 0;
+
+ winetest_push_context("(%Iu)", dummy_text ? strlen(dummy_text) : 0);
+
+ create_interfaces(&hwnd, &reole, &doc, &selection);
+
+ for (i = -2; i <= 2; i++)
+ {
+ if (i != tomFalse && i != tomTrue)
+ {
+ hr = ITextDocument_Undo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld(a)0) Undo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, i, &count);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld(a)0) Undo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == (i >= 1 ? i : 0), "(%ld(a)0) Expected %ld, got %ld\n", i, i >= 0 ? i : 0, count);
+ }
+
+ hr = ITextDocument_Redo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld(a)0) Redo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, i, &count);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld(a)0) Redo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == 0, "(%ld(a)0) got %ld\n", i, count);
+ }
+
+ while (stack_pos < ARRAY_SIZE(text_seq) - 1)
+ {
+ stack_pos++;
+ if (dummy_text)
+ {
+ hr = ITextDocument_Undo(doc, tomSuspend, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ if (SUCCEEDED(hr))
+ {
+ SendMessageA(hwnd, EM_SETSEL, 0, 0);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)dummy_text);
+ SendMessageA(hwnd, EM_SETSEL, 0, strlen(dummy_text));
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)"");
+ hr = ITextDocument_Undo(doc, tomResume, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ }
+ }
+ SendMessageA(hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_seq[stack_pos]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(seq); i++)
+ {
+ LONG expect_count;
+
+ memset(buffer, 0, sizeof(buffer));
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ todo_wine_if(stack_pos != ARRAY_SIZE(text_seq) - 1)
+ ok(strcmp(buffer, text_seq[stack_pos]) == 0, "Expected %s, got %s\n",
+ wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer));
+
+ if (!seq[i]) break;
+
+ count = 0xcccccccc;
+ expect_count = labs(stack_pos - min(max(stack_pos + seq[i], 0), (LONG)ARRAY_SIZE(seq) - 1));
+ if (seq[i] < 0)
+ {
+ hr = ITextDocument_Undo(doc, -seq[i], &count);
+ todo_wine
+ ok(hr == S_OK, "(%ld@%ld) Undo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos -= count;
+ }
+ else
+ {
+ hr = ITextDocument_Redo(doc, seq[i], &count);
+ todo_wine
+ ok(hr == (expect_count ? S_OK : S_FALSE), "(%ld@%ld) Redo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos += count;
+ }
+
+ if (FAILED(hr) || count <= 0) break;
+ }
+
+ release_interfaces(&hwnd, &reole, &doc, &selection);
+ winetest_pop_context();
+}
+
+static void test_undo(void)
+{
+ subtest_undo(NULL);
+ subtest_undo("dummy 12345");
+}
+
+#define ok_msg_result(h,m,w,l,r) ok_msg_result_(__LINE__,#m,h,m,w,l,r)
+static void ok_msg_result_(int line, const char *desc, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT expect)
+{
+ LRESULT lresult = SendMessageA(hwnd, message, wparam, lparam);
+ ok_(__FILE__,line)(lresult == expect, "%s: Expected %Id, got %Id\n", desc, expect, lresult);
+}
+
+enum editorUndoState {
+ firstUndoState = 0,
+ undoStateActive = 0,
+ undoStateSuspended = 1,
+ undoStateDisabled = 2,
+ numUndoStates = 3,
+};
+
+enum editorUndoStateAction {
+ firstUndoAction = 0,
+ undoActionNoOp = 0,
+ undoActionEnable = 1,
+ undoActionDisable = 2,
+ undoActionSuspend = 3,
+ undoActionResume = 4,
+ numUndoActions = 5
+};
+
+enum editorUndoStateTestFlags {
+ undoTestUseWindowMessages = 0x1,
+ undoTestResetUndoLimit = 0x2,
+ undoTestDoFirstUndo = 0x4,
+ undoTestDoFirstRedo = 0x8,
+ undoTestMaxFlag = 0x10,
+};
+
+static const unsigned char undo_control_state_transitions[numUndoStates][numUndoActions] = {
+ /* undoStateActive */
+ {
+ undoStateActive, /* undoActionNoOp */
+ undoStateActive, /* undoActionEnable */
+ undoStateDisabled, /* undoActionDisable */
+ undoStateSuspended, /* undoActionSuspend */
+ undoStateActive /* undoActionResume */
+ },
+ /* undoStateSuspended */
+ {
+ undoStateSuspended, /* undoActionNoOp */
+ undoStateSuspended, /* undoActionEnable */
+ undoStateDisabled, /* undoActionDisable */
+ undoStateSuspended, /* undoActionSuspend */
+ undoStateActive /* undoActionResume */
+ },
+ /* undoStateDisabled */
+ {
+ undoStateDisabled, /* undoActionNoOp */
+ undoStateActive, /* undoActionEnable */
+ undoStateDisabled, /* undoActionDisable */
+ undoStateDisabled, /* undoActionSuspend */
+ undoStateActive /* undoActionResume */
+ }
+};
+
+struct undo_test
+{
+ HWND hwnd;
+ ITextDocument *doc;
+ int test_flags;
+ enum editorUndoState undo_ctl_state;
+ LONG_PTR undo_limit;
+ BOOL last_undo_status;
+ BOOL last_redo_status;
+};
+
+static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum editorUndoStateAction action, LONG *count)
+{
+ HRESULT hr = S_OK;
+
+ if (count) *count = 0xcccccccc;
+
+ switch (action)
+ {
+ case undoActionNoOp:
+ if (count) *count = 0;
+ break;
+ case undoActionEnable:
+ if (inst->test_flags & undoTestResetUndoLimit)
+ {
+ LONG_PTR cur_undo_limit = SendMessageA(inst->hwnd, EM_SETUNDOLIMIT, inst->undo_limit, 0);
+ ok(cur_undo_limit == inst->undo_limit, "Expected undo limit %Id, got %Id\n",
+ inst->undo_limit, cur_undo_limit);
+ if (count) *count = 0;
+ }
+ else
+ {
+ hr = ITextDocument_Undo(inst->doc, tomTrue, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ }
+ inst->last_undo_status = TRUE;
+ break;
+ case undoActionDisable:
+ hr = ITextDocument_Undo(inst->doc, tomFalse, count);
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ inst->last_undo_status = FALSE;
+ inst->last_redo_status = FALSE;
+ break;
+ case undoActionSuspend:
+ hr = ITextDocument_Undo(inst->doc, tomSuspend, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ break;
+ case undoActionResume:
+ hr = ITextDocument_Undo(inst->doc, tomResume, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ break;
+ default:
+ ok(0, "unreachable\n");
+ break;
+ }
+
+ if (count)
+ {
+ todo_wine
+ ok(*count == 0, "Got %ld\n", *count);
+ }
+ if (SUCCEEDED(hr))
+ {
+ inst->undo_ctl_state = undo_control_state_transitions[inst->undo_ctl_state][action];
+ }
+ return hr;
+}
+
+static HRESULT set_editor_undo_state(struct undo_test *inst, enum editorUndoState state)
+{
+ HRESULT hr = S_OK;
+ switch (state)
+ {
+ case undoStateActive:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionEnable, NULL))) break;
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionResume, NULL))) break;
+ break;
+ case undoStateSuspended:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionEnable, NULL))) break;
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionSuspend, NULL))) break;
+ break;
+ case undoStateDisabled:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionDisable, NULL))) break;
+ break;
+ default:
+ ok(0, "unreachable\n");
+ break;
+ }
+ ok(inst->undo_ctl_state == state, "expected state %d, got %d\n", state, inst->undo_ctl_state);
+ todo_wine
+ ok(SUCCEEDED(hr), "cannot set state to %d: %#lx\n", undoStateActive, hr);
+ return hr;
+}
+
+static BOOL perform_undo(struct undo_test *inst)
+{
+ LONG count;
+ HRESULT hr;
+ LRESULT lres;
+
+ if (inst->test_flags & undoTestUseWindowMessages)
+ {
+ lres = SendMessageA(inst->hwnd, EM_UNDO, 0, 0);
+ ok(lres == FALSE || lres == TRUE, "unexpected LRESULT %#Ix\n", lres);
+ return lres;
+ }
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(inst->doc, 1, &count);
+ todo_wine
+ ok(SUCCEEDED(hr), "got hr %#lx\n", hr);
+ todo_wine
+ ok(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
+ return hr == S_OK && count > 0;
+}
+
+static BOOL perform_redo(struct undo_test *inst)
+{
+ LONG count;
+ HRESULT hr;
+ LRESULT lres;
+
+ if (inst->test_flags & undoTestUseWindowMessages)
+ {
+ lres = SendMessageA(inst->hwnd, EM_REDO, 0, 0);
+ ok(lres == FALSE || lres == TRUE, "unexpected LRESULT %#Ix\n", lres);
+ return lres;
+ }
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(inst->doc, 1, &count);
+ todo_wine
+ ok(SUCCEEDED(hr), "got hr %#lx\n", hr);
+ todo_wine
+ ok(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
+ return hr == S_OK && count > 0;
+}
+
+static HRESULT subtest_undo_control(struct undo_test *inst, enum editorUndoStateAction action)
+{
+ LONG undo_count, redo_count, count;
+ static const char text_foo[] = "foo";
+ static const char text_bar[] = "bar";
+ static const char *last_text, *last_text2;
+ char buffer[1024] = "";
+ BOOL result;
+ HRESULT hr;
+
+ SendMessageA(inst->hwnd, EM_EMPTYUNDOBUFFER, 0, 0);
+ undo_count = redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+
+ SendMessageA(inst->hwnd, WM_SETTEXT, 0, (LPARAM)(last_text = ""));
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ last_text = "";
+ ok(strcmp(buffer, last_text) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(""), wine_dbgstr_a(buffer));
+
+ SendMessageA(inst->hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(inst->hwnd, EM_REPLACESEL, TRUE, (LPARAM)(last_text = text_foo));
+ if (inst->undo_ctl_state == undoStateActive) undo_count++, redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+
+ hr = perform_editor_undo_state_action(inst, action, &count);
+ ok(SUCCEEDED(hr), "failed to transition\n");
+ if (FAILED(hr)) return hr;
+ if (inst->undo_ctl_state == undoStateDisabled) undo_count = redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+
+ if (inst->test_flags & undoTestDoFirstUndo)
+ {
+ BOOL expect = FALSE;
+ result = perform_undo(inst);
+ if (inst->undo_ctl_state == undoStateActive)
+ {
+ if (undo_count > 0) inst->last_undo_status = TRUE;
+ expect = inst->last_undo_status;
+ }
+ ok(result == expect, "state %d: expected %d, got %d\n", inst->undo_ctl_state, expect, result);
+ if (result && undo_count > 0) undo_count--, redo_count++, last_text = "";
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text), wine_dbgstr_a(buffer));
+ }
+
+ if (inst->test_flags & undoTestDoFirstRedo)
+ {
+ BOOL expect = FALSE;
+ result = perform_redo(inst);
+ if (inst->undo_ctl_state == undoStateActive)
+ {
+ if (redo_count > 0) inst->last_redo_status = TRUE;
+ expect = inst->last_redo_status;
+ }
+ ok(result == expect, "state %d: expected %d, got %d\n", inst->undo_ctl_state, expect, result);
+ if (result && redo_count > 0) undo_count++, redo_count--, last_text = text_foo;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text), wine_dbgstr_a(buffer));
+ }
+
+ SendMessageA(inst->hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(inst->hwnd, EM_REPLACESEL, TRUE, (LPARAM)(last_text2 = text_bar));
+ if (inst->undo_ctl_state == undoStateActive) undo_count++, redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ result = perform_undo(inst);
+ if (undo_count > 0) inst->last_undo_status = TRUE;
+ ok((inst->undo_ctl_state == undoStateActive) == result, "state %d: got %d\n", inst->undo_ctl_state, result);
+ if (result && undo_count > 0) undo_count--, redo_count++, last_text2 = last_text;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ result = perform_redo(inst);
+ if (redo_count > 0) inst->last_redo_status = TRUE;
+ ok((inst->undo_ctl_state == undoStateActive) == result, "state %d: got %d\n", inst->undo_ctl_state, result);
+ if (result && redo_count > 0) undo_count++, redo_count--, last_text2 = text_bar;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ return S_OK;
+}
+
+static void test_undo_control(void)
+{
+ enum editorUndoState state0;
+ enum editorUndoStateAction action0, action1;
+ IRichEditOle *reole = NULL;
+ ITextSelection *selection;
+ struct undo_test inst = { NULL };
+ HRESULT hr;
+
+ create_interfaces(&inst.hwnd, &reole, &inst.doc, &selection);
+ inst.undo_ctl_state = undoStateActive;
+ inst.last_undo_status = TRUE;
+ inst.last_redo_status = TRUE;
+ inst.undo_limit = SendMessageA(inst.hwnd, EM_SETUNDOLIMIT, 100, 0);
+ ok(inst.undo_limit >= 1, "Message EM_SETUNDOLIMIT returned %#Ix\n", inst.undo_limit);
+
+ hr = set_editor_undo_state(&inst, undoStateActive);
+ if (SUCCEEDED(hr))
+ {
+ for (inst.test_flags = 0; inst.test_flags < undoTestMaxFlag; inst.test_flags++)
+ {
+ for (state0 = firstUndoState; state0 < numUndoStates; state0++)
+ {
+ for (action0 = firstUndoAction; action0 < numUndoActions; action0++)
+ {
+ for (action1 = firstUndoAction; action1 < numUndoActions; action1++)
+ {
+ winetest_push_context("%x:%d:%d >?:%d", inst.test_flags, state0, action0, action1);
+ hr = set_editor_undo_state(&inst, state0);
+ winetest_pop_context();
+
+ if (FAILED(hr)) continue;
+
+ winetest_push_context("%x:%d:%d+>?:%d", inst.test_flags, state0, action0, action1);
+ hr = subtest_undo_control(&inst, action0);
+ winetest_pop_context();
+
+ if (FAILED(hr)) continue;
+
+ winetest_push_context("%x:%d:%d>%d:%d+", inst.test_flags, state0, action0, inst.undo_ctl_state, action1);
+ subtest_undo_control(&inst, action1);
+ winetest_pop_context();
+ }
+ }
+ }
+ }
+ }
+
+ release_interfaces(&inst.hwnd, &reole, &inst.doc, &selection);
+}
+
START_TEST(richole)
{
/* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -4996,4 +5471,6 @@ START_TEST(richole)
test_MoveEnd_story();
test_character_movement();
test_clipboard();
+ test_undo();
+ test_undo_control();
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/320
June 28, 2022
[PATCH v3 0/1] MR320: riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
by Jinoh Kang (@iamahuman)
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
--
v3: riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
https://gitlab.winehq.org/wine/wine/-/merge_requests/320
June 28, 2022
[PATCH 2/2] kernelbase: Add QueryVirtualMemoryInformation().
by Nikolay Sivov
From: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/kernelbase/kernelbase.spec | 2 +-
dlls/kernelbase/memory.c | 17 +++++++++++++
include/memoryapi.h | 45 +++++++++++++++++++++++++++++++++
include/winbase.h | 1 +
4 files changed, 64 insertions(+), 1 deletion(-)
create mode 100644 include/memoryapi.h
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 1296757b29a..07664646983 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1248,7 +1248,7 @@
@ stdcall QueryThreadpoolStackInformation(ptr ptr)
@ stdcall QueryUnbiasedInterruptTime(ptr) ntdll.RtlQueryUnbiasedInterruptTime
# @ stub QueryUnbiasedInterruptTimePrecise
-# @ stub QueryVirtualMemoryInformation
+@ stdcall QueryVirtualMemoryInformation(long ptr long ptr long ptr)
@ stdcall QueryWorkingSet(long ptr long)
@ stdcall QueryWorkingSetEx(long ptr long)
@ stdcall QueueUserAPC(ptr long long)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index e24a6f9aad0..09ab8fdc895 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -1390,6 +1390,23 @@ LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAllocExNuma( HANDLE process, void *addr,
}
+/***********************************************************************
+ * QueryVirtualMemoryInformation (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH QueryVirtualMemoryInformation( HANDLE process, const void *addr,
+ WIN32_MEMORY_INFORMATION_CLASS info_class, void *info, SIZE_T size, SIZE_T *ret_size)
+{
+ switch (info_class)
+ {
+ case MemoryRegionInfo:
+ return set_ntstatus( NtQueryVirtualMemory( process, addr, MemoryRegionInformation, info, size, ret_size ));
+ default:
+ FIXME("Unsupported info class %u.\n", info_class);
+ return FALSE;
+ }
+}
+
+
/***********************************************************************
* CPU functions
***********************************************************************/
diff --git a/include/memoryapi.h b/include/memoryapi.h
new file mode 100644
index 00000000000..8743e67927c
--- /dev/null
+++ b/include/memoryapi.h
@@ -0,0 +1,45 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+typedef enum WIN32_MEMORY_INFORMATION_CLASS
+{
+ MemoryRegionInfo
+} WIN32_MEMORY_INFORMATION_CLASS;
+
+typedef struct WIN32_MEMORY_REGION_INFORMATION
+{
+ PVOID AllocationBase;
+ ULONG AllocationProtect;
+ union
+ {
+ ULONG Flags;
+ struct
+ {
+ ULONG Private : 1;
+ ULONG MappedDataFile : 1;
+ ULONG MappedImage : 1;
+ ULONG MappedPageFile : 1;
+ ULONG MappedPhysical : 1;
+ ULONG DirectMapped : 1;
+ ULONG Reserved : 26;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ SIZE_T RegionSize;
+ SIZE_T CommitSize;
+} WIN32_MEMORY_REGION_INFORMATION;
+
+BOOL WINAPI QueryVirtualMemoryInformation(HANDLE process,const void *addr,
+ WIN32_MEMORY_INFORMATION_CLASS info_class, void *info, SIZE_T size, SIZE_T *ret_size);
diff --git a/include/winbase.h b/include/winbase.h
index bf191153ddc..1c83a5350d4 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -43,6 +43,7 @@ extern "C" {
#include <processthreadsapi.h>
#include <synchapi.h>
#include <threadpoolapiset.h>
+#include <memoryapi.h>
/* Windows Exit Procedure flag values */
#define WEP_FREE_DLL 0
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/333
June 28, 2022
[PATCH 1/2] ntdll: Partially implement MemoryRegionInformation query.
by Nikolay Sivov
From: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ntdll/tests/virtual.c | 97 +++++++++++++++++++++++++++++++
dlls/ntdll/unix/virtual.c | 115 +++++++++++++++++++++++++------------
dlls/wow64/struct32.h | 11 ++++
dlls/wow64/virtual.c | 23 ++++++++
include/winternl.h | 24 ++++++++
5 files changed, 233 insertions(+), 37 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 24c87c46d26..221b1d252ee 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -1434,6 +1434,102 @@ static void test_NtFreeVirtualMemory(void)
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
}
+static void test_query_region_information(void)
+{
+ MEMORY_REGION_INFORMATION info;
+ LARGE_INTEGER offset;
+ SIZE_T len, size;
+ NTSTATUS status;
+ HANDLE mapping;
+ void *ptr;
+
+ size = 0x10000;
+ ptr = NULL;
+ status = NtAllocateVirtualMemory(NtCurrentProcess(), &ptr, 0, &size, MEM_RESERVE, PAGE_READWRITE);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+#if _WIN64
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info,
+ FIELD_OFFSET(MEMORY_REGION_INFORMATION, PartitionId), &len);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info,
+ FIELD_OFFSET(MEMORY_REGION_INFORMATION, CommitSize), &len);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info,
+ FIELD_OFFSET(MEMORY_REGION_INFORMATION, RegionSize), &len);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %08lx.\n", status);
+#endif
+
+ len = 0;
+ memset(&info, 0x11, sizeof(info));
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info, sizeof(info), &len);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(info.AllocationBase == ptr, "Unexpected base %p.\n", info.AllocationBase);
+ ok(info.AllocationProtect == PAGE_READWRITE, "Unexpected protection %lu.\n", info.AllocationProtect);
+ ok(!info.Private, "Unexpected flag %d.\n", info.Private);
+ ok(!info.MappedDataFile, "Unexpected flag %d.\n", info.MappedDataFile);
+ ok(!info.MappedImage, "Unexpected flag %d.\n", info.MappedImage);
+ ok(!info.MappedPageFile, "Unexpected flag %d.\n", info.MappedPageFile);
+ ok(!info.MappedPhysical, "Unexpected flag %d.\n", info.MappedPhysical);
+ ok(!info.DirectMapped, "Unexpected flag %d.\n", info.DirectMapped);
+ ok(info.RegionSize == size, "Unexpected region size.\n");
+
+ size = 0;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &ptr, &size, MEM_RELEASE);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ /* Committed size */
+ size = 0x10000;
+ ptr = NULL;
+ status = NtAllocateVirtualMemory(NtCurrentProcess(), &ptr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ memset(&info, 0x11, sizeof(info));
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info, sizeof(info), &len);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(info.AllocationBase == ptr, "Unexpected base %p.\n", info.AllocationBase);
+ ok(info.AllocationProtect == PAGE_READWRITE, "Unexpected protection %lu.\n", info.AllocationProtect);
+ ok(!info.Private, "Unexpected flag %d.\n", info.Private);
+ ok(!info.MappedDataFile, "Unexpected flag %d.\n", info.MappedDataFile);
+ ok(!info.MappedImage, "Unexpected flag %d.\n", info.MappedImage);
+ ok(!info.MappedPageFile, "Unexpected flag %d.\n", info.MappedPageFile);
+ ok(!info.MappedPhysical, "Unexpected flag %d.\n", info.MappedPhysical);
+ ok(!info.DirectMapped, "Unexpected flag %d.\n", info.DirectMapped);
+ ok(info.RegionSize == size, "Unexpected region size.\n");
+
+ size = 0;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &ptr, &size, MEM_RELEASE);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ /* Pagefile mapping */
+ mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
+ ok(mapping != 0, "CreateFileMapping failed\n");
+
+ ptr = NULL;
+ size = 0;
+ offset.QuadPart = 0;
+ status = NtMapViewOfSection(mapping, NtCurrentProcess(), &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READONLY);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ memset(&info, 0x11, sizeof(info));
+ status = NtQueryVirtualMemory(NtCurrentProcess(), ptr, MemoryRegionInformation, &info, sizeof(info), &len);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ ok(info.AllocationBase == ptr, "Unexpected base %p.\n", info.AllocationBase);
+ ok(info.AllocationProtect == PAGE_READONLY, "Unexpected protection %lu.\n", info.AllocationProtect);
+ ok(!info.Private, "Unexpected flag %d.\n", info.Private);
+ ok(!info.MappedDataFile, "Unexpected flag %d.\n", info.MappedDataFile);
+ ok(!info.MappedImage, "Unexpected flag %d.\n", info.MappedImage);
+ ok(!info.MappedPageFile, "Unexpected flag %d.\n", info.MappedPageFile);
+ ok(!info.MappedPhysical, "Unexpected flag %d.\n", info.MappedPhysical);
+ ok(!info.DirectMapped, "Unexpected flag %d.\n", info.DirectMapped);
+ ok(info.RegionSize == 4096, "Unexpected region size.\n");
+
+ status = NtUnmapViewOfSection(NtCurrentProcess(), ptr);
+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+
+ NtClose(mapping);
+}
+
START_TEST(virtual)
{
HMODULE mod;
@@ -1477,4 +1573,5 @@ START_TEST(virtual)
test_NtMapViewOfSectionEx();
test_user_shared_data();
test_syscalls();
+ test_query_region_information();
}
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index a93d5b4174a..ad9955d35fb 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -4080,48 +4080,13 @@ static int get_free_mem_state_callback( void *start, SIZE_T size, void *arg )
return 1;
}
-/* get basic information about a memory block */
-static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
- MEMORY_BASIC_INFORMATION *info,
- SIZE_T len, SIZE_T *res_len )
+static NTSTATUS fill_basic_memory_info( const void *addr, MEMORY_BASIC_INFORMATION *info )
{
- struct file_view *view;
char *base, *alloc_base = 0, *alloc_end = working_set_limit;
struct wine_rb_entry *ptr;
+ struct file_view *view;
sigset_t sigset;
- if (len < sizeof(MEMORY_BASIC_INFORMATION))
- return STATUS_INFO_LENGTH_MISMATCH;
-
- if (process != NtCurrentProcess())
- {
- NTSTATUS status;
- apc_call_t call;
- apc_result_t result;
-
- memset( &call, 0, sizeof(call) );
-
- call.virtual_query.type = APC_VIRTUAL_QUERY;
- call.virtual_query.addr = wine_server_client_ptr( addr );
- status = server_queue_process_apc( process, &call, &result );
- if (status != STATUS_SUCCESS) return status;
-
- if (result.virtual_query.status == STATUS_SUCCESS)
- {
- info->BaseAddress = wine_server_get_ptr( result.virtual_query.base );
- info->AllocationBase = wine_server_get_ptr( result.virtual_query.alloc_base );
- info->RegionSize = result.virtual_query.size;
- info->Protect = result.virtual_query.prot;
- info->AllocationProtect = result.virtual_query.alloc_prot;
- info->State = (DWORD)result.virtual_query.state << 12;
- info->Type = (DWORD)result.virtual_query.alloc_type << 16;
- if (info->RegionSize != result.virtual_query.size) /* truncated */
- return STATUS_INVALID_PARAMETER; /* FIXME */
- if (res_len) *res_len = sizeof(*info);
- }
- return result.virtual_query.status;
- }
-
base = ROUND_ADDR( addr, page_mask );
if (is_beyond_limit( base, 1, working_set_limit )) return STATUS_INVALID_PARAMETER;
@@ -4195,6 +4160,79 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
}
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
+ return STATUS_SUCCESS;
+}
+
+/* get basic information about a memory block */
+static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
+ MEMORY_BASIC_INFORMATION *info,
+ SIZE_T len, SIZE_T *res_len )
+{
+ NTSTATUS status;
+
+ if (len < sizeof(*info))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ if (process != NtCurrentProcess())
+ {
+ NTSTATUS status;
+ apc_call_t call;
+ apc_result_t result;
+
+ memset( &call, 0, sizeof(call) );
+
+ call.virtual_query.type = APC_VIRTUAL_QUERY;
+ call.virtual_query.addr = wine_server_client_ptr( addr );
+ status = server_queue_process_apc( process, &call, &result );
+ if (status != STATUS_SUCCESS) return status;
+
+ if (result.virtual_query.status == STATUS_SUCCESS)
+ {
+ info->BaseAddress = wine_server_get_ptr( result.virtual_query.base );
+ info->AllocationBase = wine_server_get_ptr( result.virtual_query.alloc_base );
+ info->RegionSize = result.virtual_query.size;
+ info->Protect = result.virtual_query.prot;
+ info->AllocationProtect = result.virtual_query.alloc_prot;
+ info->State = (DWORD)result.virtual_query.state << 12;
+ info->Type = (DWORD)result.virtual_query.alloc_type << 16;
+ if (info->RegionSize != result.virtual_query.size) /* truncated */
+ return STATUS_INVALID_PARAMETER; /* FIXME */
+ if (res_len) *res_len = sizeof(*info);
+ }
+ return result.virtual_query.status;
+ }
+
+ if ((status = fill_basic_memory_info( addr, info ))) return status;
+
+ if (res_len) *res_len = sizeof(*info);
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS get_memory_region_info( HANDLE process, LPCVOID addr, MEMORY_REGION_INFORMATION *info,
+ SIZE_T len, SIZE_T *res_len )
+{
+ MEMORY_BASIC_INFORMATION basic_info;
+ NTSTATUS status;
+
+ if (len < FIELD_OFFSET(MEMORY_REGION_INFORMATION, CommitSize))
+ return STATUS_INFO_LENGTH_MISMATCH;
+
+ if (process != NtCurrentProcess())
+ {
+ FIXME("Unimplemented for other processes.\n");
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if ((status = fill_basic_memory_info( addr, &basic_info ))) return status;
+
+ info->AllocationBase = basic_info.AllocationBase;
+ info->AllocationProtect = basic_info.AllocationProtect;
+ info->RegionType = 0; /* FIXME */
+ if (len >= FIELD_OFFSET(MEMORY_REGION_INFORMATION, CommitSize))
+ info->RegionSize = basic_info.RegionSize;
+ if (len >= FIELD_OFFSET(MEMORY_REGION_INFORMATION, PartitionId))
+ info->CommitSize = basic_info.State == MEM_COMMIT ? basic_info.RegionSize : 0;
+
if (res_len) *res_len = sizeof(*info);
return STATUS_SUCCESS;
}
@@ -4366,6 +4404,9 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
case MemoryMappedFilenameInformation:
return get_memory_section_name( process, addr, buffer, len, res_len );
+ case MemoryRegionInformation:
+ return get_memory_region_info( process, addr, buffer, len, res_len );
+
case MemoryWineUnixFuncs:
case MemoryWineUnixWow64Funcs:
if (len != sizeof(unixlib_handle_t)) return STATUS_INFO_LENGTH_MISMATCH;
diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h
index b096c8d587b..b4762c1c5ee 100644
--- a/dlls/wow64/struct32.h
+++ b/dlls/wow64/struct32.h
@@ -156,6 +156,17 @@ typedef struct
DWORD Type;
} MEMORY_BASIC_INFORMATION32;
+typedef struct
+{
+ ULONG AllocationBase;
+ ULONG AllocationProtect;
+ ULONG RegionType;
+ ULONG RegionSize;
+ ULONG CommitSize;
+ ULONG PartitionId;
+ ULONG NodePreference;
+} MEMORY_REGION_INFORMATION32;
+
typedef struct
{
UNICODE_STRING32 SectionFileName;
diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c
index c21464857fa..2aed0fc854a 100644
--- a/dlls/wow64/virtual.c
+++ b/dlls/wow64/virtual.c
@@ -404,6 +404,29 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args )
break;
}
+ case MemoryRegionInformation: /* MEMORY_REGION_INFORMATION */
+ {
+ if (len >= sizeof(MEMORY_REGION_INFORMATION32))
+ {
+ MEMORY_REGION_INFORMATION info;
+ MEMORY_REGION_INFORMATION32 *info32 = ptr;
+
+ if (!(status = NtQueryVirtualMemory( handle, addr, class, &info, sizeof(info), &res_len )))
+ {
+ info32->AllocationBase = PtrToUlong( info.AllocationBase );
+ info32->AllocationProtect = info.AllocationProtect;
+ info32->RegionType = info.RegionType;
+ info32->RegionSize = info.RegionSize;
+ info32->CommitSize = info.CommitSize;
+ info32->PartitionId = info.PartitionId;
+ info32->NodePreference = info.NodePreference;
+ }
+ }
+ else status = STATUS_INFO_LENGTH_MISMATCH;
+ res_len = sizeof(MEMORY_REGION_INFORMATION32);
+ break;
+ }
+
case MemoryWorkingSetExInformation: /* MEMORY_WORKING_SET_EX_INFORMATION */
{
MEMORY_WORKING_SET_EX_INFORMATION32 *info32 = ptr;
diff --git a/include/winternl.h b/include/winternl.h
index 85aac653a21..ece7a998ba7 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1971,6 +1971,30 @@ typedef struct _MEMORY_WORKING_SET_EX_INFORMATION {
MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes;
} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION;
+typedef struct _MEMORY_REGION_INFORMATION
+{
+ PVOID AllocationBase;
+ ULONG AllocationProtect;
+ union
+ {
+ ULONG RegionType;
+ struct
+ {
+ ULONG Private : 1;
+ ULONG MappedDataFile : 1;
+ ULONG MappedImage : 1;
+ ULONG MappedPageFile : 1;
+ ULONG MappedPhysical : 1;
+ ULONG DirectMapped : 1;
+ ULONG Reserved : 26;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ SIZE_T RegionSize;
+ SIZE_T CommitSize;
+ ULONG_PTR PartitionId;
+ ULONG_PTR NodePreference;
+} MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION;
+
typedef enum _MUTANT_INFORMATION_CLASS
{
MutantBasicInformation
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/333
June 28, 2022
[PATCH 0/2] MR333: kernelbase: Add QueryVirtualMemoryInformation().
by Nikolay Sivov (@nsivov)
https://bugs.winehq.org/show_bug.cgi?id=53288
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/333
June 28, 2022
Re: [PATCH v2 0/1] MR315: windowscodecs: Fix non-zero alpha detection in ImagingFactory_CreateBitmapFromHICON.
by Jinoh Kang (@iamahuman)
v2: Fold nested for loop.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/315#note_2872
June 28, 2022
[PATCH v2 1/1] windowscodecs: Fix non-zero alpha detection in ImagingFactory_CreateBitmapFromHICON.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Increment pixel pointer for every *pixel*, not every *stride*.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/windowscodecs/imgfactory.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/imgfactory.c b/dlls/windowscodecs/imgfactory.c
index c7e101e3d62..07f5b53fefd 100644
--- a/dlls/windowscodecs/imgfactory.c
+++ b/dlls/windowscodecs/imgfactory.c
@@ -901,16 +901,14 @@ static HRESULT WINAPI ImagingFactory_CreateBitmapFromHICON(IWICImagingFactory2 *
if (bm.bmBitsPixel == 32)
{
/* If any pixel has a non-zero alpha, ignore hbmMask */
- bits = (DWORD *)buffer;
- for (x = 0; x < width && !has_alpha; x++, bits++)
+ DWORD *ptr = (DWORD *)buffer;
+ DWORD *end = ptr + width * height;
+ while (ptr != end)
{
- for (y = 0; y < height; y++)
+ if (*ptr++ & 0xff000000)
{
- if (*bits & 0xff000000)
- {
- has_alpha = TRUE;
- break;
- }
+ has_alpha = TRUE;
+ break;
}
}
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/315
June 28, 2022
[PATCH v2 0/1] MR315: windowscodecs: Fix non-zero alpha detection in ImagingFactory_CreateBitmapFromHICON.
by Jinoh Kang (@iamahuman)
Increment pixel pointer for every *pixel*, not every *stride*.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
--
v2: windowscodecs: Fix non-zero alpha detection in ImagingFactory_CreateBitmapFromHICON.
https://gitlab.winehq.org/wine/wine/-/merge_requests/315
June 28, 2022
Re: [PATCH 3/3] d3dx10_43: Support creating effect from pre-built shader
by Marvin
Hi,
It looks like your patch introduced the new failures shown below.
Please investigate and fix them before resubmitting your patch.
If they are not new, fixing them anyway would help a lot. Otherwise
please ask for the known failures list to be updated.
The full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=117785
Your paranoid android.
=== debian11 (32 bit WoW report) ===
d3dx10_43:
Unhandled exception: assertion failed in 32-bit code (0xf7f66559).
June 28, 2022