Skip to content

Commit e06255c

Browse files
[Refactoring] Added protection for MonthCalendarAccessibleObject (dotnet#2975)
1 parent 912d88c commit e06255c

22 files changed

+672
-150
lines changed

Winforms.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
126126
EndProject
127127
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Design.Editors.Facade3x", "src\System.Windows.Forms.Design.Editors\src\System.Windows.Forms.Design.Editors.Facade3x.csproj", "{E0681991-228A-420E-85D5-A9E796F0AAE0}"
128128
EndProject
129+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiMonthCalendarTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauimonthCalendarTests\MauiMonthCalendarTests.csproj", "{9DDC6936-9197-4C09-8640-AF0BE4918700}"
130+
EndProject
131+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiTestsHelper", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiTestsHelper\MauiTestsHelper.csproj", "{44BB1092-1844-4EAF-8DF5-338DE4C3149A}"
132+
EndProject
129133
Global
130134
GlobalSection(SolutionConfigurationPlatforms) = preSolution
131135
Debug|Any CPU = Debug|Any CPU
@@ -248,6 +252,14 @@ Global
248252
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
249253
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
250254
{E0681991-228A-420E-85D5-A9E796F0AAE0}.Release|Any CPU.Build.0 = Release|Any CPU
255+
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
256+
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Debug|Any CPU.Build.0 = Debug|Any CPU
257+
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Release|Any CPU.ActiveCfg = Release|Any CPU
258+
{9DDC6936-9197-4C09-8640-AF0BE4918700}.Release|Any CPU.Build.0 = Release|Any CPU
259+
{44BB1092-1844-4EAF-8DF5-338DE4C3149A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
260+
{44BB1092-1844-4EAF-8DF5-338DE4C3149A}.Debug|Any CPU.Build.0 = Debug|Any CPU
261+
{44BB1092-1844-4EAF-8DF5-338DE4C3149A}.Release|Any CPU.ActiveCfg = Release|Any CPU
262+
{44BB1092-1844-4EAF-8DF5-338DE4C3149A}.Release|Any CPU.Build.0 = Release|Any CPU
251263
EndGlobalSection
252264
GlobalSection(SolutionProperties) = preSolution
253265
HideSolutionNode = FALSE
@@ -287,6 +299,8 @@ Global
287299
{90B27178-F535-43F7-886E-0AB75203F246} = {77FEDB47-F7F6-490D-AF7C-ABB4A9E0B9D7}
288300
{9BFDE7F2-C8F3-40D6-9A16-8DCD1A37E900} = {583F1292-AE8D-4511-B8D8-A81FE4642DDC}
289301
{E0681991-228A-420E-85D5-A9E796F0AAE0} = {434C00C3-E498-4BA7-9764-9F0FC8CFE457}
302+
{9DDC6936-9197-4C09-8640-AF0BE4918700} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
303+
{44BB1092-1844-4EAF-8DF5-338DE4C3149A} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
290304
EndGlobalSection
291305
GlobalSection(ExtensibilityGlobals) = postSolution
292306
SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136}

src/System.Windows.Forms.Primitives/src/Properties/InternalsVisibleTo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
[assembly: InternalsVisibleTo("MauiListViewTests, PublicKey=00000000000000000400000000000000")]
1717
[assembly: InternalsVisibleTo("System.Windows.Forms.IntegrationTests.Common, PublicKey=00000000000000000400000000000000")]
1818
[assembly: InternalsVisibleTo("System.Windows.Forms.Maui.IntegrationTests, PublicKey=00000000000000000400000000000000")]
19+
[assembly: InternalsVisibleTo("MauiMonthCalendarTests, PublicKey=00000000000000000400000000000000")]
20+
[assembly: InternalsVisibleTo("MauiTestsHelper, PublicKey=00000000000000000400000000000000")]
1921

2022
// This is needed in order to Moq internal interfaces for testing
2123
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

src/System.Windows.Forms/src/Properties/InternalsVisibleTo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.CompilerServices;
66

77
[assembly: InternalsVisibleTo("System.Windows.Forms.Tests, PublicKey=00000000000000000400000000000000")]
8+
[assembly: InternalsVisibleTo("MauiMonthCalendarTests, PublicKey=00000000000000000400000000000000")]
89

910
// This is needed in order to Moq internal interfaces for testing
1011
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

src/System.Windows.Forms/src/System/Windows/Forms/DateTimePicker.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,12 @@ internal static Kernel32.SYSTEMTIME DateTimeToSysTime(DateTime time)
16671667
/// </summary>
16681668
internal static DateTime SysTimeToDateTime(Kernel32.SYSTEMTIME s)
16691669
{
1670+
if (s.wYear <= 0 || s.wMonth <= 0 || s.wDay <= 0)
1671+
{
1672+
Debug.Fail("Incorrect SYSTEMTIME info!");
1673+
return DateTime.MinValue;
1674+
}
1675+
16701676
return new DateTime(s.wYear, s.wMonth, s.wDay, s.wHour, s.wMinute, s.wSecond);
16711677
}
16721678

src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarBodyAccessibleObject.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ public CalendarChildAccessibleObject GetFromPoint(MCHITTESTINFO hitTestInfo)
5454
case MCHT.CALENDARWEEKNUM:
5555
case MCHT.CALENDARDATE:
5656
AccessibleObject rowAccessibleObject = _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, hitTestInfo.iRow);
57+
58+
if (rowAccessibleObject == null)
59+
{
60+
return null;
61+
}
62+
5763
return _calendarAccessibleObject.GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, hitTestInfo.iCol);
5864
}
5965

