//*** 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; }