v8.51a (and also v8.01/v7.xx) – Error of launching programs

Please report only one bug per message!

Moderators: sheep, Hacker, Stefan2, white

k3g
Junior Member
Junior Member
Posts: 3
Joined: 2014-09-09, 09:30 UTC

v8.51a (and also v8.01/v7.xx) – Error of launching programs

Post by *k3g » 2014-09-09, 11:19 UTC

When activated the Terminal Server service it is impossible to start programs which are located in “c:\Windows\”.
For example regedit.exe.

Total Commander x64 gives out the error “Access denied!”

Probably the problem in using of function GetWindowsDirectory
The Windows directory is the directory where some legacy applications store initialization and help files.
..............
If the user is running a shared version of the system, the Windows directory is guaranteed to be private for each user.
..............
Terminal Services: If the application is running in a Terminal Services environment, each user has a private Windows directory. There is also a shared Windows directory for the system. If the application is Terminal-Services-aware (has the IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag set in the image header), this function returns the path of the system Windows directory, just as the GetSystemWindowsDirectory function does. Otherwise, it retrieves the path of the private Windows directory for the user.
see the image
Image: http://3.firepic.org/3/images/2013-12/18/6n0jz5h6z0wr.jpg

Probably instead of function GetWindowsDirectory it is necessary to use function GetSystemWindowsDirectory.
Last edited by k3g on 2014-09-11, 11:22 UTC, edited 1 time in total.

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-11, 02:33 UTC

No such a problem under 32-bit Windows Server 2003 SP2 - tested when:
- local user profile redirected to R: (so GetWindowsDirectory returns "R:\Windows"),
- Terminal Services profile redirected to T: (so GetWindowsDirectory returns "T:\Windows").

Regards

k3g
Junior Member
Junior Member
Posts: 3
Joined: 2014-09-09, 09:30 UTC

Post by *k3g » 2014-09-11, 11:18 UTC

MarcinW wrote:No such a problem under 32-bit Windows Server 2003 SP2 - tested when:
- local user profile redirected to R: (so GetWindowsDirectory returns "R:\Windows"),
- Terminal Services profile redirected to T: (so GetWindowsDirectory returns "T:\Windows").

Regards
Unambiguously this problem exists.
I tried on dozen Win2k3 x32 and on dozen Win2k8R2 x64
Take this program and check - https://yadi.sk/d/nJ8250WVbRMwK

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-11, 11:37 UTC

Could you please give step-by-step instructions, how to reproduce the problem?

I just go with TC to the true Windows directory ("C:\Windows") and I can launch regedit.exe without any problems (while the private user Windows directory is "R:\Windows" or "T:\Windows" - I checked also with the sysdirs.exe tool).

Maybe you have no access rights to launch programs from "C:\Windows"? Are you able to launch C:\Windows\regedit.exe from Explorer?

k3g
Junior Member
Junior Member
Posts: 3
Joined: 2014-09-09, 09:30 UTC

Post by *k3g » 2014-09-11, 17:03 UTC

MarcinW wrote:Could you please give step-by-step instructions, how to reproduce the problem?
For example create reg-file and launch it.

MarcinW wrote:Maybe you have no access rights to launch programs from "C:\Windows"?
I perform all actions as administrator and with UAC disabled

MarcinW wrote:Are you able to launch C:\Windows\regedit.exe from Explorer?
Yes, from Explorer launching of reg-file succeeds.

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-12, 04:07 UTC

I can confirm the problem. TC can't launch a REG file from any location, not only from Windows directory.

I can reproduce the problem on a Windows Server 2003 with Terminal Services and Active Directory installed:
1) launch regedit.exe and export any registry key to "C:\test.reg",
2) launch TC and go to "C:\",
4) launch "test.reg" in TC - "access denied" error message appears.

TC fails on ShellExecuteExW call.

When I set the IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag in the DllCharacteristics field of totalcmd.exe, problem disappeared. However, TC is not allowed to use this flag, because it uses INI files: see Application compatibility layer. Because Explorer.exe has this flag set, it can launch REG files successfully.

I also created a small application that calls ShellExecuteExW and allows it to display its own error messages - and "Application not found" error message appears.

ShellExecuteExW reads association for REG files from the registry - by default this is "regedit.exe" - and tries to expand this to a full path. To do this, ShellExecuteExW uses an internal call to the GetWindowsDirectory API.

With IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag set in the main EXE file, GetWindowsDirectory returns the true Windows path, so ShellExecuteExW finds the regedit.exe and launches it.

Without IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag set in the main EXE file, operating system loads tsappcmp.dll for this application - this DLL hooks some API functions, so GetWindowsDirectory returns a redirected Windows directory. ShellExecuteExW can't find the regedit.exe there, so "Application not found" message appears.

I can see a workaround for this problem - TC could have a small utility with IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag set. TC should launch this utility, and this utility should call the ShellExecuteExW API.

Regards

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37024
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2014-09-12, 10:08 UTC

It's the first time I hear about this IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag. Where is this set in the EXE? And why can't it be set for totalcmd.exe?
Author of Total Commander
http://www.ghisler.com

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-12, 18:35 UTC

To be clear: I consider such a Windows behavior as a bug.


The IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag must be set in the PE header of EXE file, in OptionalHeader.DllCharacteristics field. In modern Delphi versions you can use:

Code: Select all

const
  IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;

{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
or just

Code: Select all

{$SetPEOptFlags $8000}
In old Delphi versions you must set this flag manually (or by using some external tool - you may use NTCore Explorer Suite).

Application, by using this flag, tells Windows that it is aware of fact, that multiple users can launch this application at the same time, on the same server machine. So application must conform to some limitations - for example, it can't store settings in INI files in Windows directory, because one user could overwrite INI settings set by other user. Without this flag, OS creates "fake" Windows directory for each user in his home directory and redirects application calls there, so application can write INI files to Windows directory (in fact this "fake" one) - and won't overwrite INI settings of another user.

ghisler(Author) wrote:And why can't it be set for totalcmd.exe?
I wrote this, because TC uses INI files. If you can guarantee, that INI files will not be written to the Windows directory (or subdirectories), you can set this flag for TC. However, location of INI files is user-configurable and, in non-server installations, user may just want to locate INI files in Windows directory, so I think that the best solution would be to create a small tool (similarly to tcmadmin.exe), that has IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag set and calls the ShellExecuteEx API. Unfortunately, creating a DLL with this flag and calling ShellExecuteEx there doesn't help - it must be a separate EXE.


Info about requirements for applications with IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE flag:
- Application compatibility layer - see end of the document
- Application Compatibility Best Practices for Remote Desktop Services.docx
- TS Application Analyzer - info about tool that may be useful

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37024
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2014-09-15, 13:52 UTC

By default, TC writes ini files to user-specific directories now. The user can set the ini location to the windows directory manually, but companies who do this do not want the user to write to the ini anyway. Therefore it shouldn't be a problem.

I already have a patch tool to set certain header flags, so I will try this too.
Author of Total Commander
http://www.ghisler.com

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-15, 20:24 UTC

OK. Just remember to review also the other requirements for this flag.

Regards

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37024
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2014-09-18, 10:06 UTC

Unfortunately I will not be able to set this flag, sorry. Why? The requirements state that ini files must not be used at all. While I could change this in TC, it wouldn't be desirable from the user's point of view. What's worse is that there are 100s of plugins using ini files, many of them are no longer maintained. It's simply not possible to exclude that any of these use ini files.
Author of Total Commander
http://www.ghisler.com

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-18, 20:29 UTC

Ok. However, no problem - you can still create a small helper tool (let's say tcmterm.exe) with this flag set - TC should launch tcmterm.exe, and tcmterm.exe should call ShellExecuteX. This seems to be the safest possible solution.

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37024
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2014-09-22, 09:42 UTC

Does this really help when it is started from TC which does not use the flag?
Author of Total Commander
http://www.ghisler.com

User avatar
MarcinW
Power Member
Power Member
Posts: 852
Joined: 2012-01-23, 15:58 UTC
Location: Poland

Post by *MarcinW » 2014-09-22, 12:42 UTC

Yes, this definitely works.

User avatar
ghisler(Author)
Site Admin
Site Admin
Posts: 37024
Joined: 2003-02-04, 09:46 UTC
Location: Switzerland
Contact:

Post by *ghisler(Author) » 2014-09-25, 14:37 UTC

Another idea: Would it help if TC just added the directory from GetSystemWindowsDirectory to its PATH variable? Windows seems to look in the path when launching a program by name only. Or maybe internally set %windir%?
Yes, this definitely works.
That's strange, programs launched from TC would inherit it's environment variables, so %windir% should be pointing to the wrong location...
Author of Total Commander
http://www.ghisler.com

Post Reply