using System;
using System.Runtime.InteropServices;

class MsgBoxTest
{
  [DllImport("user32.dll")]
  static extern int MessageBox (IntPtr hWnd, string text, string caption,
                                int type);
  public static void Main()
  {
    MessageBox (IntPtr.Zero, "Proszę, nie naciskaj tego więcej.", "Uwaga", 0);
  }
}

----------------------------------------------------------------------------------

[DllImport ("user32.dll")]
static extern int SendMessage (IntPtr hWnd, uint msg,
                               IntPtr wParam, IntPtr lParam);
[DllImport ("user32.dll")]
static extern int SendMessage (IntPtr hWnd, uint msg,
                               int wParam, int lParam);

----------------------------------------------------------------------------------

using System;
using System.Text;
using System.Runtime.InteropServices;

class Test
{
  [DllImport("kernel32.dll")]
  static extern int GetWindowsDirectory (StringBuilder sb, int maxChars);

  static void Main()
  {
    StringBuilder s = new StringBuilder (256);
    GetWindowsDirectory (s, 256);
    Console.WriteLine (s);
  }
}

----------------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
class SystemTime
{
   public ushort Year;
   public ushort Month;
   public ushort DayOfWeek;
   public ushort Day;
   public ushort Hour;
   public ushort Minute;
   public ushort Second;
   public ushort Milliseconds;
}

----------------------------------------------------------------------------------
[DllImport("kernel32.dll")]
static extern void GetSystemTime (SystemTime t);

static void Main()
{
  SystemTime t = new SystemTime();
  GetSystemTime (t);
  Console.WriteLine (t.Year);
}

----------------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;

class CallbackFun
{
  delegate bool EnumWindowsCallback (IntPtr hWnd, IntPtr lParam);

  [DllImport("user32.dll")]
  static extern int EnumWindows (EnumWindowsCallback hWnd, IntPtr lParam);

  static bool PrintWindow (IntPtr hWnd, IntPtr lParam)
  {
    Console.WriteLine (hWnd.ToInt64());
    return true;
  }

  static void Main()
  {
    EnumWindows (PrintWindow, IntPtr.Zero);
  }
}

----------------------------------------------------------------------------------

[StructLayout (LayoutKind.Explicit)]
public struct NoteMessage
{
  [FieldOffset(0)] public int PackedMsg;    // 4 bajty długości

  [FieldOffset(0)] public byte Channel;     // FieldOffset also at 0
  [FieldOffset(1)] public byte Note;
  [FieldOffset(2)] public byte Velocity;
}

----------------------------------------------------------------------------------
NoteMessage n = new NoteMessage();
Console.WriteLine (n.PackedMsg);    // 0

n.Channel = 10;
n.Note = 100;
n.Velocity = 50;    
Console.WriteLine (n.PackedMsg);    // 3302410

n.PackedMsg = 3328010;
Console.WriteLine (n.Note);         // 200

----------------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;

public class SharedMem : IDisposable
{
  // używamy typów wyliczeniowych, ponieważ są bezpieczniejsze niż stałe

  enum FileProtection : uint      // stałe z winnt.h
  {
    ReadOnly = 2,
    ReadWrite = 4
  }

  enum FileRights : uint          // stałe z WinBASE.h
  {
    Read = 4,
    Write = 2,
    ReadWrite = Read + Write
  }

  static readonly IntPtr NoFileHandle = new IntPtr (-1);

