Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2522 lines
109 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
faxqueue.cpp
Abstract:
This module implements the fax queue viewer
Environment:
WIN32 User Mode
Author:
Wesley Witt (wesw) 9-june-1997
Steven Kehrli (steveke) 30-oct-1998 - major rewrite
--*/
#include "faxqueue.h"
HINSTANCE g_hInstance; // g_hInstance is the handle to the instance
HWND g_hWndMain; // g_hWndMain is the handle to the parent window
HWND g_hWndListView; // g_hWndListView is the handle to the list view window
HWND g_hWndToolbar; // g_hWndToolbar is the handle to the toolbar
LPTSTR g_szTitleConnected; // g_szTitleConnected is the window title when connected
LPTSTR g_szTitleNotConnected; // g_szTitleNotConnected is the window title when not connected
LPTSTR g_szTitleConnecting; // g_szTitleConnecting is the window title when connecting
LPTSTR g_szTitleRefreshing; // g_szTitleRefreshing is the window title when refreshing
LPTSTR g_szTitlePaused; // g_szTitlePaused is the window title when paused
LPTSTR g_szCurrentUserName; // g_szCurrentUserName is the name of the current user
HANDLE g_hStartEvent; // g_hStartEvent is the handle to an event indicating the fax event queue exists
HANDLE g_hExitEvent; // g_hExitEvent is the handle to an event indicating the application is exiting
LPTSTR g_szMachineName; // g_szMachineName is the machine to connect to
HANDLE g_hFaxSvcMutex; // g_hFaxSvcMutex is an object to synchronize access to the fax service routines
HANDLE g_hFaxSvcHandle; // g_hFaxSvcHandle is the handle to the fax service
LONG g_nNumConnections; // g_nNumConnections is the number of connections to the fax service
HANDLE g_hCompletionPort; // g_hCompletionPort is the handle to the completion port
WINPOSINFO WinPosInfo =
{
#ifdef DEBUG
FALSE,
#endif // DEBUG
#ifdef TOOLBAR_ENABLED
FALSE, // toolbar
#endif // TOOLBAR_ENABLED
TRUE, // status bar
200, // eDocumentName
80, // eJobType
80, // eStatus
80, // eOwner
60, // ePages
100, // eSize
140, // eScheduledTime
120, // ePort
{sizeof(WINDOWPLACEMENT), 0, SW_SHOWNORMAL, {0, 0}, {0, 0}, {50, 100, 695, 300}}
};
DWORD DocumentPropertiesHelpIDs[] =
{
IDC_FAX_DOCUMENTNAME, IDH_QUEUE_DOCUMENTNAME,
IDC_FAX_RECIPIENTINFO, IDH_QUEUE_RECIPIENTINFO,
IDC_FAX_RECIPIENTNAME_TEXT, IDH_QUEUE_RECIPIENTNAME,
IDC_FAX_RECIPIENTNAME, IDH_QUEUE_RECIPIENTNAME,
IDC_FAX_RECIPIENTNUMBER_TEXT, IDH_QUEUE_RECIPIENTNUMBER,
IDC_FAX_RECIPIENTNUMBER, IDH_QUEUE_RECIPIENTNUMBER,
IDC_FAX_SENDERINFO, IDH_QUEUE_SENDERINFO,
IDC_FAX_SENDERNAME_TEXT, IDH_QUEUE_SENDERNAME,
IDC_FAX_SENDERNAME, IDH_QUEUE_SENDERNAME,
IDC_FAX_SENDERCOMPANY_TEXT, IDH_QUEUE_SENDERCOMPANY,
IDC_FAX_SENDERCOMPANY, IDH_QUEUE_SENDERCOMPANY,
IDC_FAX_SENDERDEPT_TEXT, IDH_QUEUE_SENDERDEPT,
IDC_FAX_SENDERDEPT, IDH_QUEUE_SENDERDEPT,
IDC_FAX_BILLINGCODE_TEXT, IDH_QUEUE_BILLINGCODE,
IDC_FAX_BILLINGCODE, IDH_QUEUE_BILLINGCODE,
IDC_FAX_FAXINFO, IDH_QUEUE_FAXINFO,
IDC_FAX_JOBTYPE_TEXT, IDH_QUEUE_JOBTYPE,
IDC_FAX_JOBTYPE, IDH_QUEUE_JOBTYPE,
IDC_FAX_STATUS_TEXT, IDH_QUEUE_STATUS,
IDC_FAX_STATUS, IDH_QUEUE_STATUS,
IDC_FAX_PAGES_TEXT, IDH_QUEUE_PAGES,
IDC_FAX_PAGES, IDH_QUEUE_PAGES,
IDC_FAX_SIZE_TEXT, IDH_QUEUE_SIZE,
IDC_FAX_SIZE, IDH_QUEUE_SIZE,
IDC_FAX_SCHEDULEDTIME_TEXT, IDH_QUEUE_SCHEDULEDTIME,
IDC_FAX_SCHEDULEDTIME, IDH_QUEUE_SCHEDULEDTIME,
0, 0
};
// MainWndProc is the parent window procedure
LRESULT CALLBACK MainWndProc (HWND hWndMain, UINT iMsg, WPARAM wParam, LPARAM lParam);
// SelectFaxPrinterDlgProc is the select fax printer dialog procedure
INT_PTR CALLBACK SelectFaxPrinterDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
// DocumentPropertiesDlgProc is the select fax printer dialog procedure
INT_PTR CALLBACK DocumentPropertiesDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
// EnumThreadWndProc is the callback function for the EnumThreadWindows call
BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam);
// PostEventToCompletionPort posts an exit packet to a completion port
VOID PostEventToCompletionPort(HANDLE hCompletionPort, DWORD dwEventId, DWORD dwJobId);
// FaxEventThread is the thread to handle the fax events
DWORD FaxEventThread (LPVOID lpv);
extern "C"
int __cdecl
_tmain(
int argc,
LPTSTR argv[]
)
{
WNDCLASSEX wndclass;
MSG msg;
// bStarted indicates if the application has started
BOOL bStarted;
// szFormat is a format string
TCHAR szFormat[RESOURCE_STRING_LEN];
// szComputerName is the local computer name
LPTSTR szComputerName;
DWORD dwComputerNameSize;
// hThread is the handle to a thread
HANDLE hThread;
// hAccel is the handle to the accelerators
HACCEL hAccel;
DWORD dwReturn;
DWORD cb;
// Set g_hInstance
g_hInstance = GetModuleHandle(NULL);
// Set bStarted to FALSE to indicate the application has not started
bStarted = FALSE;
// Get the machine name
g_szMachineName = NULL;
if (argc == 2) {
// Allocate the memory for the machine name
g_szMachineName = (LPTSTR) MemAlloc((lstrlen(argv[1]) + 1) * sizeof(TCHAR));
if (g_szMachineName) {
// Copy the machine name
lstrcpy(g_szMachineName, argv[1]);
// Allocate the memory for the local computer name
dwComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
szComputerName = (LPTSTR) MemAlloc((MAX_COMPUTERNAME_LENGTH + 1) * sizeof(TCHAR));
if (szComputerName) {
// Get the local computer name
if (GetComputerName(szComputerName, &dwComputerNameSize)) {
// Compare the local computer name against the machine name
if (!lstrcmpi(g_szMachineName, szComputerName)) {
// Local computer name and machine name are the same, so set machine name to NULL
MemFree(g_szMachineName);
g_szMachineName = NULL;
}
}
MemFree(szComputerName);
}
}
}
// Set the window title when connected
if (g_szMachineName) {
// Convert the machine name to uppercase
g_szMachineName = CharUpper(g_szMachineName);
LoadString(g_hInstance, IDS_FAXQUEUE_REMOTE_CAPTION, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitleConnected = (LPTSTR) MemAlloc((lstrlen(szFormat) + lstrlen(g_szMachineName) + 1) * sizeof(TCHAR));
if (!g_szTitleConnected) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel0;
}
wsprintf(g_szTitleConnected, szFormat, g_szMachineName);
}
else {
LoadString(g_hInstance, IDS_FAXQUEUE_LOCAL_CAPTION, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitleConnected = (LPTSTR) MemAlloc((lstrlen(szFormat) + 1) * sizeof(TCHAR));
if (!g_szTitleConnected) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel0;
}
lstrcpy(g_szTitleConnected, szFormat);
}
// Set the window title when not connected
LoadString(g_hInstance, IDS_FAXQUEUE_NOT_CONNECTED, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitleNotConnected = (LPTSTR) MemAlloc((lstrlen(g_szTitleConnected) + lstrlen(szFormat) + 1) * sizeof(TCHAR));
if (!g_szTitleNotConnected) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel1;
}
lstrcpy(g_szTitleNotConnected, g_szTitleConnected);
lstrcat(g_szTitleNotConnected, szFormat);
// Set the window title when connecting
LoadString(g_hInstance, IDS_FAXQUEUE_CONNECTING, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitleConnecting = (LPTSTR) MemAlloc((lstrlen(g_szTitleConnected) + lstrlen(szFormat) + 1) * sizeof(TCHAR));
if (!g_szTitleConnecting) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel2;
}
lstrcpy(g_szTitleConnecting, g_szTitleConnected);
lstrcat(g_szTitleConnecting, szFormat);
// Set the window title when refreshing
LoadString(g_hInstance, IDS_FAXQUEUE_REFRESHING, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitleRefreshing = (LPTSTR) MemAlloc((lstrlen(g_szTitleConnected) + lstrlen(szFormat) + 1) * sizeof(TCHAR));
if (!g_szTitleRefreshing) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel3;
}
lstrcpy(g_szTitleRefreshing, g_szTitleConnected);
lstrcat(g_szTitleRefreshing, szFormat);
// Set the window title when paused
LoadString(g_hInstance, IDS_FAXQUEUE_PAUSED, szFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the window title
g_szTitlePaused = (LPTSTR) MemAlloc((lstrlen(g_szTitleConnected) + lstrlen(szFormat) + 1) * sizeof(TCHAR));
if (!g_szTitlePaused) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel4;
}
lstrcpy(g_szTitlePaused, g_szTitleConnected);
lstrcat(g_szTitlePaused, szFormat);
g_hWndMain = NULL;
// Find the window
g_hWndMain = FindWindow(FAXQUEUE_WINCLASS, g_szTitlePaused);
if (g_hWndMain) {
goto ExitLevel5;
}
// Find the window
g_hWndMain = FindWindow(FAXQUEUE_WINCLASS, g_szTitleRefreshing);
if (g_hWndMain) {
goto ExitLevel5;
}
// Find the window
g_hWndMain = FindWindow(FAXQUEUE_WINCLASS, g_szTitleConnecting);
if (g_hWndMain) {
goto ExitLevel5;
}
// Find the window
g_hWndMain = FindWindow(FAXQUEUE_WINCLASS, g_szTitleNotConnected);
if (g_hWndMain) {
goto ExitLevel5;
}
// Find the window
g_hWndMain = FindWindow(FAXQUEUE_WINCLASS, g_szTitleConnected);
if (g_hWndMain) {
goto ExitLevel5;
}
// Create the g_hStartEvent
g_hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!g_hStartEvent) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel5;
}
// Create the g_hExitEvent
g_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!g_hExitEvent) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel6;
}
// Initialize the fax service
g_hFaxSvcMutex = CreateMutex(NULL, FALSE, NULL);
if (!g_hFaxSvcMutex) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel7;
}
g_hFaxSvcHandle = NULL;
g_nNumConnections = 0;
hThread = CreateThread(NULL, 0, FaxEventThread, NULL, 0, NULL);
if (!hThread) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel8;
}
CloseHandle(hThread);
// Load the accelerators
hAccel = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCEL));
if (!hAccel) {
// Set the exit code
dwReturn = GetLastError();
goto ExitLevel9;
}
// Get the name of the current user
cb = 0;
GetUserName(NULL, &cb);
g_szCurrentUserName = (LPTSTR) MemAlloc((cb + 1) * sizeof(TCHAR));
if (!GetUserName(g_szCurrentUserName, &cb)) {
MemFree(g_szCurrentUserName);
g_szCurrentUserName = NULL;
}
// Retrieve the persistent data
GetFaxQueueRegistryData(&WinPosInfo);
// Initialize the common controls
InitCommonControls();
// Set bStarted to TRUE to indicate the application has started
bStarted = TRUE;
// Initialize the wndclass
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = g_hInstance;
wndclass.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_FAXQUEUE_ICON));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wndclass.lpszClassName = FAXQUEUE_WINCLASS;
wndclass.hIconSm = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_FAXQUEUE_ICON));
RegisterClassEx(&wndclass);
g_hWndMain = CreateWindow(FAXQUEUE_WINCLASS, g_szTitleConnecting, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL);
// Move and show the window
SetWindowPlacement(g_hWndMain, &WinPosInfo.WindowPlacement);
ShowWindow(g_hWndMain, SW_SHOWNORMAL);
UpdateWindow(g_hWndMain);
// Set the start event
SetEvent(g_hStartEvent);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(g_hWndMain, hAccel, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (g_szCurrentUserName) {
MemFree(g_szCurrentUserName);
}
ExitLevel9:
SetEvent(g_hExitEvent);
ExitLevel8:
CloseHandle(g_hFaxSvcMutex);
ExitLevel7:
CloseHandle(g_hExitEvent);
ExitLevel6:
CloseHandle(g_hStartEvent);
ExitLevel5:
if ((g_hWndMain) && (!bStarted)) {
// g_hWndMain is valid but the application has not started, so it must already be running
// Switch to that window
ShowWindow(g_hWndMain, SW_RESTORE);
SetForegroundWindow(g_hWndMain);
// Set the exit code
dwReturn = 0;
// Set bStarted to TRUE to indicate the application has started
bStarted = TRUE;
}
MemFree(g_szTitlePaused);
ExitLevel4:
MemFree(g_szTitleRefreshing);
ExitLevel3:
MemFree(g_szTitleConnecting);
ExitLevel2:
MemFree(g_szTitleNotConnected);
ExitLevel1:
MemFree(g_szTitleConnected);
ExitLevel0:
if (g_szMachineName) {
MemFree(g_szMachineName);
}
if (!bStarted) {
// szErrorCaption is the error caption if the application cannot start
TCHAR szErrorCaption[RESOURCE_STRING_LEN];
// szErrorFormat is the format of the error message if the application cannot start
TCHAR szErrorFormat[RESOURCE_STRING_LEN];
// szErrorReason is the error reason if the application cannot start
LPTSTR szErrorReason;
// szErrorMessage is the error message if the application cannot start
LPTSTR szErrorMessage;
// The application did not start so display an error message
// Load the error caption
LoadString(g_hInstance, IDS_ERROR_CAPTION, szErrorCaption, RESOURCE_STRING_LEN);
// Try to get the error message from the system message table
szErrorMessage = NULL;
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwReturn, 0, (LPTSTR) &szErrorReason, 0, NULL)) {
// Load the error format
LoadString(g_hInstance, IDS_ERROR_APP_FAILED_FORMAT, szErrorFormat, RESOURCE_STRING_LEN);
// Allocate the memory for the error message
szErrorMessage = (LPTSTR) MemAlloc((lstrlen(szErrorReason) + RESOURCE_STRING_LEN + 1) * sizeof(TCHAR));
if (szErrorMessage) {
// Set the error message
wsprintf(szErrorMessage, szErrorFormat, szErrorReason);
}
LocalFree(szErrorReason);
}
if (!szErrorMessage) {
// Allocate the memory for the error message
szErrorMessage = (LPTSTR) MemAlloc((RESOURCE_STRING_LEN) * sizeof(TCHAR));
if (szErrorMessage) {
// Load the error message
LoadString(g_hInstance, IDS_ERROR_APP_FAILED, szErrorMessage, RESOURCE_STRING_LEN);
}
}
if (szErrorMessage) {
// Display the error message
MessageBox(NULL, szErrorMessage, szErrorCaption, MB_OK | MB_ICONERROR | MB_APPLMODAL);
MemFree(szErrorMessage);
}
}
return dwReturn;
}
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// rcClient is the rectangle of the client area
RECT rcClient;
// hWndToolTips is the handle to the tool tips window
static HWND hWndToolTips;
// rcToolbar is the rectangle of the toolbar
static RECT rcToolbar;
// hWndStatusBar is the handle to the status bar
static HWND hWndStatusBar;
// rcStatusBar is the rectangle of the status bar
static RECT rcStatusBar;
// hFaxMenu is the handle to the fax menu
static HMENU hFaxMenu;
// hFaxSetAsDefaultMenu is the handle to the set as default printer menu
static HMENU hFaxSetAsDefaultMenu;
// hFaxSharingMenu is the handle to the sharing menu
static HMENU hFaxSharingMenu;
// hFaxPropertiesMenu is the handle to the properties menu
static HMENU hFaxPropertiesMenu;
// hDocumentMenu is the handle to the document menu
static HMENU hDocumentMenu;
// hViewMenu is the handle to the view menu
static HMENU hViewMenu;
// uCurrentMenu indicates the current menu selection
static UINT uCurrentMenu;
// pProcessInfoList is a pointer to the process info list
static PLIST_ENTRY pProcessInfoList;
switch (iMsg) {
case WM_CREATE:
// lvc specifies the attributes of a particular column of the list view
LV_COLUMN lvc;
// nColumnIndex is used to enumerate each column of the list view
INT nColumnIndex;
// szColumnHeader is the column header text
TCHAR szColumnHeader[RESOURCE_STRING_LEN];
// Set pProcessInfoList to NULL
pProcessInfoList = NULL;
// Get the handle to the fax menu
hFaxMenu = GetSubMenu(GetMenu(hWnd), 0);
// Initialize the set as default printer menu
hFaxSetAsDefaultMenu = NULL;
// Initialize the sharing menu
hFaxSharingMenu = NULL;
// Initialize the properties menu
hFaxPropertiesMenu = NULL;
// Disable the pause faxing menu item and the cancel all faxes menu item
EnableMenuItem(hFaxMenu, IDM_FAX_PAUSE_FAXING, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hFaxMenu, IDM_FAX_CANCEL_ALL_FAXES, MF_BYCOMMAND | MF_GRAYED);
#ifdef TOOLBAR_ENABLED
// Disable the pause faxing toolbar menu item and the cancel all faxes toolbar menu item
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_PAUSE_FAXING, FALSE);
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_CANCEL_ALL_FAXES, FALSE);
#endif // TOOLBAR_ENABLED
#ifdef WIN95
// Disable the sharing menu item
EnableMenuItem(hFaxMenu, 5, MF_BYPOSITION | MF_GRAYED);
// Disable the properties menu item
EnableMenuItem(hFaxMenu, 7, MF_BYPOSITION | MF_GRAYED);
#endif // WIN95
// Get the handle to the document menu
hDocumentMenu = GetSubMenu(GetMenu(hWnd), 1);
// Get the handle to the view menu
hViewMenu = GetSubMenu(GetMenu(hWnd), 2);
#ifdef TOOLBAR_ENABLED
// Set the toolbar
if (WinPosInfo.bToolbarVisible) {
// Show the toolbar
hWndToolTips = CreateToolTips(hWnd);
g_hWndToolbar = CreateToolbar(hWnd);
// Get the rectangle of the status bar
GetWindowRect(g_hWndToolbar, &rcToolbar);
}
else {
ZeroMemory(&rcToolbar, sizeof(rcToolbar));
}
// Check the menu item
CheckMenuItem(hViewMenu, IDM_VIEW_TOOLBAR, MF_BYCOMMAND | (WinPosInfo.bToolbarVisible ? MF_CHECKED : MF_UNCHECKED));
#else
ZeroMemory(&rcToolbar, sizeof(rcToolbar));
#endif // TOOLBAR_ENABLED
// Set the status bar
if (WinPosInfo.bStatusBarVisible) {
// Show the status bar
hWndStatusBar = CreateStatusWindow(WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE | SBARS_SIZEGRIP, NULL, hWnd, IDM_STATUS_BAR);
// Get the rectangle of the status bar
GetWindowRect(hWndStatusBar, &rcStatusBar);
}
else {
ZeroMemory(&rcStatusBar, sizeof(rcStatusBar));
}
// Check the menu item
CheckMenuItem(hViewMenu, IDM_VIEW_STATUS_BAR, MF_BYCOMMAND | (WinPosInfo.bStatusBarVisible ? MF_CHECKED : MF_UNCHECKED));
// Get the rectangle of the client area
GetClientRect(hWnd, &rcClient);
// Create the list view control
g_hWndListView = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE | LVS_REPORT, 0, (rcToolbar.bottom - rcToolbar.top), rcClient.right, rcClient.bottom - (rcStatusBar.bottom - rcStatusBar.top) - (rcToolbar.bottom - rcToolbar.top), hWnd, NULL, g_hInstance, NULL);
if (g_hWndListView) {
ListView_SetExtendedListViewStyle(g_hWndListView, LVS_EX_FULLROWSELECT);
// Set common attributes for each column
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
// Get the column header text
GetColumnHeaderText((eListViewColumnIndex) nColumnIndex, szColumnHeader);
// Set the column header text
lvc.pszText = szColumnHeader;
// Set the column width
lvc.cx = WinPosInfo.ColumnWidth[nColumnIndex];
// Set the column number
lvc.iSubItem = nColumnIndex;
// Insert column into list view
ListView_InsertColumn(g_hWndListView, lvc.iSubItem, &lvc);
}
SetFocus(g_hWndListView);
}
break;
case WM_MENUSELECT:
UINT uBase;
switch (LOWORD(wParam)) {
case IDM_FAX_SET_AS_DEFAULT_PRINTER_1:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_2:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_3:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_4:
wParam = MAKELONG(LOWORD(IDM_FAX_SET_AS_DEFAULT_PRINTER), HIWORD(wParam));
break;
case IDM_FAX_SHARING_1:
case IDM_FAX_SHARING_2:
case IDM_FAX_SHARING_3:
case IDM_FAX_SHARING_4:
wParam = MAKELONG(LOWORD(IDM_FAX_SHARING), HIWORD(wParam));
break;
case IDM_FAX_PROPERTIES_1:
case IDM_FAX_PROPERTIES_2:
case IDM_FAX_PROPERTIES_3:
case IDM_FAX_PROPERTIES_4:
wParam = MAKELONG(LOWORD(IDM_FAX_PROPERTIES), HIWORD(wParam));
break;
case IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE:
case IDM_FAX_SHARING_MORE:
case IDM_FAX_PROPERTIES_MORE:
wParam = MAKELONG(LOWORD(IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE), HIWORD(wParam));
break;
}
if (hWndStatusBar) {
uBase = IDS_MENU_BASE;
MenuHelp(iMsg, wParam, lParam, NULL, g_hInstance, hWndStatusBar, &uBase);
}
break;
case WM_INITMENUPOPUP:
if (((HMENU) wParam == hFaxMenu) && (LOWORD(lParam) == 0)) {
// mii is the menu item info
MENUITEMINFO mii;
// szMenuString is a menu string
TCHAR szMenuString[RESOURCE_STRING_LEN];
// dwNumOldMenuItems is the old number of menu items
DWORD dwNumOldMenuItems;
// dwNumNewMenuItems is the new number of menu items
DWORD dwNumNewMenuItems;
// pFaxPrintersConfig is the pointer to the fax printers
LPPRINTER_INFO_2 pFaxPrintersConfig;
// dwNumFaxPrinters is the number of fax printers
DWORD dwNumFaxPrinters;
// dwIndex is a counter to enumerate each menu and printer
DWORD dwIndex;
// dwDefaultIndex is the index of the default fax printer
DWORD dwDefaultIndex;
// szDefaultPrinterName is the default printer name
LPTSTR szDefaultPrinterName;
if ((WaitForSingleObject(g_hStartEvent, 0) != WAIT_TIMEOUT) && (ListView_GetItemCount(g_hWndListView))) {
// Enable the cancel all faxes menu item
EnableMenuItem(hFaxMenu, IDM_FAX_CANCEL_ALL_FAXES, MF_BYCOMMAND | MF_ENABLED);
}
else {
// Disable the cancel all faxes menu item
EnableMenuItem(hFaxMenu, IDM_FAX_CANCEL_ALL_FAXES, MF_BYCOMMAND | MF_GRAYED);
}
// Get the default printer
szDefaultPrinterName = GetDefaultPrinterName();
// Get the fax printers
pFaxPrintersConfig = (LPPRINTER_INFO_2) GetFaxPrinters(&dwNumFaxPrinters);
if ((pFaxPrintersConfig) && (dwNumFaxPrinters > 1)) {
// Many fax printers, so set menu items as sub-menus
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE | MIIM_SUBMENU;
mii.fState = MFS_ENABLED;
// Update the set as default printer menu item
if (!hFaxSetAsDefaultMenu) {
hFaxSetAsDefaultMenu = CreatePopupMenu();
mii.hSubMenu = hFaxSetAsDefaultMenu;
SetMenuItemInfo(hFaxMenu, IDM_FAX_SET_AS_DEFAULT_PRINTER, FALSE, &mii);
}
// Update the sharing menu item
if (!hFaxSharingMenu) {
hFaxSharingMenu = CreatePopupMenu();
mii.hSubMenu = hFaxSharingMenu;
SetMenuItemInfo(hFaxMenu, IDM_FAX_SHARING, FALSE, &mii);
}
// Update the properties menu item
if (!hFaxPropertiesMenu) {
hFaxPropertiesMenu = CreatePopupMenu();
mii.hSubMenu = hFaxPropertiesMenu;
SetMenuItemInfo(hFaxMenu, IDM_FAX_PROPERTIES, FALSE, &mii);
}
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;
mii.fType = MFT_STRING;
// Get the number of menu items
dwNumOldMenuItems = (DWORD) GetMenuItemCount(hFaxSetAsDefaultMenu);
// Insert the default fax printer first into the menus
for (dwDefaultIndex = dwNumFaxPrinters, dwNumNewMenuItems = 0; (szDefaultPrinterName) && (dwDefaultIndex > 0); dwDefaultIndex--) {
if (!lstrcmpi(szDefaultPrinterName, pFaxPrintersConfig[dwDefaultIndex - 1].pPrinterName)) {
// Set the menu string
wsprintf(szMenuString, TEXT("&%d %s"), dwNumNewMenuItems + 1, pFaxPrintersConfig[dwDefaultIndex - 1].pPrinterName);
mii.fState = MFS_CHECKED | MFS_ENABLED;
mii.dwTypeData = szMenuString;
// Insert the item into the set as default printer menu
mii.wID = IDM_FAX_SET_AS_DEFAULT_PRINTER_1;
InsertMenuItem(hFaxSetAsDefaultMenu, dwNumOldMenuItems, TRUE, &mii);
// Insert the item into the sharing menu
mii.wID = IDM_FAX_SHARING_1;
InsertMenuItem(hFaxSharingMenu, dwNumOldMenuItems, TRUE, &mii);
// Insert the item into the properties menu
mii.wID = IDM_FAX_PROPERTIES_1;
InsertMenuItem(hFaxPropertiesMenu, dwNumOldMenuItems, TRUE, &mii);
// Increment the number of new menu items
dwNumNewMenuItems++;
break;
}
}
// Propagate the menus with the list of fax printers
mii.fState = MFS_ENABLED;
for (dwIndex = 0; (dwIndex < dwNumFaxPrinters) && (dwNumNewMenuItems < (IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE - IDM_FAX_SET_AS_DEFAULT_PRINTER_1)); dwIndex++) {
if (dwIndex != (dwDefaultIndex - 1)) {
// Set the menu string
wsprintf(szMenuString, TEXT("&%d %s"), dwNumNewMenuItems + 1, pFaxPrintersConfig[dwIndex].pPrinterName);
mii.dwTypeData = szMenuString;
// Insert the item into the set as default printer menu
mii.wID = (IDM_FAX_SET_AS_DEFAULT_PRINTER_1 + dwNumNewMenuItems);
InsertMenuItem(hFaxSetAsDefaultMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
// Insert the item into the sharing menu
mii.wID = (IDM_FAX_SHARING_1 + dwNumNewMenuItems);
InsertMenuItem(hFaxSharingMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
// Insert the item into the properties menu
mii.wID = (IDM_FAX_PROPERTIES_1 + dwNumNewMenuItems);
InsertMenuItem(hFaxPropertiesMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
// Increment the number of new menu items
dwNumNewMenuItems++;
}
}
if (dwNumFaxPrinters > (IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE - IDM_FAX_SET_AS_DEFAULT_PRINTER_1)) {
// Finish the menus with the printers string
LoadString(g_hInstance, IDS_MENU_ITEM_FAX_PRINTERS, szMenuString, RESOURCE_STRING_LEN);
mii.dwTypeData = szMenuString;
// Insert the item into the set as default printer menu
mii.wID = IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE;
InsertMenuItem(hFaxSetAsDefaultMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
// Insert the item into the sharing menu
mii.wID = IDM_FAX_SHARING_MORE;
InsertMenuItem(hFaxSharingMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
// Insert the item into the properties menu
mii.wID = IDM_FAX_PROPERTIES_MORE;
InsertMenuItem(hFaxPropertiesMenu, (dwNumOldMenuItems + dwNumNewMenuItems), TRUE, &mii);
}
// Remove the old items from the set as default printer menu
for (dwIndex = 0; dwIndex < dwNumOldMenuItems; dwIndex++) {
DeleteMenu(hFaxSetAsDefaultMenu, 0, MF_BYPOSITION);
}
// Remove the old items from the sharing menu
for (dwIndex = 0; dwIndex < dwNumOldMenuItems; dwIndex++) {
DeleteMenu(hFaxSharingMenu, 0, MF_BYPOSITION);
}
// Remove the old items from the properties menu
for (dwIndex = 0; dwIndex < dwNumOldMenuItems; dwIndex++) {
DeleteMenu(hFaxPropertiesMenu, 0, MF_BYPOSITION);
}
}
else {
// One or zero fax printers, so set sub-menus as menu items
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE | MIIM_SUBMENU;
mii.hSubMenu = NULL;
// Update the set as default printer menu item
if (hFaxSetAsDefaultMenu) {
DestroyMenu(hFaxSetAsDefaultMenu);
hFaxSetAsDefaultMenu = NULL;
}
if ((pFaxPrintersConfig) && (dwNumFaxPrinters == 1) && (szDefaultPrinterName) && (!lstrcmpi(szDefaultPrinterName, pFaxPrintersConfig[0].pPrinterName))) {
mii.fState = MFS_CHECKED | MFS_ENABLED;
}
else {
mii.fState = (dwNumFaxPrinters == 1) ? MFS_ENABLED : MFS_GRAYED;
}
SetMenuItemInfo(hFaxMenu, IDM_FAX_SET_AS_DEFAULT_PRINTER, FALSE, &mii);
// Update the sharing menu item
if (hFaxSharingMenu) {
DestroyMenu(hFaxSharingMenu);
hFaxSharingMenu = NULL;
}
mii.fState = (dwNumFaxPrinters == 1) ? MFS_ENABLED : MFS_GRAYED;
SetMenuItemInfo(hFaxMenu, IDM_FAX_SHARING, FALSE, &mii);
// Update the properties menu item
if (hFaxPropertiesMenu) {
DestroyMenu(hFaxPropertiesMenu);
hFaxPropertiesMenu = NULL;
}
mii.fState = (dwNumFaxPrinters == 1) ? MFS_ENABLED : MFS_GRAYED;
SetMenuItemInfo(hFaxMenu, IDM_FAX_PROPERTIES, FALSE, &mii);
}
if (pFaxPrintersConfig) {
MemFree(pFaxPrintersConfig);
}
if (szDefaultPrinterName) {
MemFree(szDefaultPrinterName);
}
}
else if (((HMENU) wParam == hDocumentMenu) && (LOWORD(lParam) == 1)) {
if ((WaitForSingleObject(g_hStartEvent, 0) == WAIT_TIMEOUT) || (!ListView_GetSelectedCount(g_hWndListView))) {
// Disconnected or no items selected, so disable all menu items
// Disable the pause menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PAUSE, MF_BYCOMMAND | MF_GRAYED);
// Disable the resume menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESUME, MF_BYCOMMAND | MF_GRAYED);
// Disable the restart menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESTART, MF_BYCOMMAND | MF_GRAYED);
// Disable the cancel menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_CANCEL, MF_BYCOMMAND | MF_GRAYED);
// Disable the properties menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
}
else {
// uAndMask is the mask indicating the item attributes ANDed together
UINT uAndMask;
// uOrMask is the mask indicating the item attributes ORed together
UINT uOrMask;
// uState is the item's state
UINT uState;
// dwListIndex is the index of a particular item in the list view
DWORD dwListIndex;
// bUserHasAccess indicates the user has job manage access
BOOL bUserHasAccess;
// Initialize uAndMask
uAndMask = LVIS_OVERLAYMASK;
// Initialize uOrMask
uOrMask = 0;
// Enumerate each selected item in the list view
dwListIndex = ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_SELECTED);
while (dwListIndex != -1) {
// Get the item's attributes
uState = ListView_GetItemState(g_hWndListView, dwListIndex, LVIS_OVERLAYMASK);
// AND the item's attributes with uAndMask
uAndMask &= uState;
// OR the item's attributes with uOrMask
uOrMask |= uState;
dwListIndex = ListView_GetNextItem(g_hWndListView, dwListIndex, LVNI_ALL | LVNI_SELECTED);
}
if (uAndMask & ITEM_USEROWNSJOB_MASK) {
// User owns all of the jobs
bUserHasAccess = TRUE;
}
else {
// User does not own all of the jobs, so determine if user has job manage permission
// Initialize bUserHasAccess to FALSE
bUserHasAccess = FALSE;
// Connect to the fax service
if (Connect()) {
// Get the user's job manage access
bUserHasAccess = FaxAccessCheck(g_hFaxSvcHandle, FAX_JOB_MANAGE);
// Disconnect from the fax service
Disconnect();
}
}
if (((uAndMask & ITEM_SEND_MASK) == 0) || ((uAndMask & ITEM_IDLE_MASK) == 0)) {
// Not a send job or a send job in progress, so disable the pause, resume and restart menu items
// Disable the pause menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PAUSE, MF_BYCOMMAND | MF_GRAYED);
// Disable the resume menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESUME, MF_BYCOMMAND | MF_GRAYED);
// Disable the restart menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESTART, MF_BYCOMMAND | MF_GRAYED);
}
else if (uAndMask & ITEM_PAUSED_MASK) {
// Idle send job that is paused, so enable the resume and restart menu items and disable the pause menu item
// Disable the pause menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PAUSE, MF_BYCOMMAND | MF_GRAYED);
// Enable the resume menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESUME, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
// Enable the restart menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESTART, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
}
else if ((uOrMask & ITEM_PAUSED_MASK) == 0) {
// Idle send job that is not paused, so enable the pause and restart menu items and disable the resume menu item
// Enable the pause menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PAUSE, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
// Disable the resume menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESUME, MF_BYCOMMAND | MF_GRAYED);
// Enable the restart menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESTART, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
}
else {
// Idle send job, so enable the restart menu item and disable the pause and resume menu items
// Enable the pause menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PAUSE, MF_BYCOMMAND | MF_GRAYED);
// Disable the resume menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESUME, MF_BYCOMMAND | MF_GRAYED);
// Enable the restart menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_RESTART, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
}
// Enable the cancel menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_CANCEL, MF_BYCOMMAND | (bUserHasAccess ? MF_ENABLED : MF_GRAYED));
if (ListView_GetSelectedCount(g_hWndListView) == 1) {
// Only one item selected, so enable the properties menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PROPERTIES, MF_BYCOMMAND | MF_ENABLED);
}
else {
// Multiple items selected, so disable the properties menu item
EnableMenuItem(hDocumentMenu, IDM_DOCUMENT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
}
}
}
break;
case WM_NOTIFY:
LPNMHDR pnmhdr;
// dwMessagePos is the cursor position for the message
DWORD dwMessagePos;
pnmhdr = (LPNMHDR) lParam;
if ((pnmhdr->hwndFrom == g_hWndListView) && (pnmhdr->code == NM_RCLICK)) {
// User has right-clicked in the list view, so display the document context menu
// Initialize the document menu
SendMessage(g_hWndMain, WM_INITMENUPOPUP, (WPARAM) hDocumentMenu, MAKELPARAM(1, FALSE));
// Get the cursor position
dwMessagePos = GetMessagePos();
// Display the document context menu
TrackPopupMenu(hDocumentMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, LOWORD(dwMessagePos), HIWORD(dwMessagePos), 0, g_hWndMain, NULL);
}
else if ((pnmhdr->hwndFrom == g_hWndListView) && (pnmhdr->code == NM_DBLCLK)) {
// rcItem is the rectangle of the item
RECT rcItem;
// User has double-clicked in the list view, so display the job properties
if (ListView_GetSelectedCount(g_hWndListView) != 1) {
break;
}
// Get the item's bounding rectangle
if (ListView_GetItemRect(g_hWndListView, ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_SELECTED), &rcItem, LVIR_BOUNDS)) {
// Get the cursor position
dwMessagePos = GetMessagePos();
// Get the window rectangle of the list view
GetWindowRect(g_hWndListView, &rcClient);
// Adjust dwMessagePos to indicate the cursor position within the list view
dwMessagePos = MAKELONG(LOWORD(dwMessagePos) - rcClient.left, HIWORD(dwMessagePos) - rcClient.top);
if ((LOWORD(dwMessagePos) >= rcItem.left) && (LOWORD(dwMessagePos) <= rcItem.right) && (HIWORD(dwMessagePos) >= rcItem.top) && (HIWORD(dwMessagePos) <= rcItem.bottom)) {
// Display the job properties
SendMessage(g_hWndMain, WM_COMMAND, MAKEWPARAM(IDM_DOCUMENT_PROPERTIES, 0), 0);
}
}
}
#ifdef TOOLBAR_ENABLED
else if (pnmhdr->code == TTN_NEEDTEXT) {
// pToolTipText is the pointer to the tool tip text structure
LPTOOLTIPTEXT pToolTipText;
// szToolTip is the tool tip text
TCHAR szToolTip[RESOURCE_STRING_LEN];
pToolTipText = (LPTOOLTIPTEXT) lParam;
switch (pToolTipText->hdr.idFrom) {
case IDM_FAX_PAUSE_FAXING:
LoadString(g_hInstance, IDS_MENU_FAX_PAUSE_FAXING, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_FAX_CANCEL_ALL_FAXES:
LoadString(g_hInstance, IDS_MENU_FAX_CANCEL_ALL_FAXES, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_DOCUMENT_PAUSE:
LoadString(g_hInstance, IDS_MENU_DOCUMENT_PAUSE, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_DOCUMENT_RESUME:
LoadString(g_hInstance, IDS_MENU_DOCUMENT_PAUSE, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_DOCUMENT_RESTART:
LoadString(g_hInstance, IDS_MENU_DOCUMENT_RESTART, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_DOCUMENT_CANCEL:
LoadString(g_hInstance, IDS_MENU_DOCUMENT_CANCEL, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_DOCUMENT_PROPERTIES:
LoadString(g_hInstance, IDS_MENU_DOCUMENT_PROPERTIES, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_VIEW_REFRESH:
LoadString(g_hInstance, IDS_MENU_VIEW_REFRESH, szToolTip, RESOURCE_STRING_LEN);
break;
case IDM_HELP_TOPICS:
LoadString(g_hInstance, IDS_MENU_HELP_TOPICS, szToolTip, RESOURCE_STRING_LEN);
break;
default:
ZeroMemory(szToolTip, sizeof(szToolTip));
break;
}
pToolTipText->lpszText = szToolTip;
}
#endif // TOOLBAR_ENABLED
break;
case WM_SETFOCUS:
SetFocus(g_hWndListView);
break;
case WM_SIZE:
#ifdef TOOLBAR_ENABLED
// Resize the toolbar
if (WinPosInfo.bToolbarVisible) {
SendMessage(g_hWndToolbar, iMsg, wParam, lParam);
}
#endif // TOOLBAR_ENABLED
// Resize the status bar
if (WinPosInfo.bStatusBarVisible) {
SendMessage(hWndStatusBar, iMsg, wParam, lParam);
}
// Get the rectangle of the client area
GetClientRect(hWnd, &rcClient);
// Resize the list view
MoveWindow(g_hWndListView, 0, (rcToolbar.bottom - rcToolbar.top), rcClient.right, rcClient.bottom - (rcStatusBar.bottom - rcStatusBar.top) - (rcToolbar.bottom - rcToolbar.top), TRUE);
break;
case UM_SELECT_FAX_PRINTER:
// szCommandLine is the command line
TCHAR szCommandLine[MAX_PATH];
// si is the startup info for the print ui
STARTUPINFO si;
// pi is the process info for the print ui
PROCESS_INFORMATION pi;
// hWndPrintUI is the handle to the print ui window
HWND hWndPrintUI;
// pProcessInfoItem is a pointer to a PROCESS_INFO_ITEM structure
PPROCESS_INFO_ITEM pProcessInfoItem;
// szErrorCaption is the error caption if CreateProcess() fails
TCHAR szErrorCaption[RESOURCE_STRING_LEN];
// szErrorMessage is the error message if CreateProcess() fails
LPTSTR szErrorMessage;
if (uCurrentMenu == IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE) {
// Set the default printer
SetDefaultPrinterName((LPTSTR) wParam);
MemFree((LPBYTE) wParam);
uCurrentMenu = 0;
return 0;
}
if (pProcessInfoList) {
// See if print ui is already open
pProcessInfoItem = (PPROCESS_INFO_ITEM) pProcessInfoList;
while (TRUE) {
if (!lstrcmpi((LPTSTR) wParam, pProcessInfoItem->szPrinterName)) {
// Printer name matches, so print ui may still be open
if (WaitForSingleObject(pProcessInfoItem->hProcess, 0) != WAIT_OBJECT_0) {
// Print ui is still open
ShowWindow(pProcessInfoItem->hWnd, SW_SHOWNORMAL);
SetForegroundWindow(pProcessInfoItem->hWnd);
return 0;
}
if (pProcessInfoItem == (PPROCESS_INFO_ITEM) pProcessInfoList) {
pProcessInfoList = pProcessInfoItem->ListEntry.Blink;
}
if (IsListEmpty(pProcessInfoList)) {
// This is the last item in the list, so set the list head to NULL
pProcessInfoList = NULL;
}
else {
// Remove the process info item from the list
RemoveEntryList(&pProcessInfoItem->ListEntry);
}
// Free the process info item
MemFree(pProcessInfoItem);
break;
}
// Step to the next process info item
pProcessInfoItem = (PPROCESS_INFO_ITEM) pProcessInfoItem->ListEntry.Blink;
if (pProcessInfoItem == (PPROCESS_INFO_ITEM) pProcessInfoList) {
// The list has been traversed
break;
}
}
}
switch (uCurrentMenu) {
case IDM_FAX_SHARING_MORE:
// Set the parameters
wsprintf(szCommandLine, TEXT("rundll32 printui.dll,PrintUIEntry /p /t1 /n \"%s\""), (LPTSTR) wParam);
break;
case IDM_FAX_PROPERTIES_MORE:
// Set the parameters
wsprintf(szCommandLine, TEXT("rundll32 printui.dll,PrintUIEntry /p /t0 /n \"%s\""), (LPTSTR) wParam);
break;
}
// Initialize si
ZeroMemory(&si, sizeof(si));
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_NORMAL;
// Initialize pi
ZeroMemory(&pi, sizeof(pi));
// Launch the print ui
hWndPrintUI = NULL;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi)) {
// Find the print ui window
do {
Sleep(250);
EnumThreadWindows(pi.dwThreadId, EnumThreadWndProc, (LPARAM) &hWndPrintUI);
} while (hWndPrintUI == NULL);
SetCursor(LoadCursor(NULL, IDC_ARROW));
// Add the process info item to the list
pProcessInfoItem = (PPROCESS_INFO_ITEM) MemAlloc(sizeof(PROCESS_INFO_ITEM) + (lstrlen((LPTSTR) wParam) + 1) * sizeof(TCHAR));
if (pProcessInfoItem) {
// Set szPrinterName
pProcessInfoItem->szPrinterName = (LPTSTR) ((UINT_PTR) pProcessInfoItem + sizeof(PROCESS_INFO_ITEM));
// Copy szPrinterName
lstrcpy(pProcessInfoItem->szPrinterName, (LPTSTR) wParam);
// Copy hProcess
pProcessInfoItem->hProcess = pi.hProcess;
// Copy hWndPrintUI
pProcessInfoItem->hWnd = hWndPrintUI;
// Insert the process info item into the list
if (pProcessInfoList) {
InsertTailList(pProcessInfoList, &pProcessInfoItem->ListEntry);
}
else {
pProcessInfoList = &pProcessInfoItem->ListEntry;
InitializeListHead(pProcessInfoList);
}
}
}
else {
// CreateProcess() failed, so display an error message
SetCursor(LoadCursor(NULL, IDC_ARROW));
// Load the error caption
LoadString(g_hInstance, IDS_ERROR_CAPTION, szErrorCaption, RESOURCE_STRING_LEN);
// Try to get the error message from the system message table
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, (LPTSTR) &szErrorMessage, 0, NULL)) {
// Display the error message
MessageBox(hWnd, szErrorMessage, szErrorCaption, MB_OK | MB_ICONERROR | MB_APPLMODAL);
LocalFree(szErrorMessage);
}
else {
// Allocate the memory for the error message
szErrorMessage = (LPTSTR) MemAlloc((RESOURCE_STRING_LEN) * sizeof(TCHAR));
if (szErrorMessage) {
// Load the error message
LoadString(g_hInstance, IDS_ERROR_PRINTER_PROPERTIES, szErrorMessage, RESOURCE_STRING_LEN);
// Display the error message
MessageBox(hWnd, szErrorMessage, szErrorCaption, MB_OK | MB_ICONERROR | MB_APPLMODAL);
MemFree(szErrorMessage);
}
}
}
MemFree((LPBYTE) wParam);
uCurrentMenu = 0;
break;
case WM_COMMAND:
// mii is the menu item info
MENUITEMINFO mii;
// szPrinterName is the printer name
LPTSTR szPrinterName;
// pFaxJobEntry is the pointer to the fax jobs
PFAX_JOB_ENTRY pFaxJobEntry;
// lvi specifies the attributes of a particular item in the list view
LV_ITEM lvi;
// dwListIndex is the index of a particular item in the list view
DWORD dwListIndex;
switch (LOWORD(wParam)) {
case IDM_FAX_PAUSE_FAXING:
// pFaxConfig is the pointer to the fax configuration
PFAX_CONFIGURATION pFaxConfig;
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fState = 0;
// Get the size of the menu item
if (!GetMenuItemInfo(hFaxMenu, IDM_FAX_PAUSE_FAXING, FALSE, &mii)) {
break;
}
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (Connect()) {
// Get the fax configuration
if (FaxGetConfiguration(g_hFaxSvcHandle, &pFaxConfig)) {
// Toggle the pause faxing status
pFaxConfig->PauseServerQueue = mii.fState & MFS_CHECKED ? FALSE : TRUE;
// Set the fax configuration
if (FaxSetConfiguration(g_hFaxSvcHandle, pFaxConfig)) {
// Check the menu item
CheckMenuItem(hFaxMenu, IDM_FAX_PAUSE_FAXING, MF_BYCOMMAND | (pFaxConfig->PauseServerQueue ? MF_CHECKED : MF_UNCHECKED));
#ifdef TOOLBAR_ENABLED
// Enable the pause faxing toolbar menu item
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_PAUSE_FAXING, pFaxConfig->PauseServerQueue);
#endif // TOOLBAR_ENABLED
}
FaxFreeBuffer(pFaxConfig);
}
Disconnect();
}
// Set the window title to indicate connected or paused
SetWindowText(hWnd, mii.fState & MFS_CHECKED ? g_szTitleConnected : g_szTitlePaused);
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case IDM_FAX_CANCEL_ALL_FAXES:
// dwNumFaxJobs is the number of fax jobs
DWORD dwNumFaxJobs;
// dwIndex is a counter to enumerate each fax job
DWORD dwIndex;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (Connect()) {
// Enumerate the fax jobs
if (FaxEnumJobs(g_hFaxSvcHandle, &pFaxJobEntry, &dwNumFaxJobs)) {
// Enumerate and cancel each fax job
for (dwIndex = 0; dwIndex < dwNumFaxJobs; dwIndex++) {
FaxSetJob(g_hFaxSvcHandle, pFaxJobEntry[dwIndex].JobId, JC_DELETE, &pFaxJobEntry[dwIndex]);
}
FaxFreeBuffer(pFaxJobEntry);
}
Disconnect();
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case IDM_FAX_CLOSE:
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
case IDM_DOCUMENT_PAUSE:
case IDM_DOCUMENT_RESUME:
case IDM_DOCUMENT_RESTART:
case IDM_DOCUMENT_CANCEL:
// pJobIdList is a pointer to the job id list
PLIST_ENTRY pJobIdList;
// JobIdItem is a JOB_ID_ITEM structure
PJOB_ID_ITEM pJobIdItem;
// FaxJobEntry is the fax job
FAX_JOB_ENTRY FaxJobEntry;
// dwCommand is the command to set the fax job entry
DWORD dwCommand;
switch (LOWORD(wParam)) {
case IDM_DOCUMENT_PAUSE:
dwCommand = JC_PAUSE;
break;
case IDM_DOCUMENT_RESUME:
dwCommand = JC_RESUME;
break;
case IDM_DOCUMENT_RESTART:
dwCommand = JC_RESTART;
break;
case IDM_DOCUMENT_CANCEL:
dwCommand = JC_DELETE;
break;
}
// Set pJobIdList to NULL
pJobIdList = NULL;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (Connect()) {
// Initialize FaxJobEntry
ZeroMemory(&FaxJobEntry, sizeof(FaxJobEntry));
FaxJobEntry.SizeOfStruct = sizeof(FaxJobEntry);
// Enumerate each selected item in the list view
dwListIndex = ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_SELECTED);
while (dwListIndex != -1) {
// Initialize lvi
lvi.mask = LVIF_PARAM;
// Set the item number
lvi.iItem = dwListIndex;
// Set the subitem number
lvi.iSubItem = 0;
// Set the lParam
lvi.lParam = 0;
// Get the selected item from the list view
if (ListView_GetItem(g_hWndListView, &lvi)) {
// Add the job id item to the list
pJobIdItem = (PJOB_ID_ITEM) MemAlloc(sizeof(JOB_ID_ITEM));
if (pJobIdItem) {
// Copy dwJobId
pJobIdItem->dwJobId = (DWORD) lvi.lParam;
// Insert the job id item into the list
if (pJobIdList) {
InsertTailList(pJobIdList, &pJobIdItem->ListEntry);
}
else {
pJobIdList = &pJobIdItem->ListEntry;
InitializeListHead(pJobIdList);
}
}
}
dwListIndex = ListView_GetNextItem(g_hWndListView, dwListIndex, LVNI_ALL | LVNI_SELECTED);
}
while (pJobIdList) {
// Get the job id item from the list
pJobIdItem = (PJOB_ID_ITEM) pJobIdList;
// Set FaxJobEntry
FaxJobEntry.JobId = pJobIdItem->dwJobId;
// Set the fax job entry
if (FaxSetJob(g_hFaxSvcHandle, FaxJobEntry.JobId, dwCommand, &FaxJobEntry)) {
if (LOWORD(wParam) != IDM_DOCUMENT_CANCEL) {
// Post an event to the completion port to indicate thread is to refresh
PostEventToCompletionPort(g_hCompletionPort, (DWORD) -1, FaxJobEntry.JobId);
}
}
// Set the head of the job id item list to the next job id item in the list
pJobIdList = pJobIdItem->ListEntry.Blink;
if (IsListEmpty(pJobIdList)) {
// This is the last item in the list, so set the list head to NULL
pJobIdList = NULL;
}
else {
// Remove the job id item from the list
RemoveEntryList(&pJobIdItem->ListEntry);
}
// Free the job id item
MemFree(pJobIdItem);
}
Disconnect();
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
case IDM_DOCUMENT_PROPERTIES:
// PropSheetHeader is the property sheet header
PROPSHEETHEADER PropSheetHeader;
// PropSheetPage is the property sheet page
PROPSHEETPAGE PropSheetPage;
// Set pJobIdList to NULL
pJobIdList = NULL;
// Initialize PropSheetHeader
PropSheetHeader.dwSize = sizeof(PropSheetHeader);
// Set the property sheet header flags
PropSheetHeader.dwFlags = PSH_NOAPPLYNOW | PSH_PROPSHEETPAGE | PSH_PROPTITLE;
// Set the property sheet header owner window
PropSheetHeader.hwndParent = hWnd;
// Set the property sheet header hInstance
PropSheetHeader.hInstance = g_hInstance;
// Set the number of property sheet pages
PropSheetHeader.nPages = 1;
// Set the start property sheet page
PropSheetHeader.nStartPage = 0;
PropSheetHeader.pStartPage = NULL;
// Set the property sheet pages
PropSheetHeader.ppsp = &PropSheetPage;
// Initialize PropSheetPage
PropSheetPage.dwSize = sizeof(PropSheetPage);
// Set the property sheet page flags
PropSheetPage.dwFlags = 0;
// Set the property sheet page hInstance
PropSheetPage.hInstance = g_hInstance;
// Set the property sheet page dialog template
PropSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_DOCUMENT_PROPERTIES);
// Set the property sheet page dialog procedure
PropSheetPage.pfnDlgProc = DocumentPropertiesDlgProc;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if (Connect()) {
// Enumerate each selected item in the list view
dwListIndex = ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_SELECTED);
while (dwListIndex != -1) {
// Initialize lvi
lvi.mask = LVIF_PARAM;
// Set the item number
lvi.iItem = dwListIndex;
// Set the subitem number
lvi.iSubItem = 0;
// Set the lParam
lvi.lParam = 0;
// Get the selected item from the list view
if (ListView_GetItem(g_hWndListView, &lvi)) {
// Add the job id item to the list
pJobIdItem = (PJOB_ID_ITEM) MemAlloc(sizeof(JOB_ID_ITEM));
if (pJobIdItem) {
// Copy dwJobId
pJobIdItem->dwJobId = (DWORD) lvi.lParam;
// Insert the job id item into the list
if (pJobIdList) {
InsertTailList(pJobIdList, &pJobIdItem->ListEntry);
}
else {
pJobIdList = &pJobIdItem->ListEntry;
InitializeListHead(pJobIdList);
}
}
}
dwListIndex = ListView_GetNextItem(g_hWndListView, dwListIndex, LVNI_ALL | LVNI_SELECTED);
}
while (pJobIdList) {
// Get the job id item from the list
pJobIdItem = (PJOB_ID_ITEM) pJobIdList;
if (FaxGetJob(g_hFaxSvcHandle, pJobIdItem->dwJobId, &pFaxJobEntry)) {
// Set the property sheet header pszCaption
PropSheetHeader.pszCaption = pFaxJobEntry->DocumentName;
// Set the property sheet page lParam
PropSheetPage.lParam = (LPARAM) pFaxJobEntry;
// Create the property sheet
PropertySheet(&PropSheetHeader);
}
// Set the head of the job id item list to the next job id item in the list
pJobIdList = pJobIdItem->ListEntry.Blink;
if (IsListEmpty(pJobIdList)) {
// This is the last item in the list, so set the list head to NULL
pJobIdList = NULL;
}
else {
// Remove the job id item from the list
RemoveEntryList(&pJobIdItem->ListEntry);
}
// Free the job id item
MemFree(pJobIdItem);
}
Disconnect();
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
#ifdef TOOLBAR_ENABLED
case IDM_VIEW_TOOLBAR:
if (WinPosInfo.bToolbarVisible) {
// Close the toolbar
DestroyWindow(g_hWndToolbar);
DestroyWindow(hWndToolTips);
ZeroMemory(&rcToolbar, sizeof(rcToolbar));
}
else {
// Show the toolbar
hWndToolTips = CreateToolTips(hWnd);
g_hWndToolbar = CreateToolbar(hWnd);
// Get the rectangle of the toolbar
GetWindowRect(g_hWndToolbar, &rcToolbar);
}
WinPosInfo.bToolbarVisible = !WinPosInfo.bToolbarVisible;
// Check the menu item
CheckMenuItem(hViewMenu, IDM_VIEW_TOOLBAR, MF_BYCOMMAND | (WinPosInfo.bToolbarVisible ? MF_CHECKED : MF_UNCHECKED));
// Get the rectangle of the client area
GetClientRect(hWnd, &rcClient);
// Resize the list view
MoveWindow(g_hWndListView, 0, (rcToolbar.bottom - rcToolbar.top), rcClient.right, rcClient.bottom - (rcStatusBar.bottom - rcStatusBar.top) - (rcToolbar.bottom - rcToolbar.top), TRUE);
break;
#endif // TOOLBAR_ENABLED
case IDM_VIEW_STATUS_BAR:
if (WinPosInfo.bStatusBarVisible) {
// Close the status bar
DestroyWindow(hWndStatusBar);
ZeroMemory(&rcStatusBar, sizeof(rcStatusBar));
}
else {
// Show the status bar
hWndStatusBar = CreateStatusWindow(WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE | SBARS_SIZEGRIP, NULL, hWnd, IDM_STATUS_BAR);
// Get the rectangle of the status bar
GetWindowRect(hWndStatusBar, &rcStatusBar);
}
WinPosInfo.bStatusBarVisible = !WinPosInfo.bStatusBarVisible;
// Check the menu item
CheckMenuItem(hViewMenu, IDM_VIEW_STATUS_BAR, MF_BYCOMMAND | (WinPosInfo.bStatusBarVisible ? MF_CHECKED : MF_UNCHECKED));
// Get the rectangle of the client area
GetClientRect(hWnd, &rcClient);
// Resize the list view
MoveWindow(g_hWndListView, 0, (rcToolbar.bottom - rcToolbar.top), rcClient.right, rcClient.bottom - (rcStatusBar.bottom - rcStatusBar.top) - (rcToolbar.bottom - rcToolbar.top), TRUE);
break;
case IDM_VIEW_REFRESH:
if (WaitForSingleObject(g_hStartEvent, 0) == WAIT_OBJECT_0) {
// Post an event to the completion port to indicate thread is to refresh
PostEventToCompletionPort(g_hCompletionPort, FEI_FAXSVC_STARTED, (DWORD) -1);
}
else {
// Set the start event
SetEvent(g_hStartEvent);
}
break;
case IDM_HELP_TOPICS:
HtmlHelp(GetDesktopWindow(), FAXQUEUE_HTMLHELP_FILENAME, HH_DISPLAY_TOPIC, 0L);
break;
case IDM_HELP_ABOUT:
// szCaption is the caption for the shell about dialog box
TCHAR szCaption[RESOURCE_STRING_LEN];
LoadString(g_hInstance, IDS_FAXQUEUE_LOCAL_CAPTION, szCaption, RESOURCE_STRING_LEN);
ShellAbout(hWnd, szCaption, NULL, NULL);
break;
case IDM_FAX_SET_AS_DEFAULT_PRINTER:
case IDM_FAX_SHARING:
case IDM_FAX_PROPERTIES:
// pFaxPrintersConfig is the pointer to the fax printers
LPPRINTER_INFO_2 pFaxPrintersConfig;
// dwNumFaxPrinters is the number of fax printers
DWORD dwNumFaxPrinters;
// Set the current menu selection
if (LOWORD(wParam) == IDM_FAX_SET_AS_DEFAULT_PRINTER) {
uCurrentMenu = IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE;
}
else if (LOWORD(wParam) == IDM_FAX_SHARING) {
uCurrentMenu = IDM_FAX_SHARING_MORE;
}
else if (LOWORD(wParam) == IDM_FAX_PROPERTIES) {
uCurrentMenu = IDM_FAX_PROPERTIES_MORE;
}
else {
break;
}
// Get the fax printers
pFaxPrintersConfig = (LPPRINTER_INFO_2) GetFaxPrinters(&dwNumFaxPrinters);
if (pFaxPrintersConfig) {
// Allocate the memory for the printer name
szPrinterName = (LPTSTR) MemAlloc((lstrlen(pFaxPrintersConfig[0].pPrinterName) + 1) * sizeof(TCHAR));
if (szPrinterName) {
// Copy the printer name
lstrcpy(szPrinterName, pFaxPrintersConfig[0].pPrinterName);
// Post a message that a printer has been selected
PostMessage(hWnd, UM_SELECT_FAX_PRINTER, (UINT_PTR) szPrinterName, 0);
}
MemFree(pFaxPrintersConfig);
}
break;
case IDM_FAX_SET_AS_DEFAULT_PRINTER_1:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_2:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_3:
case IDM_FAX_SET_AS_DEFAULT_PRINTER_4:
case IDM_FAX_SHARING_1:
case IDM_FAX_SHARING_2:
case IDM_FAX_SHARING_3:
case IDM_FAX_SHARING_4:
case IDM_FAX_PROPERTIES_1:
case IDM_FAX_PROPERTIES_2:
case IDM_FAX_PROPERTIES_3:
case IDM_FAX_PROPERTIES_4:
// hMenu is the handle to the menu
HMENU hMenu;
// szMenuString is a menu string
TCHAR szMenuString[RESOURCE_STRING_LEN];
// szMenuItemName is the menu item name
LPTSTR szMenuItemName;
// Get the handle to the menu, set the current menu selection, and set the menu string
if ((LOWORD(wParam) >= IDM_FAX_SET_AS_DEFAULT_PRINTER_1) && (LOWORD(wParam) < IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE)) {
hMenu = hFaxSetAsDefaultMenu;
uCurrentMenu = IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE;
wsprintf(szMenuString, TEXT("&%d "), LOWORD(wParam) - IDM_FAX_SET_AS_DEFAULT_PRINTER_1 + 1);
}
else if ((LOWORD(wParam) >= IDM_FAX_SHARING_1) && (LOWORD(wParam) < IDM_FAX_SHARING_MORE)) {
hMenu = hFaxSharingMenu;
uCurrentMenu = IDM_FAX_SHARING_MORE;
wsprintf(szMenuString, TEXT("&%d "), LOWORD(wParam) - IDM_FAX_SHARING_1 + 1);
}
else if ((LOWORD(wParam) >= IDM_FAX_PROPERTIES_1) && (LOWORD(wParam) < IDM_FAX_PROPERTIES_MORE)) {
hMenu = hFaxPropertiesMenu;
uCurrentMenu = IDM_FAX_PROPERTIES_MORE;
wsprintf(szMenuString, TEXT("&%d "), LOWORD(wParam) - IDM_FAX_PROPERTIES_1 + 1);
}
else {
break;
}
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_TYPE;
mii.fType = MFT_STRING;
mii.dwTypeData = NULL;
mii.cch = 0;
// Get the size of the menu item
if (GetMenuItemInfo(hMenu, LOWORD(wParam), FALSE, &mii)) {
mii.cch++;
// Allocate the memory for the menu item
szMenuItemName = (LPTSTR) MemAlloc(mii.cch * sizeof(TCHAR));
if (szMenuItemName) {
mii.dwTypeData = szMenuItemName;
// Get the menu item
if (GetMenuItemInfo(hMenu, LOWORD(wParam), FALSE, &mii)) {
// Allocate the memory for the printer name
szPrinterName = (LPTSTR) MemAlloc((lstrlen(szMenuItemName) - lstrlen(szMenuString) + 1) * sizeof(TCHAR));
if (szPrinterName) {
// Copy the printer name
lstrcpy(szPrinterName, (LPTSTR) ((UINT_PTR) szMenuItemName + lstrlen(szMenuString) * sizeof(TCHAR)));
// Post a message that a printer has been selected
PostMessage(hWnd, UM_SELECT_FAX_PRINTER, (UINT_PTR) szPrinterName, 0);
}
}
MemFree(szMenuItemName);
}
}
break;
case IDM_FAX_SET_AS_DEFAULT_PRINTER_MORE:
case IDM_FAX_SHARING_MORE:
case IDM_FAX_PROPERTIES_MORE:
uCurrentMenu = LOWORD(wParam);
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_SELECT_FAX_PRINTER), hWnd, SelectFaxPrinterDlgProc);
break;
}
break;
case WM_CLOSE:
// Set the exit event
SetEvent(g_hExitEvent);
if (WaitForSingleObject(g_hStartEvent, 0) == WAIT_OBJECT_0) {
// Post an event to the completion port to indicate thread is to exit
PostEventToCompletionPort(g_hCompletionPort, FEI_FAXSVC_ENDED, (DWORD) -1);
}
#ifdef TOOLBAR_ENABLED
// Set the persistent data
SetFaxQueueRegistryData(WinPosInfo.bToolbarVisible, WinPosInfo.bStatusBarVisible, g_hWndListView, hWnd);
#else
// Set the persistent data
SetFaxQueueRegistryData(WinPosInfo.bStatusBarVisible, g_hWndListView, hWnd);
#endif // TOOLBAR_ENABLED
// Free the process info list
while (pProcessInfoList) {
// Get the head of the process info list
pProcessInfoItem = (PPROCESS_INFO_ITEM) pProcessInfoList;
// Set the head of process info list to the next process info item in the list
pProcessInfoList = pProcessInfoItem->ListEntry.Blink;
if (IsListEmpty(pProcessInfoList)) {
// This is the last item in the list, so set the list head to NULL
pProcessInfoList = NULL;
}
else {
// Remove the process info item from the list
RemoveEntryList(&pProcessInfoItem->ListEntry);
}
// Free the process info item
MemFree(pProcessInfoItem);
}
break;
case WM_DESTROY:
#ifdef TOOLBAR_ENABLED
if (WinPosInfo.bToolbarVisible) {
// Close the toolbar
DestroyWindow(g_hWndToolbar);
DestroyWindow(hWndToolTips);
}
#endif // TOOLBAR_ENABLED
if (WinPosInfo.bStatusBarVisible) {
// Close the status bar
DestroyWindow(hWndStatusBar);
}
// Close the list view
DestroyWindow(g_hWndListView);
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, iMsg, wParam, lParam);
}
INT_PTR CALLBACK SelectFaxPrinterDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// hWndPrinterList is the handle to the fax printer list box
static HWND hWndPrinterList;
switch(iMsg) {
case WM_INITDIALOG:
// pFaxPrintersConfig is the pointer to the fax printers
LPPRINTER_INFO_2 pFaxPrintersConfig;
// dwNumFaxPrinters is the number of fax printers
DWORD dwNumFaxPrinters;
// dwIndex is a counter to enumerate each printer
DWORD dwIndex;
// Get the handle to the fax printer list box
hWndPrinterList = GetDlgItem(hDlg, IDC_FAX_PRINTER_LIST);
// Get the fax printers
pFaxPrintersConfig = (LPPRINTER_INFO_2) GetFaxPrinters(&dwNumFaxPrinters);
if ((pFaxPrintersConfig) && (dwNumFaxPrinters)) {
// Propagate the list box with the list of fax printers
for (dwIndex = 0; dwIndex < dwNumFaxPrinters; dwIndex++) {
SendMessage(hWndPrinterList, LB_ADDSTRING, 0, (UINT_PTR) pFaxPrintersConfig[dwIndex].pPrinterName);
}
}
if (pFaxPrintersConfig) {
MemFree(pFaxPrintersConfig);
}
return TRUE;
case WM_COMMAND:
switch(HIWORD(wParam)) {
case LBN_DBLCLK:
SendMessage(GetDlgItem(hDlg, IDOK), BM_CLICK, 0, 0);
break;
}
switch(LOWORD(wParam)) {
case IDOK:
// szPrinterName is the printer name
LPTSTR szPrinterName;
// ulpIndex is the index of the currently selected item in the list box
ULONG_PTR ulpIndex;
DWORD cb;
// Get the current selection of the list box
ulpIndex = SendMessage(hWndPrinterList, LB_GETCURSEL, 0, 0);
if (ulpIndex != LB_ERR) {
// Get the size of the current selection of the list box
cb = (DWORD) SendMessage(hWndPrinterList, LB_GETTEXTLEN, ulpIndex, NULL);
if (cb != LB_ERR) {
// Allocate the memory for the current selection
szPrinterName = (LPTSTR) MemAlloc((cb + 1) * sizeof(TCHAR));
if (szPrinterName) {
// Get the current selection of the list box
if (SendMessage(hWndPrinterList, LB_GETTEXT, ulpIndex, (UINT_PTR) szPrinterName) != LB_ERR) {
// Post a message that a printer has been selected
PostMessage(g_hWndMain, UM_SELECT_FAX_PRINTER, (UINT_PTR) szPrinterName, 0);
}
}
}
}
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
INT_PTR CALLBACK DocumentPropertiesDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch(iMsg) {
case WM_INITDIALOG:
// pFaxJobEntry is the pointer to the fax job
PFAX_JOB_ENTRY pFaxJobEntry;
// szColumnItem is text of a column item for those items that are equivalent to a column item
LPTSTR szColumnItem;
// Get the pointer to the fax job from the property sheet page
pFaxJobEntry = (PFAX_JOB_ENTRY) ((LPPROPSHEETPAGE) lParam)->lParam;
// Get the column item text for the document name
szColumnItem = GetColumnItemText(eDocumentName, pFaxJobEntry, NULL);
// Set the job type static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_DOCUMENTNAME, szColumnItem);
MemFree(szColumnItem);
}
// Set the recipient's name static text
if (pFaxJobEntry->RecipientName) {
SetDlgItemText(hDlg, IDC_FAX_RECIPIENTNAME, pFaxJobEntry->RecipientName);
}
// Set the recipient's fax number static text
if (pFaxJobEntry->RecipientNumber) {
SetDlgItemText(hDlg, IDC_FAX_RECIPIENTNUMBER, pFaxJobEntry->RecipientNumber);
}
// Set the sender's name static text
if (pFaxJobEntry->SenderName) {
SetDlgItemText(hDlg, IDC_FAX_SENDERNAME, pFaxJobEntry->SenderName);
}
// Set the sender's company static text
if (pFaxJobEntry->SenderCompany) {
SetDlgItemText(hDlg, IDC_FAX_SENDERCOMPANY, pFaxJobEntry->SenderCompany);
}
// Set the sender's department static text
if (pFaxJobEntry->SenderDept) {
SetDlgItemText(hDlg, IDC_FAX_SENDERDEPT, pFaxJobEntry->SenderDept);
}
// Set the billing code static text
if (pFaxJobEntry->BillingCode) {
SetDlgItemText(hDlg, IDC_FAX_BILLINGCODE, pFaxJobEntry->BillingCode);
}
// Get the column item text for the job type
szColumnItem = GetColumnItemText(eJobType, pFaxJobEntry, NULL);
// Set the job type static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_JOBTYPE, szColumnItem);
MemFree(szColumnItem);
}
// Get the column item text for the status
szColumnItem = GetColumnItemText(eStatus, pFaxJobEntry, NULL);
// Set the status static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_STATUS, szColumnItem);
MemFree(szColumnItem);
}
// Get the column item text for the pages
szColumnItem = GetColumnItemText(ePages, pFaxJobEntry, NULL);
// Set the pages static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_PAGES, szColumnItem);
MemFree(szColumnItem);
}
// Get the column item text for the size
szColumnItem = GetColumnItemText(eSize, pFaxJobEntry, NULL);
// Set the size static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_SIZE, szColumnItem);
MemFree(szColumnItem);
}
// Get the column item text for the scheduled time
szColumnItem = GetColumnItemText(eScheduledTime, pFaxJobEntry, NULL);
// Set the scheduled time static text
if (szColumnItem) {
SetDlgItemText(hDlg, IDC_FAX_SCHEDULEDTIME, szColumnItem);
MemFree(szColumnItem);
}
FaxFreeBuffer(pFaxJobEntry);
return TRUE;
case WM_HELP:
case WM_CONTEXTMENU:
FAXWINHELP(iMsg, wParam, lParam, DocumentPropertiesHelpIDs);
break;
}
return FALSE;
}
BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
if (GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE) {
CopyMemory((LPBYTE) lParam, &hWnd, sizeof(hWnd));
return FALSE;
}
return TRUE;
}
VOID PostEventToCompletionPort(HANDLE hCompletionPort, DWORD dwEventId, DWORD dwJobId)
{
PFAX_EVENT pFaxEvent;
pFaxEvent = (PFAX_EVENT) LocalAlloc(LPTR, sizeof(FAX_EVENT));
pFaxEvent->EventId = dwEventId;
pFaxEvent->JobId = dwJobId;
PostQueuedCompletionStatus(hCompletionPort, sizeof(FAX_EVENT), 0, (LPOVERLAPPED) pFaxEvent);
}
DWORD FaxEventThread (LPVOID lpv)
{
// hExitStartEvents is a pointer to the g_hExitEvent and g_hStartEvent
HANDLE hExitStartEvents[2];
// mii is the menu item info
MENUITEMINFO mii;
// hFaxMenu is a handle to the fax menu
HMENU hFaxMenu;
// pFaxConfig is the pointer to the fax configuration
PFAX_CONFIGURATION pFaxConfig;
// pPortJobInfoList is a pointer to the port job info list
PLIST_ENTRY pPortJobInfoList;
// pPortJobInfo is a pointer to a PORT_JOB_INFO_ITEM structure
PPORT_JOB_INFO_ITEM pPortJobInfoItem;
// pFaxPortInfo is the pointer to the fax ports
PFAX_PORT_INFO pFaxPortInfo;
// dwNumFaxPorts is the number of fax ports
DWORD dwNumFaxPorts;
// szDeviceName is the device name of the current fax port
LPTSTR szDeviceName;
// dwJobId is the fax job id on the current fax port
DWORD dwJobId;
// pFaxJobEntry is the pointer to the fax jobs
PFAX_JOB_ENTRY pFaxJobEntry;
// dwNumFaxJobs is the number of fax jobs
DWORD dwNumFaxJobs;
// lvfi specifies the attributes of a particular item to find in the list view
LV_FINDINFO lvfi;
// dwListIndex is the index of a particular item in the list view
DWORD dwListIndex;
// nColumnIndex is used to enumerate each column of the list view
INT nColumnIndex;
// szColumnItem is the text of a column item
LPTSTR szColumnItem;
// uState is the state of a particular item in the list view
UINT uState;
// dwOldFocusIndex is the old item in the list view with the focus
DWORD dwOldFocusIndex;
// dwNewFocusIndex is the new item in the list view with the focus
DWORD dwNewFocusIndex;
// pFaxEvent is a pointer to the port event
PFAX_EVENT pFaxEvent;
DWORD dwBytes;
ULONG_PTR ulpCompletionKey;
// dwIndex is a counter to enumerate each fax port and fax job
DWORD dwIndex;
DWORD dwRslt;
// Set hExitStartEvents
// g_hExitEvent
hExitStartEvents[0] = g_hExitEvent;
// g_hStartEvent
hExitStartEvents[1] = g_hStartEvent;
// Initialize hFaxMenu
hFaxMenu = NULL;
// Set pPortJobInfo to NULL
pPortJobInfoList = NULL;
while (TRUE) {
// Wait for Exit, or Start event
dwRslt = WaitForMultipleObjects(2, hExitStartEvents, FALSE, INFINITE);
if (dwRslt == WAIT_OBJECT_0) {
// Exit event was signaled, so exit
return 0;
}
// Set the window title to indicate connecting
SetWindowText(g_hWndMain, g_szTitleConnecting);
// Get the handle to the fax menu
if (!hFaxMenu) {
hFaxMenu = GetSubMenu(GetMenu(g_hWndMain), 0);
}
// Create the completion port
g_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (!g_hCompletionPort) {
goto ExitLevel0;
}
// Connect to the fax service
if (!Connect()) {
goto ExitLevel1;
}
// Initialize the fax event queue
if (!FaxInitializeEventQueue(g_hFaxSvcHandle, g_hCompletionPort, 0, NULL, 0)) {
// Disconnect from the fax service
Disconnect();
goto ExitLevel1;
}
// Determine if faxing is paused
if (FaxGetConfiguration(g_hFaxSvcHandle, &pFaxConfig)) {
// Check the menu item
CheckMenuItem(hFaxMenu, IDM_FAX_PAUSE_FAXING, MF_BYCOMMAND | (pFaxConfig->PauseServerQueue ? MF_CHECKED : MF_UNCHECKED));
#ifdef TOOLBAR_ENABLED
// Enable the pause faxing toolbar menu item
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_PAUSE_FAXING, pFaxConfig->PauseServerQueue);
#endif // TOOLBAR_ENABLED
FaxFreeBuffer(pFaxConfig);
}
// Enumerate the fax ports
if (FaxEnumPorts(g_hFaxSvcHandle, &pFaxPortInfo, &dwNumFaxPorts)) {
for (dwIndex = 0; dwIndex < dwNumFaxPorts; dwIndex++) {
// Add each port job info into the list
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) MemAlloc(sizeof(PORT_JOB_INFO_ITEM) + (lstrlen(pFaxPortInfo[dwIndex].DeviceName) + 1) * sizeof(TCHAR));
if (pPortJobInfoItem) {
// Copy dwDeviceId
pPortJobInfoItem->dwDeviceId = pFaxPortInfo[dwIndex].DeviceId;
// Set szDeviceName
pPortJobInfoItem->szDeviceName = (LPTSTR) ((UINT_PTR) pPortJobInfoItem + sizeof(PORT_JOB_INFO_ITEM));
// Copy szDeviceName
lstrcpy(pPortJobInfoItem->szDeviceName, pFaxPortInfo[dwIndex].DeviceName);
// Set dwJobId
pPortJobInfoItem->dwJobId = (DWORD) -1;
// Insert the port job info into the list
if (pPortJobInfoList) {
InsertTailList(pPortJobInfoList, &pPortJobInfoItem->ListEntry);
}
else {
pPortJobInfoList = &pPortJobInfoItem->ListEntry;
InitializeListHead(pPortJobInfoList);
}
}
}
FaxFreeBuffer(pFaxPortInfo);
}
// Enable the pause faxing menu item and the cancel all faxes menu item
EnableMenuItem(hFaxMenu, IDM_FAX_PAUSE_FAXING, MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem(hFaxMenu, IDM_FAX_CANCEL_ALL_FAXES, MF_BYCOMMAND | MF_ENABLED);
#ifdef TOOLBAR_ENABLED
// Enable the pause faxing toolbar menu item and the cancel all faxes toolbar menu item
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_PAUSE_FAXING, TRUE);
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_CANCEL_ALL_FAXES, TRUE);
#endif // TOOLBAR_ENABLED
// Disconnect from the fax service
Disconnect();
// Wait for fax events
while (GetQueuedCompletionStatus(g_hCompletionPort, &dwBytes, &ulpCompletionKey, (LPOVERLAPPED *) &pFaxEvent, INFINITE)) {
if (pFaxEvent->EventId == FEI_FAXSVC_ENDED) {
// Thread should stop listening for fax events
LocalFree(pFaxEvent);
break;
}
switch (pFaxEvent->EventId) {
case FEI_MODEM_POWERED_ON:
case FEI_MODEM_POWERED_OFF:
case FEI_RINGING:
case FEI_ABORTING:
// Ignore these fax events
break;
case FEI_FAXSVC_STARTED:
// Set the window title to indicate refreshing
SetWindowText(g_hWndMain, g_szTitleRefreshing);
// Initialize the menu item info
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STATE;
mii.fState = 0;
// Get the state of the menu item
GetMenuItemInfo(hFaxMenu, IDM_FAX_PAUSE_FAXING, FALSE, &mii);
// Connect to the fax service
if (Connect()) {
// Enumerate the fax jobs
if (FaxEnumJobs(g_hFaxSvcHandle, &pFaxJobEntry, &dwNumFaxJobs)) {
// Initialize lvfi
lvfi.flags = LVFI_PARAM;
// Get the old item with the focus
dwOldFocusIndex = ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_FOCUSED);
// Add new fax jobs and move existing fax jobs to their correct position
for (dwIndex = 0; dwIndex < dwNumFaxJobs; dwIndex++) {
// Set the search criteria
lvfi.lParam = pFaxJobEntry[dwIndex].JobId;
// Initialize the item's state
uState = 0;
// Initialize the device name
szDeviceName = NULL;
if (pPortJobInfoList) {
// Find the appropriate job
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoList;
while (TRUE) {
if (pFaxJobEntry[dwIndex].JobId == pPortJobInfoItem->dwJobId) {
// Job id matches, so this is the appropriate port
// Get the device name
szDeviceName = pPortJobInfoItem->szDeviceName;
break;
}
// Step to the next port job info item
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoItem->ListEntry.Blink;
if (pPortJobInfoItem == (PPORT_JOB_INFO_ITEM) pPortJobInfoList) {
// The list has been traversed
break;
}
}
}
// Find the job in the list view
dwListIndex = ListView_FindItem(g_hWndListView, -1, &lvfi);
if ((dwListIndex != -1) && (dwListIndex != dwIndex)) {
// Job exists in the list view but is in the wrong position, so get the item
// Get the item's state
uState = ListView_GetItemState(g_hWndListView, dwListIndex, LVIS_FOCUSED | LVIS_SELECTED);
// Delete the item from its current position
ListView_DeleteItem(g_hWndListView, dwListIndex);
// Set dwListIndex to -1 so item will be inserted into the list view
dwListIndex = -1;
}
for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
// Get the column item text
szColumnItem = GetColumnItemText((eListViewColumnIndex) nColumnIndex, &pFaxJobEntry[dwIndex], szDeviceName);
// Insert item into the list view
SetColumnItem(g_hWndListView, (dwListIndex == -1) ? TRUE : FALSE, dwIndex, nColumnIndex, szColumnItem, uState, &pFaxJobEntry[dwIndex]);
if (szColumnItem) {
MemFree(szColumnItem);
}
}
}
// Get the new item with the focus
dwNewFocusIndex = ListView_GetNextItem(g_hWndListView, -1, LVNI_ALL | LVNI_FOCUSED);
if ((dwOldFocusIndex != -1) && (dwNewFocusIndex != -1) && (dwNewFocusIndex >= dwNumFaxJobs)) {
// Job will no longer exist in the list view, so set the focus to the item occupying that index
// Get the state of the item occupying that index
uState = ListView_GetItemState(g_hWndListView, dwOldFocusIndex, LVIS_FOCUSED | LVIS_SELECTED | LVIS_OVERLAYMASK);
// Set the focus to the new item
ListView_SetItemState(g_hWndListView, dwOldFocusIndex, uState | LVIS_FOCUSED, uState | LVIS_FOCUSED);
}
// Remove old fax jobs
dwListIndex = ListView_GetItemCount(g_hWndListView);
for (dwIndex = dwNumFaxJobs; dwIndex < dwListIndex; dwIndex++) {
ListView_DeleteItem(g_hWndListView, dwNumFaxJobs);
}
FaxFreeBuffer(pFaxJobEntry);
}
// Disconnect from the fax service
Disconnect();
}
// Set the window title to indicate connected or paused
SetWindowText(g_hWndMain, mii.fState & MFS_CHECKED ? g_szTitlePaused : g_szTitleConnected);
continue;
case FEI_JOB_QUEUED:
case FEI_ANSWERED:
// Initialize the device name
szDeviceName = NULL;
if ((pFaxEvent->EventId == FEI_ANSWERED) && (pPortJobInfoList)) {
// Find the appropriate port
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoList;
while (TRUE) {
if (pFaxEvent->DeviceId == pPortJobInfoItem->dwDeviceId) {
// Device id matches, so this is the appropriate port
// Set the job id
pPortJobInfoItem->dwJobId = pFaxEvent->JobId;
// Get the device name
szDeviceName = pPortJobInfoItem->szDeviceName;
break;
}
// Step to the next port job info item
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoItem->ListEntry.Blink;
if (pPortJobInfoItem == (PPORT_JOB_INFO_ITEM) pPortJobInfoList) {
// The list has been traversed
break;
}
}
}
// Connect to the fax service
if (Connect()) {
// Enumerate the fax jobs
if (FaxEnumJobs(g_hFaxSvcHandle, &pFaxJobEntry, &dwNumFaxJobs)) {
// Initialize lvfi
lvfi.flags = LVFI_PARAM;
// Add the new fax job to its correct position
for (dwIndex = 0; dwIndex < dwNumFaxJobs; dwIndex++) {
// Check if the current fax job matches the new fax job
if (pFaxJobEntry[dwIndex].JobId != pFaxEvent->JobId) {
continue;
}
// Set the search criteria
lvfi.lParam = pFaxJobEntry[dwIndex].JobId;
// Find the job in the list view
dwListIndex = ListView_FindItem(g_hWndListView, -1, &lvfi);
if (dwListIndex != -1) {
// Job exists in the list view but is in the wrong position, so get the item
// Delete the item from its current position
ListView_DeleteItem(g_hWndListView, dwListIndex);
}
for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
// Get the column item text
szColumnItem = GetColumnItemText((eListViewColumnIndex) nColumnIndex, &pFaxJobEntry[dwIndex], szDeviceName);
// Insert item into the list view
SetColumnItem(g_hWndListView, TRUE, dwIndex, nColumnIndex, szColumnItem, 0, &pFaxJobEntry[dwIndex]);
if (szColumnItem) {
MemFree(szColumnItem);
}
}
break;
}
FaxFreeBuffer(pFaxJobEntry);
}
// Disconnect from the fax service
Disconnect();
}
continue;
case FEI_DELETED:
// Initialize lvfi
lvfi.flags = LVFI_PARAM;
// Set the search criteria
lvfi.lParam = pFaxEvent->JobId;
// Find the job in the list view
dwListIndex = ListView_FindItem(g_hWndListView, -1, &lvfi);
if (dwListIndex != -1) {
// Delete the item from the list view
ListView_DeleteItem(g_hWndListView, dwListIndex);
}
continue;
default:
// Initialize the device name
szDeviceName = NULL;
// Initialize the fax job id
dwJobId = (DWORD) -1;
// Set the port job info item
if ((pFaxEvent->EventId != (DWORD) -1) && (pPortJobInfoList)) {
// Find the appropriate port
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoList;
while (TRUE) {
if (pFaxEvent->DeviceId == pPortJobInfoItem->dwDeviceId) {
// Device id matches, so this is the appropriate port
// Get the fax job id
if (pFaxEvent->EventId == FEI_IDLE) {
dwJobId = pPortJobInfoItem->dwJobId;
}
else {
dwJobId = pFaxEvent->JobId;
// Set the device name
szDeviceName = pPortJobInfoItem->szDeviceName;
}
// Update the job id
pPortJobInfoItem->dwJobId = pFaxEvent->JobId;
break;
}
// Step to the next port job info item
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoItem->ListEntry.Blink;
if (pPortJobInfoItem == (PPORT_JOB_INFO_ITEM) pPortJobInfoList) {
// The list has been traversed
break;
}
}
}
else if (pFaxEvent->EventId == (DWORD) -1) {
// Set the fax job id
dwJobId = pFaxEvent->JobId;
}
// Initialize lvfi
lvfi.flags = LVFI_PARAM;
// Set the search criteria
lvfi.lParam = dwJobId;
// Find the job in the list view
dwListIndex = ListView_FindItem(g_hWndListView, -1, &lvfi);
if (dwListIndex != -1) {
// Connect to the fax service
if (Connect()) {
// Get the fax job
pFaxJobEntry = NULL;
while ((FaxGetJob(g_hFaxSvcHandle, dwJobId, &pFaxJobEntry)) && (pFaxJobEntry->Status == FPS_AVAILABLE) && ((pFaxJobEntry->JobType == JT_SEND) || (pFaxJobEntry->JobType == JT_RECEIVE))) {
FaxFreeBuffer(pFaxJobEntry);
pFaxJobEntry = NULL;
Sleep(250);
}
if (pFaxJobEntry) {
// Job exists in the list view, so set the item
for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
// Get the column item text
szColumnItem = GetColumnItemText((eListViewColumnIndex) nColumnIndex, pFaxJobEntry, szDeviceName);
// Set item in the list view
SetColumnItem(g_hWndListView, FALSE, dwListIndex, nColumnIndex, szColumnItem, 0, pFaxJobEntry);
if (szColumnItem) {
MemFree(szColumnItem);
}
}
FaxFreeBuffer(pFaxJobEntry);
}
// Disconnect from the fax service
Disconnect();
}
}
break;
}
LocalFree(pFaxEvent);
}
// Disable the pause faxing menu item and the cancel all faxes menu item
EnableMenuItem(hFaxMenu, IDM_FAX_PAUSE_FAXING, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hFaxMenu, IDM_FAX_CANCEL_ALL_FAXES, MF_BYCOMMAND | MF_GRAYED);
#ifdef TOOLBAR_ENABLED
// Disable the pause faxing toolbar menu item and the cancel all faxes toolbar menu item
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_PAUSE_FAXING, FALSE);
EnableToolbarMenuState(g_hWndToolbar, IDM_FAX_CANCEL_ALL_FAXES, FALSE);
#endif // TOOLBAR_ENABLED
// Free the port job info list
while (pPortJobInfoList) {
// Get the head of the port job info list
pPortJobInfoItem = (PPORT_JOB_INFO_ITEM) pPortJobInfoList;
// Set the head of port job info list to the next port job info item in the list
pPortJobInfoList = pPortJobInfoItem->ListEntry.Blink;
if (IsListEmpty(pPortJobInfoList)) {
// This is the last item in the list, so set the list head to NULL
pPortJobInfoList = NULL;
}
else {
// Remove the port job info item from the list
RemoveEntryList(&pPortJobInfoItem->ListEntry);
}
// Free the port job info item
MemFree(pPortJobInfoItem);
}
ExitLevel1:
CloseHandle(g_hCompletionPort);
ExitLevel0:
// Reset the start event
ResetEvent(g_hStartEvent);
// Set the window title to indicate not connected
SetWindowText(g_hWndMain, g_szTitleNotConnected);
}
return 0;
}