Saturday, September 25, 2010

Pipeline


This talk will explore the channels and see what it is, to what purpose. To make it more lively and interesting, I will use the Edit control, how to change the background color and text color to illustrate this technique.

Theory:

Channel itself is the two side channels. You can use pipes between processes, data exchange within the same process, just as portable wireless telephones. One end of the pipe to the other, he can make use of communication channels and you had.

There are two channels, namely, the famous pipe and anonymous pipes. Anonymous pipe is a pipe has no name, that does not need to know when to use them in their names. The famous pipe on the contrary, before use must know its name.

Features can also be classified according to the pipeline, that is one-way or two-way. One-way pipeline, the data could only move along one direction, from one end of the flow of the other side, while two-way channels of data can be exchanged freely between both ends. Anonymous pipes are often famous for one-way pipe is usually a two-way. Famous pipe commonly used for multiple clients contact a server network environment.

This talk will discuss it in detail anonymous pipe. Anonymous pipe main purpose is as a parent and child process, child process, the link between the communication channel. Problems in dealing with the console, anonymous pipe is quite useful. Console application that is input and output using the console as a Win32 application. A console like a DOS window. But the console application is really, truly 32-bit application, it can use other graphics programs, like GUI function, but it happens to use the console Bale.

Console application there are three criteria used to handle input and output, which is the standard input, standard output and standard error handles. Standard input for reading from console, or access information to the console standard output is used to write or print information. Standard error could not redirect the output for reporting errors.

Console application can be obtained by calling the function GetStdHandle to handle these three. A graphical application without the console, if one calls GetStdHandle will return error; If you really want to use the console, you can call AllocConsole to allocate a new console to use, but when processing is complete, do not forget to call FreeConsole the release of the console.

Anonymous pipes used most of its function is redirect the child process standard input and standard output. Parent process can be a console or a graphics program, and the child process must be a console application. As we all know, the console application using the standard input and output handles. To redirect input and output, you have to point to pipe with one end of the handle to replace the standard handle. Console application does not know what we used to point at one end of the handle of any pipeline, which will handle the handle as a standard look. To use object-oriented terminology, this is a polymorphism. Because the child process without any change, so this method is very useful.

Console Application on another point to be grasped is that it was standard from which the handle. When a console application is created, the parent has two options: for the child process to create a new console or to the child process inherits its own console. If you use the latter, then the parent process itself must be a console application, or if a GUI application, it must first call AllocConsole assigned a console.

By calling CreatePipe to create an anonymous pipe, and its prototype is:

CreatePipe proto pReadHandle: DWORD, pWriteHandle: DWORD, pPipeAttributes: DWORD, nBufferSize: DWORD

pReadHandle double word pointer variable point to read end of pipe handle.
pWriteHandle double word pointer variable point to pipe write end of the handle
pPipeAttributes double word pointer variable, point SECUR99vY_ATTRIBUTES structure, can be used to decide whether to read and write handles inherited by child processes
nBufferSize proposed pipeline to leave the buffer size of the user, it is only suggested values can be NULL to use default values
If the function succeeds the return value is nonzero, and zero otherwise. After a successful call, you get two handles, a point to read the pipe end and the other pointing to the write end of pipe. Now I will take focus to redirect the output of sub-standard console application to your process steps required. Note that this method is different from my Borland's API reference on the case. Win32 API Reference on the assumption that the parent process is a console application, so the child process to inherit the standard handles it. In most cases, however, we need to redirect the output to the console application GUI application.

Create anonymous pipe to use CreatePipe, also do not forget to SECUR99vY_ATTRIBUTES structural members bInheritable set to TRUE, it can inherit the handle.

Now ready to create the process CreateProcess function of the parameters, it can only load the child console application. STARTUPINFO is an important structure, which determines the child process the appearance of the main window appears, it is our essential goal. Through this structure can hide the main window and the pipe handle is passed to the child process.

The following are the members must be filled:

cb STARTUPINFO the size of the structure
dwFlags binary flag, which determines the structure of which members of the force also determines the main window is displayed or hidden state. In our program, a combination of the use STARTF_USESHOWWINDOW and STARTF_USESTDHANDLES
hStdOutput and hStdError you want to use the child process standard output and standard error handles, for us, we will write end of pipe as a child process standard output and error. So when the child process standard output or standard error to send a message, it actually put the information passed to the parent process through a pipe
wShowWindow decision to show or hide the main window is. We do not want to show the child process's main window, so to the members buy into SW_HIDE
Call CreateProcess to create a child process, but after the success of the child process calls still is active. It was put into the memory but did not immediately run.

In the process of closing the parent write end of pipe is necessary. This is because the parent process does not use the pipeline to write the handle, and if there are two write a pipeline terminal, will not work, so we read out the data from the pipeline must be closed before the end of the pipeline to write. But not closed before calling CreateProcess, or pipe it broke. You should just return CreateProcess and reading the data written before the closure of the pipeline end.

