//+---------------------------------------------------------------------------//+--------------------------------------------------------------------------- // // 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 #include //+------------------------------------------------------------------------- // // 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; }