[PATCH 1/3] comctl32/tests: toolbar button text length and validity

Giuseppe Bilotta giuseppe.bilotta at gmail.com
Thu Apr 23 11:02:26 CDT 2009


Windows API documentation suggests sending the TB_GETBUTTONTEXT message
with a NULL destination pointer to get the button text length. This is
currently not implemented properly in Wine.

Additionally, Windows ignores the iString field for separators, so even
if programs forget to initialize it and its bit pattern is an invalid
pointer, no crashes or failures can be seen. An uninitialized iString
field resembling an invalid pointer currently crashes Wine.

Older Windows versions (up to Windows 2003 inclusive) will not complain
if a non-separator button with an invalid pointer iString pointer is
added to a toolbar, although subsequently trying to access the button
text might cause a crash. In some versions of Vista the SendMessage will
fail but the program will not crash. In other versions of Vista, and in
Windows 2008, the program will crash on insertion.
---
 dlls/comctl32/tests/toolbar.c |   70 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c
index 1946095..dad2218 100644
--- a/dlls/comctl32/tests/toolbar.c
+++ b/dlls/comctl32/tests/toolbar.c
@@ -1300,6 +1300,75 @@ static void test_getstring(void)
     DestroyWindow(hToolbar);
 }
 
+static void test_getbuttontext(void)
+{
+    HWND hToolbar = NULL;
+    TBBUTTON buttons[3];
+    WCHAR strW[4] = { 'S', 'E', 'P', 0 };
+    INT r;
+
+    rebuild_toolbar(&hToolbar);
+
+    buttons[0].idCommand = 0;
+    buttons[0].fsStyle = BTNS_BUTTON;
+    buttons[0].fsState = 0;
+    buttons[0].iString = (int)(LPWSTR)strW;
+
+    buttons[1].idCommand = 0;
+    buttons[1].fsStyle = BTNS_SEP;
+    buttons[1].fsState = 0;
+    buttons[1].iString = (int)(LPWSTR)strW;
+
+    /* Some programs (e.g. Graphmatica 2.0f) forget to initialize the iString
+     * field for separators. If the random bit pattern of this field looks like
+     * a pointer, trying to follow it casues a crash (pagefault). This does not
+     * happen in Windows XP, 2008 or Vista. */
+    buttons[2].idCommand = 0;
+    buttons[2].fsStyle = BTNS_SEP;
+    buttons[2].fsState = TBSTATE_ENABLED;
+    buttons[2].iString = 0xdeadbeef;
+
+    r = SendMessage(hToolbar, TB_ADDBUTTONSW, 3, (LPARAM)buttons);
+    expect(1, r);
+
+    /* Get the button text length. */
+    r = SendMessage(hToolbar, TB_GETBUTTONTEXT, 0, (LPARAM)NULL);
+    expect(3, r);
+    r = SendMessage(hToolbar, TB_GETBUTTONTEXT, 1, (LPARAM)NULL);
+    expect(-1, r);
+    r = SendMessage(hToolbar, TB_GETBUTTONTEXT, 2, (LPARAM)NULL);
+    expect(-1, r);
+
+if (0) {
+    /* It is also possible that a poorly written program doesn't initialize the
+     * iString field of an actual button. Different versions of Windows seem to
+     * operate differently in this case.
+     *   + Windows 95, XP, 2k3 accept the invalid pointer
+     *   + Windows 2k8 crashes
+     *   + some Windows Vista versions crash, others don't crash but the
+     *     insertion call fails
+     * Even if insertion succeeds, subsequently retrieving the button text may
+     * crash. Or it may not. */
+
+    buttons[3].idCommand = 1;
+    buttons[3].fsStyle = BTNS_BUTTON;
+    buttons[3].fsState = 0;
+    buttons[3].iString = 0xdeadbeef;
+
+    r = SendMessage(hToolbar, TB_ADDBUTTONSW, 1, (LPARAM)(buttons+3));
+    expect(1, r);
+    r = SendMessage(hToolbar, TB_GETBUTTONTEXT, 3, (LPARAM)NULL);
+    expect(-1, r);
+}
+
+    /* TODO: another test that might be worth doing, to get more insight on how
+     * Windows handles things, would be to introduce a separator with
+     * 0xdeadbeef as iString, and then change its style to make into a real
+     * button. */
+
+    DestroyWindow(hToolbar);
+}
+
 START_TEST(toolbar)
 {
     WNDCLASSA wc;
@@ -1336,6 +1405,7 @@ START_TEST(toolbar)
     test_dispinfo();
     test_setrows();
     test_getstring();
+    test_getbuttontext();
 
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {
-- 
1.6.2.254.g84bde




More information about the wine-patches mailing list