[Bug 45930] Microsoft .NET Framework 4.x GAC update fails for some assemblies, ' Error compiling mscorlib, Path not found. (Exception from HRESULT: 0x80070003)' (legacy GAC missing: '%systemroot%\assembly')

wine-bugs at winehq.org wine-bugs at winehq.org
Mon Oct 8 14:55:17 CDT 2018


https://bugs.winehq.org/show_bug.cgi?id=45930

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|-unknown                    |fusion

--- Comment #2 from Anastasius Focht <focht at gmx.net> ---
Hello Louis,

--- quote ---
Do I get it right that you're suggesting here that adding the creation of this
dir to wine.inf is not a correct fix? If so, maybe a wine.inf patch would still
be ok for Staging?
--- quote ---

this directory doesn't exist on old Windows versions (Windows XP) without any
.NET Frameworks installed. Newer Windows versions (Vista/7+) already ship
certain versions of .NET Frameworks pre-installed "OS component":

https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/versions-and-dependencies

The MSI installer triggers the creation of this legacy GAC root path. Searching
the Shared Source CLI 2.0 repository on Github I found one possible location:

https://github.com/fixdpt/shared-source-cli-2.0/blob/d63349c09c2e93e4bfc4c8b147ff0805f36cec68/clr/src/fusion/asmcache/cacheutils.cpp#L3051

