共享跨越进程边界的内核对象的最后一个方法是使用D u p l i c a t e H a n d l e 函数:

BOOL DuplicateHandle(
HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
PHANDLE phTargetHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwOptions);

简单说来,该函数取出一个进程的句柄表中的项目,并将该项目拷贝到另一个进程的句柄表中。D u p l i c a t e H a n d l e 函数配有若干个参数,但是实际上它是非常简单的。D u p l i c a t e H a n d l e 函数最普通的用法要涉及系统中运行的3 个不同进程。

当调用D u p l i c a t e H a n d l e 函数时,第一和第三个参数h S o u r c e P r o c e s s H a n d l e 和h Ta rg e tP r o c e s s H a n d l e 是内核对象句柄。这些句柄本身必须与调用D u p l i c a t e H a n d l e 函数的进程相关。此外,这两个参数必须标识进程的内核对象。如果将句柄传递给任何其他类型的内核对象,那么该函数运行就会失败。第4 章将详细介绍进程的内核对象,而现在只需要知道,每当系统中启动一个新进程时都会创建一个进程内核对象。

第二个参数h S o u r c e H a n d l e 是任何类型的内核对象的句柄。但是该句柄值与调用D u p l i c a t eH a n d l e 的进程并无关系。相反,该句柄必须与h S o u r c e P r o c e s s H a n d l e 句柄标识的进程相关。第四个参数p h Ta rg e t H a n d l e 是H A N D L E 变量的地址,它将接收获取源进程句柄信息拷贝的项目索引。返回的句柄值与h Ta rg e t P r o c e s s H a n d l e 标识的进程相关。

D u p l i c a t e H a n d l e 的最后3 个参数用于指明该目标进程的内核对象句柄表项目中使用的访问屏蔽值和继承性标志。d w O p t i o n s 参数可以是0 (零),也可以是下面两个标志的任何组合:D U P L I C AT E _ S A M E _ A C C E S S 和D U P L I C AT E _ C L O S E _ S O U R C E 。

如果设定了D U P L I C AT E _ S A M E _ A C C E S S 标志,则告诉D u p l i c a t e H a n d l e 函数,你希望目标进程的句柄拥有与源进程句柄相同的访问屏蔽。使用该标志将使D u p l i c a t e H a n d l e 忽略它的d w D e s i r e d A c c e s s 参数。

如果设定了D U P L I C AT E _ C L O S E _ S O U R C E 标志,则可以关闭源进程中的句柄。该标志使得一个进程能够很容易地将内核对象传递给另一个进程。当使用该标志时,内核对象的使用计数不会受到影响。

下面用一个例子来说明D u p l i c a t e H a n d l e 函数是如何运行的。在这个例子中,Process S 是目前可以访问某个内核对象的源进程,Process T 是将要获取对该内核对象的访问权的目标进程。Process C 是执行对D u p l i c a t e H a n d l e 调用的催化进程。Process C 的句柄表(表3 - 4 )包含两个句柄值,即1 和2 。句柄值1 用于标识Process S 的进程内核对象,句柄值2 则用于标识Process T 的进程内核对象。

表3-4 Process C 的句柄表

索引
内核对象内存块的指针
访问屏蔽(标志位的D W O R D )
标志(标志位的D W O R D )

1
0 x F 0 0 0 0 0 0 0(Process S 的内核对象)
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 0

2
0 x F 0 0 0 0 0 1 0(Process T 的内核对象)
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 0

表3 - 5 是Process S 的句柄表,它包含句柄值为2 的单个项目。该句柄可以标识任何类型的内核对象,就是说它不必是进程的内核对象。

表3-5 Process S 的句柄表

索引
内核对象内存块的指针
访问屏蔽(标志位的D W O R D )
标志(标志位的D W O R D )

1
0 x 0 0 0 0 0 0 0 0
(无)
(无)

2
0 x F 0 0 0 0 0 2 0
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 0

表3 - 6 显示了Process C 调用D u p l i c a t e H a n d l e 函数之前Process T 的句柄表包含的项目。如你所见,Process T 的句柄表只包含句柄值为2 的单个项目,句柄项目1 目前未用。

表3-6 调用D u p l i c a t e H a n d l e 函数之前Process T 的句柄表

索引
内核对象内存块的指针
访问屏蔽(标志位的D W O R D )
标志(标志位的D W O R D )

1
0 x 0 0 0 0 0 0 0 0
(无)
(无)

2
0 x F 0 0 0 0 0 3 0
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 0

如果Process C 现在使用下面的代码来调用D u p l i c a t e H a n d l e ,那么只有Process T 的句柄表改变更,如表3 - 7 所示。

表3-7 调用D u p l i c a t e H a n d l e 函数之后Process T 的句柄表

索引
内核对象内存块的指针
访问屏蔽(标志位的D W O R D )
标志(标志位的D W O R D )

1
0 x F 0 0 0 0 0 2 0
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 1

