/*++ Copyright (c) 1997 Microsoft Corporation Module Name: events.c Abstract: This module: 1) Determines if the port is valid 2) Post a completion packet to a completion port. This packet indicates for the Fax Event Queue thread to exit. 3) Thread to handle the Fax Event Queue logic Author: Steven Kehrli (steveke) 11/15/1997 --*/ #ifndef _EVENTS_C #define _EVENTS_C BOOL fnIsPortValid( PFAX_PORT_INFO pFaxPortsConfig, DWORD dwNumPorts, DWORD dwDeviceId ) /*++ Routine Description: Determines if the port is valid Arguments: pFaxPortsConfig - pointer to the ports configuration dwNumFaxPorts - number of ports dwDeviceId - port id Return Value: TRUE on success --*/ { // dwIndex is a counter to enumerate each port DWORD dwIndex; for (dwIndex = 0; dwIndex < dwNumPorts; dwIndex++) { // Search, by priority, each port for the appropriate port if (pFaxPortsConfig[dwIndex].DeviceId == dwDeviceId) { return TRUE; } } return FALSE; } VOID fnPostExitToCompletionPort( HANDLE hCompletionPort ) /*++ Routine Description: Post a completion packet to a completion port. This packet indicates for the Fax Event Queue thread to exit. Arguments: hCompletionPort - handle to the completion port Return Value: None --*/ { PFAX_EVENT pFaxEvent; pFaxEvent = LocalAlloc(LPTR, sizeof(FAX_EVENT)); pFaxEvent->EventId = -1; PostQueuedCompletionStatus(hCompletionPort, sizeof(FAX_EVENT), 0, (LPOVERLAPPED) pFaxEvent); } DWORD WINAPI fnFaxEventQueueProc (LPVOID lpv) /*++ Routine Description: Thread to handle the Fax Event Queue logic Return Value: DWORD - exit code --*/ { // pFaxEvent is a pointer to the port event PFAX_EVENT pFaxEvent; DWORD dwBytes; UINT_PTR upCompletionKey; // FaxDialingInfo is the fax dialing info FAX_DIALING_INFO FaxDialingInfo; // bFaxPassed indicates a fax passed BOOL bFaxPassed = FALSE; // bFaxFailed indicates a fax failed BOOL bFaxFailed = FALSE; // dwDeviceId is the port id DWORD dwDeviceId = 0; while (GetQueuedCompletionStatus(g_hCompletionPort, &dwBytes, &upCompletionKey, (LPOVERLAPPED *) &pFaxEvent, INFINITE)) { if (pFaxEvent->EventId == -1) { // g_hExitEvent was signaled, so thread should exit LocalFree(pFaxEvent); break; } if (pFaxEvent->EventId == FEI_FAXSVC_ENDED) { // Signal the g_hFaxEvent SetEvent(g_hFaxEvent); // Free the packet LocalFree(pFaxEvent); break; } if (pFaxEvent->EventId == FEI_MODEM_POWERED_OFF) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_DEVICE_POWERED_OFF, pFaxEvent->DeviceId); // Free the packet LocalFree(pFaxEvent); // Decrement g_dwNumAvailPorts g_dwNumAvailPorts--; if (!g_dwNumAvailPorts) { SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_PORTS_NOT_AVAILABLE, 0); } continue; } if (pFaxEvent->EventId == FEI_MODEM_POWERED_ON) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_DEVICE_POWERED_ON, pFaxEvent->DeviceId); // Free the packet LocalFree(pFaxEvent); // Increment g_dwNumAvailPorts g_dwNumAvailPorts++; continue; } // Verify the port is valid if (!fnIsPortValid(g_pFaxPortsConfig, g_dwNumPorts, pFaxEvent->DeviceId)) { // Free the packet LocalFree(pFaxEvent); continue; } if ((pFaxEvent->EventId == FEI_IDLE) && (g_bFaxSndInProgress) && (pFaxEvent->DeviceId == dwDeviceId) && ((bFaxPassed) || (bFaxFailed))) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_IDLE, pFaxEvent->DeviceId); if (bFaxPassed) { SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_SEND_PASSED, pFaxEvent->DeviceId); // Signal the Send Passed event SetEvent(g_hSendPassedEvent); } else { SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_SEND_FAILED, pFaxEvent->DeviceId); // Signal the Send Failed event SetEvent(g_hSendFailedEvent); } dwDeviceId = 0; bFaxPassed = FALSE; bFaxFailed = FALSE; continue; } if ((pFaxEvent->EventId == FEI_IDLE) && (g_bFaxSndInProgress)) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_IDLE, pFaxEvent->DeviceId); } if ((pFaxEvent->JobId == g_dwFaxId) && (g_bFaxSndInProgress)) { switch (pFaxEvent->EventId) { case FEI_INITIALIZING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_INITIALIZING, pFaxEvent->DeviceId); break; case FEI_DIALING: g_dwAttempt++; // Set FaxDialingInfo FaxDialingInfo.dwAttempt = g_dwAttempt; FaxDialingInfo.dwDeviceId = pFaxEvent->DeviceId; // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_DIALING, (LPARAM) &FaxDialingInfo); dwDeviceId = pFaxEvent->DeviceId; break; case FEI_NO_DIAL_TONE: if (g_dwAttempt < (FAXSVC_RETRIES + 1)) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_NO_DIAL_TONE_RETRY, pFaxEvent->DeviceId); } else { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_NO_DIAL_TONE_ABORT, pFaxEvent->DeviceId); bFaxFailed = TRUE; } break; case FEI_BUSY: if (g_dwAttempt < (FAXSVC_RETRIES + 1)) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_BUSY_RETRY, pFaxEvent->DeviceId); } else { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_BUSY_ABORT, pFaxEvent->DeviceId); bFaxFailed = TRUE; } break; case FEI_NO_ANSWER: if (g_dwAttempt < (FAXSVC_RETRIES + 1)) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_NO_ANSWER_RETRY, pFaxEvent->DeviceId); } else { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_NO_ANSWER_ABORT, pFaxEvent->DeviceId); bFaxFailed = TRUE; } break; case FEI_SENDING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_SENDING, pFaxEvent->DeviceId); break; case FEI_FATAL_ERROR: if (g_dwAttempt < (FAXSVC_RETRIES + 1)) { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_FATAL_ERROR_RETRY, pFaxEvent->DeviceId); } else { // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_FATAL_ERROR_ABORT, pFaxEvent->DeviceId); bFaxFailed = TRUE; } break; case FEI_ABORTING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ABORTING, pFaxEvent->DeviceId); bFaxFailed = TRUE; break; case FEI_COMPLETED: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_COMPLETED, pFaxEvent->DeviceId); bFaxPassed = TRUE; break; default: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_UNEXPECTED_STATE, pFaxEvent->DeviceId); bFaxFailed = TRUE; break; } } if (g_bFaxRcvInProgress) { switch (pFaxEvent->EventId) { case FEI_INITIALIZING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_INITIALIZING, pFaxEvent->DeviceId); break; case FEI_RINGING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_RINGING, pFaxEvent->DeviceId); break; case FEI_ANSWERED: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ANSWERED, pFaxEvent->DeviceId); break; case FEI_NOT_FAX_CALL: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_NOT_FAX_CALL, pFaxEvent->DeviceId); break; case FEI_RECEIVING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_RECEIVING, pFaxEvent->DeviceId); break; case FEI_FATAL_ERROR: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_FATAL_ERROR, pFaxEvent->DeviceId); break; case FEI_ABORTING: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ABORTING, pFaxEvent->DeviceId); break; case FEI_COMPLETED: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_COMPLETED, pFaxEvent->DeviceId); break; case FEI_IDLE: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_IDLE, pFaxEvent->DeviceId); break; default: // Update the status SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_UNEXPECTED_STATE, pFaxEvent->DeviceId); break; } } // Free the packet LocalFree(pFaxEvent); } return 0; } #endif