commands such as CreateFile("\\mycomputer\mailslot\this_fails",...) fail with last error = 53 ERROR_BAD_NETPATH
That fails if used with any valid or non-existing computer name including the same computer on which the test is running. On computers where this works, it succeeds and returns a mailslot handle even if the referenced computer does not exist or does not have a mailslot created with that name. Note that if an non-existing computer name or mailslot is used, subsequent WriteFiles on the handle will fail, but the CreateFile does succeed.
However, the CreateFile above will succeed if the Mailslot reference is explicitly local: "\\.\mailslot\always_works"
This worked on all versions of Windows previously until the 2018-05 cumulative updates were installed. Specifically KB4103721 (Windows 10 home) seemed to be the culprit. [Edit: as noted in answers below, it is actually Feature Update Build 1803 that causes this issue.]
Test Client: (works with no parameter or "." but fails with any computername). Based on msdn sample
Syntax: testclient [server computername]
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
LPTSTR SlotName = TEXT("\\\\%hs\\mailslot\\sample_mailslot");
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
{
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot,
lpszMessage,
(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED) NULL);
if (!fResult)
{
// this failure is valid if computername is not valid
printf("WriteFile failed with %d.\n", GetLastError());
return FALSE;
}
printf("Slot written to successfully.\n");
return TRUE;
}
int main(int nArgs,char * arg[])
{
HANDLE hFile;
TCHAR szSlot[256];
_stprintf (szSlot,SlotName,nArgs > 1 ? arg[1] : ".");
_tprintf(TEXT("Writing to slot %s\n"),szSlot);
hFile = CreateFile(szSlot,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// this is the failure I'm trying to debug
printf("CreateFile failed with %d.\n", GetLastError());
return FALSE;
}
WriteSlot(hFile, TEXT("Message one for mailslot."));
WriteSlot(hFile, TEXT("Message two for mailslot."));
Sleep(5000);
WriteSlot(hFile, TEXT("Message three for mailslot."));
CloseHandle(hFile);
return TRUE;
}
Test Server: (reads a displays sent messages) Note that duplicate messages may be received because Mailslot messages are transmitted over all possible protocols. Based on msdn sample.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
HANDLE hSlot;
LPTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");
BOOL ReadSlot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
if( NULL == hEvent )
return FALSE;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo( hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed with %d.\n", GetLastError());
return FALSE;
}
if (cbMessage == MAILSLOT_NO_MESSAGE)
{
printf("Waiting for a message...\n");
return TRUE;
}
cAllMessages = cMessage;
while (cMessage != 0) // retrieve all messages
{
// Create a message-number string.
StringCchPrintf((LPTSTR) achID,
80,
TEXT("\nMessage #%d of %d\n"),
cAllMessages - cMessage + 1,
cAllMessages);
// Allocate memory for the message.
lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
if( NULL == lpszBuffer )
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;
}
// Concatenate the message and the message-number string.
StringCbCat(lpszBuffer,
lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
(LPTSTR) achID);
// Display the message.
_tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
fResult = GetMailslotInfo(hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed (%d)\n", GetLastError());
return FALSE;
}
}
CloseHandle(hEvent);
return TRUE;
}
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d\n", GetLastError());
return FALSE;
}
return TRUE;
}
void main()
{
MakeSlot(SlotName);
while(TRUE)
{
ReadSlot();
Sleep(3000);
}
}
The test server to read messages, and the test client to send messages can be run in different cmd shells on the same computer, or run on different computers. When it fails, it fails immediately and seems to be a problem trying to resolve the network path name. On the same computer, file shares such as \\ThisComputer\share work properly from the same computer or a different one.
NetBIOS is enabled over TCP/IP for the network adapters in use. The network adapters are designated as Private. Firewall was disabled for testing. File and Printer sharing are enabled. Computers are in same workgroup. Computer name resolution works, and this fails even if IP addresses are used (even 127.0.0.1).
The issue is already fixed since last Year
September 26, 2018—KB4458469 (OS Build 17134.320)