2
0 x F 0 0 0 0 0 3 0
0 x ? ? ? ? ? ? ? ?
0 x 0 0 0 0 0 0 0 0

Process S 的句柄表中的第二项已经被拷贝到Process T 的句柄表中的第一项。D u p l i c a t eH a n d l e 也已经将值1 填入Process C 的h O b j 变量中。值1 是Process T 的句柄表中的索引,新项目将被放入该索引。

由于D U P L I C AT E _ S A M E _ A C C E S S 标志被传递给了D u p l i c a t e H a n d l e ,因此Process T 的句柄表中该句柄的访问屏蔽与Process S 的句柄表项目中的访问屏蔽是相同的。另外,传递D U P L I C AT E _ S A M E _ A C C E S S 标志将使D u p l i c a t e H a n d l e 忽略它的D e s i r e d A c c e s s 参数。最后请注意,继承位标志已经被打开,因为给D u p l i c a t e H a n d l e 的b I n h e r i t H a n d l e 参数传递的是T R U E 。

显然,你永远不会像在这个例子中所做的那样,调用传递硬编码数字值的D u p l i c a t e H a n d l e函数。这里使用硬编码数字,只是为了展示函数是如何运行的。在实际应用程序中,变量可能拥有各种不同的句柄值,可以传递该变量,作为函数的参数。

与继承性一样,D u p l i c a t e H a n d l e 函数存在的奇怪现象之一是,目标进程没有得到关于新内核对象现在可以访问它的通知。因此,Process C 必须以某种方式来通知Process T,它现在拥有对内核对象的访问权,并且必须使用某种形式的进程间通信方式,以便将h O b j 中的句柄值传递给Process T 。显然,使用命令行参数或者改变Process T 的环境变量是不行的,因为该进程已经启动运行。因此必须使用窗口消息或某种别的I P C 机制。

上面是D u p l i c a t e H a n d l e 的最普通的用法。如你所见,它是个非常灵活的函数。不过,它很少在涉及3 个不同进程的情况下被使用(因为Process C 不可能知道对象的句柄值正在被P r o c e s s使用)。通常,当只涉及两个进程时,才调用D u p l i c a t e H a n d l e 函数。比如一个进程拥有对另一个进程想要访问的对象的访问权,或者一个进程想要将内核对象的访问权赋予另一个进程。例如,Process S 拥有对一个内核对象的访问权,并且想要让Process T 能够访问该对象。若要做到这一点,可以像下面这样调用D u p l i c a t e H a n d l e :

//ALL of the following code is executed by Process S.
//Create a mutex object accessible by Process S.
HANDLE hObjProcessS = CreateMutex(NULL, FALSE, NULL);
//Open a handle to Process T's kernel object.
HANDLE hProcessT = OpenProcess(PROCESS_ALL_ACCESS,
FALSE, dwProcessIdT);
//An uninitilized handle relative to Process T.
HANDLE hObjProcessT;
//Give Process T accesss to our mutex object
DuplicateHandle(GetCurrentProcess(),
hObjProcessS,
hProcessT,
&hObjProcessT, 0, FALSE,
DUPLICATE_SAME_ACCESS);
//Use some IPC mechanism to get the handle
//value in hOnjProcess S into Process T
//We no longer need to communicate with Process T.
CloseHandle(hProcessT);
//When Process S no longer needs to Use the mutex,
//it should close it.
CloseHandle(hObjProcessS);

在这个例子中,对G e t C u r r e n t P r o c e s s 的调用将返回一个伪句柄,该句柄总是用来标识调用端的进程Process S 。一旦D u p l i c a t e H a n d l e 返回,h O b j P r o c e s s T 就是与Process T 相关的句柄,它所标识的对象与引用Process S 中的代码时h O b j P r o c e s s S 的句柄标识的对象相同。Process S 决不应该执行下面的代码:

//Process S should never attempt to close the duplicated handle
CloseHandle(hObjProcessT);

如果Process S 要执行该代码,那么对代码的调用可能失败,也可能不会失败。如果P r o c e s s S 恰好拥有对内核对象的访问权,其句柄值与h O b j P r o c e s s T 的值相同,那么调用就会成功。该代码的调用将会关闭某个对象,这样Process S 就不再拥有对它的访问权,这当然会导致应用程序产生不希望有的行为特性。

下面是使用D u p l i c a t e H a n d l e 函数的另一种方法。假设一个进程拥有对一个文件映射对象的读和写访问权。在某个位置上,一个函数被调用,它通过读取文件映射对象来访问它。为了使应用程序更加健壮,可以使用D u p l i c a t e H a n d l e 为现有的对象创建一个新句柄,并确保这个新句柄拥有对该对象的只读访问权。然后将只读句柄传递给该函数,这样,该函数中的代码就永远不会偶然对该文件映射对象执行写入操作。下面这个代码说明了这个例子:

