xref: /reactos/sdk/lib/ucrt/conio/pipe.cpp (revision b09b5584)
1 //
2 // pipe.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Defines _pipe(), which creates a pipe.
7 //
8 #include <corecrt_internal_lowio.h>
9 #include <stdlib.h>
10 
11 
12 
13 // Creates a pipe.  The phandles pointer must be a pointer to an array of two
14 // int objects.  Upon successful return, phandles[0] is the read handle, and
15 // phandles[1] is the write handle for the pipe.  On success, 0 is returned; on
16 // failure, -1 is returned and errno is set.
17 //
18 // The psize is the amount of memory, in bytes, to ask the OS to reserve for the
19 // pipe.  The textmode is the text mode that will be given to the pipe.
20 extern "C" int __cdecl _pipe(int* const phandles, unsigned const psize, int const textmode)
21 {
22     _VALIDATE_CLEAR_OSSERR_RETURN(phandles != nullptr, EINVAL, -1);
23     phandles[0] = phandles[1] = -1;
24 
25     _VALIDATE_CLEAR_OSSERR_RETURN((textmode & ~(_O_NOINHERIT | _O_BINARY | _O_TEXT)) == 0, EINVAL, -1);
26     _VALIDATE_CLEAR_OSSERR_RETURN((textmode & (_O_BINARY | _O_TEXT)) != (_O_BINARY | _O_TEXT), EINVAL, -1);
27 
28 
29     SECURITY_ATTRIBUTES security_attributes;
30     security_attributes.nLength = sizeof(security_attributes);
31     security_attributes.lpSecurityDescriptor = nullptr;
32     security_attributes.bInheritHandle = (textmode & _O_NOINHERIT) == 0;
33 
34 
35     // Create the pipe:
36     HANDLE read_handle, write_handle;
37     if (!CreatePipe(&read_handle, &write_handle, &security_attributes, psize))
38     {
39         __acrt_errno_map_os_error(GetLastError());
40         return -1;
41     }
42 
43     // Create the CRT read handle for the pipe:
44     int const crt_read_handle = _alloc_osfhnd();
45     if (crt_read_handle == -1)
46     {
47         errno = EMFILE;
48         _doserrno = 0;
49         CloseHandle(read_handle);
50         CloseHandle(write_handle);
51         return -1;
52     }
53 
54     __try
55     {
56         _osfile(crt_read_handle)     = FOPEN | FPIPE | FTEXT;
57         _textmode(crt_read_handle)   = __crt_lowio_text_mode::ansi;
58         _tm_unicode(crt_read_handle) = false;
59     }
60     __finally
61     {
62         __acrt_lowio_unlock_fh(crt_read_handle);
63     }
64     __endtry
65 
66     // Create the CRT write handle for the pipe:
67     int const crt_write_handle = _alloc_osfhnd();
68     if (crt_write_handle == -1)
69     {
70         _osfile(crt_read_handle) = 0;
71         errno = EMFILE;
72         _doserrno = 0;
73         CloseHandle(read_handle);
74         CloseHandle(write_handle);
75         return -1;
76     }
77 
78     __try
79     {
80         _osfile(crt_write_handle)     = FOPEN | FPIPE | FTEXT;
81         _textmode(crt_write_handle)   = __crt_lowio_text_mode::ansi;
82         _tm_unicode(crt_write_handle) = false;
83     }
84     __finally
85     {
86         __acrt_lowio_unlock_fh(crt_write_handle);
87     }
88     __endtry
89 
90     // Figure out which textmode the file gets:
91     int fmode = 0;
92     _ERRCHECK(_get_fmode(&fmode));
93 
94     // The pipe gets binary mode if (a) binary was requested or (b) the
95     // global default fmode was changed to binary.
96     if ((textmode & _O_BINARY) || ((textmode & _O_TEXT) == 0 && fmode == _O_BINARY))
97     {
98         _osfile(crt_read_handle)  &= ~FTEXT;
99         _osfile(crt_write_handle) &= ~FTEXT;
100     }
101 
102     if (textmode & _O_NOINHERIT)
103     {
104         _osfile(crt_read_handle)  |= FNOINHERIT;
105         _osfile(crt_write_handle) |= FNOINHERIT;
106     }
107 
108     __acrt_lowio_set_os_handle(crt_read_handle,  reinterpret_cast<intptr_t>(read_handle));
109     __acrt_lowio_set_os_handle(crt_write_handle, reinterpret_cast<intptr_t>(write_handle));
110 
111     phandles[0] = crt_read_handle;
112     phandles[1] = crt_write_handle;
113 
114     return 0;
115 }
116