3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
10 ** <OWNER>[....]</OWNER>
13 ** Purpose: Centralized error methods for the IO package.
14 ** Mostly useful for translating Win32 HRESULTs into meaningful
15 ** error strings & exceptions.
18 ===========================================================*/
21 using System.Runtime.InteropServices;
22 using Win32Native = Microsoft.Win32.Win32Native;
24 using System.Globalization;
25 using System.Security;
26 using System.Security.Permissions;
27 using System.Diagnostics.Contracts;
31 internal static class __Error
33 internal static void EndOfFile() {
34 throw new EndOfStreamException(Environment.GetResourceString("IO.EOF_ReadBeyondEOF"));
37 internal static void FileNotOpen() {
38 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_FileClosed"));
41 internal static void StreamIsClosed() {
42 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
45 internal static void MemoryStreamNotExpandable() {
46 throw new NotSupportedException(Environment.GetResourceString("NotSupported_MemStreamNotExpandable"));
49 internal static void ReaderClosed() {
50 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ReaderClosed"));
53 internal static void ReadNotSupported() {
54 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
57 internal static void SeekNotSupported() {
58 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnseekableStream"));
61 internal static void WrongAsyncResult() {
62 throw new ArgumentException(Environment.GetResourceString("Arg_WrongAsyncResult"));
65 internal static void EndReadCalledTwice() {
66 // Should ideally be InvalidOperationExc but we can't maitain parity with Stream and FileStream without some work
67 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndReadCalledMultiple"));
70 internal static void EndWriteCalledTwice() {
71 // Should ideally be InvalidOperationExc but we can't maintain parity with Stream and FileStream without some work
72 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndWriteCalledMultiple"));
75 // Given a possible fully qualified path, ensure that we have path
76 // discovery permission to that path. If we do not, return just the
77 // file name. If we know it is a directory, then don't return the
79 [System.Security.SecurityCritical] // auto-generated
80 internal static String GetDisplayablePath(String path, bool isInvalidPath)
83 if (String.IsNullOrEmpty(path))
86 // Is it a fully qualified path?
87 bool isFullyQualified = false;
90 if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1]))
91 isFullyQualified = true;
92 else if (path[1] == Path.VolumeSeparatorChar) {
93 isFullyQualified = true;
96 if (!isFullyQualified && !isInvalidPath)
100 bool safeToReturn = false;
102 if (!isInvalidPath) {
104 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
109 catch (SecurityException) {
111 catch (ArgumentException) {
112 // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters
113 // inside FileIOPermission.AddPathList
115 catch (NotSupportedException) {
116 // paths like "!Bogus\\dir:with/junk_.in it" can cause NotSupportedException to be thrown
117 // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path
118 // beyond string index position 1.
121 bool safeToReturn = !isInvalidPath;
122 #endif // FEATURE_MONO_CAS
124 if (Path.IsDirectorySeparator(path[path.Length - 1]))
125 path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
127 path = Path.GetFileName(path);
133 [System.Security.SecuritySafeCritical] // auto-generated
134 internal static void WinIOError() {
135 int errorCode = Marshal.GetLastWin32Error();
136 WinIOError(errorCode, String.Empty);
139 // After calling GetLastWin32Error(), it clears the last error field,
140 // so you must save the HResult and pass it to this method. This method
141 // will determine the appropriate exception to throw dependent on your
142 // error, and depending on the error, insert a string into the message
143 // gotten from the ResourceManager.
144 [System.Security.SecurityCritical] // auto-generated
145 internal static void WinIOError(int errorCode, String maybeFullPath) {
146 // This doesn't have to be perfect, but is a perf optimization.
147 bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME;
148 String str = GetDisplayablePath(maybeFullPath, isInvalidPath);
151 case Win32Native.ERROR_FILE_NOT_FOUND:
153 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound"));
155 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound_FileName", str), str);
157 case Win32Native.ERROR_PATH_NOT_FOUND:
159 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_NoPathName"));
161 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_Path", str));
163 case Win32Native.ERROR_ACCESS_DENIED:
165 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
167 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", str));
169 case Win32Native.ERROR_ALREADY_EXISTS:
172 throw new IOException(Environment.GetResourceString("IO.IO_AlreadyExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
174 case Win32Native.ERROR_FILENAME_EXCED_RANGE:
175 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
177 case Win32Native.ERROR_INVALID_DRIVE:
178 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", str));
180 case Win32Native.ERROR_INVALID_PARAMETER:
181 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
183 case Win32Native.ERROR_SHARING_VIOLATION:
185 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
187 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_File", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
189 case Win32Native.ERROR_FILE_EXISTS:
192 throw new IOException(Environment.GetResourceString("IO.IO_FileExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
194 case Win32Native.ERROR_OPERATION_ABORTED:
195 throw new OperationCanceledException();
198 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
202 // An alternative to WinIOError with friendlier messages for drives
203 [System.Security.SecuritySafeCritical] // auto-generated
204 internal static void WinIODriveError(String driveName) {
205 int errorCode = Marshal.GetLastWin32Error();
206 WinIODriveError(driveName, errorCode);
209 [System.Security.SecurityCritical] // auto-generated
210 internal static void WinIODriveError(String driveName, int errorCode)
213 case Win32Native.ERROR_PATH_NOT_FOUND:
214 case Win32Native.ERROR_INVALID_DRIVE:
215 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", driveName));
218 WinIOError(errorCode, driveName);
223 internal static void WriteNotSupported() {
224 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
227 internal static void WriterClosed() {
228 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_WriterClosed"));
232 internal const int ERROR_FILE_NOT_FOUND = Win32Native.ERROR_FILE_NOT_FOUND;
233 internal const int ERROR_PATH_NOT_FOUND = Win32Native.ERROR_PATH_NOT_FOUND;
234 internal const int ERROR_ACCESS_DENIED = Win32Native.ERROR_ACCESS_DENIED;
235 internal const int ERROR_INVALID_PARAMETER = Win32Native.ERROR_INVALID_PARAMETER;