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).
This commit is contained in:
parent
bf346b240d
commit
36a8e5fba3
|
@ -98,6 +98,11 @@ typedef struct
|
||||||
#define HDN_UNICODE_OFFSET 20
|
#define HDN_UNICODE_OFFSET 20
|
||||||
#define HDN_FIRST_UNICODE (HDN_FIRST-HDN_UNICODE_OFFSET)
|
#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))
|
#define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0))
|
||||||
|
|
||||||
static BOOL HEADER_PrepareCallbackItems(HWND hwnd, INT iItem, INT reqMask);
|
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)
|
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)
|
if (mask & HDI_BITMAP)
|
||||||
lpItem->hbm = phdi->hbm;
|
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_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
|
||||||
HEADER_ITEM *lpItem;
|
HEADER_ITEM *lpItem;
|
||||||
|
UINT mask = phdi->mask;
|
||||||
|
|
||||||
if (!phdi)
|
if (!phdi)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
TRACE("[nItem=%d]\n", nItem);
|
TRACE("[nItem=%d]\n", nItem);
|
||||||
|
|
||||||
if (phdi->mask == 0)
|
if (mask == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
|
if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
|
||||||
return FALSE;
|
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];
|
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;
|
phdi->hbm = lpItem->hbm;
|
||||||
|
|
||||||
if (phdi->mask & HDI_FORMAT)
|
if (mask & HDI_FORMAT)
|
||||||
phdi->fmt = lpItem->fmt;
|
phdi->fmt = lpItem->fmt;
|
||||||
|
|
||||||
if (phdi->mask & HDI_WIDTH)
|
if (mask & HDI_WIDTH)
|
||||||
phdi->cxy = lpItem->cxy;
|
phdi->cxy = lpItem->cxy;
|
||||||
|
|
||||||
if (phdi->mask & HDI_LPARAM)
|
if (mask & HDI_LPARAM)
|
||||||
phdi->lParam = lpItem->lParam;
|
phdi->lParam = lpItem->lParam;
|
||||||
|
|
||||||
if (phdi->mask & HDI_IMAGE)
|
if (mask & HDI_IMAGE)
|
||||||
{
|
|
||||||
phdi->iImage = lpItem->iImage;
|
phdi->iImage = lpItem->iImage;
|
||||||
}
|
|
||||||
|
|
||||||
if (phdi->mask & HDI_ORDER)
|
if (mask & HDI_ORDER)
|
||||||
phdi->iOrder = lpItem->iOrder;
|
phdi->iOrder = lpItem->iOrder;
|
||||||
|
|
||||||
if (phdi->mask & HDI_TEXT)
|
if (mask & HDI_TEXT)
|
||||||
{
|
{
|
||||||
if (bUnicode)
|
if (bUnicode)
|
||||||
Str_GetPtrW (lpItem->pszText, phdi->pszText, phdi->cchTextMax);
|
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 i;
|
||||||
UINT copyMask;
|
UINT copyMask;
|
||||||
|
|
||||||
if ((phdi == NULL) || (nItem < 0))
|
if ((phdi == NULL) || (nItem < 0) || (phdi->mask == 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (nItem > infoPtr->uNumItem)
|
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 */
|
/* 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)
|
static void test_header_control (void)
|
||||||
{
|
{
|
||||||
LONG res;
|
LONG res;
|
||||||
|
@ -396,6 +450,8 @@ static void test_header_control (void)
|
||||||
TEST_GET_ITEMCOUNT(6);
|
TEST_GET_ITEMCOUNT(6);
|
||||||
check_auto_fields();
|
check_auto_fields();
|
||||||
TEST_GET_ITEMCOUNT(6);
|
TEST_GET_ITEMCOUNT(6);
|
||||||
|
check_mask();
|
||||||
|
TEST_GET_ITEMCOUNT(6);
|
||||||
|
|
||||||
res = delItem(hWndHeader, 5);
|
res = delItem(hWndHeader, 5);
|
||||||
ok(res == 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res);
|
ok(res == 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res);
|
||||||
|
|
Loading…
Reference in New Issue