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