Defense in depth -- the Microsoft way (part 27): the command line you get differs from the command line I use to call you

From: Stefan Kanthak <>
Subject: Defense in depth -- the Microsoft way (part 27): the command line you get differs from the command line I use to call you

Hi @ll,

on Windows, the command line an application receives can differ
from the command line the calling application supplies to

The documentation of GetCommandLine()
<> tells:

| Note  The name of the executable in the command line that
| the operating system provides to a process is not necessarily
| identical to that in the command line that the calling process
| gives to the CreateProcess function. The operating system may
| prepend a fully qualified path to an executable name that is
| provided without a fully qualified path.

This is not the whole truth, another "Note" is missing there:
when CreateProcess*() is called using a command line with an
UNQUOTED "long" filename/pathname containing spaces (a well-known
it uses try&error to guess the pathname of the executable.

The documentation of CreateProcess()
<> tells:

| [...] the module name must be the first white space-delimited
| token in the lpCommandLine string. If you are using a long file
| name that contains a space, use quoted strings to indicate where
| the file name ends and the arguments begin; otherwise, the file
| name is ambiguous. For example, consider the string
| "c:\program files\sub dir\program name".
| This string can be interpreted in a number of ways. The system
| tries to interpret the possibilities in the following order:
|    c:\program.exe files\sub dir\program name
|    c:\program files\sub.exe dir\program name
|    c:\program files\sub dir\program.exe name
|    c:\program files\sub dir\program name.exe

In the latter 3 cases the command line is but modified too:
Windows adds quotes around the part of the command line which
forms the result of this "interpretation" and yields the path
to the executable if this part contains a space.

The 4 command lines shown above are transformed into:

    c:\program.exe files\sub dir\program name
    "c:\program files\sub.exe" dir\program name
    "c:\program files\sub dir\program.exe" name
    "c:\program files\sub dir\program name.exe"

JFTR: without this transformation splitting of the command line
      into the "argv" vector would give wrong results ... in
      presense of CreateProcess*() braindead behaviour!

Stay tuned!

Stefan Kanthak

PS: the documentation of CommandLineToArgvW()
    contains a "funny" and surprising remark:

    | This function accepts command lines that contain a program name;
    | the program name can be enclosed in quotation marks or not.

    This does but NOT mean that CommandLineToArgvW() tries to
    guess like CreateProcess()!
    It treats c:\program files\sub dir\program name
    as "c:\program" "files\sub" "dir\program" "name".

Copyright © 1995-2020 All rights reserved.