For people for whom adding a half cup of milk and one egg to
two cups of
Bisquick powder
is too complicated,
now they've even dehydrated the milk and egg
and pre-measured the mix,
so all you need to do is add a measured amount of water.
Because you know,
cracking an egg is so time-consuming.

My colleague
who tips me off to all the foods that are offenses against nature
let me know by email that even she,
mother to a three-week-old baby,
was able to somehow pull it together
and measure out the milk and crack the egg.
"Oh wait," she corrected herself.
"I made the pancakes from scratch."

Imagine, you're navigating
a deeply-nested menu hierarchy
and then you want to move to one of the items in the most recent fly-out,
but instead of moving the mouse directly to the right then down,
you move it ever so slightly diagonally down.
Boom, the entire menu collapses and you have to start over.
There's a place for
maddeningly fiendish
mouse dexterity games,
but trying to create a pivot table is not it.

I run into this problem all the time on the Web.
Web site designers forget to incorporate a menu show delay,
resulting in frustration when trying to navigate around them.
For example, let's look at the navigation bar on the home page of
The Discovery Channel.
Hover over TV Shows, and the menu appears.
Suppose you want to go to Koppel on Discovery,
but instead of moving the mouse straight downward,
the way you hold your arm on the desk moves the mouse
in an arc that happens to swing to the right before it arcs downward.
You touch TV Schedules and your navigation is screwed up.
You have to start over and make sure to move the mouse exactly
straight down.

This phenomenon is even worse for sites that position their
submenus as a horizontal bar below the main navigation bar,
such as
EVA Air
or
NBC.
On the NBC site, for example,
hover over Schedule and a band appears
below the navigation bar with more options.
But you can't move the mouse diagonally to, say,
Pacific;
if you do, you'll accidentally touch News & Sports
and the Schedule submenu will be disappear.
If you just move and click in one motion, then boom, congratulations,
you just clicked on
Access Hollywood.
You have to carefully move your mouse straight down (being careful
not to touch anything else that might open a different menu or
cause the existing menu to auto-dismiss), and then straight sideways
(being careful not to accidentally move it upward three pixels,
causing the secondary navigation bar to be replaced with a different
submenu).
It's like its own miniature mouse dexterity game.
But one you didn't elect to play.

The folks over at
TechNet Magazine did take the menu show delay
into account, though it's still not as long as I'd like.
Hover over the word TechCenters
in the navigation bar, and a submenu appears.
If you move toward Script Center and happen to touch
TechNet Magazine ever so briefly (like one
Planck time),
the TechCenters menu stays up.
On the other hand, the menu animation is abysmally slow if you
use Firefox, so one step forward, one step back.

Some customers already have the answer but need to have their hand held.

My customer wants to enforce a company-wide policy of disabling
the "Keep the taskbar on top of other windows" feature.
We have confirmed that there is no group policy setting for
controlling this setting.
Further research reveals the SHAppBarMessage function.
The customer wants to know if there is any way he can write code
that will use this function to modify the setting.

The customer found a map to a stream,
saw that there were directions printed on it,
and then asked,
"Is there any way I can follow these directions and get some water?"

The product team dutifully wrote up the four-line function
to do the work the customer requested—call
SHAppBarMessage with ABM_GETSTATE
to get the current state, turn off the ABM_ALWAYSONTOP flag,
and then call it again with ABM_SETSTATE to apply the
changes—but it still frustrates me that we had to deal with this
question in the first place.

It's one thing to say, "I tried doing X and it didn't work.
Here's the code I was using."
It's another thing to say,
"I discovered function X.
Can you write code for me?"

A customer noticed that if you add three to a process ID
and pass it to the OpenProcess function, it still
succeeds.
Why is that?

Well, first of all, I need to say up front that the behavior you're
seeing is an artifact of the implementation and is not part of the
contract.
You're passing intentionally invalid parameters,
what did you expect?
The context of this question is "We're seeing this behavior and we
can't explain it," not "We're using this trick and want confirmation
that it's okay."

As we saw earlier,
for convenience,
the Windows NT kernel uses the handle manager
to parcel out process and thread IDs,
and the handle manager ignores the bottom two bits of handles.
Therefore, adding three has no effect on the process-id-to-object
mapping.

This mechanism is peculiar to kernels based on Windows NT.
Versions of Windows derived from the Windows 95 kernel
have a different mechanism for mapping process IDs to processes,
and that mechanism is
unflinchingly rigid.
If you add three, the OpenProcess function will reject
your process ID as invalid.
And I don't know how Windows CE handles it.

