Función DuplicateHandle (handleapi.h)

Duplica un identificador de objeto.

Sintaxis

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

Parámetros

[in] hSourceProcessHandle

Identificador del proceso con el identificador que se va a duplicar.

El identificador debe tener el derecho de acceso PROCESS_DUP_HANDLE. Para obtener más información, consulte Derechos de acceso y seguridad de procesos.

[in] hSourceHandle

Identificador que se va a duplicar. Se trata de un identificador de objeto abierto que es válido en el contexto del proceso de origen. Para obtener una lista de objetos cuyos identificadores se pueden duplicar, vea la siguiente sección Comentarios.

[in] hTargetProcessHandle

Identificador del proceso que va a recibir el identificador duplicado. El identificador debe tener el derecho de acceso PROCESS_DUP_HANDLE.

Este parámetro es opcional y se puede especificar como NULL si la marca DUPLICATE_CLOSE_SOURCE está establecida en Opciones.

[out] lpTargetHandle

Puntero a una variable que recibe el identificador duplicado. Este valor de identificador es válido en el contexto del proceso de destino.

Si hSourceHandle es un pseudo identificador devuelto por GetCurrentProcess o GetCurrentThread, DuplicateHandle lo convierte en un identificador real en un proceso o subproceso, respectivamente.

Si lpTargetHandle es NULL, la función duplica el identificador, pero no devuelve el valor de identificador duplicado al autor de la llamada. Este comportamiento solo existe para la compatibilidad con versiones anteriores de esta función. No debe usar esta característica, ya que perderá los recursos del sistema hasta que finalice el proceso de destino.

Este parámetro se omite si hTargetProcessHandle es NULL.

[in] dwDesiredAccess

El acceso solicitado para el nuevo identificador. Para ver las marcas que se pueden especificar para cada tipo de objeto, vea la sección Comentarios siguiente.

Este parámetro se omite si el parámetro dwOptions especifica la marca DUPLICATE_SAME_ACCESS. De lo contrario, las marcas que se pueden especificar dependen del tipo de objeto cuyo identificador se va a duplicar.

Este parámetro se omite si hTargetProcessHandle es NULL.

[in] bInheritHandle

Variable que indica si el identificador es heredable. Si es TRUE, los nuevos procesos creados por el proceso de destino pueden heredar el identificador duplicado. Si es FALSE, no se puede heredar el nuevo identificador.

Este parámetro se omite si hTargetProcessHandle es NULL.

[in] dwOptions

Acciones opcionales. Este parámetro puede ser cero o cualquier combinación de los valores siguientes.

Valor Significado
DUPLICATE_CLOSE_SOURCE
0x00000001
Cierra el identificador de origen. Esto ocurre independientemente de cualquier estado de error devuelto.
DUPLICATE_SAME_ACCESS
0x00000002
Omite el parámetro dwDesiredAccess . El identificador duplicado tiene el mismo acceso que el identificador de origen.

Valor devuelto

Si la función se realiza correctamente, el valor devuelto es distinto de cero.

Si la función no se realiza correctamente, el valor devuelto es cero. Para obtener información de error extendida, llame a GetLastError.

Comentarios

El identificador duplicado hace referencia al mismo objeto que el identificador original. Por lo tanto, los cambios realizados en el objeto se reflejan a través de ambos identificadores. Por ejemplo, si duplica un identificador de archivo, la posición del archivo actual siempre es la misma para ambos identificadores. Para que los identificadores de archivo tengan diferentes posiciones de archivo, use la función CreateFile para crear identificadores de archivo que comparten el acceso al mismo archivo.

Se puede llamar a DuplicateHandle mediante el proceso de origen o el proceso de destino (o un proceso que sea el proceso de origen y de destino). Por ejemplo, un proceso puede usar DuplicateHandle para crear un duplicado no heredable de un identificador heredable o un identificador con acceso diferente al identificador original.

El proceso de origen usa la función GetCurrentProcess para obtener un identificador a sí mismo. Este identificador es un pseudo handle, pero DuplicateHandle lo convierte en un identificador de proceso real. Para obtener el identificador del proceso de destino, puede ser necesario usar alguna forma de comunicación entre procesos (por ejemplo, una canalización con nombre o memoria compartida) para comunicar el identificador de proceso al proceso de origen. El proceso de origen puede usar este identificador en la función OpenProcess para obtener un identificador para el proceso de destino.

Si el proceso que llama a DuplicateHandle no es también el proceso de destino, el proceso de origen debe usar la comunicación entre procesos para pasar el valor del identificador duplicado al proceso de destino.

DuplicateHandle se puede usar para duplicar un identificador entre un proceso de 32 bits y un proceso de 64 bits. El identificador resultante tiene el tamaño adecuado para funcionar en el proceso de destino. Para obtener más información, consulte Interoperabilidad de procesos.

DuplicateHandle puede duplicar identificadores para los siguientes tipos de objetos.

