Hi all,
The following C# sample shows how to create a memory mapped file and use private namespaces to allow access to specific groups of users:
FORM1.CS
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Security.Principal; using System.IO; namespace Alejacma { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { bool bResult = false; IntPtr hBoundary = IntPtr.Zero; IntPtr pSid = IntPtr.Zero; int cbSid = Win32.SECURITY_MAX_SID_SIZE; IntPtr hNamespace = IntPtr.Zero; Win32.SECURITY_ATTRIBUTES securityAttributes = new Win32.SECURITY_ATTRIBUTES(); IntPtr hFile = IntPtr.Zero; IntPtr pView = IntPtr.Zero; IntPtr pData = IntPtr.Zero; try { // Create boundary hBoundary = Win32.CreateBoundaryDescriptor( "AlejacmaBoundaryDescriptor", 0 ); if (hBoundary == IntPtr.Zero) { throw new Exception("CreateBoundaryDescriptor", new Win32Exception(Marshal.GetLastWin32Error())); } pSid = Marshal.AllocHGlobal(cbSid); bResult = Win32.CreateWellKnownSid( WellKnownSidType.BuiltinAdministratorsSid, IntPtr.Zero, pSid, ref cbSid ); if (!bResult) { throw new Exception("CreateWellKnownSid", new Win32Exception(Marshal.GetLastWin32Error())); } bResult = Win32.AddSIDToBoundaryDescriptor( ref hBoundary, pSid ); if (!bResult) { throw new Exception("AddSIDToBoundaryDescriptor", new Win32Exception(Marshal.GetLastWin32Error())); } // Create namespace and give access to some groups of users: // - Remote Desktop Users (needed for remote users to access the mapped file) // - Administrators (needed to create the mapped file within this program) // - Interactive users (needed for local users to access mapped file) bResult = Win32.ConvertStringSecurityDescriptorToSecurityDescriptor( "D:(A;;GA;;;RD)(A;;GA;;;S-1-5-32-544)(A;;GA;;;S-1-5-4)", Win32.SDDL_REVISION_1, out securityAttributes.lpSecurityDescriptor, IntPtr.Zero ); if (!bResult) { throw new Exception("ConvertStringSecurityDescriptorToSecurityDescriptor", new Win32Exception(Marshal.GetLastWin32Error())); } securityAttributes.nLength = Marshal.SizeOf(securityAttributes); securityAttributes.bInheritHandle = false; hNamespace = Win32.CreatePrivateNamespace( ref securityAttributes, hBoundary, "Alejacma" ); if (hNamespace == IntPtr.Zero) { throw new Exception("CreatePrivateNamespace", new Win32Exception(Marshal.GetLastWin32Error())); } // Create file mapping, and give access to all users with access to the namespace hFile = Win32.CreateFileMapping( Win32.INVALID_HANDLE_VALUE, ref securityAttributes, Win32.PAGE_READWRITE, 0, 20971520, "Alejacma\\TestFileMapping" ); if (hFile == IntPtr.Zero) { throw new Exception("CreateFileMapping", new Win32Exception(Marshal.GetLastWin32Error())); } // Map file and write something to it pView = Win32.MapViewOfFile( hFile, Win32.FILE_MAP_WRITE, 0, 0, 11 ); if (pView == IntPtr.Zero) { throw new Exception("MapViewOfFile", new Win32Exception(Marshal.GetLastWin32Error())); } pData = Marshal.StringToHGlobalAnsi("Hello World"); Win32.MemCopy(pView, pData, 11); // We are done. Now a reader app can access the data MessageBox.Show("Run the reader app now!"); } catch (Exception ex) { // Any error? MessageBox.Show(ex.Message + " failed with '" + ex.InnerException.Message + "' error"); } finally { // Clean up memory if (pSid != IntPtr.Zero) { Marshal.FreeHGlobal(pSid); } if (securityAttributes.lpSecurityDescriptor != IntPtr.Zero) { Win32.LocalFree(securityAttributes.lpSecurityDescriptor); } if (pData != IntPtr.Zero) { Marshal.FreeHGlobal(pData); } // We must also close hBoundary, hNamespace, hFile and pView when we don't need them anymore. // Check MSDN's description of the APIs we used to create them to figure out how to close them. } } } }
WIN32.CS
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Security.Principal; namespace Alejacma { class Win32 { public const int SECURITY_MAX_SID_SIZE = 68; public const int SDDL_REVISION_1 = 1; public const uint INVALID_HANDLE_VALUE = 0xffffffff; public const int PAGE_READWRITE = 0x04; public const int FILE_MAP_WRITE = 0X02; [StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; public bool bInheritHandle; } [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr CreateBoundaryDescriptor ( [In] string Name, [In] int Flags ); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool CreateWellKnownSid ( [In] WellKnownSidType WellKnownSidType, [In] [Optional] IntPtr DomainSid, [In] IntPtr pSid, [In][Out]ref int cbSid ); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool AddSIDToBoundaryDescriptor ( [In][Out] ref IntPtr BoundaryDescriptor, [In] IntPtr RequiredSid ); [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor ( [In] string StringSecurityDescriptor, [In] int StringSDRevision, [Out] out IntPtr SecurityDescriptor, [Out] IntPtr SecurityDescriptorSize ); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LocalFree([In] IntPtr hMem); [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr CreatePrivateNamespace( [In][Optional] ref SECURITY_ATTRIBUTES lpPrivateNamespaceAttributes, [In] IntPtr lpBoundaryDescriptor, [In] string lpAliasPrefix ); [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr CreateFileMapping( [In] uint hFile, [In][Optional] ref SECURITY_ATTRIBUTES lpAttributes, [In] int flProtect, [In] int dwMaximumSizeHigh, [In] int dwMaximumSizeLow, [In][Optional] string lpName ); [DllImport("Kernel32.dll", SetLastError = true)] public static extern IntPtr MapViewOfFile( [In] IntPtr hFileMappingObject, [In] int dwDesiredAccess, [In] int dwFileOffsetHigh, [In] int dwFileOffsetLow, [In] int dwNumberOfBytesToMap ); [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] public static extern IntPtr MemCopy(IntPtr dest, IntPtr src, uint count); } }
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)