  [DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr CreateFileMapping (IntPtr hFile,
                                          int lpAttributes,
                                          FileProtection flProtect,
                                          uint dwMaximumSizeHigh,
                                          uint dwMaximumSizeLow,
                                          string lpName);
  
  [DllImport ("kernel32.dll", SetLastError=true)]
  static extern IntPtr OpenFileMapping (FileRights dwDesiredAccess,
                                        bool bInheritHandle,
                                        string lpName);

  [DllImport ("kernel32.dll", SetLastError = true)]
  static extern IntPtr MapViewOfFile (IntPtr hFileMappingObject,
                                      FileRights dwDesiredAccess,
                                      uint dwFileOffsetHigh,
                                      uint dwFileOffsetLow,
                                      uint dwNumberOfBytesToMap);
  [DllImport ("Kernel32.dll")]
  static extern bool UnmapViewOfFile (IntPtr map);

  [DllImport ("kernel32.dll")]
  static extern int CloseHandle (IntPtr hObject);

  IntPtr fileHandle, fileMap;

  public IntPtr Root { get { return fileMap; } }

  public SharedMem (string name, bool existing, uint sizeInBytes)
  {
    if (existing)
      fileHandle = OpenFileMapping (FileRights.ReadWrite, false, name);
    else
      fileHandle = CreateFileMapping (NoFileHandle, 0,
                                      FileProtection.ReadWrite,
                                      0, sizeInBytes, name);
    if (fileHandle == IntPtr.Zero)
      throw new Exception
        ("Bład otwarcia/tworzenia: " + Marshal.GetLastWin32Error());

    // pobranie mapy odczytu/zapisu dla całego pliku
    fileMap = MapViewOfFile (fileHandle, FileRights.ReadWrite, 0, 0, 0);

    if (fileMap == IntPtr.Zero)
      throw new Exception
        ("Błąd MapViewOfFile: " + Marshal.GetLastWin32Error());
  }

  public void Dispose()
  {
    if (fileMap != IntPtr.Zero) UnmapViewOfFile (fileMap);
    if (fileHandle != IntPtr.Zero) CloseHandle (fileHandle);
    fileMap = fileHandle = IntPtr.Zero;
  }
}

----------------------------------------------------------------------------------

[StructLayout (LayoutKind.Sequential)]
unsafe struct MySharedData
{
  public int Value;
  public char Letter;
  public fixed float NumberArray [50];
}

// Program 1:

static unsafe void Main()
{
  using (SharedMem sm = new SharedMem ("MójZasób", false, 1000))
  {
    void* root = sm.Root.ToPointer();
    MySharedData* data = (MySharedData*) root;

    data->Value = 123;
    data->Letter = 'X';
    data->Number[10] = 1.45f;
    Console.WriteLine ("Zapisane do pamięci współdzielonej");
  
    Console.ReadLine();

    Console.WriteLine ("Value to " + data->Value);
    Console.WriteLine ("Letter to " + data->Letter);
    Console.WriteLine ("11 wartość tablicy Numbers to " + data->Number[10]);
    Console.ReadLine();
  }
}

// Program 2:

static unsafe void Main()
{
  using (SharedMem sm = new SharedMem ("MójZasób", true, 1000))
  {
    void* root = sm.Root.ToPointer();
    MySharedData* data = (MySharedData*) root;

    Console.WriteLine ("Value to " + data->Value);
    Console.WriteLine ("Letter to " + data->Letter);
    Console.WriteLine ("11 wartość tablicy Number to " + data->Number[10]);

    // nasza kolej na aktualizację wartości w pamięci współdzielonej!
    data->Value++;
    data->Letter = '!';
    data->Number[10] = 987.5f;
    Console.WriteLine ("Zaktualizowano pamięć współdzieloną");
    Console.ReadLine();
  }
}

----------------------------------------------------------------------------------

[StructLayout (LayoutKind.Sequential)]
unsafe struct MySharedData
{
  ...

  // alokacja pamięci dla 200 znaków (czyli 400 bajtów)
  fixed char message [200];

  // ten kod najprawdopodobniej powinien się znaleźć w klasie pomocniczej
  public string Message
  {
    get { fixed (char* cp = message) return new string (cp); }
    set
    {
      fixed (char* cp = message)
      {
        int i = 0;
        for (; i < value.Length && i < 199; i++)
          cp [i] = value [i];

        // zakończenie znakiem null
        cp [i] = '\0';
      }
    }
  }
}
