windows-nt/Source/XPSP1/NT/termsrv/reskit/winsta/tsvs.cpp
2020-09-26 16:20:57 +08:00

781 lines
24 KiB
C++

#include "tsvs.h"
TCHAR szTipText[MAX_PATH];
int iItemCount, count;
int g_CurrentSortColumn = 0;
BOOL g_bAscending = FALSE;
HMENU g_hMenu;
HMENU hSysMenu;
TCHAR g_szSelectedSession[MAX_LEN];
//////////////////////////////////////////////////////////////////////////////
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable;
INITCOMMONCONTROLSEX cmctl;
LVCOLUMN lvc;
cmctl.dwICC = ICC_TAB_CLASSES | ICC_BAR_CLASSES;
cmctl.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCommonControlsEx(&cmctl);
g_hTrayThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)TrayThreadMessageLoop,
NULL, 0, &g_idTrayThread);
g_hWinstaThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)WinstaThreadMessageLoop,
NULL, 0, &g_idWinstaThread);
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TSVS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
HWND hwndOld = FindWindow(szAppName, szTitle);
if (hwndOld) {
// Send the other copy of ourselves a PWM_ACTIVATE message.
// If that succeeds, and it returns PWM_ACTIVATE back as the
// return code, it's up and alive and we can exit this instance.
DWORD dwPid = 0;
GetWindowThreadProcessId(hwndOld, &dwPid);
// Chris - Leave this in here. Might need it when
// VS gets fixed.
// AllowSetForegroundWindow(dwPid);
ULONG_PTR dwResult;
if (SendMessageTimeout(hwndOld,
PWM_ACTIVATE,
0, 0,
SMTO_ABORTIFHUNG,
FIND_TIMEOUT,
&dwResult)) {
return 0;
}
}
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) {
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TSVS);
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
lvc.pszText = pszColumn;
lvc.cchTextMax = sizeof(pszColumn);
lvc.cx = COLUMNONEWIDTH;
g_ColumnOneIndex = ListView_InsertColumn(g_hListView, 1, &lvc);
lvc.pszText = pszColumn2;
lvc.cchTextMax = sizeof(pszColumn2);
lvc.cx = COLUMNTWOWIDTH;
g_ColumnTwoIndex = ListView_InsertColumn(g_hListView, 2, &lvc);
lvc.pszText = pszColumn3;
lvc.cchTextMax = sizeof(pszColumn3);
lvc.cx = COLUMNTHREEWIDTH;
g_ColumnThreeIndex = ListView_InsertColumn(g_hListView, 3, &lvc);
lvc.pszText = pszColumn4;
lvc.cchTextMax = sizeof(pszColumn4);
lvc.cx = COLUMNFOURWIDTH;
g_ColumnFourIndex = ListView_InsertColumn(g_hListView, 4, &lvc);
ListView_SetExtendedListViewStyle(g_hListView,
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
if (g_idWinstaThread) {
PostThreadMessage(g_idWinstaThread, PM_WINSTA, 0, 0);
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return(int)msg.wParam;
}
//////////////////////////////////////////////////////////////////////////////
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = DLGWINDOWEXTRA;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TSVS);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TSVS);
wcex.lpszClassName = szAppName;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_ICON1);
return RegisterClassEx(&wcex);
}
//////////////////////////////////////////////////////////////////////////////
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_TSVS), 0, NULL);
g_hMenu = GetMenu(hWnd);
if (!hWnd)
return FALSE;
g_hListView = GetDlgItem(hWnd, IDC_LIST_VIEW);
// variable to save handle to system menu
hSysMenu = GetSystemMenu(hWnd, FALSE);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, IDM_SYS_SHOW_ALL, TEXT("Show All"));
AppendMenu(hSysMenu, MF_STRING, IDM_SYS_ABOUT, TEXT("About..."));
if (CheckForRegKey(LEFT) == TRUE &&
CheckForRegKey(TOP) == TRUE &&
CheckForRegKey(RIGHT) == TRUE &&
CheckForRegKey(BOTTOM) == TRUE) {
SetWindowPos(hWnd, HWND_NOTOPMOST,
GetRegKeyValue(LEFT),
GetRegKeyValue(TOP),
(GetRegKeyValue(RIGHT) +
GetSystemMetrics (SM_CXDLGFRAME))
- GetRegKeyValue(LEFT),
(GetRegKeyValue(BOTTOM) +
GetSystemMetrics (SM_CYDLGFRAME))
- GetRegKeyValue(TOP),
SWP_NOZORDER | SWP_NOACTIVATE);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
ListView_DeleteAllItems(g_hListView);
InitializeCriticalSection(&g_CSTrayThread);
for (UINT i = 0; i < g_cTrayIcons; i++) {
g_TrayIcons[i] =
(HICON) LoadImage(hInst,
MAKEINTRESOURCE(idTrayIcons[i]),
IMAGE_ICON,
0, 0,
LR_DEFAULTCOLOR);
}
CTrayNotification * pNot =
new CTrayNotification(hWnd,
PWM_TRAYICON,
NIM_ADD,
g_TrayIcons[GREEN],
NULL);
if (pNot) {
if (FALSE == DeliverTrayNotification(pNot)) {
delete pNot;
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HMENU hPopMenu;
switch (message) {
case WM_SYSCOMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId) {
case IDM_SYS_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
return 0;
case IDM_SYS_SHOW_ALL:
if (GetMenuState(g_hMenu, IDM_SHOW_ALL,
MF_BYCOMMAND) == MF_CHECKED) {
CheckMenuItem(g_hMenu, IDM_SHOW_ALL, MF_UNCHECKED);
CheckMenuItem(hSysMenu, IDM_SYS_SHOW_ALL, MF_UNCHECKED);
} else {
CheckMenuItem(g_hMenu, IDM_SHOW_ALL, MF_CHECKED);
CheckMenuItem(hSysMenu, IDM_SYS_SHOW_ALL, MF_CHECKED);
}
GetWinStationInfo();
return 0;
}// end wmId
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId) {
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDR_POP_CLOSE:
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_SHOW_ALL:
if (GetMenuState(g_hMenu, IDM_SHOW_ALL,
MF_BYCOMMAND) == MF_CHECKED) {
CheckMenuItem(g_hMenu, IDM_SHOW_ALL, MF_UNCHECKED);
} else {
CheckMenuItem(g_hMenu, IDM_SHOW_ALL, MF_CHECKED);
}
GetWinStationInfo();
break;
case IDD_RESTORE:
ShowRunningInstance();
break;
case IDR_POP_MIN:
case IDD_MINIMIZE:
ShowWindow(hWnd, SW_MINIMIZE);
break;
case ID_FILE_REFRESH:
if (g_idWinstaThread) {
GetWinStationInfo();
}
break;
case IDR_POP_SND_MSG:
// make sure a user is selected
if (g_szSelectedSession[0] != 0 &&
_tcslen(g_szSelectedSession) > 7)
DialogBox(hInst, (LPCTSTR)IDD_MSG_DLG,
hWnd, (DLGPROC)SndMsg);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT rt;
GetClientRect(hWnd, &rt);
EndPaint(hWnd, &ps);
break;
case WM_NOTIFY:
{
switch (((LPNMHDR) lParam)->code) {
// display a popup menu for sending a message, closing app, etc.
case NM_RCLICK :
{
LPNMITEMACTIVATE lpnmitem;
lpnmitem = (LPNMITEMACTIVATE) lParam;
hPopMenu = LoadPopupMenu(hInst, IDR_POP);
ZeroMemory(g_szSelectedSession, MAX_LEN);
// get the session ID that the user clicked on.
ListView_GetItemText(g_hListView, lpnmitem->iItem, 1,
g_szSelectedSession, MAX_LEN);
if (g_szSelectedSession[0] != 0 &&
_tcslen(g_szSelectedSession) > 7) {
EnableMenuItem(hPopMenu,
IDR_POP_SND_MSG, MF_BYCOMMAND | MF_ENABLED);
} else {
EnableMenuItem(hPopMenu,
IDR_POP_SND_MSG, MF_BYCOMMAND | MF_GRAYED);
}
if (hPopMenu) {
POINT pt;
GetCursorPos(&pt);
SetForegroundWindow(hWnd);
TrackPopupMenuEx(hPopMenu, 0, pt.x, pt.y, hWnd, NULL);
DestroyMenu(hPopMenu);
}
break;
}
case NM_DBLCLK :
{
LPNMITEMACTIVATE lpnmitem;
lpnmitem = (LPNMITEMACTIVATE) lParam;
// get the session ID that the user clicked on.
ListView_GetItemText(g_hListView, lpnmitem->iItem, 1,
g_szSelectedSession, MAX_LEN);
// make sure a user is selected
if (g_szSelectedSession[0] != 0 &&
_tcslen(g_szSelectedSession) > 7)
DialogBox(hInst, (LPCTSTR)IDD_MSG_DLG,
hWnd, (DLGPROC)SndMsg);
break;
}
case LVN_COLUMNCLICK:
{
if (g_CurrentSortColumn == ((LPNMLISTVIEW)lParam)->iSubItem)
g_bAscending = !g_bAscending;
else
g_bAscending = TRUE;
g_CurrentSortColumn = ((LPNMLISTVIEW)lParam)->iSubItem;
if (g_idWinstaThread) GetWinStationInfo();
ListView_SortItems(g_hListView, Sort,
((LPNMLISTVIEW)lParam)->iSubItem);
}
break;
}
}
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS *lpwp;
RECT rc, rm;
lpwp = (LPWINDOWPOS) lParam;
// resize the list control.
GetClientRect(hWnd, &rc);
MoveWindow(
g_hListView, // handle to window
0, // horizontal position
0, // vertical position
rc.right - rc.left, //width
rc.bottom - rc.top, // height
TRUE);
// save window position and size.
if (! IsIconic(hWnd)) {
GetWindowRect(hWnd, &rm);
GetClientRect(hWnd, &rc);
MapWindowPoints(hWnd, NULL, (LPPOINT)&rc, 2);
SetRegKey(LEFT, &rm.left);
SetRegKey(TOP, &rm.top);
SetRegKey(RIGHT, &rc.right);
SetRegKey(BOTTOM, &rc.bottom);
} else {
ShowWindow(hWnd, SW_HIDE);
}
break;
}
// notifications from tray icon
case PWM_TRAYICON:
{
Tray_Notify(hWnd, wParam, lParam);
break;
}
// wake up and be shown
case PWM_ACTIVATE:
{
ShowRunningInstance();
break;
}
case WM_DESTROY:
{
TerminateThread(g_hWinstaThread, 0);
// Remove the tray icon
CTrayNotification * pNot =
new CTrayNotification(hWnd,
PWM_TRAYICON,
NIM_DELETE,
NULL,
NULL);
if (pNot) {
if (FALSE == DeliverTrayNotification(pNot)) {
delete pNot;
}
}
// If there's a tray thread, tell it to exit
EnterCriticalSection(&g_CSTrayThread);
if (g_idTrayThread) {
PostThreadMessage(g_idTrayThread, PM_QUITTRAYTHREAD, 0, 0);
}
LeaveCriticalSection(&g_CSTrayThread);
// Wait around for some period of time for the tray thread to
// do its cleanup work. If the wait times out, worst case we
// orphan the tray icon.
if (g_hTrayThread) {
#define TRAY_THREAD_WAIT 3000
WaitForSingleObject(g_hTrayThread, TRAY_THREAD_WAIT);
CloseHandle(g_hTrayThread);
}
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
// Mesage handler for send message dialog.
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK SndMsg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
DWORD pResponse;
TCHAR pTitle[MAX_LEN];
// user name variables
DWORD nSize;
TCHAR szBuf[MAX_LEN];
TCHAR pMessage[MAX_LEN];
static HWND hwndEditTitle;
static HWND hwndEditMessage;
PSID pSID;
DWORD dwGroupSIDCount = 0;
DWORD cbSID, dwError;
SID_NAME_USE snuGroup;
DWORD dwDomainSize = MAX_LEN;
TCHAR szDomainName[MAX_LEN];
LPTSTR pszGroupName[MAX_LEN];
switch (message) {
case WM_INITDIALOG:
{
hwndEditTitle = GetDlgItem(hDlg, IDC_EDIT_TITLE);
hwndEditMessage = GetDlgItem(hDlg, IDC_EDIT_MSG);
// get the user name
nSize = sizeof(szBuf);
GetUserName(szBuf, &nSize);
cbSID = GetSidLengthRequired (10);
pSID = ( PSID) malloc ( cbSID);
if (!pSID) {
return 0;
}
// get the user's domain
LookupAccountName ( NULL, szBuf, pSID,
&cbSID, szDomainName, &dwDomainSize, &snuGroup);
/*/
dwError = GetLastError();
if ( dwError == ERROR_INSUFFICIENT_BUFFER)
{
} else {
}
/*/
free(pSID);
pSID = NULL;
for (UINT i = 0; i < pCount; i++) {
// find the correct session ID
if (! _tcscmp(ppSessionInfo[i].pWinStationName,
g_szSelectedSession)) {
_tcscpy(pTitle, TEXT("Message from: "));
_tcscat(pTitle, szDomainName);
_tcscat(pTitle, "\\");
_tcscat(pTitle, szBuf);
SetWindowText(hwndEditTitle, pTitle);
}
}
return TRUE;
}
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId) {
case IDOK:
{
GetWindowText(hwndEditTitle, pTitle, MAX_LEN - 1);
GetWindowText(hwndEditMessage, pMessage, MAX_LEN - 1);
for (UINT i = 0; i < pCount; i++) {
// find the correct session ID
if (! _tcscmp(ppSessionInfo[i].pWinStationName,
g_szSelectedSession))
WTSSendMessage(
WTS_CURRENT_SERVER_HANDLE,
ppSessionInfo[i].SessionId,
pTitle,
sizeof(pTitle),
pMessage,
sizeof(pMessage),
MB_OK, // | MB_ICONEXCLAMATION,
30,
&pResponse,
FALSE); // don't wait for a response
}
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
int FillList(int nMcIndex)
{
LVITEM lvi;
LVFINDINFO lvfi;
int iListViewIndex, i;
TCHAR string[MAX_LEN];
TCHAR tmp[10];
// initialize tool tip variable
for (i = 0; i < MAX_PATH; i++) {
szTipText[i] = 0;
}
i = 0;
iItemCount = ListView_GetItemCount(g_hListView);
ListView_GetItemText(g_hListView, nMcIndex - 1, 0, string, MAX_LEN);
ListView_DeleteAllItems(g_hListView);
// fill the list with the stats for running machines
while (i < nMcIndex) {
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = (int) SendMessage(g_hListView, LVM_GETITEMCOUNT, 0, 0);
lvi.iSubItem = 0;
lvi.pszText = szMcNames[i];
lvi.cchTextMax = sizeof(szMcNames[i]);
_itot(i, tmp, 10);
lvi.lParam = (LPARAM) i; //(TCHAR *)tmp;
//lvi.lParam = (LPARAM) (TCHAR *)szMcNames[i];
lvfi.flags = LVFI_STRING;
lvfi.psz = szMcNames[i];
lvfi.lParam = 0;
lvfi.vkDirection = 0;
// get the index of the item, if it's there.
iListViewIndex = ListView_FindItem(g_hListView, -1, &lvfi);
// the if statement makes it so you don't get any duplicate names
// in the list control
//if (iListViewIndex == -1) {
int nPos;
// insert machine name
nPos = ListView_InsertItem(g_hListView, &lvi);
// insert time field
ListView_SetItemText(g_hListView, nPos, g_ColumnTwoIndex, szMcID[i]);
// insert machine type
ListView_SetItemText(g_hListView, nPos,
g_ColumnThreeIndex, szMcAddress[i]);
// insert machine type
ListView_SetItemText(g_hListView, nPos,
g_ColumnFourIndex, szBuild[i]);
/*
// write data to file
stream1 = fopen("c:\\WinSta.log", "a");
// write name to file
fputs(szMcNames[i], stream1);
// write ID field to file
for (x = 0; x < (40 - _tcslen(szMcNames[i])); x++) {
fputs(" ", stream1);
}
fputs(szMcID[i], stream1);
// write address to file
for (x = 0; x < (20 - _tcslen(szMcAddress[i])); x++) {
fputs(" ", stream1);
}
fputs(szMcAddress[i], stream1);
fputs("\n", stream1);
fclose(stream1);
*/
i++;
}
// count the current list elements and determine
// the icon to display
iItemCount = ListView_GetItemCount(g_hListView);
_itot(iItemCount, string, 10);
_tcscpy(szTipText, string);
_tcscat(szTipText, " session(s)");
if (iItemCount == 0) {
count = GREEN;
ShowMyIcon();
return 0;
}
if (iItemCount > 0 && iItemCount < 5) {
count = YELLOW;
ShowMyIcon();
return 0;
}
if (iItemCount > 5) {
count = RED;
ShowMyIcon();
return 0;
}
return 1;
}
//////////////////////////////////////////////////////////////////////////////
int CDECL MessageBoxPrintf(TCHAR *szCaption, TCHAR *szFormat, ...)
{
TCHAR szBuffer[MAX_STATIONS];
va_list pArgList;
va_start(pArgList, szFormat);
_vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR),
szFormat, pArgList);
va_end(pArgList);
return MessageBox(NULL, szBuffer, szCaption, 0);
}
//////////////////////////////////////////////////////////////////////////////
void ShowMyIcon()
{
CTrayNotification * pNot;
// change the light back to red if no servers are listed
switch (count) {
case GREEN:
pNot = new CTrayNotification(hWnd,
PWM_TRAYICON,
NIM_MODIFY,
g_TrayIcons[GREEN],
szTipText);
if (pNot) {
if (FALSE == DeliverTrayNotification(pNot))
delete pNot;
}
break;
case YELLOW:
pNot = new CTrayNotification(hWnd,
PWM_TRAYICON,
NIM_MODIFY,
g_TrayIcons[GREEN],
//g_TrayIcons[YELLOW],
szTipText);
if (pNot) {
if (FALSE == DeliverTrayNotification(pNot))
delete pNot;
}
break;
case RED:
pNot = new CTrayNotification(hWnd,
PWM_TRAYICON,
NIM_MODIFY,
g_TrayIcons[GREEN],
//g_TrayIcons[RED],
szTipText);
if (pNot) {
if (FALSE == DeliverTrayNotification(pNot))
delete pNot;
}
break;
}
}
//////////////////////////////////////////////////////////////////////////////
int CALLBACK Sort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamColumn)
{
TCHAR szItemString[MAX_LEN];
TCHAR szItemString2[MAX_LEN];
ListView_GetItemText(g_hListView, (INT)lParam1, (INT)lParamColumn,
szItemString, MAX_LEN);
ListView_GetItemText(g_hListView, (INT)lParam2, (INT)lParamColumn,
szItemString2, MAX_LEN);
if (g_bAscending == TRUE)
return strcmp(szItemString, szItemString2);
else
return -1 * strcmp(szItemString, szItemString2);
}
//////////////////////////////////////////////////////////////////////////////