May 15th, 2006

The first word on the command line is the program name only by convention

The format of the command line returned by GetCommandLine is “program args“, but this is only a convention. If you pass NULL for the lpApplicationName to the CreateProcess function, then the CreateProcess function will treat the first word of the lpCommandLine as the program name. However, if you pass a value for lpApplicationName, then that string determines the program that is run, and the string passed as the lpCommandLine is not used for that purpose. This means that if somebody runs your program with the following parameters to the CreateProcess function

lpApplicationName  =  "C:\Path\To\Program.exe"
lpCommandLine  =  "slithy toves"

then when your program calls the GetCommandLine function, it will get the string "slithy toves", which doesn’t give your program much help at all in determining its own name or location. If your program needs to determine its own name and location, use the GetModuleFileName function, as I noted some time ago. What is the point of letting a program specify something different as the first word on the command line from the actual program being run? There isn’t much point to it in Windows, although it is used to greater effect in unix, where you can run a program under various “alias” names, executing one program but lying to it and putting a different name at the start of the command line. Some programs are specially designed to be run this way and alter their behavior depending on the “alias” name they were given. For example, the visual editor runs in screen mode if its name is given as "vi" but in line mode if its name is given as "ex". Although extremely few Windows programs use this quirk (I am not aware of any myself), the behavior nevertheless is supported, and you need to be aware of it when writing your own program, even if you don’t intend to use it. For example, if you forget to repeat the program name on the command line and create the process like this

lpApplicationName  =  "C:\Path\To\Program.exe"
lpCommandLine  =  "arg1 arg2"

then when that program runs, you will most likely see it ignore the arg1 because it thinks that arg1 is just the program name. If that program is a console program that uses the C runtime startup code, then it will receive its parameters as

argv[0]  =  "arg1"
argv[1]  =  "arg2"

As I noted earlier, most console programs merely ignore their argv[0] since that slot is just the program name. (In this case, it’s the alias program name, but the program being run doesn’t know that.) Similarly, if the program is a Windows program that uses the C runtime startup code, then the C runtime startup code will merely skip over the first word on the command line, passing "arg2" to the WinMain function as its lpCmdLine.

What was the point of all this discussion? Two things. First, that if you are launching other programs and passing an explicit lpApplicationName, then it behooves you to format the command line in a compatible manner. Otherwise, the results may not be what you expect. Second, that you as a program should not use the first token on the command line to control any security decisions since the value is controlled by the launcher and need not have any connection to reality.

Topics
Other

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.