January, 2010

  • The Old New Thing

    If you are trying to understand an error, you may want to look up the error code to see what it means instead of just shrugging


    A customer had a debug trace log and needed some help interpreting it. The trace log was generated by an operating system component, but the details aren't important to the story.

    I've attached the log file. I think the following may be part of the problem.

    [07/17/2005:18:31:19] Creating process D:\Foo\bar\blaz.exe
    [07/17/2005:18:31:19] CreateProcess failed with error 2

    Any ideas?

    Bob Smith
    Senior Test Engineer
    Tailspin Toys

    What struck me is that Bob is proud of the fact that he's a Senior Test Engineer, perhaps because it makes him think that we will take him more seriously because he has some awesome title.

    But apparently a Senior Test Engineer doesn't know what error 2 is. There are some error codes that you end up committing to memory because you run into them over and over. Error 32 is ERROR_SHARING_VIOLATION, error 3 is ERROR_PATH_NOT_FOUND, and in this case, error 2 is ERROR_FILE_NOT_FOUND.

    And even if Bob didn't have error 2 memorized, he should have known to look it up.

    Error 2 is ERROR_FILE_NOT_FOUND. Does the file D:\Foo\bar\blaz.exe exist?

    No, it doesn't.


    Bob seems to have shut off his brain and decided to treat troubleshooting not as a collaborative effort but rather as a game of Twenty Questions in which the person with the problem volunteers as little information as possible in order to make things more challenging. I had to give Bob a nudge.

    Can you think of a reason why the system would be looking at D:\Foo\bar\blaz.exe? Where did you expect it to be looking for blaz.exe?

    This managed to wake Bob out of his stupor, and the investigation continued. (And no, I don't remember what the final resolution was. I didn't realize I would have to remember the fine details of this support incident three years later.)

  • The Old New Thing

    The wrong way to determine the size of a buffer


    A colleague of mine showed me some code from a back-end program on a web server. Fortunately, the company that wrote this is out of business. Or at least I hope they're out of business!

    size = 16384;
    while (size && IsBadReadPtr(buffer, size)) {
  • The Old New Thing

    Historically, Windows didn't tend to provide functions for things you can already do yourself


    Back in the old days, programmers were assumed to be smart and hardworking. Windows didn't provide functions for things that programs could already do on their own. Windows worried about providing functionality for thing that programs couldn't do. That was the traditional separation of responsibilities in operating systems of that era. If you wanted somebody to help you with stuff you could in principle do yourself, you could use a runtime library or a programming framework.

    You know how to open files, read them, and write to them; therefore, you could write your own file copy function. You know how to walk a linked list; the operating system didn't provide a linked list management library. There are apparently some people who think that it's the job of an operating system to alleviate the need for implementing them yourself; actually that's the job of a programming framework or tools library. Windows doesn't come with a finite element analysis library either.

    You can muse all you want about how things would have been better if Windows had had an installer library built-in from the start or even blame Windows for having been released without one, but then again, the core unix operating system doesn't have an application installer library either. The unix kernel has functions for manipulating the file system and requesting memory from the operating system. Standards for installing applications didn't arrive until decades later. And even though such standards exist today (as they do in Windows), there's no law of physics preventing a vendor from writing their own installation program that doesn't adhere to those standards and which can do anything they want to the system during install. After all, at the end of the day, installing an application's files is just calling creat and write with the right arguments.

    Commenter Archangel remarks, "At least if the ACL route had been taken, the installers would have had to be fixed - and fixed they would have been, when the vendors realised they didn't run on XP."

    These arguments remind me of the infamous "Step 3: Profit" business plan of the Underpants Gnomes.

    • Step 1: Require every Windows application to adhere to new rules or they won't run on the next version of Windows.
    • ...
    • Step 3: Windows is a successful operating system without applications which cause trouble when they break those rules.

    It's that step 2 that's the killer. Because the unwritten step 2 is "All applications stop working until the vendors fix them."

    Who's going to fix the the bill-printing system that a twelve-year-old kid wrote over a decade ago, but which you still use to run your business. (I'm not making this up.) What about that shareware program you downloaded three years ago? And it's not just software where the authors are no longer available. The authors may simply not have the resources to go back and update every single program that they released over the past twenty years. There are organizations with thousands of install scripts which are used to deploy their line-of-business applications. Even if they could fix ten scripts a day, it'd take them three years before they could even start thinking about upgrading to the next version of Windows. (And what about those 16-bit applications? Will they have to be rewritten as 32-bit applications? How long will that take? Is there even anybody still around who understands 16-bit Windows enough to be able to undertake the port?)

  • The Old New Thing

    What idiot would hard-code the path to Notepad?


    There seemed to be a great deal of disbelief that anybody would hard-code the path to Notepad.

    Here's one example and here's another.

    There's a large class of problems that go like this:

    I'm running Program X, and when I tell it to view the error log, I get this error message: CreateProcess of "C:\Windows\Notepad.exe errorlog.txt" failed: error 2: The system cannot find the file specified. What is wrong and how do I fix it?

    Obviously, the file C:\Windows\Notepad.exe is missing. But how can that be? Well, Windows Server 2008 bit the bullet and removed one of the copies of Notepad. Once you learn this, troubleshooting the above problem becomes a simple exercise in psychic debugging.

    My psychic powers tell me that you're running Windows Server 2008. The Notepad program no longer exists in the Windows directory; it's now in the system directory. Find the setting for your program that lets you change the program used for viewing error logs and tell it to use C:\Windows\System32\Notepad.exe.

    Of course, this tip works only if the program permits you to change the program used for viewing error logs. If they hard-code the path, then you'll have to find some other workaround. (For example, you might try using the CorrectFilePaths shim.)

  • The Old New Thing

    People just like you, for certain values of you


    I received a brochure in the mail for a local church which says that it's "full of people just like you."

    Everybody in the brochure is white.

    "You'll fit right in!" it concludes.

    Bonus chatter: My friends guessed that perhaps the church members are all computer programmers who work at Microsoft and speak Swedish badly.

  • The Old New Thing

    Learning how to cheat at Candy Land


    My young niece received the game Candy Land and wants to play it several times a day. Naturally, I am frequently drafted as an opponent.

    I discovered that my niece cheats rampantly. Sometimes, she will advance three green squares instead of two. Or if a yellow card will take her to a licorice square (lose a turn), she will ignore it and go to the yellow square after that. But the best cheating takes place when she draws a pink location card which sends her backward.

    My niece is always careful to draw the card and turn it so only she can see what it is. If the card is an unfavorable one, she will hide it under her knee and tell me, "Hey, go play with the baby for a little bit." I naturally oblige, and when I return after a few seconds, her location card has magically changed into a two-green card or something else comparatively harmless.

    I found this change in personality surprising. In earlier encounters, she was happy to share in the winning. In fact, sometimes, while resetting a game after winning, she would say, "Okay, you win this next one." And she would let me win!

    Anyway, after one of the games of Candy Land which she won (actually, she wins every game), I declined to play another because she was cheating. She pled with me, "Okay, this time, no cheating." I agreed to play another game.

    In the game that followed, she cheated five times, even more than in the previous game.

    She wanted to play again. "I'm serious, I'm not cheating now."

    In the "I'm serious, no cheating" game, there was, I will concede, technically no cheating during game play.

    Instead, she stacked the deck.

    Perhaps I need to study up on how to cheat at Candy Land. I could mark the cards or go for one of the more advanced methods.

    Bonus chatter

  • The Old New Thing

    How about not granting debug privileges to users?


    Commenter Yuhong Bao suggests, "How about not granting debug privileges on the user? This will make bypassing the protection impossible."

    This is such a great idea that Windows has worked that way for years.

    Normal non-administrative users do not have debug privilege. They can only debug processes that they already have PROCESS_ALL_ACCESS to. In other words, non-administrative users can only pwn processes that they already pwn. No protection is being bypassed since you had full access in the first place.

    The SeDebugPrivilege allows you to debug any process, even those to which you do not have full access. This is clearly dangerous, which is why it's not granted to non-administrative users by default.

    Yuhong Bao also suggests, "How about separating the dangerous activities from the non-dangerous activities, or better, only allowing approved programs to do the dangerous activities?" (Where dangerous activities are defined as things that modify the program behavior.) I'm assuming this is discussing limiting the capabilities of SeDebugPrivilege, since in the absence of SeDebugPrivilege, the scope of your abilities is limited to things you already had the ability to do anyway; debugging didn't add anything new.

    But even if you limited SeDebugPrivilege to nondestructive actions, you can still lose the farm. This imaginary SeLimitedDebugPrivilege would still let you read a target process's memory, which means you can do things like steal passwords and snoop on the activities of other users.

    The last suggestion is to "only allow approved programs to do the dangerous activities." Again, I'm assuming this is discussing limiting the capabilities of SeDebugPrivilege, because without SeDebugPrivilege there is no new danger. But even in that limited context, what is an "approved program"? Approved by whom?

    Must the program be digitally signed by Microsoft? I suspect people who write debuggers which compete with, say, Microsoft Visual Studio, would be upset if they had to submit their debugger to Microsoft for approval. And what are the requirements for receiving this approval? Does the debugger have to pass some battery of tests like WHQL? There are already plenty of readers of this Web site who reject WHQL as useless. Would this "debugger certification" also be useless?

    Or maybe approval consists of merely being digitally signed at all? There are plenty of readers of this Web site who object to the high cost of obtaining a digital certificate (US$399; I don't think the $99 discounted version works for code signing.) And there are also plenty of readers who consider code signing to be payola and designed to maximize profit rather than effectiveness.

    Or do you mean that the program needs to be listed in some new registry key called something like Approved Debuggers? Then what's to stop a rogue program from just auto-approving itself by writing to the Approved Debuggers registry key on its own?

    But then again, all this is a pointless discussion once you realize that SeDebugPrivilege is granted by default only to administrators. And since administrators already pwn the machine, there's no protection that SeDebugPrivilege bypasses: You already bypassed it when you became an administrator.

  • The Old New Thing

    Can you get rotating an array to run faster than O(n²)?


    Some follow-up remarks to my old posting on rotating a two-dimensional array:

    Some people noticed that the article I linked to purporting to rotate the array actually transposes it. I was wondering how many people would pick up on that.

    I was surprised that people confused rotating an array (or matrix) with creating a rotation matrix. They are unrelated operations; the only thing they have in common are the letters r-o-t-a-t-i. A matrix is a representation of a linear transformation, and a rotation matrix is a linear transformation which rotates vectors. In other words, applying the rotation matrix to a vector produces a new vector which is a rotated version of the original vector. The linear transformation is a function of one parameter: It takes a vector and produces a new vector. A rotation matrix is a matrix which rotates other things. Whereas rotating an array is something you do to the array. The array is the thing being rotated, not the thing doing the rotating. It didn't even occur to me that people would confuse the two. It's the difference a phone dial and dialing a phone.

    Showing that you cannot rotate an array via matrix multiplication is straightforward. Suppose there were a matrix R which rotated an array (laid out in the form of a matrix) clockwise. The result of rotating the identity matrix would be a a matrix with 1's along the diagonal from upper right to lower left, let's call that matrix J. Then we have RI = J, and therefore R = J. Now apply R to both sides: RRI = RJ = I and therefore R² = I. But clearly rotating clockwise twice is not the identity for n ≥ 2. (Rotating clockwise twice is turning upside-down.)

    A more mechanical way to see this is to take the equation R = J and show that J does not perform the desired operation; just try it on the matrix with 1 in the upper left entry and 0's everywhere else.

    And since it's one of those geeky math pastimes to see how many differents proofs you can come up with for a single result, the third way to show that rotation cannot be effected by matrix multiplication is to observe that the transformation is not linear. (That's the magical algebra-theoretical way of showing it, which is either so obvious you can tell just by looking at it or so obscure it defies comprehension.) [The transformation viewed as a transformation on matrices rather than a transformation on column vectors is indeed linear, but the matrix for that would be an n² × n² matrix, and the operation wouldn't be matrix multiplication, so that doesn't help us here.]

    The last question raised by this exercise was whether you could do better than O(n²). Computer science students spend so much time trying to push the complexity of an algorithm down that they neglect to learn how to tell that you can't go any lower. In this case, you obviously can't do better than O(n²) because every single one of the n² entries in the array needs to move (except of course the center element if n is odd). If you did less than O(n²) of work, then for sufficiently large n, you will end up not moving some array elements, which would be a failure to complete the required operation.

    Bonus chatter: Mind you, you can do better than O(n²) if you change the rules of the problem. For example, if you allow pretending to move the elements, say by overloading the [] operator, then you can perform the rotation in O(1) time by just writing a wrapper:

    struct IArray
      virtual int& Element(int x, int y) = 0;
      virtual ~IArray() = 0;
    class RotatedArray : public IArray {
     RotatedArray(IArray *p) : m_p(p) { }
     ~RotatedArray() { delete m_p; }
     int& Element(int x, int y) {
      return m_p->Element(y, x);
     IArray *m_p;
    void RotateInPlace(IArray *& p, int N)
     p = new RotatedArray(p);

    This pseudo-rotates the elements by changing the accessor. Cute but doesn't actually address the original problem, which said that you were passed an array, not an interface that simulates an array.

  • The Old New Thing

    The wisdom of seventh graders: Success


    Seventh grade students (ages 12 to 13, roughly) were asked to write an essay on what success is and how you know when you've achieved it. The assignment was given under standardized test conditions: 90 minutes with nothing but pencil and paper, with an additional hour available upon request. (In practice, few students ask for the extra hour.)

    Remember, these are only the funny sentences/excerpts. Do not assume that all students write like this.

    On the nature of success

    • Success is not a very difficult thing to think about, but if you explain it, it can be hard to explain.
    • Stride to Success
    • Success is not the end, but the beginning.
    • As the say goes, the only time you will find sucess before work is in the dictionary.

    Recognizing success

    • You have to do something that is genuin and worth while.
    • Success means you have a jolly time.
    • It's a feel good feeling.
    • To me success is a goal a feeling of prowness. that tells me that this is a goal of your limits not an age limit.
    • Sucess is when you had the opportunity to do something greatful.
    • Success is shaking your butt in their face that you are better than them.
    • Another meaning for success is just winning. Winning is what most people think success is, but winning is only half the meaning of success. Winning is just winning. Yeah, but at least you can shake your butt in their face, and that's worth something.
    • Success is trying your best... I have a question. do teachers ever have success?
    • You know you have reached the point of succession when you do really well.
    • So many kinds of meanings can mean success but I think success mostly means to me a achieving.

    Steps which do not lead to success

    • If you slack you get failure. You end up poor, sad, terrible.
    • You can't just sit around watching television and eat Doritos.

    The fleeting nature of success

    • But even though money may make you happy it doesn't last forever.
    • After all, feeling like the king of the mountain doesn't come as soften as the frustration does.

    The recipe for success

    • After you graguat from callage you can say, Success has finaly hit me.
    • If you get good grades, you can go to a splendid colledge and then get a splendid sallary. Sounds splendid.
    • One way is to make a T chart. Put what your good at on the left and what you love on the left. Burn the right hand side.
    • My opinion of success is a cab driver.
    • If you do all of the things mentioned in this article, you'll have a very successful life.

    Personal stories of success

    • Whether your moment is singing on a stage to a huge audience, or handing out your first order of French fries at McDonald's.
    • Success can be as simple as winning a video game. You win easily and celebrate with a cookie. Do you shake your butt in their face?
    • I was the most happiest person ever!
    • Success is when you tell a casino that someone cheated at Black Jack.
    • Success is like when I was in 4th grade and I learned to play Smoke on the Water a little.
    • One thing that really makes a family is a pet.
    • outsmarting and generally twisting my opponents words against him feels like hitting the jackpot.
    • I was in such a dilemma!

    Future success

    • The fist and most important key to making a family is loving, beautiful, and wonderful wife.
    • I want to get a wife that is nice, hard working, and has simple pleasures.
    • My fantasies of success are having a great boyfriend, a job studying the migration paths of turtles in Australia, and eventually growing old and waltzing through an arch of Agust trees. But under no circumstances marry your boyfriend. That ruins it.
    • Over the past 12 years I've been alive, I've had many emotions experiences, and a few lovers. Boys write about their wives. Girls write about their boyfriends and lovers. Wait, lovers? How old are you again?
    • Success is feeling comfortable having Thanksgiving with your in-laws. I'm happy to declare that I have achieved success.

    Examples of other successful people

    • When Billy Armstrong made it to the moon, he had a great feeling of accomplishment.
    • The teacher went around asking what they wanted to be when they grew up. Most kids said normal things but one girl said she wanted to be a unicorn. The class laughed. Because she believed in her insane dream she is the creator of My Little Pony.
    • Mr. Bill Gates did not just read a get rich quick book and deside to crate Microsoft.

    Out of about 300 students, the number who cited Bill Gates as a successful person: 17.

  • The Old New Thing

    Why doesn't the window manager have a SetClipboardDataEx helper function?


    Jonathan Wilson asks why the clipboard APIs still require GlobalAlloc and friends. Why is there not a SetClipboardDataEx or something that does what SetClipboardData does but without needing to call GlobalAlloc?

    Okay, here's your function:

    HANDLE SetClipboardDataEx(UINT uFormat, void *pvData, DWORD cbData)
        if (uFormat == CF_BITMAP ||
            uFormat == CF_DSPBITMAP ||
            uFormat == CF_PALETTE ||
            uFormat == CF_METAFILEPICT ||
            uFormat == CF_DSPMETAFILEPICT ||
            uFormat == CF_ENHMETAFILE ||
            uFormat == CF_DSPENHMETAFILE ||
            uFormat == CF_OWNERDISPLAY) {
            return NULL; // these are not HGLOBAL format
        HANDLE hRc = NULL;
        if (hglob) {
            void *pvGlob = GlobalLock(hglob);
            if (pvGlob) {
                CopyMemory(pvGlob, pvData, cbData);
                hRc = SetClipboardData(uFormat, hglob);
            if (!hRc) {
        return hRc;


    Historically, Windows doesn't go out of its way to include functions like this because you can easily write them yourself, or you can at least find a framework library that did it for you. Windows focused on doing the things that only Windows could do, providing you the building blocks with which you can create your own programs.

    Besides, the classic clipboard is so old-school. The OLE clipboard provides a much richer interface, where you can generate data dynamically (for example as a stream) and expose it in formats other than just a chunk of bytes. Since SetClipboardData is old-school, if the window manager folks had written a function like SetClipboardDataEx, people would instead have asked the not unreasonable question, "Why did you bother to write a function that provides no essential new functionality to an old interface that was supplanted over a decade ago?"

Page 1 of 4 (32 items) 1234