http://bugs.winehq.org/show_bug.cgi?id=8269
Summary: GetFileSecurityW() regression: does not work for directories Product: Wine Version: 0.9.36. Platform: All OS/Version: other Status: UNCONFIRMED Severity: major Priority: P2 Component: wine-files AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net
Hello,
there seems to be a regression introduced due to recent GetFileSecurityW rewrite. Some apps, for instance native msi service die on this.
--- snip trace --- 0019:Call advapi32.GetFileSecurityW(0018dbd4 L"c:\windows\Installer",00000001,61752264,00000040,61752244) ret=74651fd1 trace:file:CreateFileW L"c:\windows\Installer" GENERIC_READ FILE_SHARE_READ creation 3 attributes 0x0 trace:file:RtlDosPathNameToNtPathName_U (L"c:\windows\Installer",0x61752120,(nil),(nil)) trace:file:RtlGetFullPathName_U (L"c:\windows\Installer" 520 0x61751e74 (nil)) trace:ntdll:NtCreateFile handle=0x61752128 access=80000000 name=L"\??\C:\windows\Installer" objattr=00000040 root=(nil) sec=(nil) io=0x61752118 alloc_size=(nil) attr=00000000 sharing=00000001 disp=1 options=00000050 ea=(nil).0x00000000 trace:file:wine_nt_to_unix_file_name L"\??\C:\windows\Installer" -> "/home/focht/.wine/dosdevices/c:/windows/Installer" warn:file:CreateFileW Unable to create file L"c:\windows\Installer" (status c00000ba) trace:file:CreateFileW returning 0xffffffff 0019:Ret advapi32.GetFileSecurityW() retval=00000000 ret=74651fd1 0019:Call kernel32.GetLastError() ret=7471d86d 0019:Ret kernel32.GetLastError() retval=00000005 ret=7471d86d --- snip trace ---
GetFileSecurityW() calls CreateFileW() with attributes = 0
In CreateFileW() before the call to NtCreateFile() is made, the options are set by following snippet:
--- snip dlls/kernel32/file.c CreateFileW() ---
options = 0; if (attributes & FILE_FLAG_BACKUP_SEMANTICS) options |= FILE_OPEN_FOR_BACKUP_INTENT; else options |= FILE_NON_DIRECTORY_FILE; ... --- snip dlls/kernel32/file.c CreateFileW() ---
This has severe consequences (at least on NT based systems). With the FILE_NON_DIRECTORY_FILE flag set, NtCreateFile() returns STATUS_FILE_IS_A_DIRECTORY because it encounters a folder ("c:\windows\installer") This status is later remapped to "access denied" (0x5)
Calling CreateFileW() with that flags is expected behaviour and works like windows.
To get GetFileSecurityW() work for directories too, CreateFileW *must* must be called with FILE_FLAG_BACKUP_SEMANTICS flag as file attributes. That way CreateFileW() will succeed, returning a handle to directory on NT based systems. Leave Windows 95/98/ME alone (unsupported flag, Microsoft calls it 'broken').
So to fix this regression, add the FILE_FLAG_BACKUP_SEMANTICS flag to attributes when calling CreateFileW():
--- snip dlls/advapi/security.c --- BOOL WINAPI GetFileSecurityW( LPCWSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded ) { ...
hfile = CreateFileW( lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 ); if ( hfile == INVALID_HANDLE_VALUE) return FALSE; ... } --- snip dlls/advapi/security.c ---
CreateFileW is now called with FILE_FLAG_BACKUP_SEMANTICS attributes set. Works for file and directories.
Trace with patched GetFileSecurityW():
--- snip trace --- 000e:Call advapi32.GetFileSecurityW(0018dbd4 L"c:\windows\Installer",00000001,60c47264,00000040,60c47244) ret=74651fd1 trace:file:CreateFileW L"c:\windows\Installer" GENERIC_READ FILE_SHARE_READ creation 3 attributes 0x2000000 trace:file:RtlDosPathNameToNtPathName_U (L"c:\windows\Installer",0x60c47120,(nil),(nil)) trace:file:RtlGetFullPathName_U (L"c:\windows\Installer" 520 0x60c46e74 (nil)) trace:ntdll:NtCreateFile handle=0x60c47128 access=80000000 name=L"\??\C:\windows\Installer" objattr=00000040 root=(nil) sec=(nil) io=0x60c47118 alloc_size=(nil) attr=00000000 sharing=00000001 disp=1 options=00004010 ea=(nil).0x00000000 trace:file:wine_nt_to_unix_file_name L"\??\C:\windows\Installer" -> "/home/focht/.wine/dosdevices/c:/windows/Installer" trace:file:CreateFileW returning 0x70 fixme:ntdll:NtQuerySecurityObject (0x70,0x00000001,0x60c47264,0x00000040,0x60c47244) stub! trace:ntdll:NtQuerySecurityObject len=36 000e:Ret advapi32.GetFileSecurityW() retval=00000001 ret=74651fd1 --- snip trace ---
Regards