https://bugs.winehq.org/show_bug.cgi?id=48993
Bug ID: 48993 Summary: 64-bit Powershell 2.0 for Windows 2003 installer fails due to missing 'scecli.dll' Product: Wine Version: 5.6 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
as it says. Mentioned a few times:
* https://bugs.winehq.org/show_bug.cgi?id=25740#c8 * https://bugs.winehq.org/show_bug.cgi?id=25740#c15 * https://bugs.winehq.org/show_bug.cgi?id=26016#c20 * https://bugs.winehq.org/show_bug.cgi?id=35891#c0
Download:
https://web.archive.org/web/20120528222714/http://download.microsoft.com/dow...
Prerequisite:
* 'winetricks -q dotnet20sp1' * 'winecfg /v win2003'
--- snip --- $ WINEDEBUG=+seh,+loaddll,+process,+relay taskset -c 0 wine ./WindowsServer2003-KB968930-x64-ENG.exe >>log.txt 2>&1 ... 0096:Call KERNEL32.CreateProcessA(00000000,0100d3e0 "c:\f95bd3e38ba11de93611\update\update.exe",00000000,00000000,00000000,00000020,00000000,0123d738 "c:\f95bd3e38ba11de93611\update",0032fe2c,0032fe94) ret=01005d78 ... 0096:trace:process:CreateProcessInternalW started process pid 00bc tid 00bd ... 0096:Ret KERNEL32.CreateProcessA() retval=00000001 ret=01005d78 ... 00bd:Call setupapi.SetupFindFirstLineA(01a801d0,100014668 "SecurityServiceAfterInstall",00000000,0022af50) ret=1000a232a ... 00bd:Call ucrtbase._wcsicmp(01bb6360 L"SecurityServiceAfterInstall",025ff678 L"Strings") ret=00250421 00bd:Ret ucrtbase._wcsicmp() retval=fffffff1 ret=00250421 ... 00bd:Ret setupapi.SetupFindFirstLineA() retval=00000000 ret=1000a232a 00bd:Call KERNEL32.LoadLibraryW(100024908 L"scecli.dll") ret=1000a2524 ... 00bd:Ret KERNEL32.LoadLibraryW() retval=00000000 ret=1000a2524 ... 00bd:Call KERNEL32.GetLastError() ret=1000a27c5 00bd:Ret KERNEL32.GetLastError() retval=0000007e ret=1000a27c5 ... 00bd:Call user32.MessageBoxA(00000000,10013b660 "Invalid handle.\r\n",1000ef0e0 "Windows Management Framework Core Setup Error",00011010) ret=10008a747 --- snip ---
$ sha1sum WindowsServer2003-KB968930-x64-ENG.exe 8ba702aa016e4c5aed581814647f4d55635eff5c WindowsServer2003-KB968930-x64-ENG.exe
$ du -sh WindowsServer2003-KB968930-x64-ENG.exe 9.9M WindowsServer2003-KB968930-x64-ENG.exe
$ wine --version wine-5.6-299-gf65cfbfe9b
Regards
https://bugs.winehq.org/show_bug.cgi?id=48993
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL| |https://web.archive.org/web | |/20120528222714/http://down | |load.microsoft.com/download | |/f/1/4/f14d3ac7-086f-4ccd-9 | |73f-e9820cae39bb/WindowsSer | |ver2003.WindowsXP-KB926139- | |v2-x64-ENU.exe Keywords| |download, Installer
https://bugs.winehq.org/show_bug.cgi?id=48993
Leith Bade leith@bade.nz changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |leith@bade.nz
--- Comment #1 from Leith Bade leith@bade.nz --- Did some poking into this yesterday. After adding the scecli.dll file from the Windows 7 SP1 installer, further relay tracing reveals that the particular function update.exe wants is SceConfigureSystem: --- snip --- 002d:Call KERNEL32.LoadLibraryW(100024908 L"scecli.dll") ret=1000a2524 ... 002d:Ret KERNEL32.LoadLibraryW() retval=64200000 ret=1000a2524 002d:Call KERNEL32.GetProcAddress(64200000,1000248f0 "SceConfigureSystem") ret=1000a2540 002d:Ret KERNEL32.GetProcAddress() retval=6420100c ret=1000a2540 --- snip ---
update.exe then continues to generate a temporary file: 002d:Call KERNEL32.GetWindowsDirectoryW(0022a6e0,00000104) ret=1000a255c 002d:Ret KERNEL32.GetWindowsDirectoryW() retval=0000000a ret=1000a255c 002d:Call KERNEL32.GetTempFileNameW(0022a6e0 L"C:\windows",1000248e8 L"SEC",00000000,0022a8f0) ret=1000a2579 ... 002d:Ret KERNEL32.GetTempFileNameW() retval=00007b26 ret=1000a2579 002d:Call KERNEL32.CreateFileW(0022a8f0 L"C:\windows\SEC7b26.tmp",40000000,00000001,00000000,00000004,00000080,00000000) ret=1000a25a7 ... 002d:Ret KERNEL32.CreateFileW() retval=00000080 ret=1000a25a7 002d:Call KERNEL32.WriteFile(00000080,1000243b0,00000069,0022a6d8,00000000) ret=1000a2675 ... 002d:Ret KERNEL32.WriteFile() retval=00000001 ret=1000a2675 002d:Call KERNEL32.WriteFile(00000080,009e2050,00000021,0022a680,00000000) ret=1000a1d21 ... 002d:Ret KERNEL32.WriteFile() retval=00000001 ret=1000a1d21 002d:Call KERNEL32.WriteFile(00000080,100024778,00000013,0022a018,00000000) ret=1000a2095 ... 002d:Ret KERNEL32.WriteFile() retval=00000001 ret=1000a2095 ... 002d:Ret KERNEL32.CloseHandle() retval=00000001 ret=1000a26ed 002d:Call msvcrt._vsnwprintf(0022ad10,00000103,100024850 L"%s\security\database\%s.sdb",0022a688) ret=1000a1f3b 002d:Ret msvcrt._vsnwprintf() retval=00000029 ret=1000a1f3b 002d:Call msvcrt._vsnwprintf(0022ab00,00000103,100024820 L"%s\security\logs\%s.log",0022a688) ret=1000a1f3b 002d:Ret msvcrt._vsnwprintf() retval=00000023 ret=1000a1f3b ... 002d:Call KERNEL32.DeleteFileW(0022a8f0 L"C:\windows\SEC7b26.tmp") ret=1000a25eb ... 002d:Ret KERNEL32.DeleteFileW() retval=00000001 ret=1000a25eb 002d:Call KERNEL32.FreeLibrary(64200000) ret=1000a2609 ... 002d:Ret ntdll.LdrUnloadDll() retval=00000000 ret=7b01da92 002d:Ret KERNEL32.FreeLibrary() retval=00000001 ret=1000a2609 -- snip ---
This file appears to be a security policy template file (which the various Windows security tools can import and export) which changes the permissions on various registry keys: --- snip --- [Unicode] Unicode=yes [Version] signature="$CHICAGO$" Revision=1 [Profile Description] Description=Windows Management Framework Core [Registry Keys] "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Listener",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Plugin",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Service",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Client",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\CertMapping",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\WinRS",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\WinRS\CustomRemoteShell",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\EventCollector",2,"D:(A;CI;GA;;;BA)(A;CI;GA;;;NS)" --- snip ---
As for where these values come from it appears update.exe searches for various special sections in the update.inf file: --- snip --- 002d:Call setupapi.SetupFindFirstLineA(0081b5a0,1000146a8 "SecurityRegistryAfterInstall",00000000,0022af50) ret=1000a232a ... 002d:Call setupapi.SetupFindFirstLineA(0081b5a0,100014688 "SecurityFileAfterInstall",00000000,0022af50) ret=1000a232a ... 002d:Call setupapi.SetupFindFirstLineA(0081b5a0,100014668 "SecurityServiceAfterInstall",00000000,0022af50) ret=1000a232a --- snip ---
Having a look at the update.inf reveals there is a SecurityRegistryAfterInstall section: --- snip --- ... [SecurityRegistryAfterInstall] "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Listener",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Plugin",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Service",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\Client",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\CertMapping",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;NS)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\WinRS",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" "MACHINE\Software\Microsoft\Windows\CurrentVersion\WSMAN\WinRS\CustomRemoteShell",2,"D:P(A;CI;GA;;;BA)(A;CI;GR;;;WD)S:P(AU;CISAFA;GW;;;WD)" ... [SecurityRegistryAfterInstall] "MACHINE\Software\Microsoft\Windows\CurrentVersion\EventCollector",2,"D:(A;CI;GA;;;BA)(A;CI;GA;;;NS)" ... -- snip --
So it appears the purpose of calling SceConfigureSystem is to apply some security changes to new files or registry keys or services. However it seems the function itself does not make changes to the system. On a real Windows machine it looks like there is an RPC service called scesrv.dll that must actually apply the changes.
Google revealed a file that indicates SceConfigureSystem possibly takes 8 parameters - https://github.com/tonado/MASM32-SDK/blob/master/include/scecli.inc
So I created a stub function and got this from the relay trace after deducing three parameters are strings: --- snip --- 002d:Call scecli.SceConfigureSystem(00000000,0022a8f0 L"C:\windows\SEC7b26.tmp",0022ad10 L"C:\windows\security\database\KB968930.sdb",0022ab00 L"C:\windows\security\logs\update.log",100000012,000000e0,00000000,00000000,00000000) ret=1000a2780 ... 0x00000000 L"C:\windows\SEC7b26.tmp" L"C:\windows\security\database\KB968930.sdb" L"C:\windows\security\logs\update.log" 0x00000012 0x000000e0 0x00000000 0x00000000 0x00000000: stub ... 002d:Ret scecli.SceConfigureSystem() retval=00000000 ret=1000a2780 --- snip ---
The first parameter is always zero, perhaps this is an optional pointer or handle to something. The second is the path to the security template file to apply. The third appears to be a path to a security database file to write out. It seems this is the main file used for security policies in Windows, e.g. the default system settings are in C:\windows\security\secedit.sdb. It's purpose here might to be save the changes made by the installer so that they can be reversed during uninstallation. The fourth appears to be a path to a log file. The fifth value appears to be set to 12h. The sixth value appears to always be set to e0h.
A zero return value appears sufficient to satisfy update.exe and allows it to finish.
It seems adding a stub function will be enough to fix this bug. Is there a way to verify the number of arguments on the stack expected by SceConfigureSystem? Similarly is there a way to know if the remaining arguments should be treated as pointers, or as integers?
https://bugs.winehq.org/show_bug.cgi?id=48993
--- Comment #2 from Leith Bade leith@bade.nz --- Created attachment 66969 --> https://bugs.winehq.org/attachment.cgi?id=66969 Patch to add a stub for SceConfigureSystem
Stops the WMF 2.0 installer from failing.
https://bugs.winehq.org/show_bug.cgi?id=48993
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch Summary|64-bit Powershell 2.0 for |64-bit Windows Management |Windows 2003 installer |Framework 2.0 for Windows |fails due to missing |2003 installer fails with |'scecli.dll' |error 'Invalid handle' | |(needs | |'scecli.SceConfigureSystem' | |stub)
--- Comment #3 from Anastasius Focht focht@gmx.net --- Hello Leith,
thanks for the patch. I'm refining the summary to highlight it's that one stub function needed which implies the addition of the stub dll as well.
--- quote --- Is there a way to verify the number of arguments on the stack expected by SceConfigureSystem? --- quote ---
There are a few techniques if you don't know the prototype when no documentation/SDK headers exist. All of that requires that the general rules of the Wine project w.r.t. reverse engineering are obeyed.
1) Analyse the caller of the API function (= application) and check how the stack is set up. Most of the time the number and type of arguments can be deduced fairly easily. This technique should only be used if the caller itself is not subject to reverse engineering restrictions (not part of OS)
2) Write a test case that does argument fuzzing, i.e. calls the unknown API function with varying number of arguments. You start with one argument (DWORD type) and check for stack imbalance (STDCALL).
--- quote --- Similarly is there a way to know if the remaining arguments should be treated as pointers, or as integers? --- quote ---
After figuring the out the number of arguments you take a look at the value range. Specific types (pointers, handle, enums) have distinct ranges. For example if you see a value that matches the return/out value of preceding win32 API calls, i.e. CreateFile(), HeapAlloc(), MultiByteToWideChar() you can deduce the type and purpose of parameters this way. For structure layout/unknown members it's more complicated. You use "magic" patterns to figure out which fields/offsets have been written to and interpret the value ranges again.
I wouldn't bother too much here since only a stub is needed. If you look at Wine source, there are multiple places where stubs exist where only the number of arguments are known, gathered by above mentioned techniques.
--- snip --- $ egrep -Hrni "(unk1|unknown1)" --- snip ---
Regards