Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/comctl32/pager.c | 44 +++++++++++++++++++ dlls/comctl32/tests/pager.c | 87 +++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+)
diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c index 421dbedd81..4763ed5640 100644 --- a/dlls/comctl32/pager.c +++ b/dlls/comctl32/pager.c @@ -1051,6 +1051,16 @@ static UINT PAGER_GetAnsiNtfCode(UINT code) case DTN_FORMATQUERYW: return DTN_FORMATQUERYA; case DTN_USERSTRINGW: return DTN_USERSTRINGA; case DTN_WMKEYDOWNW: return DTN_WMKEYDOWNA; + /* Header */ + case HDN_BEGINTRACKW: return HDN_BEGINTRACKA; + case HDN_DIVIDERDBLCLICKW: return HDN_DIVIDERDBLCLICKA; + case HDN_ENDTRACKW: return HDN_ENDTRACKA; + case HDN_GETDISPINFOW: return HDN_GETDISPINFOA; + case HDN_ITEMCHANGEDW: return HDN_ITEMCHANGEDA; + case HDN_ITEMCHANGINGW: return HDN_ITEMCHANGINGA; + case HDN_ITEMCLICKW: return HDN_ITEMCLICKA; + case HDN_ITEMDBLCLICKW: return HDN_ITEMDBLCLICKA; + case HDN_TRACKW: return HDN_TRACKA; /* List View */ case LVN_BEGINLABELEDITW: return LVN_BEGINLABELEDITA; case LVN_ENDLABELEDITW: return LVN_ENDLABELEDITA; @@ -1252,6 +1262,40 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) NMDATETIMESTRINGW *nmdts = (NMDATETIMESTRINGW *)hdr; return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, (WCHAR **)&nmdts->pszUserString, NULL, CONVERT_SEND); } + /* Header */ + case HDN_BEGINTRACKW: + case HDN_DIVIDERDBLCLICKW: + case HDN_ENDTRACKW: + case HDN_ITEMCHANGEDW: + case HDN_ITEMCHANGINGW: + case HDN_ITEMCLICKW: + case HDN_ITEMDBLCLICKW: + case HDN_TRACKW: + { + NMHEADERW *nmh = (NMHEADERW *)hdr; + WCHAR *oldText = NULL, *oldFilterText = NULL; + HD_TEXTFILTERW *tf = NULL; + + hdr->code = PAGER_GetAnsiNtfCode(hdr->code); + + if (!nmh->pitem) return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + if (nmh->pitem->mask & HDI_TEXT) oldText = PAGER_ConvertText(&nmh->pitem->pszText); + if ((nmh->pitem->mask & HDI_FILTER) && (nmh->pitem->type == HDFT_ISSTRING) && nmh->pitem->pvFilter) + { + tf = (HD_TEXTFILTERW *)nmh->pitem->pvFilter; + oldFilterText = PAGER_ConvertText(&tf->pszText); + } + ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + PAGER_RestoreText(&nmh->pitem->pszText, oldText); + if (tf) PAGER_RestoreText(&tf->pszText, oldFilterText); + return ret; + } + case HDN_GETDISPINFOW: + { + NMHDDISPINFOW *nmhddi = (NMHDDISPINFOW *)hdr; + return PAGER_SendConvertedNotify(infoPtr, hdr, &nmhddi->mask, HDI_TEXT, &nmhddi->pszText, &nmhddi->cchTextMax, + SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); + } /* List View */ case LVN_BEGINLABELEDITW: case LVN_ENDLABELEDITW: diff --git a/dlls/comctl32/tests/pager.c b/dlls/comctl32/tests/pager.c index ff10be8074..718df2510f 100644 --- a/dlls/comctl32/tests/pager.c +++ b/dlls/comctl32/tests/pager.c @@ -282,6 +282,14 @@ static const struct message set_pos_empty_seq[] = { { 0 } };
+static CHAR *heap_strdup(const CHAR *str) +{ + int len = lstrlenA(str) + 1; + CHAR *ret = heap_alloc(len * sizeof(CHAR)); + lstrcpyA(ret, str); + return ret; +} + static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; @@ -643,6 +651,10 @@ static void notify_generic_text_handler(CHAR **text, INT *text_max)
if (receive_data->write_text) memcpy(*text, receive_data->write_text, receive_data->write_text_size); + /* 64bit Windows will try to free the text pointer even if it's application provided when handling + * HDN_GETDISPINFOW. Deliberate leak here. */ + else if(notify_test_info.unicode == HDN_GETDISPINFOW) + *text = heap_strdup(receive_data->write_pointer); else *text = receive_data->write_pointer; if (text_max && receive_data->write_text_max != -1) *text_max = receive_data->write_text_max; @@ -759,6 +771,45 @@ static LRESULT WINAPI test_notify_proc(HWND hwnd, UINT message, WPARAM wParam, L notify_generic_text_handler((CHAR **)&nmdts->pszUserString, NULL); break; } + /* Header */ + case HDN_BEGINDRAG: + case HDN_ENDDRAG: + case HDN_BEGINFILTEREDIT: + case HDN_ENDFILTEREDIT: + case HDN_DROPDOWN: + case HDN_FILTERCHANGE: + case HDN_ITEMKEYDOWN: + case HDN_ITEMSTATEICONCLICK: + case HDN_OVERFLOWCLICK: + { + NMHEADERW *nmhd = (NMHEADERW *)hdr; + ok(!lstrcmpW(nmhd->pitem->pszText, test_w), "Expect %s, got %s\n", wine_dbgstr_w(test_w), + wine_dbgstr_w(nmhd->pitem->pszText)); + ok(!lstrcmpW(((HD_TEXTFILTERW *)nmhd->pitem->pvFilter)->pszText, test_w), "Expect %s, got %s\n", + wine_dbgstr_w(test_w), wine_dbgstr_w(((HD_TEXTFILTERW *)nmhd->pitem->pvFilter)->pszText)); + break; + } + case HDN_BEGINTRACKA: + case HDN_DIVIDERDBLCLICKA: + case HDN_ENDTRACKA: + case HDN_ITEMCHANGEDA: + case HDN_ITEMCHANGINGA: + case HDN_ITEMCLICKA: + case HDN_ITEMDBLCLICKA: + case HDN_TRACKA: + { + NMHEADERA *nmhd = (NMHEADERA *)hdr; + ok(!lstrcmpA(nmhd->pitem->pszText, test_a), "Expect %s, got %s\n", test_a, nmhd->pitem->pszText); + ok(!lstrcmpA(((HD_TEXTFILTERA *)nmhd->pitem->pvFilter)->pszText, test_a), "Expect %s, got %s\n", test_a, + ((HD_TEXTFILTERA *)nmhd->pitem->pvFilter)->pszText); + break; + } + case HDN_GETDISPINFOA: + { + NMHDDISPINFOA *nmhddi = (NMHDDISPINFOA *)hdr; + notify_generic_text_handler(&nmhddi->pszText, &nmhddi->cchTextMax); + break; + } /* List View */ case LVN_BEGINLABELEDITA: case LVN_ENDLABELEDITA: @@ -1046,6 +1097,36 @@ static void test_wm_notify_datetime(HWND pager) } }
+static void test_wm_notify_header(HWND pager) +{ + NMHEADERW nmh = {0}; + HDITEMW hdi = {0}; + HD_TEXTFILTERW hdtf = {0}; + + hdi.mask = HDI_TEXT | HDI_FILTER; + hdi.pszText = test_w; + hdtf.pszText = test_w; + nmh.pitem = &hdi; + nmh.pitem->pvFilter = &hdtf; + send_notify(pager, HDN_BEGINDRAG, HDN_BEGINDRAG, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ENDDRAG, HDN_ENDDRAG, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_BEGINFILTEREDIT, HDN_BEGINFILTEREDIT, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ENDFILTEREDIT, HDN_ENDFILTEREDIT, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_DROPDOWN, HDN_DROPDOWN, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_FILTERCHANGE, HDN_FILTERCHANGE, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMKEYDOWN, HDN_ITEMKEYDOWN, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMSTATEICONCLICK, HDN_ITEMSTATEICONCLICK, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_OVERFLOWCLICK, HDN_OVERFLOWCLICK, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_BEGINTRACKW, HDN_BEGINTRACKA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_DIVIDERDBLCLICKW, HDN_DIVIDERDBLCLICKA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ENDTRACKW, HDN_ENDTRACKA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMCHANGEDW, HDN_ITEMCHANGEDA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMCHANGINGW, HDN_ITEMCHANGINGA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMCLICKW, HDN_ITEMCLICKA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_ITEMDBLCLICKW, HDN_ITEMDBLCLICKA, (LPARAM)&nmh, TRUE); + send_notify(pager, HDN_TRACKW, HDN_TRACKA, (LPARAM)&nmh, TRUE); +} + static void test_wm_notify_tooltip(HWND pager) { NMTTDISPINFOW nmttdi; @@ -1094,6 +1175,8 @@ static void test_wm_notify(void) static NMDATETIMEFORMATQUERYW nmdtfq; static NMDATETIMEWMKEYDOWNW nmdtkd; static NMDATETIMESTRINGW nmdts; + /* Header */ + static NMHDDISPINFOW nmhddi; /* List View */ static NMLVDISPINFOW nmlvdi; static NMLVGETINFOTIPW nmlvgit; @@ -1124,6 +1207,9 @@ static void test_wm_notify(void) CONVERT_SEND}, {&nmdts, sizeof(nmdts), NULL, 0, (WCHAR **)&nmdts.pszUserString, NULL, DTN_USERSTRINGW, DTN_USERSTRINGA, CONVERT_SEND}, + /* Header */ + {&nmhddi, sizeof(nmhddi), &nmhddi.mask, HDI_TEXT, &nmhddi.pszText, &nmhddi.cchTextMax, HDN_GETDISPINFOW, + HDN_GETDISPINFOA, SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE}, /* List View */ {&nmlvfi, sizeof(nmlvfi), &nmlvfi.lvfi.flags, LVFI_STRING, (WCHAR **)&nmlvfi.lvfi.psz, NULL, LVN_INCREMENTALSEARCHW, LVN_INCREMENTALSEARCHA, CONVERT_SEND}, @@ -1212,6 +1298,7 @@ static void test_wm_notify(void) /* Tests for those that can't be covered by generic text test helper */ test_wm_notify_comboboxex(pager); test_wm_notify_datetime(pager); + test_wm_notify_header(pager); test_wm_notify_tooltip(pager);
DestroyWindow(parent);