Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / io / __error.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  __Error
9 ** 
10 ** <OWNER>[....]</OWNER>
11 **
12 **
13 ** Purpose: Centralized error methods for the IO package.  
14 ** Mostly useful for translating Win32 HRESULTs into meaningful
15 ** error strings & exceptions.
16 **
17 **
18 ===========================================================*/
19
20 using System;
21 using System.Runtime.InteropServices;
22 #if !MONO
23 using Win32Native = Microsoft.Win32.Win32Native;
24 #endif
25 using System.Text;
26 using System.Globalization;
27 using System.Security;
28 using System.Security.Permissions;
29 using System.Diagnostics.Contracts;
30
31 namespace System.IO {
32     [Pure]
33     internal static class __Error
34     {
35         internal static void EndOfFile() {
36             throw new EndOfStreamException(Environment.GetResourceString("IO.EOF_ReadBeyondEOF"));
37         }
38
39         internal static void FileNotOpen() {
40             throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_FileClosed"));
41         }
42         
43         internal static void StreamIsClosed() {
44             throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
45         }
46     
47         internal static void MemoryStreamNotExpandable() {
48             throw new NotSupportedException(Environment.GetResourceString("NotSupported_MemStreamNotExpandable"));
49         }
50     
51         internal static void ReaderClosed() {
52             throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ReaderClosed"));
53         }
54
55         internal static void ReadNotSupported() {
56             throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
57         }
58     
59         internal static void SeekNotSupported() {
60             throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnseekableStream"));
61         }
62
63         internal static void WrongAsyncResult() {
64             throw new ArgumentException(Environment.GetResourceString("Arg_WrongAsyncResult"));
65         }
66
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"));
70         }
71
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"));
75         }
76
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 
80         // directory name.
81         [System.Security.SecurityCritical]  // auto-generated
82         internal static String GetDisplayablePath(String path, bool isInvalidPath)
83         {
84             
85             if (String.IsNullOrEmpty(path))
86                 return String.Empty;
87
88             // Is it a fully qualified path?
89             bool isFullyQualified = false;
90             if (path.Length < 2)
91                 return path;
92             if (Path.IsDirectorySeparator(path[0]) && Path.IsDirectorySeparator(path[1]))
93                 isFullyQualified = true;
94             else if (path[1] == Path.VolumeSeparatorChar) {
95                 isFullyQualified = true;
96             }
97
98             if (!isFullyQualified && !isInvalidPath)
99                 return path;
100
101 #if DISABLE_CAS_USE
102             bool safeToReturn = !isInvalidPath;
103 #else
104             bool safeToReturn = false;
105             try {
106                 if (!isInvalidPath) {
107 #if !FEATURE_CORECLR
108                     new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
109 #endif
110                     safeToReturn = true;
111                 }
112             }
113             catch (SecurityException) {
114             }
115             catch (ArgumentException) {
116                 // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters
117                 // inside FileIOPermission.AddPathList
118             }
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.  
123             }
124 #endif // DISABLE_CAS_USE
125             if (!safeToReturn) {
126                 if (Path.IsDirectorySeparator(path[path.Length - 1]))
127                     path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
128                 else
129                     path = Path.GetFileName(path);
130             }
131
132             return path;
133         }
134 #if !MONO
135         [System.Security.SecuritySafeCritical]  // auto-generated
136         internal static void WinIOError() {
137             int errorCode = Marshal.GetLastWin32Error();
138             WinIOError(errorCode, String.Empty);
139         }
140     
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);
151
152             switch (errorCode) {
153             case Win32Native.ERROR_FILE_NOT_FOUND:
154                 if (str.Length == 0)
155                     throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound"));
156                 else
157                     throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound_FileName", str), str);
158                 
159             case Win32Native.ERROR_PATH_NOT_FOUND:
160                 if (str.Length == 0)
161                     throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_NoPathName"));
162                 else
163                     throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_Path", str));
164
165             case Win32Native.ERROR_ACCESS_DENIED:
166                 if (str.Length == 0)
167                     throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
168                 else
169                     throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", str));
170
171             case Win32Native.ERROR_ALREADY_EXISTS:
172                 if (str.Length == 0)
173                     goto default;
174                 throw new IOException(Environment.GetResourceString("IO.IO_AlreadyExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
175
176             case Win32Native.ERROR_FILENAME_EXCED_RANGE:
177                 throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
178
179             case Win32Native.ERROR_INVALID_DRIVE:
180                 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", str));
181
182             case Win32Native.ERROR_INVALID_PARAMETER:
183                 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
184
185             case Win32Native.ERROR_SHARING_VIOLATION:
186                 if (str.Length == 0)
187                     throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
188                 else
189                     throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_File", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
190
191             case Win32Native.ERROR_FILE_EXISTS:
192                 if (str.Length == 0)
193                     goto default;
194                 throw new IOException(Environment.GetResourceString("IO.IO_FileExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
195
196             case Win32Native.ERROR_OPERATION_ABORTED:
197                 throw new OperationCanceledException();
198
199             default:
200                 throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
201             }
202         }
203
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);
209         }
210
211         [System.Security.SecurityCritical]  // auto-generated
212         internal static void WinIODriveError(String driveName, int errorCode)
213         {
214             switch (errorCode) {
215             case Win32Native.ERROR_PATH_NOT_FOUND:
216             case Win32Native.ERROR_INVALID_DRIVE:
217                 throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", driveName));
218
219             default: 
220                 WinIOError(errorCode, driveName);                
221                 break;
222             }
223         }
224 #endif
225         internal static void WriteNotSupported() {
226             throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
227         }
228
229         internal static void WriterClosed() {
230             throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_WriterClosed"));
231         }
232 #if !MONO
233         // From WinError.h
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;
238 #endif
239     }
240 }