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;
23 using Win32Native = Microsoft.Win32.Win32Native;
26 using System.Globalization;
27 using System.Security;
28 using System.Security.Permissions;
29 using System.Diagnostics.Contracts;
33 internal static class __Error
35 internal static void EndOfFile() {
36 throw new EndOfStreamException(Environment.GetResourceString("IO.EOF_ReadBeyondEOF"));
39 internal static void FileNotOpen() {
40 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_FileClosed"));
43 internal static void StreamIsClosed() {
44 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
47 internal static void MemoryStreamNotExpandable() {
48 throw new NotSupportedException(Environment.GetResourceString("NotSupported_MemStreamNotExpandable"));
51 internal static void ReaderClosed() {
52 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ReaderClosed"));
55 internal static void ReadNotSupported() {
56 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
59 internal static void SeekNotSupported() {
60 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnseekableStream"));
63 internal static void WrongAsyncResult() {
64 throw new ArgumentException(Environment.GetResourceString("Arg_WrongAsyncResult"));
67 internal static void EndReadCalledTwice() {
68 // Should ideally be InvalidOperationExc but we can't maitain parity with Stream and FileStream without some work
69 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndReadCalledMultiple"));
72 internal static void EndWriteCalledTwice() {
73 // Should ideally be InvalidOperationExc but we can't maintain parity with Stream and FileStream without some work
74 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndWriteCalledMultiple"));
77 // Given a possible fully qualified path, ensure that we have path
78 // discovery permission to that path. If we do not, return just the
79 // file name. If we know it is a directory, then don't return the
81 [System.Security.SecurityCritical] // auto-generated
82 internal static String GetDisplayablePath(String path, bool isInvalidPath)
85 if (String.IsNullOrEmpty(path))
88 // Is it a fully qualified path?
89 bool isFullyQualified = false;
92 if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1]))
93 isFullyQualified = true;
94 else if (path[1] == Path.VolumeSeparatorChar) {
95 isFullyQualified = true;
98 if (!isFullyQualified && !isInvalidPath)
102 bool safeToReturn = !isInvalidPath;
104 bool safeToReturn = false;
106 if (!isInvalidPath) {
108 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
113 catch (SecurityException) {
115 catch (ArgumentException) {
116 // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters
117 // inside FileIOPermission.AddPathList
119 catch (NotSupportedException) {
120 // paths like "!Bogus\\dir:with/junk_.in it" can cause NotSupportedException to be thrown
121 // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path
122 // beyond string index position 1.
124 #endif // DISABLE_CAS_USE
126 if (Path.IsDirectorySeparator(path[path.Length - 1]))
127 path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
129 path = Path.GetFileName(path);
135 [System.Security.SecuritySafeCritical] // auto-generated
136 internal static void WinIOError() {
137 int errorCode = Marshal.GetLastWin32Error();
138 WinIOError(errorCode, String.Empty);
141 // After calling GetLastWin32Error(), it clears the last error field,
142 // so you must save the HResult and pass it to this method. This method
143 // will determine the appropriate exception to throw dependent on your
144 // error, and depending on the error, insert a string into the message
145 // gotten from the ResourceManager.
146 [System.Security.SecurityCritical] // auto-generated
147 internal static void WinIOError(int errorCode, String maybeFullPath) {
148 // This doesn't have to be perfect, but is a perf optimization.
149 bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME;
150 String str = GetDisplayablePath(maybeFullPath, isInvalidPath);
153 case Win32Native.ERROR_FILE_NOT_FOUND:
155 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound"));
157 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound_FileName", str), str);
159 case Win32Native.ERROR_PATH_NOT_FOUND:
161 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_NoPathName"));
163 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_Path", str));
165 case Win32Native.ERROR_ACCESS_DENIED:
167 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
169 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", str));
171 case Win32Native.ERROR_ALREADY_EXISTS:
174 throw new IOException(Environment.GetResourceString("IO.IO_AlreadyExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
176 case Win32Native.ERROR_FILENAME_EXCED_RANGE:
177 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
179 case Win32Native.ERROR_INVALID_DRIVE:
180 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", str));
182 case Win32Native.ERROR_INVALID_PARAMETER:
183 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
185 case Win32Native.ERROR_SHARING_VIOLATION:
187 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
189 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_File", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
191 case Win32Native.ERROR_FILE_EXISTS:
194 throw new IOException(Environment.GetResourceString("IO.IO_FileExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
196 case Win32Native.ERROR_OPERATION_ABORTED:
197 throw new OperationCanceledException();
200 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
204 // An alternative to WinIOError with friendlier messages for drives
205 [System.Security.SecuritySafeCritical] // auto-generated
206 internal static void WinIODriveError(String driveName) {
207 int errorCode = Marshal.GetLastWin32Error();
208 WinIODriveError(driveName, errorCode);
211 [System.Security.SecurityCritical] // auto-generated
212 internal static void WinIODriveError(String driveName, int errorCode)
215 case Win32Native.ERROR_PATH_NOT_FOUND:
216 case Win32Native.ERROR_INVALID_DRIVE:
217 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", driveName));
220 WinIOError(errorCode, driveName);
225 internal static void WriteNotSupported() {
226 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
229 internal static void WriterClosed() {
230 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_WriterClosed"));
234 internal const int ERROR_FILE_NOT_FOUND = Win32Native.ERROR_FILE_NOT_FOUND;
235 internal const int ERROR_PATH_NOT_FOUND = Win32Native.ERROR_PATH_NOT_FOUND;
236 internal const int ERROR_ACCESS_DENIED = Win32Native.ERROR_ACCESS_DENIED;
237 internal const int ERROR_INVALID_PARAMETER = Win32Native.ERROR_INVALID_PARAMETER;