NT4/private/ole32/com/inc/guidmap.cxx
2020-09-30 17:12:29 +02:00

226 lines
5.9 KiB
C++

//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1993.
//
// File: guidmap.cxx
//
// Contents: IID to proxy/stub CLSID mapping cache
//
// Classes: CScmGuidMap - shared memory guid map
//
// Functions:
//
// History: 07-Apr-94 Rickhi Created
//
// Notes: this class maintains an IID to CLSID mapping table
// in shared memory.
//
//----------------------------------------------------------------------------
#include <ole2int.h>
#include <guidmap.hxx>
//+-------------------------------------------------------------------------
//
// Member: CScmGuidMap::FreeSpace
//
// Synopsis: returns the amount of free space left in the table
//
// Returns: see Synopsis.
//
// Algorithm: computes the freespace by multiplying the number of each type
// of entry with the size of that type of entry, summing them,
// and subtracting the total from the map size.
//
//--------------------------------------------------------------------------
ULONG CScmGuidMap::FreeSpace()
{
ULONG ulUsed =
(_pGuidMap->ulCntShort + _pGuidMap->ulCntShortOverFlow) *sizeof(DWORDPAIR)+
(_pGuidMap->ulCntLong + _pGuidMap->ulCntLongOverFlow) *sizeof(GUIDPAIR);
return (IIDMAP_SIZE - sizeof(GUIDMAP) - ulUsed);
}
//+-------------------------------------------------------------------------
//
// Member: CScmGuidMap::SearchShortList
//
// Synopsis: searches the short list for a matching entry and returns
// a pointer to the found element, or NULL.
//
// Arguments: [dwFind] - the first dword of the GUID we want to find
//
// Returns: ptr to matching entry if found, NULL otherwise.
//
// Algorithm: does a binary search on the part of the short list that
// is sorted. If still not found, it does a linear search
// on the unsorted part of the short list.
//
//--------------------------------------------------------------------------
DWORDPAIR *CScmGuidMap::SearchShortList(DWORD dwFind)
{
// we do a binary search in the short list because we know
// they are in numerical order.
LONG lLow = 0;
LONG lHigh = _pGuidMap->ulCntShort;
while (lLow <= lHigh)
{
LONG lGuess = (lLow + lHigh) / 2;
DWORDPAIR *pCurr = _pShortList + lGuess;
if (pCurr->dw1 == dwFind)
{
return pCurr;
}
else if (pCurr->dw1 < dwFind)
{
lLow = lGuess + 1;
}
else
{
lHigh = lGuess - 1;
}
}
// not found, look in the overflow area. This is where new guids
// are added when the registry is updated while the SCM is running
DWORDPAIR *pCurr = _pShortList + _pGuidMap->ulCntShort;
DWORDPAIR *pEnd = pCurr + _pGuidMap->ulCntShortOverFlow;
while (pCurr < pEnd)
{
if (pCurr->dw1 == dwFind)
{
return pCurr;
}
pCurr++;
}
return NULL;
}
//+-------------------------------------------------------------------------
//
// Member: CScmGuidMap::SearchLongList
//
// Synopsis: searches the long list for a matching entry and returns
// a pointer to the found element, or NULL.
//
// Arguments: [rguid] - the GUID we want to find
//
// Returns: ptr to matching entry if found, NULL otherwise.
//
// Algorithm: does a binary search on the part of the long list that
// is sorted. If still not found, it does a linear search
// on the unsorted part of the long list.
//
//--------------------------------------------------------------------------
GUIDPAIR *CScmGuidMap::SearchLongList(REFGUID rguid)
{
// we do a binary search in the long list because we know
// they are in reversed numerical order.
LONG lLow = 0;
LONG lHigh = _pGuidMap->ulCntLong;
while (lLow <= lHigh)
{
LONG lGuess = (lLow + lHigh) / 2;
GUIDPAIR *pCurr = _pLongList - lGuess;
int iRes = memcmp(&pCurr->guid1, &rguid, sizeof(GUID));
if (iRes == 0)
{
return pCurr;
}
else if (iRes < 0)
{
lLow = lGuess + 1;
}
else
{
lHigh = lGuess - 1;
}
}
// not found, look in the overflow area. This is where new guids
// are added when the registry is updated while the SCM is running
GUIDPAIR *pCurr = _pLongList - _pGuidMap->ulCntLong;
GUIDPAIR *pEnd = pCurr - _pGuidMap->ulCntLongOverFlow;
while (pCurr > pEnd)
{
if (memcmp(&pCurr->guid1, &rguid, sizeof(GUID)))
{
return pCurr;
}
pCurr--;
}
return NULL;
}
//+-------------------------------------------------------------------------
//
// Member: CScmGuidMap::Find
//
// Synopsis: Searches the map for a matching guid and copies the
// mapped to value into pGuidOut.
//
// Arguments: [rguid] - the guid to find.
// [pGuidOut] - place to store the resulting guid
//
// Returns: ptr to guid if found, NULL otherwise.
//
// Algorithm: If the guid is an OLE201 style guid, we scan the short
// table first, otherwise we skip to the long table. If it
// is not found in the short table, we scan the long table
// anyway, since the second guid may not be Ole2 style.
//
//--------------------------------------------------------------------------
GUID *CScmGuidMap::Find(REFGUID rguid, GUID *pGuidOut)
{
if (_pGuidMap)
{
if (IsOleStyleGuid(rguid))
{
// look in the short list. here we store just the first DWORD
// because we know what the other 3 dwords look like.
DWORDPAIR *pEntry = SearchShortList(rguid.Data1);
if (pEntry)
{
// found it, fill the guid to return
memcpy(pGuidOut, &guidOleTemplate, sizeof(GUID));
pGuidOut->Data1 = pEntry->dw2;
return pGuidOut;
}
}
// either the first guid is not OLE201 style, or we did not
// find a match in the short table. Scan the long table.
// have to look in the long list. here we store the entire
// guids because they dont look like Ole Style guids.
GUIDPAIR *pEntry = SearchLongList(rguid);
if (pEntry)
{
memcpy(pGuidOut, &pEntry->guid2, sizeof(GUID));
return pGuidOut;
}
}
return NULL;
}