Windows objects and handles

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.

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:

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.

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.

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.

Object Handlers

If an OLE server application is a local server, meaning that it runs in its own process space, communication between container and server must occur across process boundaries. Because this process is expensive, OLE relies on a surrogate object loaded into the container’s process space to act on behalf of a local server application. This surrogate object, known as an object handler, services container requests that do not require the attention of the server application, such as requests for drawing. When a container requests something that the object handler cannot provide, the handler communicates with the server application using COM’s out-of-process communication mechanism.

An object handler is unique to an object class. When you create an instance of a handler for one class, you cannot use it for another. When used for a compound document, the object handler implements the container-side data structures when objects of a particular class are accessed remotely.

OLE provides a default object handler that local server applications can use. For applications that require special behaviors, developers can implement a custom handler that either replaces the default handler or uses it to provide certain default behaviors.

An object handler is a DLL containing several interacting components. These components include remoting pieces to manage communication between the handler and its server application, a cache for storing an object’s data, along with information on how that data should be formatted and displayed, and a controlling object that coordinates the activities of the DLL’s other components. In addition, if an object is a link, the DLL also includes a linking component, or linked object, which keeps track of the name and location of the link source.

The cache contains data and presentation information sufficient for the handler to display a loaded, but not running, object in its container. OLE provides an implementation of the cache used by OLE’s default object handler and the link object. The cache stores data in formats needed by the object handler to satisfy container draw requests. When an object’s data changes, the object sends a notification to the cache so that an update can occur. For more information on the cache, see View Caching.

For more information, see the following topic:

Handle v4.22

By Mark Russinovich

Published: June 14, 2019

Download Handle (887 KB)

Introduction

Ever wondered which program has a particular file or directory open? Now you can find out. Handle is a utility that displays information about open handles for any process in the system. You can use it to see the programs that have a file open, or to see the object types and names of all the handles of a program.

You can also get a GUI-based version of this program, Process Explorer, here at Sysinternals.

Installation

You run Handle by typing «handle». You must have administrative privilege to run Handle.

Usage

Handle is targeted at searching for open file references, so if you do not specify any command-line parameters it will list the values of all the handles in the system that refer to open files and the names of the files. It also takes several parameters that modify this behavior.

