Index: branches/eraser6/Manager/PRNG.cs
===================================================================
--- branches/eraser6/Manager/PRNG.cs	(revision 479)
+++ branches/eraser6/Manager/PRNG.cs	(revision 502)
@@ -221,8 +221,293 @@
 
 	/// <summary>
+	/// Provides an abstract interface to allow multiple sources of entropy into
+	/// the EntropyPoller class.
+	/// </summary>
+	public abstract class EntropySource
+	{
+		/// <summary>
+		/// Constructor.
+		/// </summary>
+		public EntropySource()
+		{
+		}
+
+		/// <summary>
+		/// Gets a primer to add to the pool when this source is first initialised, to
+		/// further add entropy to the pool.
+		/// </summary>
+		/// <returns>A byte array containing the entropy.</returns>
+		public abstract byte[] GetPrimer();
+		
+		/// <summary>
+		/// Retrieve entropy from a source which will have slow rate of
+		/// entropy polling.
+		/// </summary>
+		/// <returns></returns>
+		public abstract byte[] GetSlowEntropy();
+
+		/// <summary>
+		/// Retrieve entropy from a soruce which will have a fast rate of 
+		/// entropy polling.
+		/// </summary>
+		/// <returns></returns>
+		public abstract byte[] GetFastEntropy();
+
+		/// <summary>
+		/// Gets entropy from the entropy source. This will be called repetitively.
+		/// </summary>
+		/// <returns>A byte array containing the entropy, both slow rate and fast rate.</returns>
+		public abstract byte[] GetEntropy();
+				
+		/// <summary>
+		/// Converts value types into a byte array. This is a helper function to allow
+		/// inherited classes to convert value types into byte arrays which can be
+		/// returned to the EntropyPoller class.
+		/// </summary>
+		/// <typeparam name="T">Any value type</typeparam>
+		/// <param name="entropy">A value which will be XORed with pool contents.</param>
+		protected unsafe static byte[] StructToBuffer<T>(T entropy) where T : struct
+		{
+			int sizeofObject = Marshal.SizeOf(entropy);
+			IntPtr memory = Marshal.AllocHGlobal(sizeofObject);
+			try
+			{
+				Marshal.StructureToPtr(entropy, memory, false);
+				byte[] dest = new byte[sizeofObject];
+
+				//Copy the memory
+				Marshal.Copy(memory, dest, 0, sizeofObject);
+				return dest;
+			}
+			finally
+			{
+				Marshal.FreeHGlobal(memory);
+			}
+		}
+	}
+
+	/// <summary>
+	/// Provides means of generating random entropy from the system or user space
+	/// randomness.
+	/// </summary>
+	public class KernelEntropySource : EntropySource
+	{
+		public override byte[] GetPrimer()
+		{
+			List<byte> result = new List<byte>();
+
+			//Process startup information
+			KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO();
+			KernelAPI.GetStartupInfo(out startupInfo);
+			result.AddRange(StructToBuffer(startupInfo));
+
+			//System information
+			KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO();
+			KernelAPI.GetSystemInfo(out systemInfo);
+			result.AddRange(StructToBuffer(systemInfo));
+
+			result.AddRange(GetFastEntropy());
+			result.AddRange(GetSlowEntropy());
+			return result.ToArray();
+		}
+
+		public override byte[] GetEntropy()
+		{
+			List<byte> result = new List<byte>();
+			result.AddRange(GetFastEntropy());
+			result.AddRange(GetSlowEntropy());
+
+			return result.ToArray();
+		}
+
+		/// <summary>
+		/// Retrieves entropy from quick sources.
+		/// </summary>
+		public override byte[] GetFastEntropy()
+		{
+			List<byte> result = new List<byte>();
+
+			//Add the free disk space to the pool
+			result.AddRange(StructToBuffer(new DriveInfo(new DirectoryInfo(Environment.SystemDirectory).
+				Root.FullName).TotalFreeSpace));
+
+			//Miscellaneous window handles
+			result.AddRange(StructToBuffer(UserAPI.GetCapture()));
+			result.AddRange(StructToBuffer(UserAPI.GetClipboardOwner()));
+			result.AddRange(StructToBuffer(UserAPI.GetClipboardViewer()));
+			result.AddRange(StructToBuffer(UserAPI.GetDesktopWindow()));
+			result.AddRange(StructToBuffer(UserAPI.GetForegroundWindow()));
+			result.AddRange(StructToBuffer(UserAPI.GetMessagePos()));
+			result.AddRange(StructToBuffer(UserAPI.GetMessageTime()));
+			result.AddRange(StructToBuffer(UserAPI.GetOpenClipboardWindow()));
+			result.AddRange(StructToBuffer(UserAPI.GetProcessWindowStation()));
+			result.AddRange(StructToBuffer(KernelAPI.GetCurrentProcessId()));
+			result.AddRange(StructToBuffer(KernelAPI.GetCurrentThreadId()));
+			result.AddRange(StructToBuffer(KernelAPI.GetProcessHeap()));
+
+			//The caret and cursor positions
+			UserAPI.POINT point;
+			UserAPI.GetCaretPos(out point);
+			result.AddRange(StructToBuffer(point));
+			UserAPI.GetCursorPos(out point);
+			result.AddRange(StructToBuffer(point));
+
+			//Amount of free memory
+			KernelAPI.MEMORYSTATUSEX memoryStatus = new KernelAPI.MEMORYSTATUSEX();
+			memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus);
+			if (KernelAPI.GlobalMemoryStatusEx(ref memoryStatus))
+			{
+				result.AddRange(StructToBuffer(memoryStatus.ullAvailPhys));
+				result.AddRange(StructToBuffer(memoryStatus.ullAvailVirtual));
+				result.AddRange(StructToBuffer(memoryStatus));
+			}
+
+			//Thread execution times
+			long creationTime, exitTime, kernelTime, userTime;
+			if (KernelAPI.GetThreadTimes(KernelAPI.GetCurrentThread(), out creationTime,
+				out exitTime, out kernelTime, out userTime))
+			{
+				result.AddRange(StructToBuffer(creationTime));
+				result.AddRange(StructToBuffer(kernelTime));
+				result.AddRange(StructToBuffer(userTime));
+			}
+
+			//Process execution times
+			if (KernelAPI.GetProcessTimes(KernelAPI.GetCurrentProcess(), out creationTime,
+				out exitTime, out kernelTime, out userTime))
+			{
+				result.AddRange(StructToBuffer(creationTime));
+				result.AddRange(StructToBuffer(kernelTime));
+				result.AddRange(StructToBuffer(userTime));
+			}
+
+			//Current system time
+			result.AddRange(StructToBuffer(DateTime.Now.Ticks));
+
+			//The high resolution performance counter
+			long perfCount = 0;
+			if (KernelAPI.QueryPerformanceCounter(out perfCount))
+				result.AddRange(StructToBuffer(perfCount));
+
+			//Ticks since start up
+			uint tickCount = KernelAPI.GetTickCount();
+			if (tickCount != 0)
+				result.AddRange(StructToBuffer(tickCount));
+
+			//CryptGenRandom
+			byte[] cryptGenRandom = new byte[160];
+			if (CryptAPI.CryptGenRandom(cryptGenRandom))
+				result.AddRange(cryptGenRandom);
+
+			return result.ToArray();
+		}
+
+		/// <summary>
+		/// Retrieves entropy from sources which are relatively slower than those from
+		/// the FastAddEntropy function.
+		/// </summary>
+		public override byte[] GetSlowEntropy()
+		{
+			List<byte> result = new List<byte>();
+
+			//NetAPI statistics
+			unsafe
+			{
+				IntPtr netAPIStats = IntPtr.Zero;
+				if (NetAPI.NetStatisticsGet(null, NetAPI.SERVICE_WORKSTATION,
+					0, 0, out netAPIStats) == 0)
+				{
+					try
+					{
+						//Get the size of the buffer
+						uint size = 0;
+						NetAPI.NetApiBufferSize(netAPIStats, out size);
+						byte[] entropy = new byte[size];
+
+						//Copy the buffer
+						Marshal.Copy(entropy, 0, netAPIStats, entropy.Length);
+
+						//And add it to the pool
+						result.AddRange(entropy);
+					}
+					finally
+					{
+						//Free the statistics buffer
+						NetAPI.NetApiBufferFree(netAPIStats);
+					}
+				}
+			}
+
+#if false
+			//Get disk I/O statistics for all the hard drives
+			for (int drive = 0; ; ++drive)
+			{
+				//Try to open the drive.
+				using (SafeFileHandle hDevice = File.CreateFile(
+					string.Format("\\\\.\\PhysicalDrive%d", drive), 0,
+					File.FILE_SHARE_READ | File.FILE_SHARE_WRITE, IntPtr.Zero,
+					File.OPEN_EXISTING, 0, IntPtr.Zero))
+				{
+					if (hDevice.IsInvalid)
+						break;
+
+					//This only works if the user has turned on the disk performance
+					//counters with 'diskperf -y'. These counters are off by default
+					if (File.DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
+						&diskPerformance, sizeof(DISK_PERFORMANCE), &uSize, NULL))
+					{
+						addEntropy(&diskPerformance, uSize);
+					}
+				}
+			}
+#endif
+
+			/*
+			 Query performance data. Because the Win32 version of this API (through
+			 registry) may be buggy, use the NT Native API instead.
+			 
+			 Scan the first 64 possible information types (we don't bother
+			 with increasing the buffer size as we do with the Win32
+			 version of the performance data read, we may miss a few classes
+			 but it's no big deal).  In addition the returned size value for
+			 some classes is wrong (eg 23 and 24 return a size of 0) so we
+			 miss a few more things, but again it's no big deal.  This scan
+			 typically yields around 20 pieces of data, there's nothing in
+			 the range 65...128 so chances are there won't be anything above
+			 there either.
+			*/
+			uint dataWritten = 0;
+			byte[] infoBuffer = new byte[65536];
+			uint totalEntropy = 0;
+			for (uint infoType = 0; infoType < 64; ++infoType)
+			{
+				uint sysInfo = NTAPI.NtQuerySystemInformation(infoType, infoBuffer,
+					(uint)infoBuffer.Length, out dataWritten);
+
+				if (sysInfo == 0 /*ERROR_SUCCESS*/ && dataWritten > 0)
+				{
+					byte[] entropy = new byte[dataWritten];
+					Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten);
+					result.AddRange(entropy);
+					totalEntropy += dataWritten;
+				}
+			}
+
+			result.AddRange(StructToBuffer(totalEntropy));
+
+			//Finally, our good friend CryptGenRandom()
+			byte[] cryptGenRandom = new byte[1536];
+			if (CryptAPI.CryptGenRandom(cryptGenRandom))
+				result.AddRange(cryptGenRandom);
+
+			return result.ToArray();
+		}
+	}
+
+	/// <summary>
 	/// A class which uses EntropyPoll class to fetch system data as a source of
 	/// randomness at "regular" but "random" intervals
 	/// </summary>
