Windows API – Interprocess Communication

Overview

Interprocess Communication (IPC) enables separate processes to exchange data and synchronize actions. Windows provides several IPC mechanisms, each suited for different scenarios:

  • Named Pipes – byte‑stream communication, ideal for client/server models.
  • Memory‑Mapped Files – shared memory regions for fast data exchange.
  • MailSlots – one‑way broadcast messages.
  • Events, Mutexes, Semaphores – synchronization primitives.
  • RPC (Remote Procedure Call) – high‑level request/response interface.

Named Pipes

Named pipes are represented by the CreateNamedPipe and ConnectNamedPipe APIs. They support duplex communication and can be accessed over the network.

  • CreateNamedPipe
  • ConnectNamedPipe
  • DisconnectNamedPipe
  • WaitNamedPipe
  • SetNamedPipeHandleState
  • GetNamedPipeInfo

Example – Simple Pipe Server (C++)

#include <windows.h>
#include <iostream>

int main() {
    const wchar_t* pipeName = L"\\\\.\\pipe\\MyPipe";
    HANDLE hPipe = CreateNamedPipeW(
        pipeName,
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
        1, 512, 512, 0, nullptr);

    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "CreateNamedPipe failed: " << GetLastError() << std::endl;
        return 1;
    }

    std::wcout << L"Waiting for client..." << std::endl;
    BOOL connected = ConnectNamedPipe(hPipe, nullptr) ?
                     TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);

    if (!connected) {
        std::cerr << "ConnectNamedPipe failed: " << GetLastError() << std::endl;
        CloseHandle(hPipe);
        return 1;
    }

    const char* msg = "Hello from server!";
    DWORD written;
    WriteFile(hPipe, msg, (DWORD)strlen(msg), &written, nullptr);
    CloseHandle(hPipe);
    return 0;
}

Memory‑Mapped Files

Memory‑mapped files let processes share a region of virtual memory backed by a file or pagefile.

Key Functions

  • CreateFileMapping
  • OpenFileMapping
  • MapViewOfFile
  • UnmapViewOfFile

Example – Shared Counter (C++)

#include <windows.h>
#include <iostream>

int main() {
    const wchar_t* name = L"Global\\MySharedCounter";
    HANDLE hMap = CreateFileMappingW(
        INVALID_HANDLE_VALUE, nullptr,
        PAGE_READWRITE, 0, sizeof(LONG), name);

    if (!hMap) {
        std::cerr << "CreateFileMapping failed: " << GetLastError() << std::endl;
        return 1;
    }

    LPVOID pBuf = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LONG));
    if (!pBuf) {
        std::cerr << "MapViewOfFile failed: " << GetLastError() << std::endl;
        CloseHandle(hMap);
        return 1;
    }

    LONG* counter = static_cast(pBuf);
    InterlockedIncrement(counter);
    std::cout << "Counter = " << *counter << std::endl;

    UnmapViewOfFile(pBuf);
    CloseHandle(hMap);
    return 0;
}

Synchronization Primitives

Use kernel objects to coordinate access to shared resources.

ObjectCreation APIPurpose
MutexCreateMutexMutual exclusion
EventCreateEventSignaling
SemaphoreCreateSemaphoreResource counting

Further Reading