Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit ac3d3ba

Browse files
JeremyKuhnestephentoub
authored andcommitted
Change CoreFX to use SetThreadErrorMode (#19801)
* Change CoreFX to use SetThreadErrorMode See #19738. SetErrorMode isn't thread safe- we use SetThreadErrorMode in NetFX. * Add P/Invoke exceptions
1 parent 36137ca commit ac3d3ba

File tree

9 files changed

+51
-30
lines changed

9 files changed

+51
-30
lines changed

src/Common/src/Interop/Windows/kernel32/Interop.SetErrorMode.Uap.cs renamed to src/Common/src/Interop/Windows/kernel32/Interop.SetThreadErrorMode.Uap.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ internal partial class Interop
88
{
99
internal partial class Kernel32
1010
{
11-
internal static uint SetErrorMode(uint uMode)
11+
internal static bool SetThreadErrorMode(uint dwNewMode, out uint lpOldMode)
1212
{
1313
// Prompting behavior no longer occurs in all platforms supported
14-
return 0;
14+
lpOldMode = 0;
15+
return true;
1516
}
1617
}
1718
}

src/Common/src/Interop/Windows/kernel32/Interop.SetErrorMode.cs renamed to src/Common/src/Interop/Windows/kernel32/Interop.SetThreadErrorMode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal partial class Interop
88
{
99
internal partial class Kernel32
1010
{
11-
[DllImport(Libraries.Kernel32, SetLastError = false, EntryPoint = "SetErrorMode", ExactSpelling = true)]
12-
internal static extern uint SetErrorMode(uint newMode);
11+
[DllImport(Libraries.Kernel32, SetLastError = true, ExactSpelling = true)]
12+
internal static extern bool SetThreadErrorMode(uint dwNewMode, out uint lpOldMode);
1313
}
1414
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
kernel32.dll!GetDriveTypeW
22
kernel32.dll!GetLogicalDrives
33
kernel32.dll!GetVolumeInformationW
4-
kernel32.dll!SetErrorMode
4+
kernel32.dll!SetThreadErrorMode
55
kernel32.dll!SetVolumeLabelW

src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetVolumeLabel.cs">
5050
<Link>Common\Interop\Windows\Interop.SetVolumeLabel.cs</Link>
5151
</Compile>
52-
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetErrorMode.cs">
53-
<Link>Common\Interop\Windows\Interop.SetErrorMode.cs</Link>
52+
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetThreadErrorMode.cs">
53+
<Link>Common\Interop\Windows\Interop.SetThreadErrorMode.cs</Link>
5454
</Compile>
5555
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SecurityOptions.cs">
5656
<Link>Common\Interop\Windows\Interop.SecurityOptions.cs</Link>

src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Windows.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ public String DriveFormat
6767
StringBuilder fileSystemName = new StringBuilder(fileSystemNameLen);
6868
int serialNumber, maxFileNameLen, fileSystemFlags;
6969

70-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
70+
uint oldMode;
71+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
7172
try
7273
{
7374
bool r = Interop.Kernel32.GetVolumeInformation(Name, volumeName, volNameLen, out serialNumber, out maxFileNameLen, out fileSystemFlags, fileSystemName, fileSystemNameLen);
@@ -78,7 +79,8 @@ public String DriveFormat
7879
}
7980
finally
8081
{
81-
Interop.Kernel32.SetErrorMode(oldMode);
82+
if (success)
83+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
8284
}
8385
return fileSystemName.ToString();
8486
}
@@ -90,7 +92,8 @@ public long AvailableFreeSpace
9092
get
9193
{
9294
long userBytes, totalBytes, freeBytes;
93-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
95+
uint oldMode;
96+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
9497
try
9598
{
9699
bool r = Interop.Kernel32.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
@@ -99,7 +102,8 @@ public long AvailableFreeSpace
99102
}
100103
finally
101104
{
102-
Interop.Kernel32.SetErrorMode(oldMode);
105+
if (success)
106+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
103107
}
104108
return userBytes;
105109
}
@@ -111,7 +115,8 @@ public long TotalFreeSpace
111115
get
112116
{
113117
long userBytes, totalBytes, freeBytes;
114-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
118+
uint oldMode;
119+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
115120
try
116121
{
117122
bool r = Interop.Kernel32.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
@@ -120,7 +125,8 @@ public long TotalFreeSpace
120125
}
121126
finally
122127
{
123-
Interop.Kernel32.SetErrorMode(oldMode);
128+
if (success)
129+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
124130
}
125131
return freeBytes;
126132
}
@@ -134,7 +140,8 @@ public long TotalSize
134140
// Don't cache this, to handle variable sized floppy drives
135141
// or other various removable media drives.
136142
long userBytes, totalBytes, freeBytes;
137-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
143+
uint oldMode;
144+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
138145
try
139146
{
140147
bool r = Interop.Kernel32.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
@@ -143,7 +150,7 @@ public long TotalSize
143150
}
144151
finally
145152
{
146-
Interop.Kernel32.SetErrorMode(oldMode);
153+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
147154
}
148155
return totalBytes;
149156
}
@@ -174,7 +181,8 @@ public String VolumeLabel
174181
StringBuilder fileSystemName = new StringBuilder(fileSystemNameLen);
175182
int serialNumber, maxFileNameLen, fileSystemFlags;
176183