usage: handle [[-a] [-u] | [-c [-l] [-y]] | [-s]] [-p

Object type Corresponding create/open routine
Parameter Description
-a Dump information about all types of handles, not just those that refer to files. Other types include ports, Registry keys, synchronization primitives, threads, and processes.
-c Closes the specified handle (interpreted as a hexadecimal number). You must specify the process by its PID.
WARNING: Closing handles can cause application or system instability.
-l Dump the sizes of pagefile-backed sections.
-y Don’t prompt for close handle confirmation.
-s Print count of each type of handle open.
-u Show the owning user name when searching for handles.
-p Instead of examining all the handles in the system, this parameter narrows Handle’s scan to those processes that begin with the name process. Thus:
handle -p exp
would dump the open files for all processes that start with «exp», which would include Explorer.
name This parameter is present so that you can direct Handle to search for references to an object with a particular name.
For example, if you wanted to know which process (if any) has «c:\windows\system32» open you could type:
handle windows\system
The name match is case-insensitive and the fragment specified can be anywhere in the paths you are interested in.

Handle Output

When not in search mode (enabled by specifying a name fragment as a parameter), Handle divides its output into sections for each process it is printing handle information for. Dashed lines are used as a separator, immediately below which you will see the process name and its process id (PID). Beneath the process name are listed handle values (in hexadecimal), the type of object the handle is associated with, and the name of the object if it has one.

When in search mode, Handle prints the process names and id’s are listed on the left side and the names of the objects that had a match are on the right.

More Information

You can find more information on the Object Manager in Windows Internals, 4th Edition or by browsing the Object Manager name-space with WinObj.

Download Handle (887 KB)

What is a Windows Handle?

What is a «Handle» when discussing resources in Windows? How do they work?

7 Answers 7

It’s an abstract reference value to a resource, often memory or an open file, or a pipe.

Properly, in Windows, (and generally in computing) a handle is an abstraction which hides a real memory address from the API user, allowing the system to reorganize physical memory transparently to the program. Resolving a handle into a pointer locks the memory, and releasing the handle invalidates the pointer. In this case think of it as an index into a table of pointers. you use the index for the system API calls, and the system can change the pointer in the table at will.

Alternatively a real pointer may be given as the handle when the API writer intends that the user of the API be insulated from the specifics of what the address returned points to; in this case it must be considered that what the handle points to may change at any time (from API version to version or even from call to call of the API that returns the handle) — the handle should therefore be treated as simply an opaque value meaningful only to the API.

I should add that in any modern operating system, even the so-called «real pointers» are still opaque handles into the virtual memory space of the process, which enables the O/S to manage and rearrange memory without invalidating the pointers within the process.

A HANDLE is a context-specific unique identifier. By context-specific, I mean that a handle obtained from one context cannot necessarily be used in any other aribtrary context that also works on HANDLE s.

For example, GetModuleHandle returns a unique identifier to a currently loaded module. The returned handle can be used in other functions that accept module handles. It cannot be given to functions that require other types of handles. For example, you couldn’t give a handle returned from GetModuleHandle to HeapDestroy and expect it to do something sensible.

The HANDLE itself is just an integral type. Usually, but not necessarily, it is a pointer to some underlying type or memory location. For example, the HANDLE returned by GetModuleHandle is actually a pointer to the base virtual memory address of the module. But there is no rule stating that handles must be pointers. A handle could also just be a simple integer (which could possibly be used by some Win32 API as an index into an array).

HANDLE s are intentionally opaque representations that provide encapsulation and abstraction from internal Win32 resources. This way, the Win32 APIs could potentially change the underlying type behind a HANDLE, without it impacting user code in any way (at least that’s the idea).

Consider these three different internal implementations of a Win32 API that I just made up, and assume that Widget is a struct .

The first example exposes the internal details about the API: it allows the user code to know that GetWidget returns a pointer to a struct Widget . This has a couple of consequences:

  • the user code must have access to the header file that defines the Widget struct
  • the user code could potentially modify internal parts of the returned Widget struct

Both of these consequences may be undesirable.

The second example hides this internal detail from the user code, by returning just void * . The user code doesn’t need access to the header that defines the Widget struct.

The third example is exactly the same as the second, but we just call the void * a HANDLE instead. Perhaps this discourages user code from trying to figure out exactly what the void * points to.

Why go through this trouble? Consider this fourth example of a newer version of this same API:

Notice that the function’s interface is identical to the third example above. This means that user code can continue to use this new version of the API, without any changes, even though the «behind the scenes» implementation has changed to use the NewImprovedWidget struct instead.

The handles in these example are really just a new, presumably friendlier, name for void * , which is exactly what a HANDLE is in the Win32 API (look it up at MSDN). It provides an opaque wall between the user code and the Win32 library’s internal representations that increases portability, between versions of Windows, of code that uses the Win32 API.

Handle Inheritance

A child process can inherit handles from its parent process. An inherited handle is valid only in the context of the child process. To enable a child process to inherit open handles from its parent process, use the following steps.

  1. Create the handle with the bInheritHandle member of the SECURITY_ATTRIBUTES structure set to TRUE.
  2. Create the child process using the CreateProcess function, with the bInheritHandles parameter set to TRUE.

The DuplicateHandle function duplicates a handle to be used in the current process or in another process. If an application duplicates one of its handles for another process, the duplicated handle is valid only in the context of the other process.

A duplicated or inherited handle is a unique value, but it refers to the same object as the original handle. Processes can inherit or duplicate handles to the following types of objects:

  • Access Token
  • Communications device
  • Console input
  • Console screen buffer
  • Desktop
  • Directory
  • Event
  • File
  • File mapping
  • Job
  • Mailslot
  • Mutex
  • Pipe
  • Process
  • Registry key
  • Semaphore
  • Socket
  • Thread
  • Timer
  • Window station

All other objects are private to the process that created them; their object handles cannot be duplicated or inherited.

Читайте также:  Драйвер для принтера hp deskjet d4163 для windows 10
Оцените статью