5

I am creating a named pipe file as follows:

 void  SavePipeFile(){


    HANDLE hpipe;
    BOOL bRet;
    DWORD size;

    hpipe =   
        CreateNamedPipe(
        L"\\\\.\\pipe\\mypipe",
        PIPE_ACCESS_OUTBOUND,  
        PIPE_TYPE_BYTE,  
        1, 
        0,  
        0,  
        0,  
        NULL  
        );
    if(hpipe == NULL || hpipe==INVALID_HANDLE_VALUE)
    {
        printf("Error opening handle\n");
    }

    CloseHandle(hpipe);


}

The function exists ok,no errors.But I can't find the physical file "mypipe" in the system.Does Windows API saves it to a specific location?Running on Windows 7 64bit

Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • 1
    You created a *named pipe*, not a *named pipe file*. I have no idea why one would create a pipe and expect to get a file. After all, you have to have a very specific need to actually create a named pipe. It's not something you implement by accident. – IInspectable Jan 15 '14 at 16:34
  • I wanted a file as I need to specify it's location to an external app which needs to read it.Btw,on Linux I can have a file. – Michael IV Jan 15 '14 at 16:57
  • Named objects are referenced by their name. There is no requirement to have a physical file to reference a name pipe through it's name `\\.\pipe\mypipe`. – IInspectable Jan 15 '14 at 17:20

2 Answers2

13

Quote from http://en.wikipedia.org/wiki/Named_pipe.

Named pipes cannot be mounted within a normal filesystem, unlike in Unix. Also unlike their Unix counterparts, named pipes are volatile (removed after the last reference to them is closed). Every pipe is placed in the root directory of the named pipe filesystem (NPFS), mounted under the special path \.\pipe\ (that is, a pipe named "foo" would have a full path name of \.\pipe\foo). Anonymous pipes used in pipelining are actually named pipes with a random name.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30
2

When you create a named pipe on ReactOS, CreateNamedPipe in kernel32.dll calls NtCreateNamedPipeFile in ntdll.dll, which performs a syscall + index into SSDT to its kernel mode counterpart in ntoskrnl.exe, which calls IoCreateFile, which calls IopCreateFile, which will call ObOpenObjectByName, which calls ObpLookupObjectName, which calls the object parse routine ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure, which will be IopParseRoutine, which sends an IRP with major code IRP_MJ_CREATE_NAMED_PIPE to the NPFS driver, which it acquires by its name \Device\NamedPipe (it will parse \\.\pipe as \??\pipe, which is a symbolic link to the \Device\NamedPipe DO created by the NPFS driver).

The DriverEntry function of the NPFS assigns DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;. NpFsdCreateNamedPipe calls NpCreateNewNamedPipe, which will set up the file object and the CCB (Context Control Block) (FileObject->FsContext2) of the file object with the data queues.

The file object of name PipeName is accessed via \\.\pipe\PipeName and translates to \Device\NamedPipe\PipeName. The file object points to the NamedPipe device object created by the Npfs, which IoGetRelatedDeviceObject will return, meaning that all WriteFile and ReadFile operations result in an IRP, which gets sent to the top of the device stack of this Device Object, passing the pipe name \PipeName. This is similar to how \??\C:\Windows i.e. \Device\HarddiskVolume1\Windows file object PDEVICE_OBJECT points to the Device\HarddiskVolume1 device object, the file name UNICODE_STRING of the file object being \Windows. If you look at the file object, you can get the full path by getting the device object name and appending it to the start. IoCallDriver will be eventually called on the owning driver of the device object. Based on the IRP major code in the IRP passed, IoCallDriver calls either DO->DriverObject->MajorFunction[IRP_MJ_Write], which is NpFsdWrite or DO->DriverObject->MajorFunction[IRP_MJ_Read], which is NpFsdRead. Those functions will write and read to the data queues Ccb->DataQueue[FILE_PIPE_OUTBOUND] and Ccb->DataQueue[FILE_PIPE_INBOUND], which contain the head of a doubly linked list of DataEntry headers where DataEntry[0] is the header and DataEntry[1] is the buffer. If you open the named pipe as a server then it reads from the inbound and writes to the outbound. The client reads from the outbound and writes to the inbound.

If you use PIPE_TYPE_MESSAGE, then every time you write to the pipe, another DataEntry will be added to the tail of the linked list (because NpWriteDataQueue will return with IoStatus STATUS_MORE_PROCESSING_REQUIRED in the IRP, which the calling function checks before calling NpAddDataQueueEntry), and each time you read, a DataEntry will be removed from the head of the linked list (NpReadDataQueue will only call NpRemoveDataQueueEntry if !Peek). You will get an error if you do not read all of the message. If you use PIPE_TYPE_BYTE, then only the current DataEntry is used and no DataEntrys are removed when you write. Simply, the ByteOffset field of the DataEntry is increased by the number of bytes read, and I'm really not sure how writing in byte mode works.

DataEntries, CCBs and FileObjects are allocated on the non-paged pool.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
  • 1
    @KenWhite I grammatised it but that was my first draft; I need to check some stuff. The only issue is really that it may be too technical of an answer if people don't know the internals. I'm not entirely sure to which degree I should elaborate but I'll work on it. – Lewis Kelsey Apr 27 '20 at 00:17
  • For me it is too much technical. I tried to get from here answer if this means that the "pipe files" are data that stored only in RAM or does not have to be stored on disk.. this is the thing I try to understand and I could not get clear answer – gil123 Oct 04 '20 at 05:26
  • @gil123 In memory (be it from RAM or cache), seeing as the mentioned objects cannot be paged to the page file on the disk as they are allocated from the non-paged pool by design of the operating system – Lewis Kelsey Oct 05 '20 at 19:46
  • Thanks, for some reason this piece of information (that this stuff is not saved in disk even if you use the `CreateFile` function) was not clear at all and I could not find anything on the internet that state that it is not using the disk. Maybe it is only me and I missed the documentation that say it. I don't know. Anyway I think that the answer you gave to my question is very very valuable information. It is not too technical and tell thing that is the bottom line that developer may want to know. – gil123 Oct 05 '20 at 20:27
  • @gil123 I haven't looked at windows source code in a while and theres still a lot more I need to find out myself but this was my current progression on named pipes just through experimenting with debuggers (livekd, ida) and sysinternals on my own computer but also looking through the ReactOS source code. The purpose of my answer was to look at the source code and basically translate in writing what didn't exist in writing on the internet already.Most of my answers are like this; I just find a question with a suitable question title to put it on, but I will eventually be putting it on a website – Lewis Kelsey Oct 06 '20 at 00:29
  • But this answer assumes prior knowledge of a lot of things about operating systems and underlying hardware and and what you learn on the windows internals books – Lewis Kelsey Oct 06 '20 at 00:45
  • 1
    Hi, don't get me wrong. I am not saying that your original answer was unless. I just said that your answer to my question was useful and good for me and maybe for most developers. It does not mean that your original answer is redundant. Both type of answers are good, one for most use-cases and the other is more to people that want to learn / build or modify operating system. I may be wrong even about this. Anyway, thank you very much for your knowledge – gil123 Oct 06 '20 at 18:28