More typically, you have a fresh, newly-opened handle of one type and wish to now associate it with a representation more suitable for your task. For example, the C library function fopen does a pitiful job of handling file sharing, a concept which was nonexistent on the Unix operating system in which it was first specified. You want to use the full Win32 file sharing, but don't want to have to do raw WriteFile operations. And maybe you can't because you are retrofitting something into an existing, possibly portable-across-operating-systems source set, and you're writing the OS-specific module.
Keep reading! C library "handles" are small integers that index into a table in the C runtime library. The C library has traditionally limited the number of simultaneously open files to some very restrictive number of handles, such as This is no longer true in Win 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. Usually, but not necessarily, it is a pointer to some underlying type or memory location.
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. 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 doesn't need access to the header that defines the Widget struct. 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.
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. A handle can be to a window, a file, etc.
Handles are simply a way of identifying a particulate resource that you want to work with using the Win32 APIs. So for instance, if you want to create a Window, and show it on the screen you could do the following:.
If you are used to an object oriented language you can think of a HANDLE as an instance of a class with no methods who's state is only modifiable by other functions. See Handles and Data Types for more information. A handle is a unique identifier for an object managed by Windows. It's like a pointer , but not a pointer in the sence that it's not an address that could be dereferenced by user code to gain access to some data.
Instead a handle is to be passed to a set of functions that can perform actions on the object the handle identifies. So because obj was passed by value make a copy and give that to the function to foo, the printf will print the original value of 1. There is a chance that the printf will print the updated value of 2.
DrawIcon eventually executes in the server part as well, and thus it knows how to interpret the handle. In this case, the icon is a real object in the strict sense of the word: The handle is a true magic cookie without any meaning to anyone except for the operations that are allowed on it such as DrawIcon. As a side effect of this modular approach, using this technique to access resources is fairly limited.
You cannot modify the resource or look at its memory. We will look at ways to work around this in a second. Also, there is no way for the subsystem to determine if the object is in use by anybody but the process that owns it. So how does one share resources among processes? Well, the bad news is that there is no easy way for applications to share resources dynamically at run time so that a change in the resource that one application makes appears in the other application.
Aside from using the CopyIcon , CopyAcceleratorTable , and CopyCursor functions, which are especially designed to create local copies of resources, the best one can do about this is to have one application map an image of the other application's executable into its own memory space, locate the resource in the image, and party on it.
The trick here is that LoadLibrary will map the executable file into the address space of the process that calls it and return a pointer to that image. All that FindResource and LoadResource do is examine the executable header in that image, figure out where within the image the resource is located, and return a pointer to the resource image. The part that will probably confuse you here is that LoadLibrary also works on. EXE files. LoadLibrary also executes the DLL entry point routine when a library is loaded, but it does not execute anything when an application is loaded.
The return value from WinExec , which is a stripped-down version of CreateProcess , is a handle to a Windows NT executive object, whereas an instance handle, the value returned from LoadLibrary , is a virtual pointer. Now, here we run into a terminology problem: Under Windows 3. Windows NT renames the part of the Win32 subsystem that corresponds to the kernel in Windows 3.
Most of the objects that you access through the base are, in fact, native Windows NT objects, which we will discuss in the following section. The only entity that the kernel component of Windows 3. Let us elaborate on the last statement of the preceding section a little bit more.
Instance handles are, in fact, selectors of the default data segments of the application instance. The task handle is the selector of a global memory block that contains task-specific parameters such as the input queue that is associated with the task. The module handle is the selector of a global memory block that contains a modified version of the executable header associated with the module. This memory block is also known as the module database. For applications in Windows 3.
For more information on modules, tasks, and instances under Windows 3. Windows NT does not use task databases or module databases anymore, and the default data segment is built on top of an application's virtual address space. The hInstance value that is being passed to an application upon startup is basically the same as the value returned from LoadLibrary : a virtual address in the application's address space that contains the memory-mapped image of the executable file.
It is fairly easy to confuse this value with a process handle, which is something totally different namely, a native Windows NT object and cannot be used interchangeably with those virtual pointers.
The remaining kernel object type is the heap object type , which we'll look at now. As Randy Kath's technical article "Managing Heap Memory in Win32" outlines, the Windows NT heap memory manager resides on top of the virtual memory manager; that is, a heap is essentially a chunk of virtual memory that consists of the heap itself and some administrative information that is used to maintain it.
The handle returned from the HeapCreate API is essentially the virtual address of this memory chunk, and a call to HeapAlloc will look into the administration header and return a pointer to the memory chunk. You should never attempt to write to a memory location that belongs to the heap header because it would seriously confuse the heap manager.
Also, due to the very nature of disjoint address spaces, one application's local heap is of no relevance to other applications. Because heap handles are virtual pointers, and no record is kept of the local heaps allocated by the base part of the Win32 subsystem, there is really no limit on the number of heaps you can theoretically allocate, except for the limits that the executive imposes on the number of virtual memory chunks that an application can use.
Note that this is different from the number of allocations that can be drawn from heaps. Because heaps themselves are virtual memory blocks, you cannot create more than 32K-worth of heaps per application, but from a given heap, you can allocate as many memory blocks as you want to. We will now look at native objects in Windows NT. Some of the objects that Windows NT knows about are not directly visible to applications, such as driver objects or symbolic link objects, but internally they work in exactly the same way as the aforementioned objects.
In Inside Windows NT , these invisible objects are called kernel objects , as opposed to executive objects. We have already enumerated the native Windows NT objects that are visible to Win32 applications: processes, threads, files, file mappings, events, semaphores, and mutexes.
We will not elaborate too much on these here because Chapter Three of Inside Windows NT already gives a comprehensive overview of these objects and how to use them. The worthwhile aspects to mention about them are the following: They can attain a signaled state so that you can call WaitForSingleObject or WaitForMultipleObjects on them. Post by Vipin One classic example is CreateFile Post by Vipin Best thing would be to read the documentation of each windows API as when things are coded.
Thanks Vipin. Doug G. Post by Gary Chanson based functions which violate this. For file handles,. David J. Post by Doug G I may be getting my operating systems mixed up, but I thought that almost all virtual-memory operating systems set the page at address zero 0x The reason for this is that making a reference through a NULL pointer is one of the most common programming bugs, and by making this page invalid it will cause a crash or other exception if you make this mistake.
I have worked on a few non-VM systems where zero was a valid address, and that would cause all sorts of system problems when a program with NULL in a structure pointer would trash the low memory area of the system, wiping out interrupt vectors, boot code, or other important stuff! So assuming that a "handle" is used internally as a structure object pointer, I would be very surprised to find that NULL 0 would be a valid value.
Use Process Explorer from www. Or better yet, find a handle that isn't a multiple of 4 besides 0. The table begins at index 4. And then goes up by 4 8, 0xC, etc. That information can be found in the book Microsoft Windows Internals, page Uepping I want to write a generic Handle class.
0コメント