DuplicateHandle 函数 (handleapi.h)

复制对象句柄。

语法

BOOL DuplicateHandle(
  [in]  HANDLE   hSourceProcessHandle,
  [in]  HANDLE   hSourceHandle,
  [in]  HANDLE   hTargetProcessHandle,
  [out] LPHANDLE lpTargetHandle,
  [in]  DWORD    dwDesiredAccess,
  [in]  BOOL     bInheritHandle,
  [in]  DWORD    dwOptions
);

参数

[in] hSourceProcessHandle

要复制的句柄的进程句柄。

句柄必须具有PROCESS_DUP_HANDLE访问权限。 有关详细信息,请参阅 进程安全性和访问权限

[in] hSourceHandle

要复制的句柄。 这是在源进程的上下文中有效的开放对象句柄。 有关可以复制其句柄的对象的列表,请参阅以下“备注”部分。

如果 hSourceHandle 是由 GetCurrentProcess 或 GetCurrentThread 返回的伪句柄,则 hSourceProcessHandle 应该是调用 DuplicateHandle 的进程句柄

[in] hTargetProcessHandle

要接收重复句柄的进程句柄。 句柄必须具有PROCESS_DUP_HANDLE访问权限。

此参数是可选的,如果 选项中设置 DUPLICATE_CLOSE_SOURCE 标志,则可以指定为 NULL。

[out] lpTargetHandle

指向接收重复句柄的变量的指针。 此句柄值在目标进程的上下文中有效。

如果 hSourceHandleGetCurrentProcessGetCurrentThread 返回的伪句柄, 则 DuplicateHandle 将分别转换为进程或线程的实际句柄。

如果 lpTargetHandleNULL,则该函数将复制句柄,但不向调用方返回重复句柄值。 此行为仅用于向后兼容此函数的早期版本。 不应使用此功能,因为目标进程终止之前将丢失系统资源。

如果 hTargetProcessHandleNULL,则忽略此参数。

[in] dwDesiredAccess

为新句柄请求的访问。 有关可为每个对象类型指定的标志,请参阅以下“备注”部分。

如果 dwOptions 参数指定DUPLICATE_SAME_ACCESS标志,则忽略此参数。 否则,可以指定的标志取决于要复制其句柄的对象的类型。

如果 hTargetProcessHandleNULL,则忽略此参数。

[in] bInheritHandle

一个变量,指示句柄是否可继承。 如果 为 TRUE,则重复句柄可由目标进程创建的新进程继承。 如果 为 FALSE,则无法继承新句柄。

如果 hTargetProcessHandleNULL,则忽略此参数。

[in] dwOptions

可选作。 此参数可以是零,也可以是以下值的任意组合。

价值 含义
DUPLICATE_CLOSE_SOURCE
0x00000001
关闭源句柄。 无论返回的任何错误状态如何,都会发生这种情况。
DUPLICATE_SAME_ACCESS
0x00000002
忽略 dwDesiredAccess 参数。 重复句柄具有与源句柄相同的访问权限。

返回值

如果函数成功,则返回值为非零。

如果函数失败,则返回值为零。 若要获取扩展的错误信息,请调用 GetLastError

注解

重复句柄引用与原始句柄相同的对象。 因此,对对象所做的任何更改都通过这两个句柄反映。 例如,如果复制文件句柄,则两个句柄的当前文件位置始终相同。 若要使文件句柄具有不同的文件位置,请使用 CreateFile 函数创建共享对同一文件的访问权限的文件句柄。

源进程或目标进程(或源进程和目标进程)可以调用 DuplicateHandle。 例如,进程可以使用 DuplicateHandle 创建可继承句柄的非可继承副本,或者具有与原始句柄不同的访问权限的句柄。

源进程使用 GetCurrentProcess 函数获取自身句柄。 此句柄是伪句柄,但 DuplicateHandle 将其转换为实际进程句柄。 若要获取目标进程句柄,可能需要使用某种形式的进程间通信(例如命名管道或共享内存)将进程标识符传达给源进程。 源进程可以使用 OpenProcess 函数中的此标识符来获取目标进程的句柄。

如果调用 DuplicateHandle 的进程不是目标进程,则源进程必须使用进程间通信将重复句柄的值传递给目标进程。

DuplicateHandle 可用于在 32 位进程和 64 位进程之间复制句柄。 生成的句柄的大小适当,用于在目标进程中工作。 有关详细信息,请参阅 进程互作性

DuplicateHandle 可以复制以下类型的对象的句柄。

