• The Old New Thing

    The evolution of dialog templates - Introduction


    In the history of Windows, there have been four versions of dialog templates. And despite the changes, you'll see that they're basically all the same.

    My secret goal in this six-part series is to address questions people have had along the lines of "I'm trying to generate a dialog template in code, and it's not working. What am I doing wrong?"

    As it turns out, that you can get the resource compiler to tell you what you're doing wrong. Take the template that you're trying to generate, create an *.rc file for it and run it through the resource compiler. Attach the resource to a dummy program and dump the bytes! Compare the compiler-generated template against the one you generated. Look for the difference.

    In other words: To see what you're doing wrong, take somebody who does it right and compare. Clearly there's a difference somewhere. It's just bytes.

    Anyway, enough of the rant against laziness. The next several days will cover the evolution of the dialog template, with annotated byte dumps for people who are trying to figure out why their dialog template isn't working.

    Non-geeks may want to go into hibernation for a while, since this will take over a week to play out. I'll try to keep you amused with the non-technical side-postings.

  • The Old New Thing

    Exploding frying pans


    Last year there was a recall of exploding frying pans. For some reason I found this funny.

    "The pans can explode or separate when preheated, used on high heat or used for frying," the safety commission said in a statement.

    It explodes when you fry something in it.

    Apparently "frying stuff" was not in the test plan for the frying pans.

  • The Old New Thing

    Verifying that your system files are digitally signed


    If you want to re-check that the files on your system haven't been tampered with, you can run sigverif (by typing its name into the Start.Run dialog) and tell it to start scanning.

    (UI note: If you go into the Logging page on the Advanced dialog, you can get trapped where it insists on having a valid log file name even if you didn't ask for logging!)

    The signature verification process takes a while, so go and do something else while you're waiting. When it's done, you'll get a list of all the system files that are not digitally signed by Microsoft. Just because a file is listed here doesn't mean that it's necessarily bad, however. For example, it might be a video driver or printer driver.

    (Another UI note: You can't right-click the items in the list to view their properties, say, to see what company issued the files.)

    One case when you would want to run sigverif is after you remove the test root certificate which was causing your desktop to say "for test/evaluation purposes only". That way you can find all the uncertified drivers that snuck in under cover of the test signature.

  • The Old New Thing

    Anybody remember Blade Squad or MV24?


    It's often fun to go back and see the kooky ideas for television shows that floated around years ago. Here are some from 1997:

    • Blade Squad - An action series set in the year 2001 about a cop who gets around on jet-powered roller skates.
    • My Beautiful World - A comedy whose characters include a Marilyn Monroe impersonator and a child with the body of a 10-month-old baby and the head of a Queens cab driver.
    • The Notorious - A drama about seven crime families, each representing one of the seven deadly sins.
    • MV24 - A sitcom about a music video channel, starring Peter Scolari.

    Plenty more on the linked web site. What's really scary is that a lot of these kooky ideas turned into actual television programs!

  • The Old New Thing

    What was the purpose of the hPrevInstance parameter to WinMain?


    Once your average GUI program picks itself up off the ground, control begins at your WinMain function. The second parameter, hPrevInstance, is always zero in Win32 programs. Certainly it had a meaning at some point?

    Of course it did.

    In 16-bit Windows there was a function called GetInstanceData. This function took an HINSTANCE, a pointer, and a length, and copied memory from that instance into your current instance. (It's sort of the 16-bit equivalent to ReadProcessMemory, with the restriction that the second and third parameters had to be the same.)

    (Since 16-bit Windows had a common address space, the GetInstanceData function was really nothing more than a hmemcpy, and many programs relied on this and just used raw hmemcpy instead of using the documented API. Win16 was actually designed with the possibility of imposing separate address spaces in a future version - observe flags like GMEM_SHARED - but the prevalence of tricks like hmemcpy'ing your previous instance reduced this potential to an unrealized dream.)

    This was the reason for the hPrevInstance parameter to WinMain. If hPrevInstance was non-NULL, then it was the instance handle of a copy of the program that is already running. You can use GetInstanceData to copy data from it, get yourself up off the ground faster. For example, you might want to copy the main window handle out of the previous instance so you could communicate with it.

    Whether hPrevInstance was NULL or not told you whether you were the first copy of the program. Under 16-bit Windows, only the first instance of a program registered its classes; second and subsequent instances continued to use the classes that were registered by the first instance. (Indeed, if they tried, the registration would fail since the class already existed.) Therefore, all 16-bit Windows programs skipped over class registration if hPrevInstance was non-NULL.

    The people who designed Win32 found themselves in a bit of a fix when it came time to port WinMain: What to pass for hPrevInstance? The whole module/instance thing didn't exist in Win32, after all, and separate address spaces meant that programs that skipped over reinitialization in the second instance would no longer work. So Win32 always passes NULL, making all programs believe that they are the first one.

    And amazingly, it actually worked.

  • The Old New Thing

    Augusto Pinochet's beverage preferences are a matter of national security


    It appears that Augusto Pinochet's beverage preferences are a matter of national security. The web site offers the original and redacted versions of the same document, so you can see what sorts of information the U.S. government considers to be worthy of redaction.

    On a related redactorial note, researchers demonstrated last month a technique for identifying blacked-out words and phrases in confidential documents.

    On a related Pinochet note: In the United States, it has become common for grocery stores to offer "loyalty cards", which offer discounts on selected goods in exchange for the store being able to track every single item you purchase. Everybody hates these cards but uses them anyway because the non-card prices are often absurd. What people often did when signing up for the cards was to provide bogus information.

    My card is in the name of former Chilean dictator "Augusto U. Pinochet".

    It turns out that this particular grocery chain has a policy that all cashier must thank the customer by name at the conclusion of the transaction. So after I pay for my groceries, the cashier says, "Thank you, Mr. Pinochet."

    Except that it turns out that "Pinochet" is hard to pronounce. (Consensus on this continues to be hard to achieve. Many others claim the correct pronunciation is "Pee-no-chet". I use that pronunciation, too, myself, for no good reason.)

    I've been called "Mr. Peanut-Chew", "Mr. P'Notch-et", and "Mr... how do you pronounce that?" (To which I say, "Pee-no-chet. It's a Chilean name." And the cashier says, "Ooh, that's very interesting.") Only one person even recognized the name as that of the man under whose brutal rule thousands of people simply "disappeared".

    (I never actually expected the fake name to go through. I assumed that somebody would have recognized it and deleted it from the system. But no, the entry remains. Occasionally, when Pinochet makes international headlines, I consider the possibility that some people may show up at my house looking for him.)

  • The Old New Thing

    Norway works to lengthen its lead


    Norway locks its grip on "Best place to live" status:

    As I pointed out last month, this then leads to...

    Shoulda studied Norwegian like I had planned to do originally before I got sidetracked by Swedish.

  • The Old New Thing

    What is the difference between HINSTANCE and HMODULE?


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

    It all comes from 16-bit Windows.

    In those days, a "module" represented a file on disk that had been loaded into memory, and the module "handle" was a handle to a data structure that described the parts of the file, where they come from, and where they had been loaded into memory (if at all). On the other hand an "instance" represented a "set of variables".

    One analogy that might (or might not) make sense is that a "module" is like the code for a C++ class - it describes how to construct an object, it implements the methods, it describes how the objects of the class behave. On the other hand, an "instance" is like a C++ object that belongs to that class - it describes the state of a particular instance of that object.

    In C# terms, a "module" is like a "type" and an instance is like an "object". (Except that modules don't have things like "static members", but it was a weak analogy anyway.)

    Here's a diagram. (Recall that we discussed 16-bit HRSRC in a previous entry.)

    code segment descriptor USER32 code... USER32 data...
    code segment descriptor (not in memory)
    code segment descriptor USER32 code...
    data segment descriptor
    HRSRC (not in memory)
    HRSRC USER32 resource...
    HRSRC (not in memory)
    exports table

    In 16-bit Windows, all programs ran in a single address space, and if a DLL was used by five programs, it was loaded only once into memory. In particular, it got only one copy of its data segment. (In C++/C# terms, a DLL is like a "singleton class".)

    That's right, DLLs were system-global rather than per-process. The DLL did not get a separate copy of its data for each process that loaded it. If that was important to your DLL, you had to keep track of it yourself.

    In geek terms, there was only one "instance" of a DLL in the system.

    On the other hand, if you ran two copies of Notepad, each one got its separate set of variables - there were two "instances".

    code segment descriptor NOTEPAD code... NOTEPAD data...
    code segment descriptor (not in memory)
    data segment descriptor HINSTANCE
    HRSRC (not in memory) NOTEPAD data...
    HRSRC NOTEPAD resource...

    Both running copies of Notepad shared the NOTEPAD module (so the code and resources were shared), but each had its own copy of its variables (separate data segment). There were two "instances" of Notepad.

    The "instance" handles in the above diagrams are the data segments.

    Programs are identified by their the instance handle. You can't use the module handle, because the two copies of Notepad have the same module handle (since the same code is running in each). The thing that makes them different is that each has its own set of global variables.

    This is why the WinExec and ShellExecute functions return HINSTANCE: They are holdovers from 16-bit Windows, where HINSTANCEs were the way to identify running programs.

    The method by which code receives its HINSTANCE (i.e., knows where its global variables are) I will leave for a future article. It is somehow related to the now-obsolete MakeProcInstance function.

    When it came to design Win32, the question then arose, "What do we do with HINSTANCE and HMODULE for Win32?" Since programs ran in separate address spaces, you didn't have instance handles visible across process boundaries. So the designers took the only thing they had: The base address of the module. This was analogous to the HMODULE, since the file header describes the contents of the file and its structure. And it was also analogous to the HINSTANCE, since the data was kept in the data segment, which was mapped into the process directly.

    So in Win32, HINSTANCE and HMODULE are both just the base address of the module.

    Tomorrow, I'll talk about that mysterious hinstPrev parameter to WinMain.

  • The Old New Thing

    Taiwan law requires writing to go left-to-right instead of top-to-bottom


    The BBC reports that official documents in Taiwan must now be written left-to-right (Western style) instead of the traditional top-to-bottom.

    I grew up with Chinese-language newspapers that ran their stories vertically and numbered their pages from right to left, in the traditional manner. Books and newspapers which run left-to-right look "wrong" to me. But I guess I'll have to start getting used to it.

  • The Old New Thing

    A hidden performance cost of regional windows


    Regional windows are neat, but they come at a cost. Most of the cost you can see directly. For example, constantly changing the region clearly generates a cost since you have to sit there and generate new regions all the time.

    One question that came up on an internal performance alias highlights one of the hidden costs of regional windows: The putative window rectangle.

    Suppose you have a large window but set a small window region. How much worse is this than haveing a small window with a small window region?

    Quite a bit, actually.

    Hit-testing is one of the most common operations performed by a window manager. Given a point on the screen, find the window that it corresponds to. To speed this up, the window rectangle is used to rule out windows quickly. For example, if a window's rectangle is (0,0)-(100,100) then the point (200,10) is clearly not within the window since it doesn't fit in the rectangle. Rectangle tests are fast.

    If the window is regional, then the rectangle test is not good enough, because the point may exist within the rectangle but outside the region. In that case, the point must be tested against the window region itself.

    But Windows uses the window rectangle as a "quick test" to see if the region is worth checking. If the point lies outside the rectangle, then the window manager doesn't even bother checking the region, which is good because region testing is comparatively slow.

    In other word, the pseudocode for hit-testing goes something like this:

    if (point is outside window rectangle)
      return no-hit;
    else if (window has no region)
      return hit;
    else if (point is inside region)
      return hit;
      return no-hit;

    So if you create a huge window with a tiny region, the window manager can't rule out the hit-test based on the first (fast) rectangle test. It has to go to the third (slower) region test.

    Moral of the story: When using regional windows, try to keep the window rectangle reasonably close to the bounding box of the region itself. It helps the window manager decide more quickly which window a point belongs to.

Page 385 of 427 (4,263 items) «383384385386387»