Flylib.com

Books Software

 
 
 

Data Exchange between Applications

Data Exchange between Applications

Q. Are there methods of organizing information exchange between running applications?

I have already described various methods of synchronization and using the shared memory. There is another interesting approach implemented in Windows anonymous (unnamed) pipes. [i] This approach is the most efficient for organizing information exchange with the console process generated by the current process. Assume that you need your console process started by some application (e.g., some string compiler) to output information to the edit window of the primary process instead of to console. The example of such application is shown in Listing 18.3.

Listing 18.3: Communications with console process through an anonymous pipe

image from book
// The PIPE.RC file
// Constant definitions
#define WS_SYSMENU   0x00080000L
#define WS_VISIBLE   0x100000000L
#define WS_TABSTOP   0x00010000L
#define WS_VSCROLL   0x00200000L
#define DS_3DLOOK    0x0004L
#define ES_LEFT      0x0000L
#define WS_CHILD     0x40000000L
#define WS_BORDER    0x00800000L
#define ES_MULTILINE 0x0004L
#define WS_VSCROLL   0x00200000L
#define WS_HSCROLL   0x00100000L


MENUP MENU
{

 POPUP "&Start the program"
 {
 MENUITEM "S&tart", 200
 MENUITEM "E&xit the program", 300
 }
}

// Dialog box definition
DIAL1 DIALOG 0, 0, 200, 140
STYLE WS_SYSMENU  DS_3DLOOK
CAPTION "Example of PIPE use"
FONT 8, "Arial"
{
CONTROL "", 101, "edit", ES_LEFT  ES_MULTILINE
 WS_VISIBLE  WS_BORDER WS_VSCROLL
 WS_HSCROLL, 24, 20, 128, 70
}

; The PIPE.INC file
; Constants
SW_HIDE               equ 0
SW_SHOWNORMAL         equ 1
STARTFJJSESHOWWINDOW  equ 1h
STARTF_USESTDHANDLES  equ 100h
STARTF_ADD = STARTFUSESHOWWINDOW + STARTF_USESTDHANDLES
; This message arrives when the window is closed
WM_CLOSE              equ 10h
WM_INITDIALOG         equ 110h
WM_COMMAND            equ 111h
EM_REPLACESEL         equ 0C2h
; Prototypes of external procedures
IFDEF MASM
       EXTERN ReadFile@20:NEAR
       EXTERN CloseHandle@4:NEAR
       EXTERN CreatePipe@16:NEAR
       EXTERN SetMenu@8:NEAR
       EXTERN LoadMenuA@8:NEAR
       EXTERN CreateProcessA@40:NEAR
       EXTERN ExitProcess@4:NEAR
       EXTERN GetModuleHandleA@4:NEAR
       EXTERN DialogBoxParamA@20:NEAR
       EXTERN EndDialog@8:NEAR
       EXTERN SendDlgItemMessageA@20:NEAR

ELSE
       EXTERN ReadFile:NEAR
       EXTERN CloseHandle:NEAR
       EXTERN CreatePipe:NEAR
       EXTERN TerminateProcess: NEAR
       EXTERN WaitForSingleObject:NEAR
       EXTERN SetMenu:NEAR
       EXTERN LoadMenuA:NEAR
       EXTERN CreateProcessA:NEAR
       EXTERN ExitProcess:NEAR
       EXTERN GetModuleHandleA:NEAR
       EXTERN DialogBoxParamA:NEAR
       EXTERN EndDialog:NEAR
       EXTERN SendDlgItemMessageA:NEAR
       ReadFile@20 = ReadFile
       CloseHandle@4 = CloseHandle
       CreatePipe@16 = CreatePipe
       TerminateProcess@8 = TerminateProcess
       WaitForSingleObject@8 = WaitForSingleObject
       SetMenu@8 = SetMenu
       LoadMenuA@8 = LoadMenuA
       CreateProcessA@40 = CreateProcessA
       ExitProcess@4 = ExitProcess
       GetModuleHandleA@4 = GetModuleHandleA
       DialogBoxParamA@20 = DialogBoxParamA
       EndDialog@8 = EndDialog
       SendDlgItemMessageA@20 = SendDlgItemMessageA
ENDIF
; Structures
; Message structure
MSGSTRUCT STRUC
       MSHWND    DD ?
       MSMESSAGE DD ?
       MSWPARAM  DD ?
       MSLPARAM  DD ?
       MSTIME    DD ?
       MSPT      DD ?
MSGSTRUCT ENDS
; Structure for CreateProcess
STARTUP STRUC
       cb              DD 0
       lpReserved      DD 0
       lpDesktop       DD 0

       lpTitle         DD 0
       dwX             DD 0
       dwY             DD 0
       dwXSize         DD 0
       dwYSize         DD 0
       dwXCountChars   DD 0
       dwYCountChars   DD 0
       dwFillAttribute DD 0
       dwFlags         DD 0
       wShowWindow     DW 0
       cbReserved2     DW 0
       lpReserved2     DD 0
       hStdInput       DD 0
       hStdOutput      DD 0
       hStdError       DD 0
STARTUP ENDS
; Structure - Information about the process
PROCINF STRUC
       hProcess        DD ?
       hThread         DD ?
       Idproc          DD ?
       idThr           DD ?
PROCINF ENDS

; The PIPE.ASM file
.586P
; Flat memory model
.MODEL FLAT, stdcall
include pipe.inc
; INCLUDELIB directives for the linker
IFDEF MASM
       includelib c:\masm32\lib\user32.lib
       includelib c:\masm32\lib\kernel32.lib
