Merge pull request #216 from ilkerde/master
[mono.git] / mcs / class / corlib / System.Security.Cryptography / RNGCryptoServiceProvider.cs
index c7b923cc2688f3b4259055130779919b6f2ea88a..e0ffb2e8e8b50e5b0ef58b367a8f29fedc23b188 100644 (file)
@@ -6,11 +6,7 @@
 //     Sebastien Pouliot (sebastien@ximian.com)
 //
 // (C) 2002
-// Copyright (C) 2004 Novell (http://www.novell.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // Great Power without form."
 // -- The Verrah Rubicon of Verena, Book One
 
-using System;
 using System.Globalization;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 using System.Text;
 
 namespace System.Security.Cryptography {
        
-#if NET_1_0
-       public class RNGCryptoServiceProvider : RandomNumberGenerator {
-#else
-       public sealed class RNGCryptoServiceProvider : RandomNumberGenerator {
+#if !NET_2_1
+       [ComVisible (true)]
 #endif
+       public sealed class RNGCryptoServiceProvider : RandomNumberGenerator {
+               private static object _lock;
                private IntPtr _handle;
 
+               static RNGCryptoServiceProvider ()
+               {
+                       if (RngOpen ())
+                               _lock = new object ();
+               }
+
                public RNGCryptoServiceProvider ()
                {
                        _handle = RngInitialize (null);
                        Check ();
                }
-               
+#if !NET_2_1
                public RNGCryptoServiceProvider (byte[] rgb)
                {
                        _handle = RngInitialize (rgb);
@@ -79,7 +81,7 @@ namespace System.Security.Cryptography {
                                _handle = RngInitialize (Encoding.UTF8.GetBytes (str));
                        Check ();
                }
-
+#endif
                private void Check () 
                {
                        if (_handle == IntPtr.Zero) {
@@ -87,6 +89,9 @@ namespace System.Security.Cryptography {
                                        Locale.GetText ("Couldn't access random source."));
                        }
                }
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static extern bool RngOpen ();
                
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern IntPtr RngInitialize (byte[] seed);
@@ -102,7 +107,14 @@ namespace System.Security.Cryptography {
                        if (data == null)
                                throw new ArgumentNullException ("data");
 
-                       _handle = RngGetBytes (_handle, data);
+                       if (_lock == null) {
+                               _handle = RngGetBytes (_handle, data);
+                       } else {
+                               // using a global handle for randomness
+                               lock (_lock) {
+                                       _handle = RngGetBytes (_handle, data);
+                               }
+                       }
                        Check ();
                }
                
@@ -133,5 +145,12 @@ namespace System.Security.Cryptography {
                                _handle = IntPtr.Zero;
                        }
                }
+
+#if NET_4_0 || MOONLIGHT
+               protected override void Dispose (bool disposing)
+               {
+                       base.Dispose (disposing);
+               }
+#endif
        }
 }