[9.0rc4] Non-consistent empty var expanding in command field

The behaviour described in the bug report is either by design, or would be far too complex/time-consuming to be changed

Moderators: Hacker, petermad, Stefan2, white

Post Reply
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

[9.0rc4] Non-consistent empty var expanding in command field

Post by *MVV »

I know that it is a non-standard thing to have empty envvars but there is something strange with them, TC behaves inconsistently.

You need some empty envvar for test, they may be defined with e.g. Autorun plugin using following config lines:

Code: Select all

SetEnv ADM 
SetEnv NONE_OR_64 
So, strange things:
1. TC expands empty var in program path (first use) but not in rest of command line (second use):

Code: Select all

"D:\notepad.exe%NONE_OR_64%.exe" File%NONE_OR_64%.txt
2. This doesn't work (TC error message) with command line arguments but works if I will specify only program path:

Code: Select all

%ADM%"C:\Windows\notepad.exe" 1.txt
But this works:

Code: Select all

%ADM%"C:\Windows\notepad.exe"
And this works too:

Code: Select all

"%ADM%C:\Windows\notepad.exe" 1.txt
(the reason of having %ADM% here is possibility to set ADM to * under some conditions)
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50550
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Total Commander treats empty environment variables the same as non-existing environment variables. And since paths can actually contain the % character, I ignore environment variables which do not return any texts, so TC can still access real files named something%somethingother%.ext.

I will rather not change that now after so many years, it may break a lot of functions for users who rely on this behaviour.
Author of Total Commander
https://www.ghisler.com
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

But why same empty variable is expanded in one place and don't expanded in other one? And what is with question #2? Why expanding is not the same in all cases?
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50550
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

I have checked my code - TC never replaces %xyz% environment variables when they are empty or non-existant. Maybe Windows itself replaces it after launching?

Anyway, I wonder how you create them, because apparently they are NOT allowed:
Using
set variable=
removes the variable. Trying to set it in Control Panel - System - Advanced does not enable the OK button unless you put at least one character in the variable content.

Therefore I assume that they should not be used.
Author of Total Commander
https://www.ghisler.com
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

Ah, I see in a debugger now, TC just asks ShellExecuteEx to expand variables in file path (and seem to expand empty vars too), but the function doesn't expand them in parameters.

And I see why %ADM%"C:\Windows\notepad.exe" doesn't work - TC doesn't merge joined argument parts (while this syntax is correct for DOS and Windows NT batch files), so ShellExecuteEx receives file path with double quotes in it.

I agree that it is not possible to create such variable from cmd.exe or in System properties dialog, but it seems to be possible via API because Autorun plugin is able to create them.

Also I agree that they shouldn't be used but sometimes they are quite handy when you use same TC installation with different Windows versions (to allow inserting some additional symbols like asterisk or x64 suffixes for application or directory names into command lines).
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

Also I've noticed that ShellExecuteEx "understands" weird program paths like %ADM%"C:\Windows\notepad.exe" (perhaps it expands envvar and then removes outer quotes).

The only thing that is still unclear to me - why does TC pass entire %ADM%"C:\Windows\notepad.exe" 1.txt string as program path to ShellExecuteEx while there is a space in it - and it really looks like some bug.
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50550
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Probably due to the double quotes. There is no space between %ADM% and ".
Author of Total Commander
https://www.ghisler.com
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

But shouldn't TC end first parameter on a space?
User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 50550
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) »

Not when it's in double quotes.
Author of Total Commander
https://www.ghisler.com
User avatar
MVV
Power Member
Power Member
Posts: 8711
Joined: 2008-08-03, 12:51 UTC
Location: Russian Federation

Post by *MVV »

But it is not in double quotes, you see, space is not quoted at all!

I wonder which algorithm TC uses for splitting command line to arguments. Proper one is quite simple:

Code: Select all

isInQuote = false;
loop {
    char c = next string character;
    if c = '"', isInQuote = not isInQuote;
    if c = ' ' and not isInQuote, parameter is over
}
So, only a non-quoted space may separate parameters, and quotes may be in any part of parameter, e.g. one"two three"four is a single parameter. Such rule is used in cmd.exe and standard function CommandLineToArgvW uses it too (however it strips double quotes from parameters, and also does a stupid thing - it allows escaping quoble quotes with backslashes so it may easilly mess things if you pass quoted path with trailing backslash).
Post Reply