ELSE
       includelib c:\tasm32\lib\import32.lib
ENDIF
;---------------------------------------------
; Data segment
_DATA SEGMENT
       STRUP  STARTUP  <?>
       INF    PROCINF  <?>
       MSG    MSGSTRUCT  <?>
       HINST  DD 0 ; Application descriptor

       PA     DB "DIAL1", 0
       CMD    DB "c:\tasm32\bin\tlink32.exe", 0
       PMENU  DB "MENUP", 0
       HW     DD ?
       HR     DD ?
       BUFER  DB 3000 DUP(0)
       BYT    DD ?
_DATA ENDS
; Code segment
_TEXT SEGMENT
START:
; Get the application handle
       PUSH   0
       CALL   GetModuleHandleA@4
       MOV    [HINST], EAX
;--------------------------------
       PUSH   0
       PUSH   OFFSET WNDPROC
       PUSH   0
       PUSH   OFFSET PA
       PUSH   [HINST]
       CALL   DialogBoxParamA@20
       CMP    EAX, -1
       JNE    KOL
; Error message
KOL:
;-------------------------------
       PUSH  0
       CALL  ExitProcess@4
;-------------------------------
; Window procedure
; Position of parameters in the stack
; [BP+014H] ; LPARAM
; [BP+10H]  ; WAPARAM
; [BP+0CH]  ; MES
; [BP+8]    ; HWND
WNDPROC  PROC
       PUSH  EBP
       MOV   EBP, ESP
       PUSH  EBX
       PUSH  ESI
       PUSH  EDI
-----------------

       CMP   DWORD PTR [EBP+0CH], WM_CLOSE
       JNE   L1
L3:
       PUSH  0
       PUSH  DWORD PTR [EBP+08H]
       CALL  EndDialog@8
       JMP   FINISH
L1:
       CMP   DWORD PTR [EBP+0CH], WM_INITDIALOG
       JNE  L2
; Load the menu
       PUSH  OFFSET PMENU
       PUSH  [HINST]
       CALL  LoadMenuA@8
; Set the menu
       PUSH  EAX
       PUSH  DWORD PTR [EBP+08H]
       CALL  SetMenu@8
       JMP   FINISH
L2:
       CMP   DWORD PTR [EBP+0CH], WM_COMMAND
       JNE   FINISH
       CMP   WORD PTR [EBP+10H], 300
       JE    L3
       CMP   WORD PTR [EBP+10H], 200
       JNE   FINISH
; Startup here
; PIPE in the beginning
       PUSH  0
       PUSH  0
       PUSH  OFFSET HW
       PUSH  OFFSET HR
       CALL  CreatePipe@16
       MOV   EAX, HW
; Console application starts here
       MOV   STRUP.cb, 68
       MOV   STRUP.lpReserved, 0
       MOV   STRUP.lpDesktop, 0
       MOV   STRUP.lpTitle, 0
       MOV   STRUP.dwFlags, STARTF_ADD
       MOV   STRUP.cbReserved2, 0
       MOV   STRUP.lpReserved2, 0
       MOV   STRUP.wShowWindow, SW_HIDE ; Process window is invisible

       MOV   STRUP.hStdOutput, EAX
       MOV   STRUP.hStdError, EAX
;------------------------------
       PUSH  OFFSET INF
       PUSH  OFFSET STRUP
       PUSH  0
       PUSH  0
       PUSH  0
       PUSH  1 ; Inherit descriptors
       PUSH  0
       PUSH  0
       PUSH  OFFSET CMD
       PUSH  0
       CALL  CreateProcessA@40
; Read information
       PUSH  0
       PUSH  OFFSET BYT
       PUSH  3000
       PUSH  OFFSET BUFER
       PUSH  HR
       CALL  ReadFile@20
       PUSH  OFFSET BUFER
       PUSH  0
       PUSH  EM_REPLACESEL
       PUSH  101
       PUSH  DWORD PTR [EBP+08H]
       CALL  SendDlgItemMessageA@20
; Close the handle for writing
       PUSH  HW
       CALL  CloseHandle@4
; Close the handle for reading
       PUSH  HR
       CALL  CloseHandle@4
FINISH:
       MOV   EAX, 0
       POP   EDI
       POP   ESI
       POP   EBX
       POP   EBP
       RET   16
WNDPROC  ENDP
_TEXT ENDS
END START
image from book
 

The underlying idea of pipes is easy. When creating a process, it is possible to assign it the appropriate pipe descriptor as the input or the output descriptor. After that, it will be possible to organize information exchange between two processes using the WriteFile and ReadFile functions.

To translate the program presented in Listing 18.3, issue the following commands using MASM32:

ml /c /coff /DMASM pipe.asm
    rc pipe.rc
    link /subsystem:windows pipe.obj pipe.res

Issue the following commands using TASM32:

tasm32 /ml pipe.asm
    brcc32 pipe.rc
    tlink32 -aa pipe.obj,,,,,pipe.res

The program that you just considered requires some comments.

Starting a console application is a complicated task. Therefore, I won't dive into details. In the program in Listing 18.3, this procedure is practically no different from the one used in Chapter 15 for starting the WINWORD.EXE application. Consider, however, new features implemented in this program. Note that the EditBox control plays an interesting role here. This window element plays the role of the output console. To achieve this, set the ES_MULTILINE property, which displays the entire text sent to the window using the EM_REPLACESEL message. To read the information, a large buffer is used. Principally, it is possible to read the data in smaller portions, checking the number of read bytes as with files.

[i] So-called named pipes are implemented in Windows NT.