📄 unkhook.cpp
字号:
return DoMapIID((IID*)iid);
}
STDMETHODIMP
CUnkHookAggregate::get_Flags(UnkHookFlags* puhFlags)
{
*puhFlags = GetFlags();
return NOERROR;
}
STDMETHODIMP
CUnkHookAggregate::put_Flags(UnkHookFlags uhFlags)
{
// This is not allowed externally when an UnknownHook is
// created by an AggregateUnknown call.
return CTL_E_SETNOTSUPPORTED; // Facility control, error 383
}
CAggregator::PreAllocData::PreAllocData(AggregateData* pAggData, ULONG cAggElems, ULONG cIIDElems, HRESULT& hrLaunch)
{
ULONG i; // Loop counter
AggregateData* pCurData; // Current aggdata for loop
ULONG cElems; // A local for counting elements
ZeroMemory(this, sizeof(*this));
// Initialize launch as successful
hrLaunch = NOERROR;
// Make a pass to get the required IID count
i = cAggElems;
pCurData = pAggData;
while (i--)
{
ADFlags& Flags = pCurData->Flags;
// If we have an object, then we always count the entry
if (pCurData->pObject &&
(0 == (Flags & adDontQuery)))
{
// Do some flag validation. You can't specify both of these.
if ((Flags & (adWeakRefRaw | adWeakRefBalanced)) == (adWeakRefRaw | adWeakRefBalanced))
{
hrLaunch = E_INVALIDARG;
return;
}
if ((Flags & adPrimaryDispatch) &&
!fHaveDispHook)
{
cIIDs++;
fHaveDispHook = true;
}
if (Flags & adUseIIDs)
{
// Ignore LastIID if Last < First
cElems = (pCurData->LastIID <= pCurData->FirstIID) ?
1 : pCurData->LastIID - pCurData->FirstIID + 1;
if (((Flags & adFullyResolved) && cElems != 1) ||
((cElems + (ULONG)pCurData->FirstIID) > cIIDElems))
{
hrLaunch = DISP_E_BADINDEX;
return;
}
cIIDs += cElems;
}
else
{
// Can't delay create without adUseIIDs
if (Flags & adDelayCreation)
{
hrLaunch = E_INVALIDARG;
return;
}
cUnfiltered++;
if (Flags & adBeforeHookedUnknown)
{
cUnfilteredBefore++;
}
if (Flags & adNoDelegator)
{
cUnfilteredNoDelegator++;
}
}
}
// If we don't have an object, then this is an attempt to
// change the primary dispatch to something other than the primary object.
else if (pCurData->pObject == NULL &&
((Flags & (adPrimaryDispatch | adUseIIDs)) == (adPrimaryDispatch | adUseIIDs)) &&
!fHaveDispHook)
{
// We only use the first IID
if ((ULONG)pCurData->FirstIID >= cIIDElems)
{
hrLaunch = DISP_E_BADINDEX;
return;
}
cIIDs++;
fHaveDispHook = true;
}
else if (Flags & adMapIID)
{
if ((ULONG)pCurData->FirstIID >= cIIDElems ||
(ULONG)pCurData->LastIID >= cIIDElems)
{
hrLaunch = DISP_E_BADINDEX;
return;
}
cIIDMaps++;
cIIDMapAndBlockElems++;
}
else if (Flags & adBlockIIDs)
{
// Ignore LastIID if Last < First
cElems = (pCurData->LastIID <= pCurData->FirstIID) ?
1 : pCurData->LastIID - pCurData->FirstIID + 1;
if ((cElems + (ULONG)pCurData->FirstIID) > cIIDElems)
{
hrLaunch = DISP_E_BADINDEX;
return;
}
cIIDBlocks += cElems;
cIIDMapAndBlockElems++;
}
pCurData++;
}
// Figure out bytes count for the Unknown elements, as well as the
// IID maps. These are all of the items in CAggregator that are
// created with the object instead of the FSMM.
cExtraBytes = (cAggElems - cIIDMapAndBlockElems) * sizeof(CAggregator::CHoldUnk)
+ cIIDMaps * sizeof(CAggregator::IIDMapEntry)
+ cIIDBlocks * sizeof(IID);
}
CAggregator::CAggregator(AggregateData* pAggData, ULONG cAggElems, IID* pIIDs, PreAllocData& rPAD, HRESULT& hrLaunch, IUnknown* punkControlling)
// Put anything here that would cause a problem
// in the destructor if it weren't initialized.
: m_pUnks(NULL),
m_pIIDMaps(NULL),
m_pBlockIIDs(NULL),
m_pFSMMNodes(NULL)
{
ULONG i; // Loop counter
AggregateData* pCurData; // Current aggdata for loop
ULONG cElems; // A local for counting elements
ULONG cFiltered; // The number of encountered filtered objects. Order in these doesn't matter, so they're tossed at the end.
ULONG iCurEntry; // The location in the m_pUnks array where the current element is stored
IIDHookNode* pCurNode; // The node currently being worked on.
IID* pCurIID; // A loop iterator for items in the IID array
IIDMapEntry* pCurMap; // The current position in the m_pIIDMaps array
IID* pCurBlockIID; // The current position in the m_pBlockIIDs array
// Initialize launch as successful
hrLaunch = NOERROR;
m_cIIDMaps = rPAD.cIIDMaps;
m_cBlockIIDs = rPAD.cIIDBlocks;
m_cUnks = cAggElems - rPAD.cIIDMapAndBlockElems;
// Start allocating our memory
cElems = rPAD.cIIDs;
if (i = rPAD.cUnfiltered - rPAD.cUnfilteredNoDelegator)
{
cElems += 2 * i;
if (cElems < 4) cElems = 4;
}
if (cElems)
{
if (FAILED(hrLaunch = CFixedMemMgr::CreateInstance(sizeof(IIDHookNode),
// Try to alloc enough to get us through this routine up front,
// plus two slots for each unfiltered item. If this succeeds, then
// we don't have to worry about FSMM->Alloc calls failing in this routine.
cElems,
&m_pFSMMNodes)))
{
return;
}
}
if (rPAD.cExtraBytes)
{
// Zeroing is sufficient. CHoldUnk and IIDMapNode
// both need to be zero initialized.
ZeroMemory(rPAD.pExtraBytes, rPAD.cExtraBytes);
}
if (m_cUnks)
{
//Change this block of code if CHoldUnk's constructor changes
//CHoldUnk* pHoldUnk; // A loop iterator for CHoldUnk items
m_pUnks = (CHoldUnk*)rPAD.pExtraBytes;
//i = m_cUnks;
//pHoldUnk = m_pUnks;
//while (i--)
//{
// new ((void*)pHoldUnk) CHoldUnk;
// pHoldUnk++;
//}
rPAD.pExtraBytes = (BYTE*)rPAD.pExtraBytes + m_cUnks * sizeof(CHoldUnk);
}
if (m_cIIDMaps)
{
// These are sufficiently constructed with the ZeroMemory on
// the extra bytes
pCurMap = m_pIIDMaps = (IIDMapEntry*)rPAD.pExtraBytes;
rPAD.pExtraBytes = (BYTE*)rPAD.pExtraBytes + m_cIIDMaps * sizeof(IIDMapEntry);
}
if (m_cBlockIIDs)
{
pCurBlockIID = m_pBlockIIDs = (IID*)rPAD.pExtraBytes;
}
m_cUnfilteredBefore = m_cUnfilteredAfter = 0;
// Now, actually fill the arrays
i = cAggElems;
pCurData = pAggData;
cFiltered = 0;
while (i--)
{
ADFlags& Flags = pCurData->Flags;
if (pCurData->pObject)
{
if (Flags & adDontQuery)
{
// Just toss it near the end of the list. This entry won't be referenced by
// any IIDData, so it doesn't hurt anything.
m_pUnks[m_cUnks - cFiltered - 1] = pCurData->pObject;
cFiltered++;
}
else
{
if (Flags & adUseIIDs)
{
// We have a filtered item (it gets sent only predefined IIDs)
// Find out how many IIDs we have.
// Ignore LastIID if Last < First
cElems = (pCurData->LastIID <= pCurData->FirstIID) ?
1 : pCurData->LastIID - pCurData->FirstIID + 1;
// We just throw this anywhere at the end of the array.
iCurEntry = m_cUnks - cFiltered - 1;
cFiltered++;
pCurIID = &pIIDs[pCurData->FirstIID];
IIDHookNodeList& rNodeList = (Flags & adBeforeHookedUnknown) ? m_BeforeNodes : m_AfterNodes;
while (cElems--)
{
// FSMM allocates the first chunk with the object,
// so this can't fail.
m_pFSMMNodes->Alloc((long*)&pCurNode);
pCurNode->iid = *pCurIID;
pCurNode->iUnk = (short)iCurEntry;
rNodeList.AddTail(pCurNode);
pCurIID++;
}
// The delayed creation flag is ignored if no IID's are specified, so
// we must check it in here.
if (Flags & adDelayCreation)
{
// If we're delaying creation, then there's some
// more work to do.
IDelayCreation* pDelay;
IUnknown* pTest = NULL;
HRESULT hr;
if (SUCCEEDED(hr = pCurData->pObject->QueryInterface(IID_IDelayCreation, (void**)&pDelay)))
{
m_pUnks[iCurEntry] = pDelay;
if (punkControlling &&
SUCCEEDED(hr = pDelay->QueryInterface(IID_IUnknown, (void**)&pTest)))
{
if (pTest == punkControlling)
{
m_pUnks[iCurEntry].SetWeakRef();
// Keep the reference on pDelay and release
// a reference on the controlling IUnknown to
// stay balanced.
pTest->Release();
}
pTest->Release();
}
m_pUnks[iCurEntry].SetDelayedCreation();
if ((Flags & adDelayDontCacheResolved) == adDelayDontCacheResolved) // Two bit flag, need ==
{
m_pUnks[iCurEntry].SetKeepDelayed();
}
pDelay->Release();
if (Flags & adWeakRefBalanced)
{
m_pUnks[iCurEntry].SetExplicitWeakRef();
}
else if (Flags & adWeakRefRaw)
{
m_pUnks[iCurEntry].SetRawWeakRef();
}
}
if (FAILED(hr))
{
hrLaunch = DISP_E_TYPEMISMATCH;
return;
}
}
// Flag if we're fully resolved. This applies to items that
// are delay created as well as items with a single IID.
if (Flags & adFullyResolved)
{
m_pUnks[iCurEntry].SetFullyResolved();
}
}
else
{
// This is an unfiltered item (it gets blindly sent IIDs)
if (Flags & adBeforeHookedUnknown)
{
iCurEntry = m_cUnfilteredBefore;
m_cUnfilteredBefore++;
}
else
{
iCurEntry = rPAD.cUnfilteredBefore + m_cUnfilteredAfter;
m_cUnfilteredAfter++;
}
}
// Share object assignment code for both filtered and blind cases.
if (0 == (Flags & adDelayCreation))
{
CHoldUnk& rHoldUnk = m_pUnks[iCurEntry];
if (Flags & adWeakRefRaw)
{
rHoldUnk.AssignRawWeakRef(pCurData->pObject);
}
else
{
rHoldUnk = pCurData->pObject;
if (Flags & adWeakRefBalanced)
{
IUnknown* punkControl = NULL;
pCurData->pObject->QueryInterface(IID_IUnknown, (void**)&punkControl);
if (punkControl)
{
punkControl->Release();
punkControl->Release();
rHoldUnk.SetWeakRef();
}
}
}
}
// See if the blind delegation has been
// explicitly turned off.
if (Flags & adNoDelegator)
{
m_pUnks[iCurEntry].SetNoDelegator();
}
// If we found a primary dispatch request
// during the initial pass and we haven't found
// one yet, then deal with it the same as a
// before request. An IDispatch can come on
// a filtered or unfiltered object, and always
// comes before.
if (rPAD.fHaveDispHook &&
(Flags & adPrimaryDispatch))
{
m_pFSMMNodes->Alloc((long*)&pCurNode);
pCurNode->iid = IID_IDispatch;
pCurNode->iUnk = (short)iCurEntry;
m_BeforeNodes.AddTail(pCurNode);
rPAD.fHaveDispHook = false;
}
}
}
else if (rPAD.fHaveDispHook &&
((Flags & (adPrimaryDispatch | adUseIIDs)) == (adPrimaryDispatch | adUseIIDs)))
{
// This is a special case. We're remapping the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -