July, 2007

  • The Old New Thing

    I just discovered that the Scandinavian Gift Shop in Ballard is closing

    • 8 Comments

    When in Ballard for SeafoodFest, I was saddened to discover that one of the last remaining Scandinavian businesses in Ballard, the Scandinavian Gift Shop, is closing. They were in their final stages of "everything must go!", and I picked up a small number of Glad Påsk greeting cards, some pretty napkins (including a set that would be illegal if U.S. law applied to the Swedish flag), and a dozen tiny Swedish flag stick-pins. Fortunately, Olsen's Scandinavian Foods is still there, because you never know when you're going to get a hankering for some homemade pickled herring.

    I don't get to Ballard very often during business hours, but when I do, I try to make a point of vising Olsen's just to browse around the store, amuse myself at all the Norwegian packaging (most of the stuff comes from Norway), and maybe pick up an item or two. I think the previous time I was there, one of the Endresen sisters was working the register, because she very politely translated the instructions on the back of a package of asparagus soup for me. I would have waved her off and saved her the trouble, except I didn't know what vann was. (I now know that it is vatten = water.)

  • The Old New Thing

    What is the lpdwHandle parameter in GetFileVersionInfoSize used for?

    • 17 Comments

    The GetFileVersionInfoSize function returns two pieces of information. The return value is the amount of memory needed to record the version information of a file, and the DWORD pointed to by the lpdwHandle parameter is set to zero. What's the deal with this strange lpdwHandle parameter?

    That parameter used to do something.

    The documentation for GetFileVersionInfo used to read

    dwHandle: The value returned by a preceding call to GetFileVersionInfoSize in the lpdwHandle parameter.

    The purpose of that parameter is to allow GetFileVersionInfoSize to pass information to GetFileVersionInfo about what it found.

    In 16-bit Windows and Windows 95, 98, and Me, the GetFileVersionInfoSize function opened the target file and went searching for the version information. Once it was located, the size of the version was the return value and the file offset of the version information was stored in lpdwHandle. The GetFileVersionInfo function was very simple: It merely read dwLen bytes from the file starting at file offset dwHandle.

    In the Windows NT series, this mechanism was abandoned. The handle is not used any more. Why not? I don't know, but I have some guesses.

    First, Windows NT supports files larger than 2GB, so a 32-bit value isn't big enough to hold a file offset value.

    Second, multitasking introduces a race condition in the GetFileVersionInfoSize/GetFileVersionInfo pattern. Whereas in 16-bit Windows, nobody could modify the file between the two calls due to co-operative multi-tasking, in 32-bit Windows, it's possible that somebody could sneak in and modify the file between the two calls, resulting in the call to GetFileVersionInfo returning garbage. (Yes, Windows 95 has this race condition.)

    Third, the amount of memory required to load the version resource is not the same as the actual size of the version resource. It's not enough just to seek to the specified location and read dwLen bytes from it. For example, a program might load the version resources from a 32-bit module, and we've seen earlier that 32-bit version resources are Unicode. But that program might then call VerQueryValueA to retrieve the version string in the ANSI code page. The GetFileVersionInfo function needs to return a buffer that can hold not only the actual version resource but also enough memory to hold copies of all the strings in the version resource converted to the ANSI character set so that the VerQueryValueA function could return them.

    Whatever the reason, the Windows NT series of operating systems don't use the handle value. When you call GetFileVersionInfoSize, the function looks for the version resource and returns the size of the memory block needed to record it. (Which, as we saw above, includes translation space for the ANSI strings.) When you call GetFileVersionInfo, the function starts over from scratch and looks for the version resource and copies it into the buffer.

    The dwHandle parameter is now just a vestigial organ.

    Prediction

    People will take this as the opportunity to complain about the GetFileVersionInfo family of functions. (Because all I have to do is mention a function name, and that makes it open season on all problems related to that function, as if every function I mention is one that I have total responsibility and authority over.)

  • The Old New Thing

    Stuart Stevens takes performance-enhancing drugs in order to see what they do

    • 9 Comments

    It's an old story, but once again timely thanks to the drug scandal that rocked this year's Tour de France. Not to be confused with the drug scandal that rocked last year's Tour de France. (But that's okay, because it's all cleaned up now. Tipster.)

    Amateur cyclist Stuart Stevens takes performance-enhancing drugs for six months in order to see what they do. Read the first-hand account of the effects of human growth hormone, EPO, and steroids.

  • The Old New Thing

    There's a whole Internet out there, folks, you might want to check it out

    • 22 Comments

    If you're going to add a topic to the Suggestion Box,¹ at least do the courtesy of researching the question before asking it. It takes me an hour to answer each question; it's only fair that you spend ten minutes making it a good question.

    For example, one entry in the Suggestion Box asked for the story behind the MANUALLY_INITIATED_CRASH hotkey. But even the most cursory search on the Internet for the phrase manually initiated crash reveals as the #1 hit an explanation of the circumstances under which you would want to enable this feature in the first place.

    As another example, one commenter asked where I got the grayscale conversion formula from, but a few minutes of tinkering with a search engine will reveal all sorts of articles on grayscale conversion. (Heck, that's how I found the formula in the first place!)

    Generally speaking, I just ignore questions that are poorly-researched, but I felt the need to call out the issue in the first place so you can understand why I ignored your question.

    Footnote

    ¹Yes, the Suggestion Box is closed for now, since it's got enough suggestions to last me for years. If your suggestion is that totally awesome, then you will surely remember it when the Suggestion Box reopens in early 2010.

  • The Old New Thing

    Seattle to Portland (STP) 2007 trip report, part 4 of 4: St. Helens to Portland and beyond

    • 15 Comments

    Note: You probably want to start with Part 1.

    1:33pm: S and I arrive at the St. Helens High School food stop (mile 175) just as J, M, and A are on their way out. S is pretty wiped out by this point and heads over to the nearby McDonalds for a cup of Coke and an order of French fries. "What I need is fat," she explains. (And she was hardly the only person to stop at McDonalds for "alternative fuels".) Here's how the math works out:

    high fructose corn syrup + caffeine + starch + fat = ready for the last 30 miles

    Z arrives at the St. Helens stop and we tell him that we're down at the McDonald's.

    S confesses that she had been doing some mental calculus on the way to this stop. "Well, A's wife is coming down to meet him. A is going to finish around 4pm, so his wife should be somewhere near here about now. I could give her a call and ask her to pick me up. She can take me to the finish line and drop me off, and I can pick up my stuff and take the bus back to Seattle as originally planned."

    In other words, S was calculating all the possible ways of quitting. And she wasn't the only one. While we sat there enjoying the sunshine, sipping on Coke and nibbling on French fries, I saw a pick-up truck with two STP bicycles in the back, and saw a mini-van pull up and two STP bicycles get loaded onto the bike carrier. It's just 30 more miles, people!

    I manage to snap a picture of the bicycling family as they go past the McDonalds. I didn't notice it at the time, but a closer study of the photos afterwards reveals that the women on the triple are wearing headsets with boom microphones, with cables running to some sort of contraption attached to the crossbar. I'm guessing that they set up a little intercom system so they could chat as a group as they rode. The father and son on the tandem didn't need this set-up since the two people on a tandem are pretty close together, but on a triple, the person in front and the person in back are quite a distance apart. I thought this was a clever solution.

    Now recharged, the three of us hit the road. S tells me later that she felt twice as good coming out of St. Helens, thanks to the energy boost from the Coke and fries (and the loss of the headwind that dogged us for much of Highway 30), for a net gain of 5mph. Z stays with us for a while, but eventually he pulls ahead to ride at his own pace. I stay with S as we ride through Scappoose.

    Now, riding through nature is scenic and stuff, but I agree with S that riding through small towns is more interesting because of all the stores and shops you go past. Like the Hi-School Pharmacies in St. Helens. (Who wants to buy their prescription drugs from a high school?) Or Grumpy's Towing in Scappoose. Or the Peace Candle of the World.

    We approach the Scappoose mini-stop (mile 189) with no intention of stopping, but we pull over because we happen to spot Z emerging from the crowd with ice cream. He told us afterwards that he timed his arrival at the Scappoose mini-stop perfectly: Just as he arrived, so too did the truck with the ice cream bars. Z joins us, but he once again pulls ahead and we assume we'll just see him in Portland.

    3:41pm: We reach the "Portland 10 miles" sign. S is doing much better now. The infusion of all those wonderful ingredients did its magic. We notice a lot fewer children. No kids on teetery bicycles or dads pulling a child behind on a trailer. The only exception was a group of three young teenagers, two on a combination tandem (recumbent in front, upright in back) and one on her own bicycle. They were doing a pretty good job of moving along.

    At about the same time (3:50pm), the lead group of J, M, and A arrives at the finish line. They arrive as part of the main wave of finishers. It's so crowded they can't even ride across the finish line; they somewhat anticlimactically walk their bicycles under the banner. (The unicyclist finished ten minutes ahead of them. A's wife took a picture. And two minutes after them, a guy with a puppy trailer also finished.)

    As we get closer to Portland, we see more and more people stopped by the side of the road. I'm hoping that they're just waiting for the rest of their group to catch up, not that they're stopping to take a break so close to the finish. There's a rather large group gathering in the parking lot of an adult video store. I'm trying to imagine the conversation that led to that choice:

    "Where should we meet up when we get to Portland?"

    Let's meet at the adult video store at 55th.

    "What?"

    It's right by the park. On the right hand side. Can't miss it.

    "Um, Bob, how do you know about this video store?"

    Oh, um...

    4:23pm: The last steep hill of the day is a short one, at NW Wardway St (mile 201). We pass by a gentleman at the bottom of the hill talking on his phone. He's asking his personal support vehicle to come by and take him up this tiny little hill. Dude, it's only 400 feet. Just push your bicycle if you have to.

    Halfway up this hill we pass a cyclist by the side of the road fixing a flat. Bad place to have a flat. I mutter some words of encouragement as I go past.

    As we crest the hill, we see Z waiting for us by the side of the road. The three of us ride together through the streets of Portland toward the finish, but it gets more frustrating, because you think you're done, but the road just keeps going and going, turning onto this road, turning onto that road, crossing the railroad tracks, going a tenth of a mile, crossing the same railroad tracks again... It's like, "Hey, I don't need a freaking tour of Portland. Just take me to the finish line already!"

    4:50pm: At last our tour of Portland is complete and we cross the finish line to receive our finisher's badge. J is there to cheer us in, and A takes a nice picture of our arrival.

    Statistics according to my bicycle computer:

    Time in motion: 16:38:38
    Distance: 216.09 miles
    Average speed (when moving): 13.0mph
    Maximum speed: 31.8mph

    Other statistics (estimated):

    Travel time: 23 hours
    Rest time: 6½ hours (28% of travel time)
    Google Map Route

    Epilogue

    But wait, it's not over yet. First, we drop off our bicycles at the bike trucks. The trucks don't go as fast as the bus, so you need to load the bikes early. It's much better that your bike waits for you in Seattle than for you to wait for your bike.

    Next, we find our bags in the baggage corral and grab a change of clothes and a towel for the free showers. We head out to the showers and find that the women have a distinct advantage: The line for the women's shower is just ten minutes; the line for the men's shower is forty. (I'm told that, contrary to stereotype, the men are taking longer showers than the women.)

    Since the wait for a shower is so long, I decide to use a portable toilet as a changing room. Upon emerging, I use a water bottle and a face towel to wipe myself down, bringing me from icky to slightly less icky. That'll do for now. Z meanwhile gives up on waiting in line for a shower and goes the bathroom in the Doubletree hotel to change and clean up.

    As we were riding along Highway 30, S said that the first thing she's going to have at the finish line is an ice cream shake. I responded that I'm looking forward to pizza. There was no ice cream shake at the finish line, but there was a pizza stand, so at least I got my pizza. S said that her new plan is to call her husband as we neared Seattle and tell him to go get a Blizzard and put it in the freezer so it'll be ready for her when she gets home.

    I stop by the bicycle equipment stand and buy myself a replacement mirror. It's the same model that A has, one with which he is quite satisfied.

    6:20pm: While waiting in line to board the 6:30 bus back to Seattle, we notice one of the bicycle trucks appears to have run into mechanical difficulties. There's a person lying under the rear axle doing... something. We don't remember seeing it when we dropped off our bicycles, so there's a possibility that our bicycles are on the broken truck. We cross our fingers and hope for the best.

    On the ride back to Seattle, traffic on I-5 jams up near Centralia. I know exactly why, but nobody believes me until we see them: the monuments by the side of the highway. Northbound traffic always slows down there, and it speeds up once you get past it. (I have a modest proposal for fixing this, which I may write up one of these days.)

    A little further up the road is the billboard. I always keep an eye out for the billboard (which often has different messages for northbound and southbound traffic) whenever I travel along I-5.

    During the trip back, we tally our damage.

    RiderMishap
    J(none)
    Mspill + flat tire
    A(none)
    Sslipped chain
    Zslipped chain + flat tire × 3
    me(none)

    Ah, but we counted our chickens too soon. Upon arrival in Seattle, we find that only J and M's bicycles made it back. The rest of us must've been on the unlucky truck. (Not counting A, who is driving back to Seattle with his wife and son.) Need to update the chart.

    RiderMishap
    J(none)
    Mspill + flat tire
    A(none)
    Sslipped chain + bike not delivered
    Zslipped chain + flat tire × 3 + bike not delivered
    mebike not delivered

    On Monday, I drive to the University to pick up our bicycles. Fortunately, they all made it.

    The volunteer at the bike corral has more information on the truck problem. The problem wasn't just that one truck had a brake problem. That broken truck was blocking two other trucks! As a result, three trucks were stuck in Portland until well past midnight. The volunteers unloaded bicycles at 4am, poor guys.

    One guy is angry at the volunteer because his bicycle hasn't yet arrived. I guess the Monday truck is late or something, who knows. The volunteer is very good at remaining calm while the guy yells at him. From what I could tell, the guy doesn't actually have any specific demands, he just wants to yell at somebody. If I were the volunteer (and wanted to be mean), I would have said, "Okay, sir. Since your bicycle isn't here right now, I guess we'll have to declare it lost. According to the terms of service, our liability is limited to sixty cents per pound. Your bicycle weighs, what, 30 pounds tops? Thirty pounds times sixty cents per pound is eighteen bucks. Here's $20. Keep the change."

    Maybe that's why I'm not a bike volunteer.

    (Okay, that's not actually what I'm thinking, but it's funnier. What I actually think is, "Yo, dude, don't push your luck or the guy is going to give you sixty cents and call it even!")

    The Thursday after the ride, J finds what looks like a staple embedded in his rear tire. It passes through the the middle of the tread and exits out the sidewall, miraculously missing the tube. He was this close to joining the "mishap club".

    Final Thoughts

    Would I do STP again? Perhaps, provided I'm riding with people I know well. I'd try to make a point not to dawdle at the rest stops. (S says that she should have trained to a higher average speed, like say 16mph; that way, cruising at 14mph would have been much less tiring.) But it was definitely worth doing once.

  • The Old New Thing

    Don't just grab the foreground window and host UI on it

    • 58 Comments

    I was asked to look at an application compatibility bug in a program from a major vendor. But that's actually irrelevant; what I'm writing about today has nothing to do with application compatibility. That's just what drew my attention to the program in the first place.

    At some point during the install, the setup program encountered an error and wanted to display an error message. When it called DialogBox to display the error message, it didn't pass the setup program's main window as the hwndParent. Instead it passed GetForegroundWindow(). They chose the wrong owner for modal UI. (I've also seen people try GetTopWindow(0).)

    It so happened that the foreground window was Task Manager, since I had switched to Task Manager to look at various statistics of their installer as it ran.

    I hope you can see where this is going.

    They passed Task Manager as their modal owner, and since modal dialog boxes disable the owner, they ended up disabling Task Manager. (Meanwhile, their main setup program remained enabled, so I could have clicked on the Cancel button if I wanted to, which would have led to the "stack without support" problem.)

    Now I can't terminate their broken setup program from Task Manager since they inadvertently disabled Task Manager.

    But why did the programmers choose to use the foreground window anyway?

    One possibility is the programmer's version of the politician's fallacy.

    • We must pass a window.
    • The foreground window is a window.
    • Therefore, we must pass it.

    Another possibility is that they did this on purpose in order to ensure that their error message steals focus. Because their program is the most important program in the history of mankind.

    Unfortunately, I see this a lot. People who think their program is so important that they will abuse the rest of the system in order to get what they want instead of just waiting their turn. Of course, these people also fail to realize that setting a window as the owner for UI creates its own problems. As already noted, you disabled a random program. What's more, you've now attached the two input queues and tied your fates together. If the program that owns the foreground window stops responding to messages, then your program will also stop responding to messages.

    But primarily it's just rudeness. You took somebody else's window and started acting as if you owned the place. It's like looking up somebody's address in the phone book and using it as your own. That's not your house, and that's not your window.

  • The Old New Thing

    How do the names in the file security dialog map to access control masks?

    • 9 Comments

    When you call up the file security dialog, you'll see options like "Full Control" and "Read and Execute". That's really nice as friendly names go, but when you're digging into the security descriptor, you may need to know what those permissions really map to when it comes down to bits.

    First, the summary attributes:

    Friendly name Access mask Inheritance
    Full control FILE_ALL_ACCESS CONTAINER_INHERIT_ACE + OBJECT_INHERIT_ACE
    Modify FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE CONTAINER_INHERIT_ACE + OBJECT_INHERIT_ACE
    Read and execute FILE_GENERIC_READ | FILE_GENERIC_EXECUTE CONTAINER_INHERIT_ACE + OBJECT_INHERIT_ACE
    List folder contents FILE_GENERIC_READ | FILE_GENERIC_EXECUTE CONTAINER_INHERIT_ACE
    Read FILE_GENERIC_READ CONTAINER_INHERIT_ACE + OBJECT_INHERIT_ACE
    Write FILE_GENERIC_WRITE & ~READ_CONTROL CONTAINER_INHERIT_ACE + OBJECT_INHERIT_ACE

    If you go to the Advanced view, then you get much more precise control:

    Friendly name Access mask
    Traverse Folder / Execute File FILE_TRAVERSE == FILE_EXECUTE
    List Folder / Read Data FILE_LIST_DIRECTORY == FILE_READ_DATA
    Read Attributes FILE_READ_ATTRIBUTES
    Read Extended Attriibutes FILE_READ_EA
    Create Files / Write Data FILE_ADD_FILE == FILE_WRITE_DATA
    Create Folders / Append Data FILE_ADD_SUBDIRECTORY == FILE_APPEND_DATA
    Write Attributes FILE_WRITE_ATTRIBUTES
    Write Extended Attributes FILE_WRITE_EA
    Delete Subfolders and Files FILE_DELETE_CHILD
    Delete FILE_DELETE
    Read Permissions READ_CONTROL
    Change Permissions WRITE_DAC
    Take Ownership WRITE_OWNER

    (In the Advanced view, you control inheritance from the "Apply to" drop-down combo box.)

    Note that the "Delete Subfolders and Files" and "Delete" attributes together determine whether you can delete a file or subdirectory: You can delete an item either if you have DELETE permission on the item or if you have DELETE_CHILD permission on its parent. This "combo" allows you to set up a directory where everybody can create files and can delete files that they have created, while still retaining the ability as the directory's owner to delete any file in it. You do this by granting yourself DELETE_CHILD permission on the directory and granting DELETE to CREATOR_OWNER as an inheritable attribute. Since you have DELETE_CHILD permission, you can delete anything in the directory. And since the creator/owner has DELETE permission, people can delete the files that they themselves created.

    [Update 2pm: INHERIT_ONLY_ACE should be OBJECT_INHERIT_ACE.]

  • The Old New Thing

    Seattle to Portland (STP) 2007 trip report, part 3 of 4: Toledo to St. Helens

    • 14 Comments

    Note: You probably want to start with Part 1.

    Sidebar: There are a lot of groups that wore matching jerseys to build team spirit. Here are a few riders that caught my eye that I haven't already mentioned:

    Our detour to Toledo bypassed the towns of Napavine and Winlock, which meant that we missed out Napavine night life, the banana bread lady, and The World's Largest Egg. I found a funny picture of another rider trying to eat the world's largest egg, and check out that bizarro bicycle towing contraption they cobbled together later in the ride!

    Sunday (Day Two)

    6am: I did not have a very good night's sleep. My throat was still horribly sore, but I dared not cough for fear of waking up everybody else. Nobody figured out how to turn off the lights in the library, so the light streamed into our classroom all night. I feel bad for the people who are sleeping in the library!

    We got up and had breakfast, brush our teeth, change into our clothes for the day, pack up, all that stuff. Breakfast consists of pancakes, scrambled eggs, ham, and milk. They run out of cups, though.

    A and I are ready a bit earlier, so we go on a self-guided tour of Toledo High School. Okay, first thing is that these rural high schools are small. Graduating class of 66 students. When we start our wanderings, I wonder where all the other classrooms are, and then I realize: There are no other classrooms.

    Other observations:

    • Lots of motivational posters. We didn't have those when I went to high school.
    • This is an iMac shop. No PCs anywhere. But they're not exclusively Apple; they have an HP laser printer.
    • This school offers Japanese as a foreign language.
    • Our classroom is a math classroom, and from the ceiling hangs a giant slide rule. J quips, "They probably use it in industrial history class." A studies it with some amusement, and I'm surprised that he never learned how to use one. A is conversely surprised that I do know. I explain, "I asked my dad, 'Hey, what's this thing?' and he said, 'It's a slide rule' and gave me one of his older slide rules and taught me how to use it." A replies, "Ah, my experience was very similar yet different in a significant way: I asked my dad, 'Hey, what's this thing?' and he said, 'It's a slide rule.'"
    • They have chalkboards! Out here in the city, everybody switched over to whiteboards years ago. Somehow, whiteboards don't feel right. Teaching is done with chalk.

    We're all ready to go except for Z, who is not having a good morning. Eventually, he joins us, only to discover that his rear tire is once again flat. (We slap ourselves on the forehead for not checking that while we were waiting.) Fixing this flat is a team affair. M extracts the tube from the tire, I search for the puncture and proceed to patch it. J and A study the location of the puncture and track it back to a spoke in the wheel that sticks out too far beyond the rim. Z's wheel doesn't have rim tape, so a rogue spoke can puncture the tube. We might have gotten away with it at lower pressure; once again, our quest for higher tire pressure comes back to bite us. S produces a dollar bill to use as temporary rim tape.

    Okay, tube repaired, bicycle back in service, off we go.

    7:30am: As we depart Toledo High School, I take a picture of their athletic field. I don't see it at the time, but in the picture, there is a rainbow. Rainbows are pretty, but on a bike ride, they mean rain.

    Z is not quite at full power yet (after the ride, he explained that his knee was bothering him, though it loosened up later in the day), so I hang back with him while the others proceed at a peppier pace. We cross I-5 on Toledo-Vader Road, giving us a great view of the famous Vader/Ryderwood exit sign. Well, famous to me at least. I've traveled up and down I-5 many times, and somehow that sign sticks in my brain. Other people probably remember that exit as the place that has the giant ice cream cone.

    Riding along Highway 506 early in the morning is quite peaceful; there's nobody else on the road. That changes once Z and I reach Highway 411, because that's where we rejoin the official STP route and see an endless stream of bicyclists pouring down the road. We slip into the crowd, and off we go.

    I broke my bike mirror this morning, so I can't use my usual trick of riding in front of Z and checking in the mirror that I'm not pulling away. Instead, I ride behind Z for a while, then pass him and ride in front for a while, checking that I'm not pulling away, and then drop behind him for a while, and so on.

    This initial leg is a longer one than usual since we had to ride out of Toledo to rejoin the route (7½ miles), and the riders on the official route had just come out of a mini-stop, so we miss out on that, plus this section of the route is rather hilly. Note: Even though we took a detour that added about four miles to our distance, I will continue to use mileage markers as measured along the official route.

    It's around this point that Morgan Scherer, who is riding not just STP, but STPTS (Seattle to Portland to Seattle), asks another cyclist "Do you feel a headwind?" The other cyclist responds, "I don't feel anything. This is day two!"

    9am: I'm ahead of Z, maybe a third of a mile from the Castle Rock mini-stop (mile 138) when my phone rings. I pull over to answer it, and it's J checking up on us. I let him know that we'll be there real soon, but in the process of taking out my phone, I accidentally pulled my map out of my back pocket, and it fell on the road, right on the route. I have to play a little game of Frogger to wait for a break in the riders so I can scoot out, pick up the map, and scoot back to the safety of the side of the road. During all this excitement, Z passes me, and I am the last one in our group to roll into the Castle Rock mini-stop.

    The people in the lead group are about to leave when I arrive, and I'm pretty keen on leaving too, but first I have to find Z. He's over at the food tables stocking up on goodies. He offers me some candy. I look at him kind of puzzled; it's nine in the morning. Who eats candy at nine in the morning?

    I fail to notice the Four Corners General Store just a half mile down the road from the high school, but fortunately Matt Picio did: Guns, Ammo, Optics. But that's not the strangest sign combination I've seen in my life. That belongs to Rooney's Liquor Store in Los Banos, California, which has the sign "Video, Groceries, Sporting Goods, Ammo, Snacks." Ya gotta love a liquor store that also sells ammo.

    During this leg, I decide to change my strategy. Instead of sticking close all the time, I ride for a while, pulling away gradually, and then stop at the side of the road to wait for Z to catch up to me. I let him go for a while, and then I hop on and catch up to him, pass him, and then pull over some time later to wait. Repeat.

    When you use the "hare" strategy, you find yourself passing the same group of people over and over. One such group is Wheels of Change who were riding to raise money for Asha for Education. I happened to stumble across not one ride blog but two and thought it was a charming coincidence that these were the people I saw over and over again.

    At one point, I think I am ahead of Z when I am actually behind him. I pull over and wait several minutes, and Z doesn't appear. I ride for a while longer, and then wait some more. Still no sign of Z. At this point, I figure I must be behind him, and I ride onward, but at a more determined pace.

    My cold isn't getting any better. My throat is still sore, though not as bad as yesterday (doesn't hurt to talk), and my nose is now running like a garden hose.

    9:51am: Z calls me. He's at the Lexington stop and wants to know whether we should stop or keep going. I'm confused and think that the lunch stop is in Longview, not Lexington, so I tell him to keep going.

    9:59am: I reach the Lexington stop (mile 145) and realize that this is the lunch stop. I call Z to tell him to come back, but he says that he'll just pull over and eat the lunch that he brought with him. I try to convince him to come back, but he says he's fine and will just wait for us.

    The line for lunch is quite long. S comes over to keep me company waiting in line, and she grabs a lunch for Z when we reach the front. The rest of the group have been at the Lexington stop for quite some time and most of them are ready to head out. We give Z's lunch to J, and he, along with M and A, head out. S relaxes while I finish my teriyaki chicken wrap and stuff the other food in my pockets. I'm fine with eating en route, and seeing as I'm the trailing end of our group, it would behoove me not to waste time.

    11:17am: It's not long before S and I reach the Lewis and Clark Bridge (mile 153), getting there just before the assembled group of riders [source blog] is escorted over the bridge. Studying photo timestamps, I calculate that the lead group picks up Z and reaches the bridge at 10:47am just as the previous group of riders is being escorted over. They have to wait until 11:01am before they get their chance to go over the bridge. S and I luck out; we happen to arrive just before another group is to be taken over the bridge. We got the best-case scenario; the lead group got the worst-case. Without even trying, we made up nearly fifteen minutes on them! (Chana Joffe-Walt calls the mass of riders a "bobbing monster of helmets". That's why she's a writer and I'm a computer programmer.)

    As S and I descend into Oregon, we see Z waiting for us at the bottom of the bridge. We stop and chat, and I take pictures of riders descending the exit and merging onto Route 30. I don't realize it at the time, but my picture captures a group of riders I won't even learn about until later in the ride.

    11:28am: Z, S and I saddle up for the final 50 miles. Once we cross over into Oregon, I start sneezing. This is not because of my cold; I'm just allergic to Oregon. I'm used to it.

    Once we leave the town of Rainier, we find ourselves on a long, imperceptible climb. Z zips ahead, while I stick with S, who appears to be losing energy and is struggling to keep going. On the left, S spots an "observatory"; it's actually the reactor core from the former Trojan Nuclear Power Plant. The sight was more impressive before they imploded the huge cooling towers. A fire engine goes past us in the opposite direction with its sirens on. We do not stop at the Goble mini-stop (mile 163) on the principle that we should just keep moving. That same fire truck goes past us in the same direction we're going, with its sirens off. We figured it was a false alarm.

    Stopped by the side of the road is a family of five on two bicycles. The father and son are on a tandem, and the mother and two daughters are on a triple. The men have matching outfits, as do the women. These are the ones I happened to take a picture of purely by chance back at the bridge. We'll see still more of them later.

    The people who live in the towns on the Oregon side are not big fans of STP, as far as I can tell. Some businesses do well, like convenience stores and anything else that sells ready-to-eat food. Though I read that one business that suffers terribly is the cigarette store, because most of its customers come from Washington to take advantage of the significantly lower tobacco tax rate in Oregon. Travelling over the bridge is an ordeal on STP day because of all the bicyclists, so people just don't bother.

    At one point, I find myself riding by myself in a gap between two larger groups. There is a semi-trailer up ahead trying to pull out of a lot, so I slow up and let the gap expand, allowing the semi-trailer to get out. I figured the poor guy would otherwise be waiting there for a long time; heck, he may have been waiting for a long time already. I don't normally get a chance to create a gap like this; when you're riding as part of a large group, you aren't really in a position to say, "Okay, everybody stop so this car can get out."

    I resolve on future large organized rides to do more to be considerate of cars trying to cross the line of bicycles.

    Although we don't know it at the time, it is around this location earlier in the day that a drunk driver ran into a STP cyclist, seriously injuring him. (That article also has an interview with the skateboarder.)

    1:33pm: We reach the final food stop, St. Helens High School (mile 175), just 30 miles from the finish line. Tune in next time for the exciting conclusion!

  • The Old New Thing

    Seattle to Portland (STP) 2007 trip report, part 2 of 4: Spanaway to Toledo

    • 7 Comments

    Note: This story makes much more sense if you read Part 1 first. It won't be any more interesting, but at least it'll be a coherent sort of boring.

    12:20pm: We arrive in Spanaway for the lunch break (54 miles) [pic]. The consensus among seasoned riders appears to be that the Saturday lunch is pretty lame this year. It consists of a rice and bean wrap, a bagel, and a handful of grapes. I don't think it's so bad, but then again, I don't know what to expect either.

    Given that we lost a good chunk of time, I suggest that S, Z and I get a head start, since we tend to go slower. (S's normal pace is a bit slower; Z is slower thanks to mechanical problems; and I'm slower because I'm making sure we don't lose S and Z.) "Grab our bikes and meet back here." S and I grab our bikes and meet back here. We can't find Z. By the time we find him, the rest of the group (the "fast half" I'll call them) had already decided it was time for them to go, too, so even our head start evaporated before we hit the street at 12:40pm.

    I think that S and Z are ahead of me, so I pick up the pace. Flying down Highway 507 is a blast. The bulk of the riders head single file down the highway, with faster riders forming a "passing lane" just to the left. It's close quarters since the highway still has traffic on it, but everybody seems to know what to do and the miles fly by. I'm glad I have my bell because it saves me from having to put any more stress on my sore throat, which has been worsening throughout the day. Discussing the ride afterwards, A noted that when he did STP in one day, it was on this stretch of road between Spanaway and Roy that he joined a paceline and was able to go really fast. Not everybody thinks that this stretch of 507 is all that great, though. (Day Two.) And here's another rider's impressions of the cars on 507. (Day Two.)

    There was one tricky part about riding along this stretch of road: The white line at the edge of the road had divots cut out of it at regular intervals. For example, it would be clear for twenty feet, and then for twenty feet there would be pits cut into the road. And then clear for twenty feet, and so on. (The purpose is to warn drivers who wander off the edge of the road.) This made changing lanes tricky since you not only had to watch for traffic in the lane you want to change into, but you also have to time your crossing to coincide with one of the clear patches rather than the pitted segment. Apparently not everyone was able to negotiate this obstacle successfully.

    Between Roy and McKenna, around 295th St, I catch up to the lead group and ask them, "Have you seen S and Z?" No they haven't; I must've left them behind. I pull over at the entrance to the gravel facility and wait. Six minutes later, they show up, and I'm back on the road.

    At the end of the day, S asked me, "So did you see the Y in Roy?"

    What, Y as in YMCA?

    "No, Y like a fork in the road. People were talking about 'Make sure you don't miss the Roy Y' but I didn't see it."

    The only Y I remember was back in Spanaway, where we turned right at the Shell gas station onto Highway 507.

    It turns out I was right without even realizing it. The "Roy Y" is the point in Spanaway where Highway 507 starts. It's called the "Roy Y" not because it's in Roy but because it leads to Roy.

    We continue past the McKenna mini-stop without stopping because it's only four more miles to the next mini-stop.

    2:10pm: Yelm (mile 72). We take a longer-than-usual break here because Z is suffering from fatigue thanks to a suboptimal bicycle. ("Where are the sofas?" he asks.) Inside the portable toilets, there's a sticker that reads "Sanitary seat covers supplied for an additional charge, upon request of supperintendent." I don't know what a supperintendent is, but I don't want him hanging around in portable toilets.

    We are by now well into the hottest part of the day, and I have to resort to pouring water on my head to cool off. They do it on TV all the time and make it look so easy. It's quite nice, but also a minor challenge to keep the water from dripping onto your glasses.

    The fast group heads out first, and some minutes later, us slowpokes get on our bikes and continue onward.

    Or at least we try to.

    We are sort of the head of a clump of riders who leave at the same time, and I'm not able to stop them after they miss a turn. I shout feebly (sore throat), but they don't hear me. I finally catch up when they find themselves at a dangerous intersection with no Dan Henry to tell them what to do. "Hey, you missed a turn back there."

    We all turn around and head back, but the damage has been done. We became the trailblazers for hundreds of cyclists who are now heading the wrong way. As we backtrack, we try to tell them, "Wrong way! Go this way!" but they either don't hear us or don't understand what we're trying to say. They probably won't figure it out until they get to the same dangerous intersection and realize, "Oh, they were trying to tell us we were going the wrong way."

    Now on the correct route, we wait for a police officer to stop traffic so we can cross Highway 507 and ride on the Yelm/Rainier/Tenino trail. The first stretch of this trail is tricky since you're in a big clump, but eventually things spread out and you can ride at your target pace. At mile 77, Z's rear tire springs a flat. S goes on ahead, figuring that she's the slowest of the group and could use the head start. (We won't see her again until Centralia.) I pull out my patch kit and repair the puncture. A few minutes later, the tube is back in business, and we resume our travels.

    The bike mirror comes in really handy here, because I can ride ahead of Z and check in the mirror that he's still with me. I've figured out that the trick for not getting too far ahead is to shift to a lower gear to slow down; that way I can keep pedaling at my natural cadence without accidentally pulling away. I'm exerting practically no effort at this point in the ride.

    We reach the crossing at milepost 84 and watch one of the two police officers directing traffic nearly cause an accident. There are two officers at the point where the trail crosses the highway, one standing on each side of the crossing, and each holding a sign that reads STOP on one side and SLOW on the other. The officers agree to stop car traffic, and one one officer turns his sign from SLOW to STOP. The other, however, forgets to turn his sign, so it still reads SLOW. The first officer shouts, "Mike! ... Mike, turn the sign!" But Mike doesn't seem to hear him. Instead, he's distracted by a motorcycle coming down the highway that fails to come to a stop. He shouts at the motorcyclist and waves the sign in the rider's face, nearly knocking the rider off the motorcycle. Mike angrily runs to his police cruiser prepared to chase down the motorcyclist for failing to stop, but his partner finally gets his attention. "Mike, I was trying to tell you: You forgot to turn your sign. It still said SLOW."

    The officers check their signs (STOP) and wave us bicyclists across. A few miles later, we reach the Tenino ministop but keep going because we're pretty far behind schedule at this point.

    3:55pm: We reach the Tenino railroad crossing just in time to watch the Amtrak Cascades 507 go past at 70 mph. I've ridden the Talgo trains many a time, but those are different stories for a different time. It was just interesting seeing the train from the outside.

    5pm: Z and I are in Centralia, drawing close to the official midpoint stop at Centralia College, but oh, we get stuck at another railroad crossing. And this isn't a fast crossing like that Amtrak train. This is a cargo train, so it goes nice and slow, and it drags a hundred boxcars behind it. The midpoint stop taunts me from only a mile away. (At least at this crossing, nobody gets impatient and tries to sneak between two train cars, like they did at the finish, or crawl under a stopped train like people allegedly did in Puyallup.)

    Centralia College is the stopping place for a large number of cyclists, so by the time Z and I roll in under the misters it's a pretty festive atmosphere. We missed the orange creamsicles on the way in, but S helps us find them. Ah, ice cream. Z has been taunted all day by promises of ice cream and met with abject disappointment at each rest stop when he discovers that they don't have any. But now, he has his ice cream.

    5:35pm: We still have another 23 miles to go before we reach our Day One destination, Toledo High School. Once out of downtown Centralia, the route follows Airport Road, with the airport on one side and farmland on the other. There I see the world's largest garden hose reel, about ten feet tall. We also catch up to and chat with a gentleman on a unicycle before resuming speed and continuing to Chehalis. (Here's the web page of a fellow who rode a unicycle in the 2005 STP.)

    In Chehalis, we diverge from the official route and instead take Jackson Highway, which runs roughly parallel to the east. This was the dreariest part of the ride. It's been a long day, we have 17 miles to go, the rural scenery becomes tiresome, there are hills, it sucks the life out of you. But we have to get there before dark, so we soldier on. (If it's any consolation, J says that the main route through Napavine and Winlock is equally dreary.)

    While riding along Jackson Highway, the lead group passes a woman in her sixties who stops her bicycle and starts to turn around. S senses that the woman may be in trouble, and she stops to ask her if she needs any help. Turns out that she's trying to get to the Bethel Church which is her Day One stopping point. (Many churches and schools make themselves available to STP participants.) The woman pulls out a map which has the route to the church highlighted on it. Unfortunately, she's nowhere near that route. We call the church's phone number, but nobody answers. When S asks her what she's doing on Jackson Highway instead of following the directions on the sheet, she responds, "Well, I got a green wristband, so I thought I should follow the green arrows painted on the road."

    Actually, the green arrows lead to Toledo High School.

    S spots a road sign and cycles to it to figure out where we are. (She also calls the lead group to let them know we've stopped to help a lost cyclist.) Meanwhile, I study the map and make small talk. Have you ridden STP before? I ask.

    "This is my first time."

    Are you riding with anybody else?

    "Nope, I'm by myself."

    Wow, that's very, um, courageous of you.

    S returns with a location fix, and we realize that the woman is not too far from her destination, even though she definitely chose a suboptimal route to get there. We ride with her to Bishop Road and give her the rest of the directions ("turn left at Rush Road and you're back on track"). I didn't want to say "Good-bye", since that sounds rather ominous, so instead I said, "See you in Portland." For the rest of the trip, I used that farewell when talking to another rider. It has a very hopeful ring to it.

    After the woman bicycles away, S wonders aloud, "Doesn't she have kids and grandkids that tell her not to go do stuff like this by herself?"

    The woman also happens to have the highest bib number I'll see during the entire ride: 8973. Everybody on STP plays the bib number game, looking for the lowest and highest. Up to this point in the ride, my lowest is 41, part of a group of three riders numbered 41, 42 and 43 who passed me on the Yelm/Rainier/Tenino trail. This record will hold until midway through Day Two, when I see my lowest bib number, 17. (ZappoMan meets Rider Zero, which is the lowest possible bib number unless they have negative numbers.)

    6:45pm: It turns out that our delay for helping the lost woman doesn't cost us any time, because when S and I reach (I am not making this up) Vista Road, we find the lead group sitting by the side of the road tending to a flat tire. M ran over a sharp object. And yes, if you look at the map, Vista Road is a dead end. Omen? Who can say.

    Okay, tube all patched up, back onto the road. Just twelve miles to go. The twelve most dreadful miles of the entire trip. M and A spring ahead, and I take the opportunity to join the lead group for a change, leaving J to make sure we don't lose S and Z. We regroup at the Highway 12 crossing and ride past the John R. Jackson House, a building that I'm sure carries great historical significance for the area, but we weren't really in the mood to care by this point. Not far past the John R. Jackson house is the Jackson Prairie Speedway, which is already roaring with the sound of auto racing when we cycle past. At least now we know what people in Chehalis do on Saturday nights.

    After several shouts of "Are we there yet?" we finally... Nope, just kidding. We're not there yet.

    My sore throat by this point has gotten so bad I can talk only with some difficulty and pain. I try to get by with nods and hand gestures.

    At last, we... nope, still not there. What looks from a distance to be a high school athletic field is just a softball facility. The local softball team won the state championship in 2001, so this area is all softball crazy.

    Okay, finally we reach Toledo High School. The kitchen is making a new batch of spaghetti, so we can't eat quite yet. We take the opportunity to stow our bicycles, move our stuff into the classroom we reserved (our group is large enough that we get an entire classroom to ourselves), take a shower, and settle in. By the time we finish eating, it's nearing ten o'clock, and we really aren't interested in doing much beyond falling asleep.

    That was a long Day One. (You thought reading about it was long and tiring, try doing it!)

  • The Old New Thing

    What is Dave's frame class?

    • 48 Comments

    Back in 2004, we lost Dave's frame class.

    Dave's frame class, or more accurately, DavesFrameClass, was the window class that drew the CPU meter on the Performance page of Task Manager. As you might have guessed, Dave was the name of the original author of Task Manager. (If the checked version of Task Manager from NT 4 encountered an internal error, it printed a message to the debugger which includes details of the error and Dave's telephone number so you can tell him about it! Mind you, that phone number is several years old, so don't call it, or you'll probably annoy the family who lives in Dave's old house.)

    One of the quirks of Dave's frame class that we had to fix in Windows XP was the digital read-out. The original version of Dave's frame class printed statistics using a display that mimicked an 8-segment LED. It may have been cute and retro, but it was also a bug, because it prevented the translation teams from changing the way the digits were displayed to suit the target language. Not all countries use Arabic numerals. (Somewhat paradoxically, many Arabic-speaking countries don't use Arabic numerals! They use Indic numerals. Then again, Roman numerals aren't used in Rome either.)

    Nitpicker's corner

    • s/aren't used/aren't used for everyday arithmetic by most people/
Page 1 of 5 (43 items) 12345