[Bug 10601] .NET Framework 2.0: Installation Fails in winxp mode

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 29 06:19:19 CDT 2008


http://bugs.winehq.org/show_bug.cgi?id=10601





--- Comment #15 from Anastasius Focht <focht at gmx.net>  2008-03-29 06:19:18 ---
Hello,

if you want to use default "Windows XP" config for .NET 2.0 installers there
are two ways to get it work.

The .NET 2.0 Framework installer checks if the target volume is NTFS filesystem
type and then uses the FSCTL_SET_REPARSE_POINT ioctl (used for mount points and
junctions) to create junction points for each registered assembly in Windows
SxS directory to GAC assembly directory (link target). 
Basically the junction point is used to redirect access from one directory to
another.

--- trace ---
0033:Call KERNEL32.GetVolumeInformationW(7eb5e3d4
L"C:\\",00000000,00000000,00000000,7eb5e1c4,7eb5e1c4,7eb5e1c8,00000104)
ret=7a13f5bc
0033:trace:vxd:DeviceIoControl
(0x284,24000,(nil),0,0x7eb5ddb2,804,0x7eb5e0e8,(nil))
0033:Ret  KERNEL32.GetVolumeInformationW() retval=00000001 ret=7a13f5bc 
--- trace ---

I first thought they would look at the returned filesystem flags field (flags &
FILE_SUPPORTS_REPARSE_POINTS) - but that's not the case.
Instead they look directly at returned filesystem name string and compare it to
"NTFS".
Junction points were introduced with NTFS v3.0 - Windows 2000 and later.
There is a check for windows version >= Windows 2000 so NT4 NTFS 2.x targets
won't get junctions requests.

The quick fix is to not pretend that target is NTFS volume (fall back to
FAT32):

--- snip dlls/kernel32/volume.c ---

diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
index 74397a9..5c78fbd 100644
--- a/dlls/kernel32/volume.c
+++ b/dlls/kernel32/volume.c
@@ -619,7 +619,7 @@ fill_fs_info:  /* now fill in the information that depends
on the file system ty
         if (flags) *flags = FILE_CASE_PRESERVED_NAMES;  /* FIXME */
         break;
     default:
-        if (fsname) lstrcpynW( fsname, ntfsW, fsname_len );
+        if (fsname) lstrcpynW( fsname, fat32W, fsname_len );
         if (filename_len) *filename_len = 255;
         if (flags) *flags = FILE_CASE_PRESERVED_NAMES;
         break;

--- snip dlls/kernel32/volume.c ---

The long one: add NTFS junction support to wine (boils down to creation of *nix
symlink).

--- snip ---
0049:Call KERNEL32.CreateFileW(7e9fd2fc
L"C:\\windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a",c0000000,00000003,00000000,00000003,02200000,00000000)
ret=79ea0464
0049:Ret  KERNEL32.CreateFileW() retval=0000028c ret=79ea0464
0049:Call KERNEL32.lstrlenW(7e9fbfe4
L"C:\\windows\\WinSxS\\x86_System.EnterpriseServices_b03f5f7f11d50a3a_2.0.0.0_x-ww_7d5f3790")
ret=7a13f794
0049:Ret  KERNEL32.lstrlenW() retval=00000056 ret=7a13f794
0049:Call KERNEL32.lstrlenW(7e9fbdd8
L"\\??\\C:\\windows\\WinSxS\\x86_System.EnterpriseServices_b03f5f7f11d50a3a_2.0.0.0_x-ww_7d5f3790")
ret=7a13f79e
0049:Ret  KERNEL32.lstrlenW() retval=0000005a ret=7a13f79e
0049:Call KERNEL32.GetLastError() ret=79e85f0a
0049:Ret  KERNEL32.GetLastError() retval=00000000 ret=79e85f0a
0049:Call ntdll.RtlAllocateHeap(00110000,00000000,00000174) ret=79e78360
0049:Ret  ntdll.RtlAllocateHeap() retval=00d38dc0 ret=79e78360
0049:Call
KERNEL32.DeviceIoControl(0000028c,000900a4,00d38dc0,00000174,00000000,00000000,7e9fbdc4,00000000)
ret=7a13f846
0049:fixme:ntdll:server_ioctl_file Unsupported ioctl 900a4 (device=9 access=0
func=29 method=0)
0049:Ret  KERNEL32.DeviceIoControl() retval=00000000 ret=7a13f846
0049:Call KERNEL32.GetLastError() ret=7a13f856
0049:Ret  KERNEL32.GetLastError() retval=00000032 ret=7a13f856
--- snip ---

