Mikołaj Zalewski : comctl32: header: Fix INSERTITEM on a zero mask and GETITEM on a mask with unknown fields.

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 16 13:54:29 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 36a8e5fba340cc15a2e76bbd5608772b8bce4dff
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=36a8e5fba340cc15a2e76bbd5608772b8bce4dff

Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date:   Tue May 16 00:10:08 2006 +0200

comctl32: header: Fix INSERTITEM on a zero mask and GETITEM on a mask with unknown fields.

INSERTITEM should fail on a zero mask. If in GETITEM the mask has an
unknown field it should store only the comctl32 4.0 fields (with test
case).

---

 dlls/comctl32/header.c       |   37 +++++++++++++++++++---------
 dlls/comctl32/tests/header.c |   56 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index dc533e1..4dec2d7 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -98,6 +98,11 @@ #define MAX_HEADER_TEXT_LEN 260
 #define HDN_UNICODE_OFFSET 20
 #define HDN_FIRST_UNICODE (HDN_FIRST-HDN_UNICODE_OFFSET)
 
+#define HDI_SUPPORTED_FIELDS (HDI_WIDTH|HDI_TEXT|HDI_FORMAT|HDI_LPARAM|HDI_BITMAP|HDI_IMAGE|HDI_ORDER)
+#define HDI_UNSUPPORTED_FIELDS (HDI_FILTER)
+#define HDI_UNKNOWN_FIELDS (~(HDI_SUPPORTED_FIELDS|HDI_UNSUPPORTED_FIELDS|HDI_DI_SETITEM))
+#define HDI_COMCTL32_4_0_FIELDS (HDI_WIDTH|HDI_TEXT|HDI_FORMAT|HDI_LPARAM|HDI_BITMAP)
+
 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0))
 
 static BOOL HEADER_PrepareCallbackItems(HWND hwnd, INT iItem, INT reqMask);
