What is the hSection parameter to CreateDIBSection for?

The CreateDibSection function creates a special type of bitmap known as a DIB section. We've worked with these guys before: The feature of DIB sections that is by far the most interesting is that the raw pixels in the bitmap are mapped into your process space as if they were normal memory, which you can read from and write to directly.

But what is the deal with that funky hSection parameter? Although the ppvBits parameter receives "a pointer to the location of the DIB bit values," the documentation also says that if you pass NULL, then "an application cannot later obtain a handle to this memory." That second part makes no sense. Why would I want to obtain a handle to the memory if I passed NULL, since I told it I didn't have any memory to begin with? Why is it so important to call out that I can't retrieve NULL? The documentation appears to go out of its way to point out something that makes no sense!

Let's look at that second part in a little more context. Here is the entire description for the hSection parameter:

If hSection is NULL, the system allocates memory for the DIB. In this case, the CreateDIBSection function ignores the dwOffset parameter. An application cannot later obtain a handle to this memory. The dshSection member of the DIBSECTION structure filled in by calling the GetObject function will be NULL.

The "this" in "this memory" is "the memory the system allocated," not "the memory the application passed in." Because, as you noticed, the application didn't pass in any memory! It's trying to tell you that when you tell the system to allocate memory for the DIB section, you don't get to peek back in and get the handle to the memory which the system allocated.

Let's look at the bigger picture here. The memory for a DIB section needs to be mapped into the application's address space, and from the description, the application has the option of passing explicit storage in the form of a file mapping handle (and offset into that file mapping handle), or it can pass NULL and let GDI worry about where to store it. If you were writing the GDI code to manage the memory for DIB sections, how would you do it?

How would you do it? is is another one of those problem-solving questions similar to What would the world be like if that were true? or Imagine if two programs did this? For one thing, How would you do it? lets you rule out designs that involve clairvoyance or psychic powers. (It's surprising how often people quietly assume that systems are built upon clairvoyance.) For another thing, it forces you to put on a different hat and view the problem from another point of view, one which may help you understand the system better.

If you had to implement a system where memory could be managed either in the form of a file mapping handle or a mechanism of your choice, you probably would choose as your alternate mechanism... a file mapping handle. That way, there is only one code path for memory management instead of two.

Suppose you had to install a door security system that both you and Bob could use. Bob insists that he use a traditional metal key to unlock the door, but says you can use any system you want. Would you design a combination system that could be unlocked either with a metal key or an electronic smart card? Or would you just use a traditional keyed lock with two sets of keys, giving one of Bob and keeping the other for yourself?

When you create a DIB section and pass NULL for the hSection, GDI simply creates an internal hSection and uses that. The documentation is trying to say that the internal hSection is inaccessible to the application.

Note: I don't know if this is actually what happens internally, but it's the simplest explanation that matches the known facts.

Comments (9)
  1. avek says:

    [Imagine if somebody closed the handle! -Raymond]

    The system could duplicate the handle before giving it to application. That’s what capabilities are for (and the kernel handles are essentially capabilities).

    Of course, in that case some apps would not close the duplicated handle, leaking the DIB memory. And DIB section never was a small thing, especially in the days of NT 3.x.

    So CreateDIBSection approach seems to be the most reliable: if you want explicit memory control, ask for it explicitly, or you get the safe version.

  2. Joseph Koss says:

    But why use a DIB if you dont want the pointer?

    Whats the difference between a DIB created with a null pointer, and a regular old DDB?

    In both cases you get to pick the pixel format and dimensions, and in both cases you are not given direct access to the pixel data.

    [Um, CreateDIBSection gives you the pointer to the pixel data. If you pass NULL you’re saying “Please, GDI, allocate the memory for me and give me a pointer to it.” -Raymond]
  3. Myria says:

    A "section" in Windows NT is a file mapping handle.  MapViewOfFile is a thin wrapper around the native NT function NtMapViewOfSection, as an example.

    Sometimes this nomenclature difference leaks through to the Win32 side, such as this hSection parameter.  Another place is the names of some of the protection flags to CreateFileMapping: "SEC_IMAGE" means to create an image section.

  4. waleri says:

    I don’t see any reason why the system cannot return that internal handle in dshSection. However, I believe that it does not return it simply because GDI internaly *may* use different memory allocation.

    [Imagine if somebody closed the handle! -Raymond]
  5. 679 says:

    @Joseph Koss:

    I may be wrong, but I think you can only select a DDB into a memory device context if it has the same pixel format or is monochrome. CreateDIBSection allocates a DIB in the desired pixel format and, in addition, gives you a handle that you can select into any memory device context or pass to functions that expect a bitmap handle.

  6. Mark says:

    For the reason it’s spelled out in the documentation, see http://msdn.microsoft.com/en-us/library/dd183567.aspx.

    CreateDIBSection’s return value is an HBITMAP, which is in theory all you need to manage the DIB.  As it says on the previous line, you can use GetObject to get back a DIBSECTION, which is a BITMAP (with bmBits set to *ppvBits), and some extra information, including the hSection.  However, given an HBITMAP to a DIB, you can’t assume that hSection is set.

    Imagine you’re using a library that wraps CreateDIBSection, and only returns an HBITMAP.  If it’s your responsibility to call DeleteObject, you need to check whether hSection is NULL and skip the subsequent call to CloseHandle.

    (In other words, it’s not wise for a library to leave cleanup of a DIB to the client.)

  7. Nawak says:

    [Imagine if somebody closed the handle! -Raymond]

    Well, I can give an hSection to the system and close it afterwards. The net effect would be the same, wouldn’t it?

    Like waleri I think that maybe somebody didn’t want to guarantee via the API that they would always use a traditional keylock and not a smart card.

    [The kernel can dup the handle passed in. -Raymond]
  8. Nawak says:

    [The kernel can dup the handle passed in. -Raymond]

    The kernel can dup the handle passed out too, as noted by avek.

    Granted, it’s all guesswork on your and our part.

    Still, I like the “liability avoidance” scenario better :)

    [Duping the handle on the way out means that applications can use offsets beyond the one used by the DIB section to modify other bitmaps! (GDI might sub-allocate one giant section for multiple bitmaps.) -Raymond]
  9. Cheong says:

    [It’s surprising how often people quietly assume that systems are built upon clairvoyance.]

    I’d say that instead of this assumption, people always try to assume the APIs are built in the most convenient way, that whatever they want to perform can be done in single line of code (no matter how unreasonable it seems).

Comments are closed.

Skip to main content