http://bugs.winehq.org/show_bug.cgi?id=36838
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download Status|UNCONFIRMED |NEW CC| |focht@gmx.net Component|-unknown |shell32 Ever confirmed|0 |1
--- Comment #3 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
--- snip --- $ WINEDEBUG=+tid,+seh,+relay,+server wine ./SETUP.EXE >>log.txt 2>&1 ... 0009:Call shell32.SHFileOperationA(0033e984) ret=004029f5 ... 0009:Call KERNEL32.CopyFileW(0013f258 L"Z:\home\focht\Downloads\install\tourcars.exe",00151758 L"c:\Codemast\TourCar\tourcars.exe",00000000) ret=7e8fcc89 0009:Ret KERNEL32.CopyFileW() retval=00000001 ret=7e8fcc89 ... 0009:Call shlwapi.SHFreeShared(00000000,00000008) ret=7e8d3f1f 0009:Call KERNEL32.DuplicateHandle(ffffffff,00000000,ffffffff,0033e35c,000f001f,00000000,00000003) ret=7e817e1f 0009: dup_handle( src_process=ffffffff, src_handle=0000, dst_process=ffffffff, access=000f001f, attributes=00000000, options=00000003 ) 0009: dup_handle() = INVALID_HANDLE { handle=0000, self=1, closed=0 } 0009:Ret KERNEL32.DuplicateHandle() retval=00000000 ret=7e817e1f 0009:Call KERNEL32.CloseHandle(00000000) ret=7e818289 0009: close_handle( handle=0000 ) 0009: close_handle() = INVALID_HANDLE 0009:Ret KERNEL32.CloseHandle() retval=00000000 ret=7e818289 0009:Ret shlwapi.SHFreeShared() retval=00000000 ret=7e8d3f1f ... 0009:Ret shell32.SHFileOperationA() retval=00000000 ret=004029f5 0009:Call KERNEL32.GetLastError() ret=004029fb 0009:Ret KERNEL32.GetLastError() retval=00000006 ret=004029fb 0009:Call user32.MessageBoxA(0001004a,0040a268 "There was an error whilst trying to install files\n\tPress OK to quit",00407808 "TOCA Touring Car Championship Demo Setup",00002030) ret=00401578 --- snip ---
The installer doesn't like the lasterror code 0x6 (ERROR_INVALID_HANDLE) from 'SHFileOperationA' (0x12 would be acceptable, if any):
--- snip --- 004029C1 |83C4 0C |ADD ESP,0C 004029C4 |8D4424 1C |LEA EAX,DWORD PTR SS:[ESP+1C] 004029C8 |8D8C24 5C010000 |LEA ECX,DWORD PTR SS:[ESP+15C] 004029CF |8D5424 58 |LEA EDX,DWORD PTR SS:[ESP+58] 004029D3 |50 |PUSH EAX 004029D4 |895C24 20 |MOV DWORD PTR SS:[ESP+20],EBX 004029D8 |C74424 24 02000000|MOV DWORD PTR SS:[ESP+24],2 004029E0 |894C24 28 |MOV DWORD PTR SS:[ESP+28],ECX 004029E4 |895424 2C |MOV DWORD PTR SS:[ESP+2C],EDX 004029E8 |66:C74424 30 1502 |MOV WORD PTR SS:[ESP+30],215 004029EF |FF15 C4F34000 |CALL DWORD PTR DS:[<&SHELL32.SHFileOperationA>] 004029F5 |FF15 C8F24000 |CALL DWORD PTR DS:[<&KERNEL32.GetLastError>] 004029FB |25 FFFF0000 |AND EAX,0FFFF 00402A00 |74 09 |JE SHORT SETUP.00402A0B 00402A02 |83F8 12 |CMP EAX,12 00402A05 |0F85 CB000000 |JNZ SETUP.00402AD6 00402A0B |8D4C24 58 |LEA ECX,DWORD PTR SS:[ESP+58] 00402A0F |68 80000000 |PUSH 80 ; FileAttributes = NORMAL 00402A14 |51 |PUSH ECX ; FileName 00402A15 |FF15 C4F24000 |CALL DWORD PTR DS:[<&KERNEL32.SetFileAttributesA>] --- snip ---
The previous trace log was already done with +server to show where it originates from.
--- snip --- Wine-dbg>bt
Backtrace: =>0 0x7e8ede7f SHFreeShared(hShared=0x0(nil), dwProcId=0x22) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shellord.c:1459] in shell32 (0x0033e5c8)
1 0x7e916cb8 SHNotifyCopyFileW+0x115(src="Z:\home\focht\Downloads\install\tourcars.exe", dest="c:\Codemast\TourCar\tourcars.exe", bFailIfExists=0) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shlfileop.c:640] in shell32 (0x0033e638)
2 0x7e917f29 copy_file_to_file+0x8b(op=0x33e8fc, szFrom="Z:\home\focht\Downloads\install\tourcars.exe", szTo="c:\Codemast\TourCar\tourcars.exe") [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shlfileop.c:1143] in shell32 (0x0033e658)
3 0x7e9185db copy_files+0x4fa(op=0x33e8fc, flFrom=0x33e8e4, flTo=0x33e8cc) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shlfileop.c:1291] in shell32 (0x0033e8a8)
4 0x7e919015 SHFileOperationW+0x141(lpFileOp=0x33e942) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shlfileop.c:1571] in shell32 (0x0033e918)
5 0x7e9173bd SHFileOperationA+0x14a(lpFileOp=<couldn't compute location>) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shlfileop.c:887] in shell32 (0x0033e998)
6 0x004029f5 in setup (+0x29f4) (0x7b8759b1) --- snip ---
The corresponding source: http://source.winehq.org/git/wine.git/blob/0f64ffd91ff2fab97d9c52335478ff2fb...
--- snip --- 260 void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) 261 { ... 269 HANDLE shared_data = NULL; 270 LPITEMIDLIST Pidls[2]; 271 LPNOTIFICATIONLIST ptr; 272 struct list recipients; ... 414 SHFreeShared(shared_data, GetCurrentProcessId()); 415 SHFree(Pidls[0]); 416 SHFree(Pidls[1]); ... 424 } --- snip ---
'shared_data' is NULL (no notifiers) hence the call to 'SHFreeShared' is unnecessary and avoids that lasterror leaking.
After fixing that part it still fails:
--- snip --- ... 0009:Ret shell32.SHFileOperationA() retval=00000000 ret=004029f5 0009:Call KERNEL32.GetLastError() ret=004029fb 0009:Ret KERNEL32.GetLastError() retval=00000001 ret=004029fb --- snip ---
To see where this lasterror code 0x1 originates from we need to unmask all internal relay calls (remove keys in registry):
--- snip --- [HKEY_CURRENT_USER\Software\Wine\Debug] "RelayExclude"="ntdll.RtlEnterCriticalSection;ntdll.RtlLeaveCriticalSection;kernel32.48;kernel32.49;kernel32.94;kernel32.95;kernel32.96;kernel32.97;kernel32.98;kernel32.TlsGetValue;kernel32.TlsSetValue;kernel32.FlsGetValue;kernel32.FlsSetValue;kernel32.SetLastError" "RelayFromExclude"="winex11.drv;winemac.drv;user32;gdi32;advapi32;kernel32" --- snip ---
Voila - grepping through the full relay trace log yields:
--- snip --- 0009:Call KERNEL32.Wow64DisableWow64FsRedirection(0033a800) ret=7e8ed691 0009:Call ntdll.RtlWow64EnableFsRedirectionEx(00000001,0033a800) ret=7b860f0c 0009:Ret ntdll.RtlWow64EnableFsRedirectionEx() retval=c0000002 ret=7b860f0c 0009:Call ntdll.RtlNtStatusToDosError(c0000002) ret=7b860f23 0009:Ret ntdll.RtlNtStatusToDosError() retval=00000001 ret=7b860f23 0009:Ret KERNEL32.Wow64DisableWow64FsRedirection() retval=00000000 ret=7e8ed691 --- snip ---
Debugger:
--- snip --- Wine-dbg>bt Backtrace:
=>0 0x7b860ee7 Wow64DisableWow64FsRedirection(old_value=0x33a880) [/home/focht/projects/wine/wine.repo/src/dlls/kernel32/path.c:1850] in kernel32 (0x0033cad8)
1 0x7e8ede8c UNIXFS_path_to_pidl+0xce(pUnixFolder=0x141a28, pbc=0x1373e0, path="c:\Codemast\TourCar\tourcars.exe", ppidl=0x33dea4) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shfldr_unixfs.c:629] in shell32 (0x0033ddc8)
2 0x7e8eef31 ShellFolder2_ParseDisplayName+0xd1(iface=<couldn't compute location>, hwndOwner=<couldn't compute location>, pbc=<couldn't compute location>, display_name=<couldn't compute location>, pchEaten=<couldn't compute location>, ppidl=<couldn't compute location>, attrs=<couldn't compute location>) [/home/focht/projects/wine/wine.repo/src/dlls/shell32/shfldr_unixfs.c:948] in shell32 (0x0033de68) ...
Wine-dbg>n 1851 NTSTATUS status = RtlWow64EnableFsRedirectionEx( TRUE, (ULONG *)old_value ); Wine-dbg>n 1852 if (status) SetLastError( RtlNtStatusToDosError(status) ); Wine-dbg>p status => 2 0xc0000002 --- snip ---
I saved/restored the last error around the Wow64 filesystem redirection calls. And it still failed ... more code paths leaked lasterror codes too :|
--- snip --- 0009:Ret shell32.SHFileOperationA() retval=00000000 ret=004029f5 0009:Call KERNEL32.GetLastError() ret=004029fb 0009:Ret KERNEL32.GetLastError() retval=000000b7 ret=004029fb --- snip ---
That thing wasn't really visible so another debugging session revealed it's 'CopyFileExW' -> 'CreateFileW' -> 'SetLastError(ERROR_ALREADY_EXISTS)' if the destination file exists (re-run of installer).
I got fed up with all the lasterror codes leaking from various code paths (by design) and reset the lasterror in 'SHNotifyCopyFileW' if the copy operation succeeded. There might be a better place but this worked for me.
Source: http://source.winehq.org/git/wine.git/blob/2ba9ee018bce4953feb728595f4a4a6e4...
--- snip --- 625 static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists) 626 { 627 BOOL ret; 628 DWORD attribs; ... 632 /* Destination file may already exist with read only attribute */ 633 attribs = GetFileAttributesW(dest); 634 if (IsAttrib(attribs, FILE_ATTRIBUTE_READONLY)) 635 SetFileAttributesW(dest, attribs & ~FILE_ATTRIBUTE_READONLY); 636 637 ret = CopyFileW(src, dest, bFailIfExists); 638 if (ret) 639 { 640 SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); 641 return ERROR_SUCCESS; 642 } 643 644 return GetLastError(); 645 } --- snip ---
With that part fixed the installer succeeds. IMHO part 1, avoid NULL 'shared_data' cleanup call should be fixed too.
$ sha1sum tocademo_JeuxVideo.com_413.zip 3c7a4d0d8bc7e6f5095358b3d3ff005e53e44d4b tocademo_JeuxVideo.com_413.zip
$ du -sh tocademo_JeuxVideo.com_413.zip 6.8M tocademo_JeuxVideo.com_413.zip
$ wine --version wine-1.7.21-41-g5af3b8c
Regards