Win32 assembly: 14. Process

zhaozj2021-02-17  53

Fourth class process

We will learn in this lesson: What is a process? How to generate and terminate a process?

Preliminary knowledge: What is the process? Below is the explanation I am from the Win32 API Guide:

"A process is an application that is executing, which includes: private virtual address space, code, data, and other operating system resources, such as pipelines, files, and synchronization objects that can be accessed."

From the above definition you can see, a process has several objects: address space, execution module, and any other object or resource created by the executor on or created. At least, a process must contain executable modules, private address spaces and more than one thread. What is thread? A thread is actually an execution unit. When Windows generates a process, it automatically generates a primary thread for the process. This thread usually begins at the first instruction of the module. If the process requires more threads, it can be explicitly generated. When WindWos receives a message generated, it generates private memory address space for the process, then maps the executable to the space. After winning the process under Win32, you can call the function createProcess to generate more threads for your process.

The prototype of CreateProcess is as follows:

CreateProcess proto lpApplicationName: DWORD, / lpCommandLine: DWORD, / lpProcessAttributes: DWORD, / lpThreadAttributes: DWORD, / bInheritHandles: DWORD, / dwCreationFlags: DWORD, / lpEnvironment: DWORD, / lpCurrentDirectory: DWORD, / lpStartupInfo: DWORD, / lpProcessInformation: DWORD

Don't be intimidated by so many parameters, in fact, you can ignore most of the parameters (let them have default).

LPApplicationName -> The name of the executable (including or contains or without path). If this parameter is null, you must pass the file name in the parameter lpcommandline. LPCommandline -> Pass line parameters passing to the file to be executed. If lpapplicationname is NULL, you must specify in this parameter, such as "NOTEPAD.EXE README.TXT". LPPRocessAttributes and LPTHREADATTRIBUTES -> Specify the security properties of the processes and main threads. You can set them into null, which sets the default security properties. BinheritHandles -> Symbol. Use to set up the new process to inherit the creation of all open handles. DWCREATIONFLAGS -> There are several signs to set this at this point to determine how to create a process, such as you might want to create a process, do not want it to run right away, so you can do some check and modification work before it actually runs. You can also set up the priority of all threads in the new process here, usually we set it to Normal_Priority_Class. LpenVironment -> Pointer to ambient block, a general environment block contains several environment strings. If this parameter is null, then the new process inherits the environment block that creates the process. LPCurRrentDirectory -> Points to the current directory and the path to the "current directory" set for the child process. If null, inherit the "Current Directory" path to create the process. LPStartupinfo -> Pointer to start structural STARTUPINFO in the new process. StartupInfo tells Windows how to display the appearance of the new process. This parameter has many member variables. If you don't want the new process, you can call the GetStartupInfo function to populate the StartupInfo structure variable with the startup parameters of the process. LPPROCESSINFORMATION - Points to structural process_information, which contains some member variables identifying the uniqueness of the process: Process_information Struct

HProcess Handle?; Handle To The Child Process

HTHREAD HANDLE?; Handle to The Primary Thread of the child process

DWPROCESSID DWORD?; id of the child process

DWTHREADID DWORD?; ID of the privary thread of the child process

Process_information Ends

Procedures handle and process ID are two different concepts. The process ID is like a unique value, and the process handle is a return value obtained after calling the associated Windows API. You cannot use the process handle to identify the uniqueness of a process because this value is not unique. This process is created after calling createProcess generating a new process, and the CERATEPROCESS function returns immediately. You can call the function getExitCodeProcess to check if the process ends. The prototype of this function is as follows:

GetExitcodeProcess Proto HProcess: DWORD, LPEXITCODE: DWORD

If the call is successful, the LPEXITCODE contains the status code of the query process. If it is equal to STILL_ACTIVE, it indicates that the process still exists. You can call the function TERMINATEPROCESS to force the termination of a process. The prototype of this function is as follows: TerminateProcess Proto HProcess: DWORD, UEXITCODE: DWORD

