September, 2009

  • The Old New Thing

    2009 Q3 link clearance: Microsoft blogger edition

    • 7 Comments

    It's that time again: Sending some link love to my colleagues.

  • The Old New Thing

    Why do messages posted by PostThreadMessage disappear?

    • 8 Comments

    The only thread message you can meaningfully post to a thread displaying UI is WM_NULL, and even then, it's only because you want to wake up the message loop for some reason.

    A common problem I see is people who use PostThreadMessage to talk to a thread that is displaying UI and then wonder why the message never arrives.

    Oh, the message arrived all right. It arrived and then was thrown away.

    This is actually a repeat of an earlier entry with the title Thread messages are eaten by modal loops, but I'm repeating it with a better subject line to help search engines.

    But since I'm here, I may as well augment the existing article.

    Obvious places where you have modal loops on a UI thread are functions that are explicitly modal like DialogBox or MessageBox or TrackPopupMenuEx(TPM_RETURNCMD) or DoDragDrop. But there are less obvious modal loops, like the modal loop that runs when you click on the caption bar and hold the button or the modal loop that runs when COM is waiting for a cross-thread call to complete.

    And since you don't control those modal loops, when they call DispatchMessage, your thread message will simply be thrown away.

    If you need to communicate reliably with a thread that also displays UI, then create a hidden window and send or post messages to that window.

  • The Old New Thing

    Microspeak: Net net

    • 24 Comments

    In finance, the net is the total after you have cancelled positive values against negative values. For example, if you took in $30 and paid out $20, then your net is $10.

    In Microspeak, this term has moved into project planning and has undergone redoubling, so it's not just net; it's net net. The doubling of the word was probably added to create a sense of impatience. Here's an imaginary conversation that illustrates the term:

    Speaker 1: We're five days over on component X, but component Y is ahead of schedule, and we can have some of them h...

    Speaker 2: (interrupting) What's the net net?

    Speaker 1: Um, we're two days behind.

    The net net is not a real estate transaction but rather is a short summary of a complicated situation, what often goes by the term bottom line.

    Here is an actual citation:

    (At the top of a long email message)

    Net net, we're delaying the release we had planned for tomorrow to try and get some critical fixes in.

    Another use of the term net net is to highlight a conclusion from a lot of data.

    (at the bottom of a large information-dense PowerPoint slide)

    Net Net: Eliminate XYZ from our target set.

    Both senses of net net highlight the principle of I know you're impatient, so I'll cut to the chase.

  • The Old New Thing

    Why doesn't Explorer have an interface for creating hard links?

    • 119 Comments

    Nick asks why Explorer doesn't have UI for creating hard links.

    Heck, while you're at it, why not ask "Why doesn't Explorer have a UI for hex-editing a file?"

    Remember, all features start out with minus 100 points. Explorer is not under any obligation to expose every last NTFS feature, and it's certainly not going to help to expose an NTFS feature that even technical people don't understand. Just look at all the people who ask questions like "How can I tell if a file name is a hard link instead of a normal file?" or online explanations of hard links which claim that "A hard link is only a reference to the original file, not a copy of the file. If the original file is deleted, the information will be lost." I mean, if even a techno-geek doesn't understand hard links, how is your average user supposed to have a chance?

    First, let's see how you would explain a hard link to an end user.

    When you create a hard link, you give the item an additional name. The file can be accessed by either its old name or its new name; they are equivalent. A file is not deleted until all its names are deleted.

    If you open a file by one name, make changes, and then save the file, the update is made to the file, and accessing the file by a second name will show the updated file, because the data for a file is separate from its name.

    Actually, that paragraph above is only true if the application which saves the file does so by writing directly to the name you used when you opened the file. If the application updates the file by creating a temporary file, then renaming the original to a backup name and renaming the temporary file, then updating a file by one name will sever its connection with other names for the file. The other names will continue to refer to the unmodified file; the name you used for the update will refer to the updated file. Different applications handle this situation differently; consult your application documentation for information on how it treats hard links.

    Note also that some backup programs have difficulty with hard links. Consult the documentation for your backup program for information on how it behaves when faced with hard links.

    If a file has multiple names, editing the file by using different names simultaneously may result in data corruption.

    If a file has multiple names, all the names must exist on the same drive.

    Most users clicked Cancel at about the time you said, "When you create a hard link..." You'll probably lose the rest of them while you are busy warning about the potential problems with hard links, and the brave few who managed to stick it out to the end will be completely confused and hit Cancel. (The ones who hit Cancel early on were the smart ones.)

    The problem with backup programs is particularly nasty. A backup program that is not hard-link-aware will miscalculate the necessary size of the backup volume, and when it attempts to restore the files, it will not restore the hard links.

    There was a Windows XP PowerToy for creating hard links, but the backup team recommended that it not be released because so many third party backup programs exploded when they stumbled across files that had multiple names in the file system.

  • The Old New Thing

    The ways people mess up IUnknown::QueryInterface, episode 2

    • 35 Comments

    Sadly, I get to add another entry to The ways people mess up IUnknown::QueryInterface:

    Blindly responding to everything.

    Some people are just too eager to please.

    HRESULT CSomething::QueryInterface(REFIID riid, void **ppvObj)
    {
      *ppvObj = this;
      this->AddRef();
      return S_OK;
    }
    

    No matter what the interface is, they say, "Sure, we do that!"

    Furthermore, no matter what you ask for, they always return the same interface. Even if it's not what you asked for.

    Exercise: Some people say that "these problems wouldn't be there if Microsoft Windows had enforced correct behavior to begin with." My exercise to you, commenter "foo", is to come up with a list of all bugs in IUnknown::QueryInterface which Windows should enforce and describe how to enforce it. (If your response is "You should have designed it differently so these bugs are impossible to write", please outline that alternate bug-resistant design. Remember that your design must be language-independent, while still supporting things like tear-offs, aggregation, and remote objects. Oh and it needs to work on typical PC-class computers of the early 1990's, which ran at 25MHz with 4MB of memory.)

  • The Old New Thing

    Don't panic, it's just H1N1

    • 12 Comments

    The media simply can't resist a good panic story, even when there is no panic to be found.

    On the Media interviews sociology professor Eric Klinenberg on what happens when the media ask you to talk about the nonexistent widespread panic over H1N1.

    Klinenberg says to the reporter, effectively, "There is no panic." Undaunted by the lack of support for his thesis, the reporter places Klinenberg's remarks on the last page of the story, under the subhead Not Enough Panic?

    Read the article to learn about the White House press conference where a reporter repeatedly asks whether the flu outbreak is a bioterrorist attack and won't take No for an answer. Or, my favorite, where one news agency sends out a reporter in a mask and has him cough on people to get their reaction. (The reaction was, basically, "What's up with this guy?") Meanwhile, another news crew spots the guy and interviews him. So you have one news crew interviewing what they think is a man on the street, but is actually another reporter trying to create a story. It's so absurd it's almost art.

  • The Old New Thing

    When people ask for security holes as features: Privileged execution

    • 69 Comments

    A customer wanted to know if there was a way to execute privileged instructions without having to write a driver.

    "I just need to execute a few instructions, and writing a driver would be overkill since it's only three instructions. Is there a way I can execute these privileged instructions without a driver?"

    The whole point of having a class of modules called drivers is to prevent somebody from doing exactly what you're asking for. Only drivers can execute privileged instructions; that's why they're called privileged instructions.

    "Yeah, but I just need three instructions. Do I have to write a whole driver just for those three instructions?"

    Even just one instruction can pwnz0r a machine. You have to be a driver in order to have that much power over the computer.

    "Maybe there's a driver somebody has already written that I can give the instructions to, and it'll execute them for me?"

    If somebody has written a driver which is designed to execute arbitrary instructions handed to it from user-mode, that person needs to be taken outside and beaten. It's one thing to have a bug that permits arbitrary code execution, but to have it as the purpose of your driver?

    Think of writing a driver as having access to the secure area of a nuclear power plant. People have to be granted the appropriate security clearance before they are allowed into enter the control room. If you want to get into the control room of the nuclear power plant, you'll have to apply for security clearance.

    "But that's so much work. I just need to go in and change a few settings on the control panel."

    Dude, that's why you're not allowed in, so you won't change those settings!

    Your options are either to get security clearance yourself, or convince somebody with security clearance to change the settings for you.

    "Well, do you know somebody who does have security clearance who will change any settings I tell him to?"

    Gosh, I sure hope not.

  • The Old New Thing

    The COM marshaller uses the COM task allocator to allocate and free memory

    • 17 Comments

    It should be second nature to you that the code which allocates memory and the code which frees memory need to use the same allocator. Most of the time, you think of it as "If you allocate memory, you need to free it with the corresponding mechanism," but this sentence works in the reverse direction as well: If you hand memory to a function that will free it, you have to allocate the memory with the corresponding mechanism.

    Let's look at this question that appeared on a discussion group:

    I have the following method defined in my IDL file:

    HRESULT GetSomething([in, string] LPCWSTR pszArg,
                         [out] DWORD* pcchOut, 
                         [out, size_is(, *pcchOut)] LPWSTR* ppszOut);
    

    My server implementation of this method goes like this:

    STDMETHODIMP CSomething::GetSomething(
        LPCWSTR pszArg, DWORD* pcchOut, LPWSTR* ppszOut)
    {
        HRESULT hr = ...
        DWORD cch = ...
    
        *pcchOut = cch;
        *ppszOut = new(nothrow) WCHAR[cch];
        // ... fill in *ppszOut if successful ...
    
        return hr;
    }
    

    When I call this method from a client, the COM server crashes after CSomething::GetSomething returns. What am I doing wrong?

    The answer should be obvious to you, particularly given the hint in the introductory paragraph, but for some reason, the people on the discussion group got all worked up about how the annotations on the ppszOut parameter should have been written, whether *pcchOut is a count of bytes or WCHARs, how the marshaller was registered, and nobody even noticed that the allocator didn't match the deallocator.

    The rule for COM is that any memory that one module allocates and another module frees must use the COM task allocator. The intent of this rule is to set down one simple, straightforward rule; without it, everybody would have to create their own mechanism for allocating and freeing memory across module boundaries, resulting in the same mishmash that we have in plain Win32, with the global heap, the local heap, the process heap, the C runtime library, or even ad-hoc explicitly paired memory allocation functions like NetApiBufferAllocate and NetApiBufferFree.

    Instead, with COM, it's very simple. If you allocate memory that another COM component will free, then you must use CoTaskMemAlloc* and if you free memory that another COM component allocated, then you must use CoTaskMemFree.*

    In this case, the CSomething::GetSomething method is allocating memory that the calling component will eventually free. Therefore, the memory must be allocated with CoTaskMemAlloc.*

    Nitpicker's corner

    *Or a moral equivalent. Note that SysAllocString is not a moral equivalent to CoTaskMemAlloc.

    Remark: MSDN can't seem to make up its mind whether to double the L at the end of "marshal" before adding a suffix, so when searching for information about marshalling, try it both ways.

  • The Old New Thing

    We've got your hotel surrounded (on one side) (and not even the entire side)

    • 35 Comments

    A local hotel advertises itself like so:

    Surrounding the hotel are popular Seattle attractions such as Pike Place Market, the Space Needle, Safeco Park, home of baseball's Seattle Mariners, and Qwest Field, home of football's Seattle Seahawks, all just a short drive away.

    Okay, first, it's Safeco Field, not Safeco Park. Mind you, I've misspelled Qwest Field in the past, so maybe I shouldn't complain.

    But let's look at those Seattle attractions which "surround" the hotel:

    They all lie in the same direction and subtend a total of twelve degrees of arc. This is a sense of the word "surround" I was previously unfamiliar with.

    Let's hope these marketing folks never end up working for the police department.

    "Before we continue, we need to surround the building."

    No problem, Chief, I've already got that.

    And then the bad guys sneak out the back door.

    I don't understand how they got away. We had the place surrounded!

  • The Old New Thing

    Things I've written that have amused other people, Episode 5

    • 30 Comments

    A question was sent to an internal discussion list for users of the XYZ tool:

    From: Q
    To: XYZ Users

    The GHI function in the JKL tool doesn't work for me. «description of problem deleted»

    I responded with this message:

    To: Q, XYZ Users

    The JKL tool is not part of XYZ. You should contact the author of the JKL tool.

    The reason why people were amused by this is that the author of the JKL tool is me. (Says so right there in the online help.)

    As a final punch line, the person never did contact me.

Page 1 of 4 (37 items) 1234