WiX

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

Pull request

Until next time! Keep coding. You know I am.