#include "pch.h"
#include "..\Inc\TCLib.h"
#include "AutoHandle.h"
#include "UtilImpl.h"
WINOLEAPI CreateObjrefMoniker(LPUNKNOWN pUnk, LPMONIKER* ppMk);
STDMETHODIMP TCUtilImpl::CreateObject(BSTR bstrProgID, BSTR bstrComputer,
IUnknown** ppUnk)
{
CLEAROUT(ppUnk, (IUnknown*)NULL);
CLSID clsid;
if (!BSTRLen(bstrProgID))
return E_INVALIDARG;
RETURN_FAILED(CLSIDFromProgID(bstrProgID, &clsid));
COSERVERINFO csi = {0, bstrComputer, NULL, 0};
MULTI_QI mqi[] =
{
{&IID_IUnknown , NULL, S_OK},
{&IID_IDispatch , NULL, S_OK},
{&IID_IConnectionPointContainer, NULL, S_OK},
};
const static ULONG cMQI = sizeofArray(mqi);
bool bLocalForSure = true;
if (BSTRLen(bstrComputer))
{
TCHAR szLocal[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cchLocal = sizeofArray(szLocal);
GetComputerName(szLocal, &cchLocal);
USES_CONVERSION;
bLocalForSure = !_tcsicmp(szLocal, OLE2CT(bstrComputer));
}
DWORD dwClsCtx = bLocalForSure ? CLSCTX_SERVER : CLSCTX_REMOTE_SERVER;
HRESULT hr = CoCreateInstanceEx(clsid, NULL, dwClsCtx, &csi, cMQI, mqi);
if (FAILED(hr))
{
_TRACE_BEGIN
_TRACE_PART1("TCCreateObject failed: hr=0x%08X", hr);
_TRACE_PART1(", dwClsCtx=%hs", (CLSCTX_SERVER == dwClsCtx) ?
"CLSCTX_SERVER" : "CLSCTX_REMOTE_SERVER");
_TRACE_PART1(", ProgID=\"%ls\"", bstrProgID);
_TRACE_PART1(", Computer= \"%ls\"\n", bstrComputer ?
bstrComputer : L"");
_TRACE_END
return hr;
}
*ppUnk = mqi[0].pItf;
for (ULONG i = 1; i < cMQI; ++i)
if (mqi[i].pItf)
mqi[i].pItf->Release();
return mqi[0].hr;
}
STDMETHODIMP TCUtilImpl::ObjectReference(IUnknown* pUnk,
BSTR* pbstrObjectReference)
{
CLEAROUT(pbstrObjectReference, (BSTR)NULL);
IMonikerPtr spMoniker;
RETURN_FAILED(CreateObjrefMoniker(pUnk, &spMoniker));
IBindCtxPtr spbc;
RETURN_FAILED(CreateBindCtx(0, &spbc));
TCCoTaskPtr<LPOLESTR> spszDisplayName;
RETURN_FAILED(spMoniker->GetDisplayName(spbc, NULL, &spszDisplayName));
*pbstrObjectReference = SysAllocString(spszDisplayName);
return *pbstrObjectReference ? S_OK : E_OUTOFMEMORY;
}
STDMETHODIMP TCUtilImpl::Sleep(long nDurationMS)
{
const long lTimerGranularity = 1000;
double StartTickCount;
double CurTickCount;
double EndTickCount;
DWORD CurWaitTime;
MSG msg;
if (nDurationMS < 0)
return E_INVALIDARG;
StartTickCount = ::GetTickCount();
EndTickCount = StartTickCount + nDurationMS;
CurTickCount = StartTickCount;
while(CurTickCount < EndTickCount)
{
CurWaitTime = (DWORD)(EndTickCount - CurTickCount);
if (CurWaitTime > lTimerGranularity)
CurWaitTime = lTimerGranularity;
DWORD dwWait = ::MsgWaitForMultipleObjects(0, NULL, TRUE, CurWaitTime, QS_ALLINPUT);
if (WAIT_TIMEOUT != dwWait && ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
CurTickCount = ::GetTickCount();
if (CurTickCount < StartTickCount)
{
CurTickCount += (DWORD)(0xFFFFFFFF);
}
}
return NOERROR;
}
STDMETHODIMP TCUtilImpl::GetObject(BSTR bstrMoniker, VARIANT_BOOL bAllowUI,
long nTimeoutMS, IUnknown** ppUnk)
{
BIND_OPTS bo;
bo.cbStruct = sizeof(bo);
bo.grfFlags = bAllowUI ? BIND_MAYBOTHERUSER : 0;
bo.grfMode = STGM_READWRITE;
if (-1 == nTimeoutMS)
bo.dwTickCountDeadline = 0;
else
{
bo.dwTickCountDeadline = GetTickCount() + nTimeoutMS;
if (0 == bo.dwTickCountDeadline)
++bo.dwTickCountDeadline;
}
return CoGetObject(bstrMoniker, &bo, IID_IUnknown, (void**)ppUnk);
}