private unsafe void Initialize(string fileMappingName, int fileMappingSize, int initialOffset) { string mappingName = fileMappingName; SharedUtils.CheckEnvironment(); SafeLocalMemHandle securityDescriptorPointer = null; new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); try { // The sddl string consists of these parts: // D: it's a DACL // (A; this is an allow ACE // OICI; object inherit and container inherit // FRFWGRGW;;; allow file read, file write, generic read and generic write // AU) granted to Authenticated Users // ;S-1-5-33) the same permission granted to AU is also granted to restricted services string sddlString = "D:(A;OICI;FRFWGRGW;;;AU)(A;OICI;FRFWGRGW;;;S-1-5-33)"; if (!SafeLocalMemHandle.ConvertStringSecurityDescriptorToSecurityDescriptor(sddlString, NativeMethods.SDDL_REVISION_1, out securityDescriptorPointer, IntPtr.Zero)) throw new InvalidOperationException(SR.GetString(SR.SetSecurityDescriptorFailed)); NativeMethods.SECURITY_ATTRIBUTES securityAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); securityAttributes.lpSecurityDescriptor = securityDescriptorPointer; securityAttributes.bInheritHandle = false; // // // Here we call CreateFileMapping to create the memory mapped file. When CreateFileMapping fails // with ERROR_ACCESS_DENIED, we know the file mapping has been created and we then open it with OpenFileMapping. // // There is chance of a race condition between CreateFileMapping and OpenFileMapping; The memory mapped file // may actually be closed in between these two calls. When this happens, OpenFileMapping returns ERROR_FILE_NOT_FOUND. // In this case, we need to loop back and retry creating the memory mapped file. // // This loop will timeout in approximately 1.4 minutes. An InvalidOperationException is thrown in the timeout case. // // int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins int waitSleep = 0; bool created = false; while (!created && waitRetries > 0) { fileMappingHandle = NativeMethods.CreateFileMapping((IntPtr)(-1), securityAttributes, NativeMethods.PAGE_READWRITE, 0, fileMappingSize, mappingName); if ((Marshal.GetLastWin32Error() != NativeMethods.ERROR_ACCESS_DENIED) || !fileMappingHandle.IsInvalid) { created = true; } else { // Invalidate the old safehandle before we get rid of it. This prevents it from trying to finalize fileMappingHandle.SetHandleAsInvalid(); fileMappingHandle = NativeMethods.OpenFileMapping(NativeMethods.FILE_MAP_WRITE, false, mappingName); if ((Marshal.GetLastWin32Error() != NativeMethods.ERROR_FILE_NOT_FOUND) || !fileMappingHandle.IsInvalid) { created = true; } else { --waitRetries; if (waitSleep == 0) { waitSleep = 10; } else { System.Threading.Thread.Sleep(waitSleep); waitSleep *= 2; } } } } if (fileMappingHandle.IsInvalid) { throw new InvalidOperationException(SR.GetString(SR.CantCreateFileMapping)); } fileViewAddress = SafeFileMapViewHandle.MapViewOfFile(fileMappingHandle, NativeMethods.FILE_MAP_WRITE, 0,0, UIntPtr.Zero); if (fileViewAddress.IsInvalid) throw new InvalidOperationException(SR.GetString(SR.CantMapFileView)); // figure out what size the share memory really is. NativeMethods.MEMORY_BASIC_INFORMATION meminfo = new NativeMethods.MEMORY_BASIC_INFORMATION(); if (NativeMethods.VirtualQuery(fileViewAddress, ref meminfo, (IntPtr) sizeof(NativeMethods.MEMORY_BASIC_INFORMATION)) == IntPtr.Zero) throw new InvalidOperationException(SR.GetString(SR.CantGetMappingSize)); FileMappingSize = (int) meminfo.RegionSize; } finally { if (securityDescriptorPointer != null) securityDescriptorPointer.Close(); SecurityPermission.RevertAssert(); } SafeNativeMethods.InterlockedCompareExchange(fileViewAddress.DangerousGetHandle(), initialOffset, 0); }