1094 lines
32 KiB
C
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
|