Larry Osterman's WebLog

Confessions of an Old Fogey
  • Larry Osterman's WebLog

    It was 20 years ago today...


    Nope, Sgt Pepper didn’t teach the band to play.


    What a long strange trip it’s been.

    Over the past 20 years, I’ve:











    I’ve watched Microsoft grow from 650ish people to well over 50,000.



    I’ve watched the internet bubble start, blossom, and explode.























    Ken Masden – the man who brought unicycle juggling to Microsoft.











    Edit: Forgot some managers in the list :)


    Edit3: Got some more Xenix developers :)


  • Larry Osterman's WebLog

    Farewell to one of the great ones

    Yesterday was the last day at Microsoft for David WeiseI've written about David (in passing) in the past, but never in detail.

    David started at Microsoft in 1986, when Microsoft acquired Dynamical Systems Research.  Before founding DSR, he was a member of the ORIGINAL MIT blackjack team - not the latecomers that you see in all the movies, but the original team, back in the 1970s.  According to Daniel Weise (David's twin brother), they ran it like an investment company - MIT people could invest money in the blackjack team, and the blackjack team would divide their winnings up among them.  Apparently RMS was one of the original investors, during David's going away party, Daniel joked that the FSF was founded on David's blackjack winnings :)

    After leaving Princeton with a PhD in molecular biophysics, David, Chuck Whitmer, Nathan and Cameron Myhrvold, and a few others founded DSR to create a "Topview" clone.  For those new to the industry, Topview was a text based multitasking shell that IBM created that was going to totally revolutionize the PC industry - it would wrest control of the platform from Microsoft and allow IBM to maintain its rightful place as leader of the PC industry.  Unfortunately for IBM, it was an utter flop.

    And, as Daniel pointed out, it was unfortunate for DSR.  Even though their product was twice as fast as IBMs and 2/3rds the size, when you base your business model on being a clone of a flop, you've got a problem.

    Fortunately, at the time, Microsoft was also worried about Topview, and they were looking for a company that understood the Topview environment so that if it was successful, Microsoft would have the ability to integrate Topview support into Windows.

    Finding DSR may have been one of the best acquisitions that Microsoft ever made.  Not only did they find the future CTO (and founder of Microsoft Research) Nathan Myhrvold, but they also hired David Weise.

    You see, the DSR guys were wizards, and David was a wizard's wizard.  He looks at programs and makes them smaller and faster.  It's absolutely magical to watch him at his work.

    I (and others) believe that David is single handedly responsible for making Microsoft over a billion dollars.  He's also (IMHO) the person who is most responsible for the success of Windows 3.0.

    Everywhere David worked, he dramatically improved the quality of the product.  He worked on the OS/2 graphics drivers and they got faster and smarter.  He (and Chuck) figured out tricks that even the designers of the hardware didn't realize could be done.

    And eventually, David found himself in the Windows group with Aaron Reynolds, and Ralph Lipe (and several others).

    Davids job was to move the graphics drivers in windows into protected mode on 286 and better processors (to free up precious memory below 640K for Windows applications).  He (and Chuck) had already figured out how to get normal Windows applications to use expanded memory for their code and data, but now he was tackling a harder  problem - the protected mode environment is subtler than expanded memory - if you touched memory that wasn't yours, you'd crash.

    David succeeded (of course).  But David, being David, didn't stop with the graphics drivers.

    He (along with Murray Sargent, creator of the SST debugger) also figured out how to get normal Windows applications running in protected mode.

    Which totally and utterly and irrevocably blew apart the 640K memory barrier.

    I remember wandering over to the Windows group over in Building 3 to talk to Aaron Reynolds about something to do with the MS-DOS redirector (I was working on DOS Lan Manager at the time).  I ran into David, and he called me into his office "Hey, look at what I've got working!".

    He showed me existing windows apps running in protected mode on the 286.  UNMODIFIED Windows 1.0 applications running in protected mode.

    He then ran me around the rest of the group, and they showed me the other stuff they were working on.  Ralph had written a new driver architecture called VxD.  Aaron had done something astonishing (I'm not sure what).  They had display drivers that could display 256 color bitmaps on the screen (the best OS/2 could do at the time was 16 colors).

    My jaw was dropping lower and lower as I moved from office to office.  "Oh my goodness, you can't let Steve see this, he's going to pitch a fit" (those aren't quite the words I used, but this is a family blog).

    You see, at this time, Microsoft's systems division was 100% focused on OS/2 1.1.  All of the efforts of the systems division were totally invested in OS/2 development.  We had invested literally tens of millions of dollars on OS/2, because we knew that it was the future for Microsoft.  OS/2 at the time just ran a single DOS application at a time, and it had only just recently gotten a GUI (in 1989).  It didn't have support for many printers (only about 5, all made by IBM, and (I believe) the HP Laserjet).



    Btw, David had discussed it with Steve (I just learned that yesterday).  As David put it, he realized that this was potentially an issue, so he went to Steve, and told him about it.  Steve asked Dave to let him know when he'd made progress.  That night, David was up until 5AM working on the code, he got it working, and he'd left it running on his machine.  He left a note on SteveB's office door saying that he should stop by David's office.  When David got in the next day (at around 8AM), he saw that his machine had crashed, so he knew that Steve had come by and seen it.

    He went to Steve's office, and they had a chat.  Steve's only comment was that David should tell his manager and his manager's manager so that they'd not be surprised at the product review that was going to happen later that day.  At the product review, Steve and Bill greenlighted the Windows 3.0 project, and the rest was history.  My tour was apparently a couple of days after that - it was finally ok to let people know what the Windows 3.0 team was doing.




    And David absolutely belongs in their company.

    David's leaving to learn more about the state of molecular biology today, he wants to finally be able to use his PhD, the field has changed so much since he left it, and it's amazing what's happening in it these days.

    As I said as I was leaving his goodbye party:

    "Congratulations, good luck, and, from the bottom of my heart, thank you".

    Bonne Chance David, I wish you all the best.  When you get your Nobel Prize, I'll be able to say "I knew him back when he worked at Microsoft".


    Edit: Corrected David's PhD info based on Peter Woit's blog post here.  Sorry David, and thanks Peter.

    Edit2: Grey->Gray :)  Thanks Jay

  • Larry Osterman's WebLog

    Why does Windows share the root of your drive?


    Out-of-the box, a Windows system automatically shares the root of every hard drive on the machine as <drive>$ (so you get C$, D$, A$, etc).

    The shares are ACL'ed so that only members of the local administrative group can access them, and they're hidden from the normal enumeration UI (they're included in the enumeration APIs but not in the UI (as are all shares with a trailing $ in their name).

    One question that came up yesterday was why Windows does this in the first place.

    The answer is steeped in history.  It goes way back to the days of Lan Manager 1.0, and is a great example of how using your own dogfood helps create better products.

    Lan Manager was Microsoft's first attempt at competing directly with Novell in networking.  Up until that point, Microsoft produced an OEM-only networking product called MS-NET (I have a copy of the OEM adaptation kit for MS-NET 1.1 in my office - it was the first product I ever shipped at Microsoft).

    But Lan Manager was intended as a full solution.  It had a full complement of APIs to support administration, supported centralized authentication, etc.

    One of the key features for Lan Manager was, of course, remote administration.  The server admin could sit in their office and perform any administrative tasks they wanted to on the computer.

    This worked great - the product was totally living up to our expectations...

    Until the day that the development lead for Lan Manager (Russ (Ralph) Ryan) needed to change a config file on the LanMan server that hosted the source code for the Lan Manager product.  And he realized that none of the file shares on the machine allowed access to the root directory of the server!  He couldn't add a new share remotely, because the UI for adding file shares required that you navigate through a tree view of the disk - and since the root wasn't shared, he could only add shares that lived under the directories that were already shared.

    So he had to trudge from his office to the lab and make the config change to the server.

    And thus a new feature was born - by default, Lan Manager (and all MS networking products to this day) shares the root of the drives automatically to ensure that remote administrators have the ability to access the entire drive.   And we'd probably have never noticed it unless we were dogfooding our products.

    Nowadays, with RDP and other more enhanced remote administration tools, it's less critical, but there are a boatload of products that rely on the feature.

    Note1: You can disable the automatic creation of these shares by going to this KB article.

    Note2: The test lead for the Lan Manager product was a new hire, fresh from working at Intel who went by the name of Henry (Brian) Valentine.

  • Larry Osterman's WebLog

    Audio in Vista, the big picture


    So I've talked a bit about some of the details of the Vista audio architecture, but I figure a picture's worth a bunch of text, so here's a simple version of the audio architecture:

    This picture is for "shared" mode, I'll talk about exclusive mode in a future post.

    The picture looks complicated, but in reality it isn't.  There are a boatload of new constructs to discuss here, so bear with me a bit.

    The flow of audio samples through the audio engine is represented by the arrows - data flows from the application, to the right in this example.

    The first thing to notice is that once the audio leaves the application, it flows through a very simple graph - the topology is quite straightforward, but it's a graph nonetheless, and I tend to refer to samples as moving through the graph.

    Starting from the left, the audio system introduces the concept of an "audio session".  An audio session is essentially a container for audio streams, in general there is only one session per process, although this isn't strictly true.

    Next, we have the application that's playing audio.  The application (using WASAPI) renders audio to a "Cross Process Transport".  The CPT's job is to get the audio samples to the audio engine running in the Windows Audio service.

    In general, the terminal nodes in the graph are transports, there are three transports that ship with Vista, the cross process transport I mentioned above, a "Kernel Streaming" transport (used for rendering audio to a local audio adapter), and an "RDP Transport" (used for rendering audio over a Remote Desktop Connection). 


    • Volume - The volume APO provides mute and gain control.
    • Format Conversion - The format converter APOs (there are several) provide data format conversion - int to float32, float32 to int, etc.
    • Mixer - The mixer APO mixes multiple audio streams
    • Meter - The meter APO remembers the peak and RMS values of the audio samples pumped through it.
    • Limiter - The limiter APO prevents audio samples from clipping when rendering.


  • Larry Osterman's WebLog
















    Edit: To fix the title which somehow got messed up.


  • Larry Osterman's WebLog

    How do I open ports in the Windows Firewall?










    Tomorrow: How do we get the INetSharingConfiguration?

    Edit: Clarified IP addresses used for WMC after further investigation.

    Edit: Updated link


  • Larry Osterman's WebLog

    Breaking Up (shared services) Is(n't) Hard To Do

    The last time I wrote, I talked about shared services. One of the problems of working with shared services is that sometimes one service in the process gets in the way of other services.

    For the audio service, it lives in the "networking services" service host (because the networking services svchost is used for all services that run as LocalSystem).  But, because it runs in the same process as the networking functionality, it means that it can be quite difficult to debug the audio service, especially if you're using a source level debugger - if your debugger has to talk to the network, and portions of the networking stack are suspended (by the debugger) it can be hard to make things work...

    It turns out that there's a remarkably clever trick that can be used to split a normally shared service into its own process. 

    From a Windows command prompt, simply type:

    C:\>sc config <servicename> type= own

    To move the service back into its normal shared config, type:

    C:\>sc config <servicename> type= share

    The SC tool should be in the system32 directory on all XP installations, if not, it's in the platform SDK (I believe), and obviously you need to be an administrator to make this work.

    I can't take credit for this, it was shown to me by one of the NT perf guys, but I like it sufficiently that it's worth sharing.


    One more caveat: Before people start trying this on their XP system, please note that there's a reason that those services are in the same process.  Splitting them up will cause your system to use a LOT more memory, and WILL make your system unstable.  I'm posting this trick because it can be quite useful for people who are developing their own shared services.

    Several of the built-in services assume that they're in the same address space as other services, and if they start running in separate processes, they will crash in strange and mysterious ways, if you're not careful, you can render your machine unbootable.

    Just don't go there, it wouldn't be prudent.

  • Larry Osterman's WebLog

    Mirra, first impressions


    We've currently got something like 7 computers currently in use in my house these days, and I've been looking for a centralized backup solution for the home for a while.

    Eventually, I settled on a Mirra - a small form-factor appliance-like backup server.  It comes in four sizes, 80GB, 160GB, 250GB, and 400GB.  I ordered the 400GB based on the amount of stuff we've got saved on the various machines that will have to be backed up.

    I've not yet had a chance to use all the features of the product (in particular, I've not used the remote access functionality), but I  did set it up and get it running on two of the machines over the weekend.

    I have to say that I'm impressed.  IMHO, these guys have been taking lessons from Apple in terms of out-of-box experience (Personally, I think that Apple does OOBE better than any other PC hardware company).

    You open the Mirra box, and you see a cardboard inset, with a folded card-stock flyer and the power cord and an ethernet cord.

    On the cover of the flyer, are the words "Welcome to Mirra".  You open it up, and it unfolds into a four page story telling you that you're about to enter into a new world where you don't have to worry about your data.  On the back of each of the four pages is one of the four steps to setting up the Mirra - the first tab has you plugging in the appliance (you need to plug it into AC and into an ethernet port), the second tab has you installing the software on your PC, the third has you configuring the PC, the fourth is "Relax".

    I LOVED this experience - it's exactly the balance that computer-related appliance should strike - simple instructions, clearly spelled out, easy for Abby to get right.  The actual Mirra device is a small form-factor PC, I didn't crack the case to see what was running inside it, but it's got video, keyboard, mouse, and USB ports on the case (the video and USB are covered over with plastic).  The small form-factor PC is perfect for "plug it in and forget about it".

    I had some difficulties getting the software installed on the first machine I tried, it didn't recognize the firewall I was running (Microsoft One-Care Beta1), and I had to manually configure it.  On the other hand, the manufacturers web site was extremely helpful getting past this hurdle, and once set up, it immediately started copying files.

    I next went to each of the four accounts on that machine and set the software up on each of them.  It worked seamlessly for all four accounts, including all the limited user accounts.  This alone impressed the heck out of me - there aren't that many software products out there that consider the FUS (fast user switching) and LUA scenarios, but clearly the Mirra guys had.

    I then went upstairs to my computer, and installed it.  This machine doesn't have One-Care installed on it, and the Mirra detected the XP SP2 firewall and opened the relevant ports in the firewall (the firewall is enabled and I didn't need to do anything about it).  The machine then started hammering our home network copying off all the files on the machine.

    I still need to get it installed on the kids computers, that'll be interesting since the kids computers don't have access to the internet.

    The Mirra backup software runs as two services, running in two processes (I'm not sure why, since both services run at localsystem).  However, once configured, the Mirra backup software will run without requiring any process in the user's session.  If I was doing it, I'd have used just one process to run both services, but...

    As I commented to Valorie "This is the software I would have designed".  I was utterly impressed that they seem to have nailed several critical scenarios that are usually overlooked.

    One negative (not relevant to me, but probably to others) is that this is a Windows-only product - they don't seem to have Mac or Linux clients.

    In general, though, I'm pretty impressed.


  • Larry Osterman's WebLog

    APIs you never heard of - the Timer APIs


    It's time for another "APIs you never heard of" article :)

    This time, I'd like to talk about the time* APIs.

    The time* APIs are a set of 7 APIs built into the windows multimedia extensions (winmm.dll).  They provide a rudimentary set of timer functions for Windows applications.  At this point, except for two of the APIs, they exist only for historical purposes, the core OS now provides significantly higher quality APIs for timers.

    The time APIs fall into three rough categories:

    1. Timer information (timeGetDevCaps, timeGetTime and timeGetSystemTime)
    2. Timer callback functions (timeSetEvent and timeKillEvent)
    3. Timer frequency functions (timeBeginPeriod and timeEndPeriod)

    The first two categories are obsolete (arguably timeGetDevCaps still has valid uses).  The timeGetTime API is effectively identical to the GetTickCount() API, and timeGetSystemTime simply returns the exact same value that timeGetTime would have returned, packed into a MMTIME structure. 

    The timeSetEvent and timeKillEvent have been replaced with the Win32 Timer Queue functions, I'm not sure if I know of any reason to ever call the MME versions of these functions :).  In fact, timeSetEvent will call PulseEvent API, which is fundamentally flawed.  There is one difference between timeSetEvent and the Win32 timer queue functions - timeSetEvent will call timeBeginPeriod to set the timer resolution to the resolution specified in the call to timeSetEvent.  Even with this, you're better off calling timeBeginPeriod and using the Win32 Timer Queue functions (because the Win32 timer queue functions are far more flexible). 

    But then there's the timeBeginPeriod and timeEndPeriod APIs.  These are actually fun APIs, especially in the multimedia or gaming space, because they allow you to change the resolution of the internal scheduler, which can lower (or raise) the resolution with which the internal clock runs.

    This has a number of side effects - it increases the responsiveness of the system to periodic events (when event timeouts occur at a higher resolution, they expire closer to their intended time).  But that increased responsiveness comes at a cost - since the system scheduler is running more often, the system spends more time scheduling tasks, context switching, etc.  This can ultimately reduce overall system performance, since every clock cycle the system is processing "system stuff" is a clock cycle that isn't being spent running your application.  For some multimedia applications (video, for example) the increased system responsiveness is worth the system overhead (for instance, if you're interested in very low latency audio or video, you need the system timers to run at a high frequency).

    Edit: Added comment about timeSetEvent calling timeBeginPeriod to set the resolution.\

    Edit2 (years later): Updated the link to GetTickCount...

  • Larry Osterman's WebLog

    How do I divide fractions?


    Valorie works as a teacher's aid in a 6th grade classroom at a local elementary school.

    They've been working on dividing fractions recently, and she spent about two hours yesterday working with one student trying to explain exactly how division of fractions works.

    So I figured I'd toss it out to the blogsphere to see what people's answers are.  How do you explain to a 6th grader that 1/2 divided by 1/4 is 2? 

    Please note that it's not sufficient to say: Division is the same as multiplication by the inverse, so when you divide two fractions, you take the second one, invert it, and multiply.  That's stating division of fractions as an axiom, and not a reason.

    In this case in particular, the teacher wants the students to be able to graphically show how it works.

    I can do this with addition and subtraction of numbers (both positive and negative) using positions on a number line. Similarly, I can do multiplication of fractions graphically - you have a whole, divide it into 2 halves.  When you multiply the half by a quarter, you are quartering the half, so you take the half, divide it into fours, and one of those fours is the answer.

    But how do you do this for division?

    My wife had to type this part because we have a bit of, um, discussion, about how simple this part is....

    How can you explain to 9-11 year old kids why you multiply by the reciprocal without resorting to the axiom? It's easy to show graphically that 1/2 divided by 1/4 is 2 quarters because the kids can see that there are two quarters in one half. Equally so, the kids can understand that 1/4 divided by 1/2 is 1/2 of a half because the kids can see that only half of the half is covered by the original quarter. The problem comes in when their intuition goes out.  They can solve it mathematically, but the teacher is unwilling to have them do the harder problems “on faith“ and the drawing is really confusing the kids. Having tried to draw the 5/8 divided by 3/10, I can assure you, it is quite challenging. And no, the teacher is not willing to keep the problems easy. And no, don't get me started on that aspect of this issue.

    I'm a big fan that if one method of instruction isn't working, I try to find another way to explain the concept. I visited my usual math sites and found that most people don't try to graph this stuff until 10th grade or adulthood. Most of the sites have just had this “go on faith“ response (show the kids the easy ones, and let them “go on faith“ that it will hold true for all cases). I really wish I could figure out a way to show successive subtraction, but even that gets difficult on the more complicated examples.

    What I am hoping is that someone out there can provide me with the “aha!“ I need to come up with a few more ways to explain this. What this has been teaching me is that I've been doing this “on faith“ most of my life and never stopped to think about why myself.

    Any ideas/suggestions would be much appreciated.


  • Larry Osterman's WebLog



    In my previous post about OCA, the comments thread has a long discussion started by Shannon J Hager about Mozilla’s behavior when you attempt to access  If you attempt to access this web site using Firefox (or other Mozilla variants), you get the following dialog box:






    $ openssl s_client -connect -showcerts

    verify error:num=20:unable to get local issuer certificate
    verify return:1
    verify error:num=27:certificate not trusted
    verify return:1
    verify error:num=21:unable to verify the first certificate
    verify return:1
    Certificate chain
    -----END CERTIFICATE-----
    Server certificate
    No client certificate CA names sent
    SSL handshake has read 1444 bytes and written 324 bytes
    New, TLSv1/SSLv3, Cipher is RC4-MD5
    Server public key is 1024 bit
    Protocol : TLSv1
    Cipher : RC4-MD5
    Session-ID: [...]
    Master-Key: [...]
    Key-Arg : None
    Start Time: [...]
    Timeout : 300 (sec)


    Authority Information Access:
    CA Issuers - URI:





    Inside the Microsoft certificate is the following:







    Edit: Fixed picture links.

    Edit2: Fixed line wrapping of reference from RFC2459.

  • Larry Osterman's WebLog

    Transfering a pointer across processes

    I seem to be "Riffing on Raymond" more and more these days, I'm not sure why, but..

    Raymond Chen's post today on the type model for Win64 got me to thinking about one comment he made in particular:


    Actually, there IS a really good reason for sharing handles across processes.  And the Win64 team realized that and built it into the product (both the base team and the RPC team).  Sometimes you want to allocate a handle in one process, but use that handle in another.  The most common case where this occurs is inheritance - when you allocate an inheritable handle in one process, then spawn a child process, that handle is created in the child process as well.  So if a WIn64 process spawns a Win32 process, all the inheritable handles in the Win64 process will be duplicated into the Win32 process.

    In addition, there are sometimes reasons why you'd want to duplicate a handle from your process into another process.  This is why the DuplicateHandle API has an hTargetProcessHandle parameter.  One example of this is if you want to use a shared memory region between two processes.  One way of doing this would be to use a named shared memory region, and have the client open it.  But another is to have one process open the shared memory region, duplicate the handle to the shared memory region into the other process, then tell the other process about the new handle.

    In both of these cases (inheritable handles and DuplicateHandle), if the source process is a 64bit process and the target process is a 32bit process, then the resulting handle is appropriately sized to work in the 32bit process (the reverse also holds, of course)

    So we've established that there might be a reason to move a handle from one process to another.  And now, the RPC team's part of the solution comes into play.

    RPC (and by proxy DCOM) defines a data type call __int32644.  An int3264 is functionally equivalent to the Win32 DWORD_PTR (and, in fact, the DWORD_PTR type is declared as an __int3264 when compiled for MIDL).

    An __int3264 value is an integer that's large enough to hold a pointer on the current platform.  For Win32, it's a 32 bit value, for Win64, it's a 64 bit value.  When you pass an __int3264 value from one process to another it either gets truncated or extended (either signed or unsigned)..

    __int3264 values are passed on the wire as 32bit quantities (for backwards compatibility reasons).

    So you can allocate a block of shared memory in one process, force dup the handle into another process, and return that new handle to the client in an RPC call.  And it all happens automagically.

    Btw, one caveat: In the current platform SDK, the HANDLE_PTR type is NOT RPC'able across byte sizes - it's a 32bit value on 32bit platforms and a 64bit value on 64bit platforms, and it does NOT change size (like DWORD_PTR values do).  The SDK documentation on process interoperability is mostly correct, but somewhat misleading in this aspect. It says "The 64-bit HANDLE_PTR is 64 bytes on the wire (not truncated) and thus does not need mapping" - I'm not going to discuss the "64 bytes on the wire" part, but most importantly it doesn't indicate that the 32-bit HANDLE_PTR is 32 bits on the wire.

    Edit: Removed HTML error that was disabling comments...


  • Larry Osterman's WebLog

    How to lose customers without really trying...


    Not surprisingly, Valorie and I both do some of our holiday season shopping at ThinkGeek.  But no longer.  Valorie recently placed a substantial order with them, but Instead of processing her order, they sent the following email:

    From: ThinkGeek Customer Service []
    Sent: Thursday, November 15, 2007 4:28 AM
    To: <Valorie's Email Address>
    Subject: URGENT - Information Needed to Complete Your ThinkGeek Order

    Hi Valorie,

    Thank you for your recent order with ThinkGeek, <order number>. We would like to process your order as soon as possible, but we need some additional information in order to complete your order.

    To complete your order, we must do a manual billing address verification check.

    If you paid for your order via Paypal, please send us a phone bill or other utility bill showing the same billing address that was entered on your order.

    If you paid for your order via credit card, please send us one of the following:

    - A phone bill or other utility bill showing the same billing address that was entered on your order

    - A credit card statement with your billing address and last four digits of your credit card displayed

    - A copy of your credit card with last four digits displayed AND a copy of a government-issued photo ID, such as a driver's license or passport.

    To send these via e-mail (a scan or legible digital photo) please reply to or via fax (703-839-8611) at your earliest convenience. If you send your documentation as digital images via email, please make sure they total less than 500kb in size or we may not receive your email. We ask that you send this verification within the next two weeks, or your order may be canceled. Also, we are unable to accept billing address verification from customers over the phone. We must receive the requested documentation before your order can be processed and shipped out.

    For the security-minded among you, we are able to accept PGP-encrypted emails. It is not mandatory to encrypt your response, so if you have no idea what we're talking about, don't sweat it. Further information, including our public key and fingerprint, can be found at the following


    At ThinkGeek we take your security and privacy very seriously. We hope you understand that when we have to take extra security measures such as this, we do it to protect you as well as ThinkGeek.

    We apologize for any inconvenience this may cause, and we appreciate your understanding. If you have any questions, please feel free to email or call us at the number below.


    ThinkGeek Customer Service

    1-888-433-5788 (phone)

    1-703-839-8611 (fax)

    Wow.  We've ordered from them in the past (and placed other large orders with them), but we've never seen anything as outrageous as this.  They're asking for exactly the kind information that would be necessary to perpetuate an identity theft of Valorie's identity, and they're holding our order hostage if we don't comply.

    What was worse is that their order form didn't even ask for the CVE code on the back of the credit card (the one that's not imprinted).  So not only didn't they follow the "standard" practices that most e-commerce sites follow when dealing with credit cards, but they felt it was necessary for us to provide exactly the kind of information that an identity thief would ask for.

    Valorie contacted them to let them know how she felt about it, and their response was:

    Thank you for your recent ThinkGeek order. Sometimes, when an order is placed with a discrepancy between the billing and the shipping addresses, or with a billing address outside the US, or the order is above a certain value, our ordering system will flag the transaction. In these circumstances, we request physical documentation of the billing address on the order in question, to make sure that the order has been placed by the account holder. At ThinkGeek we take your security and privacy very seriously. We hope you understand that when we have to take extra security measures such as this, we do it to protect you as well as ThinkGeek.
    Unfortunately, without this documentation, we are unable to complete the processing of your order. If we do not receive the requested documentation within two weeks of your initial order date, your order will automatically be cancelled. If you can't provide documentation of the billing address on your order, you will need to cancel your current order and reorder using the proper billing address for your credit card. Once we receive and process your documentation, you should not need to provide it on subsequent orders. Please let us know if you have any further questions.

    The good news is that we have absolutely no problems with them canceling the order, and we're never going to do business with them again.  There are plenty of other retailers out there that sell the same stuff that ThinkGeek does who are willing to accept our business without being offensive about it.


    Edit to add:  Think Geek responded to our issues, their latest response can be found here.

  • Larry Osterman's WebLog

    My office guest chair


    Adam writes about his office guest chair.


    1. A desk chair
    2. One PED (sort of a mobile filing cabinet)
    4. One short straight desk piece
    5. One long straight desk piece
    6. One white board
    7. One cork board
    9. One guest chair.








  • Larry Osterman's WebLog

    So you need a worker thread pool...




    class WorkItem
        LIST_ENTRY m_listEntry;

    class WorkerThreadPool
        HANDLE m_heventThreadPool;
        CRITICAL_SECTION m_critsThreadPool;
        LIST_ENTRY m_workItemQueue;

        void QueueWorkItem(WorkItem *pWorkItem)
            //   Insert the work item onto the work item queue.
            InsertTailList(&m_workItemQueue, pWorkItem->m_listEntry);
            //   Kick the worker thread pool
        void WorkItemThread()
            while (1)
                // Wait until we’ve got work to do
                WaitForSingleObject(&m_heventThreadPool, INFINITE);
                //  Remove the first item from the queue.
                workItem = RemoveHeadList(&m_workItemQueue);
                // Process the work item if there is one.
                if (workItem != NULL)
                    <Process Work Item>








    class WorkItem

    class WorkerThreadPool
        HANDLE m_hcompletionPort;

        void QueueWorkItem(WorkItem *pWorkItem)

        void WorkItemThread()
            while (1)
                // Process the work item if there is one.
                if (pWorkItem != NULL)
                    <Process Work Item>




  • Larry Osterman's WebLog

    New Audio APIs for Vista


    In an earlier post, I mentioned that we totally re-wrote the audio stack for Windows Vista.  Today I want to talk a bit about the APIs that came along with the new stack.

    There are three major API components to the Vista audio architecture:

    • Multimedia Device API (MMDEVAPI) - an API for enumerating and managing audio endpoints.
    • Device Topology - an API for discovering the internals of your audio card's topology.
    • Windows Audio Session API ((WASAPI) - the low level API for rendering audio.

    All the existing audio APIs have been re-plumbed to use these APIs internally, for Vista, all audio goes through these three APIs.  For the vast majority of the existing audio applications, things should "just work"...

    In general, we don't expect that anyone will move to these new APIs, they're documented for completeness reasons, but the reality is that unless you're dealing with extremely low latency audio (sub 20ms), or writing a control panel applet for a specific audio adapter, you're not likely to ever want to deal with them (the new APIs really are very low level APIs - using the higher level APIs is both easier and less error prone).


    MMDEVAPI is the entrypoint API - it's a COM class that allows applications to enumerate endpoints and "activate" interfaces on them.  Endpoints fall into two general types: Capture and Render (You can consider Capture endpionts as microphones and line in, Render endpoints are things like speakers).  MMDEVAPI also allows the user to manage defaults for each of the types. As I write this, are actually three different sets of defaults supported in Vista: "Console", "Multimedia", and "Communications".  "Console" is used for general purpose audio, "Multimedia" is intended for audio playback applications (media players, etc), and "Communications" is intended for voice communications (applications like Yahoo! Messenger, Microsoft Communicator, etc). 

    Windows XP had two sets of defaults (the "default" default and the "communications" default), we're adding a 3rd default type to enable multimedia playback.  Consider the following scenario.  I have a Media Center computer.  The SPDIF output from the audio adapter's connected to my home AV receiver, I have a USB headset that I want to use for VOIP, and there are stereo speakers connected to the machine that I use for day-to-day operations.  We want to enable applications to make intelligent choices when they choose which audio device to use - the default in this scenario is to use the desktop speakers, but we want to allow Communicator (or Messenger, or whatever) to use the headset, and Media Center to use the external receiver.  We may end up changing these sets before Vista ships, but this give a flavor of what we're thinking about.

    MMDEVAPI supports an "activation" design pattern - essentially, instead of calling a class factory to create a generic object, then binding the object to another object, with activation, you can enumerate objects (endpoints in this case) and "activate" an interface on that object.  It's a really convenient pattern when you have a set of objects that may or may not have the same type.

    Btw, you can access the category defaults using wave or mixer messages, this page from MSDN describes how to access them - the console default is accessed via DRVM_MAPPER_PREFERRED_GET and the communications default is accessed via DRVM_MAPPER_CONSOLEVOICECOM_GET.

    Device Topology:

    Personally, I don't believe that anyone will ever use Device Topology, except for audio hardware vendors who are writing custom control panel extensions.  It exists for control panel type applications that need to be able to determine information about the actual hardware. 

    Device Topology exposes collections of parts and the connections between those parts.  On any part, there are zero or more controls, which roughly correspond to the controls exposed by the audio driver.  One cool thing about device topologies is that topologies can connect to other topologies.  So in the future, it's possible that an application running on an RDP server may be able to enumerate and address the audio devices on the RDP client - instead of treating the client as an endpoint, the server might be able to enumerate the device topology on the RDP client and manipulate controls directly on the client.  Similarly, in the future, the hardware volume control for a SPDIF connector might manipulate the volume on an external AV receiver via an external control connection (1394 or S/LINK).

    One major change between XP and Vista is that Device Topology will never lie about the capabilities of the hardware - before Vista, if a piece of hardware didn't have a particular control the system tried to be helpful and provide controls that it thought ought to be there (for instance if a piece of hardware didn't have a volume control, the system helpfully added one).  For Vista, we're reporting exactly what the audio hardware reports, and nothing more.  This is a part of our philosophy of "don't mess with the user's audio streams if we don't have to" - emulating a hardware control when it's not necessary adds potentially unwanted DSP to the audio stream.

    Again, the vast majority of applications shouldn't need to use these controls, for most applications, the functionality provided by the primary APIs (mixerLine, wave, DSound, etc) are going to be more suitable for their needs.


    WASAPI is the "big kahuna" for the audio engine.  You activate WASAPI on an endpoint, and it provides functionality for rendering/capturing audio streams.  It also provides functions to manage the audio clock and manipulate the volume of the audio stream.

    In general, WASAPI operates in two modes.  In "shared" mode, audio streams are rendered by the application and mixed by the global audio engine before they're rendered out the audio device.  In "exclusive" mode, audio streams are rendered directly to the audio adapter, and no other application's audio will play.  Obviously the vast majority of applications will operate in shared mode, that's the default for the wave APIs and DSound.  One relatively common scenario that WILL use exclusive mode is rendering content that requires a codec that's present in the hardware that Windows doesn't understand.  A simple example of this is compressed AC3 audio rendered over a SPDIF connection - if you attempt to render this content, if Windows doesn't have a decoder for this content, then DSound will automatically initialize WASAPI in exclusive mode and will render the content directly to the hardware.

    If your application is a pro audio application, or is interested in extremely low latency audio then you probably want to consider using WASAPI, otherwise it's better to stick with the existing APIs.

    Tomorrow: Volume control (a subject that's near and dear to my heart) :)

  • Larry Osterman's WebLog

    Turning the blog around - End of Life issues.


    I'd like to turn the blog around again and ask you all a question about end-of-life issues.

    And no, it's got nothing to do with Terry Schaivo.

    Huge amounts of text have been written about Microsoft's commitment to platform stability.

    But platform stability comes with an engineering cost.  It gets expensive maintaining old code - typically it's not written to modern coding standards, the longer that it exists, the more heavily patched it becomes, etc.

    For some code that's sufficiently old, the amount of engineering that's needed to move the code to a new platform can become prohibitively expensive (think about what would be involved in porting code originally written for MS-DOS to a 128bit platform).

    So for every API, the older it gets, the more the temptation exists to find a way of ending its viable lifetime.

    On the other hand, you absolutely can't break applications.  And not just the applications that are commercially available - If a customer's line-of-business application fails because you decided to remove an API, you're going to have to put the API back.

    So here's my question: Under what circumstances is it ok to remove an API from the operating system?  Must you carry them on forever?

    This isn't just a Microsoft question.  It's a platform engineering problem - if you're committed to a stable platform (in other words, on your platform, you're not going to break existing applications on a new version of the platform), then you're going to have to face these issues.

    I have some opinions on this (no, really?) but I want to hear from you folks before I spout off on them.

  • Larry Osterman's WebLog


    Another one from someone sending a comment:

    I came across your blog and was wondering if what to do when encountering above error message in an application program.

    The error occurs once in a while when printing out from a Windows application.

    Is there some setting missing in computer administration or in the Registry or can it only be solved in the code?

    Appreciate your help!

    Yech.  This one's ugly.  It's time for Raymond's Psychic Powers(tm) of detection.

    If you take the error message text and look inside winerror.h, you'll see that the error message mentioned is exactly the text for the RPC_E_WRONG_THREAD error.

    If you then do an MSDN search for RPC_E_WRONG_THREAD, the first hit is: "INFO: Explanation of RPC_E_WRONG_THREAD Error".  Essentially, the error's a side effect of messing up threading models.  I wrote about them about 18 months ago in "What are these threading models, and why do I care?". 

    So, knowing that the app's dutifully reporting RPC_E_WRONG_THREAD to the user, what had to have happened to cause this error?

    It means that the application did a CoCreateInstance of an Single Threaded Apartment COM object in one thread, but used it in another thread.

    Given the comment that it only happens once in a while, we can further deduce that the application called CoCreateInstance from a thread in a pool of worker threads, and attempted to use it in a function queued to that pool of threads (otherwise it would fail all the time and the author of the app would have found the problem).  Given that it only happens when printing (an operation that's usually handled in a background thread), this makes sense.

    Unfortunately for the person who asked the question, they don't really have any choice but to contact the vendor that created the app and hope that they have an update that fixes the problem, because there's no workaround you can do outside the app :(

  • Larry Osterman's WebLog

    What's wrong with this code, part 10

    Ok, time for another "what's wrong with this code".  This one's trivial from a code standpoint, but it's tricky...

    // Function:
    // CThing1::OnSomethingHappening()
    // Description:
    // Called when something happens
    // Return:
    // S_OK if successful
    HRESULT CThing1::OnSomethingHappening()
        HRESULT hr;

        <Do Some Stuff>
        // Perform some operation...
        hr = PerformAnOperation();
        if (FAILED(hr))
            hr = ERROR_NOT_SUPPORTED;
        IF_FAILED_JUMP(hr, Error);

        return hr;

        goto Exit;

    Not much code, no?  So what's wrong with it?

    As usual, answers and kudos tomorrow.

  • Larry Osterman's WebLog



    This one’s likely to get a bit controversial J.





    The problem is that this idea falls apart in reality.



    My app pops up a dialog box with the following:


                Plsae enter you password:  _______________ 


    Where the edit control is misaligned with the text.

















    Edit: To remove extra <p> tags :(

  • Larry Osterman's WebLog

    Choosing a C runtime library









    There are LOTS of reasons for always using the multithreaded DLL:


















  • Larry Osterman's WebLog

    Why add a throw() to your methods?



    class MyClass
        size_t CalculateFoo()
        size_t MethodThatCannotThrow()
    return 100;
    void ExampleMethod()
            size_t foo, bar;
                foo = CalculateFoo();
                bar = foo * 100;
    "bar is %d", bar);
            catch (...)




  • Larry Osterman's WebLog

    Should I check the parameters to my function?


    I just had an interesting discussion with one of the testers in my group.

    He had just finished filing a series of bugs against our components because they weren’t failing when he passed bogus pointers to the API.  Instead, they raised a 0xC0000005 exception and crashed his application.

    The APIs did fail if he passed a null pointer in, with E_POINTER. 

    But he felt that the API should check all the bogus pointers passed in and fail with E_POINTER if the pointer passed in didn’t point to valid memory.

    This has been a subject of a lot of ongoing discussion over the years internally here at Microsoft.  There are two schools of thought:

    School one says “We shouldn’t crash the application on bogus data.  Crashing is bad.  So we should check our parameters and return error codes if they’re bogus”.

    School two says “GIGO – if the app hands us garbage, then big deal if it crashes”.

    I’m firmly in the second camp (not surprisingly, if you know me).  There are a lot of reasons for this.  The biggest one is security.  The way you check for bad pointers on Win32 is by calling the IsBadReadPtr and IsBadWritePtr API.  Michael Howard calls these APIs “CrashMyApplication” and “CorruptMemoryAndCrashMySystem” respectively.  The problem with IsBadReadPtr/IsBadWritePtr is that they do exactly what they’re advertised as doing:  They read and/or write to the memory location specified, with an exception handler wrapped around the read/write.  If an exception is thrown, they fail, if not, they succeed.

    There are two problems with this.  The only thing that IsBadReadPtr/IsBadWritePtr verifies is that at the instant that the API is called, there was valid memory at that location.  There’s nothing to prevent another thread in the application from unmapping the virtual address passed into IsBadReadPtr immediately after the call is made.  Which means that any error checks you made based on the results of this API aren’t valid (this is called out in the documentation for IsBadWritePtr/IsBadReadPtr).

    The other one is worse.  What happens if the memory address passed into IsBadReadPtr is a stack guard page (a guard page is a page kept at the bottom of the stack – when the system top level exception handler sees a fault on a guard page, it will grow the threads stack (up to the threads stack limit))?  Well, the IsBadReadPtr will catch the guard page exception and will handle it (because IsBadReadPtr handles all exceptions).  So the system exception handler doesn’t see the exception.  Which means that when that thread later runs, its stack won’t grow past the current limit.  By calling IsBadReadPtr in your API, you’ve turned an easily identifiable application bug into a really subtle stack overflow bug that may not be encountered for many minutes (or hours) later.

    The other problem with aggressively checking for bad parameters on an API is that what happens if the app doesn’t check the return code from the API?  This means that they could easily have a bug in their code that passes a bogus pointer into IsBadWritePtr, thus corrupting memory.  But, since they didn’t check the return code, they don’t know about their bug.  And, again, much later the heap corruption bug that’s caused by the call to IsBadWritePtr shows up.  If the API had crashed, then they’d find the problem right away.

    Now, having said all this, if you go with school two, you’ve still got a problem – you can’t trust the user’s buffers.  At all.  This means you’ve got to be careful when touching those buffers to ensure that you’re not going to deadlock the process by (for instance holding onto a critical section while writing to the user’s buffer).

    The other thing to keep in mind is that there are some situations where it’s NOT a good idea to crash the user’s app.  For example, if you’re using RPC, then RPC uses structured exception handling to communicate RPC errors back to the application (as opposed to API return codes).  So sometimes you have no choice but to catch the exceptions and return them.  The other case is if someone has written and shipped an existing API that uses IsBadReadPtr to check for bad pointers on input, it may not be possible to remove this because there may be applications that depend on this behavior.

    So in general, it’s a bad idea to use IsBadXxxPtr on your input parameters to check for correctness.  Your users may curse you for crashing their app when they screw up, but in the long term, it’s a better idea.

  • Larry Osterman's WebLog

    Threat Modeling, part 1



















    Edit2: Corrected possesive on Dana Epp's name :)

  • Larry Osterman's WebLog

    Running Non Admin














    Edit: Thanks Mike :)
Page 2 of 33 (815 items) 12345»