Każdy plik wykonywalny w momencie uruchomienia tworzy tzn. Proces . W odróżnieniu od pojęcia Programu, który jest po prostu plikiem wykonywalnym na dysku, proces ma charakter dynamiczny. Jego stan zmienia się w czasie. Zmianie ulegają między innymi:
Tworzymy program uruchamiający proces programu Kalkulator i kończący działanie tego procesu poprzez wciśnięcie odpowiedniego przycisku w oknie. Na początku definiujemy standardowo typ instrukcji procesora, określamy model pamięci jako płaski z wywołaniem procedur typu STDCALL. Dołączamy także odpowiednie biblioteki: user32.lib i kernel32.lib:
.586 ;typ instrukcji procesora
.MODEL
FLAT,STDCALL
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
Następnie określamy stałe potrzebne do użycia kontrolek w programie:
IDC_BTN1 EQU 101
IDC_BTN2 EQU 102
Następnie stałe związane z komunikatami obsługiwanymi w oknie:
STARTF_USESHOWWINDOW EQU 1h
SW_SHOWMINIMIZED EQU 2
WM_INITDIALOG EQU 110h
WM_CLOSE EQU 10h
WM_COMMAND EQU 111h
Stała STARTF_USESHOWWINDOW włącza pole dwShowWindow. Jest to jedno z pól struktury STARTUP, którą musimy przekazać jako parametr inicjujący funkcji CreateProcessA@40 inicjującej proces. Funkcja ta zostanie opisana poniżej. Stała SW_SHOWMINIMIZED aktywuje okno i wyświetla je w trybie zminimalizowanym, chyba że okno nie posiada takiej funkcji. Następnie definiujemy potrzebne funkcje API:
EXTERN TerminateProcess@8:NEAR
EXTERN CreateProcessA@40:NEAR
EXTERN EndDialog@8:NEAR
EXTERN GetModuleHandleA@4:NEAR
EXTERN DialogBoxParamA@20:NEAR
EXTERN ExitProcess@4:NEAR
Nowymi w porównaniu do poprzednich przykładów są tu funkcje: TerminateProcess@8 i CreateProcessA@40 .CreateProcessA@40 tworzy proces, przyjmując jednocześnie podczas wywołania 10 parametrów. Postać funkcji CreateProcessA@40 w API przedstawiona jest na poniższym listingu:
BOOL WINAPI CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
Pierwszy parametr - lpApplicationName to nazwa uruchomionego programu. Następnie parametr lpCommandLine określa tekst startowego wiersza poleceń, jeśli parametr 1 jest różny od null. Parametr 3 i 4 - lpProcessAttributes i lpThreadAttributes to atrybuty dostępu do procesu najczęściej równe 0. Piąty parametr jeśli otrzyma wartość zerową to wygenerowany proces nie dziedziczy deskryptorów procesu generującego. Jeśli jednak wartość ta jest niezerowa to będzie dziedziczył deskryptory. Szósty parametr pozwala na zmianę właściwości generowanego procesu. Jeżeli nadana zostanie mu wartość zerowa, to wtedy proces otrzymuje domyślne właściwości. Siódmy parametr jest wskaźnikiem na bufor przechowujący parametry środowiska. Wartość zerowa oznacza, iż dziedziczy owe parametry od środowiska generującego go procesu. Ósmy parametr określa aktualny dysk i katalog generowanego procesu. Wartość 0 powoduje że proces dziedziczy aktualny napęd i katalog generującego procesu. Dziewiąty parametr jest wskaźnikiem na strukturę przechowującą informacje o oknie tworzonego procesu. Struktura zostanie przedstawiona poniżej. 10 parametr to również wskaźnik na strukturę, która jest wypełniona po uruchomieniu aplikacji. Struktura przekazywana w 9 parametrze wygląda następująco:
STARTUP STRUC
cb DD 0 ;rozmiar struktury w bajtach
lpReserved DD 0 ;zarezerwowane, musi być zerem
lpDesktop DD 0 ;nazwa pulpitu
lpTitle DD 0 ;tytuł okna dla aplikacji konsolowych.
dwX DD 0 ;współrzędna X lewego górnego roku okna
dwY DD 0 ;współrzędna Y lewego górnego roku okna
dwXSize DD 0 ;szerokość okna
dwYSize DD 0 ;wysokość okna
dwXCountChars DD 0 ;rozmiar bufora konsoli (współrzędne X)
dwYCountChars DD 0 ;rozmiar bufora konsoli (współrzędne Y)
dwFillAttribute DD 0 ;początkowe kolory tekstu dla aplikacji konsolowych
dwFlags DD 0 ;znaczniki wartości pól
wShowWindow DW 0 ;definiuje tryb wyświetlania okna
cbReserved2 DW 0 ;zarezerwowane
lpReserved2 DD 0
hStdInput DD 0 ;deskryptor wejścia dla konsoli
hStdOutput DD 0 ;deskryptor wyjścia dla konsoli
hStdError DD 0 ;deskryptor wyświetlania komunikatów o błędach
STARTUP ENDS
Struktura podawana w dziesiątym parametrze funkcji CreateProcessA@40 - PROCINF przedstawia się następująco:
PROCINF STRUC
hProcess DD ? ;deskryptor utworzonego procesu
hThread DD ? ;deskryptor głównego wątku utworzonego procesu
idProc DD ? ;identyfikator nowego procesu
idThr DD ? ;identyfikator głównego wątku nowego procesu
PROCINF ENDS
Funkcja TerminateProcess@8 powoduje natomiast zakończenie uruchomionego procesu. Sekcja danych naszego programu wygląda następująco:
.DATA
HINST DD ?
PA DB 'IDD_DLG1', 0 ;nazwa dialogu
PATH DB "C:\WINDOWS\system32\calc.exe", 0
STRUP STARTUP <?>
INF PROCINF <?>
Zmienna PATH to ścieżka do programu który uruchomimy w procesie. Zmienne STRUP i INF określają odpowiednio struktury STARTUP i PROCINF. Początkowy fragment sekcji kodu programu wygląda podobnie jak w przykładach poprzednich. W procedurze obsługi okna przechodzimy w zależności od otrzymanego komunikatu do odpowiedniej sekcji jego obsługi:
.CODE
START:
PUSH 0
CALL GetModuleHandleA@4
MOV [HINST],EAX
PUSH 0
PUSH OFFSET WNDPROC
PUSH 0
PUSH OFFSET PA
PUSH [HINST]
CALL DialogBoxParamA@20
PUSH 0
CALL ExitProcess@4
;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
CMP DWORD PTR [EBP + 0CH],WM_CLOSE;komunikat związany ze zniszczeniem okna
JNE WYKONANIE
JMP KONCZ
WYKONANIE:
CMP DWORD PTR [EBP + 0CH],WM_COMMAND;komunikat związany z kontrolkami
JNE FINISH
CMP WORD PTR [EBP + 10H],IDC_BTN1 ;czy uruchamiamy proces?
JNE CZYZAKONCZYC
JMP URUCHOM
KONCZ:
PUSH 0
PUSH DWORD PTR [EBP+ 08H]
CALL EndDialog@8
JMP FINISH
URUCHOM:
W sekcji odpowiedzialnej za uruchomienie nowego procesu, poprzez wciśnięcie odpowiedniego przycisku przez użytkownika, wypełniamy strukturę STRUP i tworzymy nowy proces:
.CODE
START:
PUSH 0
CALL GetModuleHandleA@4
MOV [HINST],EAX
PUSH 0
PUSH OFFSET WNDPROC
PUSH 0
PUSH OFFSET PA
PUSH [HINST]
CALL DialogBoxParamA@20
PUSH 0
CALL ExitProcess@4
;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
CMP DWORD PTR [EBP + 0CH],WM_CLOSE;komunikat związany ze zniszczeniem okna
JNE WYKONANIE
JMP KONCZ
WYKONANIE:
CMP DWORD PTR [EBP + 0CH],WM_COMMAND;komunikat związany z kontrolkami
JNE FINISH
CMP WORD PTR [EBP + 10H],IDC_BTN1 ;czy uruchamiamy proces?
JNE CZYZAKONCZYC
JMP URUCHOM
KONCZ:
PUSH 0
PUSH DWORD PTR [EBP+ 08H]
CALL EndDialog@8
JMP FINISH
URUCHOM:
MOV STRUP.cb,68
MOV STRUP.lpReserved,0
MOV STRUP.lpDesktop,0
MOV STRUP.lpTitle,0
MOV STRUP.dwFlags,STARTF_USESHOWWINDOW
MOV STRUP.cbReserved2,0
MOV STRUP.lpReserved2,0
MOV STRUP.wShowWindow, SW_SHOWMINIMIZED
PUSH OFFSET INF
PUSH OFFSET STRUP
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH OFFSET PATH
PUSH 0
CALL CreateProcessA@40
JMP FINISH
Natomiast sekcja odpowiedzialna za obsługę przycisku, który wywołuje zakończenie procesu - wygląda następująco:
CZYZAKONCZYC:
CMP WORD PTR [EBP + 10H],IDC_BTN2 ;czy kończymy uruchomiony proces?
JNE FINISH
PUSH 0
PUSH INF.hProcess
CALL TerminateProcess@8
FINISH:
MOV EAX,0
POP EDI
POP ESI
POP EBX
POP EBP
RET
WNDPROC ENDP
Przykładowe wywołanie programu przestawione jest na rysunku poniżej - Rys.1
Całość programu przedstawiona jest na poniższym listingu:
.586 ;typ instrukcji procesora
.MODEL
FLAT,STDCALL
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
IDC_BTN1 EQU 101
IDC_BTN2 EQU 102
STARTF_USESHOWWINDOW EQU 1h
SW_SHOWMINIMIZED EQU 2
WM_INITDIALOG EQU 110h
WM_CLOSE EQU 10h
WM_COMMAND EQU 111h
EXTERN TerminateProcess@8:NEAR
EXTERN CreateProcessA@40:NEAR
EXTERN EndDialog@8:NEAR
EXTERN GetModuleHandleA@4:NEAR
EXTERN DialogBoxParamA@20:NEAR
EXTERN ExitProcess@4:NEAR
STARTUP STRUC
cb DD 0 ;rozmiar struktury w bajtach
lpReserved DD 0 ;zarezerwowane, musi być zerem
lpDesktop DD 0 ;nazwa pulpitu
lpTitle DD 0 ;tytuł okna dla aplikacji konsolowych.
dwX DD 0 ;współrzędna X lewego górnego roku okna
dwY DD 0 ;współrzędna Y lewego górnego roku okna
dwXSize DD 0 ;szerokość okna
dwYSize DD 0 ;wysokość okna
dwXCountChars DD 0 ;rozmiar bufora konsoli (współrzędne X)
dwYCountChars DD 0 ;rozmiar bufora konsoli (współrzędne Y)
dwFillAttribute DD 0 ;początkowe kolory tekstu dla aplikacji konsolowych
dwFlags DD 0 ;znaczniki wartości pól
wShowWindow DW 0 ;definiuje tryb wyświetlania okna
cbReserved2 DW 0 ;zarezerwowane
lpReserved2 DD 0
hStdInput DD 0 ;deskryptor wejścia dla konsoli
hStdOutput DD 0 ;deskryptor wyjścia dla konsoli
hStdError DD 0 ;deskryptor wyświetlania komunikatów o błędach
STARTUP ENDS
PROCINF STRUC
hProcess DD ? ;deskryptor utworzonego procesu
hThread DD ? ;deskryptor głównego wątku utworzonego procesu
idProc DD ? ;identyfikator nowego procesu
idThr DD ? ;identyfikator głównego wątku nowego procesu
PROCINF ENDS
.DATA
HINST DD ?
PA DB 'IDD_DLG1', 0 ;nazwa dialogu
PATH DB "C:\WINDOWS\system32\calc.exe", 0
STRUP STARTUP <?>
INF PROCINF <?>
.CODE
START:
PUSH 0
CALL GetModuleHandleA@4
MOV [HINST],EAX
PUSH 0
PUSH OFFSET WNDPROC
PUSH 0
PUSH OFFSET PA
PUSH [HINST]
CALL DialogBoxParamA@20
PUSH 0
CALL ExitProcess@4
;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
CMP DWORD PTR [EBP + 0CH],WM_CLOSE;komunikat związany ze zniszczeniem okna
JNE WYKONANIE
JMP KONCZ
WYKONANIE:
CMP DWORD PTR [EBP + 0CH],WM_COMMAND;komunikat związany z kontrolkami
JNE FINISH
CMP WORD PTR [EBP + 10H],IDC_BTN1 ;czy uruchamiamy proces?
JNE CZYZAKONCZYC
JMP URUCHOM
KONCZ:
PUSH 0
PUSH DWORD PTR [EBP+ 08H]
CALL EndDialog@8
JMP FINISH
URUCHOM:
MOV STRUP.cb,68
MOV STRUP.lpReserved,0
MOV STRUP.lpDesktop,0
MOV STRUP.lpTitle,0
MOV STRUP.dwFlags,STARTF_USESHOWWINDOW
MOV STRUP.cbReserved2,0
MOV STRUP.lpReserved2,0
MOV STRUP.wShowWindow, SW_SHOWMINIMIZED
PUSH OFFSET INF
PUSH OFFSET STRUP
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH 0
PUSH OFFSET PATH
PUSH 0
CALL CreateProcessA@40
JMP FINISH
CZYZAKONCZYC:
CMP WORD PTR [EBP + 10H],IDC_BTN2 ;czy kończymy uruchomiony proces?
JNE FINISH
PUSH 0
PUSH INF.hProcess
CALL TerminateProcess@8
FINISH:
MOV EAX,0
POP EDI
POP ESI
POP EBX
POP EBP
RET
WNDPROC ENDP
END Start
Plik zasobów programu wygląda następująco:
#include "..\include\resource.h"
#define IDC_BTN1 101
#define IDC_BTN2 102
IDD_DLG1 DIALOGEX 75,87,381,210
CAPTION "Procesy"
FONT 8,"MS Sans Serif", 0, 0, 0
STYLE WS_VISIBLE|WS_OVERLAPPEDWINDOW
BEGIN
CONTROL "Uruchom proces kalkulatora",IDC_BTN1,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,51,27,102,15
CONTROL "Zakończ proces kalkulatora",IDC_BTN2,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,210,27,107,15
END
Zmodyfikować kod przykład tak, aby można było dodatkowo tworzyć i zamykać proces notatnika i painta. Przykładowe wywołanie programu na rysunku poniżej. - Rys.2.