[PATCH 2/7] Check configured selection range max width in MCM_SETSELRANGE handler

Nikolay Sivov bunglehead at gmail.com
Mon Oct 5 11:29:31 CDT 2009


---
 dlls/comctl32/monthcal.c       |  108 +++++++++++++++++++++++++---------------
 dlls/comctl32/tests/monthcal.c |   27 ++++++++++
 2 files changed, 94 insertions(+), 41 deletions(-)

diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index 9c25472..cccdaf3 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -258,6 +258,66 @@ static BOOL MONTHCAL_IsDateInValidRange(const MONTHCAL_INFO *infoPtr, const SYST
   return TRUE;
 }
 
+/* Checks passed range width with configured maximum selection count
+ *
+ * PARAMETERS
+ *
+ *  [I] infoPtr : valid pointer to control data
+ *  [I] range0  : pointer to valid date data (requested bound)
+ *  [I] range1  : pointer to valid date data (primary bound)
+ *  [O] adjust  : returns adjusted range bound to fit maximum range (optional)
+ *
+ *  Adjust value computed basing on primary bound and current maximum selection
+ *  count. For simple range check (without adjusted value required) (range0, range1)
+ *  relation means nothing.
+ *
+ * RETURN VALUE
+ *
+ *  TRUE  - range is shorter or equal to maximum
+ *  FALSE - range is larger than maximum
+ */
+static BOOL MONTHCAL_IsSelRangeValid(const MONTHCAL_INFO *infoPtr,
+                                     const SYSTEMTIME *range0,
+                                     const SYSTEMTIME *range1,
+                                     SYSTEMTIME *adjust)
+{
+  ULARGE_INTEGER ul_range0, ul_range1, ul_diff;
+  FILETIME ft_range0, ft_range1;
+  LONG cmp;
+
+  SystemTimeToFileTime(range0, &ft_range0);
+  SystemTimeToFileTime(range1, &ft_range1);
+
+  ul_range0.LowPart  = ft_range0.dwLowDateTime;
+  ul_range0.HighPart = ft_range0.dwHighDateTime;
+  ul_range1.LowPart  = ft_range1.dwLowDateTime;
+  ul_range1.HighPart = ft_range1.dwHighDateTime;
+
+  cmp = CompareFileTime(&ft_range0, &ft_range1);
+
+  if(cmp == 1)
+     ul_diff.QuadPart = ul_range0.QuadPart - ul_range1.QuadPart;
+  else
+     ul_diff.QuadPart = -ul_range0.QuadPart + ul_range1.QuadPart;
+
+  if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) {
+
+     if(adjust) {
+       if(cmp == 1)
+          ul_range0.QuadPart = ul_range1.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1);
+       else
+          ul_range0.QuadPart = ul_range1.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1);
+
+       ft_range0.dwLowDateTime  = ul_range0.LowPart;
+       ft_range0.dwHighDateTime = ul_range0.HighPart;
+       FileTimeToSystemTime(&ft_range0, adjust);
+     }
+
+     return FALSE;
+  }
+  else 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)
@@ -1249,6 +1309,9 @@ MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
     if(!MONTHCAL_ValidateTime(&range[1]))
       MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
 
+    /* maximum range exceeded */
+    if(!MONTHCAL_IsSelRangeValid(infoPtr, &range[0], &range[1], NULL)) return FALSE;
+
     old_range[0] = infoPtr->minSel;
     old_range[1] = infoPtr->maxSel;
 
@@ -1825,22 +1888,17 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 
   if(infoPtr->dwStyle & MCS_MULTISELECT)  {
     SYSTEMTIME st[2];
-    FILETIME ft_ht, ft_first;
-    ULARGE_INTEGER ul_ht, ul_first, ul_diff;
     int i;
     LONG cmp;
 
     MONTHCAL_GetSelRange(infoPtr, st);
     i = MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st[0]) ? 1 : 0;
 
