📄 lion-tutorial21.htm
字号:
<b> invoke SetTextColor,wParam,Yellow</b>
<br>
<b> invoke SetBkColor,wParam,Black</b>
<br>
<b> invoke GetStockObject,BLACK_BRUSH</b>
<br>
<b> ret</b> <br>
<b> .elseif uMsg==WM_SIZE</b> <br>
<b> mov edx,lParam</b> <br>
<b> mov ecx,edx</b> <br>
<b> shr ecx,16</b> <br>
<b> and edx,0ffffh</b> <br>
<b> invoke MoveWindow,hwndEdit,0,0,edx,ecx,TRUE</b>
<br>
<b> .elseif uMsg==WM_COMMAND</b> <br>
<b> .if lParam==0</b> <br>
<b> mov
eax,wParam</b> <br>
<b> .if
ax==IDM_ASSEMBLE</b> <br>
<b>
mov sat.niLength,sizeof SECURITY_ATTRIBUTES</b> <br>
<b>
mov sat.lpSecurityDescriptor,NULL</b> <br>
<b>
mov sat.bInheritHandle,TRUE</b> <br>
<b>
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL</b> <br>
<b>
.if eax==NULL</b> <br>
<b>
invoke MessageBox, hWnd, addr CreatePipeError, addr AppName, MB_ICONERROR+
MB_OK</b> <br>
<b>
.else</b> <br>
<b>
mov startupinfo.cb,sizeof STARTUPINFO</b> <br>
<b>
invoke GetStartupInfo,addr startupinfo</b> <br>
<b>
mov eax, hWrite</b> <br>
<b>
mov startupinfo.hStdOutput,eax</b> <br>
<b>
mov startupinfo.hStdError,eax</b> <br>
<b>
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW+ STARTF_USESTDHANDLES</b> <br>
<b>
mov startupinfo.wShowWindow,SW_HIDE</b> <br>
<b>
invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL,
NULL, addr startupinfo, addr pinfo</b> <br>
<b>
.if eax==NULL</b> <br>
<b>
invoke MessageBox,hWnd,addr CreateProcessError,addr
AppName,MB_ICONERROR+MB_OK</b> <br>
<b>
.else</b> <br>
<b>
invoke CloseHandle,hWrite</b> <br>
<b>
.while TRUE</b> <br>
<b>
invoke RtlZeroMemory,addr buffer,1024</b> <br>
<b>
invoke ReadFile,hRead,addr buffer,1023,addr bytesRead,NULL</b> <br>
<b>
.if eax==NULL</b> <br>
<b>
.break</b> <br>
<b>
.endif</b> <br>
<b>
invoke SendMessage,hwndEdit,EM_SETSEL,-1,0</b> <br>
<b>
invoke SendMessage,hwndEdit,EM_REPLACESEL,FALSE,addr buffer</b> <br>
<b>
.endw</b> <br>
<b>
.endif</b> <br>
<b>
invoke CloseHandle,hRead</b> <br>
<b>
.endif</b> <br>
<b> .endif</b>
<br>
<b> .endif</b> <br>
<b> .elseif uMsg==WM_DESTROY</b> <br>
<b> invoke PostQuitMessage,NULL</b>
<br>
<b> .else</b> <br>
<b> invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret</b> <br>
<b> .endif</b> <br>
<b> xor eax,eax</b> <br>
<b> ret</b> <br>
<b>WndProc endp</b> <br>
<b>end start</b>
</blockquote>
<h3> Analysis:</h3>
The example will call ml.exe to assemble a file named test.asm and redirect the
output of ml.exe to the edit control in its client area. <br>
When the program is loaded, it registers the window class and creates the main
window as usual. The first thing it does during main window creation is to create
an edit control which will be used to display the output of ml.exe. <br>
Now the interesting part, we will change the text and background color of the
edit control. When an edit control is going to paint its client area, it sends
WM_CTLCOLOREDIT message to its parent. <br>
wParam contains the handle to the device context that the edit control will use
to write its own client area. We can use this opportunity to modify the characteristics
of the HDC.
<blockquote><b> .elseif uMsg==WM_CTLCOLOREDIT</b> <br>
<b> invoke SetTextColor,wParam,Yellow</b>
<br>
<b> invoke SetTextColor,wParam,Black</b>
<br>
<b> invoke GetStockObject,BLACK_BRUSH</b>
<br>
<b> ret</b></blockquote>
SetTextColor changes the text color to yellow. SetTextColor changes the background
color of the text to black. And lastly, we obtain the handle to the black brush
which we return to Windows. With WM_CTLCOLOREDIT message, you must return a handle
to a brush which Windows will use to paint the background of the edit control.
In our example, I want the background to be black so I return the handle to the
black brush to Windows. <br>
Now when the user selects Assemble menuitem, it creates an anonymous pipe.
<p><b> .if ax==IDM_ASSEMBLE</b>
<br>
<b>
mov sat.niLength,sizeof SECURITY_ATTRIBUTES</b> <br>
<b>
mov sat.lpSecurityDescriptor,NULL</b> <br>
<b>
mov sat.bInheritHandle,TRUE</b>
<p>Prior to calling CreatePipe, we must fill the SECURITY_ATTRIBUTES structure
first. Note that we can use NULL in lpSecurityDescriptor member if we don't
care about security. And the bInheritHandle member must be TRUE so that the
pipe handles are inheritable to the child process.
<p><b>
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL</b>
<p> After that, we call CreatePipe which, if successful, will fill hRead
and hWrite variables with the handles to read and write ends of the pipe respectively.
<p><b>
mov startupinfo.cb,sizeof STARTUPINFO</b> <br>
<b>
invoke GetStartupInfo,addr startupinfo</b> <br>
<b>
mov eax, hWrite</b> <br>
<b>
mov startupinfo.hStdOutput,eax</b> <br>
<b>
mov startupinfo.hStdError,eax</b> <br>
<b>
mov startupinfo.dwFlags, STARTF_USESHOWWINDOW+ STARTF_USESTDHANDLES</b> <br>
<b>
mov startupinfo.wShowWindow,SW_HIDE</b>
<p>Next we must fill the STARTUPINFO structure. We call GetStartupInfo to fill
the STARTUPINFO structure with default values of the parent process. You MUST
fill the STARTUPINFO structure with this call if you intend your code to work
under both win9x and NT. After GetStartupInfo call returns, you can modify the
members that are important. We copy the handle to the write end of the pipe
into hStdOutput and hStdError since we want the child process to use it instead
of the default standard output/error handles. We also want to hide the console
window of the child process, so we put SW_HIDE value into wShowWidow member.
And lastly, we must indicate that hStdOutput, hStdError and wShowWindow members
are valid and must be used by specifying the flags STARTF_USESHOWWINDOW and
STARTF_USESTDHANDLES in dwFlags member.
<p><b>
invoke CreateProcess, NULL, addr CommandLine, NULL, NULL, TRUE, NULL, NULL,
NULL, addr startupinfo, addr pinfo</b>
<p>We now create the child process with CreateProcess call. Note that the bInheritHandles
parameter must be set to TRUE for the pipe handle to work.
<p><b>
invoke CloseHandle,hWrite</b>
<p>After we successfully create the child process, we must close the write end
of the pipe. Remember that we passed the write handle to the child process via
STARTUPINFO structure. If we don't close the write handle from our end, there
will be two write ends. And that the pipe will not work. We must close the write
handle after CreateProcess but before we read data from the read end of the
pipe.
<p><b>
.while TRUE</b> <br>
<b>
invoke RtlZeroMemory,addr buffer,1024</b> <br>
<b>
invoke ReadFile,hRead,addr buffer,1023,addr bytesRead,NULL</b> <br>
<b>
.if eax==NULL</b> <br>
<b>
.break</b> <br>
<b>
.endif</b> <br>
<b>
invoke SendMessage,hwndEdit,EM_SETSEL,-1,0</b> <br>
<b>
invoke SendMessage,hwndEdit,EM_REPLACESEL,FALSE,addr buffer</b> <br>
<b>
.endw</b>
<p>Now we are ready to read the data from the standard output of the child process.
We will stay in an infinite loop until there are no more data left to read from
the pipe. We call RtlZeroMemory to fill the buffer with zeroes then call ReadFile,
passing the read handle of the pipe in place of a file handle. Note that we
only read a maximum of 1023 bytes since we need the data to be an ASCIIZ string
which we can pass on to the edit control. <br>
When ReadFile returns with the data in the buffer, we fill the data into the
edit control. However, there is a slight problem here. If we use SetWindowText
to put the data into the edit control, the new data will overwrite existing
data! We want the data to append to the end of the existing data. <br>
To achieve that goal, we first move the caret to the end of the text in the
edit control by sending EM_SETSEL message with wParam==-1. Next, we append the
data at that point with EM_REPLACESEL message.
<p><b>
invoke CloseHandle,hRead</b>
<p>When ReadFile returns NULL, we break out of the loop and close the read handle.
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -