How do I test that return value of ShellExecute against 32?


We discussed earlier the history behind the the return value of the ShellExecute function, and why its value in Win32 is meaningless aside from testing it against the value 32 to determine whether an error occurred.

How, then, should you check for errors?

Let's turn the question around. How would you, the implementor of the ShellExecute function, report success? The ShellExecute is a very popular function, so you have to prepared for the ways people check the return code incorrectly yet manage to work in spite of themselves. The goal, therefore, is to report success in a manner that breaks as few programs as possible.

(Now, there may be those of you who say, "Hang compatibility. If programs checked the return value incorrectly, then they deserve to stop working!" If you choose to go in that direction, then be prepared for the deluge of compatibility bugs to be assigned to you to fix. And they're going to come from a grumpy compatibility testing team because they will have spent a long time just finding out that the problem was that the program was checking the return value of ShellExecute incorrectly.)

Since there is still 16-bit code out there that may thunk up to 32-bit code, you probably don't want to return a value greater than 0xFFFF. Otherwise, when that value gets truncated to a 16-bit HINSTANCE will lose the high word. If you returned a value like 0x00010001, this would truncate to 0x0001, which would be treated as an error code.

For similar reasons, the 64-bit implementation of the ShellExecute function had better not use the upper 32 bits of the return value. Code that casts the return value to int will lose the high 32 bits.

Furthermore, you shouldn't return a value that, when cast to an integer, results in a negative number. Some people will use a signed comparison against 32; others will use an unsigned comparison. If you returned a value like -5, then the people who used a signed comparison would think the function failed, whereas those who used an unsigned comparison would think it succeeded.

By the same logic, the value you choose as the return value should not result in a negative number when cast to a 16-bit integer. If the return value is passed to a 16-bit caller that casts the result to an integer and compares against 32, you want consistent results independent of whether the 16-bit caller used a signed or unsigned comparison.

Edge conditions are tricky, so you don't want to return the value 32 exactly. If you look at code that checks the return value from ShellExecute, you'll probably find that the world is split as to whether 32 is an error code or not. So it'd be in your best interest not to return the value 32 exactly but rather a value larger than 32.

So far, you're constrained to choosing a value in the range 33–32767.

Finally, you might be a fan of Douglas Adams. (Most geeks are.) The all-important number 42 fits into this range. Your choice of return value, therefore, might be (HINSTANCE)42.

Going back to the original question: How should I check the return value of ShellExecute for errors? MSDN says you can cast the result to an integer and compare the result against 32. That'll work fine. You could cast in the other direction, comparing the return value against (HINSTANCE)32. That'll work fine, too. Or you could cast the result to an INT_PTR and compare the result against 32. That's fine, too. They'll all work, because the implementor of the ShellExecute function had to plan ahead for you and all the other people who call the ShellExecute function.

Comments (39)
  1. Neal says:

    You know, I’m beginning to think Microsoft needs to add one more thing to it’s logo requirements.  That would be a clause forcing companies to patch any discovered incompatibilities of these (assorted and frequently mentioned here )natures in their software or face financial penalties and/or loss of logo rights in ALL their software.  It should also asign Microsoft rights to patch their software should they refuse or should it be orphaned.  

    I think that the most popular programs are the most likely, if not only, ones Microsoft has to include shims and other workarounds for and that those are most likely to be logo compliant.  Any time Microsoft’s compatibility testing team traced a common problem back to such a bug they’d at least have the legal options of pulling logos or patching the software rather than teaking the os.

  2. Lewis says:

    You are assuming that all of the important programs for an enterprise are "logo-ized". I’ll bet you that most of the internally developed, mission critical, applications that are out there AREN’T logo-certified, nor would the company care about that, because writing "logo-ized" apps isn’t their core business.

    However, if the perception is that upgrading to version X of the OS breaks all of the mission critical applications, half of which they can’t change because the consultants caught fire in a team-building "walking on hot coals" disaster, then the enterprise ain’t likely to want to buy version X.

  3. Peter Ritchie says:

    +1 for expanded logo requirements (not that every single program goes through certification…).

    When will we learn that overriding a function is bad; just retire/obsolete it if it no longer can accomodate what it needs to do and create a new one!  Doing that might force designers to think ahead a little more about things like future integer sizes, etc.

  4. Steve says:

    I can see the headlines now "MS EXPOSES SEC HOLES WHEN PATCHING WIDGET-TECH’S PERVASIVE YET CRUMMY APP". The only reason MS patches the OS to accommodate the crummy apps is so that they can sell more copies of the OS, not because of some altruistic need to heal the afflicted.

    Then there is the legal aspect of this idea. There is no freaking way MS could take on this responsibility. For one thing they already struggle patching their own apps would you really want them responsible for doing binary patches on 3rd party apps? I don’t.

    Another flaw in this great plan is that MS is in the business of selling the OS, not being a the coding police. If you write crappy code eventually people will figure that out and avoid your products and if they don’t then they deserve what they get.

  5. Tom says:

    I think you’re missing the poster’s point Lewis.  

    No, you wouldn’t assume that internally developed mission critical applications out there are "logo-ized," but how many of those does Microsoft shim and patch the OS for?  Few, if any?  

    It’s the big boys in widespread use that cause most of the tweaks, fixes, shims, and work-arounds on Microsoft’s part.  Right now the most Microsoft can do is notify the software makers and hope they fix it or patch the OS over and over to maintain compatibility.  They’re most often forced into the latter.

    Since Microsoft has already gone through the trouble of discovering where and what the cause of the error is, wouldn’t you much rather they have the legal right to patch the offending software or theaten loss of logo than patch and shim the OS.  Patching the OS to maintain compatibility with misbehaving apps is largely to blame for many of Windows’ shortcomings today.

    Let me point out that a companie’s enterprise, or perhaps I should say enterprisy, app can break because Microsoft is forced to change something to maintain compatibility with BigBoyApp(TM) too.

  6. Neal says:

    Steve, I doubt Microsoft would patch much software, but I would like them to have the option.  Even moreso I’d like them to have a way to pressure vendors of buggy software into fixing it.

    As far as your sensationalist headlines go, I think (hope) most developers reading Raymond’s blog are bright enough to realize I’m talking about patching programs to fix little things like checks of the return values of ShellExecute, Windows version numbers, etc..  You know, the stuff Microsoft is already forced to rig and patch but from their end instead.

  7. It’s funny how that number 42 crops up in Microsoft’s software. For example, in 16-bit Windows, rebooting was done by passing 42 (in hex, of course) to ExitWindows. (http://support.microsoft.com/kb/142820)

    Rgrds Henry

  8. Chris says:

    Raymond:

    (a) for the ignorant such as myself: why the heck doesn’t ShellExecute return zero on success in the first place?

    (b) why the heck don’t you guys, when making new ABIs such as 64-bit, insert a translation layer capable of fixing the sins of the past? I.E., when people recompile for 64-bit, they get the new, more strict behavior, but old 32-bit code doesn’t break because the 32-bit version preserves the compatibility hacks? I would think it’d be in your interest to clean things up, and ABI changes are your only real chance given your software architecture.

    [I already answered these questions. (a) and (b). -Raymond]
  9. Bilbo says:

    There’s the bug in Windows – they were handed the answer to the ultimate question of life, the universe, and everything, and they messed it up by keying it as a hex 42.

  10. Daev says:

    Some day it would be nice to see a Raymond post about crafting a good design, in the context of backward compatibility for a huge developer base, whose comments don’t immediately descend into claims that Windows is “bloated” and “hacky” because Microsoft can’t start with a blank slate.  I think there’s a big mistaken assumption being made here.

    Yes, it’s harder to pick an error return code when you have to pay attention to constraints.  It’s harder to write strict-meter poetry than free verse, too, but that doesn’t make it automatically worse.

    I’d want to see some hard data:  how much of Windows’ “bloat,” how much of its day-to-day instability, is due to code mandated for backwards compatibility with external programs that don’t play by today’s rules?

    [I find it amazing that people consider “return 42″ bloat. You have to return something. It’s not like you can save two bytes by deleting the “return” statement. -Raymond]
  11. Cody says:

    I say we mandate that 42 be the official successful return code for all functions that return an integer.  Then we can cast Integers to a new Boolean type with the values true, false and The Answer.

  12. Igor says:

    Raymond, he didn’t mean bloated because of return code. He meant because of all that legacy compat junk you kkep dragging around with you.

    >The goal, therefore, is to report success in a manner that breaks as few programs as possible.

    How about simple TRUE or FALSE?

    I mean, wasn’t there already a discussion about bad things happening because of another function which returns 3 different types of return value (has to do with add/rem programs applet and app icons)?!?

    Why don’t you return additional value through a pointer if needed?

    BOOL ShellExecute(HINSTANCE *hinstPtr,…)

    What happened with GetLastError()?!?

    Why not:

    if (!ShellExecute(&hinstPtr, …) {

       DWORD crap = GetLastError();

    }

    I am amazed why you still haven’t overhauled all APIs and deprecated all functions which use multiple different return values because they always create problems when people misunderstand them or when you have to port to next larger integer size.

    IMO, you are making your job harder intentionally by bad design. So, go and tell everyone “returning things other than TRUE and FALSE from non-computational function is a NO-NO” and move on.

    [Again, I already explained why ShellExecute returns an HINSTANCE. If you want a function that returns a BOOL and an output pointer, use ShellExecuteEx. -Raymond]
  13. Elijah says:

    You know, I’m tired of actually reading the documentation and trying to get it right when MS bends over backwards to help the monkeys who don’t care.

    Seeing as MS appear to preserve back-compat at all costs – even when it conflicts with posted documentation (the MSDN docs say that the *ONLY* thing you can do with the HINSTANCE returned by ShellExecute is cast it to an int and compare against 32, or against a few individual error codes, despite what you claim) – and will apparently happily keep their end limping along to support me from now ’til eternity no matter what manner of lunacy I attempt, I’m going to take them up on it.

    From now on, I’ll take the current implementation as the authoritative source on what is supposed to work and what isn’t. From now on, I won’t bother reading the documentation to e.g. find out whether I’m supposed to be able to pass NULL (or null for .NET) into a function. From now on, I’ll invalidate the NULL window occasionally just for the heck of it. From now on I’ll crawl up the stack and poke around there – knowing which function you’ve been called might allow me to do some “interesting” optimisations. If it works on my machine, that’s it.

    I fully expect my productivity to soar past that of my colleagues who have already learned this lesson and do not spend their precious time reading the documentation.

    I’m sick of trying to do the right thing and basically being told “yeah, but you needn’t have bothered, we’ve set the wrong thing in stone too.”

    If MS are going to reward (or at least not punish) this kind of behaviour, they shouldn’t be surprised or complain when devs start exhibiting it.

    [Where did I ever claim that you could do anything other than compare the result with 32 (and specific error codes)? -Raymond]
  14. steveg says:

    I’m constantly surprised by IT people saying "Make it better, don’t worry about how it will affect people." Every thing you do in IT has a potential downstream impact, even if it has a workaround.

    Imagine the worldwide cost in $ or hours if something as seemingly innocuous as ShellExecute’s behaviour changed. What if BestSellingApp relied on it — all of a sudden millions of users of BSA can no longer do their jobs?

    How often has the IT dept where you work suddenly decided to change something only to have critical apps like email go down for several hours? Or scheduled updates during business hours? Always think about the consequences of what you’re doing.

    When the reason is good enough, things can (and should change) but geeky cleanliness/perfectionism is not enough to convince many companies they need to spend millions of their currency units for absolutely nothing.

    WRT to ShellExecute or any function that has a preferred alternative, I’d start adding some #pragma PreferredAlternative(ShellExecuteEx) into the SDK so the messages show up at compiler time — at least future errors will be reduced over time.

    BTW how forward thinking is MS: is Win128 a consideration for the Win64 folk?

  15. Elijah says:

    “You could cast in the other direction, comparing the return value against (HINSTANCE)32. That’ll work fine, too. Or you could cast the result to an INT_PTR and compare the result against 32. That’s fine, too.”

    It says you *must* cast to an *int* and compare that way.[0]

    Therefore, any value that, when cast to an int and is less than or equal to 32, is an error. Including values that cast to negative ints.

    That’s the definition! That’s what the docs say!

    Casting the result to unsigned types (like INT_PTR) explicitly breaks this. If HINSTANCEs are/can be unsigned types (I don’t know whether this is defined or not, and the ShellExecute docs don’t have link to the HINSTANCE definition) then *not* casting the result and comparing to an unsigned 32 will also break it.

    Casting to wider/narrower types is also undefined and might break your code.

    The “only thing” you can do is “cast it to an int”. That’s not ambiguous. It’s not unclear. It’s plain blac^H^H^H^Hones and zeros.

    *boggle*

    But … but … you’re Raymond Chen. You rule! How can you not read the documentation also?

    Screw it, it must be me. If you think that everyone else in the whole world is insane, it’s much more likely that you are instead. Therefore, it is not the whole world that is insane for not reading the documentation or not caring what it actually says; it must be me for reading it and caring. Well, bring me the straightjacket – I give up.

    [0] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shellexecute.asp

    [The only correct thing you can do is to cast to an int and compare against 32, just like the documentation says. My point is that the implementation of ShellExecute has to watch out for people who do incorrect things, too. That doing things other than following the documentation is incorrect I sort of took for granted. Perhaps you would prefer that I had written more pedantically? “You could incorrectly cast in the other direction comparing the return value against (HINSTANCE)32. That’ll work fine, too (even though it is incorrect).” So go ahead and mentally insert “(Doing anything other than casting to an int and comparing against 32 is incorrect, of course.)” after every sentence. I was hoping I didn’t need to do that. This is a conversation, not formal documentation. -Raymond]
  16. required says:

    Does nobody else understand the sentence "X works even though it is incorrect"?

    You forgot to say ‘Does nobody else understand the sentence "X works today even though it is incorrect"?’

    Just to be really pedantic.

  17. Elijah says:

    “That’ll work fine, too (even though it is incorrect).”

    I *was* reading it like that. Don’t you don’t see the contradiction there?

    By saying that “you could cast in the other direction [and it] *will* work fine too” (emphasis mine), you are claiming it *is* defined behaviour, and that it *will* work.

    Therefore, you’re saying that doing those things is “correct”, *despite* what the documentation says.

    Aren’t you?

    /me is confused.

    [Casting in the other direction is undefined behavior. It’s undefined behavior that happens to work, but formally it is undefined. In the same way that driving off the road is undefined according to traffic laws but it works because the road has a shoulder. Is it just me? Does nobody else understand the sentence “X works even though it is incorrect”? -Raymond]
  18. Norman Diamond says:

    > Going back to the original question: How

    > should I check the return value of

    > ShellExecute for errors? MSDN says you can

    > cast the result to an integer and compare the

    > result against 32. That’ll work fine.

    That looks like a promise.

    If we read it in MSDN then experimentation is needed in order to
    determine whether or not this is among the 75% of MSDN’s promises that
    tend to be accurate — today.  Reading it here, it looks like a
    real promise.

    > You could cast in the other direction,

    > comparing the return value against

    > (HINSTANCE)32. That’ll work fine, too.

    That looks like a promise.  I’ve delayed a few hours and reread
    before posting, but it still looks the same.  I don’t see anything
    that says “works even though it is incorrect”.  Your later
    comments said what you meant, but your initial posting looks like a
    real promise.

    > Or you could cast the result to an INT_PTR

    > and compare the result against 32. That’s

    > fine, too.

    That also looks like a real promise.

    Obviously I’m not the only one who read it that way.  Thank you
    for making corrections, even though you thermonucleated without
    justification.

    Separate issue:

    > They’ll all work, because the implementor of

    > the ShellExecute function had to plan ahead

    > for you and all the other people who call the

    > ShellExecute function.

    OK, I really don’t have much of a complaint about this kind of
    effort when it serves a useful purpose.  My complaint is about
    priorities.  I wish that implementors of other functions would
    plan ahead for readers and people who call functions as documented, and
    would make other functions work when they’re supposed to.  I wish
    that kind of work would be given priority.

    My second-latest experience isn’t quite an example of this wish.
     The Japanese version of StringCchPrintf falls over dead as soon
    as it hits a Japanese string in the Japanese version of Windows CE.
     Well, MSDN’s documentation for StringCchPrintf’s %S and %s
    formats is all garbled up in Windows CE, unlike ordinary Windows.
     Someone pointed out this means that the implementation isn’t
    really violating MSDN.  That’s what makes this a not quite
    example.  Nonetheless I wish that priority would be given to
    making APIs work.

    [You may be shocked to realize that the people who
    work on the Japanese version of StringCchPrintf on Windows CE are not
    the same people who work on ShellExecute function. May I suggest that
    you re-read this article. -Raymond
    ]
  19. Mike Dimmick says:

    Most times backwards compatibility doesn’t mean extra code. It just means a constraint on the design parameters for your extension: that you can’t use certain values that are already defined, or you can’t change the meanings of existing parameters in the way that you might like.

    This requires more care and attention when making changes, so that you don’t accidentally break old clients, and of course there’s extra code for the new features, but you rarely have to write new code for old features.

    Sometimes compatibility code, if a mistake happened frequently enough, is placed in the main line of code. However, most errors have only occurred in a few programs, so the code to fix them is in a separately loadable shim, only loaded into programs known to have the problem. If you repeat the error, you may not get the shim and your program won’t work.

    Compatibility shims are only required when there are clients which are expecting accidental behaviour, behaviour which wasn’t specified in the documentation but which happened to occur anyway. Of course here you need reliable, complete and accurate documentation in order to use the functions as designed. Microsoft’s developers get feedback from PSS as to the most frequent/most severe problems that customers are experiencing, but I’m not sure that the community resources are processed in the same way. In my experience developers don’t generally consult PSS unless there’s a serious blocking issue with a tool, which means that a lot of the problems are dealt with only by consulting peers – who only have the public resources. If those resources are erroneous or incomplete, we have to guess what the correct incantation is, and sometimes we guess wrong.

    A lot of programmers seem to avoid recourse to books, which can be a helpful resource if the author has gained access to the development team and asked them to clarify how something is meant to work – this will then be more reliable than simply asking peers on a forum, newsgroup or mailing list. More dangerous is the type of book where the author has misunderstood something and not clarified it with the development team – this propogates the mistake through every program written by readers of the book. For ‘book’, read also ‘sample’, ‘magazine article’, ‘blog post’ etc.

    The .NET Framework team seems to have a rule that says every element – method, field or property – must have an XML doc comment, from which the documentation is generated. However, that metric says nothing about the quality of the comment, which can often be poor.

    In my book, if you implement a feature in an API – any feature – you must completely document it: what it is, how you invoke it, when to use it, how it interacts with other features. Otherwise you risk this kind of erroneous interpretation of the feature that leads to compatibility problems down the road.

    In my case I’m finding that on Windows CE, the SIO_ADDRESS_LIST_CHANGE notification isn’t working in my code – the event I’ve registered using WSAEventSelect isn’t being set when an address change occurs (which should happen when the WiFi radio comes into coverage). I can find no examples of how this call is meant to work. I’m probably going to change over to using NotifyAddrChange from the IP Helper API, which does have a sample.

  20. Mark Steward says:

    I think a lot of people are misreading this as a style guide.  Maybe the "should"s have confused people?  Raymond’s simply explaining the MSDN recommendation, which itself says *ignore* that it says it’s an HINSTANCE – it’s not one.  You might think of it as an enum unioned with HINSTANCE.  The only reason you can cast it to int is that’s part of the spec of the function.

    I’d never taken the time to see what number it returns on success.  I like that it’s 42: it makes me happy, in a Ctrl-Alt-Shift-in-About-boxes way.

  21. koehli says:

    > You could cast in the other direction,

    > comparing the return value against

    > (HINSTANCE)32. That’ll work fine, too.

    That looks like a promise.  I’ve delayed a few

    hours and reread before posting, but it still

    looks the same.  I don’t see anything that

    says "works even though it is incorrect".

    Your later comments said what you meant, but

    your initial posting looks like a real

    promise.

    I personally am not a native speaker. You probably aren’t either and the intricacies of the English language can be rather daunting. I’ll try to explain it with an example.

    "The sky is blue." – This is a description of the weather. It’s not a promise. There is no temporal specification. The sky is blue now, but it might or might not be blue tomorrow.

    "I promise, the sky will be blue tomorrow." – This is a promise. It might hold true or it might get broken. But a promise it is.

    In all of his post, Raymond never made a promise. He merely described the state as-is an the arising consequences. Hopefully this will help you with your language problems :-)

  22. C Gomez says:

    New applications should do things the correct way.  Microsoft deprecates APIs, certain usages of APIs, or even certain incorrect usages of APIs.  That is like a warning: "Everyone, this can go away someday."

    As new applications replace old, and older code (even 16-bit code) falls away, MSFT can make the "breaking change" that stops that code from working.  That same "breaking change" provides needed stability to new apps, because the newer API, usage, return value, exception, etc., is more deterministic or "better" in some way.

    This behavior can go away someday.  Stop using it.  Fix old code if you can (often you can’t).

  23. required says:

    In all of his post, Raymond never made a promise.

    No, however, and I think this is the point others are trying to make: we know that Microsoft will bend over backwards to make existing apps not break under new versions of Windows, so if enough people read things like this and do the wrong-but-works-ok thing then even if MS wants to tighten things up, they can’t, because then they’ll break compatability. This is exactly what Elijah was saying – those of us who take time to try and do things the right way will be trampled by the hordes who have read something somewhere on a webpage that says "it works ok this way", because MS will actually reward them for it.

  24. Elijah says:

    “Does nobody else understand the sentence “X works even though it is incorrect”?”

    But you’re not saying “X works”, you’re saying “X *will* work”. To
    me, that sounds like a guarantee that MS is *not* going to change the
    behaviour so that “incorrect” usage breaks; that the behaviour *is*
    “defined”

    What is correct/incorrect/defined/undefined usage of an API?
    Correct/defined usage is that which is guaranteed to work, now and in
    future versions.

    You’re saying that “incorrectly” casting the HRESULT to an INT_PTR
    and comparing works now and is *guaranteed* to work in the future. So
    under what definition is that behaviour “incorrect” or “undefined”? The
    documentation?!? Hmph – it wouldn’t be the first time MSDN is wrong/out
    of date.

    Unless you can say that MS *might* change the behaviour of
    ShellExecute() in the future in such a way that could break “incorrect”
    usage of the API, I don’t see how you can possibly claim that that
    behaviour is “undefined”.

    So, if MS are going to guarantee that current uses of an API
    continue to work in the future, no matter how “incorrect” it is
    according to the docs, in order to support the idiots who don’t read
    them, why should *I* bother reading the docs? Why don’t I just make my
    apps depend on whatever the current behaviour is, no matter what the
    docs say?

    I’m off to make my next app depend on being able to invalidate the
    NULL window. If MS are not going to punish anyone else for doing it, I
    don’t care if they have to support it for another 100 years. No skin
    off my nose.

    [The use of the future tense was for narrative fluency.

    “Go out on the porch and you’ll find a surprise.”

    “Is that a promise that in the future there will always be a surprise for me when I go out on the porch?”

    “Of course not. I’m saying that there is a surprise there right now.”

    “Well, when you used the future tense, I assumed you were making a guarantee about future behavior.”

    “Stop it already. You’re doing this on purpose just to annoy me.”

    The guarantee is that if you follow the documentation, it will work. -Raymond]

  25. Zeke says:

    The real tax of compatibility code is not size bloat but rather cognitive bloat.  Constraining the error codes ShellExec() returns is never very much code, but the comment blocks describing why devs need to maintain the behavior can be huge.  I can think of many places in the code that are essentially a simple test of maybe a couple of parameters resulting in maybe half a dozen instructions.  However the comment block explaining why the test exists and how its behavior is constrained could easily be a couple orders bigger.

    Often those comment blocks are more like Raymond’s stories.  To be honest I have a pride for a good comment block that often can’t be equaled by the code it is commenting.  Being a good developer is less about writing the "right" code and more about making the "right" tradeoffs.

  26. koehli says:

    > In all of his post, Raymond never made a promise.

    No, however, and I think this is the point others are trying to make: we know that Microsoft will bend over backwards to make existing apps not break under new versions of Windows, so if enough people read things like this and do the wrong-but-works-ok thing then even if MS wants to tighten things up, they can’t, because then they’ll break compatability. This is exactly what Elijah was saying – those of us who take time to try and do things the right way will be trampled by the hordes who have read something somewhere on a webpage that says “it works ok this way”, because MS will actually reward them for it. “

    So let me get this straight. You are not having a problem yourself, your code keeps working as prmised. However, you are explaining, that MS does NOT break other peoples software, so your software looks better in comparison?

    You’re such an idealistic and altruistic person, really loveable. “Mom, mom, Peter is watching television again, punish him” :-) Besides I don’t think reading the MSDN docs really slows you down. Reading complete and correct documentation usually is much faster than the trial and error way to find out what a function does. Of course you first have to realize that the *only* way to use the MSDN efficiently and not get lost in gazillions of irrelevant pages is Google :/

    [Perhaps the solution is for me to stop writing “behind the scenes” articles. Less work for me. -Raymond]
  27. Elijah says:

    OK, OK, sorry!

    I’m just used to a more rigorous discussion of APIs, where "Can I do X?" means "Does the API guarantee that I can do X?", and an unqualified reply of "you can do X" (*especially* where the replier is very knowledgable and well-respected, such as yourself w.r.t Win32) is taken to mean "The API guarantees you can do X; any implementation (including future implementations) that does not do X is broken".

    I like your "behind the scenes" articles a lot. I don’t *want* to annoy you or to get you to stop posting them. I’m just carrying over the rules of how language is used from a more similar environment than that of people giving each other surprise gifts.

    I’ll try to leave my API-discussion preconceptions back in comp.lang.c.moderated for your next insider article. :)

  28. Norman Diamond says:

    > You may be shocked to realize that the people

    > who work on the Japanese version of

    > StringCchPrintf on Windows CE are not the same

    > people who work on ShellExecute function. May

    > I suggest that you re-read this article.

    I looked again at the linked article.

    Thank you for not being shocked to realize that your company is a glass house.

    I still wish that your company would give a higher priority to making APIs work correctly than to making defective programs work.  As stated, I don’t really object to the effort of making defective programs work, I object to your glass house’s sense of priorities.

    And you replied to Elijah:

    > The guarantee is that if you follow the

    > documentation, it will work.

    As mentioned, my second-latest experience was a not-quite-example, but there are lots of other examples where that guarantee is still just so much shi*.  The fact is that if you follow the documentation then 75% of it will work.  You always have to experiment after reading an MSDN page, to see whether or not it’s in the 75% that’s reliable.

    Thursday, November 09, 2006 8:47 AM by koehli

    > I personally am not a native speaker. You

    > probably aren’t either

    [of English]

    Actually I am but I’ve been away long enough to have some misunderstandings of the current version.  Nonetheless a statement “you could do X” followed by “that’ll work” looks a lot more like a promise than a temporary empirical observation.

    [Please go back and read the ground rules. All postings are provided “AS IS” with no warranties and confer no rights. There are no promises in the legal sense of the word. As I already noted, the “that’ll work” was part of the conversational style. I am not going to switch to a formal writing style so you’ll just have to accept it. -Raymond]
  29. Dean Harding says:

    Norman: I think you need to remember that Raymond is a person. He is not Microsoft. He is not anyone else at Microsoft. When he says something, it is NOT with the full weight of the entire company behind him.

    It’s like if I tell you "the weather will be fine tomorrow." I don’t have the power to affect the weather, but given the current conditions (it’s fine today) and past experience (when it’s fine today, it’s usually fine tomorrow as well) I can make that statement.

    When Raymond says "you can cast 32 to an HINSTANCE and compare," he ALSO doesn’t have the power to affect company policy at Microsoft, but given the current conditions (it works today) and past experience (Microsoft tries hard to make sure the things that work today will also work tomorrow), he can make that statement.

  30. required says:

    so your software looks better in comparison?

    No, quite the contrary. My software looks /worse/ by comparison because it takes longer to develop.

    You’re such an idealistic and altruistic person, really loveable.

    Aw, diddums.

  31. required says:

    you’ll just have to accept it

    I wonder how many times you have already had this conversation.

  32. Aaron G says:

    How does anything that Raymond says on a blog constitute an explicit "promise" from Microsoft regarding the behaviour of some API?

    We read these posts (or at least I do) to get an understanding of *why* some of the more bizarre aspects of the API are the way they are.  If that understanding leads one to the additional knowledge that an API might still work correctly if used improperly, so be it; that’s still not some sort of binding contract, and Raymond has often highlighted the difference between documented (and thus supported) behaviour and undocumented hacks.

    I’m personally grateful to have such a window into the inner workings of a monolithic (and eccentric) OS that I use virtually every day of my life.  And I think it’s a little sad that some people can be so dismissive of compatibility issues; I suppose you would prefer the MSDN Mag types who obsolete entire frameworks after a year or two.  And who don’t bother to maintain compatibility, for example, between different versions of WSE (a product whose sole purpose is essentially to promote compatibility between platforms).

    As for draconian measures involving logo apps and such, Microsoft has already been involved in various anti-trust suits.  It would be really, really awful politics (not to mention bad business) for them to try to enforce any kind of policy on Windows developers.  I’d go so far as to call it clueless.

    I hope you don’t decide to quit posting because of a few cranks, Raymond.  I’m sure that the number of times someone has implemented an unsupported compatibility hack after reading about it on your blog is positively dwarfed by the number of times it’s happened on CodeProject or ExpertSexChange.

  33. Ulric says:

    Many of us here think these articles are a lot of fun, and in some cases cool brain teasers.

    Personnally I don’t understand the four or five people who react angrily to these articles, and I don’t think they reflect all the lurkers to this blog.  

    I’m guessing they’re not in the ‘frame of mind’ of us engineer who need to maintain libraries and need to balance binary compatibility between version.

    I totally understand that as soon are you begin to being limited in what kind of HINSTANCE values you can return due to a poor design spec of the original API – for example, nothing greater than 15 bit – you might as well just return a constant that has no specific meaning.  It’s actually the most elegant solution in that situation.

    About the "congitive bloat", franky… the API can never really change after it’s published.  That why you have ShellExecuteEx.

  34. Igor says:

    "[Again, I already explained why ShellExecute returns an HINSTANCE. If you want a function that returns a BOOL and an output pointer, use ShellExecuteEx. -Raymond]"

    See, that’s the point. Microsoft should’ve said "We are doing a major cleanup for the next operating system release because customers demanded stability and security. As a result, all poorly designed APIs (list follows) will be deprecated and will no longer work. Fix your programs today to make sure it will work in the future. Vista 2 is around the corner, don’t be caught with your pants down."

    In essence that means that ShellExecute() should return failure in future OS and only ShellExecuteEx() should work. Same goes for all other legacy junk. Throw it out already.

    To the bloke concerned with big corporations and their compatibility issues — what happened to real world competition? Natural selection?? Evolution???

    Why everyone expects Microsoft to jump through hoops so that some crappy company can stay in business with their crappy software?!?

    Let them fill that bankruptcy form and get a better software solution for your business — one which works without workarounds.

  35. James says:

    Igor: If Vista 2 won’t run the applications businesses depend on, they won’t change the applications so they can use Vista 2 – they’ll stick with the previous version, which does what they actually need Windows to do for them: run their software.

    Now, they could move deprecated APIs into ‘legacy.dll’ and warn people when their applications are using old interfaces – but a version of Windows which can’t run them is a version of Windows which will stay on the shelf. "Deprecated" is one thing – "will no longer work" just won’t fly.

  36. It’s in the design.

Comments are closed.