You can specify any exit value. Ending a process with this function is not good because the dynamic connection library loaded by the process does not get the message that the process is exiting.

Example: In the example below, we create a new process when the user selects the menu item "CRATE Process". It will go to "" msgbox.exe ". If the user wants to terminate the new process, you can select the menu item" Terminate Process ". At this time, the application checks if the application is still existed, if there is, call the TerminateProcess function to terminate it.

.386 .model flat, stdcall option casemap: none WinMain proto: DWORD,: DWORD,: DWORD,: DWORD include /masm32/include/windows.inc include /masm32/include/user32.inc include / masm32 / include / kernel32. Inc includelib /masm32/lib/user32.lib incruDelib /masm32/lib/kernel32.lib

.const idm_create_process EQU 1 IDM_TERMINATE EQU 2 IDM_EXIT EQU 3

.DATA CLASSNAME DB "WIN32AMPROCESSCLASS", 0 Appname DB "Win32 ASM Process Example", 0 Menuname DB "Firstmenu", 0 ProcessInfo Process_Information <> ProgramName DB "msgbox.exe", 0

.DATA? Hinstance Hinstance? CommandLine LPSTR? HMENU HANDLE? EXITCODE DWORD?; Contains The Process EXITCODE Status from getExitcodeProcess Call.

. Code Start: Invoke GetModuleHandle, Null Mov Hinstance, Eax Invoke Getcommandline Mov Commandline, Eax Invoke Winmain, Hinstance, Null, CommandLine, SW_SHOWDEFAULT INVOKE EXITPROCESS, EAX

WinMain proc hInst: HINSTANCE, hPrevInst: HINSTANCE, CmdLine: LPSTR, CmdShow: DWORD LOCAL wc: WNDCLASSEX LOCAL msg: MSG LOCAL hwnd: HWND mov wc.cbSize, SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL push hInst pop wc.hInstance mov wc.hbrBackground, COLOR_WINDOW 1 mov wc.lpszMenuName, OFFSET MenuName mov wc.lpszClassName, OFFSET ClassName invoke LoadIcon, NULL, IDI_APPLICATION mov wc. hIcon, eax mov wc.hIconSm, eax invoke LoadCursor, NULL, IDC_ARROW mov wc.hCursor, eax invoke RegisterClassEx, addr wc invoke CreateWindowEx, WS_EX_CLIENTEDGE, aDDR ClassName, aDDR AppName, / WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, / CW_USEDEFAULT, 300,200, NULL, NULL , / Hinst, Null Mov HWnd, Eax Invoke Showwindow, HWnd, SW_SHOWNORMAL INVOKE UPDATEWINDOW, HWND INVOKE GETMENU, HWND MOV HMENU, EAX .While True Invoke GetMessage, Addr MSG, NULL, 0, 0.Break .if (! EAX) Invoke TranslateMessage, Addr Msg Invoke DispatchMessage, Addr Msg .Endw Mov EAX, Msg.wParam Ret Winmain Endp

WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM LOCAL startInfo: STARTUPINFO .IF uMsg == WM_DESTROY invoke PostQuitMessage, NULL .ELSEIF uMsg == WM_INITMENUPOPUP invoke GetExitCodeProcess, processInfo.hProcess, ADDR ExitCode .if eax = = TRUE .if ExitCode == STILL_ACTIVE invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_GRAYED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_ENABLED .else invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_ENABLED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED .endif .else invoke EnableMenuItem, hMenu , IDM_CREATE_PROCESS, MF_ENABLED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED .endif .ELSEIF uMsg == WM_COMMAND mov eax, wParam .if lParam == 0 .if ax == IDM_CREATE_PROCESS .if processInfo.hProcess! = 0 invoke CloseHandl e, processInfo.hProcess mov processInfo.hProcess, 0 .endif invoke GetStartupInfo, ADDR startInfo invoke CreateProcess, ADDR programname, NULL, NULL, NULL, FALSE, / NORMAL_PRIORITY_CLASS, / NULL, NULL, ADDR startInfo, ADDR processInfo invoke CloseHandle, processInfo. Hthread .elseif AX == idm_terminate invoke getExitcodeProcess, ProcessInfo.hprocess, Addr EXITCODE .IF EXITCODE ==

