• The Old New Thing

    Why does the MoveWindow function let you suppress repainting?

    • 8 Comments

    Commenter Phil Quirk asks via the suggestion box why the MoveWindow function lets you suppress repainting. "Shouldn't the OS be able to figure out if the window needs to be repainted?"

    Indeed the window manager does do a very nice job of figuring it out if you pass bRepaint = TRUE, which is the expected value of the parameter. But if you think you're smarter than the window manager, then you can pass bRepaint = FALSE and tell the window manager, "Even though you think the window needs to be repainted, don't repaint it. Trust me on this."

    Why would you try to outwit the window manager? Maybe you have special knowledge about how your application behaves. For example, you might exploit special properties about the source and destination coordinates and decide that certain portions of the window should not be redrawn but rather should be shared between the old and new locations, sort of like the advanced tricks you can play with the WM_NCCALCSIZE message. Or you might know that your program is going to invalidate the entire client rectangle soon anyway, so a repaint immediately after the move would just be a waste of time. The bRepaint parameter provides an escape hatch, a throwback to the days when the window manager let you do strange things because you might be doing them as part of a clever thing.

    Mind you, these are pretty advanced concerns and most of the time you would be best off just passing bRepaint = TRUE and letting the window manager do its job of deciding what needs to be repainted.

  • The Old New Thing

    Don't mention the war. I mentioned it once, but I think I got away with it all right (Episode 2)

    • 18 Comments

    In preparation for the 2012 Olympic Games in London, the official UK tourism bureau produced tips for dealing with people from other countries.

  • The Old New Thing

    If you're going to throw a badminton match, you have to be less obvious about it

    • 37 Comments

    It may be possible based on your location to view what NBC euphemistically calls "highlights" from the women's badminton doubles match between China's Yu Yang/Wang Xiaoli and South Korea's Jung Kyung Eun/Kim Ha Na. The serves go laughably into the net, there is barely any attempt to chase down shots, and returns go far out of bounds. If this is top-level badminton, I think I could be a world champion.

    Both sides had secured their advance into the next round, and Wired explained why both teams decided that a strategic loss would be advantageous. Julie VanDusky-Allen provides a game-theoretical analysis of the situation. (Even if you randomize the seeds in the knockout portion of the tournament, you can still get into a situation where a team in the round-robin portion of the tournament may decide that it is advantageous to lose a match on purpose.¹)

    Partway into the match, an official warns both teams that if they do not make an effort to win, the teams will both be disqualified. That served to improve the quality of play only marginally.

    Okay, they need to study soccer or American professional basketball, where intentionally losing is a long-standing tradition: You need to make it look like you're trying, or people are going to figure you out. For example, play normally most of the time, but then have a mental lapse and "accidentally" make an error that concedes a point.

    At least fake an injury. That'll let you start playing badly with plausibility.

    (Although these techniques for throwing a match subtly probably don't work if your opponent is also trying to lose.)

    Since the attempt to get both sides to play to win didn't seem to help, perhaps the officials should have announced, "We have decided to assist in motivating the two sides by declaring that the loser of the match will be disqualified from the tournament."

    Now they have something to play for.

    ¹ Consider a four-team group with teams A, B, C, and D. In round 1, A defeats B 5–1 and C defeats D 2–1. In round 2, A defeats D 5–1 and B defeats C 2–1. At this point, A is guaranteed advancement as long as it doesn't lose to C by more than 8 points. If A defeats C, then B will advance. But A may decide that it prefers to play against C in the knockout portion of the tournament. In that case, it can intentionally lose to C in the third round by 4 points (leaving a comfortable margin of error), and as long as B doesn't win by more than 7 points, A will get its wish: C will advance.

  • The Old New Thing

    Can an x64 function repurpose parameter home space as general scratch space?

    • 23 Comments

    We saw some time ago that the x64 calling convention in Windows reserves space for the register parameters on the stack, in case the called function wants to spill them. But can the called function use the memory for other purposes, too?

    You sort of already know the answer to this question. Consider this function:

    void testfunction(int a)
    {
     a = 42;
    }
    

    How would a naïve compiler generate code for this function?

    testfunction:
        sub rsp, 8 ;; realign the stack
    
        ;; spill all register parameters into home locations
        mov [rsp+0x10], rcx
        mov [rsp+0x18], rdx
        mov [rsp+0x20], r8
        mov [rsp+0x28], r9
    
        ;; a = 42
        mov [rsp+0x10], 42
    
        ;; return
        add rsp, 8 ;; clean up local frame
        ret
    

    Observe that after spilling the register parameters into their home locations onto the stack, the function modified the local variable, which updated the value in the home location.

    Since a function can arbitrarily modify a parameter, you can see that a function is therefore allowed to arbitrarily modify a parameter's home location. At which point you can see that an optimizing compiler might choose an arbitrary value completely unrelated to the parameter.

    Our test function has only one parameter. What about the other three home registers?

    The caller is responsible for allocating space for parameters to the callee, and must always allocate sufficient space for the 4 register parameters, even if the callee doesn't have that many parameters.

    A function can therefore treat those 32 bytes as bonus free play. The rationale behind those 32 bytes is that it gives you a place to spill your inbound register parameters so that they will be adjacent to the stack-based parameters. (We saw how the naïve compiler took advantage of this by not trying to be clever in its function prologue and simply spilling all register parameters whether it needs them or not.)

    Nevertheless, you are free to use them for whatever purpose you like, and if you're looking at heavily-optimized code, you'll probably find that the compiler found all sorts of clever things it can do with them. For example, a common trick is to use them to save the nonvolatile registers that the function locally uses to hold the corresponding parameter!

    (Did this article look familiar? Turns out I covered this article a few years ago, but I'm senile and accidentally repeated a topic. And since I put so much effort into writing it, I'm going to make you suffer through it, even though it's a repeat. Hey, television programs repeat during the summer.)

  • The Old New Thing

    How can I make sure my program is launched only from my helper program and no other parent?

    • 40 Comments

    Say you have a collection of programs which work together. One of them is the "master" program that runs the show, and it has a bunch of "assistant" programs that it launches to accomplish various subtasks. These assistants are not meant to be run by themselves; they are meant to be run only by the master program. How do you design the assistant so that it can only be run by the master?

    There's nothing you can do to force the assistant to be run only by the master, since anything you do to detect the case can be faked out by an attacker. (Worst case is that they just run your program under the debugger and patch out the code that looks for the master.) So the purpose of this test is not so much to create an airtight hatchway as it is to prevent users from randomly wandering into the Program Files directory and double-clicking stuff to see what happens.

    The simplest way of doing this is to require a command-line parameter that the master passes to say, "Hey, it's me, the master. It's okay to do that thing you do." The command line parameter could be anything. assistant.exe /run say. If the command line parameter is not present, then the assistant says, "Um, please don't run this program directly. Use the master."

    You might decide to get really fancy and make the secret handshake super-complicated, but remember that there is no added security benefit here. The user can compromise assistant.exe by simply attaching a debugger to it, at which point any defensive mechanism you create can simply be disabled by a sufficiently-resourceful attacker. (And there's a class of people who will see that you put a lot of work into protecting your assistant, and that will just convince them to work harder to circumvent the protection. Because something with this much protection must certainly be very valuable!)

    There's also a benefit to keeping the secret handshake simple: It makes it a lot easier for you to debug the assistant program. Instead of having to set up the master and then get the master to do all the things it needs to generate the secret handshake for the assistant, you can just run your assistant directly with the magic flag, and boom, you're off and debugging.

    To make it even harder to run your program by accident, you can give it an extension that is not normally executable, like .MOD. That way, it cannot be double-clicked, but you can still pass it to Create­Process or (with some cajoling) Shell­Execute­Ex.

  • The Old New Thing

    Can CoCreateGuid ever return GUID_NULL?

    • 26 Comments

    A customer asked whether the Co­Create­Guid function can ever return GUID_NULL. Their code uses GUID_NULL for special purposes, and it would be bad if that was ever returned as the GUID for an object. "Can we assume that Co­Create­Guid never returns GUID_NULL? Or should we test the return value against GUID_NULL, and if it is equal, then call Co­Create­Guid and try again?"

    Some people started running Co­Create­Guid a bunch of times and observing that it was spitting out type 4 GUIDs, which will always have a 4 in the version field. Then other people started wondering whether the use of Algorithm 4 was contractual (it isn't). Then still other people went back to read the RFCs which cover UUIDs to see whether those documents provided any guidance.

    And then I had to step in and stop the madness.

    It is very easy to show that any UUID generator which generates GUID_NULL has failed to meet the requirement that the generated UUID be unique in space and time: If it's equal to GUID_NULL, then it isn't unique!

    The uniqueness requirement is that the generated GUID be different from any other valid GUID. And if it generated GUID_NULL, then it wouldn't be different from GUID_NULL! (And GUID_NULL is a valid GUID, specifically identified in RFC4122 section 4.1.7.)

    If you're so worried about Co­Create­Guid generating a duplicate GUID_NULL, why aren't you worried about Co­Create­Guid generating a duplicate IID_IUnknown or GUID_DEV­CLASS_1394 or any of the other GUIDs that have already been generated in the past?

    In other words, no valid implementation of Co­Create­Guid can generate GUID_NULL because the specification for the function says that it is not allowed to generate any GUID that has been seen before.

    One of my colleagues cheekily remarked, "And even if it did generate GUID_NULL for some reason, uniqueness would require that it do so only once! (So you should try to force this bug to occur in test, and then you can be confident that it will never occur in production.)"

  • The Old New Thing

    Joshua Roman groupies may have to set up their frequent flyer accounts

    • 5 Comments

    Cellist Joshua Roman has quite a dedicated following here in Seattle, but those Joshua Roman groupies may have to dust off their frequent flyer cards, because the young cellist is resigning his position at the end of the season in order to pursue a solo career.

    There has been quite a bit of turmoil at the Seattle Symphony in recent years. The former concertmaster was forced out, leaving bitter feelings behind, and the long search for a replacement concluded with not one, not two, but four permanent concertmasters who will divide the leadership duties among themselves. A lawsuit filed by a violinist claiming "intentional emotional distress arising out of the hostile environment and harassment ... over a long and extended period of time" tickled the interest of The New York Times in late 2007 (and generated a number of letters to the editor in response), although for us locals, it's old news. (The lawsuit was dismissed in early 2008.)

    Makes you wonder how they find time to play music.

  • The Old New Thing

    West Bank Story, the movie that sells itself in five seconds

    • 5 Comments

    This weekend, I attended an Oscar-watching party, and when the clips from the nominees for Live Action Short Film were run, I was completely won over by West Bank Story. Five seconds of dancing, finger-snapping Jews and Arabs is all I needed.

    When filling out your Oscar party ballot, "Live Action Short Film" is one of those categories you just close your eyes and pick randomly since you don't know anything about any of the movies. It felt like everybody else at the party felt the same way I did: If we had seen that clip, we would all have voted for it. In our minds, it won the award before the envelope was even torn open.

    Update: Interview with Ari Sandel, director and co-writer.

  • The Old New Thing

    Why does my window style change when I call SetWindowText?

    • 9 Comments

    A customer observed some strange behavior with window styles:

    We ran some weird behavior: Calling the Set­Window­Text function causes a change in window styles. Specifically, calling Set­Window­Text results in the WM_STYLE­CHANGING and WM_STYLE­CHANGED messages, and sometimes the result is that the WS_TAB­STOP style is removed. Is this a bug? What would cause this?

    The Set­Window­Text message sends the WM_SET­TEXT message to the control, at which point anything that happens is the window's own responsibility. If it wants to change styles based on the text you sent, then that's what happens. The window manager doesn't do anything special to force it to happen or to prevent it.

    That's weird, because I'm not even listening for WM_SET­TEXT messages. I also verified that there is no call into my code during the call to the the Set­Window­Text function.

    I'm assuming that the window belongs to the same process as the caller. If the window belongs to another process, then the rules are different.

    I'm changing the text of a window created by the same thread.

    Okay, so let's see what we have so far. The customer is calling the Set­Window­Text function to change the text of a window created on the same thread. There is no handler for the WM_SET­TEXT message, and yet the window style is changing. At this point, you might start looking for more obscure sources for the problem, like say a global hook of some sort. While I considered the possibilities, the customer added,

    It may be worth noting that I'm using the Sys­Link.

    Okay, now things are starting to make sense, and it didn't help that the customer provided misleading information in the description of the problem. For example, when the customer wrote, "There is no handler for the WM_SET­TEXT message," the customer was not referring to the window whose window text is changing but to some other unrelated window.

    It's like responding to the statement "A confirmation letter should have been sent to the account holder" with "I never got the confirmation letter," and then the person spends another day trying to figure out why the confirmation letter was never sent before you casually mention, "Oh, I'm not the account holder."

    The WM_SET­TEXT message is sent to the window you passed to Set­Window­Text; in this case, it's the Sys­Link window. It is therefore the window procedure of the Sys­Link window that is relevant here.

    The Sys­Link control remembers whether it was originally created with the WS_TAB­STOP, and if the markup it is given has no tab stops, then it removes the style; if the markup has tab stops, then it re-adds the style.

    How do I add a tab stop to a string? I couldn't find any reference to it and all my guesses failed.

    The tab stops in question are the hyperlinks you added when you used the <A>...</A> notation. If the text has no hyperlinks, then the control removes the WS_TAB­STOP style because it is no longer something you can tab to.

  • The Old New Thing

    A complex family calculus

    • 16 Comments

    I spent the other night at a relative's house, and I was woken the next morning by my young niece who politely asked me to make her breakfast. (Her technique for waking me up is to come in and call my name. If the door is closed, she pounds on the bedroom door and shouts, "Wake up! Wake up!" If I fail to open the door, she opens it herself. If the door is locked, she jiggles the handle until she forces the door open. I just leave the door open now. Making the best of a bad situation.)

    Anyway, later that morning, the following conversation took place between my niece and an adult family member (which conversation I have taken the liberty of translating into English):

    "Why did you wake up Uncle Raymond?"

    I wanted cereal for breakfast.

    "Why didn't you ask Mommy?"

    Mommy was still sleeping.

Page 369 of 447 (4,467 items) «367368369370371»