August 8th, 2011

What does the CreateProcess function do if there is no space between the program name and the arguments?

In an old discussion of why the Create­Process function modifies its command line, commenter Random832 asked, “What if there is no space between the program name and arguments – like “cmd/?” – where does it put the null then?

The Create­Process function requires a space between the program name and arguments. If you leave out the space, then the arguments are considered as part of the program name (and you’ll almost certainly get ERROR_FILE_NOT_FOUND back).

It sounds like Random832 has confused Create­Process command line parsing with cmd.exe command line parsing. Clearly the two parsers are different; you can see this even without playing with spaces between the program name and the arguments:

C:\>C:\Program Files\Windows NT\Accessories\wordpad.exe
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

If the command line had been parsed by Create­Process, this would have succeeded in running the Wordpad program, because, as I noted in the original article, the Create­Process function modifies its command line in order to find where the program name ends and the command lines begin, an example of which can be found in the Create­Process documentation. In this case, it would have plunked the null character into each of the spaces in the command line, finding that each one failed, until it finally tried treating the entire string as the program name, at which point it would have succeeded. The fact that it failed demonstrates that Create­Process didn’t do the parsing.

The cmd.exe program permits the space between a program name and its arguments to be elided if the arguments begin with a character not permitted in file names. Once it figures out what you’re running, and it determines that what you’re running is a program, it call the Create­Process function with an explicit application and command line.

But you don’t have to take my word for it. You can just see for yourself. (In fact, this is exactly what I did to investigate the issue in the first place.)

C:>ntsd -2 cmd.exe

Two windows will open, one for your debugger and one for cmd.exe. (You are welcome to replace ntsd with your favorite debugger. I chose ntsd because—at least until Windows XP—it came preinstalled, thereby avoiding multiplying the problem from one to two.)

In the debugger, set a breakpoint on kernel32!Create­ProcessW, then resume execution. In the cmd.exe window, type cmd/?. The breakpoint will fire, and you can look at the parameters:

Breakpoint 0 hit
eax=0046f600 ebx=00000000 ecx=004f8de0 edx=00000000 esi=00000000 edi=00000001
eip=757820ba esp=0046f544 ebp=0046f704 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!CreateProcessW:
757820ba 8bff            mov     edi,edi
0:000> dd esp l4
0046f544  4a5e3dd7 004f5420 004f8db0 00000000
0:000> du 004f5420
004f5420  "C:\Windows\system32\cmd.exe"
0:000> du 004f8db0
004f8db0  "cmd /?"

Observe that cmd.exe did its own manual path search to arrive at an executable of C:\Windows\system32\cmd.exe, and also that it secretly inserted a space between the cmd and the slash.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.