mscoree_main.c 21.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Implementation of mscoree.dll
 * Microsoft Component Object Runtime Execution Engine
 *
 * Copyright 2006 Paul Chitescu
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>

24
#define COBJMACROS
25
#include "wine/unicode.h"
26
#include "wine/library.h"
27 28
#include "windef.h"
#include "winbase.h"
29
#include "winuser.h"
30
#include "winnls.h"
31
#include "winreg.h"
32
#include "ole2.h"
33
#include "ocidl.h"
34
#include "shellapi.h"
35

36
#include "initguid.h"
37
#include "msxml2.h"
38
#include "corerror.h"
39
#include "cor.h"
40
#include "mscoree.h"
41 42
#include "corhdr.h"
#include "cordebug.h"
43
#include "metahost.h"
44
#include "fusion.h"
45
#include "wine/list.h"
46
#include "mscoree_private.h"
47
#include "rpcproxy.h"
48

49 50 51 52
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL( mscoree );

53 54
static HINSTANCE MSCOREE_hInstance;

55 56
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
char *WtoA(LPCWSTR wstr)
{
    int length;
    char *result;

    length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);

    result = HeapAlloc(GetProcessHeap(), 0, length);

    if (result)
        WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL);

    return result;
}

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
static BOOL get_install_root(LPWSTR install_dir)
{
    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};
    const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};

    DWORD len;
    HKEY key;

    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_key, 0, KEY_READ, &key))
        return FALSE;

    len = MAX_PATH;
    if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
    {
        RegCloseKey(key);
        return FALSE;
    }
    RegCloseKey(key);

    return TRUE;
}

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
typedef struct mscorecf
{
    IClassFactory    IClassFactory_iface;
    LONG ref;

    fnCreateInstance pfnCreateInstance;

    CLSID clsid;
} mscorecf;

static inline mscorecf *impl_from_IClassFactory( IClassFactory *iface )
{
    return CONTAINING_RECORD(iface, mscorecf, IClassFactory_iface);
}

static HRESULT WINAPI mscorecf_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj )
{
    TRACE("%s %p\n", debugstr_guid(riid), ppobj);

    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IClassFactory))
    {
        IClassFactory_AddRef( iface );
        *ppobj = iface;
        return S_OK;
    }

    ERR("interface %s not implemented\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI mscorecf_AddRef(IClassFactory *iface )
{
    mscorecf *This = impl_from_IClassFactory(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("%p ref=%u\n", This, ref);

    return ref;
}

static ULONG WINAPI mscorecf_Release(IClassFactory *iface )
{
    mscorecf *This = impl_from_IClassFactory(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("%p ref=%u\n", This, ref);

    if (ref == 0)
    {
        HeapFree(GetProcessHeap(), 0, This);
    }

    return ref;
}

static HRESULT WINAPI mscorecf_CreateInstance(IClassFactory *iface,LPUNKNOWN pOuter,
                            REFIID riid, LPVOID *ppobj )
{
    mscorecf *This = impl_from_IClassFactory( iface );
    HRESULT hr;
    IUnknown *punk;

    TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );

    *ppobj = NULL;

    if (pOuter)
        return CLASS_E_NOAGGREGATION;

    hr = This->pfnCreateInstance( &This->clsid, (LPVOID*) &punk );
    if (SUCCEEDED(hr))
    {
        hr = IUnknown_QueryInterface( punk, riid, ppobj );

        IUnknown_Release( punk );
    }
    else
    {
        WARN("Cannot create an instance object. 0x%08x\n", hr);
    }
    return hr;
}

static HRESULT WINAPI mscorecf_LockServer(IClassFactory *iface, BOOL dolock)
{
    FIXME("(%p)->(%d),stub!\n",iface,dolock);
    return S_OK;
}

static const struct IClassFactoryVtbl mscorecf_vtbl =
{
    mscorecf_QueryInterface,
    mscorecf_AddRef,
    mscorecf_Release,
    mscorecf_CreateInstance,
    mscorecf_LockServer
};

193 194 195 196 197
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
                                    LPCWSTR pwszHostConfigFile, VOID *pReserved,
                                    DWORD startupFlags, REFCLSID rclsid,
                                    REFIID riid, LPVOID *ppv)
{
198 199 200 201
    HRESULT ret;
    ICLRRuntimeInfo *info;

    TRACE("(%s, %s, %s, %p, %d, %s, %s, %p)\n", debugstr_w(pwszVersion),
202
          debugstr_w(pwszBuildFlavor), debugstr_w(pwszHostConfigFile), pReserved,
203
          startupFlags, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
204

205 206 207 208 209
    *ppv = NULL;

    ret = get_runtime_info(NULL, pwszVersion, pwszHostConfigFile, startupFlags, 0, TRUE, &info);

    if (SUCCEEDED(ret))
210
    {
211 212 213
        ret = ICLRRuntimeInfo_GetInterface(info, rclsid, riid, ppv);

        ICLRRuntimeInfo_Release(info);
214 215
    }

216
    return ret;
217 218 219 220 221 222
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);

223 224
    MSCOREE_hInstance = hinstDLL;

225 226 227 228 229
    switch (fdwReason)
    {
    case DLL_WINE_PREATTACH:
        return FALSE;  /* prefer native version */
    case DLL_PROCESS_ATTACH:
230
        runtimehost_init();
231 232 233
        DisableThreadLibraryCalls(hinstDLL);
        break;
    case DLL_PROCESS_DETACH:
234
        expect_no_runtimes();
235 236
        if (lpvReserved) break; /* process is terminating */
        runtimehost_uninit();
237 238 239 240 241
        break;
    }
    return TRUE;
}

242
__int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, LPWSTR loaderName, LPWSTR cmdLine)
243 244 245 246 247 248
{
    TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
    FIXME("Directly running .NET applications not supported.\n");
    return -1;
}

