Object Handles

Drivers and user-mode components access most system-defined objects through handles. Handles are represented by the HANDLE opaque data type. (Note that handles are not used to access device objects or driver objects.)

For most object types, the kernel-mode routine that creates or opens the object provides a handle to the caller. The caller then uses that handle in subsequent operations on the object.

Here is a list of object types that drivers typically use, and the routines that provide handles to objects of that type.

Object type Corresponding create/open routine


IoCreateFile, ZwCreateFile, ZwOpenFile

Registry keys

IoOpenDeviceInterfaceRegistryKey, IoOpenDeviceRegistryKey, ZwCreateKey, ZwOpenKey




IoCreateSynchronizationEvent, IoCreateNotificationEvent

Symbolic links


Directory objects


Section objects


When the driver no longer requires access to the object, it calls the ZwClose routine to close the handle. This works for all of the object types listed in the table above.

Most of the routines that provide handles take an OBJECT_ATTRIBUTES structure as a parameter. This structure can be used to specify attributes for the handle.

Drivers can specify the following handle attributes:


    The handle can only be accessed from kernel mode.


    Any children of the current process receive a copy of the handle when they are created.


    This attribute specifies that the system performs all access checks on the handle. By default, the system bypasses all access checks on handles created in kernel mode.

Use the InitializeObjectAttributes routine to set these attributes in an OBJECT_ATTRIBUTES structure.

For information about validating object handles, see Failure to Validate Object Handles.

Private Object Handles

Whenever a driver creates an object handle for its private use, the driver must specify the OBJ_KERNEL_HANDLE attribute. This ensures that the handle is inaccessible to user-mode applications.

Shared Object Handles

A driver that shares object handles between kernel mode and user mode must be carefully written to avoid accidentally creating security holes. Here are some guidelines:

  1. Create handles in kernel mode and pass them to user mode, instead of the other way around. Handles created by a user-mode component and passed to the driver should not be trusted.

  2. If the driver must manipulate handles on behalf of user-mode applications, use the OBJ_FORCE_ACCESS_CHECK attribute to verify that the application has the necessary access.

  3. Use ObReferenceObjectByPointer to keep a kernel-mode reference on a shared handle. Otherwise, if a user-mode component closes the handle, the reference count goes to zero, and if the driver then tries to use or close the handle the system will crash.

If a user-mode application creates an event object, a driver can safely wait for that event to be signaled, but only if the application passes a handle to the event object to the driver through an IOCTL. The driver must handle the IOCTL in the context of the process that created the event and must validate that the handle is an event handle by calling ObReferenceObjectByHandle.