STILL_ACTIVE invoke TerminateProcess, processInfo.hProcess, 0 .endif invoke CloseHandle, processInfo.hProcess mov processInfo.hProcess, 0 .else invoke DestroyWindow, hWnd .endif .endif .ELSE invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret .ENDIF xor eax EAX RET WNDPROC ENDP End Start Analysis: The application creates a main window, saving the menu handle for use. When the user selects the "Process" menu item in the main menu, the WM_INITMENUPOPUP message is received during the message processing, and we will change the "enable" and "unstent" of the menu items in the pop-up menu. There are different displays in the menu.

.ELSEIF uMsg == WM_INITMENUPOPUP invoke GetExitCodeProcess, processInfo.hProcess, ADDR ExitCode .if eax == TRUE .if ExitCode == STILL_ACTIVE invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_GRAYED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_ENABLED .else invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_ENABLED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED .endif .else invoke EnableMenuItem, hMenu, IDM_CREATE_PROCESS, MF_ENABLED invoke EnableMenuItem, hMenu, IDM_TERMINATE, MF_GRAYED .endif

The purpose of handling this message is to make the menu show different appearances to facilitate the user's use. For example, when the new process has not yet run, we turn on (enabled) menu item "Start Process", and gray gray (non-enabled) menu item "Terminate Process". When the new process runs, the menu appearance It should be the opposite. First we call the getExitCodeProcess function, which is incorporated by the creteProcess returns. If getExitCodeProcess returns false, the process has not yet run, let's let the menu item "Terminate Process" becomes gray; if returns true, indicate a new process It has been launched, we have detected whether it is running, which is completed by comparing whether EXITCODE is equal to STILL_ACTIVE. If it is equal, it means that the process is still running, we let the menu item "Start Process" beat, because in our simple application does not provide the ability to simultaneously run multiple processes ..if ax == IDM_CREATE_PROCESS .if processInfo.hProcess! = 0 invoke CloseHandle, processInfo.hProcess mov processInfo.hProcess, 0 .endif invoke GetStartupInfo, ADDR startInfo invoke CreateProcess, ADDR programname, NULL, NULL, NULL, FALSE, / NORMAL_PRIORITY_CLASS, / NULL, NULL, ADDR startInfo, ADDR processInfo invoke CloseHandle, processInfo.hThread when the user selects the menu item "start process", we first detection member variable hPRocess structure of PROCESS_INFORMATION Whether it has been closed. If it is the first start application, the variable is 0 because we have initialized the value when the .data segmentation defines the structure. 0. If the value is not 0, it indicates that the new process has ended, but we have not closed the handle of the process (to reduce the reference number of the process), we do this here. We call the getStartupInfo function to fill the structural variables of the startup information, and the variable will be passed to the CreateProcess function. Call CreateProcess Generate a new process, we do not check the return value of this function is that the problem is simplified. In practical applications, you must do this. After calling createProcess, we immediately turn off the main thread handle returned in the process information structure parameter. The closing thread handle is to reduce the reference number of the kernel object, otherwise, even if the thread exits, its kernel object is still in the kernel. There is no release, which will cause resource leakage. The process is actually the same, and the handle we close the process is not because we will use this handle to get some and process related information, as for threads, our applications do not require their related information.

.elseif ax == IDM_TERMINATE invoke GetExitCodeProcess, processInfo.hProcess, ADDR ExitCode .if ExitCode == STILL_ACTIVE invoke TerminateProcess, processInfo.hProcess, 0 .endif invoke CloseHandle, processInfo.hProcess mov processInfo.hProcess, 0 when the user selects the menu item " After Terminate Process, we call the function getExitCodeProcess to check if the new process exists. If we still have we call the function TerminateProcess to end it. In addition, we turn off its handles because we don't need it anymore.

转载请注明原文地址:https://www.9cbs.com/read-30124.html

New Post(0)