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