salt: The win_dism module does not work on a 64-bit architecture when running inside a 32-bit process
Description of Issue/Question
On a 64-bit windows system, there are two versions of the DISM.exe
binary. The first one (64-bit) is /Windows/System32/Dism.exe
and the second one (32-bit) is /Windows/SysWOW64/Dism.exe
. The win_dism
module simply trusts that the PATH is set correctly as it just tries to execute “dism”.
It is prudent to note that on 64-bit versions of windows, the directories for /Windows/System32
and /Windows/SysWOW64
have different semantics depending on the architecture of the application that is being used. So the path to the correct instance of Dism.exe
is different depending on the Python interpreter that is running the salt process.
Normally it is assumed that /Windows/SysWOW64
contains the 32-bit binaries (such as Dism.exe
) and /Windows/System32
contains the 64-bit binaries. However, when running a 32-bit application (such as the 32-bit version of Python) both the /Windows/SysWOW64
and /Windows/System32
directories point to the 32-bit binaries for the platform. This is done for compatibility reasons as historically the /Windows/System32
directory contains the system tools available for the platform.
Unfortunately this means that via a 32-bit process, it would normally be impossible to call the correct 64-bit version of Dism.exe
. However, on a 32-bit process windows creates a file-system redirection to the 64-bit platform tools at /Windows/Sysnative
. So depending on the process architecture, the correct path can be either /Windows/System32
or /Windows/Sysnative
.
In summary, if one is running salt on a 32-bit version of Windows. Nothing matters, everything is okay.
If one is running salt on a 64-bit version of Windows, then the correct path to Dism.exe
depends on the architecture of the Python interpreter that is running.
If salt is running in a 32-bit interpreter, then the path to the 64-bit Dism.exe
is at /Windows/Sysnative/Dism.exe
. If salt is running in a 64-bit interpreter, then the path to the 64-bit Dism.exe
is at /Windows/System32
.
Symptom (in minion log file)
2019-02-27 09:29:52,104 [salt.minion :1667][WARNING ][2740] The minion function caused an exception
2019-02-27 09:30:02,510 [salt.loaded.int.module.cmdmod:774 ][ERROR ][3132] Command '[u'DISM', u'/English', u'/Online', u'/Get-Features']' failed with return code: 11
2019-02-27 09:30:02,510 [salt.loaded.int.module.cmdmod:776 ][ERROR ][3132] stdout:
Deployment Image Servicing and Management tool
Version: 6.2.9200.16384
Error: 11
You cannot service a running 64-bit operating system with a 32-bit version of DISM.
Please use the version of DISM that corresponds to your computer's architecture.
The DISM log file can be found at C:\Windows\Logs\DISM\dism.log
2019-02-27 09:30:02,510 [salt.loaded.int.module.cmdmod:780 ][ERROR ][3132] retcode: 11
Setup
Install a 64-bit version of Windows that is newer than Vista (inclusive), and then use the 32-bit salt-minion so that a 32-bit version of Python gets installed.
Steps to Reproduce Issue
Try to use anything in the win_dism
module such as get_features
or something… Another way to prove that the wrong one is being executed would be to use cmd.which
as so:
$ salt $target cmd.which Dism
bX_nxPEVRyWOcIDBECwW:
C:\Windows\system32\dism.EXE
-------------------------------------------
Summary
-------------------------------------------
# of minions targeted: 1
# of minions returned: 1
# of minions that did not return: 0
# of minions with errors: 0
-------------------------------------------
If the path to the System32 Dism.exe
is returned, then the win_dism
module will not work despite the tool being available
Notes
Really this will happen with all the platform tools on Windows. If one wants to avoid smashing gophers related to calling the wrong tool, there should be a utility to locate platform-specific tools. It’s really not safe/reliable to explicitly trust the PATH environment to locate these types of tools.
Versions Report
This is independant of the version as none of the commits try to do anything funny with /Windows/System32/Sysnative
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 22 (22 by maintainers)
lol, that first case that tests for Windows should be inverted. but i think you get it…
Although using
.get()
is useful in some cases, it tends to hide errors.Rather than changing the semantics of
which
, which is well-defined, wouldn’t it be safer to modify the dism module to call%windir%\Sysnative\Dism.exe
, and then on failure call%windir%\System32\Dism.exe
?