Holy cow, I wrote a book!
why the SHFileOperation function has internal error codes
if DVDs hadn't been invented at the time it was first written
a long time ago.
As my colleague Christopher Davis
the SHFileOperation function originally came from
the old File Manager of Windows 3.0,
code which was written before Win32 error codes were invented.
File Manager error codes and Win32 error
codes had a common starting point (the MS-DOS error codes),
but evolved under divergent paths.
When no suitable MS-DOS error code existed for a situation
that might arise during file copying,
the File Manager folks invented an error code for it.
Meanwhile, when no suitable MS-DOS error code existed for a situation
that might arise in Win32, the Win32 folks invented an error code for it.
That the two sets of error codes would come up with different meanings
for the same numerical value is to be expected,
since in both cases, the number was "available for use."
Okay, so when the DVD error codes were added, why weren't they
added to winerror.h to make them official instead
of adding them to the internal error list?
Well, for one, these are internal error codes (which happen to be
exposed to applications in an accidental way).
Why bother making official error codes for things which were
meant to be internal anyway?
"Dear kernel team, please add this error code to winerror.h."
— Okay, how should we document it?
"Oh, it's not documented."
— Then why the heck do you need it in winerror.h?
Second, there may be considerations that are not immediately
obvious from the raw list of internal error codes.
For example, I noticed
that there is one error code called ERRORONDEST
which is "or"d with other error codes.
The case of DE_ROOTDIR | ERRORONDEST
is specifically called out, but it's highly likely
that the more general case applies.
DE_FILENAMETOOLONG | ERRORONDEST probably
means that a file name on the destination was too long.
If the file copy engine were to switch entirely to Win32 error codes,
all the uses of internal error codes would have
to broken up into two parts,
one for the Win32 error code and another for the boolean that
specifies whether the Win32 error code applies to the source or
This means changing all the functions which pass or return internal
which can get particularly tricky if you were passing the error code
as a parameter to SendMessage or PostMessage
or some other function where you've already used up all the bits of
expressiveness. (You'd have to put the information into a structure
and then worry about keeping track of whose job it is to free that
DE_ROOTDIR | ERRORONDEST
DE_FILENAMETOOLONG | ERRORONDEST
Third, there's the principle of proportionate response:
Sure, the person who wanted to add DVD handling to the file copy
engine could have torn apart and rewritten the way error codes are
handled inside the copy engine.
But would that have been a proportionate response to
a request to
add DVD error handling to the copy engine?
"Here you go, I added DVD error handling, and I completely
redesigned the way errors are handled."
It's like asking someone to come fix a broken light switch
and discovering that they rewired your house while they were there.
Maybe they did a good job, or maybe they accidentally introduced
a short circuit somewhere in a little-used closet.
It's even more exciting when they don't even tell you that they
rewired your house.
You test the light switch, it works, and you thank them for a job
Then two months later, you visit that closet, turn on the light switch,
and all the outlets on the second floor explode.
Now, the principle of proportionate response is not a law of the universe.
It's just a principle,
and sometimes principles need to be broken.
For example, the principle of proportionate response also results in a
frog being boiled alive.
Sometimes you just have to get out of the pot.
But apparently this was not one of those times.
Chris did point out that the new Vista copy engine returns
HRESULTs rather than goofy internal undocumented
so at least things are better now.
The frog has been taken out of the pot.
Sidebar: It was only after I had written up this message
that I realized that erangi
had already asked this question at the bottom of
the original blog entry.
If I had known that, I wouldn't have bothered writing up this
because I don't like it when people
ask the same question
in multiple places,
especially since my response is based is purely speculation,
guesswork that you too could have performed.