249 250
void WINAPI CorExitProcess(int exitCode)
{
251 252
    TRACE("(%x)\n", exitCode);
    unload_all_runtimes();
253 254 255
    ExitProcess(exitCode);
}

256
VOID WINAPI _CorImageUnloading(PVOID imageBase)
257 258 259 260
{
    TRACE("(%p): stub\n", imageBase);
}

261
HRESULT WINAPI _CorValidateImage(PVOID* imageBase, LPCWSTR imageName)
262 263 264 265
{
    TRACE("(%p, %s): stub\n", imageBase, debugstr_w(imageName));
    return E_FAIL;
}
266

267 268
HRESULT WINAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
{
269 270
    ICLRRuntimeInfo *info;
    HRESULT ret;
271

272
    TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
273

274
    if (!dwLength || !pbuffer)
275 276
        return E_POINTER;

277
    ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
278

279
    if (SUCCEEDED(ret))
280
    {
281 282
        *dwLength = cchBuffer;
        ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pbuffer, dwLength);
283

284
        ICLRRuntimeInfo_Release(info);
285
    }
286

287
    return ret;
288 289
}

290 291
HRESULT WINAPI GetCORVersion(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
{
292 293
    ICLRRuntimeInfo *info;
    HRESULT ret;
294

295
    TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
296

297
    if (!dwLength || !pbuffer)
298 299
        return E_POINTER;

300
    ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
301

302 303 304 305
    if (SUCCEEDED(ret))
    {
        *dwLength = cchBuffer;
        ret = ICLRRuntimeInfo_GetVersionString(info, pbuffer, dwLength);
306

307 308
        ICLRRuntimeInfo_Release(info);
    }
309

310
    return ret;
311
}
312

313 314 315 316
HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWSTR pConfigurationFile,
    DWORD startupFlags, DWORD runtimeInfoFlags, LPWSTR pDirectory, DWORD dwDirectory, DWORD *dwDirectoryLength,
    LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
{
317
    HRESULT ret;
318 319
    ICLRRuntimeInfo *info;
    DWORD length_dummy;
320

321
    TRACE("(%s, %s, %s, 0x%08x, 0x%08x, %p, 0x%08x, %p, %p, 0x%08x, %p)\n", debugstr_w(pExe),
322 323
          debugstr_w(pwszVersion), debugstr_w(pConfigurationFile), startupFlags, runtimeInfoFlags, pDirectory,
          dwDirectory, dwDirectoryLength, pVersion, cchBuffer, dwlength);
324

325
    if (!dwDirectoryLength) dwDirectoryLength = &length_dummy;
326

327
    if (!dwlength) dwlength = &length_dummy;
328

329
    ret = get_runtime_info(pExe, pwszVersion, pConfigurationFile, startupFlags, runtimeInfoFlags, TRUE, &info);
330

331 332 333 334
    if (SUCCEEDED(ret))
    {
        *dwlength = cchBuffer;
        ret = ICLRRuntimeInfo_GetVersionString(info, pVersion, dwlength);
335

336
        if (SUCCEEDED(ret))
337
        {
338 339 340
            if(pwszVersion)
                pVersion[0] = pwszVersion[0];

341 342
            *dwDirectoryLength = dwDirectory;
            ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pDirectory, dwDirectoryLength);
343
        }
344 345

        ICLRRuntimeInfo_Release(info);
346
    }
347

348
    return ret;
349 350
}

351 352
HRESULT WINAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
{
353
    TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), pVersion, cchBuffer, dwlength);
354 355 356 357 358 359 360

    if(!dwlength)
        return E_POINTER;

    return GetRequestedRuntimeInfo(pExe, NULL, NULL, 0, 0, NULL, 0, NULL, pVersion, cchBuffer, dwlength);
}

361 362 363 364 365 366
HRESULT WINAPI GetRealProcAddress(LPCSTR procname, void **ppv)
{
    FIXME("(%s, %p)\n", debugstr_a(procname), ppv);
    return CLR_E_SHIM_RUNTIMEEXPORT;
}

367 368 369 370 371 372 373 374 375 376 377
HRESULT WINAPI GetFileVersion(LPCWSTR szFilename, LPWSTR szBuffer, DWORD cchBuffer, DWORD *dwLength)
{
    TRACE("(%s, %p, %d, %p)\n", debugstr_w(szFilename), szBuffer, cchBuffer, dwLength);

    if (!szFilename || !dwLength)
        return E_POINTER;

    *dwLength = cchBuffer;
    return CLRMetaHost_GetVersionFromFile(0, szFilename, szBuffer, dwLength);
}

378 379
HRESULT WINAPI LoadLibraryShim( LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE * phModDll)
{
380 381 382 383 384 385
    HRESULT ret=S_OK;
    WCHAR dll_filename[MAX_PATH];
    WCHAR version[MAX_PATH];
    static const WCHAR default_version[] = {'v','1','.','1','.','4','3','2','2',0};
    static const WCHAR slash[] = {'\\',0};
    DWORD dummy;
386

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
    TRACE("(%p %s, %p, %p, %p)\n", szDllName, debugstr_w(szDllName), szVersion, pvReserved, phModDll);

    if (!szDllName || !phModDll)
        return E_POINTER;

    if (!get_install_root(dll_filename))
    {
        ERR("error reading registry key for installroot\n");
        dll_filename[0] = 0;
    }
    else
    {
        if (!szVersion)
        {
            ret = GetCORVersion(version, MAX_PATH, &dummy);
            if (SUCCEEDED(ret))
                szVersion = version;
            else
                szVersion = default_version;
        }
        strcatW(dll_filename, szVersion);
        strcatW(dll_filename, slash);
    }

    strcatW(dll_filename, szDllName);

    *phModDll = LoadLibraryW(dll_filename);

    return *phModDll ? S_OK : E_HANDLE;
416 417
}

418 419 420 421 422 423
HRESULT WINAPI LockClrVersion(FLockClrVersionCallback hostCallback, FLockClrVersionCallback *pBeginHostSetup, FLockClrVersionCallback *pEndHostSetup)
{
    FIXME("(%p %p %p): stub\n", hostCallback, pBeginHostSetup, pEndHostSetup);
    return S_OK;
}

424 425 426 427 428 429 430 431
HRESULT WINAPI CoInitializeCor(DWORD fFlags)
{
    FIXME("(0x%08x): stub\n", fFlags);
    return S_OK;
}

HRESULT WINAPI GetAssemblyMDImport(LPCWSTR szFileName, REFIID riid, IUnknown **ppIUnk)
{
432
    FIXME("(%p %s, %s, %p): stub\n", szFileName, debugstr_w(szFileName), debugstr_guid(riid), *ppIUnk);
433 434
    return ERROR_CALL_NOT_IMPLEMENTED;
}
435 436 437 438 439 440

HRESULT WINAPI GetVersionFromProcess(HANDLE hProcess, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwLength)
{
    FIXME("(%p, %p, %d, %p): stub\n", hProcess, pVersion, cchBuffer, dwLength);
    return E_NOTIMPL;
}
441

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
HRESULT WINAPI LoadStringRCEx(LCID culture, UINT resId, LPWSTR pBuffer, int iBufLen, int bQuiet, int* pBufLen)
{
    HRESULT res = S_OK;
    if ((iBufLen <= 0) || !pBuffer)
        return E_INVALIDARG;
    pBuffer[0] = 0;
    if (resId) {
        FIXME("(%d, %x, %p, %d, %d, %p): semi-stub\n", culture, resId, pBuffer, iBufLen, bQuiet, pBufLen);
        res = E_NOTIMPL;
    }
    else
        res = E_FAIL;
    if (pBufLen)
        *pBufLen = lstrlenW(pBuffer);
    return res;
}

HRESULT WINAPI LoadStringRC(UINT resId, LPWSTR pBuffer, int iBufLen, int bQuiet)
{
    return LoadStringRCEx(-1, resId, pBuffer, iBufLen, bQuiet, NULL);
}

464 465 466
HRESULT WINAPI CorBindToRuntimeEx(LPWSTR szVersion, LPWSTR szBuildFlavor, DWORD nflags, REFCLSID rslsid,
                                  REFIID riid, LPVOID *ppv)
{
467 468 469 470
    HRESULT ret;
    ICLRRuntimeInfo *info;

    TRACE("%s %s %d %s %s %p\n", debugstr_w(szVersion), debugstr_w(szBuildFlavor), nflags, debugstr_guid( rslsid ),
471 472
          debugstr_guid( riid ), ppv);

473 474
    *ppv = NULL;

475
    ret = get_runtime_info(NULL, szVersion, NULL, nflags, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
476 477

    if (SUCCEEDED(ret))
478
    {
479 480 481
        ret = ICLRRuntimeInfo_GetInterface(info, rslsid, riid, ppv);

        ICLRRuntimeInfo_Release(info);
482
    }
483 484

    return ret;
485 486
}

487 488 489 490 491 492
HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
    FIXME("(%s, %s, %s, %p): stub\n", debugstr_w(filename), debugstr_guid(rclsid), debugstr_guid(riid), ppv);
    return E_NOTIMPL;
}

493 494
STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject)
{
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    HRESULT ret;
    ICLRRuntimeInfo *info;
    RuntimeHost *host;
    MonoObject *obj;
    IUnknown *unk;

    TRACE("(%s,%s,%p)\n", debugstr_w(pTypeName), debugstr_guid(riid), ppObject);

    /* FIXME: How to determine which runtime version to use? */
    ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);

    if (SUCCEEDED(ret))
    {
        ret = ICLRRuntimeInfo_GetRuntimeHost(info, &host);

        ICLRRuntimeInfo_Release(info);
    }

    if (SUCCEEDED(ret))
        ret = RuntimeHost_CreateManagedInstance(host, pTypeName, NULL, &obj);

    if (SUCCEEDED(ret))
        ret = RuntimeHost_GetIUnknownForObject(host, obj, &unk);

    if (SUCCEEDED(ret))
    {
        ret = IUnknown_QueryInterface(unk, riid, ppObject);
        IUnknown_Release(unk);
    }

    return ret;
526 527
}

528 529 530 531 532 533 534 535 536 537 538 539
BOOL WINAPI StrongNameSignatureVerification(LPCWSTR filename, DWORD inFlags, DWORD* pOutFlags)
{
    FIXME("(%s, 0x%X, %p): stub\n", debugstr_w(filename), inFlags, pOutFlags);
    return FALSE;
}

BOOL WINAPI StrongNameSignatureVerificationEx(LPCWSTR filename, BOOL forceVerification, BOOL* pVerified)
{
    FIXME("(%s, %u, %p): stub\n", debugstr_w(filename), forceVerification, pVerified);
    return FALSE;
}

540 541 542 543 544 545
HRESULT WINAPI CreateConfigStream(LPCWSTR filename, IStream **stream)
{
    FIXME("(%s, %p): stub\n", debugstr_w(filename), stream);
    return E_NOTIMPL;
}

546
HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR version, IUnknown **ppv)
547
{
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
    HRESULT hr = E_FAIL;
    ICLRRuntimeInfo *runtimeinfo;

    if(nDebugVersion < 1 || nDebugVersion > 4)
        return E_INVALIDARG;

    TRACE("(%d %s, %p): stub\n", nDebugVersion, debugstr_w(version), ppv);

    if(!ppv)
        return E_INVALIDARG;

    *ppv = NULL;

    if(strcmpW(version, v2_0) != 0)
    {
        FIXME("Currently .NET Version '%s' not support.\n", debugstr_w(version));
        return E_INVALIDARG;
    }

    if(nDebugVersion != 3)
        return E_INVALIDARG;

    hr = CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)&runtimeinfo);
    if(hr == S_OK)
    {
        hr = ICLRRuntimeInfo_GetInterface(runtimeinfo, &CLSID_CLRDebuggingLegacy, &IID_ICorDebug, (void**)ppv);

        ICLRRuntimeInfo_Release(runtimeinfo);
    }

    if(!*ppv)
        return E_FAIL;

    return hr;
583 584
}

585 586
HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterface)
{
587
    TRACE("(%s,%s,%p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppInterface);
588

589 590 591 592 593 594
    if (IsEqualGUID(clsid, &CLSID_CLRMetaHost))
        return CLRMetaHost_CreateInstance(riid, ppInterface);

    FIXME("not implemented for class %s\n", debugstr_guid(clsid));

    return CLASS_E_CLASSNOTAVAILABLE;
595 596
}

597 598
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
599 600 601 602 603
    mscorecf *This;
    HRESULT hr;

    TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);

604 605 606
    if(!ppv)
        return E_INVALIDARG;

607 608 609 610 611 612 613 614 615 616 617
    This = HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf));

    This->IClassFactory_iface.lpVtbl = &mscorecf_vtbl;
    This->pfnCreateInstance = &create_monodata;
    This->ref = 1;
    This->clsid = *rclsid;

    hr = IClassFactory_QueryInterface( &This->IClassFactory_iface, riid, ppv );
    IClassFactory_Release(&This->IClassFactory_iface);

    return hr;
618 619
}

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
static void parse_msi_version_string(const char *version, int *parts)
{
    const char *minor_start, *build_start;

    parts[0] = atoi(version);

    parts[1] = parts[2] = 0;

    minor_start = strchr(version, '.');
    if (minor_start)
    {
        minor_start++;
        parts[1] = atoi(minor_start);

        build_start = strchr(minor_start, '.');
        if (build_start)
            parts[2] = atoi(build_start+1);
    }
}

static BOOL install_wine_mono(void)
{
    BOOL is_wow64=0;
    HMODULE hmsi;
    UINT (WINAPI *pMsiGetProductInfoA)(LPCSTR,LPCSTR,LPSTR,DWORD*);
    char versionstringbuf[15];
    UINT res;
    DWORD buffer_size;
    PROCESS_INFORMATION pi;
    STARTUPINFOW si;
    WCHAR app[MAX_PATH];
    WCHAR *args;
    LONG len;
    BOOL ret;

    static const char* mono_version = "0.0.4";
    static const char* mono_product_code = "{E45D8920-A758-4088-B6C6-31DBB276992E}";

    static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
    static const WCHAR argsW[] =
        {' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','m','o','n','o',0};

    IsWow64Process(GetCurrentProcess(), &is_wow64);

    if (is_wow64)
    {
        TRACE("not installing mono in wow64 process\n");
        return TRUE;
    }

    hmsi = LoadLibraryA("msi");

    if (!hmsi)
    {
        ERR("couldn't load msi.dll\n");
        return FALSE;
    }

    pMsiGetProductInfoA = (void*)GetProcAddress(hmsi, "MsiGetProductInfoA");

    buffer_size = sizeof(versionstringbuf);

    res = pMsiGetProductInfoA(mono_product_code, "VersionString", versionstringbuf, &buffer_size);

    FreeLibrary(hmsi);

    if (res == ERROR_SUCCESS)
    {
        int current_version[3], wanted_version[3], i;

        TRACE("found installed version %s\n", versionstringbuf);

        parse_msi_version_string(versionstringbuf, current_version);
        parse_msi_version_string(mono_version, wanted_version);

        for (i=0; i<3; i++)
        {
            if (current_version[i] < wanted_version[i])
                break;
            else if (current_version[i] > wanted_version[i])
            {
                TRACE("installed version is newer than %s, quitting\n", mono_version);
                return TRUE;
            }
        }

        if (i == 3)
        {
            TRACE("version %s is already installed, quitting\n", mono_version);
            return TRUE;
        }
    }

    len = GetSystemDirectoryW(app, MAX_PATH-sizeof(controlW)/sizeof(WCHAR));
    memcpy(app+len, controlW, sizeof(controlW));

    args = HeapAlloc(GetProcessHeap(), 0, (len*sizeof(WCHAR) + sizeof(controlW) + sizeof(argsW)));
    if(!args)
        return FALSE;

    memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW));
    memcpy(args + len + sizeof(controlW)/sizeof(WCHAR)-1, argsW, sizeof(argsW));

    TRACE("starting %s\n", debugstr_w(args));

    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    HeapFree(GetProcessHeap(), 0, args);
    if (ret) {
        CloseHandle(pi.hThread);
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hProcess);
    }

    return ret;
}

738 739
HRESULT WINAPI DllRegisterServer(void)
{
740 741
    install_wine_mono();

742
    return __wine_register_resources( MSCOREE_hInstance );
743 744 745 746
}

HRESULT WINAPI DllUnregisterServer(void)
{
747
    return __wine_unregister_resources( MSCOREE_hInstance );
748 749
}

750 751
HRESULT WINAPI DllCanUnloadNow(VOID)
{
752
    return S_FALSE;
753
}
754

755 756 757 758 759
void WINAPI CoEEShutDownCOM(void)
{
    FIXME("stub.\n");
}

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
INT WINAPI ND_RU1( const void *ptr, INT offset )
{
    return *((const BYTE *)ptr + offset);
}

INT WINAPI ND_RI2( const void *ptr, INT offset )
{
    return *(const SHORT *)((const BYTE *)ptr + offset);
}

INT WINAPI ND_RI4( const void *ptr, INT offset )
{
    return *(const INT *)((const BYTE *)ptr + offset);
}

INT64 WINAPI ND_RI8( const void *ptr, INT offset )
{
    return *(const INT64 *)((const BYTE *)ptr + offset);
}

void WINAPI ND_WU1( void *ptr, INT offset, BYTE val )
{
    *((BYTE *)ptr + offset) = val;
}

void WINAPI ND_WI2( void *ptr, INT offset, SHORT val )
{
    *(SHORT *)((BYTE *)ptr + offset) = val;
}

void WINAPI ND_WI4( void *ptr, INT offset, INT val )
{
    *(INT *)((BYTE *)ptr + offset) = val;
}

void WINAPI ND_WI8( void *ptr, INT offset, INT64 val )
{
    *(INT64 *)((BYTE *)ptr + offset) = val;
}

void WINAPI ND_CopyObjDst( const void *src, void *dst, INT offset, INT size )
{
    memcpy( (BYTE *)dst + offset, src, size );
}

void WINAPI ND_CopyObjSrc( const void *src, INT offset, void *dst, INT size )
{
    memcpy( dst, (const BYTE *)src + offset, size );
}