int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE,
PSTR pszCmdLine, int nCmdShow)
{
//Create a file-mapping object;
//the handle has read/write access.
HANDLE hFileMapRW = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL, PAGF_READWRITE, 0, 10240, NULL);
//Create anotherhandle to the file-mapping object;
//the handle has read-only access.
HANDLE hFileMapRO;
DuplicateHandle(GetCurrentProcess(), hFileMapRW,
GetCurrentProcess(), &hFileMdpRO,
FILE_MAP_READ, FALSE, 0);
//Call the function that should only read
//from the mapping.
ReadFromTheFileMapping(hFileMapRO);
//Close the read-only file-mapping object.
CloseHandle(hFileMapRO);
//We can still read/write the file-mapping
//object using hFileMapRW.When the main code
//doesnot access the file mapping anymore
CloseHandle(hFileMapRW);
}

复制对象句柄--D u p l i c a t e H a n d l e 函数相关推荐

  1. 内核对象 复制对象句柄 DuplicateHandle 跨进程边界共享内核对象

    Windows API List System Services Windows System Information Handles and Objects Handles and Object R ...

  2. D u p l i c a t e H a n d l e函数存在的奇怪现象之一是,目标进程没有得到关于新内 核对象现在可以访问它的通知

    与继承性一样,D u p l i c a t e H a n d l e函数存在的奇怪现象之一是,目标进程没有得到关于新内 核对象现在可以访问它的通知.因此, Process C必须以某种方式来通知P ...

  3. assign复制对象_JavaScript标准对象:assign,values,hasOwnProperty和getOwnPropertyNames方法介绍...

    assign复制对象 In JavaScript, the Object data type is used to store key value pairs, and like the Array ...

  4. 内核对象句柄泄漏检测

    自制工具   翰华Box:https://hanhuabox.lanzous.com/b00zjq9uf 翰华Box - 开发日志:https://blog.csdn.net/qq_41517936/ ...

  5. JS如何深度复制对象和数组,避免指针变量引用修改值

    //自定义深度复制对象or数组的递归方法---------------------------------------- let copyObjOrArr = o => {let isArray ...

  6. java 复制对象有哪些方式

    2019独角兽企业重金招聘Python工程师标准>>> java 复制对象有哪些方式 Apache的 Common beanutils库 org.apache.commons.bea ...

  7. JavaScript 复制对象与Object.assign方法无法实现深复制

    在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...

  8. UNITY 复制对象后局部坐标和世界坐标的变化问题

    UNITY 复制对象后局部坐标和世界坐标的变化问题 void Start () { var pgo = transform.Find ("Button").gameObject; ...

  9. JS:js中的复制对象值问题——Object.assign()

    在复制对象的值的时候,往往不能直接"=",这样会造成引用赋值,应该利用一些函数进行对象的复制值.如下: $scope.updateDeliveryOrder = function( ...

最新文章

  1. java8中的default关键字
  2. 网站服务器被攻击的形式,服务器被攻击的不同表现类型以及应对策略
  3. html5 测试用例,Web 测试通用测试用例
  4. [剑指offer]面试题22:栈的压入、弹出序列
  5. Android 启动过程简析(一)之 init 进程
  6. 微信怎么at所有人_微信分付怎么开通,入口在这里,简单几步教你快速开通
  7. 计算机拆装与网络配置技能,计算机硬件及网络计算机原理与拆装.ppt
  8. 智能手机下半场迎来淘汰赛:有的拼供应链,有的打起了 AI 的主意
  9. android 电池小记
  10. RHEL5中配置Sendmail邮件服务 收藏二
  11. python 学习之路1-如何入门
  12. matlab求解数学题,MATLABR2013a求解数学问题
  13. 平均值、中位数、众数等统计特性的matlab求解与示例
  14. 【学习笔记】python实现图像的手绘效果
  15. 怎样压缩图片到100k?如何把电脑图片缩小kb?
  16. Oracle RAC命令
  17. 2019年总结-做时间的朋友
  18. 零基础可以学python么
  19. GIS+=地理信息+行业+大数据——纽约公开11亿条出租车和Uber原始数据下载及分析
  20. c语言printf打印浮点型,printf以%d输出浮点数

热门文章

  1. 共享软件大敌 简析十大破解工具
  2. 案例(我们要的是开发者,而不是hacker)辩驳
  3. 嵌入式客户端程序开发大汇总
  4. android 自定义popupwindow样式,自定义popupwindow组件
  5. Nutz3---nutz实现主键自增
  6. 如何在项目立项中计算项目投资回收期!
  7. ISE 设计、综合及仿真流程
  8. 电力电子技术课程实验:实验二、可控整流电路及pwm逆变电路设计、制作、测试
  9. linux循环运算,shell case循环写个计算器
  10. 斗鱼直播服务器无响应,win7看斗鱼直播很卡怎么办|win7斗鱼未响应的解决方法