windows handle之DuplicateHandle

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

Table 3-4.

Process C's handle table

IndexPointer to Kernel Object Memory BlockAccess Mask (DWORD of Flag Bits)Flags (DWORD of Flag Bits)
10xF0000000 (Process S's kernel object)0x????????0x00000000
20xF0000010 (Process T's kernel object)0x????????

 

Table 3-5. Process S's handle table

IndexPointer to Kernel Object Memory BlockAccess Mask (DWORD of Flag Bits)Flags (DWORD of Flag Bits)
10x00000000(N/A)(N/A)
20xF0000020 (any kernel object)0x????????0x00000000

 

Table 3-6 shows what Process T's handle table contains before Process C calls the DuplicateHandle function. As you can see, Process T's handle table contains only a single entry with a handle value of 2; handle entry 1 is currently unused.

Table 3-6. Process T's handle table before calling DuplicateHandle

IndexPointer to Kernel Object Memory BlockAccess Mask (DWORD of Flag Bits)Flags (DWORD of Flag Bits)
10x00000000(N/A)(N/A)
20xF0000030 (any kernel object)0x????????0x00000000

 

If Process C now calls DuplicateHandle using the following code, only Process T's handle table has changed, as shown in Table 3-7.

DuplicateHandle(1, 2, 2, &hObj, 0, TRUE, DUPLICATE_SAME_ACCESS);

Table 3-7. Process T's handle table after calling DuplicateHandle

IndexPointer to Kernel Object Memory BlockAccess Mask (DWORD of Flag Bits)Flags (DWORD of Flag Bits)
10xF00000200x????????0x00000001
20xF0000030 (any kernel object)0x????????0x00000000

The second entry in Process S's handle table has been copied to the first entry in Process T's handle table. DuplicateHandle has also filled in Process C's hObj variable with a value of 1, which is the index in process T's handle table where the new entry was placed.

Because the DUPLICATE_SAME_ACCESS flag was passed to DuplicateHandle, the access mask for this handle in Process T's table is identical to the access mask in Process S's table entry. Also, passing the DUPLICATE_SAME_ACCESS flag causes DuplicateHandle to ignore its dwDesiredAccess parameter. Finally, notice that the inheritance bit flag has been turned on because TRUE was passed for DuplicateHandle's bInheritHandle parameter.

Obviously, you would never call DuplicateHandle passing in hard-coded numeric values as I have done in this example. I have used hard-coded numbers only to demonstrate how the function operates. In real applications, you would have the various handle values in variables and you would pass the variables as arguments to the function.

Like inheritance, one of the odd things about the DuplicateHandle function is that the target process is not given any notification that a new kernel object is now accessible to it. So, Process C must somehow notify Process T that it now has access to a kernel object and must use some form of interprocess communication to pass the handle value in hObj to Process T. Obviously, using a command-line argument or changing Process T's environment variables is out of the question since the process is already up and running. A window message or some other IPC mechanism must be used.

What I have just explained is the most general usage of DuplicateHandle. As you can see, it is a very flexible function. However, it is rarely used with the involvement of three different processes (partly because it is unlikely that Process C would know the handle value of an object in use by Process S). Usually, DuplicateHandle is called when only two processes are involved. Imagine a situation in which one process has access to an object that another process wants access to, or a case in which one process wants to give access to a kernel object to another process. For example, let's say that Process S has access to a kernel object and wants to give Process T access to this object. To do this, you would call DuplicateHandle as follows:

// 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);

HANDLE hObjProcessT;         // An uninitialized handle relative to Process T.

// Give Process T access to our mutex object.
DuplicateHandle(GetCurrentProcess(), hObjProcessS, hProcessT, 
         &hObjProcessT, 0, FALSE, DUPLICATE_SAME_ACCESS);

// Use some IPC mechanism to get the handle
// value in hObjProcessS 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);

The call to GetCurrentProcess returns a pseudo-handle that always identifies the calling process—Process S in this example. Once DuplicateHandle returns, hObjProcessT is a handle relative to Process T that identifies the same object that hObjProcessS's handle does when referenced by code in Process S. Process S should never execute the following code:

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

If Process S were to execute this code, the call might or might not fail. The call would succeed if Process S happened to have access to a kernel object with the same handle value as hObjProcessT. This call would have the effect of closing some object so that Process S no longer had access to it, which would certainly cause the application to behave undesirably (to put it nicely).

Here is another way to use DuplicateHandle: Suppose that a process has read and write access to a file-mapping object. At some point a function is called that is supposed to access the file-mapping object by reading it. To make our application more robust, we can use DuplicateHandle to create a new handle for the existing object and ensure that this new handle has read-only access on it. We would then pass this read-only handle to the function; this way, the code in the function would never be able to accidentally write to the file-mapping object. The following code illustrates this example:

int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE, 
         LPSTR szCmdLine, int nCmdShow) {

         // Create a file-mapping object; the handle has read/write access.
         HANDLE hFileMapRW = CreateFileMapping(INVALID_HANDLE_VALUE, 
            NULL, PAGE_READWRITE, 0, 10240, NULL);

         // Create another handle to the file-mapping object;
         // the handle has read-only access.
         HANDLE hFileMapRO;
         DuplicateHandle(GetCurrentProcess(), hFileMapRW, GetCurrentProcess(),
      &hFileMapRO, FILE_MAP_READ, FALSE, 0);

         // Call the function that should only read from the file 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 doesn’t access the file mapping anymore,
         // close it.
         CloseHandle(hFileMapRW);
}

n When a process creates an object, it receives a handle to it
n Handles prevents direct access to objects
n Handles provide for consistent interface to objects
n The created object lives in kernel space
n Object handle is an index into a process handle table
n Code in kernel mode can manipulate objects directly
n Handle Table Entries are two 32-bit values
n 32-byte aligned pointer to object header
n Flags
n Inheritance designation: will handle be inherited by a child process?
n Protect from close
n Audit on close
n
 
Pointer to object header
A
P
I
Access Mask
Access Mask: a product of requested access rights and allowed access rights granted by Security Reference Monitor
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值