-------------------------------------------------- ------------------------------
Download all source programs of this section here
Overview
Windows introduces multi-process and multi-threaded mechanisms. At the same time, there is also a communication method between multiple processes, including clipboard, DDE, OLE, pipeline, etc. Compared to other communication means, the pipe has its own restrictions and characteristics, and the pipeline is actually a shared memory area, process Place the shared message there. And provide information exchange through some APIs.
The pipe is two heads, each of each head connected to a process or different code of the same process, with two types of pipes, anonymity and naming; according to the pipeline transfer direction, single Bidirectional. Depending on the characteristics of the pipeline, the named pipe is usually used between the processes running on different computers in a network environment (of course, in different processes of the same machine) it can be unidirectional or two-way; and anonymous pipeline only Can be used in the same computer, it can only be one-way. Anonymous pipe is actually achieved by a famous pipe for a specified name.
The benefit of using the pipe is that reading and writing It is used by the API for file operation, and the results are the same as the operational file. Even if you communicate with a naming pipe between different computers, you don't have to know the specific details of the network communication between networks.
We briefly introduce the use of named pipes.
The named pipe is established by the server-side process. The naming of the pipe must follow the specific naming method, that is, "//pipe/ pipe name", when used as a client, use "// computer name // PIPE / Pipe name "to open the use, the specific steps are as follows:
The server creates an instance of a named pipe through the function CreateNameDpipe and returns the handle for future operation, or creates a new instance for existing pipes.
The server listened to the connection request from the client, which is implemented through the connection function.
The client is waiting for the appearance of the pipe through function WaitNameDpipe. If the timeout value becomes zero, there is a pipe to use, then WaitNameDpipe will return True and call the server connection by calling CREATEFILE or CALLNAMEDPE.
At this point, the server will accept the client's connection request, successfully establish a connection, and the server connectNamedPipe returns true.
After establishing a connection, the client can use readfile and writefile to use the obtained pipe file handle, information exchange with each other.
When the client is ended with the server, the client calls Closefile, and the server then calls DisconnectNamedPipe. Finally, the function closehandle is called to turn off the pipe.
Since the program is used as the client, the program must know the name of the pipe, so more in the server / workstation program written in the same "author", you can't find a program to ask it to write the program. By named pipe communication. The use of anonymous pipeline is completely different. It allows you and completely unpacked process communication, the condition is that this process enters the output through the console "console", typical example is the old DOS application, they are running Windows They open a DOS window, and their input and output is console mode. There are also some standard Win32 programs that also use the console input and output. If you don't want to use the graphical interface in Win32, you can use allocconsole to get a console, then get the input or output handle via the GetStdHandle, and then use WriteConsole or Writefile to put the result Outputs to the console (usually an icon DOS window). Although these programs look like a DOS program, they are unclosed Win32 programs. If you use it under pure DOS, "The Program Must Run Under Windows!" Is displayed. One console has three handles: standard input, standard output, and standard error handles, standard input, standard output handle can be reordered, you can replace it with anonymous pipeline, so that you can take the other end of the pipe Use another process to receive or enter, and the control desk is not feeling different, just like the> or (Console Process Output) WRITE ----> Standard Output Equipment (Generally Screen) (Console Process Input) Read <---- Standard Input Device (Usually Keyboard) And use the pipe instead of: (As the console process of the sub-process) Write ----> Pipe 1 ----> Read (Parent Process) (As a console process in Pi Process) Read <----> Pipe 2 <---- Write (Parent Process) The steps to use anonymous pipes are as follows: Use CreatePipe to build two pipes, get the pipe handle, one is used to input, one is used to output Ready to perform the control station process, first get startupinfo using getStartupInfo Use the first pipe handle instead of HSTDINPUT in Startupinfo, the second instead of HSTDOTPUT, HSTDEROR, namely standard input, output, error handle Use the CreateProcess execution sub-process so that the sub-process input and output of this created are directed to the pipeline. The parent process reads the second pipe through the ReadFile to obtain the output of the child process, write the first pipeline through WriteFile to write the sub-process The parent process can check the sub-process without output via PeekNameDpipe. After the child process is over, you should close the two pipes through CloseHandle. Here are specific instructions and definitions: 1. Establish anonymous pipeline using the CreatePipe protogin as follows: BOOL CREATEPIPE Phandle Hreadpipe, // Address of Variable for Read Handle Phandle hwritepipe, // address of variable for Write Handle LPSecurity_attributes LPPIPEATTRIBUTES, / / POINTER TO SECURITY TRIBUTES DWORD nsize // number of bytes reserved for pipe); When the pipe is established, the HREADPIPE and HWRITEPIPE pointed to the structure can be used to read and write the pipeline. Of course, because the anonymous pipeline is unidirectional, you can only use one of the handles, the configuration of the security_attributes in the parameter must be filled, the definition is as follows: Typedef struct_security_attributes { DWORD NLENGTH: / / Define the length of this structure in bytes LPVOID LPSECURITYDESCRIPTOR; / / Point to control the security descriptor shared by this object, if this object will be assigned a default security description Bool binherithandle; // When a new process is created, it defines whether it returns whether it is inherited. The system API function is used. Security_attribute; 2. Fill in the StartupInfo structure for creating sub-processes, usually we can fill in a default structure with GetStartupInfo, then change the place where we get it, they are: HSTDINPUT - uses one of the pipes of HWRITEPIPE instead HSTDOUTPUT, HSTDERROR - replaced with another pipe of HREADPIPE DWFLAGS - Set to startf_usestdhandles or startf_useshowwindow indicates that the input / output handle and the wshowwindow field are valid. WshowWindow - Set to sw_hide, so that the window does not display when executed. After filling out, you can use createProcess to perform sub-processes, and the specific operation of the execution sub-process can refer to the previous tutorial "process control" 3. You can use the peeknamedpipe query sub-process in the program. The original shape is as follows: Bool peeknamedpipe Handle Hnamedpipe, // Handle To Pipe To Copy from LPVOID LPBUFFER, / / POINTER TO DATA BUFFER DWord NBuffersize, // size, in bytes, of data buffer LPDWORD LPBYTESREAD, / / POINTER TO NUMBER OF BYTES READ LPDWORD LPTOTALBYTESAVAIL, / / POINTER TO TOTAL NUMBER OF BYTES AVAILABLE LPDWORD LPBYTESLEFTTHISMESSAGE / / POINTER TO Unread bytes in this Message ); We can try to read the NBuffersize size data, then you can get how much data in the pipe by returning BytesRead, if not equal to zero, indicating that there is data to be read. 4. Read the pipeline with readfile and writefile, their parameters are exactly the same, the original shape is as follows: Readfile or Writefile Handle Hfile, // Handle of File To Read Use the pipe handle here LPVOID LPBUFFER, // Address of Buffer That Receives Data Buffer Address DWORD NNUMBEROFBYTESTOREAD, // Number of Bytes To Read and write bytes LPDWORD LPNUMBEROFBYTESREAD, // address of number of bytes read, actually read or written by number LPoverlapped LPoverlapped // Address of Structure for Data Use null here; 5. Close the four handles of the HREADPIPE and HWRITEPE for Pipelines and Pipelines with CloseHandle. The following example is given, this program is an extension of the previous tutorial "process control", if you feel strange to some API, please read the previous tutorial. Source program - assembly source file Debug EQU 0 ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> PROGRAMMED by Luo Yunbin, Bigluo@telekbird.com.cn ; Website: http://asm.yeah.net Luoyunbin's Win32 ASM Page (Luo Yunbin's Programming Park) ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ; Version Information ; Assembly test with example - Pipeline example ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> .386 .Model flat, stdcall Option Casemap: None; Case Sensitive ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Include data ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Folder Windows.inc INCLUDE User32.inc INCLUDE KERNEL32.INC INCLUDE COMCTL32.INC INCLUDE COMDLG32.INC INCLUDE GDI32.INC INCLUDELIB USER32.LIB IncludeLib kernel32.lib INCLUDELIB COMCTL32.LIB INCLUDELIB COMDLG32.LIB IncludeLib GDI32.LIB ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ; EQU data ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> ICO_MAIN EQU 1000 MENU_MAIN EQU 2000 IDM_EXEC EQU 2001 IDM_EXIT EQU 2002 F_Running EQU 0001H; Process is in operation ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Data segment ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> .DATA? StSTARTUP STARTUPINFO > Hinstance DD? HMENU DD? HwinMain DD? HWINTEXT DD? HFONT DD? HRUNTHREAD DD? HREAD1 DD? HWRITE1 DD? HREAD2 DD? HWRITE2 DD? SZBuffer DB 512 DUP (?) DWFLAG DD? ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> .DATA Sz Genexecute DB 'Connect MS- & DOS Way, 0 SZEXCUTEERROR DB 'Launches an application error! ', 0 SZCAPTION DB 'Pipeline sample program ... http://asm.yeah.net' ,0 SzclassName DB 'PIPEEXAMPLE', 0 SZDLNAME DB 'Riched32.dll', 0 Szclassnamered DB 'Richedit', 0 SZDLNAME DB 'Riched20.dll', 0 SzclassNameredit DB 'Richedit20a', 0 SZCommand DB 'c: /command.com' ,0 STLOGFONT LOGFONT <24, 0, 0, FW_NORMAL, / 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, / Clip_stroke_precis, default_quality, / DEFAULT_PITCH or FF_SWISS, "Fixedsys"> ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Code segment ; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> .code IF Debug INCLUDE Debug.asm ENDIF INCLUDE WIN.ASM *********************************************************** ***************; the thread for executing the program 1. Establish a process with CreateProcess ; 2. Waiting for the process of waiting for the process of WaitforsingleOject *********************************************************** ******************* _Runthread Proc Uses EBX ECX EDX ESI EDI, / DWParam: DWORD Local @stsecurity: Security_Attributes Local @dwexitcode Local @dwbytesread Local @strange: charrange OR dwflag, f_running *********************************************************** ******************* "Execute" menu is changed to "end" *********************************************************** ******************* Invoke EnableMenuItem, HMENU, IDM_EXEC, MF_GRAYED Invoke EnableMenuItem, HMENU, IDM_EXIT, MF_GRAYED *********************************************************** ******************* Establish a pipeline *********************************************************** ******************* Mov @ stsecurity.nlength, sizeof security_attributes, SIZEOF Security_ATINGTH, SIZEOF SECURITY_ATTRIBUTES Mov @ stsecurity.lpsecurityDescriptor, NULL Mov @ stsecurity.binherithandle, true Invoke CreatePipe, AddR Hread1, AddR HWrite1, Addr @ StSecurity, Null Invoke Cread2, AddR HWRITE2, ADDR @ StSecurity, NULL *********************************************************** ******************* ; Execute file, wait for the end to end if successful *********************************************************** ******************* Invoke GetStartupinfo, AddR StStartup Mov Eax, Hread1 Mov StStartup.hstdInput, EAX Mov Eax, HWRITE2 Mov StStartup.hstdoutput, EAX Mov StStartup.hstderror, EAX Mov StStartup.dwflags, Startf_useStdhandles or Startf_useshowWindow Mov StStartup.WShowWindow, SW_HIDE Invoke CreateProcess, NULL, AddR Szcommand, Null, NULL, / NULL, NORMAL_PRIORITY_CLASS, NULL, NULL, OFFSET StStartup, Offset StPROCINFO .IF EAX! = 0 .While true Invoke getExitcodeProcess, StProcinfo.hprocess, Addr @ dwexitcode.break .if @dwexitcode! = still_active Invoke Peeknamedpipe, Hread2, Addr Szbuffer, 511, Addr @ dwbytesread, NULL, NULL .IF @dwbytesread! = 0 Invoke RTLZERMEMORY, ADDR SZBUFFER, 512 Invoke Readfile, Hread2, AddR Szbuffer, @ dwbytesread, addr @ dwbytesread, null Mov @ strange.cpmin, -1 Mov @ strange.cpmax, -1 Invoke SendMessage, Hwintext, EM_EXSETSEL, 0, ADDR @StRange Invoke SendMessage, Hwintext, EM_REPLACESEL, FALSE, ADDR SZBUFFER Invoke SendMessage, Hwintext, EM_Scrollcaret, Null, Null Invoke SendMessage, Hwintext, WM_SETFONT, HFONT, 0 .endif .endw Invoke CloseHandle, StProcinfo.hprocess Invoke Closehandle, StProcinfo.hthread .lse Invoke Messagebox, Hwinmain, Addr SzexcuteError, NULL, MB_OK OR MB_ICONERROR .endif *********************************************************** ******************* Close the pipeline *********************************************************** ******************* Invoke Closehandle, Hread1 Invoke Closehandle, HWRITE1 Invoke Closehandle, Hread2 Invoke closehandle, hwrite2 *********************************************************** ******************* ; Change the "End" menu to "Execute" *********************************************************** ******************* Invoke EnableMenuItem, HMENU, IDM_EXEC, MF_ENABLED Invoke EnableMenuItem, HMENU, IDM_EXIT, MF_ENABLED Invoke EnableWindow, HWINTEXT, FALSE And dwflag, not f_running RET _RunthRead Endp *********************************************************** ******************* Window program *********************************************************** ******************* WNDMAINPROC PROC Uses EBX EDI ESI, / HWND: DWORD, WMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD MOV EAX, WMSG *********************************************************** ******************* .IF EAX == WM_CREATEMOV EAX, HWND Mov Hwinmain, EAX Call_init *********************************************************** ******************* .ELSEIF EAX == WM_SIZE Mov Edx, LParam MOV ECX, EDX SHR ECX, 16 And EDX, 0FFFFH Invoke MoveWindow, Hwintext, 0, 0, EDX, ECX, True Invoke Postmessage, Hwintext, WM_SIZE, WPARAM, LPARAM *********************************************************** ******************* .ELSEIF EAX == WM_Close Test dwflag, f_running .IF ZERO? Invoke DestroyWindow, HwinMain Invoke PostquitMessage, NULL .endif *********************************************************** ******************* .ELSEIF EAX == WM_COMMAND Mov Eax, WPARAM .IF AX == idm_exec *********************************************************** ******************* If the thread is established if not in the execution (dwflag is not set), execute the program in the thread If it is already in execution, use TerminateProcess to terminate execution *********************************************************** ******************* Test dwflag, f_running .IF ZERO? Invoke EnableWindow, HWINTEXT, TRUE Invoke setfocus, hwintext Invoke CreateThread, Null, Null, Offset _Runthread, / NULL, NULL, OFFSET HRUNTHREAD .lse Invoke TerminateProcess, StProcinfo.hprocess, -1 .endif .ELSEIF AX == IDM_EXIT Invoke DestroyWindow, HwinMain Invoke PostquitMessage, NULL .endif .lse Invoke DefWindowProc, Hwnd, WMSG, WPARAM, LPARAM RET .endif XOR EAX, EAX RET WNDMAINPROC ENDP *********************************************************** ******************* Procedure *********************************************************** ******************* Start: Call_winmain Invoke EXITPROCESS, NULL *********************************************************** ******************* _WinMain Proc Local @stwcmain: WNDCLASSEX Local @stmsg: msg Local @hrichedit Invoke loadLibrary, Offset szdllnamemov @ hrichedit, eax Invoke INITCOMMONCONTROLS Invoke getModuleHandle, NULL Mov Hinstance, EAX Invoke loadmenu, hinstance, menu_main Mov Hmenu, EAX **************** Registration window *************************************** ********** Invoke loadCursor, 0, IDC_ARROW Mov @ stwcmain.hcursor, EAX Mov @ stwcmain.cbsize, sizeof wndclassex Mov @ stwcmain.hiconsm, 0 Mov @ stwcmain.style, cs_hredraw or cs_vredraw Mov @ stwcmain.lpfnwndproc, Offset WNDMAINPROC Mov @ stwcmain.cbclsextra, 0 Mov @ stwcmain.cbwndextra, 0 Mov Eax, Hinstance Mov @ stwcmain.hinstance, EAX INVOKE LOADICON, HINSTANCE, ICO_MAIN Mov @ stwcmain.hicon, EAX Mov @ stwcmain.hbrbackground, color_btnface 1 Mov @ stwcmain.lpszclassname, offset szclassname Mov @ stwcmain.lpszMenuname, 0 Invoke registerclassex, addr @stwcmain **************** Establish an output window ************************************** ************ Invoke CreateWindowex, NULL, / Offset szclassname, offset szcaption, / WS_OVERLAPPEDWINDOW, / 0, 0, 680, 420, / NULL, HMENU, HINSTANCE, NULL Invoke ShowWindow, Hwinmain, SW_SHOWNORMAL Invoke UpdateWindow, HwinMain *********************************************************** ******************* .While true Invoke GetMsg, NULL, 0, 0 .break .if eax == 0 Invoke TranslateMsg, Addr @stmsg Invoke DispatchMessage, Addr @STMSG .endw Invoke freelibrary, @ hrichedit Invoke deleteObject, HFONT RET _WinMain ENDP *********************************************************** ******************* Input program *********************************************************** ******************* _INPUTPROC PROC Uses EBX EDI ESI, / HWnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD Local @szbuffer [4]: Byte Local @dwbyteswrite MOV Eax, umsg.if eax == wm_char Mov Eax, WPARAM Movzx Eax, Al Mov DWord PTR @ SZBuffer, EAX Test dwflag, f_running .IF! ZERO? Invoke Writefile, Hwrite1, Addr @ Szbuffer, 1, Addr @ dwbyteswrite, null .endif XOR EAX, EAX RET .endif Invoke GetWindowlong, HWnd, GWL_USERDATA Invoke CallWindowProc, EAX, HWND, UMSG, WPARAM, LPARAM RET _Inputproc ENDP *********************************************************** ******************* _Init proc *************** Establish an output RicheDit window ************************************** ***** Invoke CreateWindowex, WS_EX_CLIENTEDGE, OFFSET SZCLASSNAMEREDIT, / NULL, WS_CHILD or WS_VISIBLE or WS_VSCROLL OR WS_HSCROLL / OR ES_MULTILINE OR ES_AUTOHSCROLL OR ES_AUTOVSCROLL, / 0, 0, 0, 0, / Hwinmain, Null, Hinstance, Null Mov Hwintext, EAX *************** Set font *************************************** **************** Invoke CreateFontIndirect, Offset Stlogfont MOV HFONT, EAX Invoke SendMessage, Hwintext, WM_SETFONT, HFONT, 0 Invoke SendMessage, Hwintext, EM_SETREADONLY, TRUE, NULL Invoke setWindowlong, Hwintext, GWL_WndProc, Offset _inputproc Invoke SetWindowlong, Hwintext, GWL_USERDATA, EAX Invoke EnableWindow, HWINTEXT, FALSE Invoke _CenterWindow, HwinMain Invoke setfocus, hwintext RET _Init ENDP *********************************************************** ******************* End Start Program analysis and points In the program, I first established a RicheDit control to display the output of the sub-process, and simultaneize the Richedit subclass, intercept its keyboard input to send it to the child process. Invoke setWindowlong, Hwintext, GWL_WndProc, Offset _inputproc This statement refers to the _inputproc process, then in the _inputproc's WM_CHAR, I will type in the line, I set up two pipes first in the program, then execute C: /command.com, so Get a DOS command line process, then there is no output through the PeeknameDpipe detection sub-process in the loop, if any, read it via the readfile, in the Richedit. Be careful when running an example, you can perform almost all other programs in this "command.com", but do not perform programs such as UCDOS, PCTools, and programs that do not use standard input output (not used in DOS ">" Or "<" redirected procedure), because we used WS_HIDE when we loaded the process, the original command.com's window is hidden. If you perform this program, it means you lose The control of the sub-process, because they do not use standard input to receive the keyboard, you can't get them from the pipeline. Here you can also quote another usage of anonymous pipes. If you don't have command.com but similar to the arj.exe program, then you don't have to display its output into the Richedit, but in the program, So, you can write a Winarj, of course, you only need to write a window interface and the cooperation between Arj.exe.