Function ReadFile can now read side Reading in the pipeline data. By using ReadFile, can make the child process is running. It will begin and when it to standard output (actually the writing end of pipe) to write data, the data will be sent to the read end of pipe. It should be kept calling ReadFile until it returns 0, that is no longer read the data. Reading from the data channel you can make any deal, in our case it is displayed in the Edit control.

I remember reading after use closed pipe handle.

Code example:


.386
. Model flat, stdcall
option casemap: none
include masm32includewindows.inc
include masm32includeuser32.inc
include masm32includekernel32.inc
include masm32includegdi32.inc
includelib masm32libgdi32.lib
includelib masm32libuser32.lib
includelib masm32libkernel32.lib
WinMain PROTO: DWORD,: DWORD,: DWORD,: DWORD

. Const
IDR_MAINMENU equ 101; the ID of the main menu
IDM_ASSEMBLE equ 40001

. Data
ClassName db "PipeWinClass", 0
AppName db "One-way Pipe Example", 0 EditClass db "ED99v", 0
CreatePipeError db "Error during pipe creation", 0
CreateProcessError db "Error during process creation", 0
CommandLine db "ml / c / coff / Cp test.asm", 0

. Data?
hInstance HINSTANCE?
hwndEdit dd?

. Code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke WinMain, hInstance, NULL, NULL, SW_SHOWDEFAULT
invoke ExitProcess, eax