"\\??\\C:\\windows\\WinSxS\\x86_System.EnterpriseServices_b03f5f7f11d50a3a_2.0.0.0_x-ww_7d5f3790"
is the native name for the junction.

"C:\\windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a"
is the redirect (link) target

My first approach was to stub FSCTL_SET_REPARSE_POINT in
ntdll.NtFsControlFile() (like FSCTL_LOCK_VOLUME) but this was not enough.

NOTE: the wine definitions of FSCTL_SET_REPARSE_POINT and
FSCTL_DELETE_REPARSE_POINT are incorrect or at least not valid for W2K, XP and
later.
Access type has to be FILE_ANY_ACCESS (0) when building the ioctl code.
E.g.: #define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41,
METHOD_BUFFERED, FILE_ANY_ACCESS) -> 0x900a4

--- snip ---
0033:Call
KERNEL32.DeviceIoControl(00000284,000900a4,00d3b180,00000174,00000000,00000000,7eb5ddc4,00000000)
ret=7a13f846
0033:trace:vxd:DeviceIoControl
(0x284,900a4,0xd3b180,372,(nil),0,0x7eb5ddc4,(nil))
0033:fixme:ntdll:NtFsControlFile stub! return success - Unsupported fsctl 900a4
(device=9 access=0 func=29 method=0)
0033:Ret  KERNEL32.DeviceIoControl() retval=00000001 ret=7a13f846
0033:Call KERNEL32.CloseHandle(00000284) ret=7a13f7ca
0033:Ret  KERNEL32.CloseHandle() retval=00000001 ret=7a13f7ca
0033:Call KERNEL32.GetLastError() ret=79e782be
0033:Ret  KERNEL32.GetLastError() retval=00000000 ret=79e782be
..
0033:Call KERNEL32.lstrlenW(00d3a4f8
L"C:\\windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a")
ret=79f6d793
0033:Ret  KERNEL32.lstrlenW() retval=0000004e ret=79f6d793
0033:Call shlwapi.PathAddBackslashW(00d3a4f8
L"C:\\windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a")
ret=79f6d7a9
0033:Ret  shlwapi.PathAddBackslashW() retval=00d3a596 ret=79f6d7a9
0033:Call KERNEL32.GetFileAttributesExW(00d3a730
L"C:\\windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a\\System.EnterpriseServices.dll",00000000,7eb5e82c)
ret=7a143d7c
0033:Ret  KERNEL32.GetFileAttributesExW() retval=00000000 ret=7a143d7c
0033:Call KERNEL32.GetLastError() ret=7a143d88
0033:Ret  KERNEL32.GetLastError() retval=00000002 ret=7a143d88 
--- snip ---

Unfortunately after pretending that the junction was created, there is a check
if the redirection succeeds by retrieving file attributes for each assembly -
so there has to be a real link...

The main problem is actually the conversion of supplied handle to something
meaningful for symlink(2).
There is no reliable way to get that path name back from the file descriptor.
Wine doesn't store this information (object name) anywhere.

So it boils down to unix style file descriptor (and associated inode) vs. 
systems calls that expect path names.
Actually it would be easier if there is *nix symlink() which accepts fd's or
inodes as parameter type :-(
Maybe the name/path information can be stored in wine server on object creation
to be later retrieved by various NtQueryXXX.

Regards


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list