终止进程是通过以下4种方式来实现的:
*主线程入口点函数返回.(推荐)
*进程中线程调用ExitProcess函数(避免)
*另一个进程中线程调用TerminateProcess函数(避免)*
进程,自然死亡(几乎不可能)
一、主线程的入口点函数返回 主程序入口点函数返回之后,这个应用程序的进程才终止.
主线程的入口点函数返回,保证以下操作会被执行.
1.线程创建任何C++对象都将由这些对象的析构函数正确销毁.
2.正确释放线程栈使用内存.
3.将进程的退出代码,设为入口点函数的返回值.
4.递减进程内核对象使用计数.
二.ExitProcess函数:
进程中的线程调用ExitProcess函数时终止:
VOID ExitProcess(UINT fuExitCode);
终止进程,并将进程的退出代码设为fuExitCode。ExitProcess不会返回值当主线程入口点函数返回时,
会返回C/C++运行库启动代码,后者将正确清理进程使用的全部C运行时资源.释放了C运行时资源之后,
C运行时启动代码将显式调用ExitProcess,将入口点函数返回的值传给它.为什么只需要从主线程入口点函数返回,
就会终止整个进程.不管进程中是否还有其他线程在运行,只要应用程序的主线程从它的入口点函数返回,
C/C++运行库就会调用ExitProcess来终止进程.调用是ExitThread,或者入口点函数直接返回,应用程序的主线程将停止执行,
但只要进程中还有其他线程正在运行,进程就不会终止.
调用ExitProcess或ExitThread会导致进程或线程直接运行-再也不会返回当前函数调用.
C/C++应用程序应避免用这些函数,因为C/C++运行库也许不能执行正确清理工作. #include <windows.h>
#include <stdio.h> class CSomeObj {
public:
CSomeObj() { printf("Constructor/r/n"); }
~CSomeObj() { printf("Destructor/r/n"); }
}; CSomeObj g_GlobalObj;
void main () {
CSomeObj LocalObj;
ExitProcess(0); // This shouldn't be here // At the end of this function, the compiler automatically added
// the code necessary to call LocalObj's destructor.
// ExitProcess prevents it from executing.
} 执行上述代码,会显示以下结果:
Constructor
Constructor ExitProcess造成进程"当场终止运行";C/C++运行时没有机会执行清理工作.
任何时候都不要显式地调用ExitProcess.再运行这个程序就会得到以下结果... Constructor
Constructor
Destructor
Destructor三、 TerminateProcess函数
TerminateProcess函数可终止一个进程
Bool TerminateProcess(
HANDLE Process, // 制定终止进程句柄
UINT fuExitCode // 退出代码值,全传给fuExitCode参数
); 任何线程可通过TerminateProcess结束另一个或自己的进程。
只有无法通过其它方法来强制进程退出时,才使用TerminateProcess
另外TerminateProcess函数是异步的,它告诉系统我们希望进程终止,
但函数返回时候,系统并不能保证进程已经被强行终止?
为了确定进程是否已终止应调用WaitForSingleObject或者一个类似的函数
并将进程句柄传给它。
四、进程终止运行时
用过调用GetExitCodeProcess获得已经终止的一个进程退出代码 BOOL GetExitCodeProcess(
HANDLE hProcess,
PDWORD pdwExitCode); 函数会查找进程内核对象,并从内核对象的数据
结构中提取用于标识进程退出代码的成员。
任何时候都可调用此函数,调用GetExitCodeProcess进程还没终止
将用STILL_ACTIVE 标识符,来填充DWORD如果进程已经终止,就返回实际退出代码值。五、子进程
Windows 提供几种不同进程间传递数据方式
包括动态数据交换(DDE)、OLE、管道、邮件槽等。
共享数据最好方式之一使用内存映射文件。
PROCESS_INFORMATION pi;
DWORD dwExitCode; // 退出代码// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) { // Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread); // 关闭主线程内核对象句柄 // Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// 等待hObject参数被触发 // The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// 获取子进程的退出代码 // Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
// 关闭主进程内核对象句柄
}WaitForSingleObject 函数声明:
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwTimeout);运行独立子进程
Windows 进程间的关系:
如当Windows资源管理器为用户创建一个新的进程,之后就不再关系这个进程是否继续存在,也
不关心用户是否要终止它。
为断绝与子进程所有联系,Windows资源管理器必须调用 CloseHandle来关闭新进程及其主线程句柄。五、管理员以标准用户权限运行时(UAC)
为什么UAC,不一定询问,然后把安全数据保存到系统中,并让用户下次可不经过提示直接运行呢?
如果提供这样一个安全数据库。那么数据被入侵了怎么办呢?
任务管理器上的用户提示权限
实际上你注意这任务管理器,在点击后的PID是不一样的,这意味着任务管理器,生成它的另一个实例。
六、自动提升进程权限
如果在应用程序中可执行文件中嵌入一种特殊资源(RT_MANIFEST)
其中系统会检查<trustInfo>段,下面是示例清单文件的<trustInfo>段。
我们可以将清单保存到可知性文件所在目录中,名称和可执行文件相同
且扩展名使用 *.manifest那么效果也是一样的。
不过这个清单须要在注销系统后生效,可知性文件嵌入清单的优先权会比外部清单文件大。...
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
/>
</requestedPrivileges>
</security>
</trustInfo>
...可能有3个不同的值
level 属性的值
值 描述
requireAdministrator 程序必须以管理员权限启动;否则不会运行
highestAvailable 使用管理员帐户登入,就会出现一个要求批准提升权限的对话框 使用管理员帐户登入,会出现一个要求批准提升权限的对话框
普通用户帐户登录,应用程序就会用这些标准权限来启动(不会提示用户提升权限)
asInvoker 应用程序使用与主调进程应用程序一样的权限来启动。
七、手动提升进程权限
shellExecutEx函数BOOL ShellExecuteEx(LPSHELLEXECUTEINFO pExecInfo);
typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
ULONG fMask;
HWND hwnd;
PCTSTR lpVerb; // 必须设为runas
PCTSTR lpFile; // 提升后的权限启动一个可执行文件路径
PCTSTR lpParameters;
PCTSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
PVOID lpIDList;
PCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hIcon;
HANDLE hMonitor;
} DUMMYUNIONNAME;
HANDLE hProcess;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;========================================================================
实用例子:// Initialize the structure.
SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };// Ask for privileges elevation.
sei.lpVerb = TEXT("runas");// Create a Command Prompt from which you will be able to start
// other elevated applications.
sei.lpFile = TEXT("cmd.exe");// Don't forget this parameter; otherwise, the window will be hidden.
sei.nShow = SW_SHOWNORMAL;if (!ShellExecuteEx(&sei)) {
DWORD dwStatus = GetLastError(); if (dwStatus == ERROR_CANCELLED) {
// The user refused to allow privileges elevation.
}
else
if (dwStatus == ERROR_FILE_NOT_FOUND) {
// The file defined by lpFile was not found and
// an error message popped up.
}
}用户拒绝提升权限,shellExecutEx返回Flase,GetLastError通过使用一个ERROR_CANCELLED值来指出情况
当父进程以已经用shellExecutEx函数取得相关权限时,有继承权的子进程就不要在用CreateProcess函数
去申请同样释放权限,否则调用会失败的,GetLastError会返回 ERROR_ELEVATION_REQUIRED八、 何为当前权限上下文
我们可以通过GetProcessElevation函数 来返回提升类型和一个指出进程是否正以管理员身份运行的布尔值。
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin) {
HANDLE hToken = NULL;
DWORD dwSize; // Get current process token
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return(FALSE); BOOL bResult = FALSE;
// Retrieve elevation type information
if (GetTokenInformation(hToken, TokenElevationType,
pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) {
// Create the SID corresponding to the Administrators group
BYTE adminSID[SECURITY_MAX_SID_SIZE];
dwSize = sizeof(adminSID);
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID,
&dwSize); if (*pElevationType == TokenElevationTypeLimited) {
// Get handle to linked token (will have one if we are lua)
HANDLE hUnfilteredToken = NULL;
GetTokenInformation(hToken, TokenLinkedToken, (VOID*)
&hUnfilteredToken, sizeof(HANDLE), &dwSize); // Check if this original token contains admin SID
if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin)) {
bResult = TRUE;
} // Don't forget to close the unfiltered token
CloseHandle(hUnfilteredToken);
} else {
*pIsAdmin = IsUserAnAdmin();
bResult = TRUE;
}
} // Don't forget to close the process token
CloseHandle(hToken); return(bResult);
}其中GetTokenInformation使用的与进程关联的安全令牌和 TokenElevationType 参数获得提升类型,
提升类型的值由TOKEN_ELEVATION_TYPE 枚举类型来定义。TOKEN_ELEVATION_TYPE 的值
值 说明
TokenElevationTypeDefault 默认运行用户运行,UAC被禁用
TokenElevationTypeFull 权限被成功提升,而且令牌没有被筛选过
TokenElevationTypeLimited 进程以受限的权限运行,它对应于一个筛选过的令牌
android 31申请权限没有弹框
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
下一篇:python 满减算法

提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
android 监听弹出权限申请弹框 android添加监听
Android应用--简、美音乐播放器添加电话监听2013年6月11日简、美音乐播放器第2阶段启动第1阶段完成了以下功能: 1. 自动显示音乐列表2. 点击列表播放音乐3. 长按列表弹出对话框4. 暂停音乐5. 上一首音
android 监听弹出权限申请弹框 移动开发 音乐播放 android 播放音乐