Again, I wish to emphasize that the behavior you see in Windows NT-based
kernels is just an implementation artifact
which can change at any time.
Who knows, maybe once they read this entry,
the kernel folks will go in and change OpenProcess
to be even more strict.

Pre-emptive Yuhong Bao comment:
"Process IDs on Windows 95 are a pointer to an internal data
structure XORed with a constant to obfuscate them."

A customer needed to generate an 8-byte unique value,
and their initial idea was to generate a GUID
and throw away the second half, keeping the first eight bytes.
They wanted to know if this was a good idea.

No, it's not a good idea.

The GUID generation algorithm
relies on the fact that it has all 16 bytes to use to establish
uniqueness,
and if you throw away half of it,
you lose the uniqueness.
There are multiple GUID generation algorithms,
but I'll pick one of them for concreteness,
specifically the version described in
this Internet draft.

The first 60 bits of the GUID encode a timestamp,
the precise format of which is not important.

The next four bits are always 0001, which identify
that this GUID was generated by "algorithm 1".
The version field is necessary to ensure that two GUID generation
algorithms do not accidentally generate the same GUID.
The algorithms are designed so that a particular algorithm
doesn't generate the same GUID twice, but without a version field,
there would be no way to ensure that some other algorithm wouldn't
generate the same GUID by some systematic collision.

The next 14 bits are "emergency uniquifier bits"; we'll look
at them later, because they are the ones that fine tune the
overall algorithm.

The next two bits are reserved and fixed at 01.

The last 48 bits are the unique address of the computer's network card.
If the computer does not have a network card,
set the top bit and use a random number generator for the other 47.
No valid network card will have the top bit set in its address,
so there is no possibility that a GUID generated from a computer
without a network card will accidentally collide with a GUID generated
from a computer with a network card.

Once you take it apart, the bits of the GUID break down like this:

60 bits of timestamp,

48 bits of computer identifier,

14 bits of uniquifier, and

six bits are fixed,

for a total of 128 bits.

The goal of this algorithm is to use the combination of time and location
("space-time coordinates" for the relativity geeks out there)
as the uniqueness key.
However, timekeeping is not perfect,
so there's a possibility that, for example,
two GUIDs are generated in rapid succession from the same machine,
so close to each other in time that the timestamp would be the same.
That's where the uniquifier comes in.
When time appears to have stood still (if two requests for a GUID are
made in rapid succession)
or gone backward
(if the system clock is set to a new time earlier than what it was),
the uniquifier is incremented so that GUIDs generated from the
"second time it was five o'clock" don't collide with those generated
"the first time it was five o'clock".

Once you see how it all works, it's clear that you can't just
throw away part of the GUID since all the parts (well, except
for the fixed parts) work together to establish the uniqueness.
If you take any of the three parts away, the algorithm falls apart.
In particular, keeping just the first eight bytes (64 bits)
gives you the timestamp and four constant bits;
in other words, all you have is a timestamp, not a GUID.

Since it's just a timestamp, you can have collisions.
If two computers generate one of these "truncated GUIDs"
at the same time, they will generate the same result.
Or if the system clock goes backward in time due to a clock reset,
you'll start regenerating GUIDs that you had generated
the first time it was that time.

Upon further investigation, the customer really didn't need
global uniqueness.
The value merely had to be unique among a cluster of a half
dozen computers.
Once you understand why the GUID generation algorithm works,
you can reimplement it on a smaller scale:

Four bits to encode the computer number,

56 bits for the timestamp, and

four bits as a uniquifier.

We can reduce the number of bits to make the computer unique
since the number of computers in the cluster is bounded,
and we can reduce the number of bits in the timestamp by
assuming that the program won't be in service 200 years from now,
or that if it is, the items that were using these unique values
are no longer relevant.
At 100 nanoseconds per tick, 2^56 ticks will take 228 years to elapse.
(Extending the range beyond 228 years is left as an exercise,
but it's wasted effort, because you're going to hit the
16-computer limit first!)

You can get away with a four-bit uniquifier by assuming that
the clock won't drift more than an hour out of skew (say)
and that the clock won't reset more than sixteen times per hour.
Since you're running under a controlled environment,
you can make this one of the rules for running your computing cluster.

