Search code examples
cwindowswinapinamed-pipes

Can't open Windows Named Pipe for writing?


I don't understand why I can't even open a named pipe for writing that I created in another process.

I get the error

231 (All pipe instances are busy).

The writer (client):

#include "Windows.h"
#include <stdio.h>
#include <errno.h>

int main()
{
    HANDLE hpipe;
    DWORD written;
    char msg[] = "play asdf.wav";

    hpipe = CreateFileA("\\\\.\\pipe\\isp-control",
               GENERIC_WRITE | GENERIC_READ,
               0, NULL, OPEN_EXISTING, 0, NULL);

    if (hpipe != INVALID_HANDLE_VALUE)
    {
      WriteFile(hpipe, msg, strlen(msg) + 1, &written, NULL);
      printf("wrote %d bytes of %d: '%s'\n", written, strlen(msg) + 1, msg);

      CloseHandle(hpipe);
    }
    else
    {
      printf("error %d opening pipe (handle %d)\n", GetLastError(), (int) hpipe);
      return 1;
    }

    return 0;
}

The reader (server) has before created the pipe like this (note the 4 instances, so one should be free, isn't it?)

hpipe_ = CreateNamedPipeA("\\\\.\\pipe\\isp-control",
             PIPE_ACCESS_DUPLEX,
             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
             4, // number of instances
             1024 * 16, // output buffer size
             65535,  // input size
             2000, // default timeout ms 
             NULL);

and then uses PeekNamedPipe to see if there's data to be read with ReadFile or send a timeout.


Solution

  • the 4-th parameter of CreateNamedPipe - nMaxInstances - this is The maximum number of instances that can be created for this pipe.

    so this is not instance count created in single call, but maximum count which can be created. single call to CreateNamedPipe always create one (1) instance of pipe. if you want have 4 instance - you need call CreateNamedPipe 4 time. also initially pipe created in listening state, so client can just connect to it by call CreateFile. but after connection is broken (because client close self handle) and you want accept new client connections for the same pipe instance - you need call DisconnectNamedPipe and then ConnectNamedPipe - only after this new client can again connect to the same pipe instance.

    but anyway, even if you create only single pipe instance, by single call CreateNamedPipeA - first client can connect to it. error 231 - i guess that real source of error is STATUS_PIPE_NOT_AVAILABLE(An instance of a named pipe cannot be found in the listening state) - you can check this by call RtlGetLastNtStatus() after CreateFile fail instead GetLastError() say that pipe name is valid, no problems with access, but somebody already connect (may be already disconnect) to pipe - never first call to CreateFile return this error