124 lines
3.7 KiB
C++
124 lines
3.7 KiB
C++
//*** 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;
|
|
}
|