private void Win32Error(int errorCode, string str)
{
switch (errorCode)
{
case Interop.Errors.ERROR_ACCESS_DENIED:
throw str != null ?
new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_RegistryKeyGeneric_Key, str)) :
new UnauthorizedAccessException();
case Interop.Errors.ERROR_INVALID_HANDLE:
// For normal RegistryKey instances we dispose the SafeRegHandle and throw IOException.
// However, for HKEY_PERFORMANCE_DATA (on a local or remote machine) we avoid disposing the
// SafeRegHandle and only throw the IOException. This is to workaround reentrancy issues
// in PerformanceCounter.NextValue() where the API could throw {NullReference, ObjectDisposed, ArgumentNull}Exception
// on reentrant calls because of this error code path in RegistryKey
//
// Normally we'd make our caller synchronize access to a shared RegistryKey instead of doing something like this,
// however we shipped PerformanceCounter.NextValue() un-synchronized in v2.0RTM and customers have taken a dependency on
// this behavior (being able to simultaneously query multiple remote-machine counters on multiple threads, instead of
// having serialized access).
if (!IsPerfDataKey())
{
_hkey.SetHandleAsInvalid();
_hkey = null;
}
goto default;
case Interop.Errors.ERROR_FILE_NOT_FOUND:
throw new IOException(SR.Arg_RegKeyNotFound, errorCode);
default:
throw new IOException(Interop.Kernel32.GetMessage(errorCode), errorCode);
}
}