-    SystemTimeToFileTime(&st_ht, &ft_ht);
-    SystemTimeToFileTime(&infoPtr->firstSel, &ft_first);
-
-    cmp = CompareFileTime(&ft_ht, &ft_first);
+    cmp = MONTHCAL_CompareSystemTime(&st_ht, &infoPtr->firstSel);
 
     if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st[1])) {
       /* If we're still at the first selected date and range is empty, return.
-         If range isn't empty we should change range to a singel firstSel */
+         If range isn't empty we should change range to a single firstSel */
       if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st_ht) &&
          MONTHCAL_IsDateEqual(&st[0], &st[1])) goto done;
 
@@ -1848,46 +1906,14 @@ MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
       if(cmp == -1) i = 0;
     }
 
-    ul_ht.LowPart  = ft_ht.dwLowDateTime;
-    ul_ht.HighPart = ft_ht.dwHighDateTime;
-    ul_first.LowPart  = ft_first.dwLowDateTime;
-    ul_first.HighPart = ft_first.dwHighDateTime;
-
-    /* new selected date is later */
-    if(cmp == 1)
-       ul_diff.QuadPart = ul_ht.QuadPart - ul_first.QuadPart;
-    else
-       ul_diff.QuadPart = -ul_ht.QuadPart + ul_first.QuadPart;
-
-    if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) {
-      if(cmp == 1)
-        ul_ht.QuadPart = ul_first.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1);
-      else
-        ul_ht.QuadPart = ul_first.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1);
-
-      ft_ht.dwLowDateTime  = ul_ht.LowPart;
-      ft_ht.dwHighDateTime = ul_ht.HighPart;
-      FileTimeToSystemTime(&ft_ht, &st_ht);
-    }
+    MONTHCAL_IsSelRangeValid(infoPtr, &st_ht, &infoPtr->firstSel, &st_ht);
 
     if(!MONTHCAL_IsDateEqual(&st[i], &st_ht)) {
-      FILETIME ft_range0, ft_range1;
-
       st[i] = st_ht;
 
-      SystemTimeToFileTime(&st[0], &ft_range0);
-      SystemTimeToFileTime(&st[1], &ft_range1);
-
-      /* swap bounds if needed */
-      if(CompareFileTime(&ft_range0, &ft_range1) == 1) {
-        SYSTEMTIME swap = st[1];
-
-        st[1] = st[0];
-        st[0] = swap;
-      }
-
       MONTHCAL_CopyTime(&infoPtr->todaysDate, &st[0]);
       MONTHCAL_CopyTime(&infoPtr->todaysDate, &st[1]);
+      /* bounds will be swapped here if needed */
       MONTHCAL_SetSelRange(infoPtr, st);
     }
   }
diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c
index 491cfa2..3b38e82 100644
--- a/dlls/comctl32/tests/monthcal.c
+++ b/dlls/comctl32/tests/monthcal.c
@@ -1592,6 +1592,33 @@ static void test_monthcal_selrange(void)
     expect(range[0].wSecond,    range2[1].wSecond);
     expect(range[0].wMilliseconds, range2[1].wMilliseconds);
 
+    /* try with range larger than maximum configured */
+    memset(&range[0], 0, sizeof(range[0]));
+    range[0].wYear  = 2009;
+    range[0].wMonth = 10;
+    range[0].wDay   = 1;
+    range[1] = range[0];
+
+    ret = SendMessage(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
+    expect(TRUE, ret);
+
+    range[1] = range[0];
+    /* default max. range is 7 days */
+    range[1].wDay = 8;
+
+    ret = SendMessage(hwnd, MCM_SETSELRANGE, 0, (LPARAM)range);
+    expect(FALSE, ret);
+
+    ret = SendMessage(hwnd, MCM_GETSELRANGE, 0, (LPARAM)range2);
+    expect(TRUE, ret);
+
+    expect(range[0].wYear,  range2[0].wYear);
+    expect(range[0].wMonth, range2[0].wMonth);
+    expect(range[0].wDay,   range2[0].wDay);
+    expect(range[0].wYear,  range2[1].wYear);
+    expect(range[0].wMonth, range2[1].wMonth);
+    expect(range[0].wDay,   range2[1].wDay);
+
     DestroyWindow(hwnd);
 }
 
-- 
1.5.6.5


--=-BNZ5k+wxb5m+cryS0Zvk--




More information about the wine-patches mailing list