diff --git a/SharedMemory/BufferWithLocks.cs b/SharedMemory/BufferWithLocks.cs
index 89f257a..62e41dd 100644
--- a/SharedMemory/BufferWithLocks.cs
+++ b/SharedMemory/BufferWithLocks.cs
@@ -28,7 +28,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
+#if NETFULL
+using System.Security.AccessControl;
using System.Security.Permissions;
+using System.Security.Principal;
+#endif
using System.Text;
using System.Threading;
@@ -59,6 +63,18 @@ public abstract class BufferWithLocks : SharedBuffer
///
protected EventWaitHandle ReadWaitEvent { get; private set; }
+#if NETFULL
+ private static EventWaitHandleSecurity CreateDefaultWaitHandleSecurity()
+ {
+ EventWaitHandleSecurity eventWaitHandleSecurity = new EventWaitHandleSecurity();
+ eventWaitHandleSecurity.AddAccessRule(new EventWaitHandleAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
+ EventWaitHandleRights.FullControl, AccessControlType.Allow));
+ return eventWaitHandleSecurity;
+ }
+
+ private static readonly EventWaitHandleSecurity waitHandleSecurity = CreateDefaultWaitHandleSecurity();
+#endif
+
#region Constructors
///
@@ -70,8 +86,48 @@ public abstract class BufferWithLocks : SharedBuffer
protected BufferWithLocks(string name, long bufferSize, bool ownsSharedMemory)
: base(name, bufferSize, ownsSharedMemory)
{
- WriteWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_write");
- ReadWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_read");
+#if NET45
+ EventWaitHandle writeWaitEvent;
+ if (EventWaitHandle.TryOpenExisting(Name + "_evt_write", out writeWaitEvent))
+ {
+ WriteWaitEvent = writeWaitEvent;
+ }
+ else
+ {
+ WriteWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_write", out _, waitHandleSecurity);
+ }
+ EventWaitHandle readWaitEvent;
+ if (EventWaitHandle.TryOpenExisting(Name + "_evt_read", out readWaitEvent))
+ {
+ ReadWaitEvent = readWaitEvent;
+ }
+ else
+ {
+ ReadWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_read", out _, waitHandleSecurity);
+ }
+#elif NET40 || NET35
+ WriteWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_write", out _, waitHandleSecurity);
+ ReadWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_read", out _, waitHandleSecurity);
+#elif NETCORE
+ EventWaitHandle writeWaitEvent;
+ if (EventWaitHandle.TryOpenExisting(Name + "_evt_write", out writeWaitEvent))
+ {
+ WriteWaitEvent = writeWaitEvent;
+ }
+ else
+ {
+ WriteWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_write");
+ }
+ EventWaitHandle readWaitEvent;
+ if (EventWaitHandle.TryOpenExisting(Name + "_evt_read", out readWaitEvent))
+ {
+ ReadWaitEvent = readWaitEvent;
+ }
+ else
+ {
+ ReadWaitEvent = new EventWaitHandle(true, EventResetMode.ManualReset, Name + "_evt_read");
+ }
+#endif
}
#endregion
diff --git a/SharedMemory/CircularBuffer.cs b/SharedMemory/CircularBuffer.cs
index bab2f9d..95cf92b 100644
--- a/SharedMemory/CircularBuffer.cs
+++ b/SharedMemory/CircularBuffer.cs
@@ -45,17 +45,17 @@ namespace SharedMemory
public unsafe class CircularBuffer : SharedBuffer
{
#region Public/Protected properties
-
+
///
/// The number of nodes within the circular linked-list
///
public int NodeCount { get; private set; }
-
+
///
/// The buffer size of each node
///
public int NodeBufferSize { get; private set; }
-
+
///
/// Event signaled when data has been written if the reading index has caught up to the writing index
///
@@ -76,7 +76,7 @@ protected virtual long NodeHeaderOffset
return 0;
}
}
-
+
///
/// Where the linked-list nodes are located within the buffer
///
@@ -120,7 +120,7 @@ protected virtual Node* this[int i]
#region Private field members
private NodeHeader* _nodeHeader = null;
-
+
#endregion
#region Structures
@@ -192,7 +192,7 @@ public struct Node
/// Represents the offset relative to where the data for this node can be found.
///
public long Offset;
-
+
///
/// Represents the index of the current node.
///
@@ -214,6 +214,9 @@ public struct Node
/// The name of the shared memory to be created
/// The number of nodes within the circular linked-list (minimum of 2)
/// The buffer size per node in bytes. The total shared memory size will be Marshal.SizeOf(SharedMemory.SharedHeader) + Marshal.SizeOf(CircularBuffer.NodeHeader) + (Marshal.SizeOf(CircularBuffer.Node) * nodeCount) + (bufferSize * nodeCount)
+#if !(NET35)
+ /// Indicates whether to allow opening an existing if already exists.
+#endif
///
/// The maximum total shared memory size is dependent upon the system and current memory fragmentation.
/// The shared memory layout on 32-bit and 64-bit architectures is:
@@ -225,10 +228,22 @@ public struct Node
///
///
///
- public CircularBuffer(string name, int nodeCount, int nodeBufferSize)
- : this(name, nodeCount, nodeBufferSize, true)
+ public CircularBuffer(string name, int nodeCount, int nodeBufferSize
+#if !(NET35)
+ , bool openExisting = false
+#endif
+ )
+ : this(name, nodeCount, nodeBufferSize, true
+#if !(NET35)
+ , openExisting
+#endif
+ )
{
- Open();
+ Open(
+#if !(NET35)
+ openExisting
+#endif
+ );
}
///
@@ -236,12 +251,20 @@ public CircularBuffer(string name, int nodeCount, int nodeBufferSize)
///
/// The name of an existing previously created with =true
public CircularBuffer(string name)
- : this(name, 0, 0, false)
+ : this(name, 0, 0, false
+#if !(NET35)
+ , false
+#endif
+ )
{
Open();
}
- private CircularBuffer(string name, int nodeCount, int nodeBufferSize, bool ownsSharedMemory)
+ private CircularBuffer(string name, int nodeCount, int nodeBufferSize, bool ownsSharedMemory
+#if !(NET35)
+ , bool openExisting = false
+#endif
+ )
: base(name, Marshal.SizeOf(typeof(NodeHeader)) + (Marshal.SizeOf(typeof(Node)) * nodeCount) + (nodeCount * (long)nodeBufferSize), ownsSharedMemory)
{
#region Argument validation
@@ -451,10 +474,10 @@ public virtual int Write(byte[] source, int startIndex = 0, int timeout = 1000)
// Copy the data
int amount = Math.Min(source.Length - startIndex, NodeBufferSize);
-
+
Marshal.Copy(source, startIndex, new IntPtr(BufferStartPtr + node->Offset), amount);
node->AmountWritten = amount;
-
+
// Writing is complete, make readable
PostNode(node);
@@ -645,9 +668,9 @@ protected virtual void ReturnNode(Node* node)
Interlocked.CompareExchange(ref _nodeHeader->ReadEnd, node->Next, blockIndex);
#pragma warning restore 0420
- // If a writer thread is waiting on "node available" signal the event
+ // If a writer thread is waiting on "node available" signal the event
if (node->Prev == _nodeHeader->WriteStart)
- NodeAvailable.Set();
+ NodeAvailable.Set();
}
}
@@ -710,7 +733,7 @@ public virtual int Read(T[] destination, int startIndex = 0, int timeout = 10
/// The number of bytes read
/// If the size of is larger than .
public virtual int Read(out T destination, int timeout = 1000)
- where T: struct
+ where T : struct
{
int structSize = Marshal.SizeOf(typeof(T));
if (structSize > NodeBufferSize)
diff --git a/SharedMemory/SharedArray.cs b/SharedMemory/SharedArray.cs
index a2c1981..d3f16db 100644
--- a/SharedMemory/SharedArray.cs
+++ b/SharedMemory/SharedArray.cs
@@ -76,13 +76,24 @@ public T this[int index]
///
/// The name of the shared memory array to be created.
/// The number of elements to make room for within the shared memory array.
- public SharedArray(string name, int length)
+#if !(NET35)
+ /// Indicates whether to allow opening an existing if already exists.
+#endif
+ public SharedArray(string name, int length
+#if !(NET35)
+ , bool openExisting = false
+#endif
+ )
: base(name, Marshal.SizeOf(typeof(T)) * length, true)
{
Length = length;
_elementSize = Marshal.SizeOf(typeof(T));
- Open();
+ Open(
+#if !(NET35)
+ openExisting
+#endif
+ );
}
///
diff --git a/SharedMemory/SharedBuffer.cs b/SharedMemory/SharedBuffer.cs
index fff7b9a..c5011fc 100644
--- a/SharedMemory/SharedBuffer.cs
+++ b/SharedMemory/SharedBuffer.cs
@@ -29,7 +29,12 @@
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Runtime.InteropServices;
+#if NETFULL
+using System.IO;
+using System.Security.AccessControl;
using System.Security.Permissions;
+using System.Security.Principal;
+#endif
using System.Text;
using System.Threading;
@@ -191,6 +196,28 @@ protected SharedBuffer(string name, long bufferSize, bool ownsSharedMemory)
#region Open / Close
+#if NETFULL
+ private static readonly WellKnownSidType[] defaultAllowedList = {
+ WellKnownSidType.CreatorOwnerSid,
+ WellKnownSidType.BuiltinAdministratorsSid,
+ WellKnownSidType.LocalSystemSid,
+ WellKnownSidType.LocalServiceSid,
+ WellKnownSidType.NetworkServiceSid,
+ WellKnownSidType.WorldSid
+ };
+
+ private FileSecurity BuildSecurityDescriptor(IEnumerable allowedList)
+ {
+ FileSecurity fileSecurity = new FileSecurity();
+ foreach (WellKnownSidType allowed in allowedList)
+ {
+ SecurityIdentifier identity = new SecurityIdentifier(allowed, null);
+ fileSecurity.AddAccessRule(new FileSystemAccessRule(identity, FileSystemRights.FullControl, AccessControlType.Allow));
+ }
+ return fileSecurity;
+ }
+#endif
+
///
/// Creates a new or opens an existing shared memory buffer with the name of depending on the value of .
///
@@ -200,7 +227,11 @@ protected SharedBuffer(string name, long bufferSize, bool ownsSharedMemory)
/// If trying to open a new shared memory buffer that does not exist as a consumer of existing buffer.
/// If trying to create a new shared memory buffer with a size larger than the logical addressable space.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
- protected bool Open()
+ protected bool Open(
+#if !(NET35)
+ bool openExisting = false
+#endif
+ )
{
Close();
@@ -210,8 +241,28 @@ protected bool Open()
if (IsOwnerOfSharedMemory)
{
// Create a new shared memory mapping
+#if NETFULL && !(NET35)
+ MemoryMappedFileSecurity memoryMappedFileSecurity = new MemoryMappedFileSecurity();
+ memoryMappedFileSecurity.SetSecurityDescriptorBinaryForm(BuildSecurityDescriptor(defaultAllowedList).GetSecurityDescriptorBinaryForm());
+ if (openExisting) {
+ Mmf = MemoryMappedFile.CreateOrOpen(Name, SharedMemorySize, MemoryMappedFileAccess.ReadWrite,
+ MemoryMappedFileOptions.DelayAllocatePages, memoryMappedFileSecurity, HandleInheritability.Inheritable);
+ } else {
+ Mmf = MemoryMappedFile.CreateNew(Name, SharedMemorySize, MemoryMappedFileAccess.ReadWrite,
+ MemoryMappedFileOptions.DelayAllocatePages, memoryMappedFileSecurity, HandleInheritability.Inheritable);
+ }
+#elif NET35
Mmf = MemoryMappedFile.CreateNew(Name, SharedMemorySize);
-
+#else
+ if (openExisting)
+ {
+ Mmf = MemoryMappedFile.CreateOrOpen(Name, SharedMemorySize);
+ }
+ else
+ {
+ Mmf = MemoryMappedFile.CreateNew(Name, SharedMemorySize);
+ }
+#endif
// Create a view to the entire region of the shared memory
View = Mmf.CreateViewAccessor(0, SharedMemorySize, MemoryMappedFileAccess.ReadWrite);
View.SafeMemoryMappedViewHandle.AcquirePointer(ref ViewPtr);