177-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
184+
uint oldMode;
185+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
178186
try
179187
{
180188
bool r = Interop.Kernel32.GetVolumeInformation(Name, volumeName, volNameLen, out serialNumber, out maxFileNameLen, out fileSystemFlags, fileSystemName, fileSystemNameLen);
@@ -190,14 +198,16 @@ public String VolumeLabel
190198
}
191199
finally
192200
{
193-
Interop.Kernel32.SetErrorMode(oldMode);
201+
if (success)
202+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
194203
}
195204
return volumeName.ToString();
196205
}
197206
[System.Security.SecuritySafeCritical] // auto-generated
198207
set
199208
{
200-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
209+
uint oldMode;
210+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
201211
try
202212
{
203213
bool r = Interop.Kernel32.SetVolumeLabel(Name, value);
@@ -212,7 +222,8 @@ public String VolumeLabel
212222
}
213223
finally
214224
{
215-
Interop.Kernel32.SetErrorMode(oldMode);
225+
if (success)
226+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
216227
}
217228
}
218229
}

src/System.IO.FileSystem/src/PinvokeAnalyzerExceptionList.analyzerdata

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ kernel32.dll!CopyFileExW
22
kernel32.dll!CreateFileW
33
kernel32.dll!DeleteVolumeMountPointW
44
kernel32.dll!GetLogicalDrives
5-
kernel32.dll!SetErrorMode
5+
kernel32.dll!SetThreadErrorMode
66

src/System.IO.FileSystem/src/System.IO.FileSystem.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@
214214
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.DeleteVolumeMountPoint.cs">
215215
<Link>Common\Interop\Windows\Interop.DeleteVolumeMountPoint.cs</Link>
216216
</Compile>
217-
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetErrorMode.cs">
218-
<Link>Common\Interop\Windows\Interop.SetErrorMode.cs</Link>
217+
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetThreadErrorMode.cs">
218+
<Link>Common\Interop\Windows\Interop.SetThreadErrorMode.cs</Link>
219219
</Compile>
220220
</ItemGroup>
221221
<!-- Windows : UAP - Win32 + WinRT -->
@@ -229,8 +229,8 @@
229229
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.DeleteVolumeMountPoint.Uap.cs">
230230
<Link>Common\Interop\Windows\Interop.DeleteVolumeMountPoint.Uap.cs</Link>
231231
</Compile>
232-
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetErrorMode.Uap.cs">
233-
<Link>Common\Interop\Windows\Interop.SetErrorMode.Uap.cs</Link>
232+
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetThreadErrorMode.Uap.cs">
233+
<Link>Common\Interop\Windows\Interop.SetThreadErrorMode.Uap.cs</Link>
234234
</Compile>
235235
<Compile Include="System\IO\FileSystem.Current.MuxWin32WinRT.cs" />
236236
<Compile Include="System\IO\FileSystemInfo.WinRT.cs" />

src/System.IO.FileSystem/src/System/IO/Win32FileSystem.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ internal static int FillAttributeInfo(String path, ref Interop.Kernel32.WIN32_FI
238238
// there is no disk in drive A:, please insert one. We don't want that.
239239
// SetErrorMode will let us disable this, but we should set the error
240240
// mode back, since this may have wide-ranging effects.
241-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
241+
uint oldMode;
242+
bool success = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
242243
try
243244
{
244245
bool error = false;
@@ -283,7 +284,8 @@ internal static int FillAttributeInfo(String path, ref Interop.Kernel32.WIN32_FI
283284
}
284285
finally
285286
{
286-
Interop.Kernel32.SetErrorMode(oldMode);
287+
if (success)
288+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
287289
}
288290

289291
// Copy the information to data
@@ -296,14 +298,16 @@ internal static int FillAttributeInfo(String path, ref Interop.Kernel32.WIN32_FI
296298
// SetErrorMode will let us disable this, but we should set the error
297299
// mode back, since this may have wide-ranging effects.
298300
bool success = false;
299-
uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
301+
uint oldMode;
302+
bool errorModeSuccess = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
300303
try
301304
{
302305
success = Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data);
303306
}
304307
finally
305308
{
306-
Interop.Kernel32.SetErrorMode(oldMode);
309+
if (errorModeSuccess)
310+
Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
307311
}
308312

309313
if (!success)

src/System.IO.FileSystem/src/System/IO/Win32FileSystemEnumerable.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ internal class Win32FileSystemEnumerableIterator<TSource> : Iterator<TSource>
112112
private readonly string _fullPath;
113113
private readonly string _normalizedSearchPath;
114114
private readonly uint _oldMode;
115+
private readonly bool _setBackOldMode;
115116

116117
[SecuritySafeCritical]
117118
internal Win32FileSystemEnumerableIterator(string path, string originalUserPath, string searchPattern, SearchOption searchOption, SearchResultHandler<TSource> resultHandler)
@@ -122,7 +123,7 @@ internal Win32FileSystemEnumerableIterator(string path, string originalUserPath,
122123
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
123124
Debug.Assert(resultHandler != null);
124125

125-
_oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS);
126+
_setBackOldMode = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out _oldMode);
126127

127128
string normalizedSearchPattern = PathHelpers.NormalizeSearchPattern(searchPattern);
128129

@@ -251,7 +252,11 @@ protected override void Dispose(bool disposing)
251252
}
252253
finally
253254
{
254-
Interop.Kernel32.SetErrorMode(_oldMode);
255+
if (_setBackOldMode)
256+
{
257+
uint _ignore;
258+
Interop.Kernel32.SetThreadErrorMode(_oldMode, out _ignore);
259+
}
255260
base.Dispose(disposing);
256261
}
257262
}

0 commit comments

Comments
 (0)