Windows 10 2018-05年Windows 10功能更新1803后,邮件槽上的CreateFile失败,错误53错误\u错误\u网络路径

Windows 10 2018-05年Windows 10功能更新1803后,邮件槽上的CreateFile失败,错误53错误\u错误\u网络路径,windows-10,mailslot,Windows 10,Mailslot,诸如CreateFile(“\\mycomputer\mailslot\this\u fails”,…)等命令失败,最后一个错误为53错误\u错误\u NETPATH 如果与任何有效或不存在的计算机名(包括运行测试的同一台计算机)一起使用,则会失败。在执行此操作的计算机上,即使引用的计算机不存在或没有使用该名称创建的邮件槽,它也会成功并返回邮件槽句柄。请注意,如果使用了不存在的计算机名或邮箱,则句柄上的后续writefile将失败,但CreateFile确实成功 但是,如果Mailslot引用是

诸如CreateFile(“\\mycomputer\mailslot\this\u fails”,…)等命令失败,最后一个错误为53错误\u错误\u NETPATH

如果与任何有效或不存在的计算机名(包括运行测试的同一台计算机)一起使用,则会失败。在执行此操作的计算机上,即使引用的计算机不存在或没有使用该名称创建的邮件槽,它也会成功并返回邮件槽句柄。请注意,如果使用了不存在的计算机名或邮箱,则句柄上的后续writefile将失败,但CreateFile确实成功

但是,如果Mailslot引用是显式本地的:“\\。\Mailslot\always\u有效”,则上面的CreateFile将成功

在安装2018-05年累积更新之前,这在所有版本的Windows上都有效。特别是KB4103721(Windows 10 home)似乎是罪魁祸首。[编辑:如下面的答案所述,实际上是功能更新版本1803导致了此问题。]

测试客户端:(不使用参数或“.”工作,但使用任何计算机名都失败)。 基于msdn

语法:testclient[服务器计算机名]

    #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;
    }
#包括
#包括
#包括
LPTSTR SlotName=TEXT(“\\\%hs\\mailslot\\sample\u mailslot”);
BOOL WriteSlot(句柄hSlot,LPTSTR lpszMessage)
{
布尔·弗雷索;
德沃德;
fResult=写入文件(hSlot,
LPSZ消息,
(德沃德)(lstrlen(lpszMessage)+1)*sizeof(TCHAR),
&CBR编写,
(重叠)空);
如果(!fResult)
{
//如果computername无效,则此故障有效
printf(“WriteFile失败,错误为%d。\n”,GetLastError());
返回FALSE;
}
printf(“插槽写入成功。\n”);
返回TRUE;
}
int main(int nArgs,char*arg[])
{
处理文件;
TCHAR szSlot[256];
_stprintf(szSlot、SlotName、nArgs>1?arg[1]:”);
_tprintf(文本(“写入插槽%s\n”)、szSlot;
hFile=CreateFile(szSlot,
你写什么,
文件共享读取,
(LPU属性)NULL,
开放式,
文件\u属性\u正常,
(句柄)NULL);
if(hFile==无效的句柄值)
{
//这就是我试图调试的失败
printf(“CreateFile因%d失败。\n”,GetLastError());
返回FALSE;
}
WriteSlot(hFile,TEXT(“邮件槽的消息一”);
WriteSlot(hFile,TEXT(“邮件槽的第二条消息”);
睡眠(5000);
WriteSlot(hFile,TEXT(“邮件槽的第三条消息”);
闭合手柄(hFile);
返回TRUE;
}
测试服务器:(读取并显示已发送的消息) 请注意,可能会收到重复的消息,因为邮件槽消息是通过所有可能的协议传输的。基于msdn

#包括
#包括
#包括
#包括
处理hSlot;
LPTSTR SlotName=TEXT(“\\.\\mailslot\\sample\u mailslot”);
BOOL ReadSlot()
{
DWORD cbMessage、CMMESSAGE、cbRead;
布尔·弗雷索;
LPTSTR LPSZ缓冲器;
TCHAR achID[80];
德沃德呼叫信息;
处理hEvent;
重叠ov;
cbMessage=cmmessage=cbRead=0;
hEvent=CreateEvent(NULL、FALSE、FALSE、TEXT(“ExampleSlot”);
if(NULL==hEvent)
返回FALSE;
偏移量=0;
ov.OffsetHigh=0;
ov.hEvent=hEvent;
fResult=GetMailslotInfo(hSlot,//mailslot句柄
(LPDWORD)NULL,//没有最大消息大小
&cbMessage,//下一条消息的大小
&cMessage,//消息数
(LPDWORD)NULL);//无读取超时
如果(!fResult)
{
printf(“GetMailsToInfo失败,错误为%d。\n”,GetLastError());
返回FALSE;
}
如果(cbMessage==邮件槽\u无\u消息)
{
printf(“等待消息…\n”);
返回TRUE;
}
cAllMessages=cMessage;
while(cMessage!=0)//检索所有消息
{
//创建消息编号字符串。
StringCchPrintf((LPTSTR)achID,
80,
文本(“\n消息#%d,共%d\n”),
cAllMessages-cMessage+1,
通话信息);
//为消息分配内存。
lpszBuffer=(LPTSTR)GlobalAlloc(GPTR,
lstrlen((LPTSTR)achID)*sizeof(TCHAR)+cbMessage;
if(NULL==lpszBuffer)
返回FALSE;
lpszBuffer[0]='\0';
fResult=读取文件(hSlot,
lpszBuffer,
cbMessage,
&cbRead,
&ov);
如果(!fResult)
{
printf(“读取文件失败,错误为%d。\n”,GetLastError());
GlobalFree((HGLOBAL)lpszBuffer);
返回FALSE;
}
//连接消息和消息编号字符串。
StringCbCat(lpszBuffer,
lstrlen((LPTSTR)achID)*sizeof(TCHAR)+cbMessage,
(LPTSTR)achID);
//显示消息。
_tprintf(文本(“邮箱的内容:%s\n”),lpszBuffer);
GlobalFree((HGLOBAL)lpszBuffer);
fResult=GetMailslotInfo(hSlot,//mailslot句柄
(LPDWORD)NULL,//没有最大消息大小
&cbMessage,//下一条消息的大小
&cMessage,//消息数
(LPDWORD)NULL);//无读取超时
如果(!fResult)
{
printf(“GetMailsToInfo失败(%d)\n”,GetLastError());
返回FALSE;
}
}
关闭手柄(hEvent);
返回TRUE;
}
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot=CreateMailslot(lpszSlotName,
0,//没有最大消息大小
MAILSLOT\u WAIT\u FOREVER,//操作没有超时
(LPSECURITY_属性)NULL);//默认安全性
if(hSlot==无效的\u句柄\u值
#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);
   }
}