Among other responsibilities,
the Archives department preserves
Microsoft history,
be it
old hardware,
old software,
old documentation,
or ephemera.
Last year,
one of my colleagues was cleaning out his office
because he was
moving to Granada,
and of the junk he was going to throw out,
the Archives asked me to save the following:

Windows NT Workstation 3.51 for PowerPC (box and CD)

Windows NT Workstation 3.51 for Alpha AXP (CD only)

Documentation for two internal UI libraries from over a decade ago

Word 97/Excel 97 Service Pack 3 for Alpha AXP

Microsoft Excel promotional pens

Windows 95 launch event commemorative paperweight

MSN 8 commemorative gold master CD and ship gift box

MSN Internet Access promotional booklet and CD (unopened)

An official CD of an internal build of a 1999
user interface project that was later abandoned
(although its spirit survives in Windows XP).

The official CD of pictures from the Windows XP RTM party (unopened)

A lava lamp prize from an internal promotional campaign

and my favorite

An HP RPN calculator which was issued to employees as part of
the standard office equipment (back in the day).

One of the proposals for adding hidden features to Windows Setup
is to have
a bunch of hidden function keys,
one for each hidden option.
Well, first of all, there are only twelve function keys
and there are way more than twelve possible Setup features.
(Yes, there may be a few function keys still active during Setup,
but they exist only for compatibility purposes.
No new Setup features involve function keys as far as I'm aware.
And yes, there are keyboard layouts with more than twelve function keys,
but think about what you're saying in context:
"Yes, Setup should use function keys that are not available on
most keyboards.")

Furthermore, there's no guarantee that there's somebody sitting in
front of the computer when it's running Setup.
Indeed, 90% of the time, there is nobody there at all;
Setup is running on a factory floor somewhere churning out computers
day and night.

Adding a command line option to Setup also
runs you into problems:
The command line gradually gets bloated with a bajillion options.
After taking your several dozen customizations and cramming them onto the
command line, you'll find yourself having to type 500 characters
onto the command line to get what you want,
and woe unto you if you typo one of those 500 characters.
Can you imagine if somebody said,
"To set up Windows the way I like, I simply type the following
command," followed by a command that goes on for six lines?
"This is total crap.
I'm expected to type this monstrosity?"

Windows Setup for quite a long time has supported so-called
unattended installation.
You build a so-called unattend file and pass it to
the setup program as a single command line parameter,
something like setup /unattend:unattendfile.
(I forget the command line exactly; you can go look it up yourself.)
Now somebody can post their favorite settings onto their
Web site, and you can download it and pass it to Setup.

For many years, this unattend file took the form of an INI file,
with [Sections] and Key=Value entries.
In Windows Vista, the Setup folks threw away the old parser
and switched to XML.
Because XML is the wave of the future, right?
(I can imagine Steve Ballmer jumping up and down shouting
"XML! XML! XML!")
I don't know whether they've actually done it, but in principle,
the switch to XML means that they can write a schema for the
unattend file, and then all the standard XML
validation tools become available.

It's great when you have a tool to make programming easier,
but you still must understand what it does or you're
just replacing one set of problems with another set of more subtle
problems.
For example, we discussed earlier the importance of knowing
when your destructor runs.
Here's another example, courtesy of my colleague Chris Ashton.
This was posted
as a Suggestion Box entry,
but it's pretty much a complete article on its own.

I came across an interesting bug this weekend
that I've never seen described anywhere else,
I thought it might be good fodder for your blog.

Obviously I'm writing here,
so the answer cannot be A. It is, in fact, B.

The key is that CComBSTR is involved here,
so operator= is being invoked.
And operator=, as you might recall,
does a deep copy of the entire string,
not just a shallow copy of the BSTR pointer.
But how long does operator= think the string is?
Well, since BSTR and LPCOLESTR are equivalent
(at least as far as the C++ compiler is concerned),
the argument to operator= is an LPCOLESTR –
so operator= naturally tries to use the
wcslen length of the string,
not the SysStringLen length.
And in this case, since the string is uninitialized,
wcslen often returns a much smaller value than
SysStringLen would.
As a result, the original 100-character string is leaked,
and you get back a buffer that can only hold, say, 25 characters.

The code you really want here is:

CComBSTR bstr;
bstr.Attach(::SysAllocStringLen(NULL, 100));

Or:

CComBSTR bstr(100);

I'm still a big fan of smart pointers
(surely the hours spent finding this bug
would have been spent finding memory leaks
caused by other incautious programmers),
but this example gives pause –
CComBSTR and some OLE calls just don't mix.

All I can add to this story is an exercise:
Chris writes,
"Since the string is uninitialized,
wcslen often returns a much smaller value than
SysStringLen would."
Can it possibly return a larger value?
Is there a potential read overflow here?

I've seen some confusion over this,
heck I've been confused by this,
so I figured I'd share what I've learned.

In MSDN, you may see wording like this:

pdwResult
[out] When the function returns,
contains a pointer to a DWORD value that
contains the result of the computation.

What they're trying to say is that the pdwResultis a pointer to a DWORD that receives the result
of the computation.
Personally, I take issue with both uses of the word "contains",
but they tell me that that is their standard for describing [out]
parameters, so you'd better get used to it.

When they say that
the parameter contains a value, they mean that the you passed that
value as the parameter.
I prefer to think of the parameter being the value;
the parameter is just a convenient name for the value that the
caller passed.
The MSDN approach is to think of the parameter as its own
variable which therefore contains a value, as variables do.
In this specific case, they are saying that pdwResult
"contains a pointer" to mean that the parameter is itself a pointer
that you pass in.

Now on to the second half.
When they say that the pointed-to value contains the result,
they mean that the function itself writes to the pointed-to value.
The opening phrase "when the function returns" is intended to
indicate this, but I have two issues with that approach.

First, it seems to modify the wrong verb.
Since it's at the beginning of the sentence,
the temporal clause appears to modify the first "contains"
and not the second.
"When the function returns, the parameter contains a pointer...",
suggesting that perhaps when you initially called the function,
the parameter didn't contain the pointer and that the
statement becomes true only when the function returns.

Second, it doesn't emphasize that the function itself sets the value.
You can read the sentence passively, as if to say,
"Well, when the function returns, there's stuff there,
who knows how it got there, maybe it was there all along,
maybe you were expected to put it there first,
sometimes things just happen to be that way, you know?"
Sort of like, "When I get home, the lights are on."
Maybe you turned on the lights remotely
from work before you left for home.
Maybe they are on a timer so they turn on at the same time every day.
Maybe they were on all day.
Heck, you're not even ruling out the possibility
that the lights have psychic powers and turn themselves on
as a way of welcoming you home.

Anyway, now you know what that sentence means when you read it in MSDN.
It's not how I would've written it, but I'm not the chief editor of MSDN.

There are many situations where you pass a structure to a function,
and the function fills in the structure with information you request.
In some cases, the function always fills in the entire structure
(example: GlobalMemoryStatus).
In other cases, you tell the function
which bits of information you care about,
to save the function the effort of computing something you weren't
interested in anyway
(example: TreeView_GetItem).

In the latter case,
if you say that you aren't interested in certain parts of the structure,
and then you change your mind and start paying attention to them,
don't be surprised if you find that there's nothing interesting there.
After all, you said you didn't care.

For example, if you call TreeView_GetItem and set the
mask to TVIF_IMAGE | TVIF_PARAM,
this means that you want the function to set the
iImage and lParam members of the
TVITEM structure and that you don't care about the rest.
After the call returns, the values of those two members are defined,
since you said that's what you wanted,
and the remainder of the output fields are undefined.
They might contain useful information,
they might contain garbage,
you're not supposed to care since you said that you didn't.

Why might fields you said you didn't care about still contain
information (correct or incorrect)?
It might be that the value is so easy to compute that checking
whether the value should be set takes more work than actually
setting it!
In such a case, the function might choose to set the value even
if you didn't say that you needed it.

On the other hand, the value might be an artifact of a translation
layer:
You pass a structure saying, "I'm interested in two out of the four
members."
The function in turn calls a lower lever function with a different
structure, saying, "I'm interested in two out of the five members
of this different structure."
After the call returns, the middle-man function converts the lower-level
structure to the higher-level structure.
Sure, it may also "convert" stuff that was never asked for,
but you said you weren't interested, so they just get garbage.
In other words, the function you're calling might be defined like this:

Notice that if you ask for just FOOINFO_DENIED,
you still get the dwRequested as a side effect,
since computing the number of requests that were denied
entails obtaining the total number of requests.
On the other hand, you also get garbage for dwInUse
since the call to GetLowLevelStats didn't ask
for LLSTATS_INUSE, but the code that converts
the LOWLEVELSTATS to a FOOINFO doesn't
know that and converts the uninitialized garbage.
But since you said that you didn't care about the dwInUse
member, you shouldn't be upset that it contains garbage.