231 lines
5.5 KiB
C++
231 lines
5.5 KiB
C++
|
#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;
|
||
|
}
|
||
|
|
||
|
|