Commit 36a8e5fb authored by Mikołaj Zalewski's avatar Mikołaj Zalewski Committed by Alexandre Julliard

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).
parent bf346b24
......@@ -98,6 +98,11 @@ typedef struct
#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_ITEM *lpItem)
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, LPHDITEMW phdi, BOOL bUnicode)
{
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, LPHDITEMW phdi, BOOL bUnicode)
UINT i;
UINT copyMask;
if ((phdi == NULL) || (nItem < 0))
if ((phdi == NULL) || (nItem < 0) || (phdi->mask == 0))
return -1;
if (nItem > infoPtr->uNumItem)
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment