note description: "Windows pipe, used in WEL_PROCESS_LAUNCHER" legal: "See notice at end of class." status: "See notice at end of class." class WEL_PIPE inherit EXCEPTIONS export {NONE} all end STRING_HANDLER create make, make_named, make_client feature {NONE} -- Initialization make -- Initialize pipe. local l_sec_attr: like security_attributes do create l_sec_attr.make l_sec_attr.set_inherit_handle (True) exists := cwin_create_pipe ($output_handle, $input_handle, l_sec_attr.item, 0) security_attributes := l_sec_attr end make_named (a_name: READABLE_STRING_GENERAL; a_direction: INTEGER) -- Create a named pipe with name `name' and 'a_direction' require non_void_name: a_name /= Void valid_name: not a_name.is_empty valid_direction: a_direction = inbound or a_direction = outbound or a_direction = duplex local l_handle: POINTER l_connected: BOOLEAN ws: WEL_STRING l_sec_attr: like security_attributes do create ws.make (format_pipe_name (a_name)) create l_sec_attr.make l_sec_attr.set_inherit_handle (True) security_attributes := l_sec_attr input_closed := True output_closed := True l_handle := cwin_create_named_pipe (ws.item, a_direction, 0, 255, max_pipe_buffer_length, max_pipe_buffer_length, 0, default_pointer) if l_handle /= invalid_handle_value then if a_direction = inbound or a_direction = duplex then output_handle := l_handle output_closed := False end if a_direction = outbound or a_direction = duplex then input_handle := l_handle input_closed := False end l_connected := cwin_connect_named_pipe (l_handle, default_pointer) check connected: l_connected end end end make_client (a_name: READABLE_STRING_GENERAL; a_direction: INTEGER; a_wait_server: BOOLEAN) -- Create a pipe connecting to named pipe with name `name' and 'a_direction' -- named pipe must have previously been created. -- if `a_wait_server' then execution halts until a compatible server has been created require non_void_name: a_name /= Void valid_name: not a_name.is_empty valid_direction: a_direction = inbound or a_direction = outbound or a_direction = duplex local l_handle: POINTER l_create_mode: INTEGER ws: WEL_STRING do create ws.make (format_pipe_name (a_name)) input_closed := True output_closed := True if a_wait_server then from until cwin_wait_piped_name (ws.item, 0) loop cwin_sleep (10) end end if cwin_wait_piped_name (ws.item, 0) then inspect a_direction when Inbound then l_create_mode := generic_read when Outbound then l_create_mode := generic_write when Duplex then l_create_mode := generic_read.bit_or (generic_write) end l_handle := cwin_create_file (ws.item, l_create_mode, 0x0, default_pointer, 0x4, 0x100, default_pointer) if l_handle /= invalid_handle_value then if a_direction = inbound or a_direction = duplex then output_handle := l_handle output_closed := False end if a_direction = outbound or a_direction = duplex then input_handle := l_handle input_closed := False end end end end feature -- Access inbound: INTEGER = 0x01 -- Named pipe will be written to outbound: INTEGER = 0x02 -- Named pipe will be listened to duplex: INTEGER = 0x03 -- Named pipe will be written and listened to feature -- Status Report exists: BOOLEAN -- Does pipe exist? output_handle: POINTER -- Pipe input handle input_handle: POINTER -- Pipe output handle input_closed: BOOLEAN -- Is pipe input closed? output_closed: BOOLEAN -- Is pipe output closed? last_write_successful: BOOLEAN -- Was last write operation successful? last_read_successful: BOOLEAN -- Was last read operation successful? last_string: detachable STRING_8 -- Last read string as a sequence of bytes encoded in a STRING_8 instance. last_written_bytes: INTEGER -- Last amount of bytes written to pipe last_read_bytes: INTEGER -- Last amount of bytes read from pipe feature -- Status setting close -- Close pipe. do if not output_closed then output_closed := cwin_close_handle (output_handle) end if not input_closed then if input_handle /= output_handle then input_closed := cwin_close_handle (input_handle) else input_closed := True end end ensure output_has_close: output_closed input_has_close: input_closed end close_output -- Close pipe output. require output_open: not output_closed do output_closed := cwin_close_handle (output_handle) end close_input -- Close pipe input. require input_open: not input_closed do input_closed := cwin_close_handle (input_handle) end feature -- Input put_string (a_string: STRING) -- Write `a_string' to pipe. -- Put number of written bytes in `last_written_bytes'. require non_void_string: a_string /= Void input_open: not input_closed local a_c_string: C_STRING do create a_c_string.make (a_string) last_write_successful := cwin_write_file (input_handle, a_c_string.item, a_string.count, $last_written_bytes, default_pointer) end feature -- Output read_stream (count: INTEGER) -- Read a string of at most `count' bound characters -- or until end of pipe is encountered. -- Put number of read bytes in `last_read_bytes'. -- Make result available in `last_string'. require valid_count: count > 0 output_open: not output_closed local l_str: C_STRING l_read_bytes: INTEGER do create l_str.make_empty (count) last_read_successful := cwin_read_file (output_handle, l_str.item, count, $l_read_bytes, default_pointer) last_read_bytes := l_read_bytes last_string := l_str.substring_8 (1, l_read_bytes) end feature {NONE} -- Implementation format_pipe_name (a_name: READABLE_STRING_GENERAL): STRING_32 -- require non_void_name: a_name /= Void valid_name: not a_name.is_empty do create Result.make_from_string_general ("\\.\pipe\") Result.append_string_general (a_name) ensure non_void_result: Result /= Void end security_attributes: detachable WEL_SECURITY_ATTRIBUTES -- Security attributes used to create pipe -- --| Note: This is not initialized in `make_client', otherwise it could be attached, more --| information needed! (Arno 01/14/2009) max_pipe_buffer_length: INTEGER = 4096 -- max length for pipe buffer generic_read: INTEGER = 0x80000000 -- generic read mode generic_write: INTEGER = 0x40000000 -- generic write mode feature {NONE} -- Externals cwin_create_named_pipe (a_name: POINTER; an_integer, an_integer2, an_integer3, an_integer4, an_integer5, an_integer6: INTEGER; a_pointer: POINTER): like output_handle -- SDK CreateNamedPiper external "C [macro <winbase.h>] (LPCTSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPSECURITY_ATTRIBUTES): HANDLE" alias "CreateNamedPipe" end cwin_create_file (a_name: POINTER; an_integer, an_integer2: INTEGER; a_pointer: POINTER; an_integer3, an_integer4: INTEGER; a_handle: POINTER): like input_handle -- SDK CreateFile external "C [macro <winbase.h>] (LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE): HANDLE" alias "CreateFile" end cwin_connect_named_pipe (a_handle: like input_handle; a_pointer: POINTER): BOOLEAN -- SDK ConnectNamedPipe external "C [macro <winbase.h>] (HANDLE, LPOVERLAPPED): BOOL" alias "ConnectNamedPipe" end cwin_wait_piped_name (a_name: POINTER; a_integer: INTEGER): BOOLEAN -- SDK WaitNamedPipe external "C [macro <winbase.h>] (LPCTSTR, DWORD): BOOL" alias "WaitNamedPipe" end cwin_read_file (a_handle: like output_handle; a_buffer: POINTER; an_integer:INTEGER; a_pointer1, a_pointer2: POINTER): BOOLEAN -- SDK ReadFile external "C [macro <winbase.h>] (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED): BOOL" alias "ReadFile" end cwin_write_file (a_handle: like input_handle; a_buffer: POINTER; an_integer:INTEGER; a_pointer1, a_pointer2: POINTER): BOOLEAN -- SDK WriteFile external "C [macro <winbase.h>] (HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED): BOOL" alias "WriteFile" end cwin_create_pipe (a_output_handle_pointer, a_input_handle_pointer, a_pointer: POINTER; a_size: INTEGER): BOOLEAN -- SDK CreatePipe external "C [macro <winbase.h>] (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD): BOOL" alias "CreatePipe" end cwin_close_handle (a_handle: POINTER): BOOLEAN -- SDK CloseHandle external "C [macro <winbase.h>] (HANDLE): BOOL" alias "CloseHandle" end cwin_sleep (a_milliseconds:INTEGER) -- SDK Sleep external "C [macro <winbase.h>] (DWORD)" alias "Sleep" end invalid_handle_value: POINTER external "C inline use <winbase.h>" alias "INVALID_HANDLE_VALUE" end note copyright: "Copyright (c) 1984-2020, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end