管道 基于iczelion教程中的例子

; pipe.asm
; 测试程序test.exe会用标准输出/错误/输出句柄进行I/O,并在之后死循环,用来测试WriteFile()阻塞的情况

; 可以在WM_CREATE消息处理时用如invoke  SendDlgItemMessage,hWnd,EDIT_OUTPUT,EM_SETSEL,-1,0
;invoke  SendDlgItemMessage,hWnd,EDIT_OUTPUT,EM_REPLACESEL,FALSE,lParam的函数调用来向EDIT控件中添加输出,而
; 不用等EDIT控件先显示出来

include common.asm

EDIT_OUTPUT = 3
EDIT_INPUT = 4
BTN_INPUT = 5

CY_EDIT_INPUT = 25
CX_BTN_INPUT = 50
CY_BTN_INPUT = CY_EDIT_INPUT

BORDER = 3 ; 各控件间的间隔,包括与主窗口边框间的

WM_CHILDOUTPUT = WM_USER + 101H

.data
hInstance dd    ?
hWndMain dd     ?
szBuf   db      256 dup (?)

.code
ReadThreadProc proc param
        local   @cbReadWritten
        local   @szBuf[256]:byte
comment /*
To read from the pipe, a process uses the read handle in a call to the ReadFile function. ReadFile returns when one of the following is true: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs. 这三个条件即:有数据可读;读完指定字节数的数据;出错
*/        
        .while 1
                invoke  ReadFile,param,addr @szBuf,sizeof @szBuf -1, \
                                addr @cbReadWritten, NULL ; 可能阻塞
                .if eax ; 读到一些数据
                        mov     eax, @cbReadWritten
                        mov     @szBuf[eax], 0                 
                        invoke  SendMessage, hWndMain, WM_CHILDOUTPUT, 0, addr @szBuf
                .else ; 不加这个,会死循环,占用大量CPU时间
                        ;msgbox  ,CTXT("ReadFile() ERROR!")
                        ; 子进程结束后,ReadFile()会出错,last error为ERROR_BROKEN_PIPE
                        .break ;
                .endif
        .endw
        ret
ReadThreadProc endp

WriteThreadProc proc param
        local   @cbReadWritten
comment /*
When a process uses WriteFile to write to an anonymous pipe, the write operation is not completed until all bytes are written. If the pipe buffer is full before all bytes are written, WriteFile does not return until another process or thread uses ReadFile to make more buffer space available.
*/
        invoke  lstrlen, addr szBuf
        mov     ebx, eax
        invoke  WriteFile,param,addr szBuf, ebx, \
                                addr @cbReadWritten, NULL ;可能会阻塞
        ;.if !eax ; 子进程结束后,WriteFile()会出错, last error为ERROR_NO_DATA
        ;        msgbox  ,CTXT("WriteFile() ERROR!")
        ;.endif
 
        ret
WriteThreadProc endp

WndProc proc uses ebx esi edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    local   @startupinfo:STARTUPINFO
    local   @sat:SECURITY_ATTRIBUTES
        static  _pinfo, PROCESS_INFORMATION, <<>>
        static  _hRead,dword, INVALID_HANDLE_VALUE
        static  _hWrite,dword,INVALID_HANDLE_VALUE
        static  _hRead2,dword,INVALID_HANDLE_VALUE
        static  _hWrite2,dword,INVALID_HANDLE_VALUE
        static  _hWriteThread, dword, NULL
        
    .if uMsg==WM_COMMAND
        .if !lParam
            return 0
        .endif
                
                mov     eax, wParam
                mov     edx, eax
                and     eax, 0ffffh
                shr     edx, 16
                .if edx!=BN_CLICKED
                        return 0
                .endif
                .if eax!=BTN_INPUT
                        return 0  
                .endif
                
                .if _hWriteThread ; 已创建过写管道线程
                        push    eax
                        invoke  GetExitCodeThread,_hWriteThread, esp
                        pop     eax ;exit code
                        .if eax==STILL_ACTIVE ; 很可能被阻塞
                                msgbox hWndMain, CTXT("The pipe's buffer maybe is full now. Try it again later."),\
                                        CTXT("info")
                                return 0   ;
                        .else ; 已终止
                                invoke  CloseHandle,_hWriteThread
                                mov     _hWriteThread, NULL
                        .endif
                .endif
                
                invoke  GetDlgItemText,hWnd,EDIT_INPUT,addr szBuf, sizeof szBuf-2
                .if _hWrite!=INVALID_HANDLE_VALUE
                        mov     szBuf[eax], CR     ; 在输入框中什么也不输,则输入回车
                        mov     szBuf[eax+1], LF
                        mov     szBuf[eax+2], 0
                        push    eax
                        invoke  CreateThread, NULL, 0, offset WriteThreadProc, _hWrite, 0, esp
                        pop     edx ;Thread id
                        mov     _hWriteThread, eax
                .endif
        .elseif uMsg==WM_CHILDOUTPUT
                invoke  SendDlgItemMessage,hWnd,EDIT_OUTPUT,EM_SETSEL,-1,0 ;或-1,-1
                invoke  SendDlgItemMessage,hWnd,EDIT_OUTPUT,EM_REPLACESEL,FALSE,lParam
    .elseif uMsg==WM_CTLCOLOREDIT
