Larry Osterman's WebLog

Confessions of an Old Fogey
  • Larry Osterman's WebLog

    What’s wrong with this code, part 25

    • 12 Comments

    Wow, 25 already.

    This one’s pretty straightforward.  Once again, it’s a UI issue, since I’ve been spending most of my time doing UI lately.

    In this particular case, the code comes from the constructor for an auto-layout class that is used internally in one of our tools.  It saves away window handles for a control and the dialog which holds the control, then saves the size of the dialog and relative location of the control within that dialog.  There’s other code that handles resizing and adjusting the layout of the control when the dialog is resized. 

    CControlLayout::CControlLayout(const HWND hWndControl, const HWND hWndDlg)
        : m_hWnd(hWndControl)
        , m_hWndDlg(hWndDlg)
    {
        // Get the parent (dialog) rect, and the control rect
        ::GetClientRect(m_hWndDlg, &m_rcRefDlg);
        ::GetWindowRect(m_hWnd, &m_rcRef);
        ScreenToClientRect(hWndDlg, m_rcRef);
    }
    void ScreenToClientRect(/* [in] */ const HWND hWndClient, 
                            /* [in/out] */ RECT &rcInOut)
    {
     CPoint ptTopLeft(rcInOut.left, rcInOut.top);
     CPoint ptBottomRight(rcInOut.right, rcInOut.bottom);
     ::ScreenToClient(hWndClient, &ptTopLeft);
     ::ScreenToClient(hWndClient, &ptBottomRight);
     rcInOut.left = ptTopLeft.x;
     rcInOut.top = ptTopLeft.y;
     rcInOut.right = ptBottomRight.x;
     rcInOut.bottom = ptBottomRight.y;
    }

    m_rcRefDlg holds the reference rect for the dialog and m_rcRef holds the reference rect for the control relative to the dialog.

    This code has been in the UI for quite a while and recently one of our testers discovered a nasty bug while running a test pass.

    The question is: What’s wrong with this code.  I believe we shipped Windows Vista with this bug (I’m not 100% sure, since I don’t have a Windows Vista machine to test it), so it’s pretty subtle.

     

    Edit: OOPS - I forgot to include ScreenToClientRect.

     

  • Larry Osterman's WebLog

    If you live in the US, don’t forget to vote today

    • 11 Comments

    It’s a really big deal, regardless of your political persuasion.

     

    Already the MSFT internal mailing lists have been filled with people asking “how long are the lines at my polling place”.  The good news is that the times appear to be pretty good – people seem to be getting in and out in very little time (at least in the town in which I live).

     

    For people living in King and Pierce counties in Washington State, this will be the last time that they will vote in person.  The rest of the state already votes entirely by mail, and starting next year, both counties will also switch to vote-by-mail.

     

    The state of Oregon has already switched to a 100% vote-by-mail system, with the switchover in King and Pierce counties, Washington state will join Oregon in eliminating the ballot box.

     

    Valorie and I have been voting absentee for about 5 years now, personally I like it – by voting at home, we have the opportunity to scope out the candidates at our leisure.  That in turn means that we’re going to vote more accurately.

     

    So if you live in the US, please, PLEASE vote today.

  • Larry Osterman's WebLog

    PDC 2008, Day 4 (and finale)

    • 6 Comments

    Ok, the PDC’s finally over and I’ve had a chance to decompress a bit.  So here’s my day 4 report, only a few days late :).

    I got up at 6:15, finished packing and schlepped my stuff to the convention center for my tech check at 7:40.

     

    At the tech check, I learned that (a) I wasn’t going to be able to use presenter view in PowerPoint (which means I wouldn’t have access to my notes), and I wasn’t going to be able to see my presentation while doing my demos :(.  All of these are minor annoyances, not fatal, but still annoying.

    I then went to the speakers lounge to chill for a couple of hours while I waited for my talk – this was my first time talking to such a big convention so I was a bit nervous.

    At about 11:30 I headed out to the room (151, with a capacity of 1000 people).  I hooked up my kit to the stage and waited until noon for my presentation to begin:

    Larry's talk is up next

    I think the talk went quite well – the demos worked perfectly and I didn’t make too many mistakes (I missed one of my talking points :(). 

     

    I knew I wasn’t going to fill the room since I was speaking (a) on the last day of the convention and (b) opposite lunch and (c) a fairly geeky topic but I was still a smidge disappointed that only 53 people showed up :(.

    Here’s the view from the podium after my talk:

    The view from the podium

     

    After the talk, I chatted with some folks in the Win7 lounge and basically hung out until 3ish when I got together with my cousin Stacy (who I haven’t seen in a long time).  We wandered over to his restaurant and I met his wife Mindy and mother Selma.  We then went to his house where I met his kids and we hung out and chatted until it was time to go to the airport for the return flight. 

     

     

    For those of you who were wondering what a PDC presenter brings to the PDC, here’s what was in my backpack:

    My PDC Kit 

    Left to right, from top to bottom there was:

    My backpack

    Lego Boeing 787 (I didn’t take that to the PDC).  Two cases for my 2 sets of Altec Lansing T515 bluetooth speakers Laptop 1 (my primary laptop)  Laptop 2 (my demo laptop).

    Power supplies for the laptops, a Jabra BT620SD bluetooth headphones, a Plantronics Voyager 510 Bluetooth headset, the 2 Altec Lansing T515 speakers, a Creative Labs talk microphone.

    Headphones for my portable media player, 2 notepads for notes from the conference, my Creative Zen Vision:M portable media player, 2 bluetooth USB dongles, a USB hub, a box of business cards, my PDC badge from the last PDC I attended (1991), and a Jabra USB headset.

     

    Most of the kit was there for redundancy – in case something got lost or broke, I wanted to make sure I had a backup for everything.    Some of the kit was just there to be props during my talk.

    And I’m glad I did – as I was returning from the conference, one of the T515 devices (the one I own) disappeared between the hotel when I packed it and my house.  I have no idea what happened to it.

  • Larry Osterman's WebLog

    PDC 2008, Day 3

    • 9 Comments

    I got finished late yesterday, so sorry this post is coming so late.

    Yesterday was yet another blast.  I got up, had a “real” breakfast in the hotel buffet (I’m not sure it was actually better than the breakfast at the PDC though :().  Then I headed over to the conference center. 

    I spent most of the morning hanging out in the speakers lounge catching up on email, then I headed down to the floor to talk to attendees in the Win7 Lounge.  It was a great deal of fun, I was astonished at the interest in the sensor platform – the sensor guys were giving out development kits and one guy literally spent the entire 3 hours I was there running back and forth between the sensor booth and their storage closet getting more kits.

     

    I was also really surprised at the excitement around the touch machines.  I honestly didn’t think that touch was that big a deal, but it was clear that there’s a real excitement about the platform.

     

    I also got a chance to chat with Raymond Chen while we were hanging out, which was fun.  I then tried to see his talk, but his first room overflowed and then the overflow room overflowed.  So I left to let a paying customer use my chair.

     

    I ended up spending most of my afternoon wandering around chatting with people and generally keeping busy and then came the “Ask The Experts”.

     

    “Ask The Experts” is the part of the conference where attendees can come in and ask the Microsoft developers any questions they want.

    The attendees arrive:

    Ask The Experts

    The Desktop team answers questions:

    The Desktop Experience Team answers questions

    I was at a table with Frank Biger of the Windows Telemetry team, Crispin Cowan of the UAC team, a couple of folks from the internationalization team.  We fielded a couple of great questions and then the director of development for WEX stopped by and hung out with us for a while.  I’m not sure that the people asking questions realized that the guy answering their questions was the guy who ran the entire development organization in WEX :).

     

    After the A-T-E, I went back to my hotel room, called my cousin Stacy (we’re getting together this afternoon) and chatted with Valorie.

    I then did the final rehearsal of my PDC talk and went to bed.

     

    This morning, I had my tech check (at 7:40 AM :() and now I’m in the speakers lounge chilling until about 11:30 when I’m going to go set up for my 12:00PM talk.

  • Larry Osterman's WebLog

    PDC 2008, Day Two

    • 13 Comments

    Wow, it’s midnight on day two.  What a day.

    I started the day at the Win7 keynote.  It was amazing how the product was received by our customers – I’m really gratified that people seemed to like what they saw.  You know you’re in a group of geeks when the biggest applause line of the demo was “you can boot off of a VHD”.

    I was in the way back of the auditorium (speakers were asked to hang out in the back to let the guests have the best seats) so I ended up taking pictures of the monitors – sorry about the crappy quality:

    Steven and Julie

    Steven and Julie discuss 7.

    And Windows 7 with the new taskbar:

    Windows 7

    After the keynote I ran into Crispin Cowan and we ended up chatting through lunch all the way to his talk.  I sat through most of his talk and then wandered off (he overflowed his room, which is cool).

    I ended up in the speakers lounge to run over my slides and commentary again.   While I was up there I realized I had a great view of the conference floor:

    The view from the speakers lounge

    I also took a picture of the breakfast area – it brings a new level of perspective on just how large this place really is:

    Lunch seating for 3500

    It was a few minutes after I took this picture that I realized that my cell phone needed to be charged.  So I pulled out my USB cable and prepared to download the drivers for the phone (even though the phone has a USB-B jack for charging, it needs to have a Windows driver installed before it will charge from a PC).  After downloading the driver, I started the install and experienced a sinking feeling in the pit of my stomach.

    The driver refused to install on Windows 7.  I don’t know why, I’m running Windows 7 on my main machine at work and the driver works just fine (that’s why I didn’t worry about the whole charging thing).  So here I was with a cell phone that’s just about out of juice.

    And my demo depends on the fact that I can make cell phone calls during the talk.  If the phone’s out of juice on Tuesday, I’ve got a real problem.

    Fortunately there was a Verizon store about 10 miles away that had a charger for my phone, so after an hour or so to drive the 10 miles to the store (and back) I got a charger.  I’ve got to say that I was pretty terrified for a while there…

    After the excitement of the afternoon I went back to the hotel and showered and changed from my show duds to the PDC party at Universal Studios.  That was a total blast, they’d done up the place with all sorts of scary stuff:

    Universal Studios done up for Halloween

    I love taking night photos – even though I only had a micro-tripod, the view of downtown LA was so neat that I wanted to try to get a picture.  It’s ok (the tripod was balanced on a garbage can on a elevated walkway which was shuddering a bit, but I still like it):

    Los Angeles at night from Universal Studios

    One last nighttime photo, this time from the Jurassic Park ride:

    Jurassic Park the ride

    The mist at the bottom of the photo is actually the ride splashing down – this is a four and a half second exposure, so all you see is the remnants of the boat’s passing. 

    While I was at Universal I chatted with a whole lot of folks, including Scott Guthrie, Scott Hanselman, Scott’s boss Simon, Dave Snipp (ex MSFT) and several other people.  It was pretty fun.

    I then came back to my room, uploaded these (and a few other) photos and wrote this.  And now it’s bedtime :).

     

    Edit: s/Stephen/Steven/ - sorry about that :).

     

  • Larry Osterman's WebLog

    PDC 2008, Day 1

    • 1 Comments

    Wow, today’s been a long day.  For whatever reason, I woke up at 4 AM and wasn’t able to get back to sleep :(.  On the other hand, I did get this cool picture from outside my window:

    The View From My Window - 6AM at the Westin Bonaventure

    When I got to the convention center I discovered that they were right – this place is absolutely immense.  You really can’t see it from this picture, but this is just one of the eating areas – there’s another on the opposite side of the “big room” that’s equally large:

    The breakfast nook - cozy eating for 3000

    I know I’m going to get my exercise just walking to and from the keynotes :). 

    The other thing I didn’t realize was the amount of ancillary manpower associated with the conference – there was a veritable army of waiters there to clean up after all 6500 of us.  There are also staff people in front of just about every door in the convention center (and that’s a lot of doors) to help direct people.  

    I’m also really impressed with the logistics – the wireless network works flawlessly throughout the convention center and bandwidth appears to be quite reasonable.  My hat’s off to the organizers they’ve done a great job so far.

    Since there was nothing specifically related to Win7 going on today (the Win7 hoopla starts tomorrow), I mostly hung out at the various lounges and worked on my talk a bit – there was a typo in one of my slides I needed to fix, and I wanted to get some of the colors cleaned up in one of my images.  Fortunately the PDC organizers had a crack team of graphic designers who were able to fix up my slides and dramatically improve the look of the offending slide (the rest of the deck looked fine because the graphic designers had already gone over the deck once). 

    Realistically the day was pretty boring.  I stopped in and watched most of the Windows Azure keynote, I’ve got to say that it looks pretty good – I like what Dave Cutler’s done, it looks like a very impressive piece of work.

    Most of my day was spent chatting with attendees (and other Microsoft people).  I finally met Brandon Paddock, who I’ve known for a while on email and we chatted for a bit.  I also ran into the Channel 9 folks and again we chatted.  I also tried (unsuccessfully) to catch up with my email.

    At about 6:30 I finally gave up and headed back to the hotel.  At the hotel, I ran into some folks from DevDiv who were having drinks with Anders, so I kibitzed on their conversation a bit.

    Then I cam back to my hotel room to rehearse my talk and wait for Valorie’s nightly call. I’m really looking forward to tomorrow – I can’t wait for the Win7 keynote :). 

    One final picture – this one’s for Daniel (who loves taking pictures of architectural elements):

    Architectural elements inside the convention center

    PS: I’ve put these and a number of other photos up on Flickr with the pdc2008 tag.

    ETA: One unexpected side bonus of being at the PDC is running into people I've not seen for years.  I ran into a bunch of co-workers I've not seen for a really long time including Dave Snipp (who worked on NT 3.1), David Treadwell and Dave D'Souza.  That was just cool - kinda like old times.

     

  • Larry Osterman's WebLog

    I'm in LA!

    • 3 Comments

    I just got into LA and checked into my hotel for the PDC.  The flight was uneventful, while I was flying down, there was a most amazing sunset (I was in an isle seat so the picture’s kinda blurry – I didn’t have anything to stabilize the shot and it’s a somewhat long exposure):

    PDC 2008 013 Once I got here, I found it was too late to register, that means that I’m going to have to brave the lines tomorrow morning – yech. 

    I’m in the Bonaventure hotel which is quite nice, however the hotel room is annoyingly short of plugs – there are only 2 plugs available in the bedroom, and I’m using both of them for my laptops (I brought two down, one for day-to-day use and the other for the demo during my presentation – my day-to-day laptop acts as a backup  for the demo laptop if it fails) – my camera battery is currently charging in the bathroom.

     

    I’m going to do daily posts of my overall PDC experiences, preferably with pictures as well.

  • Larry Osterman's WebLog

    Chrome is fixing the file download bug…

    • 13 Comments

    I just noticed that Ryan Naraine has written that Google’s fixed the file download bug in Chrome.  This is awesome, but there’s one aspect of the fix that concerns me.

    According to the changelog:

    This CL adds prompting for dangerous types of files (executable) when they are automatically downloaded.

    When I read this, my first thought was: “I wonder how they determine if a file is ‘dangerous’?”

    One of the things that we’ve learned over time is that there are relatively few files that aren’t “dangerous”.  Sure there are the obvious files (.exe, .dll, .com, .bat, etc) but there are lots of other file types that can contain executable content.  For instance most word processors and spreadsheets support some form of scripting language, that means that most documents downloaded can contain executable content.

    Even if you ignore the files that contain things that are clearly identifiable as “code”, you’ve still got problems.  After all, just about every single file format out there has had readers who have had bugs that would have allowed remote code execution.

    It’s unfortunate, but given the history of the past couple of years, I can’t see how ANY content that was downloaded from the internet could be considered “safe”.

    IMHO Google’s change is a good start, but I’m worried that that it doesn’t go far enough. 

  • Larry Osterman's WebLog

    Engineering 7: A view from the bottom

    • 8 Comments

    About 2 months ago, Steven Sinofsky and Jon DeVaan started the “Engineering Windows 7” blog.  The instant I saw the blog, I wanted to contribute to the blog (because I love writing :)).

    I spent a fair amount of time thinking about what to write about and realized that one thing that wasn’t likely to be discussed was how the actual software engineering process of Windows 7 worked – not the data behind particular features, but how the hard core engineering work was managed.  So I wrote it and submitted it to Steven and Jon.

     

    My article (it’s too long to be considered a “post”) went live on the Engineering 7 blog sometime last night.

     

    Enjoy!

  • Larry Osterman's WebLog

    I get spam :)

    • 18 Comments

    I just received this spam message the other day:

    From: Microsoft [mailto:customerservice@microsoft.com]

    Sent: Saturday, October 11, 2008 11:13 PM

    To: Larry Osterman

    Subject: Security Update for OS Microsoft Windows

    Dear Microsoft Customer,

    Please notice that Microsoft company has recently issued a Security Update for OS Microsoft Windows. The update applies to the following OS versions: Microsoft Windows 98, Microsoft Windows 2000, Microsoft Windows Millenium, Microsoft Windows XP, Microsoft Windows Vista.

    Please notice, that present update applies to high-priority updates category. In order to help protect your computer against security threats and performance problems, we strongly recommend you to install this update.

    Since public distribution of this Update through the official website http://www.microsoft.com would have result in efficient creation of a malicious software, we made a decision to issue an experimental private version of an update for all Microsoft Windows OS users.

    As your computer is set to receive notifications when new updates are available, you have received this notice.

    In order to start the update, please follow the step-by-step instruction:

    1. Run the file, that you have received along with this message.

    2. Carefully follow all the instructions you see on the screen.

    If nothing changes after you have run the file, probably in the settings of your OS you have an indication to run all the updates at a background routine. In that case, at this point the upgrade of your OS will be finished.

    We apologize for any inconvenience this back order may be causing you.

    Thank you,

    Steve Lipner

    Director of Security Assurance

    Microsoft Corp.

    -----BEGIN PGP SIGNATURE-----

    Version: PGP 7.1

    AN86DCS206WKI6IK8LIFD5S1VODA48SHXDCG6KT8V4C50MO21RUHP8O84T6P73YGX

    EO755U27OA5JVX3U51QF8N2E97FQQDOC6IRHH7T3TSQJRFYYPR3434M634A375LAO

    49ICIMQZ680BR307KVS857K6U9UYSBHE20RNI16HUB45SMTDF0DDMQZ4YIR2QIHLD

    UVPMVD54LRY8HNLDA020KWMIFYYD9B1A07AM1VWIA0YO8QZO2WLY27KAPXBFDN6DT

    48VYUVW7M7JZ5P2NIU7FGDRIGCM819WMKJ2==

    -----END PGP SIGNATURE-----

    Attached to the message was an attachment named “KB266311.exe”.

    I’ve heard that these before but I’ve never received one.  Apparently the email was sent from “koln-5d8184e2.pool.einsundeins.de (93.129.132.226)”, which I suspect is a trojaned machine in Germany.   In this case I’m pretty impressed with the email – it’s in plain text with the name of a real Microsoft employee, it has a PGP signature (which tends to give credence to the email).  On the other hand it has some grammatical errors (“Please notice that Microsoft company has…”, “We apologize for any inconvenience this back order may be causing you”) that give the scam away.  I also don’t know what trojan was inside KB266311 because it was filtered by our email servers before it got to me.

     

     

    For those that are wondering how I knew it came from koln-5d8184e2.pool.einsundeins.de, here’s what I did:

    I started with the raw email headers (some servers and IP addresses obscured):

    Received: from XXX.microsoft.com (n.n.n.n) by
    YYY.microsoft.com (m.m.m.m) with Microsoft SMTP
    Server (TLS) id 8.2.83.0; Sat, 11 Oct 2008 23:13:52 -0700
    Received: from koln-5d8184e2.pool.einsundeins.de (93.129.132.226) by
    ZZZ.microsoft.com (o.o.o.o) with Microsoft SMTP Server id
    8.1.291.1; Sat, 11 Oct 2008 23:13:41 -0700
    Received: from [93.129.132.226] by QQQ.hotmail.com; Sun, 12 Oct 2008 07:13:17
    +0100
    From: Microsoft <customerservice@microsoft.com>
    To: <<Larry’s Email Address>>
    Subject: Security Update for OS Microsoft Windows
    Date: Sun, 12 Oct 2008 07:13:17 +0100
    MIME-Version: 1.0
    Content-Type: multipart/mixed;
        boundary="----=_NextPart_000_000E_01C92C39.FF9CE480"
    X-Mailer: Microsoft Office Outlook, Build 11.0.5510
    Thread-Index: Aca6Q862Q89QD80AN22RHXR0U7WZ61==
    X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700
    Message-ID: <01c92c39$ff9ce480$e284815d@60GC7Q>
    Return-Path: 60GC7Q@hotmail.com
    X-MS-Exchange-Organization-PRD: microsoft.com
    Received-SPF: TempError (XXX.microsoft.com: error in
    processing during lookup of customerservice@microsoft.com: DNS timeout)
    X-MS-Exchange-Organization-PCL: 2
    X-MS-Exchange-Organization-Antispam-Report: DV:3.3.7011.600;SV:3.3.7011.1437;SID:SenderIDStatus
    TempError;OrigIP:93.129.132.226
    X-MS-Exchange-Organization-SCL: 0
    X-MS-Exchange-Organization-SenderIdResult: TEMPERROR

    RFC 2821 says that SMTP servers should prepend a Received: header to an email message whenever they process the email message.  In this case the last email server was XXX.microsoft.com.  XXX.microsoft.com received the message from YYY.microsoft.com which in turn received the message from koln-5d8184e2.pool.einsundeins.de (einsundeins.de appears to be a german ISP).   The next bit of trace is confusing.  The machine at 93.129.132.226 says that it received the message from QQQ.hotmail.com. 

    It’s possible that this spam email originated from hotmail, but I don’t think so.  First off, as far as I know, you can’t relay through the hotmail SMTP servers and the sender of the email is “customerservice@microsoft.com” (the sender is included in the Received-SPF header which indicates that the “MAIL FROM” header in the SMTP exchange was “customerservice@microsoft.com”.  Secondly the hotmail servers don’t set the X-Mailer header, but this header indicates that it was sent from Outlook 2003.  Instead, I think that the bottom Received: header was forged to throw off people trying to figure out where the email came from.

     

     

    Needless to say, Microsoft will never EVER send a security update to customers by mail, and customers should immediately delete any emails that claim to have security fixes from Microsoft.

  • Larry Osterman's WebLog

    What really happens when you shutdown Windows?

    • 7 Comments

    About a year or so ago, I wrote a post that talked about the Windows shutdown experience.

     

    A couple of the people reading the post asked for more details, and it turns out that the performance folks have just issued this paper which describes (in great detail) what happens during system boot and shutdown.

     

    I skimmed over it before posting and thought it was pretty cool.

  • Larry Osterman's WebLog

    What’s wrong with this code, part 24 – the answer

    • 6 Comments

    In my last post, I included a snippet from an MSDN article written by Kenny Kerr. 

    The snippet was pretty straightforward, but had a subtle bug in it:

    CRect rectangle;
    VERIFY(m_splitButton.GetWindowRect(
        &rectangle));
    
    TPMPARAMS params = { sizeof(TPMPARAMS) };
    params.rcExclude = rectangle;
    
    CMenuHandle menu = m_menu.GetSubMenu(0);
    
    VERIFY(menu.TrackPopupMenuEx(TPM_LEFTBUTTON,
        rectangle.left, rectangle.bottom,
        m_hWnd, &params));

     

    The problem was that on Bidi localized systems the popup menu is located in the wrong location.  The TrackPopupMenuEx API takes screen coordinates for the popup menu and on a LTR system creates the popup window with the top left corner of the window at that screen coordinate.  The problem here is that on an RTL system the top right of the menu is located at the screen coordinates.  The good news is that the fix is relatively simple:

    CRect rectangle;
    VERIFY(m_splitButton.GetWindowRect(
        &rectangle));
    
    TPMPARAMS params = { sizeof(TPMPARAMS) };
    params.rcExclude = rectangle;
    
    CMenuHandle menu = m_menu.GetSubMenu(0);
    
    VERIFY(menu.TrackPopupMenuEx(TPM_LEFTBUTTON,
        ((GetWindowLong(m_hWnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0 ? rectangle.right :  rectangle.left), rectangle.bottom,
        m_hWnd, &params));

    Before I posted this blog post, I asked the author (who also commented on the previous post) about it.  His response was:

    As I tried to trim the sample to the bare minimum I didn’t bother with this. You can use GetSystemMetrics to get the proper alignment, but I’m not sure this constitutes a “nasty bug” so you may be after something else.

    IMHO Kenny’s right – code samples are intended to be the bare minimums, there are tons of differences between what you do in a code sample and what you do in production code – support for RTL languages is one of those taxes that get left behind when writing samples.

    The reason I wrote the post wasn’t to pick on Kenny or MSDN magazine.  Instead it was to point out the fact that popup menus tied to UI elements don’t work the way you expect on mirrored builds, leading to subtle display issues.

     

     

    Kudos and mea culpas:

    First off, my phrasing was incorrect – the bug wasn’t “nasty” it was subtle and not at all obvious.

    Kenny’s comment was the first to mention the RTL issue, but to be fair, he and I had exchanged emails last week about this issue so I don’t feel good in giving him the kudos.  Instead I’m going to give it to Ryan who correctly pointed out that the snippet assumes LTR order.

     

    There are some other interesting potential issues like Maciej Rutkowski pointing out that the UI might misbehave at the bottom of the screen (a good point).

  • Larry Osterman's WebLog

    What’s wrong with this code part 24 (From an MSDN article)?

    • 23 Comments

    I ran into this bug earlier today and realized that it’d make an awesome “What’s wrong with this code”.

    I started pulling together a test app when I realized that this MSDN magazine article contains sample code that perfectly exhibits the bug:

    CRect rectangle;
    VERIFY(m_splitButton.GetWindowRect(
        &rectangle));
    
    TPMPARAMS params = { sizeof(TPMPARAMS) };
    params.rcExclude = rectangle;
    
    CMenuHandle menu = m_menu.GetSubMenu(0);
    
    VERIFY(menu.TrackPopupMenuEx(TPM_LEFTBUTTON,
        rectangle.left, rectangle.bottom,
        m_hWnd, &params));

    There’s not much to the code – it’s from the handler for the BCN_DROPDOWN notification message.  And it’s got a very nasty subtle bug in it.

    So what’s the bug?

     

    Edit: s/nasty/subtle/

     

  • Larry Osterman's WebLog

    The common control library sometimes sends an NMCUSTOMDRAW message for the NM_CUSTOMDRAW notification.

    • 7 Comments

    I just fixed a bug in our UI that was caused by a misunderstanding of the API contract for the NM_CUSTOMDRAW handler for some of the common controls.

    On of October 3rd, 2008 The common control documentation for the NM_CUSTOMDRAW message says:

    lpNMCustomDraw
    A pointer to a custom draw-related structure that contains information about the drawing operation. The following list specifies the controls and their associated structures.
    List view
    NMLVCUSTOMDRAW
    ToolTip
    NMTTCUSTOMDRAW
    Tree view
    NMTVCUSTOMDRAW
    Toolbar
    NMTBCUSTOMDRAW
    All other supported controls
    NMCUSTOMDRAW

    While this is correct in general it is NOT true for the CDDS_PREPAINT draw stage.  It turns out that some of the common controls only provide an NMCUSTOMDRAW structure when the drawing logic is in the CDDS_PREPAINT stage. 

    If you look VERY carefully at MSDN, you can find this page which mentions that the first NM_CUSTOMDRAW notification receives an NMCUSTOMDRAW structure and not an NMLVCUSTOMDRAW handler but that’s the only page I was able to find to indicate this.

     

    I’ve notified the relevant documentation folks about this and hopefully the documents will be updated in the future.  You can consider this blog post as a pre-update to the SDK documentation.

  • Larry Osterman's WebLog

    Ok, I’m strange…

    • 5 Comments

    I was looking at the front page of MSNBC and ran into this picture:

    Image: Traders at stock exchange in Sao Paulo, Brazil

    (image copyright Sebastiao Moreira / EPA). 

     

    My first thought was “Why do these people all have hotdogs with yellow mustard pressed up to their face?”

     

    I did say that I was being weird.

  • Larry Osterman's WebLog

    DrawThemeText doesn’t really support the DT_CALCRECT format value

    • 1 Comments

    I just noticed this while working on a bug fix.

    We have some code that attempts to determine the size of a piece of text by calling DrawThemeText with the DT_CALCRECT format value.

    According to this page (as of 9/30/2008) the DT_CALCRECT option determines the width and height of the display rectangle.

    Unfortunately the DT_CALCRECT option doesn’t actually return the width and height of the display rectangle.  Instead it doesn’t modify the input LPRECT field.  I asked the developer and he indicated that the reason was that the pRect parameter to DrawThemeText is actually defined as a LPCRECT and thus the implicit contract for the API is that it doesn’t change the contents of the pRect field.

     

    There are two ways of working around this problem.  The first (and recommended) way is to call GetThemeTextExtent to retrieve the dimensions of the rectangle.  The second (which works on Vista and later operating systems) is to call DrawThemeTextEx passing in the DTT_CALCRECT flag – in that case the DrawThemeTextEx API will return the size of the text in the pRect parameter.

     

    I’ve sent emails to the SDK folks so it’s entirely likely that the page will be updated in the future but until it is, hopefully this will help someone using the search engines to find what’s going on.

  • Larry Osterman's WebLog

    Why specify SND_NODEFAULT when calling PlaySound?

    • 5 Comments

    Because the alternative is often much worse.

     

    Several months ago, I got a bug report that if you launched mmsys.cpl then set the “Select” sound to a value, then cleared the sound, the reporters application would ding whenever you moved around their tree control.

    I dug into the problem a bit and discovered that the problem was actually in the Windows common controls.  Under some circumstances the common controls would call PlaySound specifying a sound alias and the SND_ASYNC and SND_ALIAS flags only. 

    The problem with this is that if you specify SND_ALIAS without also specifying SND_NODEFAULT, the PlaySound API decides that you really want the sound to be played and it will play the default “ding” sound instead. 

    From the PlaySound API’s point of view this makes sense.  After all, you asked the API to play a sound, it doesn’t know that you meant “only play this sound when the sound file represented by the alias exists”. 

     

    In fact, that’s the entire reason for the SND_NODEFAULT flag – it lets the PlaySound API that you only want to play a sound when the sound has been defined.

  • Larry Osterman's WebLog

    They just announced my PDC talk, so I guess I can mention at least the title of the talk.

    • 5 Comments

    The PDC folks just announced a host of Windows 7 related PDC talks, one of which is mine.

    The title of the talk is “Windows 7: Building Great Communications Applications”.  You can find it under the Windows 7 track on the Microsoft PDC site.

     

    The primary target for my talk is developers who are building an application that in any way communicates between users (voice mail, instant messaging, voice over ip, etc).  In addition, if you’re a games developer or a media player developer, you should also attend, there’s stuff in the talk for you too.

     

    There are also some other cool talks included in the list that I’m absolutely planning on attending.

     

     

    See you in LA!

  • Larry Osterman's WebLog

    Why call PlaySound(NULL, NULL, SND_NODEFAULT)?

    • 5 Comments

    Someone just wandered over to my office and he had noticed the following pattern in his code:

    PlaySound(NULL, NULL, SND_NODEFAULT);
    PlaySound(".Default", NULL, SND_SYSTEM | SND_ASYNC | SND_NODEFAULT);

    He was wondering why on earth the code would do that call to PlaySound(NULL). 

    As I explained it to him, the reason is because you almost always want to cancel the current sound playing before you queue up the next sound.

    The problem is that the current implementation[1] of PlaySound(…, SND_ASYNC) simply queues the request to a worker thread which blocks waiting on the currently playing sound to complete.  So if you have a situation where you call PlaySound(…, SND_ASYNC) many times in succession, you’ll find that all the calls to PlaySound pile up behind each other, which means that you might end up playing sounds long after the action associated with the sound has completed.

    Of course you might want this behavior – it’s certainly possible to string lots of system sounds together to produce any number of interesting effects.

    But most of the time you just want to stop the current sound before you start playing the next.

     

     

    [1] There are obviously no guarantees that the implementation of PlaySound won’t change – I’m just describing what the current code does.  Even if the implementation is changed, it won’t change the underlying behavior.

  • Larry Osterman's WebLog

    See you in LA in October!

    • 3 Comments

    I just got word that the talk we’d proposed for the PDC in October was approved, so I’m going to La-La-Land next month for a couple of days.

     

    The contents of my talk have not yet been disclosed, so I can’t talk about what I’m talking about at the PDC :(. 

     

    Disclaimer: Life sometimes happens.  Right now I’m scheduled to talk but who knows whats gonna happen between now and then?  But I AM excited.  This will be my second PDC – the first one was WAY back in 1992 (I need to make sure that I remember to bring my speaker badge from that (yes, I still have it)).

  • Larry Osterman's WebLog

    What’s wrong with this code, Part 23 – The Answers

    • 21 Comments

    My last post was all about a problem with what appeared to be some really simple ATL code.

    It turns out that the problem was easier than I had expected.  James Skimming came up with the answer on the second comment.  The problem here was that the following code (snipped a bit)

    IMMDeviceEnumerator *GetDeviceEnumerator()
    {
        CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    
        HRESULT hr = deviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
        if (FAILED(hr))
        {
            return NULL;
        }
        return deviceEnumerator.Detach();
    
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        CoInitialize(NULL);
        {
            CComPtr<IMMDeviceEnumerator> deviceEnumerator(GetDeviceEnumerator());
            CComPtr<IMMDeviceCollection> deviceCollection;
    
            if (deviceEnumerator != NULL)
            {
                HRESULT hr = deviceEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &deviceCollection);
                if (SUCCEEDED(hr))
                {

    That’s because the CComPtr<T> constructor takes a reference to the input T* object.  As a result, the code leaks a reference to the MMDeviceEnumerator object.  The correct fix for the problem generated a fair amount of discussion in the comments and on email internally.

    The root cause of the problem  is that the code in question mixes raw interface pointers and smart pointers.  In this case there’s an impedance mismatch between the GetDeviceEnumerator (which returns a raw pointer) and it’s caller (which is expecting a smart pointer).

    My preferred solution to the problem is:

    CComPtr<IMMDeviceEnumerator> GetDeviceEnumerator()
    {
        CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    
        HRESULT hr = deviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
        if (FAILED(hr))
        {
            return NULL;
        }
        return deviceEnumerator;
    
    }

    The reason I prefer this solution is that it consistently uses the smart pointer class.  There are two downsides to it.  The first is that it loses the result of the call to CoCreateInstance.  The other downside is that it constructs a temporary object on the stack and has two additional calls to AddRef()/Release().

     

    There are other possible solutions.  The second possible solution changes the GetDeviceEnumerator function:

    HRESULT GetDeviceEnumerator(IMMDeviceEnumerator *Enumerator)
    {
        CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    
        if (Enumerator == NULL)
        {
            return E_POINTER;
        }
        HRESULT hr = deviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
        if (FAILED(hr))
        {
            *Enumerator = NULL;
            return hr;
        }
        *Enumerator = deviceEnumerator.Detach();
    
        return S_OK;
    }

    With this change, the caller looks like:

        {
            CComPtr<IMMDeviceEnumerator> deviceEnumerator;
            if (SUCCEEDED(GetDeviceEnumerator(&deviceEnumerator))
            {
                CComPtr<IMMDeviceCollection> deviceCollection;
                HRESULT hr = deviceEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &deviceCollection);
                if (SUCCEEDED(hr))

    This solution fits closely with the COM usage pattern so it is quite attractive.  You also don’t lose the result of the CoCreateInstance API call, which can be extremely useful for diagnostics.  The major negative with this is that it depends on the fact that the CComPtr<T> operator& returns a raw pointer to the underlying object.

     

    The third possible solution keeps the “return a value” idea of the original code but works around the additional reference applied in the constructor.  Keep the original implementation of GetDeviceEnumerator and change the tmain function as follows:

    int _tmain(int argc, _TCHAR* argv[])
    {
        CoInitialize(NULL);
        {
            CComPtr<IMMDeviceEnumerator> deviceEnumerator;
            deviceEnumerator.Attach(GetDeviceEnumerator());
            CComPtr<IMMDeviceCollection> deviceCollection;

    The big problem with this solution is that to me it’s “unnatural” – the whole point of using smart pointers is that their use is supposed to be intuitive, however in this case there’s nothing intuitive about the use – it certainly fixes the problem but it relies on internal behaviors of the smart pointer class.  To me this is the least attractive solution to the problem.

     

    As I mentioned, Kudos to James Skimming for figuring the problem out quickly.

  • Larry Osterman's WebLog

    What’s wrong with this code, Part 23..

    • 26 Comments

    I recently tracked down a bug that was causing problems in my code.  Once I figured out the bug, I realized it made a good “what’s wrong with this code”…

    #include "stdafx.h"
    #include <mmdeviceapi.h>
    
    
    IMMDeviceEnumerator *GetDeviceEnumerator()
    {
        CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    
        HRESULT hr = deviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
        if (FAILED(hr))
        {
            return NULL;
        }
        return deviceEnumerator.Detach();
    
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        CoInitialize(NULL);
        {
            CComPtr<IMMDeviceEnumerator> deviceEnumerator(GetDeviceEnumerator());
            CComPtr<IMMDeviceCollection> deviceCollection;
    
            if (deviceEnumerator != NULL)
            {
                HRESULT hr = deviceEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE, &deviceCollection);
                if (SUCCEEDED(hr))
                {
                    UINT deviceCount;
                    hr = deviceCollection->GetCount(&deviceCount);
                    if (SUCCEEDED(hr))
                    {
                        printf("There are %d audio endpoints on the machine\n", deviceCount);
                    }
                }
            }
        }
        CoUninitialize();
        return 0;
    }

    Simple code, right?  But there’s a nasty bug hidden in there, and it was NOT obvious to me what the bug was.

    As always, kudos to the person who gets the bug first.  And of course mea culpa's for bugs I accidentally included.

  • Larry Osterman's WebLog

    Anatomy of a Heisenbug

    • 15 Comments

    I just spent a half an hour debugging a heisenbug and thought I’d pass on what was happening.

     

    I was running my unit tests for one of my features and they were reliably failing.  Unfortunately the instant I ran the test case under the debugger, the problem went away.  Problems that disappear under the debugger are a classic symptom of a heisenbug, this was no exception.

    If I attached the debugger AFTER the test started but before the failure hit, I was able to see the failure occur.  The problem only occurred when launching the app under the debugger.  At that point I realized what was happening.

    As MSDN says

    Processes that the debugger creates (also known as spawned processes) behave slightly differently than processes that the debugger does not create.

    Instead of using the standard heap API, processes that the debugger creates use a special debug heap. On Microsoft Windows XP and later versions of Windows, you can force a spawned process to use the standard heap instead of the debug heap by using the _NO_DEBUG_HEAP environment variable or the -hd command-line option.

    It turns out that I had added a member variable to a class and failed to initialize it in the constructor of the class.  When launched under the debugger, the debug heap initializes all allocated memory to a known value.  That means that when launched under the debugger the member variable had that known value, when launched without the debugger it was uninitialized and happened to have the value of 0.  For a number of reasons, this value caused the test to fail. 

     

    I hate heisenbugs, but I like it when they’re really easy to find like this one.

  • Larry Osterman's WebLog

    I'm So Excited!

    • 34 Comments

    image

    'nuf said.

     

     

    I know it's bragging, but I'm sorry - I really couldn't resist.  It's been a very long time.

  • Larry Osterman's WebLog

    Gotchas associated with using WM_PRINTCLIENT…

    • 22 Comments

    Yesterday I mentioned WM_PRINTCLIENT and how awesome it is when trying to strictly control the drawing of your application.

    Part of the reason it took over a week to change the drawing model is that there are a number of serious gotcha’s associated with using WM_PRINTCLIENT and controlling your own drawing story.  The first is that not all controls support WM_PRINTCLIENT.  It turns out that some controls don’t support the WM_PRINTCLIENT, however if you search the documentation for WM_PAINT, you’ll find the following comment:

    “For some common controls, the default WM_PAINT message processing checks the wParam parameter. If wParam is non-NULL, the control assumes that the value is an HDC and paints using that device context.”

    That means that if you find a common control that doesn’t support WM_PRINTCLIENT, you can use WM_PAINT specifying wParam as the HDC[1].  Fortunately I didn’t run into this in my control.

    The next gotcha is that some controls (like buttons and toolbars etc) have animations that are launched when you mouse over the control.  These are often subtle (like the glow when you hover over a scrollbar thumb).  In order to continue to have these effects work, you need to let those controls paint themselves – in my experience it generally didn’t cause much of a problem with flickering, but your mileage might vary.

     

    The last gotcha is a very big one and hung me up for about half a day.  The WM_PRINTCLIENT message only paints the client area of a window.  If you have a window with the WM_HSCROLL or WM_VSCROLL style then you won’t be able to paint the scroll bar.  Instead you need to create your own scrollbar control (with CreateWindow) and use that instead of the built-in scroll styles.  There are ways you can convince the window to paint it’s non client region to an HDC but they are fraught with peril (one senior developer I was talking to about this problem described them as “unnatural acts”) and simply not worth the effort.

     

     

     

    [1] There’s also a corollary to that: If you ever send a WM_PAINT to a control you MUST ensure that wParam and lParam are 0 even though they’re documented as “not used”.

Page 4 of 33 (815 items) «23456»