Two surprising Windows “bugs”

Follow Jacques Bensimon at @JacqBens.

On two recent occasions, I came across a Windows bug (or at the very least “unexpected and surprising behavior”) in the basic behavior of two venerable components (XCopy.exe and CMD.exe) which you’d think after all these years would long ago have been sniffed out and corrected.

XCopy.exe:

An XCopy command of the form

XCopy <some_path>Folder1Folder2<some_file_pattern> <some_target_path>

will *fail* if the executing user account does not have Read (or maybe just List) permissions to Folder1, the *parent* of the folder containing the source files, even if the user has (as Everyone usually does) the “Bypass traverse checking” right (and of course at least Read permissions to Folder2, the folder that actually contains the source files).  The Copy command has no such issue, and neither does Explorer which lets the user open Folder2 directly and copy anything out of it.  Process Monitor shows that, however deep the source path, XCopy always starts off by attempting to open the source folder’s parent (why?) and, when access is denied, exits without an error message but with the message “0 File(s) copied”.

CMD.exe:

This one requires an appreciation for the so-called “C command line parsing rules” (e.g. https://msdn.microsoft.com/en-us/library/a1y7w461.aspx) which pretty much all Windows console programs (whether or not written in C) obey.  For example, if you wish to use Reg.exe to write the path “C:\Program Files (x86)MyApp” (without the double-quotes) to a Registry value, you’d use the syntax

Reg Add HKLM\Software\MyApp /v Path1 /d "C:\Program Files (x86)MyApp" /f

If however you did want the double-quotes around the path in a Registry entry, you would use the syntax  

Reg Add HKLM\Software\MyApp /v Path2 /d ""C:\Program Files (x86)MyApp"" /f

Within a double-quoted parameter, preceding any double-quote with a backslash makes it literal, part of the parameter.  You can put these two lines into a batch file and confirm that they do exactly what they’re supposed to.  Now say that you want to put some condition (doesn’t matter which) on executing these two lines and use the following valid syntax

If %SystemDrive%==C:\

(

Reg Add HKLM\Software\MyApp /v Path1 /d "C:\Program Files (x86)MyApp" /f

Reg Add HKLM\Software\MyApp /v Path2 /d ""C:\Program Files (x86)MyApp"" /f

)

Now the entire thing fails and CMD.exe spits out the message “MyApp"" was unexpected at this time”.  Why?  Well, after the opening parenthesis following the condition test, CMD is parsing what follows looking for the closing parenthesis that completes the command, and it’s smart enough to ignore any closing parenthesis that occurs within double-quotes (such as the closing parenthesis in (x86) within the first Reg command).  But now comes the second Reg command, and by CMD’s “naïve” count of double-quotes, only the first backslash is inside double-quotes, followed by C:\Program Files (x86)”outside” any double-quotes and hey, there’s the closing parenthesis it was looking for, … but wait, what’s this “MyApp""“ stuff that follows??  Parsing error!

To be fair, this may be unresolvable from CMD’s standpoint because it would require it to understand the parameter syntax of arbitrary programs invoked from within a batch file (though in this case the syntax in question is a pretty standard one), and this parsing issue has suddenly become more likely to occur in everyday batch files as a result of Microsoft’s (demented) decision to use parentheses in the name of a standard system folder (combined with the pre-existing use of parentheses to group commands in batch files).  Would using “Program Files x86” have somehow caused difficulties?

As far as getting around this issue should you encounter it, I see no alternative but to abandon structured syntax and fall back on good old “Goto”, as in  

If Not %SystemDrive%==C:\ Goto :Skip

Reg Add HKLM\Software\MyApp /v Path1 /d "C:\Program Files (x86)MyApp" /f

Reg Add HKLM\Software\MyApp /v Path2 /d ""C:\Program Files (x86)MyApp"" /f

:Skip

Later,

J3

TAGS