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

要複製的句柄。 這是在來源進程內容中有效的開啟物件句柄。 如需可複製句柄的物件清單,請參閱下列一節。

[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 可以複製下列類型的物件句柄。

Object 描述
存取權杖 句柄是由 CreateRestrictedTokenDuplicateToken、DuplicateTokenExOpenProcessTokenOpenThreadToken 函式傳回。
變更通知 FindFirstChangeNotification 函式會傳回句柄。
通訊裝置 CreateFile 函式會傳回句柄。
主控台輸入 當指定 CONIN$ 時, CreateFile 函式會傳回句柄,或在指定STD_INPUT_HANDLE時由 GetStdHandle 函式傳回。 控制台句柄可以重複,只用於相同的進程。
控制台畫面緩衝區 當指定 CONOUT$ 時, CreateFile 函式會傳回句柄,或在指定STD_OUTPUT_HANDLE時由 GetStdHandle 函式傳回。 控制台句柄可以重複,只用於相同的進程。
桌面 句柄是由 GetThreadDesktop 函式傳回。
事件 CreateEventOpenEvent 函式會傳回句柄。
檔案 CreateFile 函式會傳回句柄。
檔案對應 CreateFileMapping 函式會傳回句柄。
作業 CreateJobObject 函式會傳回句柄。
Mailslot CreateMailslot 函式會傳回句柄。
Mutex CreateMutex 或 [ OpenMutex ] ( 會傳回句柄。/synchapi/nf-synchapi-openmutexw.md) 函式。
Pipe 命名管道句柄是由 CreateNamedPipeCreateFile 函式傳回。 CreatePipe 函式會傳回匿名管道句柄。
流程 CreateProcess、GetCurrentProcessOpenProcess 函式會傳回句柄。
登錄機碼 RegCreateKeyRegCreateKeyExRegOpenKey 或 RegOpenKeyEx式會傳回句柄。 請注意, RegConnectRegistry 函式所傳回的登錄機碼句柄不能用於對 DuplicateHandle 的呼叫。
Semaphore 句柄是由 CreateSemaphoreOpenSemaphore 函式傳回。
執行緒 CreateProcess、CreateThreadCreateRemoteThreadGetCurrentThread 函式會傳回句柄
計時器 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。

範例

下列範例會建立 mutex、複製 mutex 的句柄,並將它傳遞給另一個線程。 複製句柄可確保參考計數增加,因此在兩個線程都關閉句柄之前,Mutex 物件將不會終結。

#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 專業版 [傳統型應用程式 |UWP 應用程式]
最低支援的伺服器 Windows 2000 Server [傳統型應用程式 |UWP 應用程式]
目標平台 Windows
標頭 handleapi.h (包含 Windows.h)
程式庫 Kernel32.lib
DLL Kernel32.dll

另請參閱

CloseHandle

處理繼承

句柄和物件函式