226 lines
5.9 KiB
C++
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;
|
|
}
|