--- snip ---
HRESULT LockCacheDir(CACHE_FLAGS dwCacheFlags, LPCWSTR pwzLockFile, HANDLE
*phLock)
{
    HRESULT hr = S_OK;
    DWORD  dwErr = 0;
    HANDLE hLock = INVALID_HANDLE_VALUE;
    DWORD dwWaitTime = 0;
    DWORD dwFileFlags = 0;
    DWORD dwRetry = 0;

    _ASSERTE(IsGacType(dwCacheFlags) || (dwCacheFlags == CACHE_DOWNLOAD));
    _ASSERTE(pwzLockFile);
    _ASSERTE(*pwzLockFile);
    _ASSERTE(phLock);

    if (IsGacType(dwCacheFlags)) {
        hr = CreateFilePathHierarchy(pwzLockFile);
        if (FAILED(hr)) {
            goto Exit;
        }
    }
--- snip ---

CreateFilePathHierarchy() ->
https://github.com/fixdpt/shared-source-cli-2.0/blob/d63349c09c2e93e4bfc4c8b147ff0805f36cec68/clr/src/fusion/utils/helpers.cpp#L628
-> will create the GAC root folder due to lock file creation.

LockCacheDir() is called by Lock() ->
https://github.com/fixdpt/shared-source-cli-2.0/blob/d63349c09c2e93e4bfc4c8b147ff0805f36cec68/clr/src/fusion/inc/lock.h#L107

Lock() is member of CMutex class which is used in many places as scoped lock.

I looked again multiple times at the trace log and finally it made *click*.

--- snip ---
...
00b2:Call KERNEL32.LoadLibraryW(007a0dc0
L"C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\fusion.dll") ret=1001233c
00b2:Call PE DLL (proc=0xf7b8a830,module=0xf7b80000
L"fusion.dll",reason=WINE_PREATTACH,res=(nil))
00b2:Ret  PE DLL (proc=0xf7b8a830,module=0xf7b80000
L"fusion.dll",reason=WINE_PREATTACH,res=(nil)) retval=1
...
00b2:Call PE DLL (proc=0xf7b8a830,module=0xf7b80000
L"fusion.dll",reason=PROCESS_ATTACH,res=(nil))
...
00b2:Ret  PE DLL (proc=0xf7b8a830,module=0xf7b80000
L"fusion.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
00b2:Ret  KERNEL32.LoadLibraryW() retval=f7b80000 ret=1001233c
00b2:Call KERNEL32.GetProcAddress(f7b80000,10004a8c "CreateAssemblyCache")
ret=10012384
00b2:Ret  KERNEL32.GetProcAddress() retval=f7b83c58 ret=10012384
00b2:Call fusion.CreateAssemblyCache(0045f280,00000000) ret=100123b2
...
00b2:Call KERNEL32.CreateMutexW(00000000,00000000,f7b8b080
L"__WINE_FUSION_CACHE_MUTEX__") ret=f7b8589d
00b2:Ret  KERNEL32.CreateMutexW() retval=00000070 ret=f7b8589d
00b2:Ret  fusion.CreateAssemblyCache() retval=00000000 ret=100123b2 
--- snip ---

That's of course Wine's builtin fusion at work here.

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/fusion/asmcache.c#l418

IAssemblyCacheImpl_InstallAssembly -> get_assembly_directory() ->
create_full_path()

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/fusion/asmcache.c#l108

The .NET CLR installer expects its own fusion implementation (CLR Fusion, see
shared-source-cli-2.0) to be loaded here and do the work which creates also the
legacy GAC roots/caches (for native images).

Preventing builtin from being loaded shows indeed:

--- snip ---
$ WINEDLLOVERRIDES=fusion=n WINEDEBUG=+seh,+relay,+msi wine
./dotNetFx40_Full_x86_x64.exe >>log.txt 2>&1
...
00b2:Ret  PE DLL (proc=0x604a321f,module=0x604a0000
L"fusion.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
00b2:Ret  KERNEL32.LoadLibraryW() retval=604a0000 ret=1001233c
00b2:Call KERNEL32.GetProcAddress(604a0000,10004a8c "CreateAssemblyCache")
ret=10012384
00b2:Ret  KERNEL32.GetProcAddress() retval=008b0033 ret=10012384
...
00b2:Call KERNEL32.LoadLibraryExW(0045ef94
L"C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\clr.dll",00000000,00000008)
ret=604a2b07
00b2:Call PE DLL (proc=0x790851d4,module=0x79060000
L"MSVCR100_CLR0400.dll",reason=PROCESS_ATTACH,res=(nil)) 
...
00b2:Call PE DLL (proc=0x791f58f0,module=0x79140000
L"clr.dll",reason=PROCESS_ATTACH,res=(nil)) 
...
00b2:Call KERNEL32.CreateFileW(00160fe0
L"C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\ISymWrapper.dll",80000000,00000005,00000000,00000003,00000080,00000000)
ret=792e90be
00b2:Ret  KERNEL32.CreateFileW() retval=00000070 ret=792e90be 
...
00b2:Call KERNEL32.CreateDirectoryW(0045e13c L"C:\\windows\\assembly",00000000)
ret=7927aacc
00b2:Ret  KERNEL32.CreateDirectoryW() retval=00000001 ret=7927aacc
00b2:Call KERNEL32.CreateFileW(0045e384
L"C:\\windows\\assembly\\GACLock.dat",40000000,00000000,00000000,00000002,04000104,00000000)
ret=7926e15d
00b2:Ret  KERNEL32.CreateFileW() retval=0000007c ret=7926e15d
...
--- snip ---

Installer custom action dll 'InstallAssembly' -> fusion.CreateAssemblyCache ->
clr.CreateAssemblyCache ...

There we go - legacy GAC root created as expected, triggered by GAC lock file
(corresponding to source).

It fails later though:

--- snip ---
...
00b6:Call KERNEL32.CreateFileW(0045e69c
L"C:\\windows\\Microsoft.Net\\assembly\\GAC_32\\System.EnterpriseServices\\v4.0_4.0.0.0__b03f5f7f11d50a3a",c0000000,00000003,00000000,00000003,02200000,00000000)
ret=794b1d64
00b6:Ret  KERNEL32.CreateFileW() retval=00000080 ret=794b1d64
...
00b6:Call
KERNEL32.DeviceIoControl(00000080,000900a4,0016c4b0,00000174,00000000,00000000,0045d164,00000000)
ret=794b1e60
00b6:fixme:ntdll:server_ioctl_file Unsupported ioctl 900a4 (device=9 access=0
func=29 method=0)
00b6:Ret  KERNEL32.DeviceIoControl() retval=00000000 ret=794b1e60
00b6:Call KERNEL32.GetLastError() ret=794b1e6e
00b6:Ret  KERNEL32.GetLastError() retval=00000032 ret=794b1e6e
...
0079:trace:msi:MSI_ProcessMessageVerbatim Calling UI handler
0x1004bf8a(pvContext=0x103fcd8, iMessageType=04000000, szMessage=L"Info
0.10/08/18 21:25:05 DDSet_Error: Failed to install assembly
'C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.EnterpriseServices.dll'
because of system error: Request not supported.\r\n") 
...
00b6:Call msi.MsiRecordSetStringW(00000001,00000000,0045e394 L"There is a
problem with this Windows Installer package. Please refer to the setup log for
more information.\r\n") ret=1002bae1 
...
0079:trace:msi:MSI_ProcessMessageVerbatim Calling UI handler
0x1004bf8a(pvContext=0x103fcd8, iMessageType=04000000, szMessage=L"Info
0.10/08/18 21:25:05 DDSet_Exit: InstallAssembly ended with return value 1603") 
...
0031:err:msi:execute_script Execution of script 0 halted; action
L"[C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\;C:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\System.EnterpriseServices.dll;246128<=>S-1-5-21-0-0-0-1000<=>{3C3901C5-3455-3E0A-A214-0B093A5070A6}]CA_InstallAssemblyDef.3643236F_FC70_11D3_A536_0090278A1BB8"
returned 1603 
...
0031:err:msi:ITERATE_Actions Execution halted, action L"InstallFinalize"
returned 1603 
--- snip ---

Unfortunately we run into our old friend here: bug 12401 ("NET Framework 2.0,
3.0, 4.0 installers and other apps that make use of GAC API for managed
assembly installation need reparse point/junction API support, i.e.
DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)").

A workaround/compromise could be that Wine's fusion also creates the legacy GAC
cache/root folder by default so that scheduled native NGEN/mscorsvc runs will
succeed on all assemblies.

Regards

-- 
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