-	class EntropyPoller
+	public class EntropyPoller : KernelEntropySource
 	{
 		/// <summary>
@@ -278,9 +563,10 @@
 					}
 				
-				st.Stop(); 
+				st.Stop();
+				// 2049 = bin '100000000001', great avalanche
 				Thread.Sleep(2000 + (int)(st.ElapsedTicks % 2049L));
 				st.Reset();
 
-				//Send entropy to the PRNGs for new seeds.
+				// Send entropy to the PRNGs for new seeds.
 				if (DateTime.Now - lastAddedEntropy > managerEntropySpan)
 					ManagerLibrary.Instance.PRNGManager.AddEntropy(GetPool());
@@ -510,274 +796,3 @@
 		private List<EntropySource> EntropySources = new List<EntropySource>();
 	}
-	
-	/// <summary>
-	/// Provides an abstract interface to allow multiple sources of entropy into
-	/// the EntropyPoller class.
-	/// </summary>
-	public abstract class EntropySource
-	{
-		/// <summary>
-		/// Constructor.
-		/// </summary>
-		public EntropySource()
-		{
-		}
-
-		/// <summary>
-		/// Gets a primer to add to the pool when this source is first initialised, to
-		/// further add entropy to the pool.
-		/// </summary>
-		/// <returns>A byte array containing the entropy.</returns>
-		public abstract byte[] GetPrimer();
-
-		/// <summary>
-		/// Gets entropy from the entropy source. This will be called repetitively.
-		/// </summary>
-		/// <returns>A byte array containing the entropy.</returns>
-		public abstract byte[] GetEntropy();
-
-		/// <summary>
-		/// Converts value types into a byte array. This is a helper function to allow
-		/// inherited classes to convert value types into byte arrays which can be
-		/// returned to the EntropyPoller class.
-		/// </summary>
-		/// <typeparam name="T">Any value type</typeparam>
-		/// <param name="entropy">A value which will be XORed with pool contents.</param>
-		protected unsafe static byte[] StructToBuffer<T>(T entropy) where T: struct
-		{
-			int sizeofObject = Marshal.SizeOf(entropy);
-			IntPtr memory = Marshal.AllocHGlobal(sizeofObject);
-			try
-			{
-				Marshal.StructureToPtr(entropy, memory, false);
-				byte[] dest = new byte[sizeofObject];
-
-				//Copy the memory
-				Marshal.Copy(memory, dest, 0, sizeofObject);
-				return dest;
-			}
-			finally
-			{
-				Marshal.FreeHGlobal(memory);
-			}
-		}
-	}
-
-	/// <summary>
-	/// Provides means of generating random entropy from the system or user space
-	/// randomness.
-	/// </summary>
-	internal class KernelEntropySource : EntropySource
-	{
-		public override byte[] GetPrimer()
-		{
-			List<byte> result = new List<byte>();
-
-			//Process startup information
-			KernelAPI.STARTUPINFO startupInfo = new KernelAPI.STARTUPINFO();
-			KernelAPI.GetStartupInfo(out startupInfo);
-			result.AddRange(StructToBuffer(startupInfo));
-
-			//System information
-			KernelAPI.SYSTEM_INFO systemInfo = new KernelAPI.SYSTEM_INFO();
-			KernelAPI.GetSystemInfo(out systemInfo);
-			result.AddRange(StructToBuffer(systemInfo));
-
-			result.AddRange(GetFastEntropy());
-			result.AddRange(GetSlowEntropy());
-			return result.ToArray();
-		}
-
-		public override byte[] GetEntropy()
-		{
-			List<byte> result = new List<byte>();
-			result.AddRange(GetFastEntropy());
-			result.AddRange(GetSlowEntropy());
-			
-			return result.ToArray();
-		}
-
-		/// <summary>
-		/// Retrieves entropy from quick sources.
-		/// </summary>
-		private byte[] GetFastEntropy()
-		{
-			List<byte> result = new List<byte>();
-
-			//Add the free disk space to the pool
-			result.AddRange(StructToBuffer(new DriveInfo(new DirectoryInfo(Environment.SystemDirectory).
-				Root.FullName).TotalFreeSpace));
-
-			//Miscellaneous window handles
-			result.AddRange(StructToBuffer(UserAPI.GetCapture()));
-			result.AddRange(StructToBuffer(UserAPI.GetClipboardOwner()));
-			result.AddRange(StructToBuffer(UserAPI.GetClipboardViewer()));
-			result.AddRange(StructToBuffer(UserAPI.GetDesktopWindow()));
-			result.AddRange(StructToBuffer(UserAPI.GetForegroundWindow()));
-			result.AddRange(StructToBuffer(UserAPI.GetMessagePos()));
-			result.AddRange(StructToBuffer(UserAPI.GetMessageTime()));
-			result.AddRange(StructToBuffer(UserAPI.GetOpenClipboardWindow()));
-			result.AddRange(StructToBuffer(UserAPI.GetProcessWindowStation()));
-			result.AddRange(StructToBuffer(KernelAPI.GetCurrentProcessId()));
-			result.AddRange(StructToBuffer(KernelAPI.GetCurrentThreadId()));
-			result.AddRange(StructToBuffer(KernelAPI.GetProcessHeap()));
-
-			//The caret and cursor positions
-			UserAPI.POINT point;
-			UserAPI.GetCaretPos(out point);
-			result.AddRange(StructToBuffer(point));
-			UserAPI.GetCursorPos(out point);
-			result.AddRange(StructToBuffer(point));
-
-			//Amount of free memory
-			KernelAPI.MEMORYSTATUSEX memoryStatus = new KernelAPI.MEMORYSTATUSEX();
-			memoryStatus.dwLength = (uint)Marshal.SizeOf(memoryStatus);
-			if (KernelAPI.GlobalMemoryStatusEx(ref memoryStatus))
-			{
-				result.AddRange(StructToBuffer(memoryStatus.ullAvailPhys));
-				result.AddRange(StructToBuffer(memoryStatus.ullAvailVirtual));
-				result.AddRange(StructToBuffer(memoryStatus));
-			}
-
-			//Thread execution times
-			long creationTime, exitTime, kernelTime, userTime;
-			if (KernelAPI.GetThreadTimes(KernelAPI.GetCurrentThread(), out creationTime,
-				out exitTime, out kernelTime, out userTime))
-			{
-				result.AddRange(StructToBuffer(creationTime));
-				result.AddRange(StructToBuffer(kernelTime));
-				result.AddRange(StructToBuffer(userTime));
-			}
-
-			//Process execution times
-			if (KernelAPI.GetProcessTimes(KernelAPI.GetCurrentProcess(), out creationTime,
-				out exitTime, out kernelTime, out userTime))
-			{
-				result.AddRange(StructToBuffer(creationTime));
-				result.AddRange(StructToBuffer(kernelTime));
-				result.AddRange(StructToBuffer(userTime));
-			}
-
-			//Current system time
-			result.AddRange(StructToBuffer(DateTime.Now.Ticks));
-
-			//The high resolution performance counter
-			long perfCount = 0;
-			if (KernelAPI.QueryPerformanceCounter(out perfCount))
-				result.AddRange(StructToBuffer(perfCount));
-
-			//Ticks since start up
-			uint tickCount = KernelAPI.GetTickCount();
-			if (tickCount != 0)
-				result.AddRange(StructToBuffer(tickCount));
-
-			//CryptGenRandom
-			byte[] cryptGenRandom = new byte[160];
-			if (CryptAPI.CryptGenRandom(cryptGenRandom))
-				result.AddRange(cryptGenRandom);
-
-			return result.ToArray();
-		}
-
-		/// <summary>
-		/// Retrieves entropy from sources which are relatively slower than those from
-		/// the FastAddEntropy function.
-		/// </summary>
-		private byte[] GetSlowEntropy()
-		{
-			List<byte> result = new List<byte>();
-
-			//NetAPI statistics
-			unsafe
-			{
-				IntPtr netAPIStats = IntPtr.Zero;
-				if (NetAPI.NetStatisticsGet(null, NetAPI.SERVICE_WORKSTATION,
-					0, 0, out netAPIStats) == 0)
-				{
-					try
-					{
-						//Get the size of the buffer
-						uint size = 0;
-						NetAPI.NetApiBufferSize(netAPIStats, out size);
-						byte[] entropy = new byte[size];
-
-						//Copy the buffer
-						Marshal.Copy(entropy, 0, netAPIStats, entropy.Length);
-
-						//And add it to the pool
-						result.AddRange(entropy);
-					}
-					finally
-					{
-						//Free the statistics buffer
-						NetAPI.NetApiBufferFree(netAPIStats);
-					}
-				}
-			}
-
-#if false
-			//Get disk I/O statistics for all the hard drives
-			for (int drive = 0; ; ++drive)
-			{
-				//Try to open the drive.
-				using (SafeFileHandle hDevice = File.CreateFile(
-					string.Format("\\\\.\\PhysicalDrive%d", drive), 0,
-					File.FILE_SHARE_READ | File.FILE_SHARE_WRITE, IntPtr.Zero,
-					File.OPEN_EXISTING, 0, IntPtr.Zero))
-				{
-					if (hDevice.IsInvalid)
-						break;
-
-					//This only works if the user has turned on the disk performance
-					//counters with 'diskperf -y'. These counters are off by default
-					if (File.DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
-						&diskPerformance, sizeof(DISK_PERFORMANCE), &uSize, NULL))
-					{
-						addEntropy(&diskPerformance, uSize);
-					}
-				}
-			}
-#endif
-
-			/*
-			 Query performance data. Because the Win32 version of this API (through
-			 registry) may be buggy, use the NT Native API instead.
-			 
-			 Scan the first 64 possible information types (we don't bother
-			 with increasing the buffer size as we do with the Win32
-			 version of the performance data read, we may miss a few classes
-			 but it's no big deal).  In addition the returned size value for
-			 some classes is wrong (eg 23 and 24 return a size of 0) so we
-			 miss a few more things, but again it's no big deal.  This scan
-			 typically yields around 20 pieces of data, there's nothing in
-			 the range 65...128 so chances are there won't be anything above
-			 there either.
-			*/
-			uint dataWritten = 0;
-			byte[] infoBuffer = new byte[65536];
-			uint totalEntropy = 0;
-			for (uint infoType = 0; infoType < 64; ++infoType)
-			{
-				uint sysInfo = NTAPI.NtQuerySystemInformation(infoType, infoBuffer,
-					(uint)infoBuffer.Length, out dataWritten);
-
-				if (sysInfo == 0 /*ERROR_SUCCESS*/ && dataWritten > 0)
-				{
-					byte[] entropy = new byte[dataWritten];
-					Buffer.BlockCopy(infoBuffer, 0, entropy, 0, (int)dataWritten);
-					result.AddRange(entropy);
-					totalEntropy += dataWritten;
-				}
-			}
-
-			result.AddRange(StructToBuffer(totalEntropy));
-
-			//Finally, our good friend CryptGenRandom()
-			byte[] cryptGenRandom = new byte[1536];
-			if (CryptAPI.CryptGenRandom(cryptGenRandom))
-				result.AddRange(cryptGenRandom);
-
-			return result.ToArray();
-		}
-	}
 }