Object Descripción
Access token El identificador lo devuelve la función CreateRestrictedToken, DuplicateToken, DuplicateTokenEx, OpenProcessToken o OpenThreadToken .
Notificación de cambios La función FindFirstChangeNotification devuelve el identificador.
Dispositivo de comunicaciones La función CreateFile devuelve el identificador.
Entrada de la consola La función CreateFile devuelve el identificador cuando se especifica CONIN$ o mediante la función GetStdHandle cuando se especifica STD_INPUT_HANDLE. Los identificadores de consola solo se pueden duplicar para su uso en el mismo proceso.
Búfer de pantalla de la consola La función CreateFile devuelve el identificador cuando se especifica CONOUT$ o mediante la función GetStdHandle cuando se especifica STD_OUTPUT_HANDLE. Los identificadores de consola solo se pueden duplicar para su uso en el mismo proceso.
Escritorio La función GetThreadDesktop devuelve el identificador.
Evento El identificador lo devuelve la función CreateEvent o OpenEvent .
Archivo La función CreateFile devuelve el identificador.
Asignación de archivos La función CreateFileMapping devuelve el identificador.
Trabajo La función CreateJobObject devuelve el identificador.
Mailslot La función CreateMailslot devuelve el identificador.
Mutex El identificador lo devuelve CreateMutex o [OpenMutex](.. Función /synchapi/nf-synchapi-openmutexw.md).
Pipe La función CreateNamedPipe o CreateFile devuelve un identificador de canalización con nombre. La función CreatePipe devuelve un identificador de canalización anónimo.
Proceso El identificador lo devuelve la función CreateProcess, GetCurrentProcess o OpenProcess .
Clave del Registro El identificador lo devuelve la función RegCreateKey, RegCreateKeyEx, RegOpenKey o RegOpenKeyEx . Tenga en cuenta que los identificadores de clave del Registro devueltos por la función RegConnectRegistry no se pueden usar en una llamada a DuplicateHandle.
Semaphore La función CreateSemaphore o OpenSemaphore devuelve el identificador.
Thread El identificador lo devuelve la función CreateProcess, CreateThread, CreateRemoteThread o GetCurrentThread .
Temporizador El identificador lo devuelve la función CreateWaitableTimerW o OpenWaitableTimerW .
Transacción La función CreateTransaction devuelve el identificador.
Estación de ventana La función GetProcessWindowStation devuelve el identificador.
 

No debe usar DuplicateHandle para duplicar identificadores de los objetos siguientes:

  • Puertos de finalización de E/S. No se devuelve ningún error, pero no se puede usar el identificador duplicado.
  • Sockets. No se devuelve ningún error, pero Winsock no reconoce el identificador duplicado en el proceso de destino. Además, el uso de DuplicateHandle interfiere con el recuento de referencias internas en el objeto subyacente. Para duplicar un identificador de socket, use la función WSADuplicateSocket .
  • Pseudo-handles distintos de los devueltos por las funciones GetCurrentProcess o GetCurrentThread .
El parámetro dwDesiredAccess especifica los derechos de acceso del nuevo identificador. Todos los objetos admiten los derechos de acceso estándar. Los objetos también pueden admitir derechos de acceso adicionales en función del tipo de objeto. Para obtener más información, vea los temas siguientes: En algunos casos, el nuevo identificador puede tener más derechos de acceso que el identificador original. Sin embargo, en otros casos, DuplicateHandle no puede crear un identificador con más derechos de acceso que el original. Por ejemplo, un identificador de archivo creado con el derecho de acceso GENERIC_READ no se puede duplicar para que tenga el derecho de acceso GENERIC_READ y GENERIC_WRITE.

Normalmente, el proceso de destino cierra un identificador duplicado cuando ese proceso finaliza con el identificador . Para cerrar un identificador duplicado del proceso de origen, llame a DuplicateHandle con los parámetros siguientes:

  • Establezca hSourceProcessHandle en el proceso de destino desde la llamada DuplicateHandle que creó el identificador.
  • Establezca hSourceHandle en el identificador duplicado para cerrar.
  • Establezca hTargetProcessHandle en NULL.
  • Establezca dwOptions en DUPLICATE_CLOSE_SOURCE.

Ejemplos

En el ejemplo siguiente se crea una exclusión mutua, se duplica un identificador para la exclusión mutua y se pasa a otro subproceso. Duplicar el identificador garantiza que se aumente el recuento de referencias para que el objeto de exclusión mutua no se destruya hasta que ambos subprocesos hayan cerrado el identificador.

#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;
}

Requisitos

Requisito Value
Cliente mínimo compatible Windows 2000 Professional [aplicaciones de escritorio | Aplicaciones para UWP]
Servidor mínimo compatible Windows 2000 Server [aplicaciones de escritorio | Aplicaciones para UWP]
Plataforma de destino Windows
Encabezado handleapi.h (incluir Windows.h)
Library Kernel32.lib
Archivo DLL Kernel32.dll

Vea también

CloseHandle

Control de la herencia

Funciones handle y object