物体 DESCRIPTION
访问令牌 句柄由 CreateRestrictedTokenDuplicateToken、DuplicateTokenExOpenProcessTokenOpenThreadToken 函数返回。
更改通知 FindFirstChangeNotification 函数返回句柄。
通信设备 CreateFile 函数返回句柄。
控制台输入 指定 CONIN$ 时 ,CreateFile 函数返回句柄,或者在指定STD_INPUT_HANDLE时由 GetStdHandle 函数返回。 可以复制控制台句柄,以便仅在同一进程中使用。
控制台屏幕缓冲区 指定 CONOUT$ 时 ,CreateFile 函数或指定 STD_OUTPUT_HANDLE时 GetStdHandle 函数返回句柄。 可以复制控制台句柄,以便仅在同一进程中使用。
桌面 句柄由 GetThreadDesktop 函数返回。
事件 / 活动 句柄由 CreateEventOpenEvent 函数返回。
文件 CreateFile 函数返回句柄。
文件映射 CreateFileMapping 函数返回句柄。
工作 CreateJobObject 函数返回句柄。
Mailslot CreateMailslot 函数返回句柄。
互斥 句柄由 CreateMutex 或 [OpenMutex](.) 返回。/synchapi/nf-synchapi-openmutexw.md) 函数。
命名管道句柄由 CreateNamedPipeCreateFile 函数返回。 CreatePipe 函数返回匿名管道句柄。
流程 句柄由 CreateProcessGetCurrentProcessOpenProcess 函数返回。
注册表项 句柄由 RegCreateKey、RegCreateKeyExRegOpenKey 或 RegOpenKeyEx 函数返回。 请注意, RegConnectRegistry 函数返回的注册表项句柄不能用于对 DuplicateHandle 的调用。
信号 句柄由 CreateSemaphoreOpenSemaphore 函数返回。
线程 句柄由 CreateProcessCreateThreadCreateRemoteThreadGetCurrentThread 函数返回
定时器 句柄由 CreateWaitableTimerWOpenWaitableTimerW 函数返回。
交易 句柄由 CreateTransaction 函数返回。
窗口工作站 该句柄由 GetProcessWindowStation 函数返回。
 

不应使用 DuplicateHandle 复制以下对象的句柄:

  • I/O 完成端口。 不会返回错误,但不能使用重复句柄。
  • 插座。 不会返回任何错误,但目标进程中 Winsock 可能无法识别重复句柄。 此外,使用 DuplicateHandle 会干扰基础对象的内部引用计数。 若要复制套接字句柄,请使用 WSADuplicateSocket 函数。
  • GetCurrentProcessGetCurrentThread 函数返回的处理以外的伪句柄。
dwDesiredAccess 参数指定新句柄的访问权限。 所有对象都支持 标准访问权限。 对象还可能支持其他访问权限,具体取决于对象类型。 有关详细信息,请参阅以下主题: 在某些情况下,新句柄可以具有比原始句柄更多的访问权限。 但是,在其他情况下, DuplicateHandle 无法创建具有比原始权限更多的访问权限的句柄。 例如,不能复制使用GENERIC_READ访问权限创建的文件句柄,使其具有GENERIC_READ和GENERIC_WRITE访问权限。

通常,当进程使用句柄完成时,目标进程将关闭重复的句柄。 若要从源进程关闭重复的句柄,请使用以下参数调用 DuplicateHandle

  • 从创建句柄的 DuplicateHandle 调用将 hSourceProcessHandle 设置为目标进程。
  • hSourceHandle 设置为要关闭的重复句柄。
  • hTargetProcessHandle 设置为 NULL
  • dwOptions 设置为DUPLICATE_CLOSE_SOURCE。

例子

以下示例创建互斥体,复制互斥体的句柄,并将其传递给另一个线程。 复制句柄可确保增加引用计数,以便在两个线程关闭句柄之前,互斥体对象不会被销毁。

#include <windows.h>

DWORD CALLBACK ThreadProc(PVOID pvParam);

int main()
{
    HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
    HANDLE hMutexDup, hThread;
    DWORD dwThreadId;

    DuplicateHandle(GetCurrentProcess(), 
                    hMutex, 
                    GetCurrentProcess(),
                    &hMutexDup, 
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS);

    hThread = CreateThread(NULL, 0, ThreadProc, 
        (LPVOID) hMutexDup, 0, &dwThreadId);

    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);

    // Wait for the worker thread to terminate and clean up.
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    return 0;
}

DWORD CALLBACK ThreadProc(PVOID pvParam)
{
    HANDLE hMutex = (HANDLE)pvParam;

    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);
    return 0;
}

要求

要求 价值
最低支持的客户端 Windows 2000 Professional [桌面应用 |UWP 应用]
支持的最低服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 Windows操作系统
标头 handleapi.h (包括 Windows.h)
图书馆 内核 32.lib
DLL Kernel32.dll

另请参阅

CloseHandle

处理继承

句柄和对象函数