Holy cow, I wrote a book!
Commenter J-F has a friend who wonders
why Windows XP didn't auto-elevate all installers
but rather only the ones named setup.exe.
(Perhaps that friend's name is
Josh, who repeated the question twelve days later.)
Remember what the starting point was.
In Windows 2000, nothing was auto-elevated.
Before adding a feature, you have to know what problem the feature
is trying to solve.
The problem is improving the experience for non-administrators
who want to install software.
When they try to install a program and forget to use the Run as
instead of proceeding halfway through the installer
and then getting an Access denied error,
do the Run as for them automatically.
Knowing whether the user is running an installer that requires
elevation requires a degree of semantic analysis beyond what
you want to add to the CreateProcess code path.
Hey, here's a program called PRONT4.EXE.
Is it an installer?
Turns out that it is.
And then there are the programs that might be installers,
depending on what other command line switches you provide.
Given that you're reduced to a heuristic, you have to decide
what the acceptable rates of false positives and false negatives
If you guess wrong and think a program requires administrator
privileges when it doesn't,
then you've screwed over all the non-administrators who want to use
"I used to be able to run this program, but now when I try,
I'm asked for the administrator password, which I do not know.
Windows broke my program."
The effect of a false positive is My program stops working.
On the other hand, if you fail to detect a program that requires
being run with administrator privileges, the behavior is the same as before:
The user gets an Access denied error.
The effect of a false negative is No change.
Given that the cost of a false positive is huge and the cost
of a false negative is zero,
you can see that the math says to use a conservative heuristic.
The heuristic is that a program named setup.exe will
be treated as an installation program, and nothing else.
Windows was under no obligation to auto-detect installation programs.
Indeed, according to the strict interpretation of operating system
design, it shouldn't do this.
If the user says to run this program at the current privilege level,
then you darned well better run the program with the current privilege level.
The treatment of programs named setup.exe is really
just a compatibility hack,
a courtesy to make your life a little bit easier.
It's a case of giving somebody five dollars and being asked
why you didn't give them ten.
Starting in Windows Vista,
applications can specify via a manifest whether they want
to run at the privilege level the user requested
or always to elevate to administrator
Hopefully, all new applications will specify their elevation requirements
explicitly, and the heuristic will be necessary only for old programs.
Unless you've been living under a rock,
by now you know about MSDN's
low bandwidth view (aka ScriptFree)
But there are other views too, like
PDA view (for when you want to look up MSDN documentation on your phone?),
Robot view, printer-friendly view, unstyled HTML view...
(See that first link above for more details.)
But in addition to all the views, you can go directly to the back-end
that drives all the data:
MSDN/TechNet Publish System (MTPS) Content Service.
With that interface, you can request the back-end data and
format it any way you like.
an MSDN Magazine article which builds a documentation viewer,
the author of that article
a command-line tool which returns the content as a man page.
(Update: Looks like the command-line tool no longer exists.
Sorry, all you retro-heads out there.)
Some time ago, I opined that
should really be called CrashProgramRandomly
and you really should just let the program crash if somebody passes
you a bad pointer.
It is common to put pointer validation code at the start of functions
for debugging purposes
(as long as you don't make logic decisions based on whether the pointer
But if you can't use IsBadXxxPtr,
how can you validate
Well, to validate a write pointer, write to it.
To validate a read pointer, read from it.
If the pointer is invalid, you'll crash, and at a predictable
location, before the function has gotten halfway through its
processing (making post-mortem debugging more difficult).
Here are the functions I used:
// Make sure to disable compiler optimizations in these functions
// so the code won't be removed by the optimizer.
void DebugValidateWritePtr(void *p, size_t cb)
memcpy(p, p, cb);
void DebugValidateReadPtr(void *p, size_t cb)
memcmp(p, p, cb);
To verify that a buffer can be written to, we write to it
by copying it to itself.
Similarly, to verify that a buffer can be read, we read from it
by comparing it to itself.
The result of the operation is not important; we are interested
in the side-effect of the memory access itself.
Note that the DebugValidateWritePtr function
is not thread-safe: If another thread modifies the buffer while
we are copying it to itself, the write may be lost.
But code that does this violates one of the
ground rules for programming (specifically the parameter
Of course, if your function has specific behavior requirements
beyond the ground rules, then that helper function may not
work for you.
I'm just putting it out there as a courtesy.
Microsoft has an internal conference known as
the eleventh edition of which will take place in Seattle next week.
Having learned that
the way to get me to show up at your conference is to invite me,
the TechReady folks invited me to give a talk on advanced debugging
I wasn't their first choice, though.
This talk is a regular event at TechReady,
but the usual presenter
will not be available;
I'm a substitute.
Lav usually knocks everybody dead with his presentation, so I've got
big shoes to fill.
I've been trying to squeeze preparing for this talk in amongst the
things I actually get paid to do,
and I hope I'll get everything done before the conference
organizers start yelling at me for not having gone through all the
checklist items on schedule.
If you're a Microsoft employee at TechReady, you can watch me sweat
and panic on Friday at 1pm.
I'll also try to make it to Ask the Experts on Wednesday night.
The presentation is technically a Chalk Talk
(code CLICT400, and no I don't know what those letters stand for,
though the CT probably stands for Chalk Talk),
in case you were wondering why you can't find it in the session list.
A customer asked for advice on how to accomplish something,
the details of which are not important,
except to say that what they were trying to do was far
more complicated than the twenty-word summary would suggest.
And I wasn't convinced that it was a good idea,
sort of like asking for advice on how to catch a baseball
in your teeth or
pick all the cheese off your cheeseburger.
I explained several of the pitfalls of their approach,
the ones that I could think of off the top of my head,
things they need to watch out for or take precautions against,
and I concluded with the sentence,
"This idea is fraught with peril,
and I fear that my answers to your questions
will be interpreted as approval rather than reluctant assistance."
That sentence immediately went into many people's
In another installment of
I bet somebody got a really nice bonus for that feature,
I offer you this customer:
My customer has created a Windows Vista sidebar gadget and
wants to know if there's a way to force this gadget to appear
at the top of the sidebar and prevent the user from moving or removing it.
I applaud this company for having written
the most awesome sidebar gadget in the history of the universe.
It's so compelling that it should override the user's preferences
and force itself into the upper right
corner of their screen in all perpetuity.
Unfortunately, Windows was not prepared for a program as awesome
as this, and there
is no supported way to force a gadget into a particular
position and prevent the user from moving or removing it.
The topic backlog from
Suggestion Box 3
has nearly cleared out,
and I've actually been enjoying not having to write up a reply
every Monday for the past several months,
but all good things must come to an end, and so,
without much fanfare, we now have Suggestion Box 4.
Remember, the suggestion box is for suggestions for future topics.
It isn't for developer support, bug reports, or ranting.
Topics I'm inclined to cover:
Topics I am not inclined to cover:
Selected products at Microsoft participate in the
and many more have official blogs.
Suggestions should be between two and four sentences in length.
Think of it as an elevator pitch:
You have three seconds to get your point across.
Please also search the Web site first
because your suggestion may have already been covered.
(Possibly as a suggestion that was submitted to an earlier
Suggestion Box that was not accepted.)
And remember, questions aren't suggestions.
The Suggestion Box will be open for only two weeks,
and I will be much more selective about which one I choose to
accept than in previous go-rounds.
I'll answer one every Monday of 2012 (minus holidays and
special events such as CLR Week), and once the end of the year
is reached, that's the end of Suggestion Box 4.
A colleague of mine visited an internal Web site for task ABC
and found that the site was no longer there.
Instead it was replaced with a simple message:
Designed with the user in mind you will now find
contextual ABC and DEF information served up in a secure format alongside
all GHI information.
Access to relevant multi-perspective content will enable
faster resolution for your GHI needs.
HTTP/1.1 301 Moved Permanently
Chris 'Xenon' Hanson
points out that
fiddling with the WS_DISABLED style directly via
leads to strange behavior.
However it isn't the case that "most widget classes work fine."
Reaching in and fiddling the style bit directly is
like reaching into a program's internal variables and
just changing the values:
All the other work that is associated with changing the value
simply doesn't happen.
It's like taking a book you checked out of the library,
re-shelving it, and then
going into the library computer and marking it as "returned".
The bookkeeping will say that the book has been returned,
but all the other processes associated with a book return
has not taken place:
People who had placed a hold on the book aren't notified.
The "number of books checked out" counter isn't updated.
(Which gets interesting when you come to the end of your
senior year and the system won't let you graduate because
its records say that you still have 1 book outstanding,
yet when you say "Show me all the books I have checked out"
it returns no records.)
In the case of windows, merely setting the WS_DISABLED
style does not generate WM_ENABLE messages,
it doesn't generate accessibility notifications,
it doesn't do focus bookkeeping,
all it does is set the flag and goes home.
some code will stop working because
happened (in this case,
a window transitioning from enabled to disabled without ever receiving a
Similarly, the way to change a window's visible state is to use
the ShowWindow function and not to
manipulate the WS_VISIBLE style directly.
"I think I filed a suggestion on MSDN2.microsoft.com's suggestion box
to advise people not to fiddle with the WS_DISABLED flag
at runtime via SetWindowLong()
since it seems like a viable route if you don't know otherwise."
Actually, the advice already exists
right at the top of the
Window Styles page where it
"After the control has been created,
these styles cannot be modified, except as noted."
And for WS_DISABLED, it says
"To change this after a window has been created, use
A customer wanted to know how to launch Explorer's Search window
with specific fixed search criteria.
It turns out that there are two ways of doing this,
the poor man's way and the overachiever's way.
The overachiever's way is actually easier to discover.
use the search-ms protocol
a command string that describes the query you want to perform
pass it to ShellExecute.
The poor man's way actually requires a little bit of out-of-the-box
Open the Explorer Search window and interactively
create the query you want to be able to relaunch later.
Now do File, Save Search, and save the query.
When you want to relaunch the query, execute the saved search.
This is, after all, how end users save and re-use searches.