NT4/private/ole32/com/inc/psctbl.hxx

439 lines
12 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1993.
//
// File: psctbl.hxx
//
// Contents: IID to proxy/stub CLSID mapping cache
//
// Classes: CPSClsidTbl - shared memory guid map
//
// Functions: none
//
// History: 07-Apr-94 Rickhi Created
//
// Notes: this class maintains an IID to CLSID mapping table
// in shared memory.
//
//----------------------------------------------------------------------------
#ifndef __PSCTBL__
#define __PSCTBL__
#define IIDTBL_MAX_SIZE 12288
// structures for one entry in the cache. the first is for entries of
// ole2 style guids, the second for other guids.
typedef struct tagDWORDPAIR
{
DWORD dw1; // IID
DWORD dw2; // CLSID
} DWORDPAIR;
typedef struct tagGUIDPAIR
{
GUID guid1; // IID
GUID guid2; // CLSID
} GUIDPAIR;
// structure for global table info. This appears at the start of the table
// and is used by all readers.
typedef struct tagGUIDMAP
{
ULONG ulSize; // size of table
ULONG ulFreeSpace; // Free space in table
ULONG ulCntShort; // number of entries in the short list
ULONG ulCntLong; // number of entries in the long list
} GUIDMAP;
// template for OLE201 style guids
const GUID guidOleTemplate =
{0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
extern TCHAR tszInterface[];
// the following string is used in compapi.cxx
extern WCHAR wszProxyStubClsid[];
extern WCHAR wszProxyStubClsid16[];
//+---------------------------------------------------------------------------
//
// class: CPSClsidTbl
//
// synopsis: OLE32 version of shared memory cache for
// IID to PSCLSID mappings
//
// Classes: CPSClsidTbl
//
// History: 06-Apr-94 Rickhi Created
//
// Notes: this is the OLE32.DLL version of the class. It reads the
// the entries from the shared memory table, but never updates
// them.
//
// the table is a list of IID to CLSID mappings in shared mem.
// this list is used by ole32.dll when loading interface proxies
// and stubs, and we want to avoid random registry hits.
//
// the SCM creates the list and is the only one who can modify
// the shared memory. the clients are simply read only. the
// SCM updates it when the registry changes.
//
// for OLE20 style guids that change only in the first DWORD,
// we store only the first DWORD instead of the whole GUID,
// giving us 4-1 compression for the (currently) common case.
//
// the DWORD cache starts at the beginning of the shared mem
// and grows up, the GUID cache starts at the end of the shared
// mem and grows down, giving us the maximum capacity.
//
//----------------------------------------------------------------------------
class CPSClsidTbl
{
public:
CPSClsidTbl();
void Initialize(BYTE *pTbl);
HRESULT Find(REFGUID rguid, GUID *pGuidOut);
BOOL IsFull();
private:
DWORDPAIR * SearchShortList(DWORD dwFind);
GUIDPAIR * SearchLongList(REFGUID rguid);
GUIDMAP * _pGuidMap; // ptr to table header
DWORDPAIR * _pShortList; // list of OLE style guids
GUIDPAIR * _pLongList; // list of non OLE style guids
};
//+-------------------------------------------------------------------------
//
// Member: CPSClsidTbl::CPSClsidTbl
//
// Synopsis: ctor for the client side table
//
//--------------------------------------------------------------------------
inline CPSClsidTbl::CPSClsidTbl() :
_pGuidMap(NULL),
_pShortList(NULL),
_pLongList(NULL)
{
}
//+-------------------------------------------------------------------------
//
// Member: CPSClsidTbl::Initialize
//
// Synopsis: intializes the client side of the table
//
// Arguments: [pTblHdr] - ptr to where the table header should start
//
//--------------------------------------------------------------------------
inline void CPSClsidTbl::Initialize(BYTE *pTblHdr)
{
Win4Assert(pTblHdr && "CPSClsidTbl invalid TblHdr pointer");
_pGuidMap = (GUIDMAP *)pTblHdr;
_pShortList = (DWORDPAIR *)(((BYTE *)_pGuidMap) + sizeof(GUIDMAP));
_pLongList = (GUIDPAIR *) (((BYTE *)_pGuidMap) + _pGuidMap->ulSize -
sizeof(GUIDPAIR));
}
//+-------------------------------------------------------------------------
//
// Member: CPSClsidTbl::IsFull
//
// Synopsis: returns TRUE if there is no room in the table
//
// Algorithm: ulFreeSpace is zero if there is no room in the table,
// otherwise it is set to 1.
//
//--------------------------------------------------------------------------
inline BOOL CPSClsidTbl::IsFull()
{
return (_pGuidMap->ulFreeSpace == 0);
}
//+---------------------------------------------------------------------------
//
// class: CScmPSClsidTbl
//
// synopsis: shared memory cache of IID to PSCLSID mappings
//
// History: 06-Apr-94 Rickhi Created
//
// Notes: this is the SCM.EXE version of the class. It constructs
// the table in shared memory.
//
// it maintains a list of IID to CLSID mappings in shared mem.
// this list is used by ole32.dll when loading interface proxies
// and stubs, and we want to avoid random registry hits.
//
// the SCM creates the list and is the only one who can modify
// the shared memory. the clients are simply read only. the
// SCM updates it when the registry changes.
//
// for OLE20 style guids that change only in the first DWORD,
// we store only the first DWORD instead of the whole GUID,
// giving us 4-1 compression for the (currently) common case.
//
// the DWORD cache starts at the beginning of the shared mem
// and grows up, the GUID cache starts at the end of the shared
// mem and grows down, giving us the maximum capacity.
//
//----------------------------------------------------------------------------
class CScmPSClsidTbl
{
public:
CScmPSClsidTbl();
~CScmPSClsidTbl();
HRESULT InitTbl(ULONG *pulSize);
BYTE *CopyTbl(BYTE *pShrTbl);
void FreeTbl(void);
private:
BOOL Add(REFGUID rguid1, REFGUID rguid2);
GUIDMAP * _pGuidMap; // ptr to table header
DWORDPAIR * _pShortList; // list of OLE style guids
GUIDPAIR * _pLongList; // list of non OLE style guids
};
//+-------------------------------------------------------------------------
//
// Member: CScmPSClsidTbl::CScmPSClsidTbl
//
// Synopsis: constructor for the SCM side of the table
//
//--------------------------------------------------------------------------
inline CScmPSClsidTbl::CScmPSClsidTbl() :
_pGuidMap(NULL),
_pShortList(NULL),
_pLongList(NULL)
{
}
//+-------------------------------------------------------------------------
//
// Member: CScmPSClsidTbl::~CScmPSClsidTbl
//
// Synopsis: destructor for the SCM side of the table
//
//--------------------------------------------------------------------------
inline CScmPSClsidTbl::~CScmPSClsidTbl()
{
PrivMemFree(_pGuidMap);
}
//+-------------------------------------------------------------------------
//
// Member: CScmPSClsidTbl::FreeTbl
//
// Synopsis: deletes the local copy of the table
//
//--------------------------------------------------------------------------
inline void CScmPSClsidTbl::FreeTbl(void)
{
PrivMemFree(_pGuidMap);
_pGuidMap = NULL;
}
//+-------------------------------------------------------------------------
//
// Function: IsOleStyleGuid
//
// Synopsis: determines if the GUID is one of the OLE201 style guids
//
// Arguments: [rguid] - guid to check
//
// Returns: TRUE if OLE20 style guid, FALSE otherwise.
//
// Algorithm: If the last 3 dwords of the GUID match the ones uses by all
// OLE20 guids, then this returns TRUE, otherwise FALSE
//
//--------------------------------------------------------------------------
inline BOOL IsOleStyleGuid(REFGUID rguid)
{
const DWORD *ptr = &rguid.Data1;
return (*(ptr+1) == 0x00000000 && // all ole sytle guids's have
*(ptr+2) == 0x000000C0 && // these common values
*(ptr+3) == 0x46000000);
}
//+-------------------------------------------------------------------------
//
// Member: CScmPSClsidTbl::InitTbl
//
// Synopsis: intializes the local copy of the table
//
// Arguments: [pulSize] - where to return the table size
//
// Algorithm: This starts by building the table in local memory. When
// the table is complete, a call to Copy will copy the local
// table into shared memory.
//
//--------------------------------------------------------------------------
inline HRESULT CScmPSClsidTbl::InitTbl(ULONG *pulSize)
{
HKEY hKey;
FILETIME ftLastWrite;
WCHAR awName[MAX_PATH];
DWORD cName = sizeof(awName);
DWORD iSubKey = 0;
BOOL fTableFull = FALSE;
// allocate some local memory in which to build the mapping
_pGuidMap = (GUIDMAP *) PrivMemAlloc(IIDTBL_MAX_SIZE);
if (_pGuidMap == NULL)
{
return E_OUTOFMEMORY;
}
// initialize the map header
_pGuidMap->ulSize = IIDTBL_MAX_SIZE;
_pGuidMap->ulFreeSpace = IIDTBL_MAX_SIZE - sizeof(GUIDMAP);
_pGuidMap->ulCntShort = 0;
_pGuidMap->ulCntLong = 0;
// initialize this objects pointers
_pShortList = (DWORDPAIR *)(((BYTE *)_pGuidMap) + sizeof(GUIDMAP));
_pLongList = (GUIDPAIR *) (((BYTE *)_pGuidMap) + _pGuidMap->ulSize -
sizeof(GUIDPAIR));
// enumerate the interface keys in the registry and create a table
// entry for each interface that has a ProxyStubClsid32 entry.
#ifdef _CHICAGO_
if (RegOpenKeyExA(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
== ERROR_SUCCESS)
#else //_CHICAGO_
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
== ERROR_SUCCESS)
#endif //_CHICAGO_
{
while (RegEnumKeyEx(hKey, iSubKey, awName, &cName,
NULL, NULL, NULL, &ftLastWrite) == ERROR_SUCCESS)
{
// Get data from registry for this interface
WCHAR awcsPSClsid[80];
LONG cbPSClsid = sizeof(awcsPSClsid);
// This variable is used below to overwrite the ProxyStubClsid32
WCHAR *pwcEndOfName = awName + lstrlenW(awName);
lstrcatW(awName, wszProxyStubClsid);
if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
== ERROR_SUCCESS)
{
// Convert registry string formats to GUID formats
GUID guidIID;
GUID guidCLSID;
*pwcEndOfName = 0;
if (GUIDFromString(awName, &guidIID))
{
if (GUIDFromString(awcsPSClsid, &guidCLSID))
{
if (!Add(guidIID, guidCLSID))
{
// we ran out of space in the cache table, exit
// now to avoid doing anymore work
fTableFull = TRUE;
break;
}
}
}
}
else
{
// There wasn't a ProxyStubClsid32 for this interface.
// Because many applications install with interfaces
// that are variations on IDispatch, we are going to check
// to see if there is a ProxyStubClsid. If there is, and its
// class is that of IDispatch, then the OLE Automation DLL is
// the correct one to use. In that particular case, we will
// pretend that ProxyStubClsid32 existed, and that it is
// for IDispatch.
// Copy over ProxyStubClsid
cbPSClsid = sizeof(awcsPSClsid);
lstrcpyW(pwcEndOfName, wszProxyStubClsid16);
if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
== ERROR_SUCCESS)
{
// Convert registry string formats to GUID formats
GUID guidIID;
GUID guidCLSID;
if (GUIDFromString(awcsPSClsid, &guidCLSID))
{
// If the clsid for the proxy stub is that of
// IDispatch, then register it.
*pwcEndOfName = 0;
if (!memcmp(&guidCLSID,&CLSID_PSDispatch, sizeof(GUID)) &&
GUIDFromString(awName, &guidIID))
{
if (!Add(guidIID, guidCLSID))
{
// we ran out of space in the cache table, exit
// now to avoid doing anymore work
fTableFull = TRUE;
break;
}
}
}
}
}
iSubKey++;
cName = sizeof(awName);
}
RegCloseKey(hKey);
}
// update the size and freespace. Note: because CopyTbl compacts the table,
// it is important to subtract the correct amount of freespace left in the
// table in order for the client-side computation of _pLongList to work
// out correctly.
_pGuidMap->ulSize = _pGuidMap->ulSize - _pGuidMap->ulFreeSpace;
_pGuidMap->ulFreeSpace = (fTableFull) ? 0 : 1;
// set the return values
*pulSize = _pGuidMap->ulSize;
return S_OK;
}
#endif __PSCTBL__