I have a windows-free installation of current CVS wine, with wordpad.exe and the needed DLLs pulled in from a Windows ME installation. wordpad works great. However, ShellExecute(... "wordpad.exe", ".\stl\readme.wri" ...) is failing to find wordpad.exe for me. (The call in question is issued by the msvc4.0 setup.exe. The current directory when I run this is /mnt/cdrom, and stl/readme.wri is indeed there.)
To get some insight on how this is supposed to work, I went to a real Windows Me system, searched the registry for references to "wordpad.exe", and removed them, one by one, testing after each deletion. The reference that mattered was [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WORDPAD.EXE] @="C:\Progra~1\Access~1\WORDPAD.EXE"
So I ran "regedit foo.reg" to import the above registry key, and made sure it does show up in ~/.wine/system.reg. Still didn't work.
I then ran wine --debugmsg +exec,+file,+reg setup.exe to see whether Wine was properly searching that registry key. Sure enough, Wine is trying to search that key, and it's not finding it. So... what's wrong? Best I can figure is there's something fishy about what registry file is being loaded. Here are the interesting bits of the log (word wrapped, unfortunately):
--------------------- ... trace:reg:NtQueryValueKey (0x24,L"LoadWindowsRegistryFiles",2,0xbfffe7fc,1024) trace:reg:_w31_loadreg (void) trace:file:FILE_DoOpenFile reg.dat OF_READ OF_SHARE_COMPAT trace:file:FILE_DoOpenFile reg.dat 0000 trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0xbfffbb08) trace:reg:NtOpenKey <- (nil) warn:file:FILE_DoOpenFile 'reg.dat' not found or sharing violation warn:file:FILE_DoOpenFile (reg.dat): return = HFILE_ERROR error= 2 trace:reg:NtQueryValueKey (0x24,L"LoadGlobalRegistryFiles",2,0xbfffe7fc,1024) trace:reg:NtQueryValueKey (0x24,L"GlobalRegistryDir",2,0xbfffe7fc,1024) trace:reg:SHELL_LoadRegistry GlobalRegistryDir is '/usr/local/etc'. warn:reg:_get_wine_registry_file_format_version Couldn't open /usr/local/etc/wine.userreg for reading: No such file or directory warn:reg:_get_wine_registry_file_format_version Couldn't open /usr/local/etc/wine.systemreg for reading: No such file or directory ... [snip] ... trace:exec:ShellExecuteA trace:exec:ShellExecuteExA32 mask=0x00000000 hwnd=0x10023 verb=(null) file="wordpad.exe" parm=".\stl\readme.wri" dir="." show=0x00000001 class=not used trace:exec:ShellExecuteExA32 execute:'wordpad.exe','.\stl\readme.wri' trace:exec:SHELL_ExecuteA Execute wordpad.exe .\stl\readme.wri from directory . trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0x4078ebcc) trace:reg:NtOpenKey <- (nil) trace:reg:NtOpenKey ((nil),L"Machine\Software\Wine\Wine\Config\AppDefaults",f003f,0x40790040) trace:reg:NtOpenKey <- (nil) trace:reg:NtQueryValueKey (0x14,L"wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*",2,0x40790134,80) trace:file:CreateFileW L"C:\WINDOWS\SYSTEM\wordpad.exe" GENERIC_READ FILE_SHARE_READ OPEN_EXISTING attributes 0x0 warn:file:CreateFileW Unable to get full filename from L"C:\WINDOWS\SYSTEM\wordpad.exe" (GLE 2) trace:exec:SHELL_FindExecutable wordpad.exe trace:exec:SHELL_FindExecutable xlpFile=,extension=(null) warn:exec:SHELL_FindExecutable Returning 31 - No association trace:exec:ShellExecuteA trace:exec:ShellExecuteExA32 mask=0x00000000 hwnd=0x10023 verb=(null) file=".wordpad.exe" parm=".\stl\readme.wri" dir="." show=0x00000001 class=not used trace:exec:ShellExecuteExA32 execute:'.wordpad.exe','.\stl\readme.wri' trace:exec:SHELL_ExecuteA Execute .wordpad.exe .\stl\readme.wri from directory . trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0x4078ebcc) trace:reg:NtOpenKey <- (nil) trace:reg:NtOpenKey ((nil),L"Machine\Software\Wine\Wine\Config\AppDefaults",f003f,0x40790040) trace:reg:NtOpenKey <- (nil) trace:reg:NtQueryValueKey (0x14,L".wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*.wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*",2,0x40790134,80) trace:file:CreateFileW L"C:\WINDOWS\SYSTEM\.wordpad.exe" GENERIC_READ FILE_SHARE_READ OPEN_EXISTING attributes 0x0 warn:file:CreateFileW Unable to get full filename from L"C:\WINDOWS\SYSTEM\.wordpad.exe" (GLE 2) trace:exec:SHELL_FindExecutable .wordpad.exe trace:exec:SHELL_FindExecutable xlpFile=,extension=(null) warn:exec:SHELL_FindExecutable Returning 31 - No association trace:file:GetFileInformationByHandle 0xffffffff ---------------------
OK, so then I copied my system.reg to /usr/local/etc/wine.systemreg. Now it finds that key (!) but unfortunately, the only change is that the line warn:reg:_get_wine_registry_file_format_version Couldn't open /usr/local/etc/wine.systemreg for reading: No such file or directory no longer shows up in the log.
I'm pretty sure this is supposed to work, but I'm having trouble untangling it. Help would be greatly appreciated.
If anyone's interested, I can send an executable that does the ShellExecute call in question so they can reproduce it themselves...
Thanks, Dan
I wrote:
OK, so then I copied my system.reg to /usr/local/etc/wine.systemreg. Now it finds that key (!) but unfortunately, the only change is ...
Editing error... that should be
OK, so then I copied my system.reg to /usr/local/etc/wine.systemreg. Unfortunately, the only change is ...
Dan Kegel wrote:
I have a windows-free installation of current CVS wine, with wordpad.exe and the needed DLLs pulled in from a Windows ME installation. wordpad works great. However, ShellExecute(... "wordpad.exe", ".\stl\readme.wri" ...) is failing to find wordpad.exe for me. (The call in question is issued by the msvc4.0 setup.exe. The current directory when I run this is /mnt/cdrom, and stl/readme.wri is indeed there.)
Ignore the part about /usr/local/etc/system.reg.
With a few more traces, I see the first attempt to execute, triggered by the execfunc at line 608 of ShellExecuteExA32. This is just a test to see if the command line can be executed as is.
trace:exec:ShellExecuteExA32 mask=0x00000000 hwnd=(nil) verb="open" file="wordpad.exe" parm="readme.txt" dir="C:\" show=0x00000005 class=not used trace:exec:ShellExecuteExA32 execute:'wordpad.exe','readme.txt' trace:exec:SHELL_ExecuteA Execute wordpad.exe readme.txt from directory C:\ 08073208:Call kernel32.CreateProcessA(00000000,40582788 "wordpad.exe readme.txt",00000000,00000000,00000000,00000000,00000000,0040e4db "C:\",40581eb8,40581ea8) ret=40c8d29f trace:process:CreateProcessA app (null) cmdline "wordpad.exe readme.txt" trace:process:find_exe_file looking for "wordpad.exe"
According to MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas...
CreateProcess should check several places for an application, none of which include the registry key. So that call should fail, and it does.
08073208:Ret kernel32.CreateProcessA() retval=00000000 ret=40c8d29f
Next comes the test at line 614 of ShellExecuteExA32, which calls SHELL_FindExecutable.
trace:exec:SHELL_FindExecutable wordpad.exe 08073208:Call kernel32.SearchPathA(0040e4db "C:\",40582548 "wordpad.exe",40ca9be7 ".exe",00000100,40581af0,00000000) ret=40c8d43a 08073208:Ret kernel32.SearchPathA() retval=00000000 ret=40c8d43a trace:exec:SHELL_FindExecutable xlpFile=,extension=(null) warn:exec:SHELL_FindExecutable Returning 31 - No association
That call should have passed. It returns early at line 203, because xlpFile and the extension, returned from SearchPathA are null. That appears to be where things broke. Even if that passed, it does not appear that a check for the "App Patch" key is being done here, and it looks to me like it should be.
Is that enough to get you going further?
Duane Clark wrote:
According to MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas...
CreateProcess should check several places for an application, none of which include the registry key. So that call should fail, and it does.
By the way, since many things are "inadvertently" left out of the MSDN, it might be worth testing whether that is really the way CreateProcess works on Windows. In fact, that would make a good test case to add to Wine, if you really wanted go for it.
Duane Clark wrote:
Ignore the part about /usr/local/etc/system.reg.
OK, but I am still curious what's going on there.
trace:process:CreateProcessA app (null) cmdline "wordpad.exe readme.txt"
CreateProcess should check several places for an application, none of which include the registry key. So that call should fail, and it does.
Agreed.
trace:exec:SHELL_FindExecutable wordpad.exe 08073208:Call kernel32.SearchPathA(0040e4db "C:\",40582548 "wordpad.exe",40ca9be7 ".exe",00000100,40581af0,00000000) ret=40c8d43a 08073208:Ret kernel32.SearchPathA() retval=00000000 ret=40c8d43a trace:exec:SHELL_FindExecutable xlpFile=,extension=(null) warn:exec:SHELL_FindExecutable Returning 31 - No association
That call should have passed. It returns early at line 203, because xlpFile and the extension, returned from SearchPathA are null. That appears to be where things broke. Even if that passed, it does not appear that a check for the "App Patch" key is being done here, and it looks to me like it should be.
Is that enough to get you going further?
Thanks for the --debugmsg +process tip (and I guess you also did relay?)!
But if you also add +reg, you'll see that the App Paths key is indeed being searched by SearchPath():
trace:exec:ShellExecuteA trace:exec:ShellExecuteExA32 mask=0x00000000 hwnd=0x10023 verb=(null) file="wordpad.exe" parm=".\stl\readme.wri" dir="." show=0x00000001 class=not used trace:exec:ShellExecuteExA32 execute:'wordpad.exe','.\stl\readme.wri' trace:exec:SHELL_ExecuteA Execute wordpad.exe .\stl\readme.wri from directory . trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0x4078ebcc) trace:reg:NtOpenKey <- 0x74 trace:reg:NtOpenKey (0x74,L"setup.exe",f003f,0x4078ebc8) trace:reg:NtOpenKey <- (nil) trace:reg:NtOpenKey ((nil),L"Machine\Software\Wine\Wine\Config\AppDefaults",f003f,0x40790040) trace:reg:NtOpenKey <- (nil) trace:reg:NtQueryValueKey (0x14,L"wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*wordpad.exe",2,0x40790134,80) trace:reg:NtQueryValueKey (0x14,L"*",2,0x40790134,80) trace:file:CreateFileW L"C:\WINDOWS\SYSTEM\wordpad.exe" GENERIC_READ FILE_SHARE_READ OPEN_EXISTING attributes 0x0 warn:file:CreateFileW Unable to get full filename from L"C:\WINDOWS\SYSTEM\wordpad.exe" (GLE 2) trace:exec:SHELL_FindExecutable wordpad.exe trace:exec:SHELL_FindExecutable xlpFile=,extension=(null) warn:exec:SHELL_FindExecutable Returning 31 - No association
So it's *supposed* to be implemented already, but the implementation is broken, maybe. See http://www.winehq.com/hypermail/wine-patches/2002/02/0079.html (I would have thought it belonged right in ShellExecute rather than SearchPath, but as long as it works, I guess it doesn't matter.)
Anyway, I reproduced the problem with a trivial C program, compiled it with msvc4.0's cl.exe from wine :-), and verified that the program works fine under Windows, but not under Wine.
Here's the source:
#include <stdio.h> #include <windows.h> main() { int h; h = ShellExecute(NULL, "open", "wordpad.exe", NULL, NULL, SW_SHOWNORMAL); printf("ShellExecute returns %d\n", h); }
The executable is at http://www.kegel.com/shelltext.tgz
I'd like to create a conformance test for ShellExecute to check this...
Dan Kegel wrote:
Thanks for the --debugmsg +process tip (and I guess you also did relay?)!
But if you also add +reg, you'll see that the App Paths key is indeed being searched by SearchPath():
That was done inside CreateProcessA (note the relay Call and Ret pair), and at least at first glance, appears to be looking for the App Path key for "ListV", which is the name of my test application. I am note real sure what the NtQueryValueKey calls are doing though. I still think the problem is later on, in SHELL_FindExecutable. I think the registry checks here are "red herrings". Then again, I could be completely wrong about that ;)
Probably the best way to determine that is to modify your simple program to call CreateProcess directly, and see what happens then.
08073208:Call kernel32.CreateProcessA(00000000,40582788 "wordpad.exe readme.txt",00000000,00000000,00000000,00000000,00000000,0040e4db "C:\",40581eb8,40581ea8) ret=40c8d29f trace:process:CreateProcessA app (null) cmdline "wordpad.exe readme.txt" trace:process:find_exe_file looking for "wordpad.exe" trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0x4057e998) trace:reg:NtOpenKey <- 0x4c trace:reg:NtOpenKey (0x4c,L"ListV.exe",f003f,0x4057e994) trace:reg:NtOpenKey <- (nil) trace:reg:NtOpenKey ((nil),L"Machine\Software\Wine\Wine\Config\AppDefaults",f003f,0x4057fdf0) trace:reg:NtOpenKey <- 0x4c trace:reg:NtOpenKey (0x4c,L"ListV.exe\DllOverrides",f003f,0x4057fdec) trace:reg:NtOpenKey <- (nil) trace:reg:NtQueryValueKey (0x14,L"wordpad.exe",2,0x4057fee4,80,22) trace:reg:NtQueryValueKey (0x14,L"*wordpad.exe",2,0x4057fee4,80,24) trace:reg:NtQueryValueKey (0x14,L"*",2,0x4057fee4,80,2) trace:process:find_exe_file Trying built-in exe "C:\WINDOWS\SYSTEM\wordpad.exe" trace:process:find_exe_file Trying native exe "C:\WINDOWS\SYSTEM\wordpad.exe" trace:process:find_exe_file looking for "wordpad.exe readme.txt" trace:reg:NtOpenKey ((nil),L"Machine\Software\Microsoft\Windows\CurrentVersion\App Paths",f003f,0x4057e998) trace:reg:NtOpenKey <- 0x4c trace:reg:NtOpenKey (0x4c,L"ListV.exe",f003f,0x4057e994) trace:reg:NtOpenKey <- (nil) trace:reg:NtOpenKey ((nil),L"Machine\Software\Wine\Wine\Config\AppDefaults",f003f,0x4057fdf0) trace:reg:NtOpenKey <- 0x4c trace:reg:NtOpenKey (0x4c,L"ListV.exe\DllOverrides",f003f,0x4057fdec) trace:reg:NtOpenKey <- (nil) trace:reg:NtQueryValueKey (0x14,L"wordpad.exe readme.txt",2,0x4057fee4,80,44) trace:reg:NtQueryValueKey (0x14,L"*wordpad.exe readme.txt",2,0x4057fee4,80,46) trace:reg:NtQueryValueKey (0x14,L"*",2,0x4057fee4,80,2) trace:process:find_exe_file Trying built-in exe "C:\WINDOWS\SYSTEM\wordpad.exe readme.txt" trace:process:find_exe_file Trying native exe "C:\WINDOWS\SYSTEM\wordpad.exe readme.txt" 08073208:Ret kernel32.CreateProcessA() retval=00000000 ret=40c8d29f
Duane Clark wrote:
... the App Paths key is indeed being searched by SearchPath()
That was done inside CreateProcessA (note the relay Call and Ret pair), and at least at first glance, appears to be looking for the App Path key for "ListV", which is the name of my test application.
Oh. Right. Looks like the functionality implemented by http://www.winehq.com/hypermail/wine-patches/2002/02/0079.html is the *other* use of "App Paths"
I found a few links that mention both uses: http://www.oreilly.com/catalog/win95nut/chapter/ch03.html http://www.geocities.com/completehackz/registry.html http://students.cs.byu.edu/~apippin/aim/aimfaq.htm http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwue/html/...
Maybe I'll try to code up the missing functionity. Thanks for helping me think about this stuff. - Dan
Dan Kegel wrote:
I have a windows-free installation of current CVS wine, with wordpad.exe and the needed DLLs pulled in from a Windows ME installation. wordpad works great. However, ShellExecute(... "wordpad.exe", ".\stl\readme.wri" ...) is failing to find wordpad.exe for me.
I just submitted a patch to wine-patches that fixes this. This is the first functionality I've ever contributed to Wine. (Six whole lines! :-)
I also noticed that ShellExecute will sometimes try to run the executable "C:\Program" (the first word of "C:\Program Files\whatever..."). I fixed that for the case I touched, I think, but didn't do a general fix.
When we finally have a conformance test for ShellExecute, it should verify that it never tries to run the first space-terminated fragment of the program name as an executable! - Dan
Dan Kegel wrote:
... I also noticed that ShellExecute will sometimes try to run the executable "C:\Program" (the first word of "C:\Program Files\whatever..."). I fixed that for the case I touched, I think, but didn't do a general fix.
MSDN for CreateProcess claims that if the supplied string is not quoted, then that is the correct behavior.
Duane Clark wrote:
Dan Kegel wrote:
... I also noticed that ShellExecute will sometimes try to run the executable "C:\Program" (the first word of "C:\Program Files\whatever..."). I fixed that for the case I touched, I think, but didn't do a general fix.
MSDN for CreateProcess claims that if the supplied string is not quoted, then that is the correct behavior.
That is the correct behavior for CreateProcess, yes. But it is an error for ShellExecute to execute C:\Program when it intended to execute C:\Program Files\Accessories\wordpad.exe
See the "Security Remarks" at the bottom of http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas... which advise callers of CreateProcess to avoid this pitfall. - Dan