/*** *pipe.c - create a pipe * * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved. * *Purpose: * defines _pipe() - creates a pipe (i.e., an I/O channel for interprocess * communication) * *Revision History: * 06-20-89 PHG Module created, based on asm version * 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include * and fixed copyright. Also, cleaned up the * formatting a bit. * 04-03-90 GJF Now _CALLTYPE1. * 07-24-90 SBM Removed '32' from API names * 08-14-90 SBM Compiles cleanly with -W3 * 10-01-90 GJF New-style function declarator. * 12-04-90 SRW Changed to include instead of * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. * 01-18-91 GJF ANSI naming. * 02-18-91 SRW Added _WIN32_ implementation [_WIN32_] * 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] * 03-13-91 SRW Fixed _pipe so it works [_WIN32_] * 03-18-91 SRW Fixed _pipe NtCreatePipe handles are inherited [_WIN32_] * 04-06-92 SRW Pay attention to _O_NOINHERIT flag in oflag parameter * 01-10-93 GJF Fixed bug in checking for _O_BINARY (inadvertently * introduced by SRW's change above). * 04-06-93 SKS Replace _CRTAPI* with __cdecl * 09-06-94 CFW Remove Cruiser support. * 12-03-94 SKS Clean up OS/2 references * 06-12-95 GJF Replaced _osfile[] with _osfile() (macro referencing * field in ioinfo struct). * 05-16-96 GJF Set the FNOINHERIT bit (new) if appropriate. Also, * detab-ed and cleaned up the formatting a bit. * 05-31-96 SKS Fix expression error in GJF's most recent check-in * 12-29-97 GJF Exception-safe locking. * 02-07-98 GJF Changes for Win64: arg type of _set_osfhnd is now * intptr_t. * 10-16-00 PML Avoid deadlock in _alloc_osfhnd (vs7#173087). * *******************************************************************************/ #include #include #include #include #include #include #include #include #include /*** *int _pipe(phandles, psize, textmode) - open a pipe * *Purpose: * Checks if the given handle is associated with a character device * (terminal, console, printer, serial port) * * Multi-thread notes: No locking is performed or deemed necessary. The * handles returned by DOSCREATEPIPE are newly opened and, therefore, * should not be referenced by any thread until after the _pipe call is * complete. The function is not protected from some thread of the caller * doing, say, output to a previously invalid handle that becomes one of * the pipe handles. However, any such program is doomed anyway and * protecting the _pipe function such a case would be of little value. * *Entry: * int phandle[2] - array to hold returned read (phandle[0]) and write * (phandle[1]) handles * * unsigned psize - amount of memory, in bytes, to ask o.s. to reserve * for the pipe * * int textmode - _O_TEXT, _O_BINARY, _O_NOINHERIT, or 0 (use default) * *Exit: * returns 0 if successful * returns -1 if an error occurs in which case, errno is set to: * *Exceptions: * *******************************************************************************/ int __cdecl _pipe ( int phandles[2], unsigned psize, int textmode ) { ULONG dosretval; /* o.s. return value */ int handle0, handle1; HANDLE ReadHandle, WriteHandle; SECURITY_ATTRIBUTES SecurityAttributes; phandles[0] = phandles[1] = -1; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; if (textmode & _O_NOINHERIT) { SecurityAttributes.bInheritHandle = FALSE; } else { SecurityAttributes.bInheritHandle = TRUE; } if (!CreatePipe(&ReadHandle, &WriteHandle, &SecurityAttributes, psize)) { /* o.s. error */ dosretval = GetLastError(); _dosmaperr(dosretval); return -1; } /* now we must allocate C Runtime handles for Read and Write handles */ if ((handle0 = _alloc_osfhnd()) != -1) { #ifdef _MT __try { #endif /* _MT */ _osfile(handle0) = (char)(FOPEN | FPIPE | FTEXT); #ifdef _MT } __finally { _unlock_fh( handle0 ); } #endif /* _MT */ if ((handle1 = _alloc_osfhnd()) != -1) { #ifdef _MT __try { #endif /* _MT */ _osfile(handle1) = (char)(FOPEN | FPIPE | FTEXT); #ifdef _MT } __finally { if ( handle1 != -1 ) _unlock_fh( handle1 ); } #endif /* _MT */ if ( (textmode & _O_BINARY) || (((textmode & _O_TEXT) == 0) && (_fmode == _O_BINARY)) ) { /* binary mode */ _osfile(handle0) &= ~FTEXT; _osfile(handle1) &= ~FTEXT; } if ( textmode & _O_NOINHERIT ) { _osfile(handle0) |= FNOINHERIT; _osfile(handle1) |= FNOINHERIT; } _set_osfhnd(handle0, (intptr_t)ReadHandle); _set_osfhnd(handle1, (intptr_t)WriteHandle); errno = 0; } else { _osfile(handle0) = 0; errno = EMFILE; /* too many files */ } } else { errno = EMFILE; /* too many files */ } /* If error occurred, close Win32 handles and return -1 */ if (errno != 0) { CloseHandle(ReadHandle); CloseHandle(WriteHandle); _doserrno = 0; /* not an o.s. error */ return -1; } phandles[0] = handle0; phandles[1] = handle1; return 0; }