|
|
//*** uassist.cpp -- User Assist helpers (retail and debug)
//
// DESCRIPTION
// this file has the shared-source 'master' implementation. it is
// #included in each DLL that uses it. NEEDED because of ENTERCRITICAL
// as stocklib.dll does not have a critical section in it.
//
// clients do something like:
// #include "priv.h" // for types, ASSERT, DM_*, DF_*, etc.
// #include "../lib/uassist.cpp"
//
// we cache the UAssist object and provide thunks for 'safe' access to it.
#include "uemapp.h"
#define DM_UASSIST 0
IUserAssist *g_uempUa; // 0:uninit, -1:failed, o.w.:cached obj
//*** GetUserAssist -- get (and create) cached UAssist object
//
IUserAssist *GetUserAssist() { HRESULT hr; IUserAssist * pua = NULL;
if (g_uempUa == 0) { // re: CLSCTX_NO_CODE_DOWNLOAD
// an ('impossible') failed CCI of UserAssist is horrendously slow.
// e.g. click on the start menu, wait 10 seconds before it pops up.
// we'd rather fail than hose perf like this, plus this class should
// never be remote.
// FEATURE: there must be a better way to tell if CLSCTX_NO_CODE_DOWNLOAD
// is supported, i've sent mail to 'com' to find out...
DWORD dwFlags = staticIsOS(OS_WIN2000ORGREATER) ? (CLSCTX_INPROC|CLSCTX_NO_CODE_DOWNLOAD) : CLSCTX_INPROC; hr = THR(CoCreateInstance(CLSID_UserAssist, NULL, dwFlags, IID_IUserAssist, (void**)&pua)); ASSERT(SUCCEEDED(hr) || pua == NULL); // follow COM rules
if (pua) { HINSTANCE hInst;
hInst = SHPinDllOfCLSID(&CLSID_UserAssist); // cached across threads
// we're toast if this fails!!! (but happily, that's 'impossible')
// e.g. during logon when grpconv.exe is ShellExec'ed, we do
// a GetUserAssist, which caches a ptr to browseui's singleton
// object. then when the ShellExec returns, we do CoUninit,
// which would free up the (non-pinned) browseui.dll. then
// a later use of the cache would go off into space.
}
ENTERCRITICAL; if (g_uempUa == 0) { g_uempUa = pua; // xfer refcnt (if any)
if (!pua) { // mark it failed so we won't try any more
g_uempUa = (IUserAssist *)-1; } pua = NULL; } LEAVECRITICAL; if (pua) pua->Release(); TraceMsg(DM_UASSIST, "sl.gua: pua=0x%x g_uempUa=%x", pua, g_uempUa); }
return (g_uempUa == (IUserAssist *)-1) ? 0 : g_uempUa; }
extern "C" BOOL UEMIsLoaded() { BOOL fRet;
fRet = GetModuleHandle(TEXT("ole32.dll")) && GetModuleHandle(TEXT("browseui.dll")); return fRet; }
//*** UEMFireEvent, QueryEvent, SetEvent -- 'safe' thunks
// DESCRIPTION
// call these so don't have to worry about cache or whether Uassist object
// even was successfully created.
extern "C" HRESULT UEMFireEvent(const GUID *pguidGrp, int eCmd, DWORD dwFlags, WPARAM wParam, LPARAM lParam) { HRESULT hr = E_FAIL; IUserAssist *pua;
pua = GetUserAssist(); if (pua) { hr = pua->FireEvent(pguidGrp, eCmd, dwFlags, wParam, lParam); } return hr; }
extern "C" HRESULT UEMQueryEvent(const GUID *pguidGrp, int eCmd, WPARAM wParam, LPARAM lParam, LPUEMINFO pui) { HRESULT hr = E_FAIL; IUserAssist *pua;
pua = GetUserAssist(); if (pua) { hr = pua->QueryEvent(pguidGrp, eCmd, wParam, lParam, pui); } return hr; }
extern "C" HRESULT UEMSetEvent(const GUID *pguidGrp, int eCmd, WPARAM wParam, LPARAM lParam, LPUEMINFO pui) { HRESULT hr = E_FAIL; IUserAssist *pua;
pua = GetUserAssist(); if (pua) { hr = pua->SetEvent(pguidGrp, eCmd, wParam, lParam, pui); } return hr; }
|