注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

从C开始

 
 
 

日志

 
 

《Windows核心编程》学习笔记(12)– 获取线程,进程的伪句柄,并转换为真正的句柄  

2010-10-14 15:38:06|  分类: 《Windows核心编 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

HANDLE GetCurrentProcess(); 

HANDLE GetCurrentThread(); 

 

这两个函数都返回到主调线程的进程或线程内核对象的一个伪句柄(pseudohandle )。它们不会在主调进程的句柄表中新建句柄。而且,调用这两个函数,不会影响进程或线程内核对象的使用计数。如果调用CloseHandle,将一个伪句柄作为参数传入,CloseHandle只是简单地忽略此调 用,并返回FALSE。在这种情况下,GetLastError将返回ERROR_INVALID_HANDLE 

 

 

将伪句柄转换为真正的句柄

 

    有时或许需要一个真正的线程句柄,而不是一个伪句柄。所谓真正的句柄,指的是能明确、无歧义地标识一个线程的句柄。来仔细分析下面的代码: 

 

DWORD WINAPI ParentThread(PVOID pvParam) { 

HANDLE hThreadParent = GetCurrentThread(); 

CreateThread(NULL, 0, ChildThread, (PVOID) hThreadParent, 0, NULL); 

// Function continues... 

DWORD WINAPI ChildThread(PVOID pvParam) { 

HANDLE hThreadParent = (HANDLE) pvParam; 

FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime; 

GetThreadTimes(hThreadParent, 

&ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime); 

// Function continues... 

 

  能看出这个代码段的问题吗?其意图是让父线程向子线程传递一个可以标识父线程的句柄。但是,父线程传递的是一个伪句柄,

而不是一个真正的句柄。子线程开始执行时,它把这个伪句柄传给GetThreadTimes函数,这将导致子线程得到的是它自己的CPU

计时数据,而不是父线程的。之所以会发生这种情况,是因为线程的伪句柄是一个指向当前线程的句柄;换言之, 

指向的是发出函数调用的那个线程。 

 

     为了修正这段代码,必须将伪句柄转换为一个真正的句柄。DuplicateHandle函数可以执行这个转换: 

 

BOOL DuplicateHandle( 

HANDLE hSourceProcess, 

HANDLE hSource, 

HANDLE hTargetProcess, 

PHANDLE phTarget, 

DWORD dwDesiredAccess, 

BOOL bInheritHandle, 

DWORD dwOptions); 

 

正常情况下,利用这个函数,你可以根据与进程A相关的一个内核对象句柄来创建一个新句柄,并让它同进程B相关。但是,我们可以采取一种特殊的方式来使用它,以纠正前面的那个代码段的错误。纠正过后的代码如下: 

 

DWORD WINAPI ParentThread(PVOID pvParam) { 

HANDLE hThreadParent; 

DuplicateHandle( 

GetCurrentProcess(), // Handle of process that thread pseudohandle is relative to 

GetCurrentThread(), // 父伪句柄

GetCurrentProcess(), // Handle of process that the new, real, thread handle is relative to 

&hThreadParent, // Will receive the new, real, handle identifying the parent thread 

0, // Ignored due to DUPLICATE_SAME_ACCESS 

FALSE, // New thread handle is not inheritable 

DUPLICATE_SAME_ACCESS); // New thread handle has same access as pseudohandle 

 

CreateThread(NULL, 0, ChildThread, (PVOID) hThreadParent, 0, NULL); 

// Function continues... 

 

DWORD WINAPI ChildThread(PVOID pvParam) { 

HANDLE hThreadParent = (HANDLE) pvParam; 

FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime; 

GetThreadTimes(hThreadParent, &ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime); 

CloseHandle(hThreadParent); 

// Function continues... 

 

现在,当父线程执行时,它会把标识父线程的有歧义的伪句柄转换为一个新的、真正的句柄,后者明确、无歧义地标识了父线程。然后,它将这个真正的句柄传给CreateThread。当子线程开始执行时,其pvParam参数就会包含这个真正的线程句柄。在调用任何函数时,只要传入这个句 柄,影响的就将是父线程,而非子线程。 因为DuplicateHandle递增了指定内核对象的使用计数,所以在用完复制的对象句柄后,有必要 把目标句柄传给CloseHandle

以递减对象的使用计数。前面的代码体现了这一点。调用 GetThreadTimes之后,子线程紧接着调用CloseHandle来递减父线程对象的使用计数。在这段代 码中,我假设子线程不会用这个句柄调用其他任何函数。如果还要在调用其他函数时传入父线程的句柄,那么只有在子线程完全不需要此句柄的时候,才能调用CloseHandle 

 

还要强调一点,DuplicateHandle函数同样可用于把进程的伪句柄转换为真正的进程句柄,如下所示: 

HANDLE hProcess; 

DuplicateHandle( 

GetCurrentProcess(), // Handle of process that the process pseudohandle is relative to 

GetCurrentProcess(), // Process' pseudohandle 

GetCurrentProcess(), 

&hProcess

0

FALSE,

DUPLICATE_SAME_ACCESS

)

 

  评论这张
 
阅读(871)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018