January, 2014

  • The Old New Thing

    Why chicken wings dominate Super Bowl snack time


    This upcoming Sunday is the biggest sports day of the year in the United States: The championship game for the professional American Football league. The entire country grinds to a halt.

    The most famous secondary effect of the game is the commercials. So many people watch the game that television advertisement costs are the highest for the Super Bowl, which means that companies will produce spectacular ads specifically for the Super Bowl, which means that more people watch the Super Bowl just for the ads.

    Another secondary effect of the Super Bowl is the spike in chicken wing sales. The United States chicken industry even issues an Annual Chicken Wing Report. NPR explains how the chicken wing became the dominant snack food for the Super Bowl.

    Bonus viewing: A Guide to American Football.

  • The Old New Thing

    Non-psychic debugging: If somebody's complaining that a collection should be empty but isn't, you might want to see what's in there


    A programmer on the GHI team (yes, the same GHI team) reported that they were hitting an assertion failure using an internal library and asked for help debugging it.

    // All factories should be unregistered by now

    "Can somebody help me figure out which factory it is that did not get unregistered?"

    I didn't work on this internal library, but on the other hand I'm not afraid to look inside.

    Let's see what a m_pFactory­List looks like.

    0:000> ?? this->m_pFactoryList
    class LookupTable<CFactory*>
       +0x000 m_uListSize      : 1 // this probably means that the list has one element
       +0x004 m_pList          : 0x00212e60 LookupTable<CFactory*>::ENTRY // this is probably the list
       +0x008 m_uCapacity      : 0x7f
    0:000> ?? this->m_pFactoryList->m_pList
    struct LookupTable<CFactory*>::ENTRY * 0x00212e60
       +0x000 pszName          : 0x02cf4048  "GHI_factory"
       +0x004 data             : 0x02cf4ce0 CFactory* // I bet this is the item that got leaked
    0:000> dps 0x02cf4ce0 l1
    02cf4ce0  6b626d58 GHI!CGhiFactory::`vftable`

    No psychic powers needed here. I just followed my nose.

    The assertion says that a list is not empty. Therefore, we should look to see what is on the list.

    As a general rule, code is not intentionally written to be impossible to understand. The person who wrote it meant well, so if you see a member called m_uList­Size, it's a pretty safe bet that it represents the list size. And if you see a member called m_pList, it probably points to the start of the list.

  • The Old New Thing

    Can process IDs be greater than 64000? Because we're seeing process IDs greater than 64000


    A customer asked what to me was a very strange question.

    Can process IDs be greater than 64000? Because we're seeing process IDs greater than 64000.

    This is a strange question because the answer is right there: You're seeing process IDs greater than 64000 with your very own eyes. Do you doubt the evidence right there in front of you?

    It's like asking, "Is it possible to have an orange with no seeds? Because I have an orange with no seeds."

    We saw some time ago that process IDs can get very high indeed, although the kernel tries to keep the numbers small purely for cosmetic reasons.

    The customer explained why they were asking this question.

    Our application is crashing when the process ID gets too large. Here is the code:

    int eventId = System.Diagnostics.Process.GetCurrentProcess().Id;

    Okay, um, that code makes no sense.

    The code uses the process ID as the event ID. But event IDs are static; they are references to messages in your event source's message table. It's not like your message table contains 65535 entries like this:

    An event occurred in Process ID 1: %1
    An event occurred in Process ID 2: %1
    An event occurred in process ID 3: %1
    … and so on until …
    An event occurred in process ID 65535: %1

    The event ID describes what happened, and the process ID and other information goes into the payload.

    You can see from the format of event IDs that the event number can be at most 65535 because the upper bits of the event ID are used to encode other information.

    And the code crashes because the Write­Entry method specifically checks for absurd event IDs and rejects them with an Argument­Exception.

    The fix is therefore to put the process ID in the payload of your event and let the event number describe what actually happened, like "A multi-part print job was created."

  • The Old New Thing

    One of my favorite error codes: Optional parameter missing


    The error Optional parameter missing sounds awfully paradoxical, doesn't it. I mean, if the parameter is optional, why are you complaining that it's missing?

    This KB article explains why, specifically, the part that says, "If a parameter is omitted, the calling program must…".

    For those who don't want to click through, here's the deal: Methods described in a type library can declare parameters as optional. Optional parameters must come at the end of the parameter list, of course. The catch is how you programmatically invoke a method that contains optional parameters.

    If you want to call a method that has optional parameters, you still have to pass the parameters. But you have to pass them a special way so that the method knows that they were omitted. (Specifically, you have to pass them as type VT_ERROR, code DISP_E_PARAM­NOT­FOUND.)

    In other words, an optional parameter is optional from the high-level language, but it isn't optional at the low-level interface. Rather the optional keyword instructs the scripting engine to deploy syntactic sugar and allow the script to omit the parameters. The scripting engine then must follow specific rules in providing values for the parameters that were omitted by the script author.

    In the lingo of C# and C++, a parameter declared optional in the TLB is really a mandatory parameter whose default value is DISP_E_PARAM­NOT­FOUND.

  • The Old New Thing

    Why does my setup program detect the operating system incorrectly the second time I run it?


    A customer reported that when their application called the Get­Version­Ex function, it sometimes reported incorrect values. Specifically, the logs collected from clients shows that the first time the program was run on a Windows 7 machine, the operating system was correctly reported as 6.1.7600 (Windows 7), but the second time it was run, the operating system was erroneously reported as 6.0.6000 (Windows Vista).

    This was definitely strange behavior, and upon further questioning, the customer admitted that their application was a setup program.

    The fact that it was a setup program was the missing ingredient.

    What happened is that the setup program ran, correctly detected the version as Windows 7, and then started installing its pre-requisite components. The installer for one of the pre-requisites failed, causing the entire setup to fail.

    The Program Compatibility Assistant noticed that the initial attempt to install the program failed, and it guessed (based on its internal heuristics) that the problem was that the program had an incorrect operating system version check. After the first setup failed, the Program Compatibility Assistant puts up a dialog box saying, "Hey, I think I know what went wrong. This setup program has a bad operating system version check. Do you want to give it another shot?" If the client says, "Go for it", then it will run the setup program again, but with a false operating system version.

    Unfortunately, the heuristic that the Program Compatibility Assistant used was a false positive in this case, so saying "Go for it" was the wrong answer. (Not like the client had any idea. This was a case of the computer asking the user a question they cannot answer.)

    The fix is to add a manifest to the setup program specifying whether it needs to run as administrator. It doesn't matter what the manifest says as its requirements; the fact that the manifest said anything at all means that the setup program understands the new rules introduced in Windows Vista and doesn't need the Program Compatibility Assistant's help.

    (You can read the Excluding Programs from PCA section for other ways to disable the Program Compatibility Assistant for a program.)

  • The Old New Thing

    The 2014/2015 Seattle Symphony subscription season at a glance


    For many years, I've put together a little pocket guide to the Seattle Symphony subscription season for my symphony friends to help them decide which ticket package they want. For a few years now, we haven't ordered any tickets at all because we all have young children, but I still make this guide out of some sense of obligation.

    So here's the at-a-glance season guide for the 2014/2015 season anyway, again with no comments from me because nobody I know is going to use them to decide which tickets to order. Besides, you can probably preview nearly all of the pieces nowadays (minus the premieres) by searching on YouTube.

    Here is the official brochure for those who want to read the details, and you can see what The Seattle Times thinks of it.

    Week Program 21 13 7A
    7G 4A SU WG
    Wagner: Die Meistersinger Overture
    Tchaikovsky: Piano Concerto #1
    Dvořák: Symphony #7
    Dutilleux; Métaboles
    Rachmaninoff: Rhapsody on a Theme of Paganini
    Dvořák: Symphony #8
    Dvořák: Bagatelles
    John Adams: Lollapalooza
    Korngold: Violin Concerto
    Dvořák: Symphony #9, "From the New World"



    R. Strauss: Metamorphosen
    Mozart: Requiem
    Barber: Second Essay for Orchestra
    Esa-Pekka Salonen: Violin Concerto
    Tchaikovsky: Symphony #4
    Esteban Bezecry: Colors of the Southern Cross
    Mendelssohn: Violin Concerto
    Mussorgsky: Pictures at an Exhibition
    Boccherini: String Quintet in E major
    Rossini: The Barber of Seville Overture
    Respighi: Church Windows
    Beethoven: Symphony #6


    Prokofiev: Lieutenant Kijé Suite
    Mason Bates: Cello Concerto
    Tchaikovsky: Sleeping Beauty excerpts
    Bach: Violin Concerto #2
    Brahms: Academic Festival Overture
    Beethoven: Symphony #3, "Eroica"
    Rachmaninoff: Piano Concerto #3
    Ives: Symphony #4
    Berlioz: Le Corsaire Overture
    Beethoven: Violin Concerto
    Debussy: Ibéria
    Ravel: La valse
    02/12 Berlioz: Roméo et Juliette, Op. 17                  
    Sibelius: Finlandia
    Sibelius: Symphony #1
    Sibelius: Symphony #2

    Sibelius: Symphony #3
    Sibelius: Violin Concerto
    Sibelius: Symphony #4
    Sibelius: Symphony #5
    Sibelius: Symphony #6
    Sibelius: Symphony #7
    Szymanowski: Concert Overture
    Chopin: Piano Concerto #2
    Prokofiev: Symphony #5

    Schnittke: Violin Concerto #4
    Shostakovich: Symphony #7, "Leningrad"
    Sebastian Currier: World Premiere
    Grieg: Piano Concerto
    Schumann: Symphony #2
    Beethoven: Piano Concerto #4
    Beethoven: Symphony #7
    Glinka: Russlan and Ludmilla Overture
    Borodin: Symphony #2
    Prokofiev: Cinderella excerpts
    Beethoven: Egmont Overture
    Julian Anderson: Violin Concerto
    Brahms: Symphony #1

    06/18 Mahler: Symphony #3                  
    Week Program 21 13 7A
    7G 4A SU WG


    21Masterworks 21-concert series (Choice of Thursdays or Saturdays)
    13Masterworks 13-concert series (Choice of Thursdays or Saturdays)
    7AMasterworks 7-concert series A (Thursdays)
    7BMasterworks 7-concert series B (Saturdays)
    7CMasterworks 7-concert series C (Thursdays)
    7DMasterworks 7-concert series D (Saturdays)
    7EMasterworks 7-concert series E (Thursdays)
    7FMasterworks 7-concert series F (Saturdays)
    7GMasterworks 7-concert series G (Sunday afternoons)
    4AMasterworks 4-concert series A (Friday afternoons)
    SUSymphony Untuxed (Fridays, reduced program)
    WGWolfGang (Various evenings), see notes below

    For those not familiar with the Seattle Symphony ticket package line-ups: Most of the ticket packages are named Masterworks nX where n is the number is the number of concerts in the package, and the letter indicates which variation. Ticket packages have been combined if they are identical save for the day of the week. For example, 7C and 7D are the same concerts; the only difference is that 7C is for Thursday nights, while 7D is for Saturday nights.

    The WolfGang series is available only to members of the WolfGang club. It also includes one concert not listed in the chart above: The Movie Music of John Williams.

    This chart doesn't include concert series such as the Mozart Concertos or Distinguished Artists series which share no concerts with any of the Masterworks concerts.

    Notes and changes:

    • The 7[AB], 7[CD], and 7[EF] concert series do not overlap, so you can create your own 14-concert series by taking any two of them, or recreate the 21-concert series by taking all three.
    • The 13-concert series is the same as the 7[CD] and 7[EF] series combined, minus the November 13 concert.
    • The non-Masterworks series line-up has been tweaked. The Mozart series is now a concerto series, and there is a Sunday Untuxed series for families.
    • The Sunday Untuxed series squeezes out the the Behind the Score series, though there is a one-shot Behind the Score concert for Sibelius's Fifth Symphony.

    There are two festivals: Dvořák and Sibelius. Although there are no ticket packages specifically for the Dvořák or Sibelius concerts, tickets for the concerts are available individually so you can make your own festival.

    And this year, they made a promotional video.

  • The Old New Thing

    How can I make a callback function a member of my C++ class?


    Instead of a Little Program today, I'm going to answer a Little Question. This is a common beginner question, but I figure I'll just spell it out right here for posterity.

    First of all, you probably noticed that you can't do this:

    class CountWindows
      int CountThem();
      BOOL CALLBACK WndEnumProc(HWND hwnd, LPARAM lParam);
      int m_count;
    BOOL CountWindows::WndEnumProc(HWND hwnd, LPARAM lParam)
       return TRUE;
    int CountWindows::CountThem()
      m_count = 0;
      EnumWindows(WndEnumProc, 0); // compiler error here
      return m_count;

    That's because the WNDENUMPROC is declared as a so-called free function, but member functions are not free. Neither are function objects (also known as functors) so you can't use a boost::function as a window procedure either. The reason is that member functions and functors need to have a hidden this parameter, but free functions do not have a hidden this parameter.

    On the other hand, static methods are free functions. They can get away with it because they don't have a hidden this parameter either.

    Win32 has a general principle that callback functions have a special parameter where you can pass any information you like (known as context or reference data), and that same value is passed back to your callback function so it knows what's going on. In practice, most people will pass a pointer to a class or structure.

    In other words, the reference data parameter makes explicit what C++ hides (the this parameter).

    class CountWindows
      int CountThem();
      static BOOL CALLBACK StaticWndEnumProc(HWND hwnd, LPARAM lParam);
      int m_count;
    BOOL CountWindows::StaticWndEnumProc(HWND hwnd, LPARAM lParam)
       CountWindows *pThis = reinterpret_cast<CountWindows *>(lParam);
       return TRUE;
    int CountWindows::CountThem()
      m_count = 0;
      EnumWindows(StaticWndEnumProc, reinterpret_cast<LPARAM>(this));
      return m_count;

    What we did was pass our this parameter explicitly as the reference data to the Enum­Windows function, and then in the callback, cast the reference data back to this so that we can use it to access our member variables.

    If the Wnd­Enum­Proc is long, then it can get tedious typing pThis-> in front of everything, so a common follow-up technique is to make the static member function a wrapper that calls a normal member function.

    class CountWindows
      int CountThem();
      static BOOL CALLBACK StaticWndEnumProc(HWND hwnd, LPARAM lParam);
      BOOL WndEnumProc(HWND hwnd);
      int m_count;
    BOOL CountWindows::StaticWndEnumProc(HWND hwnd, LPARAM lParam)
       CountWindows *pThis = reinterpret_cast<CountWindows* >(lParam);
       return pThis->WndEnumProc(hwnd);
    BOOL CountWindows::WndEnumProc(HWND hwnd)
        return TRUE;
    int CountWindows::CountThem()
      m_count = 0;
      EnumWindows(StaticWndEnumProc, reinterpret_cast<LPARAM>(this));
      return m_count;

    Observe that by putting all the real work inside the traditional member function Count­Windows::Wnd­Enum­Proc, we avoid having to type pThis-> in front of everything.

    This principle of using reference data to pass context through a callback is very common in Windows programming. We'll see a few more examples in the future, but I'm not going to jam all the beginner articles in a row because that would bore my regular readers.

    Historical note: The term reference data was used in 16-bit Windows, but the Windows NT folks preferred to use the term context. You can tell which team introduced a particular callback function by seeing what they call that extra parameter.

  • The Old New Thing

    Jan-Keno Janssen decides to rent a bicycle to get around Las Vegas; this is what happens


    Jan-Keno Janssen writes about technology for German computer magazine c't. He covered the Consumer Electronics Show in Las Vegas earlier this month. And that means horrific traffic that turns a trip from the hotel to the convention center into an hour-long ordeal. But he had an idea: Everywhere he needs to go is within a five-kilometer radius. The terrain is flat. The weather is cold but nothing a coat can't handle. Solution: Rent a bicycle and use that to get around.

    This was not as simple as it sounds.

    Uneasy Rider: Radfahren in Las Vegas chronicles his absurd experience trying to execute on his simple plan, through the lack of comprehension, the blank stares, the offer of a mobility scooter, the hotel employees privately talking about the crazy European, the impossibility of finding a place to lock his bicycle, and a video of his triumphant bike ride. (Article is in German, which you should read if you can because the attitude may not survive translation. And because stories of the absurd naturally belong in German.)

    Maybe he should've asked this guy for tips.

    A friend of mine who is more clued in to the bicycling scene says that at Interbike, a bicycle conference held in Las Vegas, a common solution is to buy a cheap bicycle at a local big-box department store and abandon it at the end of the convention. Maybe he could try that next year. (If abandoning the bicycle offends his sensibilities, he could always donate it.)

    Bonus content: Here's my translation of the article into English.

    Uneasy Rider: Bicycling in Las Vegas

    Media coverage on bicycle? In Las Vegas? To Americans, this is about as absurd as using a jet-pack to get a loaf of bread. A report on my experiences at CES 2014.

    The traffic situation in Las Vegas at CES is a catastrophe. Whether by taxi, monorail, or bus, there are annoying queues of people everywhere. For six years in a row, I have tortured myself through the crowd of chaos to report on technology for c't and heise online, and every year, I think, "There must be another way."

    On the opening day of the conference, it can take an hour to get from the hotel to your next appointment. The distances to be bridged are fairly short: The convention takes place within a radius of about five kilometers, including hotels. A European doesn't have to think very long to come up with a way out of the interminable waiting: This year I will try to get to every appointment by bicycle, not handing over a cent for taxi or public transportation.

    This notion strikes an American as if you had said you wanted to take a jet-pack to get a loaf of bread. The reactions of the locals left no doubt about that. Before the conference, I sent a few messages to businesses which rent bicycles. That's right. Bike rental companies. They actually exist. However, they aren't what I had imagined: From the email replies I got back, I gathered that bicycles here are used exclusively for sport and exercise, not as a means of transportation.

    The customers of the bike rental companies drive up in their cars, toss in the rental bike, and drive off somewhere into the desert. As a result, I also was offered a high-tech mountain bike with full suspension for $100 a day. My relatively simple request (renting a simple bicycle with a light and lock for a week) seemed so absurd that the proprietor simply ignored it.

    Wheelchair instead of a bicycle

    Upon arriving in Vegas, I inquired at the hotel. The concierge of the MGM Grand can help with any request, or so it says in the brochure of the third-largest hotel in the world. But when I asked about renting a bicycle, I got the same story the bicycle rental gave me via email: You can rent expensive mountain bikes for desert riding.

    Me: I don't want to exercise. Just use the bicycle as a means of transportation. It is very practical, because at CES I have meetings all day in different hotels.

    Concierge: <blank stare>

    Me: It's so easy to bicycle here. Everything is flat!

    Concierge: You can rent a mobility scooter here in the hotel.

    Me: Isn't that intended for handicapped people?

    Concierge: Well yeah, but anyone can use them.

    Me: I would rather rent a bicycle.

    Concierge: Please wait a moment.

    The concierge called somebody on the phone. Unfortunately, I could not hear what he said, he had taken a few steps back and turned away from me. I could barely make out a few fragments of conversation. "European." "Crazy." As he turned back to me, he informed me that there is a bicycle shop named McGhie's "nearby". I could try my luck there. I knew about McGhies already. That was one of the businesses that didn't answer my emailed questions.

    Me: Okay, thanks. Assuming I can rent a bicycle, may I take it with me to my room? Or is there somewhere a place to park a bicycle? I haven't seen one.

    Concierge: Please wait a moment.

    And again he picked up the phone, turned away from me, and called somebody. The phone call lasted a very long time, but ended apparently with a positive result: Yes, I may take the bicycle to my room. But I was strongly advised against riding a bicycle in Las Vegas. It was far too dangerous. Aha.

    Okay, so off to McGhie. Apparently it is the closest bicycle shop to Las Vegas Boulevard (commonly called "The Strip", the location of pretty much all the city's hotels). Around 15 kilometers and taxi fare of over $50 later, I stood in a large store for mountain bikes and snowboards. And here too, people understood me only after prolonged attempts at explanation. The salesman asked if I really wanted to do it. He said it was very dangerous, lots of traffic, and furthermore the drivers are not accustomed to seeing bicyclists. I replied that I didn't have to go on the eight-lane Strip, but rather could take the smaller side streets.

    "This is America"

    Shaking his head, the salesman gave me a bicycle helmet, included in the price of $150 per week. 150 dollars? Yes, because McGhie doesn't rent simple street bicycles. The simplest model was a crossover bike from Trek. Does it at least come with a clip-on light and a lock? No. Our customers don't ask for lights, and we don't rent locks for insurance reasons. "This is America," the salesman insisted. And speaking of insurance: There wasn't any. If the bicycle got stolen, I would have to replace it. For $1250. I swallowed hard and bought myself a $50 lock and a few simple LED lights.

    Now the salesman wanted to know whether I had my own car or whether I would like the bicycle delivered to the hotel. When I answered that I just wanted to ride the bike to the hotel right now, I earned another shake of the head. "Good luck."

    Somewhat intimidated and slowed down by the thought that I'm about to do something forbidden, I head out. And then it happened: Nothing. It was pleasantly warm, little traffic, I could travel on the sidewalk most of the time. When the kitchily and bombastically-lit Strip emerged at dusk, I had for the first time the sense that my bicycle riding idea was maybe not so preposterous.

    This feeling held up until the next day. The ride from the MGM Hotel to the meeting at Mandalay Bay was admittedly trouble-free, but where the hell was I supposed to put this expensive bike? There were (obviously) no bike racks, and on top of that there was nothing I could chain the thing to. So I asked at the hotel lobby. There I was met with the usual skepticism, but they offered to store it in the baggage room. Good idea, great. So for the next few days, the baggage-room-as-bicycle-rack strategy worked great. Only at the LVH Hotel at the convention center, the very place I had to go most often, did the people in the baggage room put their foot down, even though the hotel was one of the official CES venues. I was not a hotel guest at all, and on top of that was some sort of problem with the insurance again. When I asked where I could store my bicycle, the answer was merely a shrug. Ultimately, with my CES press pass, tips, and tenacity, I finally succeeded.

    Fear and Cycling in Las Vegas

    After five days of putting the cycling plan into practice, the result is clear: The whole fear-mongering was unjustified. You can ride your bicycle in Las Vegas quite decently. There are the fewest problems on the side streets, the sidewalks are practically always free. (In Las Vegas, one travels by foot only in explicitly designated areas. Under no circumstances is this rule broken.) Now, on the large multi-lane roads like the Strip, riding requires considerable concentration because the drivers employ an, er, original driving style. But that also makes it rather enjoyable to whiz past the rows of cars by the Bellagio fountains, the Mirage volcano, and the neon signs.

    Also, you can see places where tourists and convention attendees rarely go, and for good reason: The mini-supermarkets beyond the Strip often sell groceries and drinks a full one third cheaper than at the kiosks of the hotel monopolists. In the stores away from the tourist stomping grounds, you meet the alcoholic and/or mentally ill people who were spit out by the glossy gaming industry. If you talk with the people here, you learn sad stories about the downsides of the American dream and a de facto non-existent social system.

    At one point, I also came to understand why the locals warned me about being stopped frequently by the police. Anyone not riding in a car is a priori a suspicious person, just like for example in Los Angeles. "Only the homeless ride bicycles in the city," I heard more than once. I cleared the police screening probably only because I was wearing a suit most of the time. Sad.

    The efficiency-loving Americans should at least see that you can save huge amounts of time with a bicycle. From the hotel to the convention center, for example, it took me only twenty minutes. At rush hour on the first day of the convention, it was easily an hour by taxi or monorail. That's what I told the man I met in the hotel elevator: He had seen plenty of things in Vegas, but a guy riding around the hotel hallways on a bicycle? Never. He acknowledged my story of the time savings with a shake of the head. Like I said, a jet pack probably would have confused him less.

    Photo captions

    1. Bicycling in Las Vegas: To a European, this sounds completely ordinary, but in practice, it requires a lot of discussion. But it's worth it because...
    2. ... during CES, a person on a bicycle is significantly faster than a car: In a car, you spend most of your time stuck in a traffic jam.
    3. If you go for the shuttle bus, first and foremost, you must wait...
    4. ... same goes for the taxi stands in front of the hotels.
    5. Here is the end of the taxi queue. From here to finally sitting in a taxi, it'll take up to an hour.
    6. With a bicycle, you simply ride past all the traffic chaos. However, since there are (almost) no parking facilities, you have to put the bicycle in your room. At least in the MGM Grand it's allowed.
    7. Not allowed is riding down the extremely long hallways. Purely theoretically speaking, one could save a lot of time by doing so.
    8. The elevators in the hotels are, fortunately, roomy enough. The bike came along with me without a problem. On top of that, it is a safe "conversation starter" in the small-talk-friendly USA.
    9. Although riding along the at-times eight-laned Las Vegas Boulevard falls into the category or "extreme sports", you can take a relaxing ride on the sidewalks of the quiet side streets. Also, the traffic is easy to negotiate here.
    10. Here, right at the beginning of Las Vegas Boulevard, at the famous sign, the traffic is not quite so relaxing. Two kilometers to the north, traffic gets confusing. (See videos.)

    Video caption

    First-person view of bike riding in Vegas: To get from the MGM to Treasure Island, you have to cross a number of overpasses and escalators. Logic would suggest otherwise. The video was designed by the Amsterdam multimedia artist Christopher Holloran.

  • The Old New Thing

    Non-psychic debugging: Looking for leaked objects by their vtable


    A programmer on the GHI team reported that they were hitting an assertion failure using an internal library and asked for help debugging it.

    DEF!CWidget::`scalar deleting destructor'+0xd
    ABC!operator delete()+0x6

    I didn't work on this internal library, but on the other hand I'm also not afraid to look inside and around.

    The assertion failure said, "Assertion failed: All widgets from a factory must be destroyed before you can unregister the factory."

    The factory does not keep a list of all the widgets it created. It merely keeps a count and asserts that the count is zero when the factory is unregistered."

    A good start would be to find the widgets that are still outstanding, so we can try to figure out why they weren't destroyed.

    0:000> u ABC!CWidget::CWidget
    1071158b mov     dword ptr [esi],offset ABC!CWidget::`vftable' (106da08c)

    This gives us the widget vtable, so a memory scan should find all the outstanding widgets.

    0:000> !heap -search 106da08c
        _HEAP @ 950000
          HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
            01eb12d8 000e 0000  [00]   01eb12e0    00064 - (busy)

    Okay, so a search of the heap shows that there is only one widget, and it is at 0x01eb12e0. Let's see what that widget can tell us about who it is.

    0:000> dt ABC!CWidget 01eb12e0
       +0x000 __VFN_table : 0x106da08c
       +0x004 m_uBucketId      : 2
       +0x008 m_rgClassData    : 
       +0x050 m_rgSharedData   :
       +0x05c m_fLocked        : 1
       +0x060 m_pszName        : 0x01eba4c0  "GHI_widget"

    Hey, how about that. The widget conveniently has the name GHI_widget, which seems like a pretty good sign that the GHI component leaked a widget.

    Notice that I didn't use any special knowledge of Widgets, Widget Factories, the ABC component, or the GHI component. All I did was take the error message that said, "You leaked a widget" and said, "Maybe I should go look for that widget. That may tell us something." I disassembled the widget constructor to look for a unique tag common to all widgets, and then scanned memory looking for that vtable. From the found object, I dumped its member variables looking for some sort of clue as to its identity, and by an amazing stroke of luck, the widget had a name.

    Back in my trainee days in tech support, if a customer asked a question that we couldn't answer, we escalated the problem to the next higher level and were encouraged to tag along and learn from the subject matter expert. That way, when the problem came up again, we could solve it ourselves.

    In other words, we were encouraged not to run away from information, but to run toward it.

    (It helped that we weren't graded on "number of cases closed per second.")

    One of the most important skills in a programmer is the willingness to look at code that you didn't write. When I joined Microsoft, this instinct to run toward information led me to watch as somebody else debugged a problem and learn from them. I would then go back and read the code that they debugged to see how much of it I could understand. And if I ran into a problem of my own, I dove in and read the source code to the component that was giving me trouble, even if it was not a component I remotely had any responsibility for. Maybe I could figure out what it was doing, maybe I couldn't, but at least I gave it a try. And when I went to another developer with my theory, I was told either that my understanding was correct, or that I had gotten it wrong and was told the correct answer. Either way, I learned a little bit more that day.

    Exercise: If the widget had not had a name, what would be a reasonable next step in the investigation?

  • The Old New Thing

    The Visual Effects dialog box just tells you what you want to hear


    The Visual Effects dialog box has three options, "Let Windows choose what's best for my computer," "Adjust for best appearance," and "Adjust for crappiest appearance best performance." Some people have discovered the registry key where the Visual Effects dialog box remembers which radio button was most recently checked, but they found that when they programmatically manipulate the registry key, there is no effect on the actual visual settings.

    What's going on?

    What's going on is that the registry key is just there to tell you what you want to hear. It remembers which radio button you clicked, so that when you reopen the dialog box, the same radio button will be selected by default.

    The actual work of changing the setting happens when you click the OK or Apply button. The registry key is just for show.

    If you want to change a Visual Effects setting programmatically, you need to make the corresponding API call for that visual effect. For example, you might call System­Parameters­Info with the SPI_SET­NON­CLIENT­ANIMATION flag to programmatically enable or disable non-client animation.

    Note of course that by doing this you are using a global solution to a local problem. The user's visual effects preferences should be modified by the user, not by a program.

Page 1 of 3 (30 items) 123