regmon portmon filemon windows handle

portmon - ¿Qué es un controlador de Windows?



windows psexec (8)

¿Qué es un "Manejar" cuando se discuten los recursos en Windows? ¿Cómo trabajan?


Entonces, en el nivel más básico, una MANIJA de cualquier tipo es un puntero a un puntero o

#define HANDLE void **

Ahora en cuanto a por qué querrías usarlo

Vamos a tomar una configuración:

class Object{ int Value; } class LargeObj{ char * val; LargeObj() { val = malloc(2048 * 1000); } } void foo(Object bar){ LargeObj lo = new LargeObj(); bar.Value++; } void main() { Object obj = new Object(); obj.val = 1; foo(obj); printf("%d", obj.val); }

Entonces, como obj fue pasado por valor (hacer una copia y dárselo a la función) para foo, el printf imprimirá el valor original de 1.

Ahora si actualizamos foo a:

void foo(Object * bar) { LargeObj lo = new LargeObj(); bar->val++; }

Existe la posibilidad de que printf imprima el valor actualizado de 2. Pero también existe la posibilidad de que foo cause algún tipo de corrupción de memoria o excepción.

El motivo es que mientras usa un puntero para pasar obj a la función, también está asignando 2 Megas de memoria, esto podría hacer que el sistema operativo mueva la memoria para actualizar la ubicación de obj. Como ha pasado el puntero por valor, si obj se mueve, el SO actualiza el puntero pero no la copia en la función y puede causar problemas.

Una actualización final para foo de:

void foo(Object **bar){ LargeObj lo = LargeObj(); Object * b = &bar; b->val++; }

Esto siempre imprimirá el valor actualizado.

Ver, cuando el compilador asigna memoria para punteros, los marca como inamovibles, por lo que cualquier reordenación de la memoria causada por el objeto grande al que se le asigna el valor pasado a la función apuntará a la dirección correcta para averiguar la ubicación final en la memoria. actualizar.

Cualquier tipo particular de HANDLEs (hWnd, FILE, etc.) son específicos del dominio y apuntan a cierto tipo de estructura para proteger contra la corrupción de memoria.


Es un valor de referencia abstracto para un recurso, a menudo la memoria o un archivo abierto, o una tubería.

Correctamente , en Windows, (y generalmente en informática), un identificador es una abstracción que oculta una dirección de memoria real del usuario API, lo que permite que el sistema reorganice la memoria física de forma transparente para el programa. La resolución de un identificador en un puntero bloquea la memoria y al soltar el identificador se invalida el puntero. En este caso, piense en ello como un índice en una tabla de punteros ... usa el índice para las llamadas a la API del sistema, y ​​el sistema puede cambiar el puntero en la tabla a voluntad.

Alternativamente, se puede asignar un puntero real como manejador cuando el autor de la API pretende que el usuario de la API esté aislado de los detalles de a qué apunta la dirección; en este caso, debe considerarse que lo que indica el identificador puede cambiar en cualquier momento (desde la versión de la API a la versión o incluso desde la llamada a la API que devuelve el identificador); por lo tanto, el identificador debe tratarse simplemente como un valor opaco significativo solo para la API.

Debo añadir que en cualquier sistema operativo moderno, incluso los llamados "punteros reales" siguen siendo identificadores opacos en el espacio de la memoria virtual del proceso, lo que permite al O / S administrar y reorganizar la memoria sin invalidar los punteros dentro del proceso. .


Piense en la ventana de Windows como una estructura que lo describe. Esta estructura es una parte interna de Windows y no necesita conocer los detalles. En cambio, Windows proporciona un typedef para puntero a struct para esa estructura. Ese es el "mango" con el que puedes agarrarte a la ventana.


Un identificador es como el valor de clave principal de un registro en una base de datos.

edit 1: bueno, por qué el downvote, una clave primaria identifica de manera única un registro de la base de datos, y un identificador en el sistema de Windows identifica de forma única una ventana, un archivo abierto, etc. Eso es lo que estoy diciendo.


Un identificador es un identificador único para un objeto administrado por Windows. Es como un puntero , pero no como un puntero en el sentido de que no es una dirección a la que el código del usuario pueda desreferenciar para obtener acceso a algunos datos. En su lugar, un identificador debe pasarse a un conjunto de funciones que pueden realizar acciones en el objeto identificado por el identificador.


Un objeto es una estructura de datos que representa un recurso del sistema, como un archivo, hilo o imagen gráfica. Una aplicación no puede acceder directamente a los datos del objeto o al recurso del sistema que representa un objeto. En cambio, una aplicación debe obtener un identificador de objeto, que puede usar para examinar o modificar el recurso del sistema. Cada identificador tiene una entrada en una tabla mantenida internamente. Estas entradas contienen las direcciones de los recursos y los medios para identificar el tipo de recurso.


