http://bugs.winehq.org/show_bug.cgi?id=58745
--- Comment #5 from Eric Pouech eric.pouech@gmail.com --- (In reply to Robin Haberkorn from comment #4)
(In reply to Eric Pouech from comment #3)
to do a proper implementation, you'd need to somehow buffer the unix pipe stream (for eg peeknamedpipe to work) and that cannot be done on reader side (as several processes can peek from the same Unix pipe) this cannot be done on writer side as its a Unix process
But couldn't you just return TRUE when peeking 0 elements on the pipe? Even if you do not allow peeking more than 0 elements, this would already improve compatibility.
I agree that peek:ing 0 elements is easier to implement as it doesn't require buffering
one quick workaround is to fallback to ReadFile when PeekNamedPipe fails
in Wine (quick & dirty, didn't test it, could help diagnose if there are other problems): diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index 6c69a0ab88f..bb102c7e322 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -1568,8 +1568,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetNamedPipeInfo( HANDLE pipe, LPDWORD flags, LPDW /*********************************************************************** * PeekNamedPipe (kernelbase.@) */ -BOOL WINAPI DECLSPEC_HOTPATCH PeekNamedPipe( HANDLE pipe, LPVOID out_buffer, DWORD size, - LPDWORD read_size, LPDWORD avail, LPDWORD message ) +static BOOL PeekNamedPipe2( HANDLE pipe, LPVOID out_buffer, DWORD size, + LPDWORD read_size, LPDWORD avail, LPDWORD message ) { FILE_PIPE_PEEK_BUFFER local_buffer; FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer; @@ -1600,6 +1600,19 @@ BOOL WINAPI DECLSPEC_HOTPATCH PeekNamedPipe( HANDLE pipe, LPVOID out_buffer, DWO return !status; }
+BOOL WINAPI DECLSPEC_HOTPATCH PeekNamedPipe( HANDLE pipe, LPVOID out_buffer, DWORD size, + LPDWORD read_size, LPDWORD avail, LPDWORD message ) +{ + if (!PeekNamedPipe2(pipe, out_buffer, size, read_size, avail, message) && GetLastError() != ERROR_BROKEN_PIPE && + size == 0 && avail == NULL && message == NULL) + { + DWORD gle = GetLastError(); + if (ReadFile(pipe, out_buffer, 0, read_size, NULL)) return TRUE; + SetLastError(gle); + return FALSE; + } + return TRUE; +}
/*********************************************************************** * SetNamedPipeHandleState (kernelbase.@)
in glib: in the _S_IFIFO case, I'd do something like: (it's possible that PeekNamedPipe has been used to work around blocking reads on pipe:s) so perhaps a very simple hack would be to add after readable and writable have been set something like: if (GetFileType(pipe) == FILE_TYPE_PIPE && !channel->is_readable && !channel->is_writable) channel->is_readable = 1; (it's broken if the pipe is neither readable nor writable, but detects if the pipe handle is still valid, and doesn't use ReadFile in case of blocking reads) also not tested (or falling back to ReadFile)
neither options look nice to me and really look like dirty workarounds there are other ways to get handle attributes, but not from kernel32/kernelbase IIRC