windows-nt/Source/XPSP1/NT/printscan/fax/test/faxvrfy/sndthrd.c
2020-09-26 16:20:57 +08:00

1094 lines
32 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
sndthrd.c
Abstract:
This module:
1) Verifies a tiff
2) Enables or disables the FaxRcv Routing Extension
3) Callback function for the change of state during the RAS connection process
4) Sends a RAS call
5) Sends a fax
6) Receives a fax
7) Thread to handle the Send logic
Author:
Steven Kehrli (steveke) 11/15/1997
--*/
#ifndef _SNDTHRD_C
#define _SNDTHRD_C
#include <tifflib.h>
#include <tifflibp.h>
#define SUSPECT_RAS_SPEED 28800
#define IMAGEWIDTH_REF 1728
#define IMAGELENGTH_200_REF 2200
#define IMAGELENGTH_100_REF 1100
#define SOFTWARE_REF "Windows NT Fax Server"
UINT
fnVerifyTiff(
LPWSTR szTiffFile,
LPDWORD pdwPages
)
/*++
Routine Description:
Verifies a tiff
Arguments:
szTiffFile - tiff file name
pdwPages - pointer to the number of pages
Return Value:
TRUE on success
--*/
{
HANDLE hTiffFile;
TIFF_INFO TiffInfo;
PTIFF_INSTANCE_DATA pTiffInstanceData;
DWORD IFDOffset;
WORD wNumDirEntries;
PTIFF_TAG pTiffTag;
WORD wIndex;
DWORD ImageLengthRef;
DWORD ImageWidth;
DWORD ImageLength;
DWORD Compression;
DWORD Photometric;
DWORD XResolution;
DWORD YResolution;
LPSTR SoftwareBuffer;
LPSTR Software;
UINT uFlags;
uFlags = ERROR_SUCCESS;
*pdwPages = 0;
// Open the tiff file
hTiffFile = TiffOpen(szTiffFile, &TiffInfo, TRUE, FILLORDER_MSB2LSB);
if (hTiffFile == NULL) {
TiffClose(hTiffFile);
return IDS_TIFF_INVALID_TIFF;
}
pTiffInstanceData = (PTIFF_INSTANCE_DATA) hTiffFile;
// Get the next IFD offset
IFDOffset = pTiffInstanceData->TiffHdr.IFDOffset;
while (IFDOffset) {
// Increment the number of pages
(*pdwPages)++;
// Get the number of tags in this IFD
wNumDirEntries = (WORD) *(LPWORD) (pTiffInstanceData->fPtr + IFDOffset);
// Set the tag pointer
pTiffTag = (PTIFF_TAG) (pTiffInstanceData->fPtr +IFDOffset + sizeof(WORD));
// Get the tiff tags
ImageWidth = -1;
ImageLength = -1;
Compression = -1;
Photometric = -1;
XResolution = -1;
YResolution = -1;
Software = NULL;
for (wIndex = 0; wIndex < wNumDirEntries; wIndex++) {
switch (pTiffTag[wIndex].TagId) {
case TIFFTAG_IMAGEWIDTH:
ImageWidth = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_IMAGELENGTH:
ImageLength = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_COMPRESSION:
Compression = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_PHOTOMETRIC:
Photometric = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_XRESOLUTION:
XResolution = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_YRESOLUTION:
YResolution = GetTagData(pTiffInstanceData->fPtr, 0, &pTiffTag[wIndex]);
break;
case TIFFTAG_SOFTWARE:
SoftwareBuffer = (LPSTR) (DWORD UNALIGNED *) (pTiffInstanceData->fPtr + pTiffTag[wIndex].DataOffset);
Software = MemAllocMacro((lstrlenA(SOFTWARE_REF) + 1) * sizeof(CHAR));
lstrcpynA(Software, SoftwareBuffer, (lstrlenA(SOFTWARE_REF) + 1));
break;
}
}
if ((ImageWidth < (IMAGEWIDTH_REF - (IMAGEWIDTH_REF * .1))) || (ImageWidth > (IMAGEWIDTH_REF + (IMAGEWIDTH_REF * .1)))) {
uFlags = IDS_TIFF_INVALID_IMAGEWIDTH;
goto InvalidFax;
}
if (YResolution == 196) {
ImageLengthRef = IMAGELENGTH_200_REF;
}
else if (YResolution == 98) {
ImageLengthRef = IMAGELENGTH_100_REF;
}
else {
uFlags = IDS_TIFF_INVALID_YRESOLUTION;
goto InvalidFax;
}
if ((ImageLength < (ImageLengthRef - (ImageLengthRef * .1))) || (ImageLength > (ImageLengthRef + (ImageLengthRef * .1)))) {
uFlags = IDS_TIFF_INVALID_IMAGELENGTH;
goto InvalidFax;
}
if (Compression != 4) {
uFlags = IDS_TIFF_INVALID_COMPRESSION;
goto InvalidFax;
}
if (Photometric != 0) {
uFlags = IDS_TIFF_INVALID_PHOTOMETRIC;
goto InvalidFax;
}
if (XResolution != 204) {
uFlags = IDS_TIFF_INVALID_XRESOLUTION;
goto InvalidFax;
}
if ((YResolution != 196) && (YResolution != 98)) {
uFlags = IDS_TIFF_INVALID_YRESOLUTION;
goto InvalidFax;
}
if (lstrcmpA(SOFTWARE_REF, Software)) {
uFlags = IDS_TIFF_INVALID_SOFTWARE;
goto InvalidFax;
}
MemFreeMacro(Software);
// Get the next IFD offset
IFDOffset = (DWORD) *(DWORD UNALIGNED *) (pTiffInstanceData->fPtr + (wNumDirEntries * sizeof(TIFF_TAG)) + IFDOffset + sizeof(WORD));
}
TiffClose(hTiffFile);
return ERROR_SUCCESS;
InvalidFax:
if (Software) {
MemFreeMacro(Software);
}
TiffClose(hTiffFile);
return uFlags;
}
VOID
fnEnableFaxRcv(
BOOL bEnable
)
/*++
Routine Description:
Enables or disables the FaxRcv Routing Extension
Arguments:
bEnable - indicates whether to enable or disable the FaxRcv Routing Extension
TRUE enables the FaxRcv Routing Extension
FALSE enables the FaxRcv Routing Extension
Return Value:
None
--*/
{
// hFaxRcvExtKey is the handle to the FaxRcv Extension Registry key
HKEY hFaxRcvExtKey;
// Open the FaxRcv Extension Registry key
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, FAXRCV_EXT_REGKEY, 0, KEY_ALL_ACCESS, &hFaxRcvExtKey) != ERROR_SUCCESS) {
return;
}
// Set the FaxRcv Extension bEnable Registry value
if (RegSetValueEx(hFaxRcvExtKey, BENABLE_EXT_REGVAL, 0, REG_DWORD, (LPBYTE) &bEnable, sizeof(BOOL)) != ERROR_SUCCESS) {
// Close the FaxRcv Extension Registry key
RegCloseKey(hFaxRcvExtKey);
return;
}
// Close the FaxRcv Extension Registry key
RegCloseKey(hFaxRcvExtKey);
}
VOID WINAPI
fnRasDialCallback(
UINT uMsg,
RASCONNSTATE RasConnState,
DWORD dwError
)
/*++
Routine Description:
Callback function for the change of state during the RAS connection process
Arguments:
uMsg - type of event
RasConnState - state
dwError - error
Return Value:
None
--*/
{
static BOOL bError = FALSE;
if ((dwError) && (!bError)) {
bError = TRUE;
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_FAILED, dwError);
SetEvent(g_hRasFailedEvent);
}
else if (RasConnState == RASCS_OpenPort) {
bError = FALSE;
}
else if (RasConnState == RASCS_ConnectDevice) {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_DIALING, 0);
}
else if (RasConnState == RASCS_Authenticate) {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_AUTHENTICATING, 0);
}
else if (RasConnState == RASCS_Connected) {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_CONNECTED, 0);
SetEvent(g_hRasPassedEvent);
}
return;
}
UINT
fnSendRas(
LPHANDLE phFaxStopRasPassFailEvents
)
/*++
Routine Description:
Sends a RAS call
Arguments:
phFaxStopSendPassFailEvents - pointer to the g_hFaxEvent, g_hStopEvent, g_hRasPassedEvent and g_hRasFailedEvent
Return Value:
UINT - resource id
--*/
{
DWORD_PTR dwRslt;
UINT uRslt;
// RasDialParams is the RAS dial params
RASDIALPARAMS RasDialParams;
// hRasConn is the handle to the RAS connection
HRASCONN hRasConn;
// RasConnStatus is the RAS connection status
RASCONNSTATUS RasConnStatus;
// RasStats are the RAS connection statistics
RAS_STATS RasStats;
// RasInfo is the RAS connection info
RAS_INFO RasInfo;
// Initialize hRasConn
hRasConn = NULL;
// Initialize RasDialParams
ZeroMemory(&RasDialParams, sizeof(RASDIALPARAMS));
// Set RasDialParams
RasDialParams.dwSize = sizeof(RASDIALPARAMS);
lstrcpy(RasDialParams.szPhoneNumber, g_szSndNumber);
lstrcpy(RasDialParams.szUserName, g_szRasUserName);
lstrcpy(RasDialParams.szPassword, g_szRasPassword);
lstrcpy(RasDialParams.szDomain, g_szRasDomain);
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STARTING, (LPARAM) g_szSndNumber);
// Start the RAS session
ResetEvent(g_hRasPassedEvent);
ResetEvent(g_hRasFailedEvent);
dwRslt = g_RasApi.RasDial(NULL, NULL, &RasDialParams, 0, fnRasDialCallback, &hRasConn);
if (dwRslt != 0) {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_FAILED, dwRslt);
return IDS_STATUS_RAS_FAILED;
}
// Wait for Fax, Stop, RAS Passed or RAS Failed event
dwRslt = WaitForMultipleObjects(4, phFaxStopRasPassFailEvents, FALSE, INFINITE);
switch (dwRslt) {
case WAIT_OBJECT_0:
uRslt = IDS_STATUS_FAXSVC_ENDED;
break;
case (WAIT_OBJECT_0 + 1):
uRslt = IDS_STATUS_ITERATION_STOPPED;
break;
case (WAIT_OBJECT_0 + 2):
uRslt = IDS_STATUS_RAS_PASSED;
break;
case (WAIT_OBJECT_0 + 3):
uRslt = IDS_STATUS_RAS_FAILED;
break;
}
if (uRslt != IDS_STATUS_RAS_PASSED) {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STOPPING, 0);
// Stop the RAS session
g_RasApi.RasHangUp(hRasConn);
if (uRslt != IDS_STATUS_RAS_FAILED) {
WaitForSingleObject(g_hRasFailedEvent, INFINITE);
}
return uRslt;
}
// Initialize RasConnStatus
ZeroMemory(&RasConnStatus, sizeof(RASCONNSTATUS));
// Set RasConnStatus
RasConnStatus.dwSize = sizeof(RASCONNSTATUS);
// Get the RAS connection status
g_RasApi.RasGetConnectStatus(hRasConn, &RasConnStatus);
// Initialize RasStats
ZeroMemory(&RasStats, sizeof(RAS_STATS));
// Set RasStats
RasStats.dwSize = sizeof(RAS_STATS);
// Get the connection statistics
g_RasApi.RasGetConnectionStatistics(hRasConn, &RasStats);
// Set the line speed
RasInfo.dwBps = RasStats.dwBps;
// Set the port name
RasInfo.szDeviceName = RasConnStatus.szDeviceName;
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_LINESPEED, (LPARAM) &RasInfo);
if (RasStats.dwBps < SUSPECT_RAS_SPEED) {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_SPEED_SUSPECT, SUSPECT_RAS_SPEED);
}
else {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_PASSED, 0);
}
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_RAS_STOPPING, 0);
// Stop the RAS session
g_RasApi.RasHangUp(hRasConn);
return IDS_STATUS_RAS_PASSED;
}
UINT
fnSendFax(
FAX_JOB_PARAM FaxJobParams,
LPWSTR szDocumentName,
LPHANDLE phFaxStopSendPassFailEvents,
DWORD dwSendTimeout
)
/*++
Routine Description:
Sends a fax
Arguments:
FaxJobParams - fax job parameters
szDocumentName - name of document to send
phFaxStopSendPassFailEvents - pointer to the g_hFaxEvent, g_hStopEvent, g_hSendPassedEvent and g_hSendFailedEvent
dwSendTimeout - send timeout interval
Return Value:
UINT - resource id
--*/
{
DWORD dwRslt;
UINT uRslt;
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_STARTING, (LPARAM) FaxJobParams.RecipientNumber);
if (!g_bNoCheck) {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ID, (LPARAM) FaxJobParams.Tsid);
}
// Send a fax
if (!FaxSendDocument(g_hFaxSvcHandle, szDocumentName, &FaxJobParams, NULL, &g_dwFaxId)) {
return IDS_STATUS_FAX_SEND_FAILED;
}
g_bFaxSndInProgress = TRUE;
g_dwAttempt = 0;
// Wait for Fax, Stop, Send Passed or Send Failed event
dwRslt = WaitForMultipleObjects(4, phFaxStopSendPassFailEvents, FALSE, dwSendTimeout);
g_bFaxSndInProgress = FALSE;
switch (dwRslt) {
case WAIT_TIMEOUT:
uRslt = IDS_STATUS_TIMEOUT_ENDED;
break;
case WAIT_OBJECT_0:
uRslt = IDS_STATUS_FAXSVC_ENDED;
break;
case (WAIT_OBJECT_0 + 1):
uRslt = IDS_STATUS_ITERATION_STOPPED;
break;
case (WAIT_OBJECT_0 + 2):
uRslt = IDS_STATUS_FAX_SEND_PASSED;
break;
case (WAIT_OBJECT_0 + 3):
uRslt = IDS_STATUS_FAX_SEND_FAILED;
break;
}
if (uRslt != IDS_STATUS_FAX_SEND_PASSED) {
if (uRslt == IDS_STATUS_ITERATION_STOPPED) {
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_STOPPING, 0);
}
FaxAbort(g_hFaxSvcHandle, g_dwFaxId);
return uRslt;
}
return IDS_STATUS_FAX_SEND_PASSED;
}
UINT
fnReceiveFax(
LPHANDLE phFaxStopRcvEvents,
DWORD dwReceiveTimeout,
LPWSTR szTsid,
DWORD dwTsidSize,
LPWSTR szCopyTiffFile,
DWORD dwCopyTiffFileSize,
LPWSTR szCopyTiffName,
DWORD dwCopyTiffNameSize
)
/*++
Routine Description:
Receives a fax
Arguments:
phFaxStopRcvEvents - pointer to the g_hFaxEvent, g_hStopEvent and hFaxRcvEvent
dwReceiveTimeout - receive timeout interval
szTsid - TSID of the received fax
dwTsidSize - size of szTsid buffer, in bytes
szCopyTiffFile - name of the copy of the received fax
dwCopyTiffFileSize - size of szCopyTiffFile buffer, in bytes
szCopyTiffName - name of the copy of the received fax
dwCopyTiffNameSize - size of szCopyTiffName buffer, in bytes
Return Value:
UINT - resource id
--*/
{
// hFaxRcvEvent is the handle to the FaxRcv named event
HANDLE hFaxRcvEvent;
// hFaxRcvMutex is the handle to the FaxRcv named mutex
HANDLE hFaxRcvMutex;
// hFaxRcvMap is the handle to the FaxRcv memory map
HANDLE hFaxRcvMap;
// pFaxRcvView is the pointer to the FaxRcv memory map view
LPBYTE pFaxRcvView;
// szTiffFile is the name of the received fax
LPWSTR szTiffFile;
// szFile is the name of the received fax
WCHAR szFile[_MAX_FNAME];
// szExt is the extension of the received fax
WCHAR szExt[_MAX_EXT];
// FaxReceiveInfo is the fax receive info
FAX_RECEIVE_INFO FaxReceiveInfo;
DWORD dwRslt;
UINT uRslt;
UINT_PTR upOffset;
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_WAITING, 0);
// Open FaxRcv named event
hFaxRcvEvent = OpenEvent(SYNCHRONIZE, FALSE, FAXRCV_EVENT);
// Open FaxRcv named mutex
hFaxRcvMutex = OpenMutex(SYNCHRONIZE, FALSE, FAXRCV_MUTEX);
if ((!hFaxRcvEvent) || (!hFaxRcvMutex)) {
if (hFaxRcvEvent) {
CloseHandle(hFaxRcvEvent);
}
if (hFaxRcvMutex) {
CloseHandle(hFaxRcvMutex);
}
return IDS_STATUS_FAXSVC_ENDED;
}
// Update phFaxStopRcvEvents
// hFaxRcvEvent
phFaxStopRcvEvents[2] = hFaxRcvEvent;
// Wait for FaxRcv named mutex
WaitForSingleObject(hFaxRcvMutex, INFINITE);
// Enable the FaxRcv Routing Extension
fnEnableFaxRcv(TRUE);
// Release access to the FaxRcv named mutex
ReleaseMutex(hFaxRcvMutex);
g_bFaxRcvInProgress = TRUE;
// Wait for Fax, Stop or FaxRcv named event
dwRslt = WaitForMultipleObjects(3, phFaxStopRcvEvents, FALSE, dwReceiveTimeout);
g_bFaxRcvInProgress = FALSE;
// Wait for FaxRcv named mutex
WaitForSingleObject(hFaxRcvMutex, INFINITE);
// Disable the FaxRcv Routing Extension
fnEnableFaxRcv(FALSE);
switch (dwRslt) {
case WAIT_TIMEOUT:
uRslt = IDS_STATUS_TIMEOUT_ENDED;
break;
case WAIT_OBJECT_0:
uRslt = IDS_STATUS_FAXSVC_ENDED;
break;
case (WAIT_OBJECT_0 + 1):
uRslt = IDS_STATUS_ITERATION_STOPPED;
break;
case (WAIT_OBJECT_0 + 2):
uRslt = IDS_STATUS_FAX_RECEIVED;
break;
}
if (uRslt != IDS_STATUS_FAX_RECEIVED) {
// Release access to the FaxRcv named mutex
ReleaseMutex(hFaxRcvMutex);
CloseHandle(hFaxRcvEvent);
CloseHandle(hFaxRcvMutex);
return uRslt;
}
// Open FaxRcv memory map
hFaxRcvMap = OpenFileMapping(FILE_MAP_READ, FALSE, FAXRCV_MAP);
if (!hFaxRcvMap) {
// Release access to the FaxRcv named mutex
ReleaseMutex(hFaxRcvMutex);
CloseHandle(hFaxRcvEvent);
CloseHandle(hFaxRcvMutex);
return IDS_STATUS_FAXSVC_ENDED;
}
// Create FaxRcv memory map view
pFaxRcvView = (LPBYTE) MapViewOfFile(hFaxRcvMap, FILE_MAP_READ, 0, 0, 0);
// Set upOffset
upOffset = 0;
// Set szTiffFile
szTiffFile = MemAllocMacro((lstrlen((LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset)) + 1) * sizeof(WCHAR));
lstrcpy(szTiffFile, (LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset));
upOffset += (lstrlen(szTiffFile) + 1) * sizeof(WCHAR);
// Initialize szTsid
ZeroMemory(szTsid, dwTsidSize);
// Set szTsid
lstrcpy(szTsid, (LPWSTR) ((UINT_PTR) pFaxRcvView + upOffset));
upOffset += (lstrlen(szTsid) + 1) * sizeof(WCHAR);
// Set FaxReceiveInfo.dwDeviceId
FaxReceiveInfo.dwDeviceId = (DWORD) *(LPDWORD) ((UINT_PTR) pFaxRcvView + upOffset);
// Close FaxRcv memory map view
UnmapViewOfFile(pFaxRcvView);
// Close FaxRcv memory map
CloseHandle(hFaxRcvMap);
_wsplitpath(szTiffFile, NULL, NULL, szFile, szExt);
// Initialize szCopyTiffFile
ZeroMemory(szCopyTiffFile, dwCopyTiffFileSize * sizeof(WCHAR));
// Set szCopyTiffFile
GetCurrentDirectory(dwCopyTiffFileSize, szCopyTiffFile);
lstrcat(szCopyTiffFile, L"\\");
lstrcat(szCopyTiffFile, (LPWSTR) ((UINT_PTR) szFile + lstrlen(L"Copy of ") * sizeof(WCHAR)));
lstrcat(szCopyTiffFile, szExt);
// Initialize szCopyTiffName
ZeroMemory(szCopyTiffName, dwCopyTiffNameSize);
// Set szCopyTiffName
lstrcpy(szCopyTiffName, (LPWSTR) ((UINT_PTR) szFile + lstrlen(L"Copy of ") * sizeof(WCHAR)));
lstrcat(szCopyTiffName, szExt);
// Set FaxReceiveInfo.szCopyTiffName
FaxReceiveInfo.szCopyTiffName = szCopyTiffName;
// Copy szTiffFile to szCopyTiffFile
CopyFile(szTiffFile, szCopyTiffFile, FALSE);
// Delete the received fax
DeleteFile(szTiffFile);
// Free szTiffFile
MemFreeMacro(szTiffFile);
// Release access to the FaxRcv named mutex
ReleaseMutex(hFaxRcvMutex);
CloseHandle(hFaxRcvEvent);
CloseHandle(hFaxRcvMutex);
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_RECEIVED, (LPARAM) &FaxReceiveInfo);
return IDS_STATUS_FAX_RECEIVED;
}
DWORD WINAPI fnSendProc (LPVOID lpv)
/*++
Routine Description:
Thread to handle the Send logic
Return Value:
DWORD - exit code
--*/
{
// hFaxExitStartEvents is a pointer to the g_hFaxEvent, g_hExitEvent and g_hStartEvent
HANDLE hFaxExitStartEvents[3];
// hFaxStopRasPassFailEvents is a pointer to the g_hFaxEvent, g_hStopEvent, g_hRasPassedEvent and g_hRasFailedEvent
HANDLE hFaxStopRasPassFailEvents[4];
// hFaxStopSendPassFailEvents is a pointer to the g_hFaxEvent, g_hStopEvent, g_hSendPassedEvent and g_hSendFailedEvent
HANDLE hFaxStopSendPassFailEvents[4];
// hFaxStopRcvEvents is a pointer to the g_hFaxEvent, g_hStopEvent and g_hFaxRcvEvent
HANDLE hFaxStopRcvEvents[3];
// dwSendTimeout is the send timeout interval
DWORD dwSendTimeout;
// dwReceiveTimeout is the receive timeout interval
DWORD dwReceiveTimeout;
// szOriginalTiffFile is the name of the original tiff file
LPWSTR szOriginalTiffFile;
// dwNumFaxesToSend is the number of faxes to be sent
DWORD dwNumFaxesToSend;
// dwNumFaxesRemaining is the number of faxes remaining to be sent
DWORD dwNumFaxesRemaining;
// FaxJobParams is the fax job params
FAX_JOB_PARAM FaxJobParams;
// szCopyTiffFile is the name of the copy of the received fax
WCHAR szCopyTiffFile[_MAX_PATH];
// szCopyTiffName is the name of the copy of the received fax
WCHAR szCopyTiffName[_MAX_FNAME + _MAX_EXT];
// szReceivedTsid is the received TSID
WCHAR szReceivedTsid[ENCODE_CHAR_LEN + CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1];
// szEncodedTsid is the encoded TSID
WCHAR szEncodedTsid[ENCODE_CHAR_LEN + CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1];
// szDecodedTsid is the decoded TSID
WCHAR szDecodedTsid[PHONE_NUM_LEN + 1];
DWORD dwPages;
DWORD dwRslt;
UINT uRslt;
// Set hFaxExitStartEvents
// g_hFaxEvent
hFaxExitStartEvents[0] = g_hFaxEvent;
// g_hExitEvent
hFaxExitStartEvents[1] = g_hExitEvent;
// g_hStartEvent
hFaxExitStartEvents[2] = g_hStartEvent;
// Set hFaxStopRasPassFailEvents
// g_hFaxEvent
hFaxStopRasPassFailEvents[0] = g_hFaxEvent;
// g_hStopEvent
hFaxStopRasPassFailEvents[1] = g_hStopEvent;
// g_hPassEvent
hFaxStopRasPassFailEvents[2] = g_hRasPassedEvent;
// g_hFailEvent
hFaxStopRasPassFailEvents[3] = g_hRasFailedEvent;
// Set hFaxStopSendPassFailEvents
// g_hFaxEvent
hFaxStopSendPassFailEvents[0] = g_hFaxEvent;
// g_hStopEvent
hFaxStopSendPassFailEvents[1] = g_hStopEvent;
// g_hSendPassedEvent
hFaxStopSendPassFailEvents[2] = g_hSendPassedEvent;
// g_hSendFailedEvent
hFaxStopSendPassFailEvents[3] = g_hSendFailedEvent;
// Set hFaxStopRcvEvents
// g_hFaxEvent
hFaxStopRcvEvents[0] = g_hFaxEvent;
// g_hStopEvent
hFaxStopRcvEvents[1] = g_hStopEvent;
if (g_bBVT) {
dwSendTimeout = FAXSVC_RETRIES * ((FAXSVC_RETRIES + 1) * FAXSVC_RETRYDELAY) * 60000;
dwReceiveTimeout = dwSendTimeout * 2;
szOriginalTiffFile = FAXBVT_TIF;
dwNumFaxesToSend = FAXBVT_NUM_FAXES;
dwNumFaxesRemaining = dwNumFaxesToSend;
}
else {
dwSendTimeout = INFINITE;
dwReceiveTimeout = INFINITE;
szOriginalTiffFile = FAXWHQL_TIF;
dwNumFaxesToSend = FAXWHQL_NUM_FAXES;
dwNumFaxesRemaining = dwNumFaxesToSend;
}
while (TRUE) {
// Wait for Fax, Exit, or Start event
dwRslt = WaitForMultipleObjects(3, hFaxExitStartEvents, FALSE, INFINITE);
if (dwRslt == WAIT_OBJECT_0) {
SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
continue;
}
else if (dwRslt == (WAIT_OBJECT_0 + 1)) {
return 0;
}
if (g_bSend) {
if (g_bRasEnabled) {
// Send a RAS call
uRslt = fnSendRas(hFaxStopRasPassFailEvents);
if (uRslt != IDS_STATUS_RAS_PASSED) {
switch (uRslt) {
case IDS_STATUS_TIMEOUT_ENDED:
SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
break;
case IDS_STATUS_FAXSVC_ENDED:
SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
break;
case IDS_STATUS_ITERATION_STOPPED:
SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
break;
case IDS_STATUS_RAS_FAILED:
SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
break;
}
dwNumFaxesRemaining = dwNumFaxesToSend;
continue;
}
}
// Encode the TSID
if (!g_bNoCheck) {
fnEncodeTsid(g_szRcvNumber, TX_CONTROL_CHARS, szEncodedTsid);
}
else {
lstrcpy(szEncodedTsid, g_szSndNumber);
}
// Initialize FaxJobParams
ZeroMemory(&FaxJobParams, sizeof(FAX_JOB_PARAM));
// Set FaxJobParams
FaxJobParams.SizeOfStruct = sizeof(FAX_JOB_PARAM);
FaxJobParams.RecipientNumber = g_szSndNumber;
FaxJobParams.RecipientName = g_szSndNumber;
FaxJobParams.Tsid = szEncodedTsid;
FaxJobParams.ScheduleAction = JSA_NOW;
// Send a fax
uRslt = fnSendFax(FaxJobParams, szOriginalTiffFile, hFaxStopSendPassFailEvents, dwSendTimeout);
if (uRslt != IDS_STATUS_FAX_SEND_PASSED) {
switch (uRslt) {
case IDS_STATUS_TIMEOUT_ENDED:
SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
break;
case IDS_STATUS_FAXSVC_ENDED:
SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
break;
case IDS_STATUS_ITERATION_STOPPED:
SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
break;
case IDS_STATUS_FAX_SEND_FAILED:
SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
break;
}
dwNumFaxesRemaining = dwNumFaxesToSend;
continue;
}
}
// Receive a fax
uRslt = fnReceiveFax(hFaxStopRcvEvents, dwReceiveTimeout, szReceivedTsid, sizeof(szReceivedTsid) / sizeof(WCHAR), szCopyTiffFile, sizeof(szCopyTiffFile) / sizeof(WCHAR), szCopyTiffName, sizeof(szCopyTiffName) / sizeof(WCHAR));
if (uRslt != IDS_STATUS_FAX_RECEIVED) {
switch (uRslt) {
case IDS_STATUS_TIMEOUT_ENDED:
SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
break;
case IDS_STATUS_FAXSVC_ENDED:
SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
break;
case IDS_STATUS_ITERATION_STOPPED:
SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
break;
}
if (g_bSend) {
if (uRslt != IDS_STATUS_ITERATION_STOPPED) {
// This iteration failed
SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
}
// Reset the number of faxes remaining to be sent
dwNumFaxesRemaining = dwNumFaxesToSend;
}
continue;
}
if (!g_bNoCheck) {
if (!fnDecodeTsid(szReceivedTsid, g_bSend ? RX_CONTROL_CHARS : TX_CONTROL_CHARS, szDecodedTsid)) {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_INVALID, 0);
if (g_bSend) {
// This iteration failed
SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
// Reset the number of faxes remaining to be sent
dwNumFaxesRemaining = dwNumFaxesToSend;
}
else {
// Set the g_hStartEvent to start another cycle to receive a fax
SetEvent(g_hStartEvent);
}
continue;
}
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_ID, (LPARAM) szReceivedTsid);
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, IDS_STATUS_FAX_VERIFYING, (LPARAM) szCopyTiffName);
// Verify the tiff
uRslt = fnVerifyTiff(szCopyTiffFile, &dwPages);
if ((uRslt == ERROR_SUCCESS) && (((g_bBVT) && (dwPages == FAXBVT_PAGES)) || ((!g_bBVT) && (dwPages == FAXWHQL_PAGES)))) {
// Fax is valid
uRslt = IDS_TIFF_VALID_TIFF;
}
else if (uRslt == ERROR_SUCCESS) {
// Each page is valid, but missing pages
uRslt = IDS_TIFF_INVALID_PAGES;
}
if (uRslt == IDS_TIFF_INVALID_PAGES) {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, uRslt, dwPages);
}
else {
// Update the status
SendMessage(g_hWndDlg, UM_UPDATE_STATUS, uRslt, 0);
}
}
else {
lstrcpy(szDecodedTsid, szReceivedTsid);
uRslt = IDS_TIFF_VALID_TIFF;
}
if ((g_bSend) && (uRslt == IDS_TIFF_VALID_TIFF)) {
// Decrement the number of faxes remaining to be sent
dwNumFaxesRemaining--;
if (dwNumFaxesRemaining == 0) {
// All faxes have been sent, so this iteration passed
SendMessage(g_hWndDlg, UM_ITERATION_PASSED, 0, 0);
// Reset the number of faxes remaining to be sent
dwNumFaxesRemaining = dwNumFaxesToSend;
}
else {
// There are faxes remaining to be sent, so set the g_hStartEvent to start another cycle to send a fax
SetEvent(g_hStartEvent);
}
continue;
}
else if (g_bSend) {
// This iteration failed
SendMessage(g_hWndDlg, UM_ITERATION_FAILED, 0, 0);
// Reset the number of faxes remaining to be sent
dwNumFaxesRemaining = dwNumFaxesToSend;
continue;
}
else if (uRslt != IDS_TIFF_VALID_TIFF) {
// Set the g_hStartEvent to start another cycle to receive a fax
SetEvent(g_hStartEvent);
continue;
}
if (!g_bSend) {
// Encode the TSID
if (!g_bNoCheck) {
fnEncodeTsid(szDecodedTsid, RX_CONTROL_CHARS, szEncodedTsid);
}
else {
lstrcpy(szEncodedTsid, szDecodedTsid);
}
// Initialize FaxJobParams
ZeroMemory(&FaxJobParams, sizeof(FAX_JOB_PARAM));
// Set FaxJobParams
FaxJobParams.SizeOfStruct = sizeof(FAX_JOB_PARAM);
FaxJobParams.RecipientNumber = szDecodedTsid;
FaxJobParams.RecipientName = szDecodedTsid;
FaxJobParams.Tsid = szEncodedTsid;
FaxJobParams.ScheduleAction = JSA_NOW;
// Send a fax
uRslt = fnSendFax(FaxJobParams, szCopyTiffFile, hFaxStopSendPassFailEvents, dwSendTimeout);
switch (uRslt) {
case IDS_STATUS_TIMEOUT_ENDED:
SendMessage(g_hWndDlg, UM_TIMEOUT_ENDED, 0, 0);
break;
case IDS_STATUS_FAXSVC_ENDED:
SendMessage(g_hWndDlg, UM_FAXSVC_ENDED, 0, 0);
break;
case IDS_STATUS_ITERATION_STOPPED:
SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
break;
case IDS_STATUS_FAX_SEND_PASSED:
case IDS_STATUS_FAX_SEND_FAILED:
break;
}
if ((uRslt == IDS_STATUS_FAX_SEND_PASSED) || (uRslt == IDS_STATUS_FAX_SEND_FAILED)) {
if (g_bBVT) {
SendMessage(g_hWndDlg, UM_ITERATION_STOPPED, 0, 0);
SendMessage(GetDlgItem(g_hWndDlg, IDC_EXIT_BUTTON), BM_CLICK, 0, 0);
}
else {
// Set the g_hStartEvent to start another cycle to wait for a fax
SetEvent(g_hStartEvent);
}
}
continue;
}
}
}
#endif