Let's Code - WiX: Bad filenames
For the longest time, the bulk of the WiX Toolset was developed on "WiX Nights". One night a week a bunch of us would hang out at my house or (later) in a meeting room at Microsoft, eat dinner and write some code. It was a great way to maintain momentum but it was terrible at including those that were not physically present.
Today the core set of WiX developers are spread about the country so gathering in a room together isn’t a possiblity. But I’d like to find a way to get the momentum back. So tonight, I’m trying an experiment. I’m starting this blog entry before I start working on a bug fix. Before finishing tonight, I will then write the conclusion of the post with a summary of what I got done. My hope is to get into a habit where, at least, one night a week I make some progress and start building some of that momentum again. So, enough introduction. Let’s code!
Checkout
As mentioned over on the FireGiant blog, we reviewed all WiX v3.11 issues today. At this time, I have ten issues assigned to me. That means if I only fix one issue per week WiX v3.11 won’t ship until mid-April. That doesn’t sound good because I’m certain other issues will come up that require my attention. So, I clearly need to get started.
I decided the best idea is to start at the oldest issue and work up from there. So tonight I’m tackling #4797.
This issue is all about reserved filenames
in Windows.
In particular,
there are ancient MS-DOS filenames
such as PRN
and COM1
and LPT2
that today serve as landmines
in the file system’s namespace.
Since I committed to this issue,
back when I was being a nice guy,
the goal for tonight is to prevent
the user from hitting those landmines
with a nice error message.
How far will I go?
I haven’t decided.
This issue is specifically targeted
at the MediaTemplate/@CabinetTemplate
attribute
because it is possible
to step on one of those MS-DOS landmines
without realizing it.
But, in reality,
there are a great many places
where we work with filenames
that could benefit from being protected.
Time to start coding.
git fetch upstream
git merge --ff --ff-only upstream/develop
git checkout -b 4797-bad-filenames
Commit
The first step was research: What exactly are all the invalid filenames? A quick Bing search led me to StackOverflow. We’re not surprised are we?
The StackOverflow information was helpful. Particularly the link to the MSDN documentation. But the solutions gave me pause. Regular expressions. Raymond Chen’s words always haunt me when I see regex proposed as the solution. But we already had a number of regular expressions in the WiX Toolset. Wouldn’t this be more of the same?
Probably.
But, honestly, the proposed solutions were overkill. All I needed to protect against were valid filenames that do bad things. Like those that output your cabinets to the serial port.
So it was time to find the code in question.
Quick jump into AutoMediaAssigner.cs
found the cabinet template being used in AddMediaRow()
.
That was as I expected.
Then I started wonder where to put the filename validation.
I walked the code back to where the cabinets are created
in CreateCabinetWorkItem()
in Binder.cs
.
There I saw the use of FileTransfer
and immediately thought “Perfect!”
I should be able to solve this problem globally
without too much risk.
Then I saw the handling
for embedded cabinets right there as well
and that made me wonder
if embedded cabinets suffered from the same name restrictions.
A quick test:
<MediaTemplate CabinetTemplate="COM{0}" EmbedCab="yes" />
and I had my answer. “Nope. Embedded cabinets were fine.”
Oh, and yes, if you removed or set EmbedCab='no'
then the build would hang
as the bug said it would.
Now I had my solution.
I was not going to put the check
in the AutoMediaAssigner
because that would block valid usage for embedded cabinets.
Blocking people from using valid embedded cabinet names
would be a breaking change (very, very bad)
and incorrect (also very bad).
Plus it wouldn’t catch FileTransfer
requests
that would step on the landmine.
The only downside with validating
in the FileTransfer
request
is the error will happen
after the cabinet is created.
That means you’d pay the cost
of building the cabinet
before you find out the filename is bad.
The ideal would be if the FileTransfer
requests
were created before cabinets
so the error message would before the cabinet creation.
But that scope of change
is something to consider in WiX v4
not WiX v3.x.
Now I just needed to add some validation code to FileTransfer.TryCreate()
and update the InvalidFileName
message
to include information about our MS-DOS landmines.
git commit -a
> Protect against use of reserved file names
>
> Windows has a set of reserved file names such as `CON`, `NUL`, `COM1`,
> `LPT2`. Creating files with those names will result in all sorts of
> undesirable behavior, the most common is that that the build hangs.
> Now we'll catch use of reserved names and print out a helpful error
> message.
>
> Fixes wixtoolset/issues#4797
Until next time! Keep coding. You know I am.