comment /*    
An edit control that is not read-only or disabled sends the WM_CTLCOLOREDIT message to its parent window when the control is about to be drawn.
*/
        invoke  SetTextColor, wParam, Magenta ;洋红
        invoke  SetBkColor, wParam, White
        invoke  GetStockObject, WHITE_BRUSH
        ret  ;
        .elseif uMsg==WM_CTLCOLORSTATIC
comment /*
Read-only or disabled edit controls do not send the WM_CTLCOLOREDIT message; instead, they send the WM_CTLCOLORSTATIC message.
*/
                invoke  SetTextColor, wParam, Yellow
                invoke  SetBkColor, wParam, Black
                invoke  GetStockObject, BLACK_BRUSH
                ret
    .elseif uMsg==WM_SIZE
                invoke  GetDlgItem, hWnd, EDIT_OUTPUT
                mov     ebx, eax
                
        mov     eax, lParam
        mov     edx, eax
        and     eax, 0ffffh
        mov     esi, eax ;
        sub     eax, BORDER*2 ; 各控件间的间隔,包括与主窗口边框间的
        
        shr     edx, 16
        mov     edi, edx ;
        sub     edx, CY_EDIT_INPUT+BORDER*3
        invoke  MoveWindow,ebx,BORDER,BORDER, eax, edx, TRUE
            
        invoke  GetDlgItem, hWnd, EDIT_INPUT
        mov     ecx, edi
        sub     ecx, CY_EDIT_INPUT+BORDER
        mov     edx, esi
                sub     edx, CX_BTN_INPUT+BORDER*3
        invoke  MoveWindow,eax,BORDER,ecx,edx, CY_EDIT_INPUT, TRUE
        
        invoke  GetDlgItem, hWnd, BTN_INPUT
        mov     ecx, esi
        sub     ecx, CX_BTN_INPUT+BORDER
        mov     edx, edi
        sub     edx, CY_BTN_INPUT+BORDER
        invoke  MoveWindow,eax,ecx,edx,CX_BTN_INPUT,CY_BTN_INPUT,TRUE    
        .elseif uMsg==WM_CREATE
        invoke  CreateWindowEx,NULL, CTXT("edit"),NULL,\
                                WS_CHILD or WS_VISIBLE or ES_MULTILINE or WS_BORDER or \
                                ES_AUTOHSCROLL or ES_AUTOVSCROLL or ES_READONLY,\
                                0,0,0,0,hWnd,EDIT_OUTPUT,hInstance,NULL            
                invoke  CreateWindowEx,NULL, CTXT("edit"), CTXT("dir"),\
                                WS_CHILD or WS_VISIBLE or WS_BORDER or\
                                ES_AUTOHSCROLL or WS_TABSTOP,\
                                0,0,0,0,hWnd,EDIT_INPUT,hInstance,NULL    
                invoke  CreateWindowEx,NULL, CTXT("button"), CTXT("input"),\
                                WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_BORDER,\
                                0,0,0,0,hWnd,BTN_INPUT,hInstance,NULL    

                mov     @sat.nLength, sizeof @sat
                mov     @sat.lpSecurityDescriptor, NULL
                mov     @sat.bInheritHandle, TRUE
                ; 这一个管道用来向子进程传递信息,即由父进程写给子进程,父进程使用_hWrite
                invoke  CreatePipe, addr _hRead, addr _hWrite, addr @sat, NULL
                ; use the default buffer size
                
                .if !eax
                        invoke  MessageBox,hWnd,CTXT("Error during pipe creation"),\
                                        CTXT("One-way Pipe Example"),MB_ICONERROR or MB_OK
                        return 0
                .endif

                ; 这一个管道用来从子进程读取信息,即父进程读子进程写到管道的内容,父进程使用_hRead2
                invoke  CreatePipe, addr _hRead2, addr _hWrite2, addr @sat, NULL
                .if !eax
                        invoke  CloseHandle, _hRead   
                        mov     _hRead, INVALID_HANDLE_VALUE                                    
                        invoke  CloseHandle,_hWrite
                        mov     _hWrite, INVALID_HANDLE_VALUE  
                        invoke  MessageBox,hWnd,CTXT("Error during pipe creation"),\
                                        CTXT("One-way Pipe Example"),MB_ICONERROR or MB_OK
                        return 0
                .endif

                mov     @startupinfo.cb, sizeof @startupinfo
                invoke  GetStartupInfo, addr @startupinfo
                m2m     @startupinfo.hStdInput, _hRead
                m2m     @startupinfo.hStdOutput, _hWrite2
                m2m     @startupinfo.hStdError, _hWrite2
                mov     @startupinfo.dwFlags, STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW
                mov     @startupinfo.wShowWindow, SW_HIDE ;

                invoke  CreateProcess,NULL,CTXT("cmd"),\
                                NULL,NULL,TRUE,NULL,NULL,NULL,addr @startupinfo, addr _pinfo
                .if !eax
                        invoke  MessageBox,hWnd,CTXT("Error during process creation"),\
                                        CTXT("One-way Pipe Example"),MB_ICONERROR or MB_OK
                        invoke  CloseHandle, _hRead   
                        mov     _hRead, INVALID_HANDLE_VALUE                                    
                        invoke  CloseHandle,_hWrite
                        mov     _hWrite, INVALID_HANDLE_VALUE                 
                        invoke  CloseHandle,_hRead2
                        mov     _hRead2, INVALID_HANDLE_VALUE
                        invoke  CloseHandle, _hWrite2
                        mov     _hWrite2, INVALID_HANDLE_VALUE
                        return 0
                 .endif      
                 
                invoke  CloseHandle, _hRead                            
                mov     _hRead, INVALID_HANDLE_VALUE
                invoke  CloseHandle, _hWrite2
                mov     _hWrite2, INVALID_HANDLE_VALUE
                invoke CloseHandle, _pinfo.hThread
                mov    _pinfo.hThread, NULL
                 
                push    eax
                invoke  CreateThread, NULL, 0, offset ReadThreadProc, _hRead2, 0, esp
                pop     edx ;thread id
                invoke  CloseHandle, eax
        .elseif uMsg==WM_DESTROY
                .if _hWrite!=INVALID_HANDLE_VALUE
                        invoke  CloseHandle,_hWrite
                        mov     _hWrite, INVALID_HANDLE_VALUE
                .endif
                .if _hRead2!=INVALID_HANDLE_VALUE
                        invoke  CloseHandle,_hRead2
                        mov     _hRead2, INVALID_HANDLE_VALUE
                .endif
                
                .if _hWriteThread
                        invoke  CloseHandle, _hWriteThread
                        mov     _hWriteThread, NULL
                .endif
                
                .if _pinfo.hProcess  
                        push    eax
                        invoke  GetExitCodeProcess,_pinfo.hProcess, esp
                        pop     eax ;exit code
                        .if eax==STILL_ACTIVE
                                invoke  TerminateProcess,_pinfo.hProcess,0
                        .endif
                        invoke  CloseHandle,_pinfo.hProcess
                        mov     _pinfo.hProcess, NULL
                .endif
                
        invoke  PostQuitMessage, 0
    .else
        invoke  DefWindowProc,hWnd,uMsg,wParam,lParam        
        ret
    .endif
    return 0
