In this case, what the customer really wanted to do was
create additional supporting files into the
directory that the user dropped the file onto.
To solve the real problem, all you have to do is add
virtual objects to the data object the file being dragged.

Let's illustrate this by adding a second file to our
minimal example of dragging a virtual file.
Actually, let's make it more interesting.
We're going to drag one real file plus one virtual file.
Start by adding another file's contents to our list of clipboard formats:

We need to add this second file to our FILEGROUPDESCRIPTOR.
Doing this is trickier because the FILEGROUPDESCRIPTOR
is a variable-size structure, so we have to declare our own version
that has room for two files.

The ad-hoc union declares a block of memory large enough
for a FILEGROUPDESCRIPTOR that holds two files.
File zero is the file we are dragging, and as a courtesy
(and in violation of the "doing the absolute least amount of
work necessary" that has guided the series),
we fill in the file attributes so that when the file is dropped
onto Explorer, the resulting file has the right metadata.
On the other hand, our virtual file tries to sneak by
with as little as possible, providing only the mandatory file name.

The last thing to do is hand out the FILEGROUPDESCRIPTOR
and the two files when we are asked for them.

Quantum Hoops
is a new documentary which follows the
college basketball program at the
California Institute of Technology
through its 2007–2008 season.
The school is
regularly honored as one of the finest academic colleges in the United States.
Their basketball team, on the other hand, is not as well-honored.
It has won two conference games in the last 35 years.
Their last victory was 240 games ago.

The elite college basketball teams dream of winning the NCAA tournament,
or at least winning their conference championship.
Lesser teams dream of posting a winning record.
These guys just want to win a game.
Just one game.

When talking about why people buy computers, there are two
broad categories,
"replacement computers"
(those which replace an older machine being retired)
and "new placement computers"
(those which do not).

Now, sure, you have to call them something,
but "new placements" sounds kind of markety.
Then again, I felt the same way about using "seats" to mean
"users" and see what that got me.

As we noted last time, structure tags are different from the
typedef name as a historical artifact of earlier versions of the C
language.
But what about just leaving out the name entirely?

typedef struct {
...
} XYZ;

One problem with this approach is that it becomes impossible to make
a forward reference to this structure because it has no name.
For example, if you wanted to write a prototype for a function
that took one of these structures,
and you could not be sure that the header file defining the XYZ
type definition has already been included, you can still refer to
the structure by its tag name.

The two header files can be included in either order
because header file B uses a forward reference to the
XYZ structure.
Naturally, you would hope that people would include header file A
before header file B, but there can be cases where it is not
practical.
(For example, header file A may contain definitions that conflict
with something else that the program needs,
or header file A may change its behavior based on what has
already been #define'd, and you don't want to
include it before the application has a chance to set up those
#defines.)

But a more important reason to avoid anonymous types is that
it creates problems for MIDL.

Okay, it doesn't actually create problems for MIDL.
MIDL handles it just fine, but the way MIDL handles it
creates problems for you,
for when you create an anonymous type in MIDL,
such as an anonymous structure above, or an anonymous enumeration
like this:

typedef enum { ... } XYZ;

MIDL auto-generates a name for you.
For example, the above enumeration might end up in the
generated header file as

typedef enum __MIDL___MIDL_itf_scratch_0000_0001
{
...
} XYZ;

The kicker is that the auto-generated name changes if you
change the IDL file.
And since typedefs are just shorthand for the underlying type
(rather than a type in and of themselves),
the name saved in the PDB is the unwieldy
__MIDL___MIDL_itf_scratch_0000_0001.
Try typing that into the debugger, yuck.

Furthermore, having the name change from build to build means
that you have to make sure code libraries are all built from
exactly the same header file versions,
even if the changes are ostensibly compatible.
For example, suppose you compile a library with a particular
version of the header file, and then you add a structure to the
MIDL file which has no effect on the functions and structures
that the library used.
But still, since you changed the MIDL file, this changes
the auto-generated symbol names.
Now you compile a program with the new header file and link
against the library.
Result: A whole bunch of errors,
because the library, say, exports a function that expects
its first parameter to be a
__MIDL___MIDL_itf_scratch_0000_0001
(because the library was built from the older MIDL-generated header file),
but your program imports a function that expects its first
parameter to be a
__MIDL___MIDL_itf_scratch_0001_0002
(because you compiled with the newer MIDL-generated header file).

What's more, when you update the header file, your source control
system will recognize hundreds of changes, since the MIDL
compiler generated a whole different set of names
which no longer match the names from the previous version of
the header file, even though you didn't change the structure!
This isn't fatal, but it makes digging through source code
history more of an ordeal since the "real changes" are buried
amidst hundreds of lines of meaningless changes.

Now, this particular rule of thumb is not universally
adhered-to in Windows header files,
in large part, I believe, simple because people aren't aware
of the potential for mischief.
But maybe now that I wrote them up,
people might start paying closer attention.

My trip to Lisbon entailed a connection in Paris at
Charles de Gaulle International Airport.
So now, I've technically been to France,
but since I never left the airport, I don't think it really counts.

(When I mentioned to one of my colleagues that I paid a brief
visit to his native country, he replied, "I hope it went okay."
Off my confused expression, he continued:
"I try to avoid changing planes in Paris.
There is about a 30% chance that somebody will be on strike.")

When our flight landed, a series of buses arrived
to take the passengers to the terminal.
Or at least, that's what we thought the bus was going to do.
In fact, the bus took us on what appeared to be a grand tour of all
the service areas of the airport.
Look, the baggage sorting machine.
Here's
a building shaped like
a wheel of cheese.
Over there, the food service trucks.
Hey, didn't we pass this building already?

After
a three-hour tour
of the facilities, we finally stopped in
front of the terminal.
I was expecting an announcement over the speaker:
"We hope you enjoyed this bus tour of Charles de Gaulle International Airport."

This is a holdover from very early versions of the C language
where structure tags, union tags,
and typedefs were kept in the same namespace.
Consequently, you couldn't say
typedef struct XYZ { ... } XYZ;.
At the open brace, the compiler registers XYZ
as a structure tag name, and then when XYZ appears
a second time, you get a redeclaration error.
The standard workaround for this was to make the structure tag name
a minor modification of the typedef name,
most typically by putting the word tag in front.

The C language standardization process separated the structure
and typename name spaces, so this workaround is no longer necessary,
but it doesn't hurt either.
Besides, even if new structures followed the
typedef struct XYZ { ... } XYZ; pattern,
you would just have people asking,
"Why do some structures in winuser.h use
the tagXYZ pattern and others use the XYZ
pattern?
Why can't it just be consistent?"

Next time, why you also don't see the pattern
typedef struct { ... } XYZ very much either.

Today is Waffle Day in Sweden, and the reason why today of all days
is Waffle Day I find quite amusing.

March 25th is the Feast of The Annunciation according to the Catholic
Church calendar,
the day on which
the archangel Gabriel announced to Mary that she would
conceive a child, the Son of God.
Why March 25th?
The date was arrived at by the following highly scientific calculation:

Ipso facto, habeas corpus delicti,
we have determined the date of the Annunciation to be March 25th
via incontrovertible logic.

In England, the holiday is known as Lady Day,
a name which is echoed Sweden, where
the holiday goes by the name Our Lady's Day:
Vårfrudagen.
Now, if you say Vårfrudagen really fast and mumble it,
somebody with bad hearing might misinterpret what you said as
Vaffeldagen,
which means Waffle Day.

Now, Waffle Day is not to be confused with
Pancake Day, a British holiday which coincides with
Shrove Tuesday, the day before the beginning of Lent.
Unlike Waffle Day, which is based on a pun,
Pancake Day had a practical origin:
In olden days, consumption of dairy products was prohibited during Lent,
and pancakes were a convenient way to use up your leftover
eggs, butter, and milk all at one go.
(That is, on years when it isn't
cancelled.)

And this year, a Polish colleague taught me about
Pączki Day, a holiday that takes place on the Thursday
before Lent and is apparently celebrated by "eating as many
pączki as possible."
Pączki
are pastries that resemble a jelly-filled doughnut,
and the holiday served the same practical purpose as Pancake Day in England.

What food-based holidays exist in your country?
Here are a few more to get you started:

When you go through Windows header files, you'll see types
with names
INT,
LONG,
CHAR,
and so on.
What's the difference between these types and the uncapitalized ones?

Well, there isn't one any more.

What follows is an educated guess as to the story behind these types.

The application binary interface for an operating system needs to
be unambiguous.
Everybody has to agree on how parameters are passed,
which registers are preserved, that sort of thing.
A compiler need only enforce the calling convention rules
at the boundary between the application and the operating system.
When a program calls another function provided by that same program,
it can use whatever calling convention it likes.
(Not a true statement but the details aren't important here.)
Therefore, a calling convention attribute on the declarations of
each operating system function is sufficient to get everybody
to agree on the interface.

However, another thing that everybody needs to agree on is the sizes
of the types being passed to those functions or used in structures
that cross the application/operating system boundary.
The C language makes only very loose guarantees as to the sizes
of each of the types,
so language types like int and long
would be ambiguous.
One compiler might decide that a long is a 32-bit
integer, and another might decide that it's a 64-bit integer.
To make sure that everybody was on the same page,
the Windows header files defined "platform types"
like INT and LONG with prescribed semantics
that everybody could agree on.
Each compiler vendor could tweak the Windows header file to ensure that
the type definition for these platform types resulted in the value
that Windows expected.
One compiler might use
typedef long LONG
another might use
typedef __int32 LONG.

Okay, but this doesn't explain VOID.
Maybe
VOID was added for the benefit of compilers
which didn't yet support the then-new ANSI C standard type void?
Those older compilers could typedef int VOID; and functions
that were declared as "returning VOID" would be treated
as if they returned an integer that was always ignored.
Or maybe it was just added to complete the set, who knows.

In the intervening years, most if not all compilers which target Windows
have aligned their native types with Windows' platform types.
An int is always a 32-bit signed integer,
as is a long.
As a result, the distinction between language types and platform types
is now pretty much academic,
and the two can be used interchangeably.
New Windows functions tend to be introduced with language types,
leaving platform types behind only for compatibility.