src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarChildAccessibleObject.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ public partial class MonthCalendar
1616
/// </summary>
1717
internal abstract class CalendarChildAccessibleObject : AccessibleObject
1818
{
19-
protected MonthCalendarAccessibleObject _calendarAccessibleObject;
19+
protected readonly MonthCalendarAccessibleObject _calendarAccessibleObject;
2020
protected int _calendarIndex;
2121
protected CalendarChildType _itemType;
2222

2323
public CalendarChildAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarChildType itemType)
2424
{
25-
_calendarAccessibleObject = calendarAccessibleObject;
25+
_calendarAccessibleObject = calendarAccessibleObject ?? throw new ArgumentNullException(nameof(calendarAccessibleObject));
2626
_calendarIndex = calendarIndex;
2727
_itemType = itemType;
2828
}
@@ -65,7 +65,7 @@ public void RaiseMouseClick()
6565
return;
6666
}
6767

68-
var rectangle = CalculateBoundingRectangle();
68+
RECT rectangle = CalculateBoundingRectangle();
6969
int x = rectangle.left + ((rectangle.right - rectangle.left) / 2);
7070
int y = rectangle.top + ((rectangle.bottom - rectangle.top) / 2);
7171

src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.CalendarGridChildAccessibleObject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ public partial class MonthCalendar
1313
/// </summary>
1414
internal abstract class CalendarGridChildAccessibleObject : CalendarChildAccessibleObject
1515
{
16-
protected AccessibleObject _parentAccessibleObject;
16+
protected readonly AccessibleObject _parentAccessibleObject;
1717

1818
public CalendarGridChildAccessibleObject(MonthCalendarAccessibleObject calendarAccessibleObject, int calendarIndex, CalendarChildType itemType,
1919
AccessibleObject parentAccessibleObject, int itemIndex) : base(calendarAccessibleObject, calendarIndex, itemType)
2020
{
21-
_parentAccessibleObject = parentAccessibleObject;
21+
_parentAccessibleObject = parentAccessibleObject ?? throw new ArgumentNullException(nameof(parentAccessibleObject));
2222
}
2323

2424
public override AccessibleObject Parent => _parentAccessibleObject;

src/System.Windows.Forms/src/System/Windows/Forms/MonthCalendar.MonthCalendarAccessibleObject.cs

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ internal class MonthCalendarAccessibleObject : ControlAccessibleObject
2727
public MonthCalendarAccessibleObject(Control owner)
2828
: base(owner)
2929
{
30-
_owner = owner as MonthCalendar;
30+
_owner = (MonthCalendar)owner;
3131
}
3232

3333
public UiaCore.UIA ControlType =>
@@ -83,10 +83,6 @@ public override string Name
8383
}
8484

8585
name = string.Empty;
86-
if (_owner == null)
87-
{
88-
return name;
89-
}
9086

