#include "stock.h" #pragma hdrstop STDAPI BindCtx_CreateWithMode(DWORD grfMode, IBindCtx **ppbc) { ASSERTMSG(ppbc != NULL, "Caller must pass valid ppbc"); HRESULT hr = CreateBindCtx(0, ppbc); if (SUCCEEDED(hr)) { BIND_OPTS bo = {sizeof(bo), 0, grfMode, 0}; hr = (*ppbc)->SetBindOptions(&bo); if (FAILED(hr)) { ATOMICRELEASE(*ppbc); } } ASSERT(SUCCEEDED(hr) ? (*ppbc != NULL) : (*ppbc == NULL)); return hr; } STDAPI_(DWORD) BindCtx_GetMode(IBindCtx *pbc, DWORD grfModeDefault) { if (pbc) { BIND_OPTS bo = {sizeof(bo)}; // Requires size filled in. if (SUCCEEDED(pbc->GetBindOptions(&bo))) grfModeDefault = bo.grfMode; } return grfModeDefault; } STDAPI_(BOOL) BindCtx_ContainsObject(IBindCtx *pbc, LPOLESTR psz) { BOOL bResult = FALSE; IUnknown *punk; if (pbc && SUCCEEDED(pbc->GetObjectParam(psz, &punk))) { bResult = TRUE; punk->Release(); } return bResult; } class CDummyUnknown : public IOleWindow { public: CDummyUnknown() : _cRef(1), _hwnd(NULL) {} CDummyUnknown(HWND hwnd) : _cRef(1), _hwnd(hwnd) {} // IUnknown refcounting STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CDummyUnknown, IOleWindow ), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) AddRef(void) { return ++_cRef; } STDMETHODIMP_(ULONG) Release(void) { if (--_cRef > 0) return _cRef; delete this; return 0; } // IOleWindow STDMETHODIMP GetWindow(HWND * lphwnd) { *lphwnd = _hwnd; return _hwnd ? S_OK : E_NOTIMPL; } STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; } protected: LONG _cRef; HWND _hwnd; }; STDAPI BindCtx_RegisterObjectParam(IBindCtx *pbcIn, LPCOLESTR pszRegister, IUnknown *punkRegister, IBindCtx **ppbcOut) { HRESULT hr = S_OK; *ppbcOut = pbcIn; if (pbcIn) pbcIn->AddRef(); else hr = CreateBindCtx(0, ppbcOut); if (SUCCEEDED(hr)) { IUnknown *punkDummy = NULL; if (!punkRegister) { punkRegister = punkDummy = new CDummyUnknown(); hr = punkDummy ? S_OK : E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { hr = (*ppbcOut)->RegisterObjectParam((LPOLESTR)pszRegister, punkRegister); if (punkDummy) punkDummy->Release(); } if (FAILED(hr)) ATOMICRELEASE(*ppbcOut); } return hr; } STDAPI BindCtx_RegisterObjectParams(IBindCtx *pbcIn, BINDCTX_PARAM *rgParams, UINT cParams, IBindCtx **ppbcOut) { HRESULT hr = S_FALSE; // require at least one param ASSERT(cParams); *ppbcOut = 0; for (UINT i = 0; SUCCEEDED(hr) && i < cParams; i++) { // returns the in param if NON-NULL hr = BindCtx_RegisterObjectParam(pbcIn, rgParams[i].pszName, rgParams[i].pbcParam, &pbcIn); // we only keep the first addref() // and we return it if (SUCCEEDED(hr)) { if (i == 0) *ppbcOut = pbcIn; else pbcIn->Release(); } } if (FAILED(hr)) { ATOMICRELEASE(*ppbcOut); } return hr; } STDAPI BindCtx_RegisterUIWindow(IBindCtx *pbcIn, HWND hwnd, IBindCtx **ppbcOut) { IUnknown *punkDummy = new CDummyUnknown(hwnd); HRESULT hr = punkDummy ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hr)) { hr = BindCtx_RegisterObjectParam(pbcIn, STR_DISPLAY_UI_DURING_BINDING, punkDummy, ppbcOut); punkDummy->Release(); } else { *ppbcOut = 0; } return hr; } STDAPI_(HWND) BindCtx_GetUIWindow(IBindCtx *pbc) { HWND hwnd = NULL; IUnknown *punk; if (pbc && SUCCEEDED(pbc->GetObjectParam(STR_DISPLAY_UI_DURING_BINDING, &punk))) { IUnknown_GetWindow(punk, &hwnd); punk->Release(); } return hwnd; } // dwTicksToAllow is time in msec relative to "now" STDAPI BindCtx_CreateWithTimeoutDelta(DWORD dwTicksToAllow, IBindCtx **ppbc) { HRESULT hr = CreateBindCtx(0, ppbc); if (SUCCEEDED(hr)) { DWORD dwDeadline = GetTickCount() + dwTicksToAllow; if (0 == dwDeadline) dwDeadline = 1; BIND_OPTS bo = {sizeof(bo), 0, 0, dwDeadline}; hr = (*ppbc)->SetBindOptions(&bo); if (FAILED(hr)) { ATOMICRELEASE(*ppbc); } } ASSERT(SUCCEEDED(hr) ? (*ppbc != NULL) : (*ppbc == NULL)); return hr; } // returns # of msec relative to "now" to allow the operation to take STDAPI BindCtx_GetTimeoutDelta(IBindCtx *pbc, DWORD *pdwTicksToAllow) { *pdwTicksToAllow = 0; HRESULT hr = E_FAIL; if (pbc) { BIND_OPTS bo = {sizeof(bo)}; // Requires size filled in. if (SUCCEEDED(pbc->GetBindOptions(&bo))) { if (bo.dwTickCountDeadline) { DWORD dwNow = GetTickCount(); if (dwNow > bo.dwTickCountDeadline) { *pdwTicksToAllow = 0; // we have already elappsed the timeout, return 0 } else { *pdwTicksToAllow = bo.dwTickCountDeadline - dwNow; // positive delta in the future } hr = S_OK; } } } return hr; }