2 * Implementation of mscoree.dll
3 * Microsoft Component Object Runtime Execution Engine
5 * Copyright 2006 Paul Chitescu
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "strongname.h"
44 #include "wine/list.h"
45 #include "mscoree_private.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
51 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
53 struct print_handler_tls
59 static DWORD print_tls_index
= TLS_OUT_OF_INDEXES
;
61 typedef HRESULT (*fnCreateInstance
)(REFIID riid
, LPVOID
*ppObj
);
63 char *WtoA(LPCWSTR wstr
)
68 length
= WideCharToMultiByte(CP_UTF8
, 0, wstr
, -1, NULL
, 0, NULL
, NULL
);
70 result
= HeapAlloc(GetProcessHeap(), 0, length
);
73 WideCharToMultiByte(CP_UTF8
, 0, wstr
, -1, result
, length
, NULL
, NULL
);
78 static BOOL
get_install_root(LPWSTR install_dir
)
80 static const WCHAR dotnet_key
[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','.','N','E','T','F','r','a','m','e','w','o','r','k','\\',0};
81 static const WCHAR install_root
[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
86 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, dotnet_key
, 0, KEY_READ
, &key
))
89 len
= MAX_PATH
* sizeof(WCHAR
);
90 if (RegQueryValueExW(key
, install_root
, 0, NULL
, (LPBYTE
)install_dir
, &len
))
100 typedef struct mscorecf
102 IClassFactory IClassFactory_iface
;
105 fnCreateInstance pfnCreateInstance
;
110 static inline mscorecf
*impl_from_IClassFactory( IClassFactory
*iface
)
112 return CONTAINING_RECORD(iface
, mscorecf
, IClassFactory_iface
);
115 static HRESULT WINAPI
mscorecf_QueryInterface(IClassFactory
*iface
, REFIID riid
, LPVOID
*ppobj
)
117 TRACE("%s %p\n", debugstr_guid(riid
), ppobj
);
119 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
120 IsEqualGUID(riid
, &IID_IClassFactory
))
122 IClassFactory_AddRef( iface
);
127 ERR("interface %s not implemented\n", debugstr_guid(riid
));
128 return E_NOINTERFACE
;
131 static ULONG WINAPI
mscorecf_AddRef(IClassFactory
*iface
)
133 mscorecf
*This
= impl_from_IClassFactory(iface
);
134 ULONG ref
= InterlockedIncrement(&This
->ref
);
136 TRACE("%p ref=%lu\n", This
, ref
);
141 static ULONG WINAPI
mscorecf_Release(IClassFactory
*iface
)
143 mscorecf
*This
= impl_from_IClassFactory(iface
);
144 ULONG ref
= InterlockedDecrement(&This
->ref
);
146 TRACE("%p ref=%lu\n", This
, ref
);
150 HeapFree(GetProcessHeap(), 0, This
);
156 static HRESULT WINAPI
mscorecf_CreateInstance(IClassFactory
*iface
,LPUNKNOWN pOuter
,
157 REFIID riid
, LPVOID
*ppobj
)
159 mscorecf
*This
= impl_from_IClassFactory( iface
);
163 TRACE("%p %s %p\n", pOuter
, debugstr_guid(riid
), ppobj
);
168 return CLASS_E_NOAGGREGATION
;
170 hr
= This
->pfnCreateInstance( &This
->clsid
, (LPVOID
*) &punk
);
173 hr
= IUnknown_QueryInterface( punk
, riid
, ppobj
);
175 IUnknown_Release( punk
);
179 WARN("Cannot create an instance object. 0x%08lx\n", hr
);
184 static HRESULT WINAPI
mscorecf_LockServer(IClassFactory
*iface
, BOOL dolock
)
186 FIXME("(%p)->(%d),stub!\n",iface
,dolock
);
190 static const struct IClassFactoryVtbl mscorecf_vtbl
=
192 mscorecf_QueryInterface
,
195 mscorecf_CreateInstance
,
199 HRESULT WINAPI
CorBindToRuntimeHost(LPCWSTR pwszVersion
, LPCWSTR pwszBuildFlavor
,
200 LPCWSTR pwszHostConfigFile
, VOID
*pReserved
,
201 DWORD startupFlags
, REFCLSID rclsid
,
202 REFIID riid
, LPVOID
*ppv
)
205 ICLRRuntimeInfo
*info
;
207 TRACE("(%s, %s, %s, %p, %ld, %s, %s, %p)\n", debugstr_w(pwszVersion
),
208 debugstr_w(pwszBuildFlavor
), debugstr_w(pwszHostConfigFile
), pReserved
,
209 startupFlags
, debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
213 ret
= get_runtime_info(NULL
, pwszVersion
, pwszHostConfigFile
, NULL
, startupFlags
, 0, TRUE
, &info
);
217 ret
= ICLRRuntimeInfo_GetInterface(info
, rclsid
, riid
, ppv
);
219 ICLRRuntimeInfo_Release(info
);
225 void CDECL
mono_print_handler_fn(const char *string
, INT is_stdout
)
227 struct print_handler_tls
*tls
= TlsGetValue(print_tls_index
);
231 tls
= HeapAlloc(GetProcessHeap(), 0, sizeof(*tls
));
233 TlsSetValue(print_tls_index
, tls
);
238 int remaining_buffer
= sizeof(tls
->buffer
) - tls
->length
;
239 int length
= strlen(string
);
240 const char *newline
= memchr(string
, '\n', min(length
, remaining_buffer
));
244 length
= newline
- string
+ 1;
245 wine_dbg_printf("%.*s%.*s", tls
->length
, tls
->buffer
, length
, string
);
249 else if (length
> remaining_buffer
)
251 /* this would overflow Wine's debug buffer */
252 wine_dbg_printf("%.*s%.*s\n", tls
->length
, tls
->buffer
, remaining_buffer
, string
);
254 string
+= remaining_buffer
;
258 memcpy(tls
->buffer
+ tls
->length
, string
, length
);
259 tls
->length
+= length
;
265 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
267 TRACE("(%p, %ld, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
271 case DLL_PROCESS_ATTACH
:
274 print_tls_index
= TlsAlloc();
276 if (print_tls_index
== TLS_OUT_OF_INDEXES
)
280 case DLL_THREAD_DETACH
:
281 if (print_tls_index
!= TLS_OUT_OF_INDEXES
)
282 HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index
));
284 case DLL_PROCESS_DETACH
:
285 expect_no_runtimes();
286 if (lpvReserved
) break; /* process is terminating */
287 runtimehost_uninit();
288 if (print_tls_index
!= TLS_OUT_OF_INDEXES
)
290 HeapFree(GetProcessHeap(), 0, TlsGetValue(print_tls_index
));
291 TlsFree(print_tls_index
);
298 __int32 WINAPI
_CorExeMain2(PBYTE ptrMemory
, DWORD cntMemory
, LPWSTR imageName
, LPWSTR loaderName
, LPWSTR cmdLine
)
300 TRACE("(%p, %lu, %s, %s, %s)\n", ptrMemory
, cntMemory
, debugstr_w(imageName
), debugstr_w(loaderName
), debugstr_w(cmdLine
));
301 FIXME("Directly running .NET applications not supported.\n");
305 void WINAPI
CorExitProcess(int exitCode
)
307 TRACE("(%x)\n", exitCode
);
308 CLRMetaHost_ExitProcess(0, exitCode
);
311 VOID WINAPI
_CorImageUnloading(PVOID imageBase
)
313 TRACE("(%p): stub\n", imageBase
);
316 HRESULT WINAPI
_CorValidateImage(PVOID
* imageBase
, LPCWSTR imageName
)
318 TRACE("(%p, %s): stub\n", imageBase
, debugstr_w(imageName
));
322 HRESULT WINAPI
GetCORSystemDirectory(LPWSTR pbuffer
, DWORD cchBuffer
, DWORD
*dwLength
)
324 ICLRRuntimeInfo
*info
;
327 TRACE("(%p, %ld, %p)!\n", pbuffer
, cchBuffer
, dwLength
);
329 if (!dwLength
|| !pbuffer
)
332 ret
= get_runtime_info(NULL
, NULL
, NULL
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, TRUE
, &info
);
336 *dwLength
= cchBuffer
;
337 ret
= ICLRRuntimeInfo_GetRuntimeDirectory(info
, pbuffer
, dwLength
);
339 ICLRRuntimeInfo_Release(info
);
345 HRESULT WINAPI
GetCORVersion(LPWSTR pbuffer
, DWORD cchBuffer
, DWORD
*dwLength
)
347 ICLRRuntimeInfo
*info
;
350 TRACE("(%p, %ld, %p)!\n", pbuffer
, cchBuffer
, dwLength
);
352 if (!dwLength
|| !pbuffer
)
355 ret
= get_runtime_info(NULL
, NULL
, NULL
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, TRUE
, &info
);
359 *dwLength
= cchBuffer
;
360 ret
= ICLRRuntimeInfo_GetVersionString(info
, pbuffer
, dwLength
);
362 ICLRRuntimeInfo_Release(info
);
368 HRESULT WINAPI
CorIsLatestSvc(int *unk1
, int *unk2
)
370 ERR_(winediag
)("If this function is called, it is likely the result of a broken .NET installation\n");
378 HRESULT WINAPI
CorGetSvc(void *unk
)
380 ERR_(winediag
)("If this function is called, it is likely the result of a broken .NET installation\n");
385 HRESULT WINAPI
GetRequestedRuntimeInfo(LPCWSTR pExe
, LPCWSTR pwszVersion
, LPCWSTR pConfigurationFile
,
386 DWORD startupFlags
, DWORD runtimeInfoFlags
, LPWSTR pDirectory
, DWORD dwDirectory
, DWORD
*dwDirectoryLength
,
387 LPWSTR pVersion
, DWORD cchBuffer
, DWORD
*dwlength
)
390 ICLRRuntimeInfo
*info
;
393 TRACE("(%s, %s, %s, 0x%08lx, 0x%08lx, %p, 0x%08lx, %p, %p, 0x%08lx, %p)\n", debugstr_w(pExe
),
394 debugstr_w(pwszVersion
), debugstr_w(pConfigurationFile
), startupFlags
, runtimeInfoFlags
, pDirectory
,
395 dwDirectory
, dwDirectoryLength
, pVersion
, cchBuffer
, dwlength
);
397 if (!dwDirectoryLength
) dwDirectoryLength
= &length_dummy
;
399 if (!dwlength
) dwlength
= &length_dummy
;
401 ret
= get_runtime_info(pExe
, pwszVersion
, pConfigurationFile
, NULL
, startupFlags
, runtimeInfoFlags
, TRUE
, &info
);
405 *dwlength
= cchBuffer
;
406 ret
= ICLRRuntimeInfo_GetVersionString(info
, pVersion
, dwlength
);
411 pVersion
[0] = pwszVersion
[0];
413 *dwDirectoryLength
= dwDirectory
;
414 ret
= ICLRRuntimeInfo_GetRuntimeDirectory(info
, pDirectory
, dwDirectoryLength
);
417 ICLRRuntimeInfo_Release(info
);
423 HRESULT WINAPI
GetRequestedRuntimeVersion(LPWSTR pExe
, LPWSTR pVersion
, DWORD cchBuffer
, DWORD
*dwlength
)
425 TRACE("(%s, %p, %ld, %p)\n", debugstr_w(pExe
), pVersion
, cchBuffer
, dwlength
);
430 return GetRequestedRuntimeInfo(pExe
, NULL
, NULL
, 0, 0, NULL
, 0, NULL
, pVersion
, cchBuffer
, dwlength
);
433 HRESULT WINAPI
GetRealProcAddress(LPCSTR procname
, void **ppv
)
435 FIXME("(%s, %p)\n", debugstr_a(procname
), ppv
);
436 return CLR_E_SHIM_RUNTIMEEXPORT
;
439 HRESULT WINAPI
GetFileVersion(LPCWSTR szFilename
, LPWSTR szBuffer
, DWORD cchBuffer
, DWORD
*dwLength
)
441 TRACE("(%s, %p, %ld, %p)\n", debugstr_w(szFilename
), szBuffer
, cchBuffer
, dwLength
);
443 if (!szFilename
|| !dwLength
)
446 *dwLength
= cchBuffer
;
447 return CLRMetaHost_GetVersionFromFile(0, szFilename
, szBuffer
, dwLength
);
450 HRESULT WINAPI
LoadLibraryShim( LPCWSTR szDllName
, LPCWSTR szVersion
, LPVOID pvReserved
, HMODULE
* phModDll
)
453 WCHAR dll_filename
[MAX_PATH
];
454 WCHAR version
[MAX_PATH
];
455 static const WCHAR default_version
[] = {'v','1','.','1','.','4','3','2','2',0};
456 static const WCHAR slash
[] = {'\\',0};
459 TRACE("(%p %s, %p, %p, %p)\n", szDllName
, debugstr_w(szDllName
), szVersion
, pvReserved
, phModDll
);
461 if (!szDllName
|| !phModDll
)
464 if (!get_install_root(dll_filename
))
466 ERR("error reading registry key for installroot\n");
473 ret
= GetCORVersion(version
, MAX_PATH
, &dummy
);
477 szVersion
= default_version
;
479 lstrcatW(dll_filename
, szVersion
);
480 lstrcatW(dll_filename
, slash
);
483 lstrcatW(dll_filename
, szDllName
);
485 *phModDll
= LoadLibraryW(dll_filename
);
487 return *phModDll
? S_OK
: E_HANDLE
;
490 HRESULT WINAPI
LockClrVersion(FLockClrVersionCallback hostCallback
, FLockClrVersionCallback
*pBeginHostSetup
, FLockClrVersionCallback
*pEndHostSetup
)
492 FIXME("(%p %p %p): stub\n", hostCallback
, pBeginHostSetup
, pEndHostSetup
);
496 HRESULT WINAPI
CoInitializeCor(DWORD fFlags
)
498 FIXME("(0x%08lx): stub\n", fFlags
);
502 HRESULT WINAPI
GetAssemblyMDImport(LPCWSTR szFileName
, REFIID riid
, IUnknown
**ppIUnk
)
504 FIXME("(%p %s, %s, %p): stub\n", szFileName
, debugstr_w(szFileName
), debugstr_guid(riid
), *ppIUnk
);
505 return ERROR_CALL_NOT_IMPLEMENTED
;
508 HRESULT WINAPI
GetVersionFromProcess(HANDLE hProcess
, LPWSTR pVersion
, DWORD cchBuffer
, DWORD
*dwLength
)
510 FIXME("(%p, %p, %ld, %p): stub\n", hProcess
, pVersion
, cchBuffer
, dwLength
);
514 HRESULT WINAPI
LoadStringRCEx(LCID culture
, UINT resId
, LPWSTR pBuffer
, int iBufLen
, int bQuiet
, int* pBufLen
)
517 if ((iBufLen
<= 0) || !pBuffer
)
521 FIXME("(%ld, %x, %p, %d, %d, %p): semi-stub\n", culture
, resId
, pBuffer
, iBufLen
, bQuiet
, pBufLen
);
527 *pBufLen
= lstrlenW(pBuffer
);
531 HRESULT WINAPI
LoadStringRC(UINT resId
, LPWSTR pBuffer
, int iBufLen
, int bQuiet
)
533 return LoadStringRCEx(-1, resId
, pBuffer
, iBufLen
, bQuiet
, NULL
);
536 HRESULT WINAPI
CorBindToRuntimeEx(LPWSTR szVersion
, LPWSTR szBuildFlavor
, DWORD nflags
, REFCLSID rslsid
,
537 REFIID riid
, LPVOID
*ppv
)
540 ICLRRuntimeInfo
*info
;
542 TRACE("%s %s %ld %s %s %p\n", debugstr_w(szVersion
), debugstr_w(szBuildFlavor
), nflags
, debugstr_guid( rslsid
),
543 debugstr_guid( riid
), ppv
);
547 ret
= get_runtime_info(NULL
, szVersion
, NULL
, NULL
, nflags
, RUNTIME_INFO_UPGRADE_VERSION
, TRUE
, &info
);
551 ret
= ICLRRuntimeInfo_GetInterface(info
, rslsid
, riid
, ppv
);
553 ICLRRuntimeInfo_Release(info
);
559 HRESULT WINAPI
CorBindToCurrentRuntime(LPCWSTR filename
, REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
562 ICLRRuntimeInfo
*info
;
564 TRACE("(%s, %s, %s, %p)\n", debugstr_w(filename
), debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
568 ret
= get_runtime_info(NULL
, NULL
, filename
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, TRUE
, &info
);
572 ret
= ICLRRuntimeInfo_GetInterface(info
, rclsid
, riid
, ppv
);
574 ICLRRuntimeInfo_Release(info
);
580 STDAPI
ClrCreateManagedInstance(LPCWSTR pTypeName
, REFIID riid
, void **ppObject
)
583 ICLRRuntimeInfo
*info
;
588 TRACE("(%s,%s,%p)\n", debugstr_w(pTypeName
), debugstr_guid(riid
), ppObject
);
590 /* FIXME: How to determine which runtime version to use? */
591 ret
= get_runtime_info(NULL
, NULL
, NULL
, NULL
, 0, RUNTIME_INFO_UPGRADE_VERSION
, TRUE
, &info
);
595 ret
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
597 ICLRRuntimeInfo_Release(info
);
601 ret
= RuntimeHost_CreateManagedInstance(host
, pTypeName
, NULL
, &obj
);
604 ret
= RuntimeHost_GetIUnknownForObject(host
, obj
, &unk
);
608 ret
= IUnknown_QueryInterface(unk
, riid
, ppObject
);
609 IUnknown_Release(unk
);
615 BOOLEAN WINAPI
StrongNameSignatureVerification(LPCWSTR filename
, DWORD inFlags
, DWORD
*pOutFlags
)
617 FIXME("(%s, 0x%lX, %p): stub\n", debugstr_w(filename
), inFlags
, pOutFlags
);
621 BOOLEAN WINAPI
StrongNameSignatureVerificationEx(LPCWSTR filename
, BOOLEAN forceVerification
, BOOLEAN
*pVerified
)
623 FIXME("(%s, %u, %p): stub\n", debugstr_w(filename
), forceVerification
, pVerified
);
628 HRESULT WINAPI
CreateDebuggingInterfaceFromVersion(int nDebugVersion
, LPCWSTR version
, IUnknown
**ppv
)
630 static const WCHAR v2_0
[] = {'v','2','.','0','.','5','0','7','2','7',0};
632 ICLRRuntimeInfo
*runtimeinfo
;
634 if(nDebugVersion
< 1 || nDebugVersion
> 4)
637 TRACE("(%d %s, %p): stub\n", nDebugVersion
, debugstr_w(version
), ppv
);
644 if(wcscmp(version
, v2_0
) != 0)
646 FIXME("Currently .NET Version '%s' not support.\n", debugstr_w(version
));
650 if(nDebugVersion
!= 3)
653 hr
= CLRMetaHost_GetRuntime(0, version
, &IID_ICLRRuntimeInfo
, (void**)&runtimeinfo
);
656 hr
= ICLRRuntimeInfo_GetInterface(runtimeinfo
, &CLSID_CLRDebuggingLegacy
, &IID_ICorDebug
, (void**)ppv
);
658 ICLRRuntimeInfo_Release(runtimeinfo
);
667 HRESULT WINAPI
CLRCreateInstance(REFCLSID clsid
, REFIID riid
, LPVOID
*ppInterface
)
669 TRACE("(%s,%s,%p)\n", debugstr_guid(clsid
), debugstr_guid(riid
), ppInterface
);
671 if (IsEqualGUID(clsid
, &CLSID_CLRMetaHost
))
672 return CLRMetaHost_CreateInstance(riid
, ppInterface
);
673 if (IsEqualGUID(clsid
, &CLSID_CLRMetaHostPolicy
))
674 return CLRMetaHostPolicy_CreateInstance(riid
, ppInterface
);
676 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
678 return CLASS_E_CLASSNOTAVAILABLE
;
681 HRESULT WINAPI
CreateInterface(REFCLSID clsid
, REFIID riid
, LPVOID
*ppInterface
)
683 TRACE("(%s,%s,%p)\n", debugstr_guid(clsid
), debugstr_guid(riid
), ppInterface
);
685 return CLRCreateInstance(clsid
, riid
, ppInterface
);
688 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
693 TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
698 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf
));
700 This
->IClassFactory_iface
.lpVtbl
= &mscorecf_vtbl
;
701 This
->pfnCreateInstance
= create_monodata
;
703 This
->clsid
= *rclsid
;
705 hr
= IClassFactory_QueryInterface( &This
->IClassFactory_iface
, riid
, ppv
);
706 IClassFactory_Release(&This
->IClassFactory_iface
);
711 static void parse_msi_version_string(const char *version
, int *parts
)
713 const char *minor_start
, *build_start
;
715 parts
[0] = atoi(version
);
717 parts
[1] = parts
[2] = 0;
719 minor_start
= strchr(version
, '.');
723 parts
[1] = atoi(minor_start
);
725 build_start
= strchr(minor_start
, '.');
727 parts
[2] = atoi(build_start
+1);
731 static int compare_versions(const char *a
, const char *b
)
733 int a_parts
[3], b_parts
[3], i
;
735 parse_msi_version_string(a
, a_parts
);
736 parse_msi_version_string(b
, b_parts
);
739 if (a_parts
[i
] != b_parts
[i
])
740 return a_parts
[i
] - b_parts
[i
];
745 static BOOL
invoke_appwiz(void)
747 PROCESS_INFORMATION pi
;
754 static const WCHAR controlW
[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
755 static const WCHAR argsW
[] =
756 {' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','m','o','n','o',0};
758 len
= GetSystemDirectoryW(app
, MAX_PATH
- ARRAY_SIZE(controlW
));
759 memcpy(app
+len
, controlW
, sizeof(controlW
));
761 args
= HeapAlloc(GetProcessHeap(), 0, (len
*sizeof(WCHAR
) + sizeof(controlW
) + sizeof(argsW
)));
765 memcpy(args
, app
, len
*sizeof(WCHAR
) + sizeof(controlW
));
766 memcpy(args
+ len
+ ARRAY_SIZE(controlW
) - 1, argsW
, sizeof(argsW
));
768 TRACE("starting %s\n", debugstr_w(args
));
770 memset(&si
, 0, sizeof(si
));
772 ret
= CreateProcessW(app
, args
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
773 HeapFree(GetProcessHeap(), 0, args
);
775 CloseHandle(pi
.hThread
);
776 WaitForSingleObject(pi
.hProcess
, INFINITE
);
777 CloseHandle(pi
.hProcess
);
783 static BOOL
get_support_msi(LPCWSTR mono_path
, LPWSTR msi_path
)
785 static const WCHAR support_msi_relative
[] = {'\\','s','u','p','p','o','r','t','\\','w','i','n','e','m','o','n','o','-','s','u','p','p','o','r','t','.','m','s','i',0};
786 UINT (WINAPI
*pMsiOpenPackageW
)(LPCWSTR
,ULONG
*);
787 UINT (WINAPI
*pMsiGetProductPropertyA
)(ULONG
,LPCSTR
,LPSTR
,LPDWORD
);
788 UINT (WINAPI
*pMsiCloseHandle
)(ULONG
);
790 char versionstringbuf
[15];
796 hmsi
= GetModuleHandleA("msi");
798 lstrcpyW(msi_path
, mono_path
);
799 lstrcatW(msi_path
, support_msi_relative
);
801 pMsiOpenPackageW
= (void*)GetProcAddress(hmsi
, "MsiOpenPackageW");
803 res
= pMsiOpenPackageW(msi_path
, &msiproduct
);
805 if (res
== ERROR_SUCCESS
)
807 buffer_size
= sizeof(versionstringbuf
);
809 pMsiGetProductPropertyA
= (void*)GetProcAddress(hmsi
, "MsiGetProductPropertyA");
811 res
= pMsiGetProductPropertyA(msiproduct
, "ProductVersion", versionstringbuf
, &buffer_size
);
813 pMsiCloseHandle
= (void*)GetProcAddress(hmsi
, "MsiCloseHandle");
815 pMsiCloseHandle(msiproduct
);
818 if (res
== ERROR_SUCCESS
) {
819 TRACE("found support msi version %s at %s\n", versionstringbuf
, debugstr_w(msi_path
));
821 if (compare_versions(WINE_MONO_VERSION
, versionstringbuf
) <= 0)
830 static BOOL
install_wine_mono(void)
832 BOOL is_wow64
= FALSE
;
834 HRESULT initresult
= E_FAIL
;
835 UINT (WINAPI
*pMsiEnumRelatedProductsA
)(LPCSTR
,DWORD
,DWORD
,LPSTR
);
836 UINT (WINAPI
*pMsiGetProductInfoA
)(LPCSTR
,LPCSTR
,LPSTR
,DWORD
*);
837 UINT (WINAPI
*pMsiInstallProductW
)(LPCWSTR
,LPCWSTR
);
838 char versionstringbuf
[15];
839 char productcodebuf
[39];
843 WCHAR mono_path
[MAX_PATH
];
844 WCHAR support_msi_path
[MAX_PATH
];
846 static const char* mono_upgrade_code
= "{DE624609-C6B5-486A-9274-EF0B854F6BC5}";
848 IsWow64Process(GetCurrentProcess(), &is_wow64
);
852 TRACE("not installing mono in wow64 process\n");
856 TRACE("searching for mono runtime\n");
858 if (!get_mono_path(mono_path
, FALSE
))
860 TRACE("mono runtime not found\n");
861 return invoke_appwiz();
864 TRACE("mono runtime is at %s\n", debugstr_w(mono_path
));
866 hmsi
= LoadLibraryA("msi");
870 ERR("couldn't load msi.dll\n");
874 pMsiEnumRelatedProductsA
= (void*)GetProcAddress(hmsi
, "MsiEnumRelatedProductsA");
876 res
= pMsiEnumRelatedProductsA(mono_upgrade_code
, 0, 0, productcodebuf
);
878 if (res
== ERROR_SUCCESS
)
880 pMsiGetProductInfoA
= (void*)GetProcAddress(hmsi
, "MsiGetProductInfoA");
882 buffer_size
= sizeof(versionstringbuf
);
884 res
= pMsiGetProductInfoA(productcodebuf
, "VersionString", versionstringbuf
, &buffer_size
);
886 else if (res
!= ERROR_NO_MORE_ITEMS
)
888 ERR("MsiEnumRelatedProducts failed, err=%u\n", res
);
891 if (res
== ERROR_SUCCESS
)
893 TRACE("found installed support package %s\n", versionstringbuf
);
895 if (compare_versions(WINE_MONO_VERSION
, versionstringbuf
) <= 0)
897 TRACE("support package is at least %s, quitting\n", WINE_MONO_VERSION
);
903 initresult
= CoInitialize(NULL
);
905 ret
= get_support_msi(mono_path
, support_msi_path
);
908 /* Try looking outside c:\windows\mono */
909 ret
= (get_mono_path(mono_path
, TRUE
) &&
910 get_support_msi(mono_path
, support_msi_path
));
915 TRACE("installing support msi\n");
917 pMsiInstallProductW
= (void*)GetProcAddress(hmsi
, "MsiInstallProductW");
919 res
= pMsiInstallProductW(support_msi_path
, NULL
);
921 if (res
== ERROR_SUCCESS
)
927 ERR("MsiInstallProduct failed, err=%i\n", res
);
930 ret
= invoke_appwiz();
935 if (SUCCEEDED(initresult
))
940 HRESULT WINAPI
DllRegisterServer(void)
944 return __wine_register_resources();
947 HRESULT WINAPI
DllUnregisterServer(void)
949 return __wine_unregister_resources();
952 void WINAPI
CoEEShutDownCOM(void)
957 INT WINAPI
ND_RU1( const void *ptr
, INT offset
)
959 return *((const BYTE
*)ptr
+ offset
);
962 INT WINAPI
ND_RI2( const void *ptr
, INT offset
)
964 return *(const SHORT
*)((const BYTE
*)ptr
+ offset
);
967 INT WINAPI
ND_RI4( const void *ptr
, INT offset
)
969 return *(const INT
*)((const BYTE
*)ptr
+ offset
);
972 INT64 WINAPI
ND_RI8( const void *ptr
, INT offset
)
974 return *(const INT64
*)((const BYTE
*)ptr
+ offset
);
977 void WINAPI
ND_WU1( void *ptr
, INT offset
, BYTE val
)
979 *((BYTE
*)ptr
+ offset
) = val
;
982 void WINAPI
ND_WI2( void *ptr
, INT offset
, SHORT val
)
984 *(SHORT
*)((BYTE
*)ptr
+ offset
) = val
;
987 void WINAPI
ND_WI4( void *ptr
, INT offset
, INT val
)
989 *(INT
*)((BYTE
*)ptr
+ offset
) = val
;
992 void WINAPI
ND_WI8( void *ptr
, INT offset
, INT64 val
)
994 *(INT64
*)((BYTE
*)ptr
+ offset
) = val
;
997 void WINAPI
ND_CopyObjDst( const void *src
, void *dst
, INT offset
, INT size
)
999 memcpy( (BYTE
*)dst
+ offset
, src
, size
);
1002 void WINAPI
ND_CopyObjSrc( const void *src
, INT offset
, void *dst
, INT size
)
1004 memcpy( dst
, (const BYTE
*)src
+ offset
, size
);