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:
Mikołaj Zalewski 2006-05-16 00:10:08 +02:00 committed by Alexandre Julliard
parent bf346b240d
commit 36a8e5fba3
2 changed files with 81 additions and 12 deletions

View File

@ -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;
lpItem = &infoPtr->items[nItem]; if (mask & HDI_UNKNOWN_FIELDS)
HEADER_PrepareCallbackItems(hwnd, nItem, phdi->mask);
if (phdi->mask & HDI_BITMAP)
phdi->hbm = lpItem->hbm;
if (phdi->mask & HDI_FORMAT)
phdi->fmt = lpItem->fmt;
if (phdi->mask & HDI_WIDTH)
phdi->cxy = lpItem->cxy;
if (phdi->mask & HDI_LPARAM)
phdi->lParam = lpItem->lParam;
if (phdi->mask & HDI_IMAGE)
{ {
phdi->iImage = lpItem->iImage; TRACE("mask %x contains unknown fields. Using only comctl32 4.0 fields\n", mask);
mask &= HDI_COMCTL32_4_0_FIELDS;
} }
if (phdi->mask & HDI_ORDER) lpItem = &infoPtr->items[nItem];
HEADER_PrepareCallbackItems(hwnd, nItem, mask);
if (mask & HDI_BITMAP)
phdi->hbm = lpItem->hbm;
if (mask & HDI_FORMAT)
phdi->fmt = lpItem->fmt;
if (mask & HDI_WIDTH)
phdi->cxy = lpItem->cxy;
if (mask & HDI_LPARAM)
phdi->lParam = lpItem->lParam;
if (mask & HDI_IMAGE)
phdi->iImage = lpItem->iImage;
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)

View File

@ -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);