複製物件句柄。
語法
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 旗標是在 Options中設定,則可以指定為 NULL。
[out] lpTargetHandle
接收重複句柄之變數的指標。 這個句柄值在目標進程的內容中有效。
如果 hSourceHandle 是 GetCurrentProcess 或 GetCurrentThread 傳回的虛擬句柄,DuplicateHandle 會分別將它轉換成進程或線程的實際句柄。
如果 lpTargetHandle 為 NULL,函式會複製句柄,但不會將重複的句柄值傳回給呼叫端。 此行為僅適用於與舊版此函式的回溯相容性。 您不應該使用這項功能,因為目標進程終止之前將會遺失系統資源。
如果 hTargetProcessHandle 為 NULL,則會忽略此參數。
[in] dwDesiredAccess
要求新句柄的存取權。 如需每個物件類型可以指定的旗標,請參閱下列一節。
如果 dwOptions 參數指定DUPLICATE_SAME_ACCESS旗標,則會忽略此參數。 否則,可以指定的旗標取決於要複製句柄的物件類型。
如果 hTargetProcessHandle 為 NULL,則會忽略此參數。
[in] bInheritHandle
變數,指出句柄是否可繼承。 如果 為TRUE,則目標進程所建立的新進程可以繼承重複的句柄。 如果 為 FALSE,則無法繼承新的句柄。
如果 hTargetProcessHandle 為 NULL,則會忽略此參數。
[in] dwOptions
選擇性動作。 此參數可以是零,或下列值的任何組合。
| 價值觀 | 意義 |
|---|---|
|
關閉來源句柄。 不論傳回的任何錯誤狀態為何,都會發生此情況。 |
|
忽略 dwDesiredAccess 參數。 重複的句柄具有與來源句柄相同的存取權。 |
返回值
如果函式成功,則傳回值為非零值。
如果函式失敗,傳回值為零。 若要取得擴充的錯誤資訊,請呼叫 GetLastError。
備註
重複句柄是指與原始句柄相同的物件。 因此,物件的任何變更都會透過這兩個句柄反映。 例如,如果您複製檔句柄,則這兩個句柄的目前檔案位置一律相同。 若要讓檔句柄具有不同的檔案位置,請使用 CreateFile 函式來建立檔案句柄,以共用相同檔案的存取權。
來源進程或目標進程可以呼叫 DuplicateHandle(或來源和目標進程)。 例如,進程可以使用 DuplicateHandle 來建立不可繼承句柄的不可繼承複本,或是具有與原始句柄不同存取權的句柄。
來源進程會使用 GetCurrentProcess 函式來取得本身的句柄。 此句柄是虛擬句柄,但 DuplicateHandle 會將它轉換成實際的進程句柄。 若要取得目標進程句柄,可能需要使用某種形式的進程間通訊(例如,命名管道或共用記憶體),將進程標識碼傳達給來源進程。 來源進程可以使用 OpenProcess 函式中的這個識別碼來取得目標進程的句柄。
如果呼叫 DuplicateHandle 的進程不是目標進程,來源進程必須使用進程間通訊,將重複句柄的值傳遞至目標進程。
DuplicateHandle 可用來在32位進程與64位進程之間複製句柄。 產生的句柄會適當地調整大小,以在目標進程中運作。 如需詳細資訊,請參閱 處理互作性。
DuplicateHandle 可以將句柄重複至下列類型的 物件。
| 物體 | 說明 |
|---|---|
| 存取憑證 | 句柄是由 CreateRestrictedToken、DuplicateToken、DuplicateTokenEx、OpenProcessToken 或 OpenThreadToken 函式所傳回。 |
| 變更通知 | FindFirstChangeNotification 函式會傳回句柄。 |
| 通訊裝置 | CreateFile 函式會傳回句柄。 |
| 主控台輸入 | 指定 CONIN$ 時, CreateFile 函式會傳回句柄,或指定STD_INPUT_HANDLE時由 GetStdHandle 函式傳回。 控制台句柄可以重複,以便只在同一個進程中使用。 |
| 控制台畫面緩衝區 | 指定 CONOUT$ 時, CreateFile 函式會傳回句柄,或指定STD_OUTPUT_HANDLE時 由 GetStdHandle 函式傳回。 控制台句柄可以重複,以便只在同一個進程中使用。 |
| 桌面 | GetThreadDesktop 函式會傳回句柄。 |
| 事件 | 句柄是由 CreateEvent 或 OpenEvent 函式傳回。 |
| 檔案 | CreateFile 函式會傳回句柄。 |
| 檔案對應 | CreateFileMapping 函式會傳回句柄。 |
| 工作 | 句柄是由 CreateJobObject 函式傳回。 |
| Mailslot | CreateMailslot 函式會傳回句柄。 |
| 互斥 | 句柄是由 CreateMutex 或 [OpenMutex](.. 傳回。/synchapi/nf-synchapi-openmutexw.md) 函式。 |
| 管 | CreateNamedPipe 或 CreateFile 函式會傳回命名管道句柄。 CreatePipe 函式會傳回匿名管道句柄。 |
| 流程 | 句柄是由 CreateProcess、 GetCurrentProcess 或 OpenProcess 函式傳回。 |
| 登錄鍵 | RegCreateKey、RegCreateKeyEx、RegOpenKey 或 RegOpenKeyEx 函式會傳回句柄。 請注意, RegConnectRegistry 函式傳回的登錄機碼句柄無法在 對 DuplicateHandle 的呼叫中使用。 |
| 信號量 | 句柄是由 CreateSemaphore 或 OpenSemaphore 函式傳回。 |
| 線程 | 句柄是由 CreateProcess、 CreateThread、 CreateRemoteThread 或 GetCurrentThread 函式傳回 |
| 定時器 | 句柄是由 CreateWaitableTimerW 或 OpenWaitableTimerW 函 式傳回。 |
| 交易 | CreateTransaction 函式會傳回句柄。 |
| 視窗月臺 | GetProcessWindowStation 函式會傳回句柄。 |
您不應該使用 DuplicateHandle 複製下列物件的句柄:
- I/O 完成埠。 不會傳回錯誤,但無法使用重複的句柄。
- 插座。 不會傳回錯誤,但目標進程的 Winsock 可能無法辨識重複的句柄。 此外,使用 DuplicateHandle 會干擾基礎對象的內部參考計數。 若要複製套接字句柄,請使用 WSADuplicateSocket 函式。
- 除了 GetCurrentProcess 或 GetCurrentThread 函式所傳回的虛擬句柄以外。
- 桌面安全性與訪問許可權
- 檔案安全性和訪問許可權
- File-Mapping 安全性和訪問許可權
- 作業物件安全性和訪問許可權
- 進程安全性和訪問許可權
- 登錄機碼安全性和訪問許可權
- 同步處理物件安全性和訪問許可權
- 線程安全性和訪問許可權
- Window-Station 安全性和訪問許可權
目標進程通常會在使用句柄完成時關閉重複的句柄。 若要從來源進程關閉重複的句柄,請使用下列參數呼叫 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 |