The management of memory for resources in 16-bit Windows

In a previous entry I threatened to discuss the way resources were managed in 16-bit Windows.

In 16-bit Windows, resources were not loaded until explicitly requested.

  • The FindResource function located the entry for the resource in the resource directory and returned it in the form of a HRSRC.
  • The LoadResource function took that resource handle, allocated some movable memory (HGLOBAL), and loaded the referenced resources off the disk into that memory.
  • The LockResource function took that global handle and locked it, returning a pointer to the resource bytes themselves.
  • The UnlockResource function unlocked the global handle.
  • The FreeResource function freed the memory that had been allocated to hold the resource.

Actually, it was more complicated than this. Additional bookkeeping ensure that if two people tried to load the same resource, the same memory block got used for both, and the FreeResource didn't actually free the memory until the reference count went back to zero.

Actually, it was even more complicated than this. If the resource was marked DISCARDABLE, then the memory wasn't actually freed when the reference count dropped to zero. Instead, the global handle was marked as discardable (GMEM_DISCARDABLE), so the handle remained valid, but when the system came under memory pressure, the memory behind the handle would get freed, and the next time you did a LoadResource, it would get reloaded from disk.

So now you know what that DISCARDABLE keyword in resource files means. Or at least what it used to mean. Win32 doesn't do any of this; the DISCARDABLE flag is ignored but remains for compatibility.

Comments (13)
  1. Mike Kolitz says:

    Raymond – love your blog! Thanks for all your valuable information, I find it most refreshing.

    Out of curiosity, I was wondering what your take would be – from a technical standpoint – on removing 16-bit compatibility from next-gen versions of Windows. Do you believe this would increase performance in the OS, or make it more stable and secure?

    In general, would a move like that be more helpful or harmful to Windows from a purely technical standpoint?

  2. Jack Mathews says:

    So in Win32, LoadResource just basically returns a pointer, and LockResource, UnlockResource, and FreeResource are pretty much no-ops, right?

  3. 2/2/2004 7:17 AM Mike Kolitz:

    > on removing 16-bit compatibility from

    > next-gen versions of Windows

    You mean like this?:;en-us;282423&Product=winxp

  4. Mike Kolitz says:

    Norman – Yeah, that’s pretty close to what I’m talking about. I’m guessing that since Win64 doesn’t seem to suffer from any problems from the lack of Win16 support, Win32 wouldn’t either. Nice to know :)

  5. Thomas Fogglebottom. says:

    Hi Raymond. After your recent entry on programmers using incorrect calling conventions(, I had to laugh when I read this prototype on MSDN:

    int WinMain(

    HINSTANCE hInstance,

    HINSTANCE hPrevInstance,

    LPSTR lpCmdLine,

    int nCmdShow


    Something missing!?

  6. Raymond Chen says:

    Jack: "Try it and see". And if you did, you’d find that LockResource does do something. FindResource returns a resource handle, and LockResource turns it into a pointer. But UnlockResource and FreeResource don’t do anything any more.

    Mike: From a technical standpoint, I would be overjoyed if Win16 support were finally to go away. It would significant reduce attack surface, since there’s an awful lot of code which exists solely to support Win16. But from a practical standpoint, the world is not ready to abandon Win16 yet (alas).

  7. Mike Kolitz says:

    Thanks Raymond. That’s kind of what I figured :P Maybe someday…

  8. Will says:

    Very late message I know, but I wanted to comment on the "LockResource turns it into a pointer". When I stepped through the disassembly of LockResource, all it did was pass back the passed in value unverified and unaltered. In other words the code for LockResource could be written as–

    MOV EAX, [hResData]


    So, at least on Win32, you could get rid of LockResource calls altogether by simply typecasting the passed in HGLOBAL to a pointer. Of course this isn’t advisable for code that’s meant to run on other platforms (Win64 or, shudder, Win16) but if you’re bent on performance, it’s worth knowing.

  9. Raymond Chen says:

    I challenge you to find any scenario where the extra memory access is even measureable in a real-world program. If you’re looking for performance improvements, this is the wrong place to optimize.

  10. They mean the same thing today, but at one time they were quite different.

  11. The SZ (a.k.a. Steffen) asked in the suggestion box:

    What is the prefered way to select the "most…

Comments are closed.