590 likes | 609 Views
Chapter 11. Win32 windows programming. The chapter introduces a subset of the Win 32 API functions. You can find out more by visiting Help in VC++ Or MSDN website There are predefined constants
E N D
Chapter 11 Win32 windows programming
The chapter introduces a subset of the Win 32 API functions • You can find out more by visiting Help in VC++ • Or MSDN website • There are predefined constants • Two sets of chars available: old 8-bit ASCII or 16 bit Unicode via writeConsoleA or writeConsoleW functions.
High/low level access available • High level access read or write to screen buffer • Low level functions can access mouse and kbd events
smallWin.inc • A file created by Irvine includes many constant definitions, text equates and function prototypes for win32 API programming • Included automatically in 32 bit asm
Some things in smallwin • The structures COORD and SYSTIME we looked at in chapter 10 • Definition for HANDLE (file handle) as a DWORD • Console handles are predefined • GetSTDHandle returns a handle to an input, output or error output
Win32 console functions • Text pg 424-425 • Functions like readConsoleInput, GetConsoleMode, GetSTDHandle, etc
readconsole • Example pg 431-432 • A convenient way to read text input and store in a buffer
ReadConsole : run Assembling: ReadConsole.asm Volume in drive C has no label. Volume Serial Number is 07D2-0208 Directory of C:\masm615\examples\CH11 01/20/2002 01:23 PM 614 ReadConsole.asm 11/26/2006 01:19 PM 4,177 ReadConsole.obj 11/26/2006 01:19 PM 16,364 ReadConsole.lst 11/26/2006 01:19 PM 33,352 ReadConsole.ilk 11/26/2006 01:19 PM 28,729 ReadConsole.exe 11/26/2006 01:19 PM 91,136 ReadConsole.pdb 11/26/2006 01:19 PM 6,948 ReadConsole.map 7 File(s) 181,320 bytes 0 Dir(s) 4,048,109,568 bytes free Press any key to continue . . . C:\MASM615\EXAMPLES\CH11>readconsole 123abc Dump of offset 00404000 ------------------------------- 31 32 33 61 62 63 0D 0A 00 00 00 00 00 00 00 00
ReadConsole : code INCLUDE Irvine32.inc BufSize = 80 .data buffer BYTE BufSize DUP(?),0,0 stdInHandle DWORD ? bytesRead DWORD ? .code main PROC ; Get handle to standard input INVOKE GetStdHandle, STD_INPUT_HANDLE mov stdInHandle,eax ; Wait for user input INVOKE ReadConsole, stdInHandle, ADDR buffer, BufSize - 2, ADDR bytesRead, 0 ; Display the buffer mov esi,OFFSET buffer mov ecx,16 ; 16 bytes mov ebx,TYPE buffer call DumpMem exit main ENDP END main
Running readconsole Running Application with parameters: W:\assembly\irvinecd\content\Examples\ch11 ReadConsole.exe xyz Dump of offset 00404000 ------------------------------- 78 79 7A 0D 0A 00 00 00 00 00 00 00 00 00 00 00 Press any key to continue . . .
Console1 pg 436 • Writing a string to console
Console1: run Assembling: console1.asm Volume in drive C has no label. Volume Serial Number is 07D2-0208 Directory of C:\masm615\examples\CH11 01/20/2002 01:40 PM 1,170 Console1.asm 11/26/2006 01:26 PM 4,255 console1.obj 11/26/2006 01:26 PM 17,927 console1.lst 11/26/2006 01:26 PM 14,536 console1.ilk 11/26/2006 01:26 PM 28,726 console1.exe 11/26/2006 01:26 PM 66,560 console1.pdb 11/26/2006 01:26 PM 1,610 console1.map 7 File(s) 134,784 bytes 0 Dir(s) 4,043,505,664 bytes free Press any key to continue . . . C:\MASM615\EXAMPLES\CH11>console1 -------------------- Console1.asm ----------------------- This program is a simple demonstration of console mode output, using the GetStdHandle and WriteConsole functions. --------------------------------------------------------- C:\MASM615\EXAMPLES\CH11>
Console1: code INCLUDE Irvine32.inc .data endl EQU <0dh,0ah> ; end of line sequence message \ BYTE "-------------------- Console1.asm -----------------------" BYTE endl,endl BYTE "This program is a simple demonstration of console ",endl BYTE "mode output, using the GetStdHandle and WriteConsole ",endl BYTE "functions.",endl BYTE "---------------------------------------------------------" BYTE endl,endl,endl messageSize = ($-message) consoleHandle DWORD 0 ; handle to standard output device bytesWritten DWORD ? ; number of bytes written .code main PROC ; Get the console output handle: INVOKE GetStdHandle, STD_OUTPUT_HANDLE mov consoleHandle,eax ; Write a string to the console: INVOKE WriteConsole, consoleHandle, ; console output handle ADDR message, ; string pointer messageSize, ; string length ADDR bytesWritten, ; returns num bytes written 0 ; not used INVOKE ExitProcess,0 main ENDP END main
Console2.asm positions cursor TITLE Console Demo #2 (Console2.asm) ; Demonstration of SetConsoleCursorPosition, ; GetConsoleCursorInfo, SetConsoleCursorInfo, ; SetConsoleScreenBufferSize, SetConsoleCursorPosition, ; SetConsoleTitle, and GetConsoleScreenBufferInfo. ; Last update: 9/28/01 INCLUDE SmallWin.inc .data outHandle DWORD ? scrSize COORD <120,50> xyPos COORD <20,5> consoleInfo CONSOLE_SCREEN_BUFFER_INFO <> cursorInfo CONSOLE_CURSOR_INFO <> titleStr BYTE "Console2 Demo Program",0
Console2 continued .code main PROC ; Get Console output handle. INVOKE GetStdHandle,STD_OUTPUT_HANDLE mov outHandle,eax ; Get console cursor information. INVOKE GetConsoleCursorInfo, outHandle, ADDR cursorInfo ; Set console cursor size to 75% mov cursorInfo.dwSize,75 INVOKE SetConsoleCursorInfo, outHandle, ADDR cursorInfo ; Set the screen buffer size. INVOKE SetConsoleScreenBufferSize, outHandle,scrSize
And a bit more ; Set the cursor position to (20,5). INVOKE SetConsoleCursorPosition, outHandle, xyPos ; Set the console window's title. INVOKE SetConsoleTitle, ADDR titleStr ; Get screen buffer & window size information. INVOKE GetConsoleScreenBufferInfo, outHandle, ADDR consoleInfo INVOKE ExitProcess,0 main ENDP END main
Wrapping api functions • Irvine32.Inc file contains wrappers for file i/o (also covered in chpt 5) • On pg 442 text provides source code for these wrapper functions: • createOutputFile • OpenFile • WriteToFile • ReadFromFile • CloseFile
ReadFile • Code on pg 445 • Just opens file created by writefile example and displays contents
Readfile: code INCLUDE Irvine32.inc .data buffer BYTE 500 DUP(?) bufSize = ($-buffer) errMsg BYTE "Cannot open file",0dh,0ah,0 filename BYTE "output.txt",0 fileHandle DWORD ? ; handle to output file byteCount DWORD ? ; number of bytes written .code main PROC INVOKE CreateFile, ADDR filename, GENERIC_READ, DO_NOT_SHARE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 mov fileHandle,eax ; save file handle .IF eax == INVALID_HANDLE_VALUE mov edx,OFFSET errMsg ; Display error message call WriteString jmp QuitNow .ENDIF
Readfile: code INVOKE ReadFile, ; write text to file fileHandle, ; file handle ADDR buffer, ; buffer pointer bufSize, ; number of bytes to write ADDR byteCount, ; number of bytes written 0 ; overlapped execution flag INVOKE CloseHandle, fileHandle mov esi,byteCount ; insert null terminator mov buffer[esi],0 ; into buffer mov edx,OFFSET buffer ; display the buffer call WriteString QuitNow: exit main ENDP END main
Writefile: run (no output) & file contents C:\MASM615\EXAMPLES\CH11>writefile C:\MASM615\EXAMPLES\CH11>type output.txt This text is written to an output file. • Each run will create file and put text in the file.
Writefile: code INCLUDE Irvine32.inc .data buffer BYTE "This text is written to an output file.",0dh,0ah;;;;here is text to write bufSize = ($-buffer) errMsg BYTE "Cannot create file",0dh,0ah,0 filename BYTE "output.txt",0 ;;;;name of output file fileHandle DWORD ? ; handle to output file bytesWritten DWORD ? ; number of bytes written .code main PROC INVOKE CreateFile, ADDR filename, GENERIC_WRITE, DO_NOT_SHARE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 mov fileHandle,eax ; save file handle .IF eax == INVALID_HANDLE_VALUE mov edx,OFFSET errMsg ; Display error message call WriteString jmp QuitNow .ENDIF INVOKE WriteFile, ; write text to file fileHandle, ; file handle ADDR buffer, ; buffer pointer bufSize, ; number of bytes to write ADDR bytesWritten, ; number of bytes written 0 ; overlapped execution flag INVOKE CloseHandle, fileHandle QuitNow: exit main ENDP END main
Appendfile.asm is similar, but appends text to an existing file TITLE Appending to a File (AppendFile.asm) ; This program appends text to an existing file. ; Last update: 1/30/02 INCLUDE Irvine32.inc .data buffer BYTE "This text is appended to an output file.",0dh,0ah bufSize = ($-buffer) errMsg BYTE "Cannot open file",0dh,0ah,0 filename BYTE "output.txt",0 fileHandle DWORD ? ; handle to output file bytesWritten DWORD ? ; number of bytes written
Appendfile.asm code .code main PROC INVOKE CreateFile, ADDR filename, GENERIC_WRITE, DO_NOT_SHARE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 mov fileHandle,eax ; save file handle .IF eax == INVALID_HANDLE_VALUE mov edx,OFFSET errMsg ; Display error message call WriteString jmp QuitNow .ENDIF ; Move the file pointer to the end of the file INVOKE SetFilePointer, fileHandle,0,0,FILE_END ; Append text to the file INVOKE WriteFile, fileHandle, ADDR buffer, bufSize, ADDR bytesWritten, 0 INVOKE CloseHandle, fileHandle QuitNow: exit main ENDP END main
Scroll: writes 50 lines (and console window scrolls) C:\MASM615\EXAMPLES\CH11>scroll 0: This line of text was written to the screen buffer 1: This line of text was written to the screen buffer 2: This line of text was written to the screen buffer 3: This line of text was written to the screen buffer 4: This line of text was written to the screen buffer 5: This line of text was written to the screen buffer 6: This line of text was written to the screen buffer 7: This line of text was written to the screen buffer 8: This line of text was written to the screen buffer 9: This line of text was written to the screen buffer 10: This line of text was written to the screen buffer 11: This line of text was written to the screen buffer 12: This line of text was written to the screen buffer 13: This line of text was written to the screen buffer 14: This line of text was written to the screen buffer 15: This line of text was written to the screen buffer 16: This line of text was written to the screen buffer 17: This line of text was written to the screen buffer 18: This line of text was written to the screen buffer 19: This line of text was written to the screen buffer 20: This line of text was written to the screen buffer 21: This line of text was written to the screen buffer 22: This line of text was written to the screen buffer 23: This line of text was written to the screen buffer 24: This line of text was written to the screen buffer 25: This line of text was written to the screen buffer 26: This line of text was written to the screen buffer 27: This line of text was written to the screen buffer 28: This line of text was written to the screen buffer 29: This line of text was written to the screen buffer
Scroll: example from text pg 449: write 50 lines of text to screen buffer INCLUDE Irvine32.inc .data message BYTE ": This line of text was written " BYTE "to the screen buffer",0dh,0ah messageSize = ($-message) outHandle DWORD 0 ; standard output handle bytesWritten DWORD ? ; number of bytes written lineNum DWORD 0 windowRect SMALL_RECT <0,0,60,11> ; left,top,right,bottom .code main PROC INVOKE GetStdHandle, STD_OUTPUT_HANDLE mov outHandle,eax .REPEAT mov eax,lineNum call WriteDec ; display each line number INVOKE WriteConsole, outHandle, ; console output handle ADDR message, ; string pointer messageSize, ; string length ADDR bytesWritten, ; returns num bytes written 0 ; not used inc lineNum ; next line number .UNTIL lineNum > 50
scroll ; Resize and reposition the console window relative to the ; screen buffer. INVOKE SetConsoleWindowInfo, outHandle, TRUE, ADDR windowRect call Readchar ; wait for a key call Clrscr ; clear the screen buffer call Readchar ; wait for a second key INVOKE ExitProcess,0 main ENDP END main
Write colors • Text pg 452 • Create an array of chars and an array of attributes (one for each char) • It calls writeconsoleattribute to put attributes on screenbuffer • It calls writeconsolecharacter to copy the characters to the same screen buffer cells
Writecolors INCLUDE Irvine32.inc .data outHandle DWORD ? cellsWritten DWORD ? xyPos COORD <10,2> ; Array of character codes: buffer BYTE 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 BYTE 16,17,18,19.20 BufSize = ($ - buffer) ; Array of attributes: attributes WORD 0Fh,0Eh,0Dh,0Ch,0Bh,0Ah,9,8,7,6 WORD 5,4,3,2,1,0F0h,0E0h,0D0h,0C0h,0B0h .code main PROC ; Get the Console standard output handle: INVOKE GetStdHandle,STD_OUTPUT_HANDLE mov outHandle,eax ; Set the colors from (10,2) to (30,2): INVOKE WriteConsoleOutputAttribute, outHandle, ADDR attributes, BufSize, xyPos, ADDR cellsWritten ; Write character codes 1 to 20: INVOKE WriteConsoleOutputCharacter, outHandle, ADDR buffer, BufSize, xyPos, ADDR cellsWritten call ReadChar exit main ENDP END main
TimingLoop just prints dots (slowly) INCLUDE Irvine32.inc TIME_LIMIT = 5000 .data startTime DWORD ? dot BYTE ".",0 .code main PROC INVOKE GetTickCount mov startTime,eax L1: mov edx,OFFSET dot ; display a dot call WriteString INVOKE Sleep,100 ; sleep for 100ms INVOKE GetTickCount sub eax,startTime ; check the elapsed time cmp eax,TIME_LIMIT jb L1 L2: exit main ENDP END main
Timingloop counts elapsed time before keypress C:\MASM615\EXAMPLES\CH11>timer 5000 milliseconds have elapsed
Timer.asm • Text pg 454-455 • A stopwatch program gets elapsed time between two calls to tickcount
timer INCLUDE Irvine32.inc TimerStart PROTO, pSavedTime: PTR DWORD TimerStop PROTO, pSavedTime: PTR DWORD .data msg BYTE " milliseconds have elapsed",0dh,0ah,0 timer1 DWORD ? .code main PROC INVOKE TimerStart, ; start the timer ADDR timer1 INVOKE Sleep, 5000 ; sleep for a while INVOKE TimerStop, ; EAX = elapsed milliseconds ADDR timer1 call WriteDec ; display elapsed time mov edx,OFFSET msg call WriteString exit main ENDP
timer ;-------------------------------------------------- TimerStart PROC uses eax esi, pSavedTime: PTR DWORD ; Starts a stopwatch timer. ; Receives: pointer to a variable that will hold ; the current time. ; Returns: nothing ;-------------------------------------------------- INVOKE GetTickCount mov esi,pSavedTime mov [esi],eax ret TimerStart ENDP ;-------------------------------------------------- TimerStop PROC uses esi, pSavedTime: PTR DWORD ; ; Stops the current stopwatch timer. ; Receives: pointer to a variable holding the ; saved time ; Returns: EAX = number of elapsed milliseconds ; Remarks: Accurate to about 10ms ;-------------------------------------------------- INVOKE GetTickCount mov esi,pSavedTime sub eax,[esi] ret TimerStop ENDP END main
winApp.asm text pg 461 • Display text in a pop up messagebox • About winMain • Every windows app needs a startup proc typically named WinMain which • Gets handle to current program • Loads program icon and mouse cursor • Creates main window • Show/update window • Loops to receive and dspatch messages
Winapp data area INCLUDE Irvine32.inc INCLUDE GraphWin.inc ;==================== DATA ======================= .data AppLoadMsgTitle BYTE "Application Loaded",0 AppLoadMsgText BYTE "This window displays when the WM_CREATE " BYTE "message is received",0 PopupTitle BYTE "Popup Window",0 PopupText BYTE "This window was activated by a " BYTE "WM_LBUTTONDOWN message",0 GreetTitle BYTE "Main Window Active",0 GreetText BYTE "This window is shown immediately after " BYTE "CreateWindow and UpdateWindow are called.",0 CloseMsg BYTE "WM_CLOSE message received",0 ErrorTitle BYTE "Error",0 WindowName BYTE "ASM Windows App",0 className BYTE "ASMWin",0 ; Define the Application's Window class structure. MainWin WNDCLASS <NULL,WinProc,NULL,NULL,NULL,NULL,NULL, \ COLOR_WINDOW,NULL,className> msg MSGStruct <> winRect RECT <> hMainWnd DWORD ? hInstance DWORD ?
Winapp code-4 slides ;=================== CODE ========================= .code WinMain PROC ; Get a handle to the current process. INVOKE GetModuleHandle, NULL mov hInstance, eax mov MainWin.hInstance, eax ; Load the program's icon and cursor. INVOKE LoadIcon, NULL, IDI_APPLICATION mov MainWin.hIcon, eax INVOKE LoadCursor, NULL, IDC_ARROW mov MainWin.hCursor, eax ; Register the window class. INVOKE RegisterClass, ADDR MainWin .IF eax == 0 call ErrorHandler jmp Exit_Program .ENDIF
Winapp code ; Create the application's main window. ; Returns a handle to the main window in EAX. INVOKE CreateWindowEx, 0, ADDR className, ADDR WindowName,MAIN_WINDOW_STYLE, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL mov hMainWnd,eax ; If CreateWindowEx failed, display a message & exit. .IF eax == 0 call ErrorHandler jmp Exit_Program .ENDIF ; Show and draw the window. INVOKE ShowWindow, hMainWnd, SW_SHOW INVOKE UpdateWindow, hMainWnd ; Display a greeting message. INVOKE MessageBox, hMainWnd, ADDR GreetText, ADDR GreetTitle, MB_OK ; Begin the program's message-handling loop. Message_Loop: ; Get next message from the queue. INVOKE GetMessage, ADDR msg, NULL,NULL,NULL ; Quit if no more messages. .IF eax == 0 jmp Exit_Program .ENDIF ; Relay the message to the program's WinProc. INVOKE DispatchMessage, ADDR msg jmp Message_Loop Exit_Program: INVOKE ExitProcess,0 WinMain ENDP
Winapp code ;----------------------------------------------------- WinProc PROC, hWnd:DWORD, localMsg:DWORD, wParam:DWORD, lParam:DWORD ; The application's message handler, which handles ; application-specific messages. All other messages ; are forwarded to the default Windows message ; handler. ;----------------------------------------------------- mov eax, localMsg .IF eax == WM_LBUTTONDOWN ; mouse button? INVOKE MessageBox, hWnd, ADDR PopupText, ADDR PopupTitle, MB_OK jmp WinProcExit .ELSEIF eax == WM_CREATE ; create window? INVOKE MessageBox, hWnd, ADDR AppLoadMsgText, ADDR AppLoadMsgTitle, MB_OK jmp WinProcExit .ELSEIF eax == WM_CLOSE ; close window? INVOKE MessageBox, hWnd, ADDR CloseMsg, ADDR WindowName, MB_OK INVOKE PostQuitMessage,0 jmp WinProcExit .ELSE ; other message? INVOKE DefWindowProc, hWnd, localMsg, wParam, lParam jmp WinProcExit .ENDIF WinProcExit: ret WinProc ENDP
Winapp code ;--------------------------------------------------- ErrorHandler PROC ; Display the appropriate system error message. ;--------------------------------------------------- .data pErrorMsg DWORD ? ; ptr to error message messageID DWORD ? .code INVOKE GetLastError ; Returns message ID in EAX mov messageID,eax ; Get the corresponding message string. INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \ FORMAT_MESSAGE_FROM_SYSTEM,NULL,messageID,NULL, ADDR pErrorMsg,NULL,NULL ; Display the error message. INVOKE MessageBox,NULL, pErrorMsg, ADDR ErrorTitle, MB_ICONERROR+MB_OK ; Free the error message string. INVOKE LocalFree, pErrorMsg ret ErrorHandler ENDP END WinMain
ReadFile • Code on pg 445 • Just opens file created by writefile example and displays contents