December, 2008

  • The Old New Thing

    2008 year-end link clearance

    • 20 Comments

    Time for the semi-annual link clearance.

    Finally, we have the traditional plug for my column in TechNet Magazine:

  • The Old New Thing

    Sorry, I don't get calls on this phone often

    • 7 Comments

    Many years ago, I was in a small meeting: It consisted of the project manager, me, and one other person. Just a quick little status meeting to discuss how things were going. We were a few minutes into the meeting when the project manager's cell phone rang. Now, this was back in the days before cell phones were ubiquitous. They were pretty spendy gadgets; pulling out your shiny $400 Nokia 8810 was an ostentatious move, allowing you to demonstrate your alpha position in the social hierarchy.

    Anyway, when the cell phone rang, the project manager answered it and started talking. After a little while, it became clear to me that this person was taking the call without so much as a "Would you excuse me for a few minutes?", so I headed down to the lobby and read the newspaper for a while.

    When I returned, the project manager explained, "Sorry, I don't get calls on this phone often."

    I replied, "That's okay. I don't read The Wall Street Journal often."

  • The Old New Thing

    Crazy or cell phone?

    • 53 Comments

    You've seen it, I'm sure. People walking down the street talking to themselves. Crazy or cellphone?

    What really gets me are the people who wear the headsets even when they aren't talking on the telephone, but rather in anticipation of receiving a telephone call. To those people, I have this to say to you:

    You're not that important. Get over yourself.

    I remember a few years ago, I was in Los Angeles attending a little party and got a ride home from somebody who was heading my way. We got in the car, and she put on her headset before putting the car in gear. It was a half-hour drive. No telephone call.

  • The Old New Thing

    Every crash is a potential security vulnerability

    • 8 Comments

    Whenever I post about a programming error that can lead to crashes, the security team gets all excited and starts looking for ways to exploit it. For example, when I wrote about the fundamentally flawed DONT_RESOLVE_DLL_REFERENCES flag, the security folks went scouring through the Windows source code looking for anybody who passed that flag, and then tried to come up with ways they could trick the code into loading an unintended DLL and causing trouble.

    I wouldn't have known about this exercise at all if one of the team members hadn't forwarded me some email discussing their preliminary investigations as if to say, "See what you started?"

  • The Old New Thing

    Undecorating names to see why a function can't be found

    • 28 Comments

    Here's a problem inspired by actual events.

    When I build my project, it compiles fine, but it fails during the link step with an unresolved external:

    program.obj : error LNK2001: unresolved external symbol
    "public: virtual wchar_t const * __thiscall
    UILibrary::PushButton::GetName(class UILibrary::StringHolder * *)"
    (?GetName@PushButton@UILibrary@@UAEPB_WPAPAVStringHolder@2@@Z)
    

    The function I'm trying to call exists in the source code for uilibrary.lib; I'm looking at it right now. And the definition in the source code matches the declaration in the header file:

    namespace UILibrary {
     ...
     class PushButton {
     public:
      virtual LPCWSTR GetName(StringHolder **Holder);
     };
     ...
    }
    

    Why can't the linker find it? (Other functions in uilibrary.lib link just fine.)

    In order to find something, you have to be looking in the right place, and the thing you're looking for actually needs to be there. (And you have to be able to see it when it's there.) The first part, looking in the right place, appears to be addressed by the parenthetical: The linker is definitely looking in uilibrary.lib since it managed to find other things in that library.

    Let's look at the second step, then. Is the thing you're looking for really there? I fired up a little hex editor on uilibrary.lib, but you could use strings or, if you really want to get fancy, link /dump /headers. I went looking for "GetName@PushButton" to see if the member function was actually in the library.

    And yup, the function is there. But it looks slightly different: ?GetName@PushButton@UILibrary@@UAEPBGPAPAVStringHolder@2@@Z. (See if you can spot the difference.) Aha, the symbol couldn't be found because it indeed doesn't exist! What does exist is something that superficially resembles the symbol we want, but which has different decoration. We ask the undname program to convert this name into something a bit more readable:

    C:\> undname ?GetName@PushButton@UILibrary@@UAEPBGPAPAVStringHolder@2@@Z
    public: virtual unsigned short const * __thiscall
    UILibrary::PushButton::GetName(class UILibrary::StringHolder * *)
    

    Looking carefully at the two functions, we see that the difference is that the one that program.obj is looking for has a return type of wchar_t const *, whereas the one in the library returns a unsigned short const *.

    At this point the answer is obvious. The library was compiled with the /Zc:wchar_t-* flag, which disables wchar_t as a native type. When that happens, the Windows header files gives the wchar_t symbol the definition typedef unsigned short wchar_t; On the other hand, the customer's project was being compiled without that switch, in which case wchar_t is a native type and not an alias for unsigned short.

    Now you know enough to solve this customer's problem, which is very similar to the previous one:

    When I build my project, it compiles fine, but it fails during the link step with an unresolved external:

    program.obj : error LNK2019: unresolved external symbol
    "long __cdecl UILibrary::Initialize(bool)"
    (?Initialize@UILibrary@@YAJ_N@Z)
    

    The function as it exists in the library undecorates as follows:

    long __stdcall UILibrary::Initialize(bool)
    

    Note

    The undname program and the /Zc:wchar_t- switches are specific to the Microsoft Visual C++ compiler. Naturally, if you use a different compiler, you should use the utility or command line switch appropriate to your compiler. In particular, if you use the Visual Studio development environment, I'm told (but have not tried it myself) that the switch you're looking for is called "Treat wchar_t as a built-in type" on the "C/C++ Language" property page.

  • The Old New Thing

    Why are all computers shown with a Printers folder even if printer sharing is disabled?

    • 27 Comments

    When you visited a computer on the network by typing \\computername into the address bar, Explorer showed you a Printers folder if the computer had printer sharing enabled. But starting in Windows Vista, the Printers folder is shown regardless of whether the remote computer is sharing any printers. Why did this change?

    Communicating with the remote computer to ask it about its printers simply took too long. The IShellFolder::EnumObjects method returns an enumerator that produces a list of items in the folder. Think of it as the shell namespace version of FindFirstFile. When the IEnumIDList::Next method is called, it must produce the next item in the folder or return a code that means Sorry, no more items. There is no return code that means Hey, deciding on the next item is going to take a while, so maybe you should go do something else for a while and check back later when I finally have an answer for you. After all, FindNextFile doesn't have such a return code either. It returns the next file or says No more files. (Yes, there are also other errors that can be returned, but they aren't important here.)

    Now, Explorer does the enumeration of folder contents on a background thread, so the UI remains responsive while all this querying is going on to determine whether or not to show the Printers folder, but a responsive UI is scant consolation if it's a responsive Please Wait message. If you went to a remote computer, the folder would show a flashlight while the background thread did its thing, and then two minutes later (or sometimes longer), it finally would show you what it found. That's two minutes of your life you can't get back. (I predict people will use that one sentence as an excuse to go off-topic.)

    As I've quipped before, the fastest code is the code that never runs. Instead of trying to figure out whether a remote computer is sharing any printers with you, just show a Printers folder icon. Users who are interested in seeing the printers can double-click the Printers folder icon, and then they won't be too surprised to find that they have to wait a while for the remote computer to respond with its list of printers. Which might be empty.

  • The Old New Thing

    Then again, sometimes the improvement is merely incremental

    • 18 Comments

    Several years ago, the security department sent out a company-wide memo:

    Over the next few months, we will be upgrading the card readers on all of our major campuses. The old card readers show a solid red light when the door is locked, whereas the new card readers show a blinking red light.

    Aw-right, a blinking light. Now we're cookin' with gas!

  • The Old New Thing

    Foiled by my withered hand

    • 16 Comments

    A few years ago, some email was sent out to the product team asking for a volunteer hand model to demonstrate how to open the Windows Vista box. Alas, I withdrew myself from consideration due to my withered hand.

  • The Old New Thing

    Misheard lyrics as applied to Christmas songs

    • 6 Comments

    While visiting my young nieces, we sang some Christmas songs, and when it came to sing Toyland, the four-year-old sang it with misheard lyrics: "Toi-let! Toi-let!"

  • The Old New Thing

    Why isn't there a SendThreadMessage function?

    • 42 Comments

    Here's an interesting customer question:

    Windows has PostMessage and SendMessage. It also has PostThreadMessage but no SendThreadMessage. Why isn't there a SendThreadMessage function? Am I forced to simulate it with an event?

    What would this imaginary SendThreadMessage function do? Recall that SendMessage delivers the message directly to the window procedure; the message pump never sees it. The imaginary SendThreadMessage function would have to deliver the message directly to.... what? There is no "thread window procedure" to deliver it to.

    Okay, maybe you still intend to process the thread message in your message pump, but you want the caller of the imaginary SendThreadMessage function to wait until you've finished processing the message. But how does it know when you're finished? It can't wait for DispatchMessage to return, since DispatchMessage can't dispatch thread messages. (Where would it dispatch them to?) The processing of the thread message is completely under the control of the message pump. The window manager gives it a thread message, and as far as the window manager is concerned, that's the end of the story.

    You might say that the processing of the thread message is complete when somebody next calls GetMessage or PeekMessage, but there's no guarantee that the next call to a message-retrieval function will come from the message pump. Handling the thread message may result in a call to MessageBox, and as a modal function, it will have its own message loop, which will call GetMessage, resulting in your imaginary SendThreadMessage function deciding that message processing is complete when in fact it's still going on.

    What should you do instead? Just create a window and send it a message. The scenarios where you would want to use the PostThreadMessage function are very limited and specialized. Under normal circumstances, you should just send a regular window message.

Page 1 of 4 (38 items) 1234