Merge pull request #3622 from rolfbjarne/remove-stray-file
[mono.git] / mcs / class / System.Core / System.IO.Pipes / PipeStream.cs
1 //
2 // PipeStream.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2009 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 #if !BOOTSTRAP_BASIC
30
31 using Microsoft.Win32.SafeHandles;
32 using System;
33 using System.IO;
34 using System.Linq;
35 using System.Security.AccessControl;
36 using System.Security.Permissions;
37 using System.Security.Principal;
38 using System.Runtime.InteropServices;
39
40 namespace System.IO.Pipes
41 {
42         [PermissionSet (SecurityAction.InheritanceDemand, Name = "FullTrust")]
43         [HostProtection (SecurityAction.LinkDemand, MayLeakOnAbort = true)]
44         public abstract class PipeStream : Stream
45         {
46                 // FIXME: not precise.
47                 internal const int DefaultBufferSize = 0x400;
48
49 #if !MOBILE
50                 internal static bool IsWindows {
51                         get { return Win32Marshal.IsWindows; }
52                 }
53 #endif
54
55                 internal Exception ThrowACLException ()
56                 {
57                         return new NotImplementedException ("ACL is not supported in Mono");
58                 }
59
60                 internal static PipeAccessRights ToAccessRights (PipeDirection direction)
61                 {
62                         switch (direction) {
63                         case PipeDirection.In:
64                                 return PipeAccessRights.ReadData;
65                         case PipeDirection.Out:
66                                 return PipeAccessRights.WriteData;
67                         case PipeDirection.InOut:
68                                 return PipeAccessRights.ReadData | PipeAccessRights.WriteData;
69                         default:
70                                 throw new ArgumentOutOfRangeException ();
71                         }
72                 }
73
74                 internal static PipeDirection ToDirection (PipeAccessRights rights)
75                 {
76                         bool r = (rights & PipeAccessRights.ReadData) != 0;
77                         bool w = (rights & PipeAccessRights.WriteData) != 0;
78                         if (r) {
79                                 if (w)
80                                         return PipeDirection.InOut;
81                                 else
82                                         return PipeDirection.In;
83                         } else {
84                                 if (w)
85                                         return PipeDirection.Out;
86                                 else
87                                         throw new ArgumentOutOfRangeException ();
88                         }
89                 }
90
91                 protected PipeStream (PipeDirection direction, int bufferSize)
92                         : this (direction, PipeTransmissionMode.Byte, bufferSize)
93                 {
94                 }
95
96                 protected PipeStream (PipeDirection direction, PipeTransmissionMode transmissionMode, int outBufferSize)
97                 {
98                         this.direction = direction;
99                         this.transmission_mode = transmissionMode;
100                         read_trans_mode = transmissionMode;
101                         if (outBufferSize <= 0)
102                                 throw new ArgumentOutOfRangeException ("bufferSize must be greater than 0");
103                         buffer_size = outBufferSize;
104                 }
105
106                 PipeDirection direction;
107                 PipeTransmissionMode transmission_mode, read_trans_mode;
108                 int buffer_size;
109                 SafePipeHandle handle;
110                 Stream stream;
111
112                 public override bool CanRead {
113                         get { return (direction & PipeDirection.In) != 0; }
114                 }
115
116                 public override bool CanSeek {
117                         get { return false; }
118                 }
119
120                 public override bool CanWrite {
121                         get { return (direction & PipeDirection.Out) != 0; }
122                 }
123
124                 public virtual int InBufferSize {
125                         get { return buffer_size; }
126                 }
127
128                 public bool IsAsync { get; private set; }
129
130                 public bool IsConnected { get; protected set; }
131
132                 internal Stream Stream {
133                         get {
134                                 if (!IsConnected)
135                                         throw new InvalidOperationException ("Pipe is not connected");
136                                 if (stream == null)
137                                         stream = new FileStream (handle.DangerousGetHandle (),
138                                                                  CanRead ? (CanWrite ? FileAccess.ReadWrite : FileAccess.Read)
139                                                                          : FileAccess.Write, true, buffer_size, IsAsync);
140                                 return stream;
141                         }
142                         set { stream = value; }
143                 }
144
145                 protected bool IsHandleExposed { get; private set; }
146
147                 [MonoTODO]
148                 public bool IsMessageComplete { get; private set; }
149
150                 [MonoTODO]
151                 public virtual int OutBufferSize {
152                         get { return buffer_size; }
153                 }
154
155                 public virtual PipeTransmissionMode ReadMode {
156                         get {
157                                 CheckPipePropertyOperations ();
158                                 return read_trans_mode;
159                         }
160                         set {
161                                 CheckPipePropertyOperations ();
162                                 read_trans_mode = value;
163                         }
164                 }
165
166                 public SafePipeHandle SafePipeHandle {
167                         get {
168                                 CheckPipePropertyOperations ();
169                                 return handle;
170                         }
171                 }
172
173                 public virtual PipeTransmissionMode TransmissionMode {
174                         get {
175                                 CheckPipePropertyOperations ();
176                                 return transmission_mode;
177                         }
178                 }
179
180                 // initialize/dispose/state check
181
182                 [MonoTODO]
183                 protected internal virtual void CheckPipePropertyOperations ()
184                 {
185                 }
186
187                 [MonoTODO]
188                 protected internal void CheckReadOperations ()
189                 {
190                         if (!IsConnected)
191                                 throw new InvalidOperationException ("Pipe is not connected");
192                         if (!CanRead)
193                                 throw new NotSupportedException ("The pipe stream does not support read operations");
194                 }
195
196                 [MonoTODO]
197                 protected internal void CheckWriteOperations ()
198                 {
199                         if (!IsConnected)
200                                 throw new InvalidOperationException ("Pipe is not connected");
201                         if (!CanWrite)
202                                 throw new NotSupportedException ("The pipe stream does not support write operations");
203                 }
204
205                 protected void InitializeHandle (SafePipeHandle handle, bool isExposed, bool isAsync)
206                 {
207                         this.handle = handle;
208                         this.IsHandleExposed = isExposed;
209                         this.IsAsync = isAsync;
210                 }
211
212                 protected override void Dispose (bool disposing)
213                 {
214                         if (handle != null && disposing)
215                                 handle.Dispose ();
216                 }
217
218                 // not supported
219
220                 public override long Length {
221                         get { throw new NotSupportedException (); }
222                 }
223
224                 public override long Position {
225                         get { return 0; }
226                         set { throw new NotSupportedException (); }
227                 }
228
229                 public override void SetLength (long value)
230                 {
231                         throw new NotSupportedException ();
232                 }
233
234                 public override long Seek (long offset, SeekOrigin origin)
235                 {
236                         throw new NotSupportedException ();
237                 }
238
239                 public PipeSecurity GetAccessControl ()
240                 {
241 #if MOBILE
242                         throw new PlatformNotSupportedException ();
243 #else
244                         return new PipeSecurity (SafePipeHandle,
245                                                  AccessControlSections.Owner |
246                                                  AccessControlSections.Group |
247                                                  AccessControlSections.Access);
248 #endif
249                 }
250
251                 public void SetAccessControl (PipeSecurity pipeSecurity)
252                 {
253 #if MOBILE
254                         throw new PlatformNotSupportedException ();
255 #else
256                         if (pipeSecurity == null)
257                                 throw new ArgumentNullException ("pipeSecurity");
258                                 
259                         pipeSecurity.Persist (SafePipeHandle);
260 #endif
261                 }
262
263                 // pipe I/O
264
265                 public void WaitForPipeDrain ()
266                 {
267                 }
268
269                 [MonoTODO]
270                 public override int Read ([In] byte [] buffer, int offset, int count)
271                 {
272                         CheckReadOperations ();
273
274                         return Stream.Read (buffer, offset, count);
275                 }
276
277                 [MonoTODO]
278                 public override int ReadByte ()
279                 {
280                         CheckReadOperations ();
281
282                         return Stream.ReadByte ();
283                 }
284
285                 [MonoTODO]
286                 public override void Write (byte [] buffer, int offset, int count)
287                 {
288                         CheckWriteOperations ();
289
290                         Stream.Write (buffer, offset, count);
291                 }
292
293                 [MonoTODO]
294                 public override void WriteByte (byte value)
295                 {
296                         CheckWriteOperations ();
297
298                         Stream.WriteByte (value);
299                 }
300
301                 [MonoTODO]
302                 public override void Flush ()
303                 {
304                         CheckWriteOperations ();
305
306                         Stream.Flush ();
307                 }
308
309                 // async
310
311                 Func<byte [],int,int,int> read_delegate;
312
313                 [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
314                 public override IAsyncResult BeginRead (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
315                 {
316                         if (read_delegate == null)
317                                 read_delegate = new Func<byte[],int,int,int> (Read);
318                         return read_delegate.BeginInvoke (buffer, offset, count, callback, state);
319                 }
320
321                 Action<byte[],int,int> write_delegate;
322
323                 [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
324                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
325                 {
326                         if (write_delegate == null)
327                                 write_delegate = new Action<byte[],int,int> (Write);
328                         return write_delegate.BeginInvoke (buffer, offset, count, callback, state);
329                 }
330
331                 public override int EndRead (IAsyncResult asyncResult)
332                 {
333                         return read_delegate.EndInvoke (asyncResult);
334                 }
335
336                 public override void EndWrite (IAsyncResult asyncResult)
337                 {
338                         write_delegate.EndInvoke (asyncResult);
339                 }
340         }
341 }
342
343 #endif