Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@hyrious
Created July 7, 2019 03:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyrious/67f243671456ce47f53371969dbcaba8 to your computer and use it in GitHub Desktop.
Save hyrious/67f243671456ce47f53371969dbcaba8 to your computer and use it in GitHub Desktop.
Windows IPC -- MailSlot
#include <windows.h>
#include <stdio.h>
HANDLE hSlot;
LPTSTR Slot = TEXT("\\\\.\\mailslot\\meow");
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName) {
hSlot = CreateMailslot(lpszSlotName, 0, MAILSLOT_WAIT_FOREVER, 0);
if (hSlot == INVALID_HANDLE_VALUE) {
printf("CreateMailSlot failed with %d.\n", GetLastError());
return FALSE;
}
return TRUE;
}
BOOL WINAPI GetSlot(LPTSTR lpszSlotName) {
hSlot = CreateFile(lpszSlotName, GENERIC_WRITE, FILE_SHARE_READ,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSlot == INVALID_HANDLE_VALUE) {
printf("CreateFile failed with %d.\n", GetLastError());
return FALSE;
}
return TRUE;
}
BOOL ReadSlot(void) {
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(0, FALSE, FALSE, Slot);
ov.Offset = ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo(hSlot, 0, &cbMessage, &cMessage, 0);
if (!fResult) {
printf("GetMailslotInfo failed with %d.\n", GetLastError());
return FALSE;
}
if (cbMessage == MAILSLOT_NO_MESSAGE) {
printf("waiting...\n");
return TRUE;
}
cAllMessages = cMessage;
while (cMessage) {
lpszBuffer = (LPTSTR) GlobalAlloc(GPTR, cbMessage);
if (lpszBuffer == NULL)
return FALSE;
lpszBuffer[0] = '\0';
fResult = ReadFile(hSlot, lpszBuffer, cbMessage, &cbRead, &ov);
if (!fResult) {
printf("ReadFile failed with %d.\n", GetLastError());
GlobalFree((HGLOBAL) lpszBuffer);
return FALSE;
}
printf(">> %s\n", lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
fResult = GetMailslotInfo(hSlot, 0, &cbMessage, &cMessage, 0);
if (!fResult) {
printf("GetMailslotInfo failed with %d.\n", GetLastError());
return FALSE;
}
}
CloseHandle(hEvent);
return TRUE;
}
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage) {
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot, lpszMessage, (lstrlen(lpszMessage) + 1) * sizeof(TCHAR), &cbWritten, 0);
if (!fResult) {
printf("WriteFile failed with %d.\n", GetLastError());
return FALSE;
}
return TRUE;
}
int main(int argc, char **argv) {
if (argc < 2) {
if (!MakeSlot(Slot)) {
return EXIT_FAILURE;
}
printf("hSlot: %p\n", hSlot);
while (ReadSlot()) {
Sleep(1000);
}
} else {
if (!GetSlot(Slot)) {
return EXIT_FAILURE;
}
WriteSlot(hSlot, TEXT("Hello world! (1)"));
WriteSlot(hSlot, TEXT("Hello world! (2)"));
Sleep(5000);
WriteSlot(hSlot, TEXT("Hello world! (3 ... after 5s)"));
}
CloseHandle(hSlot);
return 0;
}
@hyrious
Copy link
Author

hyrious commented Jul 7, 2019

MailSlot is a one-way IPC method. To do duplex you should create two different slot.
This file is both server and client. Suppose we compiled it to a.exe.

Server:

> a.exe
waiting...

Client:

> a.exe 1
(now the server side should see the messages)

If client starts before server, it will end with WinError (2), meaning it can not find such slot.
If server stops suddenly, the client will get WinError (38), meaning it got EOF.
If multiple servers start with the same slot name, the later ones will get WinError (183), meaning Errno::EEXIST.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment