Esempio n. 1
0
File: link.c Progetto: GYGit/reactos
static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
        IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
{
    HlinkImpl  *This = impl_from_IHlink(iface);
    IMoniker *mon = NULL;
    HRESULT r;

    FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);

    r = __GetMoniker(This, &mon, HLINKGETREF_ABSOLUTE);
    TRACE("Moniker %p\n", mon);

    if (SUCCEEDED(r))
    {
        IBindCtx *bcxt;
        IUnknown *unk = NULL;
        IHlinkTarget *target;

        CreateBindCtx(0, &bcxt);

        RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);

        r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IUnknown, (void**)&unk);
        if (r == S_OK)
        {
            r = IUnknown_QueryInterface(unk, &IID_IHlinkTarget, (void**)&target);
            IUnknown_Release(unk);
        }
        if (r == S_OK)
        {
            IHlinkTarget_SetBrowseContext(target, phbc);
            r = IHlinkTarget_Navigate(target, grfHLNF, This->Location);
            IHlinkTarget_Release(target);
        }
        else
        {
            static const WCHAR szOpen[] = {'o','p','e','n',0};
            LPWSTR target = NULL;

            r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
            if (SUCCEEDED(r) && target)
            {
                ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
                CoTaskMemFree(target);
            }
        }

        RevokeBindStatusCallback(bcxt, pbsc);

        IBindCtx_Release(bcxt);
        IMoniker_Release(mon);
    }

    if (This->Site)
        IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, r, NULL);

    TRACE("Finished Navigation\n");
    return r;
}
// Create the specified control, optionally providing properties to initialise
// it with and a name.
HRESULT CControlSite::Create(REFCLSID clsid, PropertyList &pl,
    LPCWSTR szCodebase, IBindCtx *pBindContext)
{
    TRACE_METHOD(CControlSite::Create);

    m_CLSID = clsid;
    m_ParameterList = pl;

    // See if security policy will allow the control to be hosted
    if (m_pSecurityPolicy && !m_pSecurityPolicy->IsClassSafeToHost(clsid))
    {
        return E_FAIL;
    }

    // See if object is script safe
    BOOL checkForObjectSafety = FALSE;
    if (m_pSecurityPolicy && m_bSafeForScriptingObjectsOnly)
    {
        BOOL bClassExists = FALSE;
        BOOL bIsSafe = m_pSecurityPolicy->IsClassMarkedSafeForScripting(clsid, bClassExists);
        if (!bClassExists && szCodebase)
        {
            // Class doesn't exist, so allow code below to fetch it
        }
        else if (!bIsSafe)
        {
            // The class is not flagged as safe for scripting, so
            // we'll have to create it to ask it if its safe.
            checkForObjectSafety = TRUE;
        }
    }

    // Create the object
    CComPtr<IUnknown> spObject;
    HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void **) &spObject);
    if (SUCCEEDED(hr) && checkForObjectSafety)
    {
        // Assume scripting via IDispatch
        if (!m_pSecurityPolicy->IsObjectSafeForScripting(spObject, __uuidof(IDispatch)))
        {
            return E_FAIL;
        }
        // Drop through, success!
    }

    // Do we need to download the control?
    if (FAILED(hr) && szCodebase)
    {
        wchar_t *szURL = NULL;

        // Test if the code base ends in #version=a,b,c,d
        DWORD dwFileVersionMS = 0xffffffff;
        DWORD dwFileVersionLS = 0xffffffff;
        const wchar_t *szHash = wcsrchr(szCodebase, wchar_t('#'));
        if (szHash)
        {
            if (wcsnicmp(szHash, L"#version=", 9) == 0)
            {
                int a, b, c, d;
                if (swscanf(szHash + 9, L"%d,%d,%d,%d", &a, &b, &c, &d) == 4)
                {
                    dwFileVersionMS = MAKELONG(b,a);
                    dwFileVersionLS = MAKELONG(d,c);
                }
            }
            szURL = _wcsdup(szCodebase);
            // Terminate at the hash mark
            if (szURL)
                szURL[szHash - szCodebase] = wchar_t('\0');
        }
        else
        {
            szURL = _wcsdup(szCodebase);
        }
        if (!szURL)
            return E_OUTOFMEMORY;

        CComPtr<IBindCtx> spBindContext; 
        CComPtr<IBindStatusCallback> spBindStatusCallback;
        CComPtr<IBindStatusCallback> spOldBSC;

        // Create our own bind context or use the one provided?
        BOOL useInternalBSC = FALSE;
        if (!pBindContext)
        {
            useInternalBSC = TRUE;
            hr = CreateBindCtx(0, &spBindContext);
            if (FAILED(hr))
            {
                free(szURL);
                return hr;
            }
            spBindStatusCallback = dynamic_cast<IBindStatusCallback *>(this);
            hr = RegisterBindStatusCallback(spBindContext, spBindStatusCallback, &spOldBSC, 0);
            if (FAILED(hr))
            {
                free(szURL);
                return hr;
            }
        }
        else
        {
            spBindContext = pBindContext;
        }

        hr = CoGetClassObjectFromURL(clsid, szURL, dwFileVersionMS, dwFileVersionLS,
            NULL, spBindContext, CLSCTX_ALL, NULL, IID_IUnknown, (void **) &m_spObject);
        
        free(szURL);
        
        // Handle the internal binding synchronously so the object exists
        // or an error code is available when the method returns.
        if (useInternalBSC)
        {
            if (MK_S_ASYNCHRONOUS == hr)
            {
                m_bBindingInProgress = TRUE;
                m_hrBindResult = E_FAIL;

                // Spin around waiting for binding to complete
                HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
                while (m_bBindingInProgress)
                {
                    MSG msg;
                    // Process pending messages
                    while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
                    {
                        if (!::GetMessage(&msg, NULL, 0, 0))
                        {
                            m_bBindingInProgress = FALSE;
                            break;
                        }
                        ::TranslateMessage(&msg);
                        ::DispatchMessage(&msg);
                    }
                    if (!m_bBindingInProgress)
                        break;
                    // Sleep for a bit or the next msg to appear
                    ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
                }
                ::CloseHandle(hFakeEvent);

                // Set the result
                hr = m_hrBindResult;
            }

            // Destroy the bind status callback & context
            if (spBindStatusCallback)
            {
                RevokeBindStatusCallback(spBindContext, spBindStatusCallback);
                spBindContext.Release();
            }
        }
    }

    if (spObject)
        m_spObject = spObject;

    return hr;
}