October, 2007

  • The Old New Thing

    The Acorn Wand, key to a magical puzzle hunt

    • 8 Comments

    Puzzle hunts are a popular pastime at Microsoft. For the Microsoft Intern Puzzleday 2007, the puzzle design team decided upon a Harry Potter theme. Competitors ("students") formed teams ("study groups") as they attended classes at the Hogwarts campus at Microsoft. Of course, since this is Harry Potter, you need a magic wand, so the puzzle design team made a bunch of functional magic wands.

    Some members of the puzzle design team had attended Hogwarts and the Draconian Prophecy and came back raving about these amazing magic wands. The wand designer (who goes by the name Acorn) advised the puzzle design team on how to build their own wands, and they ordered custom circuit boards, soldered the components, assembled the plastic enclosures, and programmed the wands to recognize the puzzle spells.

    Solving each puzzle revealed a spell in the form of a series of wand motions. The wand itself contained an accelererometer and supporting firmware to recognize the motions and determine which (if any) spell was cast. After performing a spell, you shook the wand back and forth, and the persistence of vision effect permitted the wand to display a short message. (As an added bonus, the puzzle design team added a lumos spell which lit the tip of the wand for 30 seconds.)

    Pretty neat if you ask me.

  • The Old New Thing

    It rather involved being on the other side of this airtight hatchway: Local execution

    • 68 Comments

    The security response team gets all sorts of reports, and a good number of them are from people who just get excited that they were able to do something unusual, even if it isn't a security vulnerability.

    Attached please find a security exploit in the ABC ActiveX control. If you save this Web page to a file and double-click it, it <does something that Web pages shouldn't be allowed to do>.

    The security folks study the Web page and discover that it indeed uses the ABC ActiveX control and invokes a method that is not safe from untrusted script, say, delete a file. But the control is marked not safe for scripting. How can script execute it?

    More careful study shows that the not safe for scripting attribute is indeed being respected. Copying the page to a Web server and visiting it from Internet Explorer blocks the creation of the ActiveX object, as expected. The only reason the local Web page version works is that you copied the file to your computer and ran it from there. If you do that, it runs in the context of the local computer rather than an untrusted Web server.

    When this was pointed out to the person reporting the alleged vulnerability, the explanation was, "That's right. To use this exploit, you have to convince users to save the file to their computer and double-click it. I understand that there is a lot that would have to happen for this exploit to succeed, but it's still possible."

    Well, heck, if that's your M.O, then why bother with the Web page? You can do the same thing with a boring executable. "To use this exploit, you simply have to convince users to save the file to their computer and double-click it. I understand that there is a lot that would have to happen for this exploit to succeed, but it's still possible."

    Saving the file to the local computer is the step that crossed the security boundary. And that's the step these people just waved their hands at. They're assuming they're on the other side of the airtight hatchway and then proclaiming, "Woo-hoo! I managed to sneak to the other side of the airtight hatchway!"

  • The Old New Thing

    Email tips from Adam Phillabaum

    • 3 Comments

    Adam Phillabaum of Doing Boeing (who kept the name even though he left Boeing and now works for PayScale) has his own tips for writing email. Recommended reading.

  • The Old New Thing

    You can't change it, but you can hide it and add something that looks like it

    • 43 Comments

    Today we have another case of "Now you have two problems." The corporate customer already solved their problem halfway and needed help on the other half. The impossible half.

    We want to change the Add or Remove Programs icon in the Windows XP control panel so it runs our custom install management program instead of running the one built into Windows. In other words, we want to change what happens when the user clicks the Add or Remove Programs icon. Is this possible?

    What they specifically request isn't possible because the icon is provided by Add or Remove Programs itself, but you can easily get the same effect. This is why it's important to understand why somebody wants to do something even though they are asking how to do it. Once you understand why they're doing something, you can unwind the steps they've taken and come up with something that doesn't answer the specific question but still solves the bigger problem.

    You can't redirect an icon but you can remove the existing icon and replace it with something else. Set a policy to remove the existing Add or Remove Programs icon from the control panel and then write your own control panel called Add or Remove Programs.

    I'm not sure what happened next, but they acted as if I wrote, "Could you please repeat the question?"

    Raymond, we need to replace the link in the Control Panel with a custom program that elevates the user's privileges so that they can manage the programs on the computer. Is there any registry key or setting that specifies how the control panel applet is launched that we could inject an EXE into? This EXE would just be a wrapper for launching the original CPL.

    I'm assuming that the extra wrinkle of "And then we want to re-launch the original CPL" made them think their situation was somehow special, so that regular-grade advice wasn't good advice. They needed premium.

    You can still follow the original suggestion. Remove the original CPL via policy and add your custom EXE (which then launches the original CPL after doing whatever it wants).

    But no, that wasn't the problem. They simply missed the point entirely. They were so focused on looking for the sentence "Here is how you change what the icon launches" that they completely missed the point of the suggestion. They're looking for a solution to the specific problem instead of the bigger problem.

    How do you configure the policy to launch our EXE instead of the CPL?

    At this point I pulled out my bad analogy gun.

    In your car there is an ignition switch. It is wired to the starter. You want to make the driver take a breathalyzer test before they can start the car.

    Plan A (what you are proposing): Patch into the wire connecting the ignition switch to the starter so it goes through a breathalyzer. Unfortunately the wire is sheathed in kevlar and cannot be cut open. The designers of the wire did not include any hooks for breathalyzers.

    Plan B (my suggestion): Remove the old ignition switch and install a new ignition switch that is connected to a breathalyzer. If the driver passes the breathalyzer test, then your ignition switch turns the original ignition switch. Notice that this method doesn't require you to bust open the kevlar sheathing that protects the wire between the old ignition switch and the starter.

    All the driver sees is a keyhole. They stick the key in and turn the key. If you're really clever you make your new ignition switch's faceplate look just like the original so the driver can't tell the difference between the two methods (all they see is a keyhole, a breathalyzer, and if they pass, the car starts).

    • The existing CPL is the old ignition switch.
    • Your replacement program is the new ignition switch.
    • Deploying the Hide the Add or Remove Programs control panel policy is removing the old ignition switch.
    • The Add or Remove Programs icon is the keyhole.
    • The way Windows XP works, the keyhole leads to the old ignition switch.
    • Plan B: Use policy to remove the old ignition switch, and install new ignition switch (your replacement program). Use some paint to make the new keyhole look just like old keyhole. The person in driver's seat is none the wiser.

    You know you're in trouble when I have to pull out my bad analogy gun.

    Note: I don't know whether this trick will actually work, but it seemed a useful example of the principle of "Just because it has to look like something doesn't mean it has to be that something."

  • The Old New Thing

    Why doesn't Explorer show recursive directory size as an optional column?

    • 43 Comments

    "Why start up another program to see folder sizes, when they should just be right there, in Explorer, all the time?"

    The same reason \\ does not autocomplete to all the computers on the network: Because it would destroy corporate networks.

    Showing folder sizes "all the time" means that when you open, say, the root of a large server, Explorer would start running around recursively enumerating every single directory on the server in order to compute the folder sizes. One person doing this to a server is bad enough. Imagine if hundreds of people did it simultaneously: The server would be hammered continously.

    Even worse: imagine doing this across a limited-bandwidth link like a VPN or an overseas link. The link would be saturated with file enumerations and wouldn't have any bandwidth remaining for "real work". Even the change-notifications that Explorer registers are cause for much hair-pulling on corporate networks. (And these are change-notifications, which are passive.)

    Even on a home computer, computing folder sizes automatically is is still not a good idea. How would you like it if opening a folder caused Explorer to start churning your disk computing all the folder sizes recursively? (Then again, maybe you don't mind, in which case, go nuts.)

    (Of course, the question sidesteps the question the linked article tries to address, namely, "What do you mean by the size of a directory anyway?")

  • The Old New Thing

    The King County Council race gets even stranger

    • 10 Comments

    I told you it was going to get weird.

    In the month since my last report, there have been a few developments in the county council race between an accused drunk (the incumbent) and a fringe candidate (the challenger).

    The Seattle Times tries to summarize the state of the race with a series of articles:

  • The Old New Thing

    If you pass enough random numbers, eventually one of them will look valid

    • 12 Comments

    One customer traced a problem they were having to the way they were calling a function similar in spirit to this one:

    HGLOBAL CopyClipboardData(UINT cf)
    {
     HGLOBAL hglob = NULL;
     HANDLE h = GetClipboardData(cf);
     if (h) {
      void *p = GlobalLock(h);
      if (p) {
       SIZE_T size = GlobalSize(h);
       hglob = GlobalAlloc(GMEM_FIXED, size);
       if (hglob) {
        CopyMemory(hglob, p, size);
       }
       GlobalUnlock(h);
      }
     }
     return hglob;
    }
    

    This function takes a clipboard format and looks for it on the clipboard. If found, it returns a copy of the data.

    Looks great, huh?

    The problem is that the customer would sometimes call the function as CopyClipboardData(CF_BITMAP). The CF_BITMAP clipboard format stores its contents in the form of a HBITMAP, not an HGLOBAL.

    The question from the customer:

    This code was written in 2002, and we are wondering why it works "most" of the time and crashes sporadically. We expected that the call to GlobalLock would fail with an invalid parameter error, but sometimes it succeeds, and then when we call GlobalSize we crash. Why does it crash sometimes?

    You already know the answer to this. GlobalAlloc works closely with GlobalLock so that GlobalLock can be fast. The bitmap handle returned by GetClipboardData usually fails the quick tests performed by GlobalLock to see whether the parameter is a fixed memory block, in which case the GlobalLock must go down its slow code path, and it is in this slow code path that the function recognizes that the the handle is downright invalid.

    But once in a rare while, the bitmap handle happens to smell just enough like a fixed global handle that it passes the tests, and GlobalLock uses its highly optimized code path where it says, "Okay, this is one of those fixed global handles that GlobalAlloc created for me. I can just return the pointer back." Result: The call to GlobalLock succeeds (garbage in, garbage out), and then you crash in the GlobalSize function where it tries to use the HBITMAP as if it were a HGLOBAL and access some of the memory block metadata, which isn't there since the handle isn't valid after all.

    The bitmap handle is basically a random number from the global heap's point of view, since it's just some number that some other component made up. It's not a global handle. If you generate enough random numbers, eventually one of them will look like a valid parameter.

  • The Old New Thing

    What's the deal with the EM_SETHILITE message?

    • 28 Comments

    If you look up the documentation on the EM_SETHILITE and EM_GETHILITE messages, they just say "not implemented". What's going on here?

    The EM_SETHILITE and EM_GETHILITE messages were added back in 2002 for the breadcrumb bar to use. Back in those days, the breadcrumb bar wasn't what you see in Windows Vista today, a series of buttons with drop-down arrows, each representing a level in the hierarchy. The breadcrumb bar back in those days was just a fancy-looking address bar (i.e., an edit control). Instead of having a button for each level in the hierarchy, the breadcrumb bar would highlight a path component if you moved the mouse over it (or used the keyboard to select it). Instead of having drop-down arrows, the breadcrumb bar would wait for you to hover your mouse and the highlighted path would auto-open to show the menu of sibling items.

    The design of the breadcrumb bar changed and the "fancy-looking address bar" design was abandoned. The functionality of the EM_SETHILITE and EM_GETHILITE messages was ripped out, but the message numbers were left behind to avoid build breaks in case anybody was using those messages. Of course the messages have no effect any more, but at least the product still builds. The people who were using the message can then wean themselves from it on their own schedule.

    This is one of the realities of developing both a library and the library's clients simultaneously. If you are the person who is responsible for the library and you intend to make a breaking change, you have to do it in stages so that all the clients can make the transition smoothly. It's not like you can go in and change all the clients yourself since they aren't yours to change, and you might not have access to the source code anyway. The clients belong to other teams, or even other companies. You have to coordinate with those other teams and let them know what your transition plan is so they can work it into their schedule.

    The fact that the EM_GETHILITE and EM_SETHILITE messages still linger is just leftover dirt that never got cleaned up. What's in the header files now is the penultimate stage of the transition plan. The final stage would have been to remove the messages from the header file entirely, but the "no changes to public header files allowed" deadline came before the final stage could be executed, and now that the messages are in a public header file, they have to stay in there forever. Even though they don't do anything.

  • The Old New Thing

    What's the difference between LVM_HITTEST and LVM_INSERTMARKHITTEST?

    • 3 Comments

    One customer was confused by the two list view hit-test messages LVM_HITTEST and LVM_INSERTMARKHITTEST. What is the difference between the two?

    The LVM_HITTEST message tries to find the item the point is over.

    The LVM_INSERTMARKHITTEST message tries to find the item the point is next to.

    For example, suppose you have two 32×32 items, item zero at (0, 0) and item one at (0, 32).

    Coordinates LVM_HITTEST LVM_INSERTMARKHITTEST
    (0, 34) On item 1 Next to item 1 on the top side
    (0, 99) Nowhere Next to item 1 on the bottom side

    You use LVM_HITTEST when you the user is dragging something and you want to see what the item is going to be dropped on. For example, your program might ask the user to drag an icon representing a trouble report and drop it onto the icon representing the department the report should be assigned to.

    You use LVM_INSERTMARKHITTEST when the user is dragging something and you want to see what the item is going to be dropped between. For example, your program might show a list of customers, and the user can drag a new customer into the list or rearrange the customers by dragging an existing one. The LVM_INSERTMARKHITTEST message tells you where the dropped item should go.

    The shell uses both of these hit-test messages when you drop a file into an Explorer window. It uses the Explorer uses LVM_HITTEST to determine whether you're dropping the file onto an item in the folder (hit-test reports an item) or whether you're dropping the file into the folder itself (hit-test reports nowhere). Furthermore, if you're dropping into the folder and Auto-Arrange is enabled, then Explorer uses the LVM_INSERTMARKHITTEST to determine where to place the item after it is dropped.

  • The Old New Thing

    Superstition: Why is GetFileAttributes the way old-timers test file existence?

    • 45 Comments

    If you ask an old-timer how to test for file existence, they'll say, "Use GetFileAttributes." This is still probably the quickest way to test for file existence, since it requires only a single call. Other methods such as FindFirstFile or CreateFile require a separate FindClose or CloseHandle call, which triggers another network round-trip, which adds to the cost.

    But back in the old days, the preference for GetFileAttributes wasn't just a performance tweak. If you tried to open the file to see if it existed, you could get the wrong answer!

    Some network providers had a feature called a "data path". You can add directories to the data path, and if any attempt to open a file failed, the network provider would try again in all the directories in the data path. For example, suppose your data path was \\server1\backups\dir1;\\server1\backups\dir2 and you tried to open the file File.txt. If the file File.txt could not be found in the current directory, the network provider would try again, looking for \\server1\backups\dir1\File.txt, and if it couldn't find that file, it would try again with \\server1\backups\dir2\File.txt.

    All this extra path searching happened behind Windows's back. Windows had no idea it was happening. All it knew is that it issued an open call, and the open succeeded.

    As a result, if you used the "open a file to see if it exists" algorithm, you would get the wrong result for any file that existed on the data path but not in the current directory. These network providers didn't search the data path in response to GetFileAttributes, however, so a call to GetFileAttributes would fail if the file didn't exist in the current directory, regardless of whether it existed on the data path.

    I don't know if any network providers still implement this data path feature, but Windows code in general sticks to GetFileAttributes, because it's better to be safe than sorry.

Page 1 of 4 (33 items) 1234