Una HANDLE en la programación de Win32 es un token que representa un recurso administrado por el kernel de Windows. Un identificador puede ser una ventana, un archivo, etc.

Los identificadores son simplemente una forma de identificar un recurso de partículas con el que desea trabajar utilizando las API de Win32.

Por ejemplo, si quiere crear una ventana y mostrarla en la pantalla, puede hacer lo siguiente:

// Create the window HWND hwnd = CreateWindow(...); if (!hwnd) return; // hwnd not created // Show the window. ShowWindow(hwnd, SW_SHOW);

En el ejemplo anterior, HWND significa "manejar una ventana".

Si está acostumbrado a un lenguaje orientado a objetos, puede pensar en un MANIBRIO como una instancia de una clase sin métodos cuyo estado solo es modificable por otras funciones. En este caso, la función ShowWindow modifica el estado de Window HANDLE.

Vea los identificadores y tipos de datos para más información.


A HANDLE es un identificador único específico del contexto. Por contexto específico, quiero decir que un identificador obtenido de un contexto no necesariamente se puede usar en cualquier otro contexto aribtrary que también funcione en HANDLE .

Por ejemplo, GetModuleHandle devuelve un identificador único a un módulo cargado actualmente. El identificador devuelto se puede usar en otras funciones que aceptan identificadores de módulo. No puede asignarse a funciones que requieren otros tipos de identificadores. Por ejemplo, no podría dar un manejador devuelto por GetModuleHandle a HeapDestroy y esperar que haga algo sensato.

El HANDLE sí es solo un tipo integral. Por lo general, pero no necesariamente, es un puntero a algún tipo subyacente o ubicación de memoria. Por ejemplo, la HANDLE devuelta por GetModuleHandle es en realidad un puntero a la dirección de memoria virtual base del módulo. Pero no hay ninguna regla que establezca que los identificadores deben ser punteros. Un identificador también podría ser simplemente un entero (que posiblemente podría ser utilizado por alguna API de Win32 como un índice en una matriz).

HANDLE s son representaciones intencionalmente opacas que proporcionan encapsulación y abstracción de recursos internos de Win32. De esta forma, las API de Win32 podrían potencialmente cambiar el tipo subyacente detrás de un HANDLE, sin que afecte el código de usuario de ninguna manera (al menos esa es la idea).

Considere estas tres implementaciones internas diferentes de una API de Win32 que acabo de inventar, y asuma que Widget es una struct .

Widget * GetWidget (std::string name) { Widget *w; w = findWidget(name); return w; }

void * GetWidget (std::string name) { Widget *w; w = findWidget(name); return reinterpret_cast<void *>(w); }

typedef void * HANDLE; HANDLE GetWidget (std::string name) { Widget *w; w = findWidget(name); return reinterpret_cast<HANDLE>(w); }

El primer ejemplo expone los detalles internos sobre la API: permite que el código de usuario sepa que GetWidget devuelve un puntero a un struct Widget . Esto tiene un par de consecuencias:

  • el código de usuario debe tener acceso al archivo de encabezado que define la estructura de Widget
  • el código de usuario podría modificar partes internas de la estructura de Widget devuelta

Ambas consecuencias pueden ser indeseables.

El segundo ejemplo oculta este detalle interno del código de usuario, devolviendo simplemente void * . El código de usuario no necesita acceso al encabezado que define la estructura del Widget .

El tercer ejemplo es exactamente el mismo que el segundo, pero en su lugar llamamos void * a HANDLE . Quizás esto desaliente que el código de usuario trate de descubrir exactamente a qué apunta el void * .

¿Por qué pasar por este problema? Considere este cuarto ejemplo de una versión más nueva de esta misma API:

typedef void * HANDLE; HANDLE GetWidget (std::string name) { NewImprovedWidget *w; w = findImprovedWidget(name); return reinterpret_cast<HANDLE>(w); }

Tenga en cuenta que la interfaz de la función es idéntica al tercer ejemplo anterior. Esto significa que el código de usuario puede seguir utilizando esta nueva versión de la API, sin ningún cambio, incluso aunque la implementación "detrás de escena" haya cambiado para usar la estructura NewImprovedWidget .

Los identificadores en estos ejemplos son realmente solo un nuevo nombre, presumiblemente más amigable, para void * , que es exactamente lo que es HANDLE en la API de Win32 ( búscalo en MSDN ). Proporciona una pared opaca entre el código de usuario y las representaciones internas de la biblioteca Win32 que aumenta la portabilidad, entre las versiones de Windows, del código que usa la API de Win32.