WinMain proc hInst: DWORD, hPrevInst: DWORD, CmdLine: DWORD, CmdShow: DWORD
LOCAL wc: WNDCLASSEX
LOCAL msg: MSG
LOCAL hwnd: HWND
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground, COLOR_APPWORKSPACE
mov wc.lpszMenuName, IDR_MAINMENU
mov wc.lpszClassName, OFFSET ClassName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, WS_EX_CLIENTEDGE, ADDR ClassName, ADDR AppName, WS_OVERLAPPEDWINDOW + WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 400,200, NULL, NULL, hInst, NULL
mov hwnd, eax
. While TRUE
invoke GetMessage, ADDR msg, NULL, 0,0
. BREAK. IF (! Eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
. Endw
mov eax, msg.wParam
ret
WinMain endp

WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
LOCAL rect: RECT
LOCAL hRead: DWORD
LOCAL hWrite: DWORD
LOCAL startupinfo: STARTUPINFO
LOCAL pinfo: PROCESS_INFORMATION
LOCAL buffer [1024]: byte
LOCAL bytesRead: DWORD
LOCAL hdc: DWORD
LOCAL sat: SECUR99vY_ATTRIBUTES
. If uMsg == WM_CREATE
invoke CreateWindowEx, NULL, addr EditClass, NULL, WS_CHILD + WS_VISIBLE + ES_MULTILINE + ES_AUTOHSCROLL + ES_AUTOVSCROLL, 0, 0, 0, 0, hWnd, NULL, hInstance, NULL
mov hwndEdit, eax
. Elseif uMsg == WM_CTLCOLORED99v
invoke SetTextColor, wParam, Yellow
invoke SetBkColor, wParam, Black
invoke GetStockObject, BLACK_BRUSH
ret
. Elseif uMsg == WM_SIZE
mov edx, lParam
mov ecx, edx
shr ecx, 16
and edx, 0ffffh
invoke MoveWindow, hwndEdit, 0,0, edx, ecx, TRUE
. Elseif uMsg == WM_COMMAND
. If lParam == 0
mov eax, wParam
. If ax == IDM_ASSEMBLE
mov sat.niLength, sizeof SECUR99vY_ATTRIBUTES
mov sat.lpSecurityDescriptor, NULL
mov sat.bInheritHandle, TRUE
invoke CreatePipe, addr hRead, addr hWrite, addr sat, NULL
. If eax == NULL
invoke MessageBox, hWnd, addr CreatePipeError, addr AppName, MB_ICnERROR + MB_OK
. Else
mov startupinfo.cb, sizeof STARTUPINFO
invoke GetStartupInfo, addr startupinfo
mov eax, hWrite
mov startupinfo.hStdOutput, eax
mov startupinfo.hStdError, eax
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES
mov startupinfo.wShowWindow, SW_HIDE
invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, addr startupinfo, addr pinfo
. If eax == NULL
invoke MessageBox, hWnd, addr CreateProcessError, addr AppName, MB_ICnERROR + MB_OK
. Else
invoke CloseHandle, hWrite
. While TRUE
invoke RtlZeroMemory, addr buffer, 1024
invoke ReadFile, hRead, addr buffer, 1023, addr bytesRead, NULL
. If eax == NULL
. Break
. Endif
invoke SendMessage, hwndEdit, EM_SETSEL, -1,0
invoke SendMessage, hwndEdit, EM_REPLACESEL, FALSE, addr buffer
. Endw
. Endif
invoke CloseHandle, hRead
. Endif
. Endif
. Endif
. Elseif uMsg == WM_DESTROY
invoke PostQuitMessage, NULL
. Else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret
. Endif
xor eax, eax
ret
WndProc endp
end start
Analysis:

This example calls ml.exe to compile a program called test.asm, and redirect the output to the client area ml.exe the Edit control. When the program is loaded, as usual to register the window class and create the main window. In the main window is created in the process of the first thing to do is to create the output for the display program ml.exe Edit control.

Now interesting things come, we will change this Edit control text color and background color. When the Edit control will repaint the client area, it will send WM_CTLCOLORED99v message parent window. Parameters wParam contains the controls for painting the client area of their device descriptor handle (HDC). We can use this mechanism to modify the characteristics of HDC.

. Elseif uMsg == WM_CTLCOLORED99v
invoke SetTextColor, wParam, Yellow
invoke SetTextColor, wParam, Black
invoke GetStockObject, BLACK_BRUSH
ret
SetTextColor the text color to yellow, the background color to black. Finally, we return to a black by calling GetStockObject and get a handle brush. Processing WM_CTLCOLORED99v must return a brush handle, because Windows will use the brush to repaint the background of Edit control. In this case, I hope the background is black, it returns the handle of a black brush.

Now when the user selects Assemble sub-menu, it will create an anonymous pipe.

. If ax == IDM_ASSEMBLE
mov sat.niLength, sizeof SECUR99vY_ATTRIBUTES
mov sat.lpSecurityDescriptor, NULL
mov sat.bInheritHandle, TRUE

Before calling CreatePipe must be filled SECUR99vY_ATTRIBUTES structure. If we do not care about security, you can fill in the lpSecurityDescriptor members of NULL. bInheritHandle you must be TRUE, so the pipeline can only be inherited by child processes handle.

invoke CreatePipe, addr hRead, addr hWrite, addr sat, NULL

After that, we call CreatePipe to create a pipeline, if successful, then the variable hRead and hWrite will be filled pipe corresponding read and write end of the handle end.

mov startupinfo.cb, sizeof STARTUPINFO
invoke GetStartupInfo, addr startupinfo
mov eax, hWrite
mov startupinfo.hStdOutput, eax
mov startupinfo.hStdError, eax
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW + STARTF_USESTDHANDLES
mov startupinfo.wShowWindow, SW_HIDE

The next step is to complete the structure of the STARTUPINFO. Call GetStartupinfo parent process with the default values to fill STARTUPINFO structure. If you want to both work in Windows9x and Windows NT, we need to call GetStartupInfo to fill STARTUPINFO structure. Call returns, you can modify the important members of the. Because we want the child process output to the parent process rather than the default standard output and standard error, so we hStdOutput and hStdError Ode to write into the pipe end of the handle. To hide the main window of the child process, must be assigned to member variables wShowWidow SW_HIDE. Finally, the members assigned to STARTF_USESHOWWINDOW and STARTF_USESTDHANDLES dwFlags to specify the members of the hStdOutput, hStdError and wShowWindow is effective.

invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, addr startupinfo, addr pinfo

Now call CreateProcess to create a child process. Note To make the pipe work, the parameter bInheritHandles must be set to TRUE. invoke CloseHandle, hWrite successfully created after the child process, the parent process must close the write end of pipe. We have to write end of the handle to pass through the structure STARTUPINFO a child process. If you do not shut down, then there are two write-side pipe, but this channel will not work. Therefore, it must create a child process, but after reading the data to close the handle.

. While TRUE
invoke RtlZeroMemory, addr buffer, 1024
invoke ReadFile, hRead, addr buffer, 1023, addr bytesRead, NULL
. If eax == NULL
. Break
. Endif
invoke SendMessage, hwndEdit, EM_SETSEL, -1,0
invoke SendMessage, hwndEdit, EM_REPLACESEL, FALSE, addr buffer
. Endw

Are now ready to process standard output from the child read the data. Until no more data, and that only when the ReadFile returns NULL out of circulation, or that it will be waiting for data. Before we call the ReadFile call RtlZeroMemory to clear the memory, and replaced with a pipe read handle file handles. Note that the maximum length of read data 1023 (sizeof (buffer) -1), because we need to accept the character into an Edit control that can handle ASCII string. When ReadFile returns, put the data passed to Edit control. However, this has a small problem, if you use SetWindowText API to write data to the Edit control, the new data will overwrite the old data already exists, and we want to add new data behind the existing data. To achieve this goal, first by sending a message wParam is -1 the EM_SETSEL, the Edit control the input focus moves to the end of the text; and then send a message to add data back EM_REPLACESEL.

invoke CloseHandle, hRead

When ReadFile returns NULL when out of loop on the read handle and close the pipeline.






Recommended links:



Operators tangle: 3G what is The best billing



Ten problems of answers interview sample



Comparison E-Mail Tools



The Surprise Move To Improve Alternative Network



3GPP converter



Seagate Layoffs Affected 1,100 People In China: Li Xudong Transferred To Retire



MP4 To Flash



"Nobunaga's Ambition 12 Innovations," 55-year Survival Of The Road Ota



View from the MIS MIS Success or failure of their own



Ghost 20 Little-known Practical Parameters



MP4 to 3GP



Recommend Mail Servers



Baidu, eNet, "Jurisprudence" has been criticized



Compare Browser Tools



My FAVORITE Anti-Virus Tools



No comments:

Post a Comment