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)
99 bool safeToReturn = false;
101 if (!isInvalidPath) {
103 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
108 catch (SecurityException) {
110 catch (ArgumentException) {
111 // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters
112 // inside FileIOPermission.AddPathList
114 catch (NotSupportedException) {
115 // paths like "!Bogus\\dir:with/junk_.in it" can cause NotSupportedException to be thrown
116 // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path
117 // beyond string index position 1.
121 if (Path.IsDirectorySeparator(path[path.Length - 1]))
122 path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
124 path = Path.GetFileName(path);
130 [System.Security.SecuritySafeCritical] // auto-generated
131 internal static void WinIOError() {
132 int errorCode = Marshal.GetLastWin32Error();
133 WinIOError(errorCode, String.Empty);
136 // After calling GetLastWin32Error(), it clears the last error field,
137 // so you must save the HResult and pass it to this method. This method
138 // will determine the appropriate exception to throw dependent on your
139 // error, and depending on the error, insert a string into the message
140 // gotten from the ResourceManager.
141 [System.Security.SecurityCritical] // auto-generated
142 internal static void WinIOError(int errorCode, String maybeFullPath) {
143 // This doesn't have to be perfect, but is a perf optimization.
144 bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME;
145 String str = GetDisplayablePath(maybeFullPath, isInvalidPath);
148 case Win32Native.ERROR_FILE_NOT_FOUND:
150 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound"));
152 throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound_FileName", str), str);
154 case Win32Native.ERROR_PATH_NOT_FOUND:
156 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_NoPathName"));
158 throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_Path", str));
160 case Win32Native.ERROR_ACCESS_DENIED:
162 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
164 throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", str));
166 case Win32Native.ERROR_ALREADY_EXISTS:
169 throw new IOException(Environment.GetResourceString("IO.IO_AlreadyExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
171 case Win32Native.ERROR_FILENAME_EXCED_RANGE:
172 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
174 case Win32Native.ERROR_INVALID_DRIVE:
175 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", str));
177 case Win32Native.ERROR_INVALID_PARAMETER:
178 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
180 case Win32Native.ERROR_SHARING_VIOLATION:
182 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
184 throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_File", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
186 case Win32Native.ERROR_FILE_EXISTS:
189 throw new IOException(Environment.GetResourceString("IO.IO_FileExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
191 case Win32Native.ERROR_OPERATION_ABORTED:
192 throw new OperationCanceledException();
195 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
199 // An alternative to WinIOError with friendlier messages for drives
200 [System.Security.SecuritySafeCritical] // auto-generated
201 internal static void WinIODriveError(String driveName) {
202 int errorCode = Marshal.GetLastWin32Error();
203 WinIODriveError(driveName, errorCode);
206 [System.Security.SecurityCritical] // auto-generated
207 internal static void WinIODriveError(String driveName, int errorCode)
210 case Win32Native.ERROR_PATH_NOT_FOUND:
211 case Win32Native.ERROR_INVALID_DRIVE:
212 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", driveName));
215 WinIOError(errorCode, driveName);
220 internal static void WriteNotSupported() {
221 throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
224 internal static void WriterClosed() {
225 throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_WriterClosed"));
229 internal const int ERROR_FILE_NOT_FOUND = Win32Native.ERROR_FILE_NOT_FOUND;
230 internal const int ERROR_PATH_NOT_FOUND = Win32Native.ERROR_PATH_NOT_FOUND;
231 internal const int ERROR_ACCESS_DENIED = Win32Native.ERROR_ACCESS_DENIED;
232 internal const int ERROR_INVALID_PARAMETER = Win32Native.ERROR_INVALID_PARAMETER;