http://bugs.winehq.org/show_bug.cgi?id=25740
Summary: setupapi: registry values missing %token% replacement (dynamic strings, updspapi) (Windows PowerShell 2.0) Product: Wine Version: 1.3.11 Platform: x86 OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: setupapi AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net
Hello,
trying to start the Windows PowerShell Integrated Scripting Environment (ISE) after installing Windows PowerShell 2.0 fails.
--- snip --- $ wine powershell_ise.exe ... Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Value cannot be null. Parameter name: window at System.Windows.MessageBox.Show(Window owner, String messageBoxText, String caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult) at Microsoft.Windows.PowerShell.Gui.Internal.Program.Initialize() --- End of inner exception stack trace --- at Microsoft.Windows.PowerShell.GuiExe.Internal.GPowerShell.Main(String[] args) wine: Unhandled exception 0xe0434f4d at address 0x7b838ce2 (thread 0009), starting debugger... --- snip ---
The real cause is the inability to locate/load the assembly "CompiledComposition.Microsoft.PowerShell.GPowerShell.dll" leading to later crash.
The path to assembly is resolved using registry:
--- snip --- 0026:Call advapi32.RegOpenKeyExW(80000002,009bf828 L"Software\Microsoft\PowerShell\1\PowerShellEngine",00000000,00020019,0032ece8) ret=0036a6a7 0026:Ret advapi32.RegOpenKeyExW() retval=00000000 ret=0036a6a7 ... 0026:Call advapi32.RegQueryValueExW(00000180,009bf770 L"ApplicationBase",00000000,0032ed18,00000000,0032ed1c) ret=0036a7aa 0026:Ret advapi32.RegQueryValueExW() retval=00000000 ret=0036a7aa ... 0026:Call KERNEL32.GetFullPathNameW(0032ea1c L"%SystemRoot%\system32\WindowsPowerShell\v1.0\CompiledComposition.Microsoft.PowerShell.GPowerShell.dll",00000105,0032e810,00000000) ret=0036a1c3 0026:Ret KERNEL32.GetFullPathNameW() retval=00000073 ret=0036a1c3 --- snip ---
Registry export:
--- snip --- REGEDIT4
[HKEY_LOCAL_MACHINE\Software\Microsoft\PowerShell\1\PowerShellEngine] "ApplicationBase"="%SystemRoot%\system32\WindowsPowerShell\v1.0" "ConsoleHostAssemblyName"="Microsoft.PowerShell.ConsoleHost,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35,ProcessorArchitecture=msil" "ConsoleHostModuleName"=""%SystemRoot%\system32\WindowsPowerShell\v1.0\Microsoft.PowerShell.ConsoleHost.dll"" "PowerShellVersion"="2.0" "PSCompatibleVersion"="1.0,2.0" "RuntimeVersion"="v2.0.50727" --- snip ---
The path contains "%SystemRoot%" token which should have been deformated at _install_ time (.NET app code directly takes the path string).
From the setupapi/updspapi based installer's update.inf:
--- snip --- ... [ProductInstall.GlobalRegistryChanges.Install]
AddReg=PowerShell.Add.Reg DelReg=PowerShell.Del.Reg
... [PowerShell.Add.Reg] HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"ApplicationBase",0x00000000,%SystemRoot%\system32\WindowsPowerShell\v1.0 HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"ConsoleHostAssemblyName",0x00000000,"Microsoft.PowerShell.ConsoleHost,Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35,ProcessorArchitecture=msil" HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"ConsoleHostModuleName",0x00000000,"""%SystemRoot%\system32\WindowsPowerShell\v1.0\Microsoft.PowerShell.ConsoleHost.dll""" HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"PowerShellVersion",0x00000000,"2.0" HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"PSCompatibleVersion",0x00000000,"1.0,2.0" HKLM,SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine,"RuntimeVersion",0x00000000,"v2.0.50727" HKLM,SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell,"Path",0x00000000,%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
--- snip ---
There are also %token% strings which are _not_ to be replaced, hence the double % quoting:
--- snip --- HKLM, SYSTEM\CurrentControlSet\Services\WinRM\Parameters, ServiceDll, 0x00020000, "%%SystemRoot%%\system32\WsmSvc.dll" --- snip ---
MSDN says about the "INF AddReg Directive": http://msdn.microsoft.com/en-us/library/ff546320.aspx
--- snip --- [add-registry-section] reg-root, [subkey],[value-entry-name],[flags],[value]
... value
... The expression of such a value depends on the registry type specified for the flag, as follows:
* A registry string-type value can be expressed either as a "quoted string" or as a %strkey% token defined in a Strings section of the INF file. Such an INF-specified value does not have to include a NULL terminator at the end of each string. ... --- snip ---
There is a "dynamic strings" directive present in .inf file:
--- snip --- [DynamicStrings] SystemRoot=InstallPathEnvVar,SystemRoot --- snip ---
This part is processed by installer, updspapi.UpdSpSetDynamicStringA gets called:
--- snip --- 0023:Call setupapi.SetupFindFirstLineA(00144c68,01025d10 "DynamicStrings",00000000,0033bb94) ret=010758be 0023:Call ntdll.RtlCreateUnicodeStringFromAsciiz(0033baa8,01025d10 "DynamicStrings") ret=688f6bbf 0023:Ret ntdll.RtlCreateUnicodeStringFromAsciiz() retval=00000001 ret=688f6bbf 0023:trace:setupapi:SetupFindFirstLineW (0x144c68,L"DynamicStrings",(null)): returning 63/0 .. 0023:Call msvcrt._vsnprintf(0033b34b,000007f7,01025830 "ProcessDynamicStrings: InstallPathEnvVar for %s returned %s",0033bb80) ret=010706ea ... 0023:Call updspapi.UpdSpSetDynamicStringA(00144c68,010f4940 "SystemRoot",001b7108 "C:\windows") ret=01075d51 0023:fixme:updspapi:UpdSpSetDynamicStringA 0x144c68 "SystemRoot" "C:\windows" 0023:Ret updspapi.UpdSpSetDynamicStringA() retval=00000001 ret=01075d51 ... 0023:Call msvcrt._vsnprintf(0033b34b,000007f7,01025754 "ProcessDynamicStrings: all %%%s%% replaced with %s.",0033bb80) ret=010706ea --- snip ---
Setupapi installer log:
--- snip --- 2.734: ProcessDynamicStrings: InstallPathEnvVar for SystemRoot returned C:\windows 2.734: ProcessDynamicStrings: all %SystemRoot% replaced with C:\windows. --- snip ---
At later stage, when the registry section is processed:
--- snip --- 0023:trace:setupapi:SetupFindNextMatchLineW (0x144c68,L"ProductInstall.GlobalRegistryChanges.Install",L"AddReg"): returning 2 0023:trace:setupapi:SetupGetStringFieldW context 0x144c68/0x144c68/10/2 index 1 returning L"PowerShell.Add.Reg" 0023:trace:setupapi:SetupFindFirstLineW (0x144c68,L"PowerShell.Add.Reg",(null)): returning 48/0 0023:trace:setupapi:SetupGetStringFieldW context 0x144c68/0x144c68/48/0 index 1 returning L"HKLM" 0023:trace:setupapi:SetupGetStringFieldW context 0x144c68/0x144c68/48/0 index 2 returning L"SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine" ... 0023:trace:setupapi:SetupGetStringFieldA context 0x144c68/0x144c68/48/0 index 4 returning "0x00000000" 0023:Call advapi32.RegCreateKeyExW(80000002,0033935c L"SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine",00000000,00000000,00000000,02000000,00000000,0033b37c,00000000) ret=688ec641 0023:Ret advapi32.RegCreateKeyExW() retval=00000000 ret=688ec641 0023:trace:setupapi:registry_callback key 0x80000002 L"SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine" 0023:trace:setupapi:SetupGetStringFieldW context 0x144c68/0x144c68/48/0 index 3 returning L"ApplicationBase" ... 0023:trace:setupapi:SetupGetStringFieldW context 0x144c68/0x144c68/48/0 index 5 returning L"%SystemRoot%\system32\WindowsPowerShell\v1.0" 0023:trace:setupapi:do_reg_operation setting value L"ApplicationBase" to L"%SystemRoot%\system32\WindowsPowerShell\v1.0" 0023:Call advapi32.RegSetValueExW(0000006c,0033935c L"ApplicationBase",00000000,00000001,0075d100,0000005a) ret=688ec5be 0023:Ret advapi32.RegSetValueExW() retval=00000000 ret=688ec5be ... 0023:Call advapi32.RegCloseKey(0000006c) ret=688ec6ce 0023:Ret advapi32.RegCloseKey() retval=00000000 ret=688ec6ce
--- snip ---
The string field containing %SystemRoot% token never got the replacement value. Updspapi.dll UpdSpSetDynamicStringA() is a stub and does not have any connection to setupapi, maybe this is the problem. Updspapi seems like an internal/private version of Microsofts setupapi library, distributed with installers/SP installers - not to be installed into OS. Unfortunately setting updspapi to "native", skipping Wine's builtin stub crashes the installer.
BTW ... the PowerShell console/command line stuff really integrates nicely now that Wine has proper console support (wineconsole no longer needed).
Regards