共用方式為


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

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

如果 hSourceHandleGetCurrentProcess 或 GetCurrentThread 所傳回的虛擬句柄,則 hSourceProcessHandle 應該是呼叫 DuplicateHandle 的進程句柄。

[in] hTargetProcessHandle

要接收重複句柄之進程的句柄。 句柄必須具有PROCESS_DUP_HANDLE訪問許可權。

此參數是選擇性的,如果 DUPLICATE_CLOSE_SOURCE 旗標是在 Options中設定,則可以指定為 NULL。

[out] lpTargetHandle

接收重複句柄之變數的指標。 這個句柄值在目標進程的內容中有效。

如果 hSourceHandleGetCurrentProcess 或 GetCurrentThread 傳回的虛擬句柄,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 可以將句柄重複至下列類型的 物件。

物體 說明
存取憑證 句柄是由 CreateRestrictedToken、DuplicateTokenDuplicateTokenExOpenProcessToken 或 OpenThreadToken 函式所傳回。
變更通知 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 函式傳回。
登錄鍵 RegCreateKeyRegCreateKeyExRegOpenKey 或 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。

範例

下列範例會建立 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 應用程式]
目標平臺 窗戶
頁首 handleapi.h (包括 Windows.h)
程式庫 內核 32.lib
DLL Kernel32.dll

另請參閱

CloseHandle

處理繼承

句柄和物件函式