419 lines
16 KiB
C++
419 lines
16 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1996.
|
|
//
|
|
// File: dllcache.hxx
|
|
//
|
|
// Contents: Classes which implement cache of class Dlls previously
|
|
// located and local server class registrations.
|
|
//
|
|
// Classes: CDllCache
|
|
// CDllAptEntry
|
|
//
|
|
// Structures: SClassntry
|
|
// SDllPathEntry
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 09-May-93 Ricksa Created
|
|
// 31-Dec-93 ErikGav Chicago port
|
|
// 24-Jun-94 Rickhi Add Apartment Crap
|
|
// 13-Feb-95 BruceMa Change class object registration so
|
|
// volatile addresses are not used
|
|
// 07-Mar-95 BruceMa Rewrote
|
|
//
|
|
// Notes: The dll/class cache was rewritten to simplify and to improve
|
|
// performance. Since only a few entries (max ~16) are expected,
|
|
// linear search is deemed sufficient. The inclinaton then is to
|
|
// store entries on a linked list. However, since the cache is
|
|
// visited infrequently there is a good chance that it will have
|
|
// been paged out. So, instead of a linked list of different
|
|
// allocations which may touch many pages, the entries are
|
|
// stored in an array occupying a single area of memory. There
|
|
// are two arrays, one storing dll paths, etc. and one for
|
|
// class registrations. These arrays are initialized small and
|
|
// dynamically expanded as needed. Also, the CDllAptEntry
|
|
// was eliminated for the same reason. Instead, threadId's
|
|
// associated with a dll are stored in the CDllPathEntry to
|
|
// nominally 16, and thereafter it is dynamically expanded.
|
|
//
|
|
// SDllPathEntry and SClassEntry were originally implemented as
|
|
// classes but were made structures and their management was
|
|
// moved to the CDllCache level, since during an outgoing call
|
|
// it is possible that another thread may come in causing the
|
|
// cache to get reallocated and moved. This would invalidate
|
|
// any internal 'this' pointers. Because of the WOW we can't
|
|
// hold a mutex across outgoing calls. Therefore class entries
|
|
// and dll path entries are managed from the top level via
|
|
// indices.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#ifndef __DLLCACHE_HXX__
|
|
#define __DLLCACHE_HXX__
|
|
|
|
#include <olesem.hxx>
|
|
|
|
const UINT NOMINAL_CACHE_SIZE = 8;
|
|
const UINT NOMINAL_NUMBER_THREADS = 16;
|
|
|
|
const DWORD CLASS_CACHE_SIG = 0x53534c43;
|
|
const DWORD DLL_PATH_CACHE_SIG = 0x534c4c44;
|
|
const DWORD DLL_APT_CACHE_SIG = 0x53545041;
|
|
|
|
#define DLL_GET_CLASS_OBJECT_EP "DllGetClassObject"
|
|
#define DLL_CAN_UNLOAD_EP "DllCanUnloadNow"
|
|
|
|
const DWORD NONE = ~0UL;
|
|
|
|
// Flags
|
|
#define SIXTEEN_BIT 0x00000001
|
|
#define IS_OLE32 0x00000002
|
|
#ifdef WX86OLE
|
|
#define WX86_THUNK 0x00000004
|
|
#define WX86_LOADASX86 0x00000008
|
|
#endif
|
|
#define DELAYED_UNLOAD 0x00000010 // delay unloading this DLL
|
|
|
|
#define DLL_DELAY_UNLOAD_TIME 600000 // 600,000 ticks == 10 minutes
|
|
|
|
|
|
// Typedef for pointer to DllCanUnloadNow function
|
|
typedef HRESULT (*DLLUNLOADFNP)(void);
|
|
|
|
|
|
class CDllCache;
|
|
class CObjServer;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Structure: SClassEntry
|
|
//
|
|
// Purpose: Provides cached information for a class object
|
|
//
|
|
// History: 09-May-93 Ricksa Created
|
|
// 07-Mar-95 BruceMa Rewrote
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
struct SClassEntry
|
|
{
|
|
DWORD _dwNext; // Next entry in in-use or avail list
|
|
DWORD _dwSig; // Marks entry as in use
|
|
CLSID _clsid; // Class of this server
|
|
IUnknown *_pUnk; // Class factory IUnknown
|
|
DWORD _dwContext; // Class context
|
|
DWORD _dwFlags; // Single vs. multiple use
|
|
DWORD _dwReg; // Registration key for caaller
|
|
DWORD _dwScmReg; // Registration ID at the SCM
|
|
HAPT _hApt; // Thread Id
|
|
DWORD _cCallOut; // Count of active call outs
|
|
ULONG _fRevokePending:1; // Whether revoked while calling out
|
|
ULONG _fRevoking:1; // Prevents recursive revoking
|
|
ULONG _fReleasing:1; // Prevents recursive releasing
|
|
DWORD _dwDllThreadModel; // Threading model for the DLL
|
|
DWORD _fAtStorage; // Whether server is an at bits server
|
|
DWORD _dwDllEnt; // Associated dll path entry
|
|
DWORD _dwNextDllCls; // Next class entrry for this dll
|
|
HWND _hWndDdeServer; // Handle of associated DDE window
|
|
CObjServer *_pObjServer; // object server interface
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CDllAptEntry
|
|
//
|
|
// Purpose: Abstracts per apartment info for a Dll.
|
|
//
|
|
// Interface: Init - loads the Dll and retrieves the entry points
|
|
// IsValidInApartment - TRUE if data valid for given apartment
|
|
//
|
|
// History: 27-Jun-94 Rickhi Created
|
|
// 07-Mar-95 BruceMa Rewrote
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
class CDllAptEntry
|
|
{
|
|
public:
|
|
|
|
void Init(DWORD j);
|
|
|
|
void Create(HAPT hApt);
|
|
|
|
private:
|
|
|
|
DWORD _dwNext; // Next entry in avail or in use list
|
|
DWORD _dwSig; // Unique signature for apt entries
|
|
HAPT _hApt; // apartment id
|
|
HMODULE _hDll; // module handle
|
|
|
|
friend class CDllCache;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Structure: SDllPathEntry
|
|
//
|
|
// Purpose: Represents a DLL.
|
|
//
|
|
// Interface: Init - Complete initialization
|
|
// MakeValidInApartment - make Dll valid for current apartment
|
|
// GetClassInterface - Gets DLL to return the class factory
|
|
// CanUnloadNow - Asks DLL if it can unload
|
|
// AddClass - Adds class object to list of classes
|
|
// served by DLL
|
|
// CleanUpForApartment - cleanup per apartment entries
|
|
//
|
|
// History: 09-May-93 Ricksa Created
|
|
// 07-Mar-95 BruceMa Rewrote
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
struct SDllPathEntry
|
|
{
|
|
DWORD _dwNext; // Next in-use/avail entry
|
|
DWORD _dwSig; // Unique signature for safty
|
|
LPTSTR _ptszPath; // The dll pathname
|
|
DWORD _dwHash; // Hash value for searching
|
|
LPFNGETCLASSOBJECT _pfnGetClassObject; // Create object entry point
|
|
DLLUNLOADFNP _pfnDllCanUnload; // DllCanUnloadNow entry point
|
|
DWORD _dwFlags; // Internal flags
|
|
DWORD _dw1stClass; // First class entry for dll
|
|
DWORD _cUsing; // Count of using threads
|
|
DWORD _cAptEntries; // Total apt entries
|
|
DWORD _nAptAvail; // List of available apt entries
|
|
DWORD _nAptInUse; // List of in use apt entries
|
|
CDllAptEntry *_pAptEntries; // Per thread info
|
|
HMODULE _hDll32; // Module handle if this is a 32 bit dll
|
|
DWORD _dwExpireTime; // Time until safe to unload dll
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CDllCache
|
|
//
|
|
// Purpose: Provide unified access to the cached class/dll information
|
|
//
|
|
// Interface: GetClass - Get a class factory for a class
|
|
// Add - Add a DLL and class
|
|
// FreeUnused - Free DLLs which are not being used
|
|
// RegisterServer - Add a server object to the registration
|
|
// Revoke - Revoke a server object
|
|
//
|
|
// Notes: This class *must* be allocated statically, since it includes
|
|
// a COleStaticMutexSem.
|
|
//
|
|
// History: 09-May-93 Ricksa Created
|
|
// 07-Mar-95 BruceMa Rewrote
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
class CDllCache
|
|
{
|
|
public:
|
|
|
|
// Top level methods
|
|
|
|
CDllCache(void);
|
|
|
|
IUnknown *GetClassInterface(DWORD dwDll,
|
|
DWORD dwDllThreadModel,
|
|
REFCLSID rclsid,
|
|
REFIID riid,
|
|
HRESULT& hr);
|
|
|
|
HRESULT CanUnloadNow(DWORD dwDll);
|
|
|
|
void RemoveAndUnload(DWORD dwDll);
|
|
|
|
BOOL Init(void);
|
|
|
|
// Get a class factory interface for a class
|
|
HRESULT GetClass(REFCLSID rclsid,
|
|
REFIID riid,
|
|
BOOL fRemote,
|
|
BOOL fForSCM,
|
|
BOOL fForSurrogate,
|
|
#ifdef WX86OLE
|
|
BOOL fWx86,
|
|
#endif
|
|
IUnknown **ppunk
|
|
);
|
|
|
|
IUnknown *GetOrLoadClass(REFCLSID rclsid,
|
|
REFIID riid,
|
|
BOOL fRemote,
|
|
BOOL fForSCM,
|
|
#ifdef WX86OLE
|
|
BOOL fWx86,
|
|
#endif
|
|
DWORD dwContext,
|
|
DWORD dwThreadingType,
|
|
HRESULT &hr);
|
|
|
|
BOOL GetClassObjForDde(REFCLSID clsid,
|
|
LPDDECLASSINFO lpDdeInfo);
|
|
|
|
BOOL GetClassInformationFromKey(LPDDECLASSINFO lpDdeInfo);
|
|
|
|
|
|
#ifdef _CHICAGO_
|
|
BOOL GetApartmentForCLSID(REFCLSID rclsid, HAPT &hApt);
|
|
#endif
|
|
|
|
// Add a new entry to the class/dll cache and
|
|
// get a class factory if requested.
|
|
IUnknown * Add(REFCLSID rclsid,
|
|
REFIID riid,
|
|
DWORD dwDllThreadModel,
|
|
const TCHAR *ptszDllPath,
|
|
BOOL fGetClassObject,
|
|
BOOL fSixteenBit,
|
|
#ifdef WX86OLE
|
|
BOOL fWx86,
|
|
#endif
|
|
HRESULT& hr);
|
|
|
|
void FreeUnused(void);
|
|
|
|
HRESULT RegisterServer(REFCLSID rclsid,
|
|
IUnknown *punk,
|
|
DWORD flags,
|
|
DWORD dwTypeToRegister,
|
|
LPDWORD lpdwRegister);
|
|
|
|
HRESULT Revoke(DWORD pdwRegister);
|
|
|
|
BOOL SetDdeServerWindow(DWORD dwKey,
|
|
HWND hwndDdeServer);
|
|
|
|
void CleanUpDllsForApartment(void);
|
|
void CleanUpLocalServersForApartment(void);
|
|
void CleanUpDllsForProcess(void);
|
|
|
|
ULONG AddRefServerProcess(void);
|
|
ULONG ReleaseServerProcess(void);
|
|
HRESULT SuspendProcessClassObjects(void);
|
|
HRESULT ResumeProcessClassObjects(void);
|
|
|
|
private:
|
|
|
|
#ifdef WX86OLE
|
|
HRESULT Load(LPCTSTR pwszPath,
|
|
LPFNGETCLASSOBJECT *ppfnGetClassObject,
|
|
DLLUNLOADFNP *ppfnDllCanUnload,
|
|
BOOL fSixteenBit,
|
|
HMODULE *hDll,
|
|
BOOL *pIsX86Dll,
|
|
BOOL fLoadAsX86);
|
|
#else
|
|
HRESULT Load(LPCTSTR pwszPath,
|
|
LPFNGETCLASSOBJECT *ppfnGetClassObject,
|
|
DLLUNLOADFNP *ppfnDllCanUnload,
|
|
BOOL fSixteenBit,
|
|
HMODULE *hDll);
|
|
#endif
|
|
|
|
void InitClsent(DWORD dwCls, DWORD k);
|
|
|
|
HRESULT CreateClsentLSvr(DWORD dwCls,
|
|
REFCLSID rclsid,
|
|
IUnknown *punk,
|
|
DWORD dwFlags,
|
|
DWORD dwContext,
|
|
DWORD dwReg);
|
|
|
|
HRESULT CreateClsentInProc(DWORD dwCls,
|
|
DWORD dwDll,
|
|
DWORD dwDllThreadModel,
|
|
DWORD dwNextDllCls,
|
|
REFCLSID rclsid
|
|
#ifdef WX86OLE
|
|
,BOOL fWx86
|
|
#endif
|
|
);
|
|
|
|
BOOL GetClassObjForDdeByClsent(DWORD dwCls,
|
|
LPDDECLASSINFO lpDdeClassInfo);
|
|
|
|
HRESULT Release(DWORD dwCls);
|
|
|
|
void InitDllent(DWORD dwDll, DWORD k);
|
|
|
|
HRESULT CreateDllent(DWORD dwDll,
|
|
LPCTSTR ptszDllPath,
|
|
BOOL fSixteenBit,
|
|
LPFNGETCLASSOBJECT pfnGetClassObject,
|
|
DLLUNLOADFNP pfnDllCanUnload,
|
|
HMODULE hDll
|
|
#ifdef WX86OLE
|
|
,BOOL fIsX86Dll,
|
|
BOOL fLoadAsX86
|
|
#endif
|
|
);
|
|
|
|
BOOL NewAptEntries(DWORD dwDll);
|
|
|
|
DWORD AllocAptEntry(DWORD dwDll);
|
|
|
|
void FreeAptEntry(DWORD dwDll, DWORD dwAptent);
|
|
|
|
HRESULT MakeValidInApartment(DWORD dwDll);
|
|
|
|
BOOL CleanUpForApartmentByDllent(DWORD dwDll, HAPT hApt);
|
|
|
|
// Search for a class entry by registration key
|
|
DWORD Search(DWORD dwRegkey, HAPT hApt);
|
|
|
|
// Search for a class entry for specific apartment
|
|
DWORD Search(REFCLSID clsid, DWORD dwContext, HAPT hApt);
|
|
|
|
// Search for a dll path entry
|
|
DWORD SearchForDll(const _TCHAR *ptszDllPath
|
|
#ifdef WX86OLE
|
|
, BOOL fWx86
|
|
#endif
|
|
);
|
|
|
|
// Allocate/free class and dll entries
|
|
DWORD AllocClassEntry(void);
|
|
DWORD AllocDllPathEntry(void);
|
|
void FreeClassEntry(DWORD dwClsent);
|
|
void FreeDllPathEntry(DWORD dwDllent);
|
|
|
|
// For dll path entries
|
|
BOOL IsValidInApartment(DWORD dwDllent, HAPT hApt);
|
|
|
|
// Compute a hash on the pathname
|
|
DWORD Hash(LPTSTR ptszPath);
|
|
|
|
COleStaticMutexSem _mxs; // Protects from multiple threads
|
|
DWORD _cClassEntries; // Count of class entries
|
|
DWORD _nClassEntryInUse; // First in-use class entry
|
|
DWORD _nClassEntryAvail; // First available class entry
|
|
SClassEntry *_pClassEntries; // Array of class entries
|
|
DWORD _cDllPathEntries; // Count of dll path entries
|
|
DWORD _nDllPathEntryInUse; // First in-use dll path entry
|
|
DWORD _nDllPathEntryAvail; // First available dll path entry
|
|
SDllPathEntry *_pDllPathEntries; // Array of DLL path entries
|
|
ULONG _cRefsServerProcess; // global refcnt for this process
|
|
};
|
|
|
|
|
|
|
|
#endif // __DLLCACHE_HXX__
|