9187
if (_owner._mcCurView == MCMV.MONTH)
9288
{
@@ -134,47 +130,34 @@ public override string Value
134130
{
135131
get
136132
{
137-
var value = string.Empty;
138-
if (_owner == null)
139-
{
140-
return value;
141-
}
142-
143133
try
144134
{
145135
if (_owner._mcCurView == MCMV.MONTH)
146136
{
147137
if (System.DateTime.Equals(_owner.SelectionStart.Date, _owner.SelectionEnd.Date))
148138
{
149-
value = _owner.SelectionStart.ToLongDateString();
150-
}
151-
else
152-
{
153-
value = string.Format("{0} - {1}", _owner.SelectionStart.ToLongDateString(), _owner.SelectionEnd.ToLongDateString());
139+
return _owner.SelectionStart.ToLongDateString();
154140
}
141+
142+
return string.Format("{0} - {1}", _owner.SelectionStart.ToLongDateString(), _owner.SelectionEnd.ToLongDateString());
155143
}
156-
else if (_owner._mcCurView == MCMV.YEAR)
144+
145+
if (_owner._mcCurView == MCMV.YEAR)
157146
{
158147
if (System.DateTime.Equals(_owner.SelectionStart.Month, _owner.SelectionEnd.Month))
159148
{
160-
value = _owner.SelectionStart.ToString("y");
161-
}
162-
else
163-
{
164-
value = string.Format("{0} - {1}", _owner.SelectionStart.ToString("y"), _owner.SelectionEnd.ToString("y"));
149+
return _owner.SelectionStart.ToString("y");
165150
}
151+
152+
return string.Format("{0} - {1}", _owner.SelectionStart.ToString("y"), _owner.SelectionEnd.ToString("y"));
166153
}
167-
else
168-
{
169-
value = string.Format("{0} - {1}", _owner.SelectionRange.Start.ToString(), _owner.SelectionRange.End.ToString());
170-
}
154+
155+
return string.Format("{0} - {1}", _owner.SelectionRange.Start.ToString(), _owner.SelectionRange.End.ToString());
171156
}
172157
catch
173158
{
174-
value = base.Value;
159+
return base.Value;
175160
}
176-
177-
return value;
178161
}
179162
set => base.Value = value;
180163
}
@@ -195,6 +178,7 @@ internal override int ColumnCount
195178

196179
int columnCount = 0;
197180
bool success = true;
181+
198182
while (success)
199183
{
200184
success = GetCalendarGridInfo(
@@ -236,6 +220,7 @@ internal override int RowCount
236220

237221
int rowCount = 0;
238222
bool success = true;
223+
239224
while (success)
240225
{
241226
success = GetCalendarGridInfo(
@@ -271,6 +256,7 @@ internal override UiaCore.IRawElementProviderFragment ElementProviderFromPoint(d
271256
int innerY = (int)y;
272257

273258
MCHITTESTINFO hitTestInfo = GetHitTestInfo(innerX, innerY);
259+
274260
switch ((MCHT)hitTestInfo.uHit)
275261
{
276262
case MCHT.TITLEBTNPREV:
@@ -289,7 +275,7 @@ internal override UiaCore.IRawElementProviderFragment ElementProviderFromPoint(d
289275
case MCHT.CALENDARDATE:
290276
// Get calendar body's child.
291277
CalendarBodyAccessibleObject calendarBodyAccessibleObject = (CalendarBodyAccessibleObject)GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody);
292-
return calendarBodyAccessibleObject.GetFromPoint(hitTestInfo);
278+
return calendarBodyAccessibleObject?.GetFromPoint(hitTestInfo);
293279

294280
case MCHT.TODAYLINK:
295281
return GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.TodayLink);
@@ -361,7 +347,8 @@ public string GetCalendarChildName(int calendarIndex, CalendarChildType calendar
361347

362348
private CalendarCellAccessibleObject GetCalendarCell(int calendarIndex, AccessibleObject parentAccessibleObject, int columnIndex)
363349
{
364-
if (columnIndex < 0 ||
350+
if (parentAccessibleObject == null ||
351+
columnIndex < 0 ||
365352
columnIndex >= MAX_DAYS ||
366353
columnIndex >= ColumnCount)
367354
{
@@ -379,12 +366,16 @@ private CalendarCellAccessibleObject GetCalendarCell(int calendarIndex, Accessib
379366
out Kernel32.SYSTEMTIME systemEndDate,
380367
out Kernel32.SYSTEMTIME systemStartDate);
381368

382-
DateTime endDate = DateTimePicker.SysTimeToDateTime(systemEndDate).Date;
383-
DateTime startDate = DateTimePicker.SysTimeToDateTime(systemStartDate).Date;
384-
385369
if (getNameResult && !string.IsNullOrEmpty(text))
386370
{
387-
string cellName = GetCalendarCellName(endDate, startDate, text, rowIndex == -1);
371+
string cellName = string.Empty;
372+
373+
if (getDateResult)
374+
{
375+
DateTime endDate = DateTimePicker.SysTimeToDateTime(systemEndDate).Date;
376+
DateTime startDate = DateTimePicker.SysTimeToDateTime(systemStartDate).Date;
377+
cellName = GetCalendarCellName(endDate, startDate, text, rowIndex == -1);
378+
}
388379

389380
// The cell is present on the calendar, so create accessible object for it.
390381
return new CalendarCellAccessibleObject(this, calendarIndex, parentAccessibleObject, rowIndex, columnIndex, cellName);
@@ -414,7 +405,8 @@ private string GetCalendarCellName(DateTime endDate, DateTime startDate, string
414405

415406
private CalendarRowAccessibleObject GetCalendarRow(int calendarIndex, AccessibleObject parentAccessibleObject, int rowIndex)
416407
{
417-
if ((HasHeaderRow ? rowIndex < -1 : rowIndex < 0) ||
408+
if (parentAccessibleObject == null ||
409+
(HasHeaderRow ? rowIndex < -1 : rowIndex < 0) ||
418410
rowIndex >= RowCount)
419411
{
420412
return null;
@@ -439,7 +431,7 @@ private CalendarRowAccessibleObject GetCalendarRow(int calendarIndex, Accessible
439431

440432
SelectionRange cellsRange = _owner.GetDisplayRange(false);
441433

442-
if (cellsRange.Start > DateTimePicker.SysTimeToDateTime(endDate) || cellsRange.End < DateTimePicker.SysTimeToDateTime(startDate))
434+
if (cellsRange == null || cellsRange.Start > DateTimePicker.SysTimeToDateTime(endDate) || cellsRange.End < DateTimePicker.SysTimeToDateTime(startDate))
443435
{
444436
// Do not create row if the row's first cell is out of the current calendar's view range.
445437
return null;
@@ -648,6 +640,7 @@ private unsafe void SendMouseInput(int x, int y, User32.MOUSEEVENTF flags)
648640
public void RaiseAutomationEventForChild(UiaCore.UIA automationEventId, DateTime selectionStart, DateTime selectionEnd)
649641
{
650642
AccessibleObject calendarChildAccessibleObject = GetCalendarChildAccessibleObject(selectionStart, selectionEnd);
643+
651644
if (calendarChildAccessibleObject != null)
652645
{
653646
calendarChildAccessibleObject.RaiseAutomationEvent(automationEventId);
@@ -661,13 +654,23 @@ public void RaiseAutomationEventForChild(UiaCore.UIA automationEventId, DateTime
661654

662655
private AccessibleObject GetCalendarChildAccessibleObject(DateTime selectionStart, DateTime selectionEnd)
663656
{
664-
int columnCount = ColumnCount;
665-
666657
AccessibleObject bodyAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody);
658+
659+
if (bodyAccessibleObject == null)
660+
{
661+
return null;
662+
}
663+
667664
for (int row = 0; row < RowCount; row++)
668665
{
669666
AccessibleObject rowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, bodyAccessibleObject, row);
670-
for (int column = 0; column < columnCount; column++)
667+
668+
if (rowAccessibleObject == null)
669+
{
670+
continue;
671+
}
672+
673+
for (int column = 0; column < ColumnCount; column++)
671674
{
672675
bool success = GetCalendarGridInfo(
673676
MCGIF.DATE,
@@ -685,6 +688,7 @@ private AccessibleObject GetCalendarChildAccessibleObject(DateTime selectionStar
685688
}
686689

687690
AccessibleObject cellAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, rowAccessibleObject, column);
691+
688692
if (cellAccessibleObject == null)
689693
{
690694
continue;
@@ -715,7 +719,15 @@ internal override UiaCore.IRawElementProviderSimple[] GetColumnHeaderItems()
715719

716720
UiaCore.IRawElementProviderSimple[] headers =
717721
new UiaCore.IRawElementProviderSimple[MonthCalendarAccessibleObject.MAX_DAYS];
718-
AccessibleObject headerRowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, this, -1);
722+
723+
AccessibleObject bodyAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarBody, this, -1);
724+
AccessibleObject headerRowAccessibleObject = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarRow, bodyAccessibleObject, -1);
725+
726+
if (headerRowAccessibleObject == null)
727+
{
728+
return null;
729+
}
730+
719731
for (int columnIndex = 0; columnIndex < MonthCalendarAccessibleObject.MAX_DAYS; columnIndex++)
720732
{
721733
headers[columnIndex] = GetCalendarChildAccessibleObject(_calendarIndex, CalendarChildType.CalendarCell, headerRowAccessibleObject, columnIndex);

0 commit comments

Comments
 (0)