Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

827 lines
21 KiB

/****************************************************************************
PROGRAM: xerox.c
PURPOSE: Copies keyboard input to multiple target windows.
****************************************************************************/
#include "xerox.h"
#include "string.h"
#include "group.h"
#include "pos.h"
// #define TESTING
static char pszMainWindowClass[] = "Main Window Class";
char szTitle[] = "Xerox";
HANDLE hInst;
HACCEL hAccel;
HWND hwndMain;
HWND hwndList; // handle of listbox containing targets.
BOOL InitApplication(HANDLE);
BOOL InitInstance(HANDLE, INT);
LONG APIENTRY MainWndProc(HWND, UINT, WPARAM, LONG);
BOOL PostToTargets(HWND, UINT, WPARAM, LONG);
BOOL APIENTRY WindowListDlgProc(HWND, UINT, WPARAM, LONG);
BOOL WindowListDlgInit(HWND);
BOOL CALLBACK WindowListWindowEnum(HWND, LONG);
HWND WindowListDlgEnd(HWND);
BOOL APIENTRY AboutDlgProc(HWND, UINT, WPARAM, LONG);
BOOL APIENTRY GroupAddDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL APIENTRY GroupDeleteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL APIENTRY GroupSelectDlgProc(HWND hDlg, UINT msg, WPARAM wParam,LPARAM lParam);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG Message;
if (!hPrevInstance) {
if (!InitApplication(hInstance)) {
DbgPrint("xerox - InitApplication failed\n");
return (FALSE);
}
}
if (!InitInstance(hInstance, nCmdShow)) {
DbgPrint("xerox - InitInstance failed\n");
return (FALSE);
}
while (GetMessage(&Message, NULL, 0, 0)) {
if (!TranslateAccelerator(hwndMain, hAccel, &Message)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
}
SaveGroups();
FreeGroups();
return (Message.wParam);
}
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(HANDLE hInstance)
{
WNDCLASS wc;
// Register the main window class
wc.style = 0;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = (LPSTR)IDM_MAINMENU;
wc.lpszClassName = pszMainWindowClass;
return (RegisterClass(&wc));
}
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(HANDLE hInstance, INT nCmdShow)
{
RECT rc;
BOOL fLastPosSet;
LoadGroups();
// Store instance in global
hInst = hInstance;
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCEL));
fLastPosSet = GetLastPosition(&rc);
// Create the main window
hwndMain = CreateWindow(
pszMainWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
fLastPosSet ? rc.left : CW_USEDEFAULT,
fLastPosSet ? rc.top : CW_USEDEFAULT,
fLastPosSet ? rc.right - rc.left : CW_USEDEFAULT,
fLastPosSet ? rc.bottom - rc.top : CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (hwndMain == NULL) {
return(FALSE);
}
if (GetCurrentGroup() != NULL) {
SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE);
}
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
return (TRUE);
}
/****************************************************************************
FUNCTION: MainWndProc(HWND, UINT, WPARAM, LONG)
PURPOSE: Processes messages for main window
COMMENTS:
****************************************************************************/
LONG APIENTRY MainWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LONG lParam)
{
HMENU hMenu;
BOOL Result;
RECT rcWindow;
HWND hwndAdd, hwndDelete;
CHAR string[MAX_STRING_BYTES];
INT ItemDelete;
INT TargetCount;
INT Index;
HWND hwndTarget;
WINDOWPLACEMENT wndpl;
switch (message) {
case WM_CREATE:
GetWindowRect(hwnd, &rcWindow);
if (GetCurrentGroup() != NULL) {
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup());
SetWindowText(hwnd, string);
}
hwndList = CreateWindow(
"LISTBOX",
NULL, // Title
WS_CHILD | WS_VISIBLE,
0, 0, // x,y
rcWindow.right - rcWindow.left,
rcWindow.bottom - rcWindow.top,
hwnd, // owner
NULL, // menu
hInst,
NULL);
ASSERT(hwndList != NULL);
//
// Attach all threads to our input state
//
#ifndef TESTING
Result = AttachThreadInput(
0,
GetCurrentThreadId(),
TRUE // Attaching
);
if (!Result) {
DbgPrint("Xerox: Failed to attach threads to our input state, error = %d\n", GetLastError());
}
#endif // !TESTING
return(0); // Continue creating window
case WM_INITMENU:
hMenu = (HMENU)wParam;
EnableMenuItem(hMenu, IDM_GROUPRSTWIN, GetCurrentGroup() != NULL ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenu, IDM_GROUPMINWIN, GetCurrentGroup() != NULL ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenu, IDM_GROUPDELETE, CountGroups() ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenu, IDM_GROUPSELECT, CountGroups() ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenu, IDM_TARGETDELETE,
(SendMessage(hwndList, LB_GETCURSEL, 0, 0) != LB_ERR) ?
MF_ENABLED : MF_GRAYED);
break;
case WM_SIZE:
//
// Keep the listbox in sync with the main window
//
MoveWindow(hwndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
return(0);
case WM_COMMAND:
switch (LOWORD(wParam)) {
/*
* Restore the windows of the current group. Assumes that everything
* can be restored.
*/
case IDM_GROUPRSTWIN:
TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0);
if (TargetCount == LB_ERR) {
break;
}
for (Index = 0; Index < TargetCount; Index ++) {
hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0);
ShowWindow(hwndTarget, SW_RESTORE);
}
SetFocus(hwndMain);
break;
/*
* Minimize the windows of the current group. Assumes that everything
* can be minimized.
*/
case IDM_GROUPMINWIN:
TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0);
if (TargetCount == LB_ERR) {
break;
}
for (Index = 0; Index < TargetCount; Index ++) {
hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0);
ShowWindow(hwndTarget, SW_MINIMIZE);
}
break;
case IDM_TARGETADD:
hwndAdd = (HWND)DialogBox(hInst,(LPSTR)IDD_WINDOWLIST, hwnd, WindowListDlgProc);
//
// If the window is already in our list, don't add it
//
if (FindLBData(hwndList, (DWORD)hwndAdd) >= 0) {
break;
}
//
// Don't add ourselves to the list
//
if (hwndAdd == hwnd) {
break;
}
//
// Add the window to the list
//
if (GetWindowText(hwndAdd, string, sizeof(string)) > 0) {
if (AddLBItemhwnd(hwndList, string, (LONG)hwndAdd) < 0) {
DbgPrint("Xerox: Failed to add window to listbox\n");
}
}
SetNoCurrentGroup(hwnd, szTitle);
break;
case IDM_TARGETDELETE:
ItemDelete = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
if (ItemDelete != LB_ERR) {
SendMessage(hwndList, LB_DELETESTRING, ItemDelete, 0);
}
SendMessage(hwndList, LB_SETCURSEL, max(0, ItemDelete - 1), 0);
SetNoCurrentGroup(hwnd, szTitle);
break;
case IDM_GROUPADD:
//
// Defines a 'group' of processes to equal the current target list
//
if (((LPSTR)DialogBox(hInst,
MAKEINTRESOURCE(IDD_GROUPADD),
hwnd,
GroupAddDlgProc)) != NULL) {
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup());
SetWindowText(hwnd, string);
}
break;
case IDM_GROUPDELETE:
DialogBox(hInst, MAKEINTRESOURCE(IDD_GROUPDELETE), hwnd, GroupDeleteDlgProc);
if (GetCurrentGroup() == NULL) {
SetWindowText(hwnd, szTitle);
} else {
SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE);
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup());
SetWindowText(hwnd, string);
}
break;
case IDM_GROUPSELECT:
if (DialogBox(hInst,
MAKEINTRESOURCE(IDD_GROUPSELECT),
hwnd,
GroupSelectDlgProc)) {
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup());
SetWindowText(hwnd, string);
}
break;
case IDM_REFRESHITEMS:
SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE);
break;
case IDM_ABOUT:
DialogBox(hInst,(LPSTR)IDD_ABOUT, hwnd, AboutDlgProc);
break;
default:
break;
}
break;
case WM_DESTROY:
//
// Detach all threads from our input state
//
#ifndef TESTING
Result = AttachThreadInput(
0,
GetCurrentThreadId(),
FALSE // Detaching
);
if (!Result) {
DbgPrint("Xerox: Failed to detach threads from our input state, error = %d\n", GetLastError());
}
#endif // !TESTING
GetWindowRect(hwndMain, &rcWindow);
SetLastPosition(&rcWindow);
PostQuitMessage(0);
break;
case WM_KEYUP:
case WM_KEYDOWN:
//
// Forward key messages to all targets
//
#ifndef TESTING
PostToTargets(hwndList, message, wParam, lParam);
#endif // !TESTING
// drop through to default processing...
default:
return(DefWindowProc(hwnd, message, wParam, lParam));
}
return 0;
}
/****************************************************************************
FUNCTION: PostToTargets(HWND)
PURPOSE: Posts a message to all target windows
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL PostToTargets(
HWND hwndList,
UINT message,
WPARAM wparam,
LONG lparam
)
{
INT TargetCount;
INT Index;
HWND hwndTarget;
BOOL Restarted = FALSE;
RestartPost:
TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0);
if (TargetCount == LB_ERR) {
return(FALSE);
}
for (Index = 0; Index < TargetCount; Index ++) {
hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0);
if ((hwndTarget != INVALID_HANDLE_VALUE) &&
!PostMessage(hwndTarget, message, wparam, lparam)) {
if (Restarted) {
return(FALSE);
}
if (!SelectGroupDefinition(GetCurrentGroup(), hwndList, TRUE)) {
return(FALSE);
}
Restarted = TRUE;
goto RestartPost;
}
}
return(TRUE);
}
/****************************************************************************
FUNCTION: WindowListDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
****************************************************************************/
BOOL APIENTRY WindowListDlgProc(hDlg, message, wParam, lParam)
HWND hDlg;
UINT message;
WPARAM wParam;
LONG lParam;
{
HWND hwndEdit = NULL;
switch (message) {
case WM_INITDIALOG:
if (!WindowListDlgInit(hDlg)) {
// Failed to initialize dialog, get out
EndDialog(hDlg, FALSE);
}
return (TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDLB_WINDOWLIST:
switch (HIWORD(wParam)) {
case LBN_DBLCLK:
break; // drop through
default:
return(0);
}
// drop through on double click ...
case IDOK:
hwndEdit = WindowListDlgEnd(hDlg);
// We're done, drop through to enddialog...
case IDCANCEL:
EndDialog(hDlg, (int)hwndEdit);
return TRUE;
break;
default:
// We didn't process this message
return FALSE;
break;
}
break;
default:
// We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
DBG_UNREFERENCED_PARAMETER(lParam);
}
/****************************************************************************
FUNCTION: WindowListDlgInit(HWND)
PURPOSE: Initialise the window list dialog
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL WindowListDlgInit(
HWND hDlg)
{
// Fill the list box with top-level windows and their handles
EnumWindows((FARPROC)WindowListWindowEnum, (LONG)hDlg);
return(TRUE);
}
/****************************************************************************
FUNCTION: WindowListWindowEnum
PURPOSE: Window enumeration call-back function.
Adds each window to the window list-box
RETURNS: TRUE to continue enumeration, FALSE to stop.
****************************************************************************/
BOOL CALLBACK WindowListWindowEnum(
HWND hwnd,
LONG lParam)
{
HWND hDlg = (HWND)lParam;
CHAR string[MAX_STRING_BYTES];
//
// Don't add ourselves to the list
//
if (hwnd == hDlg) {
return(TRUE);
}
//
// Don't add our main window to the list
//
if (hwnd == hwndMain) {
return(TRUE);
}
if (GetWindowText(hwnd, string, MAX_STRING_BYTES) != 0) {
// This window has a caption, so add it to the list-box
AddLBItem(hDlg, IDLB_WINDOWLIST, string, (LONG)hwnd);
}
return(TRUE);
}
/****************************************************************************
FUNCTION: WindowListDlgEnd(HWND)
PURPOSE: Cleans up after window list dialog
RETURNS: handle to window the user has selected or NULL
****************************************************************************/
HWND WindowListDlgEnd(
HWND hDlg)
{
HWND hwndListBox = GetDlgItem(hDlg, IDLB_WINDOWLIST);
HWND hwndEdit;
INT iItem;
// Read selection from list-box and get its hwnd
iItem = (INT)SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
if (iItem == LB_ERR) {
// No selection
hwndEdit = NULL;
} else {
hwndEdit = (HWND)SendMessage(hwndListBox, LB_GETITEMDATA, iItem, 0);
}
return (hwndEdit);
}
/****************************************************************************
FUNCTION: AboutDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for About dialog
****************************************************************************/
BOOL APIENTRY AboutDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LONG lParam)
{
switch (message) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
// we're done, drop through to quit dialog....
case IDCANCEL:
EndDialog(hDlg, TRUE);
return TRUE;
break;
default:
// We didn't process this message
return FALSE;
break;
}
break;
default:
// We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
DBG_UNREFERENCED_PARAMETER(lParam);
}
BOOL APIENTRY GroupAddDlgProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
char szName[MAX_STRING_BYTES];
int item;
switch (msg) {
case WM_INITDIALOG:
GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE);
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0);
return(TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (GetDlgItemText(hDlg, IDEF_GROUPNAME, szName, sizeof(szName)) > 0) {
if (!AddGroupDefinition(szName, hwndList)) {
EndDialog(hDlg, 0);
}
} else {
MessageBeep(0);
return(0);
}
EndDialog(hDlg, (LONG)GetCurrentGroup());
return(0);
case IDCANCEL:
EndDialog(hDlg, 0);
return(0);
case IDCB_GROUPLIST:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
item = SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETCURSEL, 0, 0);
if (item != CB_ERR) {
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT,
item, (LONG)szName);
SetDlgItemText(hDlg, IDEF_GROUPNAME, szName);
}
return(0);
}
break;
}
}
return(0);
}
BOOL APIENTRY GroupDeleteDlgProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
char szName[MAX_STRING_BYTES];
int item;
switch (msg) {
case WM_INITDIALOG:
GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE);
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0);
return(TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if ((item = SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETCURSEL, 0, 0)) != CB_ERR) {
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT,
item, (LONG)szName);
DeleteGroupDefinition(szName);
} else {
MessageBeep(0);
return(0);
}
EndDialog(hDlg, (LONG)szName);
return(0);
case IDCANCEL:
EndDialog(hDlg, 0);
return(0);
}
}
return(0);
}
BOOL APIENTRY GroupSelectDlgProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
char szName[MAX_STRING_BYTES];
int item;
switch (msg) {
case WM_INITDIALOG:
GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE);
if (GetCurrentGroup() != NULL) {
item = SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_FINDSTRING, (UINT)-1,
(LONG)(LPSTR)GetCurrentGroup());
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, item, 0);
} else {
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0);
}
return(TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if ((item = SendDlgItemMessage(hDlg, IDCB_GROUPLIST,
CB_GETCURSEL, 0, 0)) != CB_ERR) {
SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT,
item, (LONG)szName);
SelectGroupDefinition(szName, hwndList, FALSE);
} else {
MessageBeep(0);
return(0);
}
EndDialog(hDlg, (LONG)szName);
return(0);
case IDCANCEL:
EndDialog(hDlg, 0);
return(0);
}
}
return(0);
}