// Note: in order to be consistent with other messagings (e.g. TcpMessaging) value 0 for timeouts mean infinite time. public SharedMemoryReceiver(string memoryMappedFileName, bool useExistingMemoryMappedFile, TimeSpan openTimeout, int maxMessageSize, MemoryMappedFileSecurity memmoryMappedFileSecurity) { using (EneterTrace.Entering()) { myOpenTimeout = (openTimeout == TimeSpan.Zero) ? TimeSpan.FromMilliseconds(-1) : openTimeout; myMemoryMappedFileName = memoryMappedFileName; myMaxMessageSize = maxMessageSize; // If true then the listener will not create the new memory shared file but will open existing one. // This is useful for security restrictions if the functionality is used in the windows service. myUseExistingMemoryMappedFile = useExistingMemoryMappedFile; myMemmoryMappedFileSecurity = memmoryMappedFileSecurity; // If the security shall be applied. if (myMemmoryMappedFileSecurity != null) { // Create the security for the WaitHandle sync logic. myEventWaitHandleSecurity = new EventWaitHandleSecurity(); myEventWaitHandleSecurity.SetSecurityDescriptorSddlForm("S:(ML;;NW;;;LW)"); SecurityIdentifier aSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); EventWaitHandleAccessRule anAccessRule = new EventWaitHandleAccessRule(aSid, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize, AccessControlType.Allow); myEventWaitHandleSecurity.AddAccessRule(anAccessRule); } } }
/// <summary> /// Create global events necessary for handshaking with the parent /// </summary> /// <param name="nodeNumber"></param> /// <returns>True if events created successfully and false otherwise</returns> private static bool CreateGlobalEvents(int nodeNumber) { bool createdNew; if (NativeMethods.IsUserAdministrator()) { EventWaitHandleSecurity mSec = new EventWaitHandleSecurity(); // Add a rule that grants the access only to admins and systems mSec.SetSecurityDescriptorSddlForm(NativeMethods.ADMINONLYSDDL); // Create an initiation event to allow the parent side to prove to the child that we have the same level of privilege as it does. // this is done by having the parent set this event which means it needs to have administrative permissions to do so. globalInitiateActivationEvent = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeInitiateActivationEventName(nodeNumber), out createdNew, mSec); } else { // Create an initiation event to allow the parent side to prove to the child that we have the same level of privilege as it does. // this is done by having the parent set this event which means it has atleast the same permissions as the child process globalInitiateActivationEvent = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeInitiateActivationEventName(nodeNumber), out createdNew); } // This process must be the creator of the event to prevent squating by a lower privilaged attacker if (!createdNew) { return(false); } // Informs the parent process that the child process has been created. globalNodeActive = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeActiveEventName(nodeNumber)); globalNodeActive.Set(); // Indicate to the parent process, this node is currently is ready to start to recieve requests globalNodeInUse = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeInUseEventName(nodeNumber)); // Used by the parent process to inform the child process to shutdown due to the child process // not recieving the initialization command. globalNodeErrorShutdown = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeErrorShutdownEventName(nodeNumber)); // Inform the parent process the node has started its communication threads. globalNodeActivate = new EventWaitHandle(false, EventResetMode.ManualReset, LocalNodeProviderGlobalNames.NodeActivedEventName(nodeNumber)); return(true); }
// Note: in order to be consistent with other messagings (e.g. TcpMessaging) value 0 for timeouts mean infinite time. public SharedMemorySender(string memoryMappedFileName, bool useExistingMemoryMappedFile, TimeSpan openTimeout, TimeSpan sendTimeout, int maxMessageSize, MemoryMappedFileSecurity memoryMappedFileSecurity) { using (EneterTrace.Entering()) { try { mySendTimeout = (sendTimeout == TimeSpan.Zero) ? TimeSpan.FromMilliseconds(-1) : sendTimeout; myUseExistingMemoryMappedFile = useExistingMemoryMappedFile; myMaxMessageSize = maxMessageSize; // If the shared memory file is created by SharedMemoryReceiver then open existing one. if (useExistingMemoryMappedFile) { TimeSpan anOpenTimeout = (openTimeout == TimeSpan.Zero) ? TimeSpan.FromMilliseconds(-1) : openTimeout; // Try to open synchronization handlers. mySharedMemoryReady = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_SharedMemoryReady", anOpenTimeout); mySharedMemoryFilled = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_SharedMemoryFilled", anOpenTimeout); mySharedMemoryCreated = EventWaitHandleExt.OpenExisting(memoryMappedFileName + "_ResponseSharedMemoryCreated", anOpenTimeout); // Wait until the memory mapped file exist and then open it. // Note: it shall be created by SharedMemoryReceiver. if (!mySharedMemoryCreated.WaitOne(anOpenTimeout)) { throw new InvalidOperationException(TracedObject + "failed to open memory mapped file because it does not exist."); } myMemoryMappedFile = MemoryMappedFile.OpenExisting(memoryMappedFileName); } // If the shared memory file shall be created by SharedMemorySender. else { EventWaitHandleSecurity anEventWaitHandleSecurity = null; if (memoryMappedFileSecurity != null) { // Create the security for the WaitHandle logic. anEventWaitHandleSecurity = new EventWaitHandleSecurity(); anEventWaitHandleSecurity.SetSecurityDescriptorSddlForm("S:(ML;;NW;;;LW)"); SecurityIdentifier aSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); EventWaitHandleAccessRule anAccessRule = new EventWaitHandleAccessRule(aSid, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize, AccessControlType.Allow); anEventWaitHandleSecurity.AddAccessRule(anAccessRule); } // Create synchronization handlers. bool aDummy; mySharedMemoryReady = new EventWaitHandle(false, EventResetMode.AutoReset, memoryMappedFileName + "_SharedMemoryReady", out aDummy, anEventWaitHandleSecurity); mySharedMemoryFilled = new EventWaitHandle(false, EventResetMode.AutoReset, memoryMappedFileName + "_SharedMemoryFilled", out aDummy, anEventWaitHandleSecurity); mySharedMemoryCreated = new EventWaitHandle(false, EventResetMode.ManualReset, memoryMappedFileName + "_ResponseSharedMemoryCreated", out aDummy, anEventWaitHandleSecurity); // Create the memory mapped file. myMemoryMappedFile = MemoryMappedFile.CreateNew(memoryMappedFileName, maxMessageSize, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, memoryMappedFileSecurity, HandleInheritability.None); // Indicate the shared memory is created. mySharedMemoryCreated.Set(); } myMemoryMappedFileStream = myMemoryMappedFile.CreateViewStream(); } catch (Exception err) { EneterTrace.Error(TracedObject + "failed to create SharedMemorySender.", err); // Dispose resources alocated so far. Dispose(); throw; } } }