Resolve "you are registering twice the same counter address" warning on Windows Relea...
[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 #if !MOBILE
61                 internal static PipeAccessRights ToAccessRights (PipeDirection direction)
62                 {
63                         switch (direction) {
64                         case PipeDirection.In:
65                                 return PipeAccessRights.ReadData;
66                         case PipeDirection.Out:
67                                 return PipeAccessRights.WriteData;
68                         case PipeDirection.InOut:
69                                 return PipeAccessRights.ReadData | PipeAccessRights.WriteData;
70                         default:
71                                 throw new ArgumentOutOfRangeException ();
72                         }
73                 }
74
75                 internal static PipeDirection ToDirection (PipeAccessRights rights)
76                 {
77                         bool r = (rights & PipeAccessRights.ReadData) != 0;
78                         bool w = (rights & PipeAccessRights.WriteData) != 0;
79                         if (r) {
80                                 if (w)
81                                         return PipeDirection.InOut;
82                                 else
83                                         return PipeDirection.In;
84                         } else {
85                                 if (w)
86                                         return PipeDirection.Out;
87                                 else
88                                         throw new ArgumentOutOfRangeException ();
89                         }
90                 }
91 #endif
92
93                 protected PipeStream (PipeDirection direction, int bufferSize)
94                         : this (direction, PipeTransmissionMode.Byte, bufferSize)
95                 {
96                 }
97
98                 protected PipeStream (PipeDirection direction, PipeTransmissionMode transmissionMode, int outBufferSize)
99                 {
100                         this.direction = direction;
101                         this.transmission_mode = transmissionMode;
102                         read_trans_mode = transmissionMode;
103                         if (outBufferSize <= 0)
104                                 throw new ArgumentOutOfRangeException ("bufferSize must be greater than 0");
105                         buffer_size = outBufferSize;
106                 }
107
108                 PipeDirection direction;
109                 PipeTransmissionMode transmission_mode, read_trans_mode;
110                 int buffer_size;
111                 SafePipeHandle handle;
112                 Stream stream;
113
114                 public override bool CanRead {
115                         get { return (direction & PipeDirection.In) != 0; }
116                 }
117
118                 public override bool CanSeek {
119                         get { return false; }
120                 }
121
122                 public override bool CanWrite {
123                         get { return (direction & PipeDirection.Out) != 0; }
124                 }
125
126                 public virtual int InBufferSize {
127                         get { return buffer_size; }
128                 }
129
130                 public bool IsAsync { get; private set; }
131
132                 public bool IsConnected { get; protected set; }
133
134                 internal Stream Stream {
135                         get {
136                                 if (!IsConnected)
137                                         throw new InvalidOperationException ("Pipe is not connected");
138                                 if (stream == null)
139                                         stream = new FileStream (handle.DangerousGetHandle (),
140                                                                  CanRead ? (CanWrite ? FileAccess.ReadWrite : FileAccess.Read)
141                                                                          : FileAccess.Write, true, buffer_size, IsAsync);
142                                 return stream;
143                         }
144                         set { stream = value; }
145                 }
146
147 #if !MOBILE
148                 protected bool IsHandleExposed { get; private set; }
149 #endif
150
151                 [MonoTODO]
152                 public bool IsMessageComplete { get; private set; }
153
154                 [MonoTODO]
155                 public virtual int OutBufferSize {
156                         get { return buffer_size; }
157                 }
158
159                 public virtual PipeTransmissionMode ReadMode {
160                         get {
161                                 CheckPipePropertyOperations ();
162                                 return read_trans_mode;
163                         }
164                         set {
165                                 CheckPipePropertyOperations ();
166                                 read_trans_mode = value;
167                         }
168                 }
169
170                 public SafePipeHandle SafePipeHandle {
171                         get {
172                                 CheckPipePropertyOperations ();
173                                 return handle;
174                         }
175                 }
176
177                 public virtual PipeTransmissionMode TransmissionMode {
178                         get {
179                                 CheckPipePropertyOperations ();
180                                 return transmission_mode;
181                         }
182                 }
183
184                 // initialize/dispose/state check
185 #if MOBILE
186                 internal static void CheckPipePropertyOperations ()
187                 {
188                 }
189
190                 static void CheckReadOperations ()
191                 {
192                 }
193
194                 static void CheckWriteOperations ()
195                 {
196                 }
197 #else
198                 [MonoTODO]
199                 protected internal virtual void CheckPipePropertyOperations ()
200                 {
201                 }
202
203                 [MonoTODO]
204                 protected internal void CheckReadOperations ()
205                 {
206                         if (!IsConnected)
207                                 throw new InvalidOperationException ("Pipe is not connected");
208                         if (!CanRead)
209                                 throw new NotSupportedException ("The pipe stream does not support read operations");
210                 }
211
212                 [MonoTODO]
213                 protected internal void CheckWriteOperations ()
214                 {
215                         if (!IsConnected)
216                                 throw new InvalidOperationException ("Pipe is not connected");
217                         if (!CanWrite)
218                                 throw new NotSupportedException ("The pipe stream does not support write operations");
219                 }
220
221                 protected void InitializeHandle (SafePipeHandle handle, bool isExposed, bool isAsync)
222                 {
223                         this.handle = handle;
224                         this.IsHandleExposed = isExposed;
225                         this.IsAsync = isAsync;
226                 }
227 #endif
228
229                 protected override void Dispose (bool disposing)
230                 {
231                         if (handle != null && disposing)
232                                 handle.Dispose ();
233                 }
234
235                 // not supported
236
237                 public override long Length {
238                         get { throw new NotSupportedException (); }
239                 }
240
241                 public override long Position {
242                         get { return 0; }
243                         set { throw new NotSupportedException (); }
244                 }
245
246                 public override void SetLength (long value)
247                 {
248                         throw new NotSupportedException ();
249                 }
250
251                 public override long Seek (long offset, SeekOrigin origin)
252                 {
253                         throw new NotSupportedException ();
254                 }
255
256 #if !MOBILE
257                 public PipeSecurity GetAccessControl ()
258                 {
259                         return new PipeSecurity (SafePipeHandle,
260                                                  AccessControlSections.Owner |
261                                                  AccessControlSections.Group |
262                                                  AccessControlSections.Access);
263                 }
264
265                 public void SetAccessControl (PipeSecurity pipeSecurity)
266                 {
267                         if (pipeSecurity == null)
268                                 throw new ArgumentNullException ("pipeSecurity");
269                                 
270                         pipeSecurity.Persist (SafePipeHandle);
271                 }
272 #endif
273
274                 // pipe I/O
275
276                 public void WaitForPipeDrain ()
277                 {
278                 }
279
280                 [MonoTODO]
281                 public override int Read ([In] byte [] buffer, int offset, int count)
282                 {
283                         CheckReadOperations ();
284
285                         return Stream.Read (buffer, offset, count);
286                 }
287
288                 [MonoTODO]
289                 public override int ReadByte ()
290                 {
291                         CheckReadOperations ();
292
293                         return Stream.ReadByte ();
294                 }
295
296                 [MonoTODO]
297                 public override void Write (byte [] buffer, int offset, int count)
298                 {
299                         CheckWriteOperations ();
300
301                         Stream.Write (buffer, offset, count);
302                 }
303
304                 [MonoTODO]
305                 public override void WriteByte (byte value)
306                 {
307                         CheckWriteOperations ();
308
309                         Stream.WriteByte (value);
310                 }
311
312                 [MonoTODO]
313                 public override void Flush ()
314                 {
315                         CheckWriteOperations ();
316
317                         Stream.Flush ();
318                 }
319
320                 // async
321
322 #if !MOBILE
323                 Func<byte [],int,int,int> read_delegate;
324
325                 [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
326                 public override IAsyncResult BeginRead (byte [] buffer, int offset, int count, AsyncCallback callback, object state)
327                 {
328                         if (read_delegate == null)
329                                 read_delegate = new Func<byte[],int,int,int> (Read);
330                         return read_delegate.BeginInvoke (buffer, offset, count, callback, state);
331                 }
332
333                 Action<byte[],int,int> write_delegate;
334
335                 [HostProtection (SecurityAction.LinkDemand, ExternalThreading = true)]
336                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
337                 {
338                         if (write_delegate == null)
339                                 write_delegate = new Action<byte[],int,int> (Write);
340                         return write_delegate.BeginInvoke (buffer, offset, count, callback, state);
341                 }
342
343                 public override int EndRead (IAsyncResult asyncResult)
344                 {
345                         return read_delegate.EndInvoke (asyncResult);
346                 }
347
348                 public override void EndWrite (IAsyncResult asyncResult)
349                 {
350                         write_delegate.EndInvoke (asyncResult);
351                 }
352 #endif
353         }
354 }
355
356 #endif