From b97697dbe7f43aca866ec1481e13b5dec9e54504 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 4 Oct 2009 23:17:33 +0400 Subject: [PATCH] comctl32/monthcal: Check range limits in MCM_SETCURSEL. --- dlls/comctl32/monthcal.c | 57 ++++++++++++++++++++++++++++++++++ dlls/comctl32/tests/monthcal.c | 33 ++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c index 2078efcc563..a35d26110f5 100644 --- a/dlls/comctl32/monthcal.c +++ b/dlls/comctl32/monthcal.c @@ -202,6 +202,62 @@ static BOOL MONTHCAL_ValidateDate(const SYSTEMTIME *time) return TRUE; } +/* Compares two dates in SYSTEMTIME format + * + * PARAMETERS + * + * [I] first : pointer to valid first date data to compare + * [I] second : pointer to valid second date data to compare + * + * RETURN VALUE + * + * -1 : first < second + * 0 : first == second + * 1 : first > second + * + * Note that no date validation performed, alreadt validated values expected. + */ +static LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second) +{ + FILETIME ft_first, ft_second; + + SystemTimeToFileTime(first, &ft_first); + SystemTimeToFileTime(second, &ft_second); + + return CompareFileTime(&ft_first, &ft_second); +} + +/* Checks largest possible date range and configured one + * + * PARAMETERS + * + * [I] infoPtr : valid pointer to control data + * [I] date : pointer to valid date data to check + * + * RETURN VALUE + * + * TRUE - date whithin largest and configured range + * FALSE - date is outside largest or configured range + */ +static BOOL MONTHCAL_IsDateInValidRange(const MONTHCAL_INFO *infoPtr, const SYSTEMTIME *date) +{ + static const SYSTEMTIME max_date = { .wYear = 9999, .wMonth = 12, .wDay = 31 }; + static const SYSTEMTIME min_date = { .wYear = 1752, .wMonth = 9, .wDay = 14 }; + + if((MONTHCAL_CompareSystemTime(date, &max_date) == 1) || + (MONTHCAL_CompareSystemTime(date, &min_date) == -1)) return FALSE; + + if(infoPtr->rangeValid & GDTR_MAX) { + if((MONTHCAL_CompareSystemTime(date, &infoPtr->maxSel) == 1)) return FALSE; + } + + if(infoPtr->rangeValid & GDTR_MIN) { + if((MONTHCAL_CompareSystemTime(date, &infoPtr->minSel) == -1)) return FALSE; + } + + return TRUE; +} + /* Used in MCM_SETRANGE/MCM_SETSELRANGE to determine resulting time part. Milliseconds are intentionaly not validated. */ static BOOL MONTHCAL_ValidateTime(const SYSTEMTIME *time) @@ -1119,6 +1175,7 @@ MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel) if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE; if(!MONTHCAL_ValidateDate(curSel)) return FALSE; + if(!MONTHCAL_IsDateInValidRange(infoPtr, curSel)) return FALSE; infoPtr->minSel = *curSel; infoPtr->maxSel = *curSel; diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c index 4a051b7a02c..034487df4c2 100644 --- a/dlls/comctl32/tests/monthcal.c +++ b/dlls/comctl32/tests/monthcal.c @@ -789,6 +789,39 @@ static void test_monthcal_currdate(void) ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE); + /* December, 31, 9999 is the maximum allowed date */ + memset(&st_new, 0, sizeof(st_new)); + st_new.wYear = 9999; + st_new.wMonth = 12; + st_new.wDay = 31; + res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); + expect(1, res); + memset(&st_test, 0, sizeof(st_test)); + res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test); + expect(1, res); + expect(st_new.wYear, st_test.wYear); + expect(st_new.wMonth, st_test.wMonth); + expect(st_new.wDay, st_test.wDay); + expect(st_new.wHour, st_test.wHour); + expect(st_new.wMinute, st_test.wMinute); + expect(st_new.wSecond, st_test.wSecond); + /* try one day later */ + st_original = st_new; + st_new.wYear = 10000; + st_new.wMonth = 1; + st_new.wDay = 1; + res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_new); + expect(0, res); + memset(&st_test, 0, sizeof(st_test)); + res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_test); + expect(1, res); + expect(st_original.wYear, st_test.wYear); + expect(st_original.wMonth, st_test.wMonth); + expect(st_original.wDay, st_test.wDay); + expect(st_original.wHour, st_test.wHour); + expect(st_original.wMinute, st_test.wMinute); + expect(st_original.wSecond, st_test.wSecond); + DestroyWindow(hwnd); }