WndProc endp

start   proc
    local   @wc:WNDCLASSEX
    local   @msg:MSG
    
    invoke  GetModuleHandle, NULL
    mov     hInstance,eax
    
    mov     @wc.cbSize, sizeof @wc
    mov     @wc.style, CS_HREDRAW or CS_VREDRAW
    mov     @wc.lpfnWndProc, offset WndProc
    mov     @wc.cbClsExtra, 0
    mov     @wc.cbWndExtra, 0
    m2m     @wc.hInstance, hInstance
    mov     @wc.hbrBackground, COLOR_APPWORKSPACE+1
    mov     @wc.lpszMenuName, NULL
    mov     @wc.lpszClassName, CTXT("PipeWinClass")
    invoke  LoadIcon, 0, IDI_APPLICATION
    mov     @wc.hIcon,eax
    mov     @wc.hIconSm,eax
    invoke  LoadCursor, 0, IDC_ARROW
    mov     @wc.hCursor,eax
    invoke  RegisterClassEx, addr @wc
    invoke  CreateWindowEx,WS_EX_CLIENTEDGE, CTXT("PipeWinClass"),CTXT("One-way Pipe Example"),\
                        WS_OVERLAPPEDWINDOW or WS_VISIBLE,CW_USEDEFAULT,\
                        CW_USEDEFAULT,400,200,NULL,NULL,\
                        hInstance, NULL
        mov     hWndMain, eax
        
    .while 1
        invoke  GetMessage, addr @msg,NULL,0,0
        .break  .if !eax
        
        invoke  IsDialogMessage, hWndMain, addr @msg
                .continue .if eax
                
        invoke  TranslateMessage, addr @msg
        invoke  DispatchMessage, addr @msg
    .endw
    invoke  ExitProcess, @msg.wParam
start   endp


        end start

---------------------------------------------------------------

; test.asm

include common.asm

.code
start   proc
        local   @szBuf[8]:byte
        
        invoke  SetConsoleTitle, CTXT("CONSOLE DEMO")
        invoke  _StdOut, CTXT("HELLO, CONSOLE!", CR, LF)
        invoke  _StdErr, CTXT("你好!", CR, LF)
        
        invoke  _StdIn, addr @szBuf, sizeof @szBuf
        invoke  _StdOut, addr @szBuf
        
        invoke  _GetFileRootPathName, CTXT("j:abc.txt"), addr @szBuf
        invoke  _StdOut, addr @szBuf
        
        .while 1
                invoke  Sleep, 3000
        .endw
        
        xor     eax, eax
        ret
start   endp
        
        
        end     start
       


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值