@@ -116,6 +121,9 @@ static void HEADER_DisposeItem(HEADER_IT
 
 static void HEADER_StoreHDItemInHeader(HEADER_ITEM *lpItem, UINT mask, HDITEMW *phdi, BOOL fUnicode)
 {
+    if (mask & HDI_UNSUPPORTED_FIELDS)
+        FIXME("unsupported header fields %x\n", (mask & HDI_UNSUPPORTED_FIELDS));
+    
     if (mask & HDI_BITMAP)
         lpItem->hbm = phdi->hbm;
 
@@ -955,41 +963,46 @@ HEADER_GetItemT (HWND hwnd, INT nItem, L
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
     HEADER_ITEM *lpItem;
+    UINT mask = phdi->mask;
 
     if (!phdi)
 	return FALSE;
 
     TRACE("[nItem=%d]\n", nItem);
 
-    if (phdi->mask == 0)
+    if (mask == 0)
 	return TRUE;
     if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
         return FALSE;
 
+    if (mask & HDI_UNKNOWN_FIELDS)
+    {
+        TRACE("mask %x contains unknown fields. Using only comctl32 4.0 fields\n", mask);
+        mask &= HDI_COMCTL32_4_0_FIELDS;
+    }
+    
     lpItem = &infoPtr->items[nItem];
-    HEADER_PrepareCallbackItems(hwnd, nItem, phdi->mask);
+    HEADER_PrepareCallbackItems(hwnd, nItem, mask);
 
-    if (phdi->mask & HDI_BITMAP)
+    if (mask & HDI_BITMAP)
         phdi->hbm = lpItem->hbm;
 
-    if (phdi->mask & HDI_FORMAT)
+    if (mask & HDI_FORMAT)
         phdi->fmt = lpItem->fmt;
 
-    if (phdi->mask & HDI_WIDTH)
+    if (mask & HDI_WIDTH)
         phdi->cxy = lpItem->cxy;
 
-    if (phdi->mask & HDI_LPARAM)
+    if (mask & HDI_LPARAM)
         phdi->lParam = lpItem->lParam;
 
-    if (phdi->mask & HDI_IMAGE) 
-    {
+    if (mask & HDI_IMAGE) 
         phdi->iImage = lpItem->iImage;
-    }
 
-    if (phdi->mask & HDI_ORDER)
+    if (mask & HDI_ORDER)
         phdi->iOrder = lpItem->iOrder;
 
-    if (phdi->mask & HDI_TEXT)
+    if (mask & HDI_TEXT)
     {
         if (bUnicode)
             Str_GetPtrW (lpItem->pszText, phdi->pszText, phdi->cchTextMax);
@@ -1094,7 +1107,7 @@ HEADER_InsertItemT (HWND hwnd, INT nItem
     UINT      i;
     UINT      copyMask;
 
-    if ((phdi == NULL) || (nItem < 0))
+    if ((phdi == NULL) || (nItem < 0) || (phdi->mask == 0))
 	return -1;
 
     if (nItem > infoPtr->uNumItem)
diff --git a/dlls/comctl32/tests/header.c b/dlls/comctl32/tests/header.c
index 856bfc6..eb06bb0 100644
--- a/dlls/comctl32/tests/header.c
+++ b/dlls/comctl32/tests/header.c
@@ -321,6 +321,60 @@ static void check_auto_fields(void)
     /* field from comctl >4.0 not tested as the system probably won't touch them */
 }
 
+static void check_mask()
+{
+    HDITEMA hdi;
+    LRESULT ret;
+
+    /* don't create items if the mask is zero */
+    ZeroMemory(&hdi, sizeof(hdi));
+    hdi.mask = 0;
+    hdi.cxy = 200;
+    hdi.pszText = "ABC";
+    hdi.fmt = 0;
+    hdi.iOrder = 0;
+    hdi.lParam = 17;
+    hdi.cchTextMax = 260;
+    ret = SendMessage(hWndHeader, HDM_INSERTITEM, (WPARAM)0, (LPARAM)&hdi);
+    ok(ret == -1, "Creating an item with a zero mask should have failed\n");
+    if (ret != -1) SendMessage(hWndHeader, HDM_DELETEITEM, (WPARAM)0, (LPARAM)0);
+
+    /* with a non-zero mask creation will succeed */
+    ZeroMemory(&hdi, sizeof(hdi));
+    hdi.mask = HDI_LPARAM;
+    ret = SendMessage(hWndHeader, HDM_INSERTITEM, (WPARAM)0, (LPARAM)&hdi);
+    ok(ret != -1, "Adding item with non-zero mask failed\n");
+    if (ret != -1)
+        SendMessage(hWndHeader, HDM_DELETEITEM, (WPARAM)0, (LPARAM)0);
+
+    /* in SETITEM if the mask contains a unknown bit, it is ignored */
+    ZeroMemory(&hdi, sizeof(hdi));
+    hdi.mask = 0x08000000 | HDI_LPARAM | HDI_IMAGE;
+    hdi.lParam = 133;
+    hdi.iImage = 17;
+    ret = SendMessage(hWndHeader, HDM_INSERTITEM, (WPARAM)0, (LPARAM)&hdi);
+    ok(ret != -1, "Adding item failed\n");
+
+    if (ret != -1)
+    {
+        /* check result */
+        ZeroMemory(&hdi, sizeof(hdi));
+        hdi.mask = HDI_LPARAM | HDI_IMAGE;
+        SendMessage(hWndHeader, HDM_GETITEM, (WPARAM)0, (LPARAM)&hdi);
+        ok(hdi.lParam == 133, "comctl32 4.0 field not set\n");
+        ok(hdi.iImage == 17, "comctl32 >4.0 field not set\n");
+
+        /* but in GETITEM if an unknown bit is set, comctl32 uses only version 4.0 fields */
+        ZeroMemory(&hdi, sizeof(hdi));
+        hdi.mask = 0x08000000 | HDI_LPARAM | HDI_IMAGE;
+        SendMessage(hWndHeader, HDM_GETITEM, (WPARAM)0, (LPARAM)&hdi);
+        ok(hdi.lParam == 133, "comctl32 4.0 field not read\n");
+        ok(hdi.iImage == 0, "comctl32 >4.0 field shouldn't be read\n");
+
+        SendMessage(hWndHeader, HDM_DELETEITEM, (WPARAM)0, (LPARAM)0);
+    }
+}
+
 static void test_header_control (void)
 {
     LONG res;
@@ -396,6 +450,8 @@ static void test_header_control (void)
     TEST_GET_ITEMCOUNT(6);
     check_auto_fields();
     TEST_GET_ITEMCOUNT(6);
+    check_mask();
+    TEST_GET_ITEMCOUNT(6);
 
     res = delItem(hWndHeader, 5);
     ok(res == 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res);




More information about the wine-cvs mailing list