using System;
using System.Runtime.InteropServices;
namespace Almdal.AutoPlayListener {
[Flags]
enum PageProtection : uint {
NoAccess = 0x01,
Readonly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
Guard = 0x100,
NoCache = 0x200,
WriteCombine = 0x400,
}
enum FileAccess : uint {
SECTION_QUERY = 0x0001,
SECTION_MAP_WRITE = 0x0002,
SECTION_MAP_READ = 0x0004,
SECTION_MAP_EXECUTE = 0x0008,
SECTION_EXTEND_SIZE = 0x0010,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
SECTION_MAP_WRITE |
SECTION_MAP_READ |
SECTION_MAP_EXECUTE |
SECTION_EXTEND_SIZE,
FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
}
public class SharedMemory : IDisposableImpl {
#region Memory Mapping Routines
static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFileMapping(
IntPtr hFile, // A handle to the file from which to create a mapping object
// If hFile is INVALID_HANDLE_VALUE, the calling process must
// also specify a mapping object size in the dwMaximumSizeHigh
// and dwMaximumSizeLow parameters. In this scenario,
// CreateFileMapping creates a file mapping object of a specified
// size that the operating system paging file backs, instead of by
// a named file in the file system.
IntPtr lpFileMappingAttributes, // A pointer to a SECURITY_ATTRIBUTES structure that determines
// whether or not a returned handle can be inherited by child
// processes. If lpAttributes is NULL, the handle cannot be inherited.
PageProtection flProtect, // The protection for the file view, when the file is mapped.
uint dwMaximumSizeHigh, // A high-order DWORD for the maximum size of a file mapping object.
uint dwMaximumSizeLow, // A low-order DWORD for the maximum size of a file mapping object.
string lpName); // A pointer to a null-terminated string that specifies the name of a mapping object
[DllImport("kernel32.dll")]
private static extern IntPtr OpenFileMapping(
FileAccess dwDesiredAccess, // Access to the file mapping object
bool bInheritHandle, // If this parameter is TRUE, a process created by the CreateProcess
// function can inherit the handle; otherwise, the handle cannot be
// inherited
string lpName); // Pointer to a string that names the file mapping object to be opened.
// If there is an open handle to a file mapping object by this name
// and the security descriptor on the mapping object does not conflict
// with the dwDesiredAccess parameter, the open operation succeeds
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr MapViewOfFile(
IntPtr hFileMappingObject, // A handle to an open handle of a file mapping object
FileAccess dwDesiredAccess, // The type of access to a file mapping object, which ensures the
// protection of the pages
uint dwFileOffsetHigh, // A high-order DWORD of the file offset where the view begins.
uint dwFileOffsetLow, // A low-order DWORD of the file offset where the view is begins
uint dwNumberOfBytesToMap); // The number of bytes of a file mapping to map to the view. If this
// parameter is 0 (zero), the mapping extends from the specified offset
// to the end of the section.
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UnmapViewOfFile(
IntPtr lpBaseAddress); // Pointer to the base address of the mapped view of a file that is to be
// unmapped. This value must be identical to the value returned by a
// previous call to the MapViewOfFile.
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(
IntPtr hObject); // Handle of the File Object
#endregion
private string _name;
private IntPtr _memHandle;
public SharedMemory(string name) {
_name = name;
_memHandle = OpenFileMapping(FileAccess.FILE_MAP_ALL_ACCESS, false, _name);
if (IntPtr.Zero.Equals(_memHandle) ) {
throw new Exception("Could not open shared memory file mapping object: LasterrorCode: " +
Marshal.GetLastWin32Error());
}
}
public SharedMemory(string name, uint size) {
_name = name;
_memHandle = CreateFileMapping(INVALID_HANDLE_VALUE, // Use paging file
IntPtr.Zero, // Default security
PageProtection.ReadWrite, // Read/write access
0,
size,
_name);
if (IntPtr.Zero.Equals(_memHandle) || INVALID_HANDLE_VALUE.Equals(_memHandle)) {
throw new Exception("Could not create shared memory file mapping object: LasterrorCode: " +
Marshal.GetLastWin32Error());
}
}
public void WriteString(string str) {
IntPtr pbuf = MapViewOfFile(_memHandle, FileAccess.FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (IntPtr.Zero.Equals(_memHandle)) {
throw new Exception("Unable to Map to shared memory file mapping object: LasterrorCode: " +
Marshal.GetLastWin32Error());
}
try {
Marshal.Copy(str.ToCharArray(), 0, pbuf, str.Length);
IntPtr bufPos = new IntPtr((int)pbuf + (sizeof(char)*str.Length));
Marshal.Copy(new char[] { '\0' }, 0, bufPos, 1);
} finally {
UnmapViewOfFile(pbuf);
}
}
public string ReadString() {
IntPtr pbuf = MapViewOfFile(_memHandle, FileAccess.FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (IntPtr.Zero.Equals(_memHandle)) {
throw new Exception("Unable to Map to shared memory file mapping object: LasterrorCode: " +
Marshal.GetLastWin32Error());
}
try {
return Marshal.PtrToStringUni(pbuf);
} finally {
UnmapViewOfFile(pbuf);
}
}
protected override void DisposeUnmanagedResources() {
CloseHandle(_memHandle);
_memHandle = IntPtr.Zero;
}
}
}