windows-nt/Source/XPSP1/NT/enduser/netmeeting/srvc/taskbar.cpp
2020-09-26 16:20:57 +08:00

347 lines
9.5 KiB
C++

// File: taskbar.cpp
#include "precomp.h"
#include "taskbar.h"
#include <iappldr.h>
#include <tsecctrl.h>
static HWND g_hwndHidden = NULL;
const TCHAR g_cszHiddenWndClassName[] = _TEXT("MnmSrvcHiddenWindow");
BOOL g_fTaskBarIconAdded = FALSE;
BOOL g_fTimerRunning = FALSE;
extern INmSysInfo2 * g_pNmSysInfo;
extern int g_cPersonsInConf;
// This routine starts a timer to periodically retry adding the taskbar icon.
// This is necessary in case the taskbar is not showing at the time the
// service is launched, or the taskbar is destroyed by a logoff-logon sequence.
VOID StartTaskbarTimer(VOID)
{
if ( !g_fTimerRunning)
{
ASSERT(g_hwndHidden);
SetTimer(g_hwndHidden, 0, 5000, NULL);
g_fTimerRunning = TRUE;
}
}
VOID KillTaskbarTimer(VOID)
{
if ( g_fTimerRunning )
{
KillTimer ( g_hwndHidden, 0 );
g_fTimerRunning = FALSE;
}
}
LRESULT CALLBACK HiddenWndProc( HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_USERCHANGED:
case WM_ENDSESSION:
// A user is logging on or off... We don't know which but
// since the desktop is changing we assume our taskbar icon
// is toast. Start a timer to periodically try to add it back
// until it succeeds.
g_fTaskBarIconAdded = FALSE;
StartTaskbarTimer();
break;
case WM_TASKBAR_NOTIFY:
{
if (WM_RBUTTONUP == lParam)
{
::OnRightClickTaskbar();
}
break;
}
case WM_TIMER:
AddTaskbarIcon();
break;
case WM_DESTROY:
{
// NULL the global variable:
g_hwndHidden = NULL;
return 0;
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return FALSE;
}
BOOL CmdActivate(VOID)
{
RegEntry Re( REMOTECONTROL_KEY, HKEY_LOCAL_MACHINE );
Re.SetValue ( REMOTE_REG_ACTIVATESERVICE, (DWORD)1 );
if (MNMServiceActivate())
{
ReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0);
return TRUE;
}
else
{
return FALSE;
}
}
VOID CmdInActivate(VOID)
{
RegEntry Re( REMOTECONTROL_KEY, HKEY_LOCAL_MACHINE );
Re.SetValue ( REMOTE_REG_ACTIVATESERVICE, (DWORD)0 );
if (MNMServiceDeActivate())
ReportStatusToSCMgr( SERVICE_PAUSED, NO_ERROR, 0);
}
VOID CmdSendFiles(VOID)
{
ASSERT(g_pNmSysInfo);
if (g_pNmSysInfo)
{
g_pNmSysInfo->ProcessSecurityData(LOADFTAPPLET, 0, 0, NULL);
}
}
VOID CmdShutdown(VOID)
{
if (STATE_ACTIVE == g_dwActiveState)
{
CmdInActivate();
}
MNMServiceStop();
DestroyWindow(g_hwndHidden);
}
BOOL AddTaskbarIcon(VOID)
{
BOOL bRet = FALSE;
if ( NULL == g_hwndHidden )
{
// Register hidden window class:
WNDCLASS wcHidden =
{
0L,
HiddenWndProc,
0,
0,
GetModuleHandle(NULL),
NULL,
NULL,
NULL,
NULL,
g_cszHiddenWndClassName
};
if (!RegisterClass(&wcHidden))
{
ERROR_OUT(("Could not register hidden wnd classes"));
return FALSE;
}
// Create a hidden window for event processing:
g_hwndHidden = ::CreateWindow( g_cszHiddenWndClassName,
_TEXT(""),
WS_POPUP, // not visible!
0, 0, 0, 0,
NULL,
NULL,
GetModuleHandle(NULL),
NULL);
}
if (NULL == g_hwndHidden)
{
ERROR_OUT(("Could not create hidden windows"));
return FALSE;
}
// Place a 16x16 icon in the taskbar notification area:
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = g_hwndHidden;
tnid.uID = ID_TASKBAR_ICON;
tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
tnid.uCallbackMessage = WM_TASKBAR_NOTIFY;
tnid.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SM_WORLD));
::LoadString(GetModuleHandle(NULL), IDS_MNMSRVC_TITLE,
tnid.szTip, CCHMAX(tnid.szTip));
// Attempt to add the icon. This may fail because there is no taskbar
// (no user desktop shown). Warn if this is so... We will retry on
// a periodic timer.
if (FALSE == (bRet = Shell_NotifyIcon(NIM_ADD, &tnid)))
{
#ifdef DEBUG
if ( !g_fTimerRunning )
WARNING_OUT(("Could not add notify icon!"));
#endif // DEBUG
// Start the taskbar timer to periodically retry until this succeeds
StartTaskbarTimer();
}
else
{
g_fTaskBarIconAdded = TRUE;
KillTaskbarTimer(); // Kill timer if necessary
}
if (NULL != tnid.hIcon)
{
DestroyIcon(tnid.hIcon);
}
return bRet;
}
BOOL RemoveTaskbarIcon(VOID)
{
NOTIFYICONDATA tnid;
BOOL ret;
if ( !g_fTaskBarIconAdded || NULL == g_hwndHidden )
{
return FALSE;
}
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = g_hwndHidden;
tnid.uID = ID_TASKBAR_ICON;
ret = Shell_NotifyIcon(NIM_DELETE, &tnid);
g_fTaskBarIconAdded = FALSE;
return ret;
}
BOOL OnRightClickTaskbar()
{
TRACE_OUT(("OnRightClickTaskbar called"));
POINT ptClick;
if (FALSE == ::GetCursorPos(&ptClick))
{
ptClick.x = ptClick.y = 0;
}
// Get the menu for the popup from the resource file.
HMENU hMenu = ::LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_TASKBAR_POPUP));
if (NULL == hMenu)
{
return FALSE;
}
// Get the first menu in it which we will use for the call to
// TrackPopup(). This could also have been created on the fly using
// CreatePopupMenu and then we could have used InsertMenu() or
// AppendMenu.
HMENU hMenuTrackPopup = ::GetSubMenu(hMenu, 0);
RegEntry reLM( REMOTECONTROL_KEY, HKEY_LOCAL_MACHINE);
BOOL fNoExit = reLM.GetNumber(REMOTE_REG_NOEXIT, DEFAULT_REMOTE_NOEXIT);
::EnableMenuItem(hMenuTrackPopup, IDM_TBPOPUP_STOP, fNoExit ? MF_GRAYED : MF_ENABLED);
if (STATE_ACTIVE == g_dwActiveState)
{
::EnableMenuItem(hMenuTrackPopup, IDM_TBPOPUP_INACTIVATE, fNoExit ? MF_GRAYED : MF_ENABLED);
::EnableMenuItem(hMenuTrackPopup, IDM_TBPOPUP_SENDFILES, (2 == g_cPersonsInConf) ? MF_ENABLED : MF_GRAYED);
}
else if (STATE_INACTIVE == g_dwActiveState)
{
HANDLE hInit = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, _TEXT("CONF:Init"));
::EnableMenuItem(hMenuTrackPopup, IDM_TBPOPUP_ACTIVATE, hInit ?
MF_GRAYED : MF_ENABLED);
::CloseHandle(hInit);
}
else
{
// Leave all menus grayed
}
// Draw and track the "floating" popup
// According to the font view code, there is a bug in USER which causes
// TrackPopupMenu to work incorrectly when the window doesn't have the
// focus. The work-around is to temporarily create a hidden window and
// make it the foreground and focus window.
HWND hwndDummy = ::CreateWindow(_TEXT("STATIC"), NULL, 0,
ptClick.x,
ptClick.y,
1, 1, HWND_DESKTOP,
NULL, GetModuleHandle(NULL), NULL);
if (NULL != hwndDummy)
{
HWND hwndPrev = ::GetForegroundWindow(); // to restore
TPMPARAMS tpmp;
tpmp.cbSize = sizeof(tpmp);
tpmp.rcExclude.right = 1 + (tpmp.rcExclude.left = ptClick.x);
tpmp.rcExclude.bottom = 1 + (tpmp.rcExclude.top = ptClick.y);
::SetForegroundWindow(hwndDummy);
::SetFocus(hwndDummy);
int iRet = ::TrackPopupMenuEx( hMenuTrackPopup,
TPM_RETURNCMD | TPM_HORIZONTAL | TPM_RIGHTALIGN |
TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
ptClick.x,
ptClick.y,
hwndDummy,
&tpmp);
// Restore the previous foreground window (before destroying hwndDummy).
if (hwndPrev)
{
::SetForegroundWindow(hwndPrev);
}
::DestroyWindow(hwndDummy);
switch (iRet)
{
case IDM_TBPOPUP_ACTIVATE:
{
CmdActivate();
break;
}
case IDM_TBPOPUP_INACTIVATE:
{
CmdInActivate();
break;
}
case IDM_TBPOPUP_SENDFILES:
{
CmdSendFiles();
break;
}
case IDM_TBPOPUP_STOP:
{
CmdShutdown();
break;
}
default:
break;
}
}
// We are finished with the menu now, so destroy it
::RemoveMenu(hMenu, 0, MF_BYPOSITION);
::DestroyMenu(hMenuTrackPopup);
::DestroyMenu(hMenu);
return TRUE;
}