|
|
#include "nc.h"
#pragma hdrstop
HANDLE MyHeapHandle; HINSTANCE MyhInstance; HLINEAPP MyLineAppHandle; CONFIG_DATA ConfigData;
void FaxDevPrintErrorMsg( HANDLE FaxHandle, LPTSTR Format, ... ) { #if DBG
NcSTHandle status = NULL; ULONG statusCode; CHAR errorString[256]; size_t Size; LPWSTR p; TCHAR buf[1024]; va_list arg_ptr;
status = STCreateFaxStatusObject( JobInfo(FaxHandle)->ServerId, JobInfo(FaxHandle)->JobId ); STSetConnectionInfo( status, JobInfo(FaxHandle)->connInfo ); statusCode = STGetLastError( status ); STGetLastErrorString( status, errorString, &Size ); p = AnsiStringToUnicodeString( errorString );
va_start( arg_ptr, Format ); _vsnwprintf( buf, sizeof(buf), Format, arg_ptr ); va_end( arg_ptr );
DebugPrint(( L"%s: %s", buf, p ));
STDestroyFaxStatusObject( status ); #endif
}
extern "C" DWORD CALLBACK FaxDevDllInit( HINSTANCE hInstance, DWORD Reason, LPVOID Context ) { if (Reason == DLL_PROCESS_ATTACH) { MyhInstance = hInstance; DisableThreadLibraryCalls( hInstance ); }
return TRUE; }
void CALLBACK MyLineCallback( IN HANDLE FaxHandle, IN DWORD hDevice, IN DWORD dwMessage, IN DWORD dwInstance, IN DWORD dwParam1, IN DWORD dwParam2, IN DWORD dwParam3 ) { return; }
BOOL WINAPI FaxDevInitialize( IN HLINEAPP LineAppHandle, IN HANDLE HeapHandle, OUT PFAX_LINECALLBACK *LineCallbackFunction, IN PFAX_SERVICE_CALLBACK FaxServiceCallback ) { MyHeapHandle = HeapHandle; MyLineAppHandle = LineAppHandle; *LineCallbackFunction = MyLineCallback; HeapInitialize( MyHeapHandle, NULL, NULL, 0 ); InitCommonControls(); GetNcConfig( &ConfigData ); return TRUE; }
BOOL WINAPI FaxDevVirtualDeviceCreation( OUT LPDWORD DeviceCount, OUT LPWSTR DeviceNamePrefix, OUT LPDWORD DeviceIdPrefix, IN HANDLE CompletionPort, IN DWORD CompletionKey ) { *DeviceCount = 1; wcscpy( DeviceNamePrefix, L"NetCentric" ); *DeviceIdPrefix = 69000; return TRUE; }
BOOL WINAPI FaxDevStartJob( IN HLINE LineHandle, IN DWORD DeviceId, OUT PHANDLE FaxHandle, IN HANDLE CompletionPortHandle, IN DWORD CompletionKey ) { LPSTR s;
*FaxHandle = (PHANDLE) MemAlloc( sizeof(JOB_INFO) ); if (!*FaxHandle) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return FALSE; }
JobInfo(*FaxHandle)->LineHandle = LineHandle; JobInfo(*FaxHandle)->DeviceId = DeviceId; JobInfo(*FaxHandle)->CompletionPortHandle = CompletionPortHandle; JobInfo(*FaxHandle)->CompletionKey = CompletionKey;
JobInfo(*FaxHandle)->faxJob = new CNcFaxJob; JobInfo(*FaxHandle)->connInfo = new CNcConnectionInfo; JobInfo(*FaxHandle)->sender = new CNcUser; JobInfo(*FaxHandle)->recipient = new CNcUser;
s = UnicodeStringToAnsiString( ConfigData.ServerName ); JobInfo(*FaxHandle)->connInfo->SetHostName( s ); MemFree( s );
s = UnicodeStringToAnsiString( ConfigData.UserName ); JobInfo(*FaxHandle)->connInfo->SetAccountName( s ); MemFree( s );
s = UnicodeStringToAnsiString( ConfigData.Password ); JobInfo(*FaxHandle)->connInfo->SetPassword( s ); MemFree( s );
JobInfo(*FaxHandle)->connInfo->SetClientIdentification( PRODUCTION_KEY, NCFAX_ID, NCFAX_CLIENTID, NCFAX_MAJOR, NCFAX_MINOR, NCFAX_RELEASE, NCFAX_PATCH );
return TRUE; }
BOOL WINAPI FaxDevEndJob( IN HANDLE FaxHandle ) { delete JobInfo(FaxHandle)->faxJob; delete JobInfo(FaxHandle)->connInfo; delete JobInfo(FaxHandle)->sender; delete JobInfo(FaxHandle)->recipient;
MemFree( FaxHandle );
return TRUE; }
VOID SetStatusValues( PFAX_DEV_STATUS FaxStatus, ULONG StatusCode, ULONG ExtStatusCode ) { FaxStatus->ErrorCode = 0;
switch( StatusCode ) { case ST_STATUS_PENDING: switch( ExtStatusCode ) { case ST_EXT_BUSY: FaxStatus->StatusId = FS_BUSY; break;
case ST_EXT_NO_ANSWER: FaxStatus->StatusId = FS_NO_ANSWER; break;
case ST_EXT_NO_RINGBACK: FaxStatus->StatusId = FS_NO_DIAL_TONE; break;
case ST_EXT_DEST_FAX_REFUSED: FaxStatus->StatusId = FS_BAD_ADDRESS; break;
// case ST_EXT_COMMUNICATION_ERROR:
// FaxStatus->StatusId = FS_INITIALIZING;
// break;
} break;
case ST_STATUS_ACTIVE: switch( ExtStatusCode ) { case ST_EXT_ACTIVE_DIALING: FaxStatus->StatusId = FS_DIALING; break;
case ST_EXT_ACTIVE_CONNECTING: FaxStatus->StatusId = FS_TRANSMITTING; break;
case ST_EXT_ACTIVE_TRANSMISSION_BEGIN: FaxStatus->StatusId = FS_TRANSMITTING; break;
case ST_EXT_ACTIVE_PAGE_SENT: FaxStatus->StatusId = FS_TRANSMITTING; break; } break;
case ST_STATUS_FAILED: FaxStatus->StatusId = FS_FATAL_ERROR; FaxStatus->ErrorCode = ExtStatusCode; break; }
FaxStatus->SizeOfStruct = sizeof(FAX_DEV_STATUS); FaxStatus->StringId = 0; FaxStatus->PageCount = 0; FaxStatus->CSI = NULL; FaxStatus->CallerId = NULL; FaxStatus->RoutingInfo = NULL; FaxStatus->Reserved[0] = 0; FaxStatus->Reserved[1] = 0; FaxStatus->Reserved[2] = 0; }
BOOL FaxDevPostStatus( ULONG StatusCode, ULONG ExtStatusCode, HANDLE CompletionPort, DWORD CompletionKey ) { DWORD FaxDevStatusSize = 4096; PFAX_DEV_STATUS FaxStatus;
FaxStatus = (PFAX_DEV_STATUS) HeapAlloc( MyHeapHandle, HEAP_ZERO_MEMORY, FaxDevStatusSize ); if (!FaxStatus) { return FALSE; }
SetStatusValues( FaxStatus, StatusCode, ExtStatusCode );
PostQueuedCompletionStatus( CompletionPort, FaxDevStatusSize, CompletionKey, (LPOVERLAPPED) FaxStatus );
return TRUE; }
BOOL ParsePhoneNumber( LPWSTR PhoneNumber, LPSTR *CountryCode, LPSTR *AreaCode, LPSTR *SubscriberNumber ) { BOOL rVal = FALSE; LPWSTR p; LPWSTR h;
*CountryCode = NULL; *AreaCode = NULL; *SubscriberNumber = NULL;
if (*PhoneNumber == L'+') {
//
// canonical address
//
p = PhoneNumber;
h = p + 1; while( *p != L' ') p++; *p = 0;
*CountryCode = UnicodeStringToAnsiString( h ); if (!*CountryCode) { goto exit; }
p += 1; while( *p == L' ') p++;
if (*p == L'(') { h = p + 1; while( *p != L')') p++; *p = 0; *AreaCode = UnicodeStringToAnsiString( h ); if (!*AreaCode) { goto exit; } p += 1; while( *p == L' ') p++; }
*SubscriberNumber = UnicodeStringToAnsiString( p ); if (!*SubscriberNumber) { goto exit; }
} else {
//
// non-canonical address
//
p = wcschr( PhoneNumber, L'-' ); if (!p) { //
// malformed address
//
goto exit; }
if (!wcschr( PhoneNumber, L'-' )) {
//
// the address does not contain an area code
//
*SubscriberNumber = UnicodeStringToAnsiString( PhoneNumber ); if (!*SubscriberNumber) { goto exit; }
*CountryCode = UnicodeStringToAnsiString( L"" ); if (!*CountryCode) { goto exit; }
*AreaCode = UnicodeStringToAnsiString( L"" ); if (!*AreaCode) { goto exit; }
} else {
*SubscriberNumber = UnicodeStringToAnsiString( p+1 ); if (!*SubscriberNumber) { goto exit; }
*CountryCode = UnicodeStringToAnsiString( L"" ); if (!*CountryCode) { goto exit; }
*p = 0;
*AreaCode = UnicodeStringToAnsiString( PhoneNumber ); if (!*AreaCode) { goto exit; }
*p = L'-';
}
}
rVal = TRUE;
exit:
if (!rVal) { MemFree( *CountryCode ); MemFree( *AreaCode ); MemFree( *SubscriberNumber ); }
return rVal; }
BOOL WINAPI FaxDevSend( IN HANDLE FaxHandle, IN PFAX_SEND FaxSend, IN PFAX_SEND_CALLBACK FaxSendCallback ) { #define BUFFER_SIZE 4096
BOOL rVal = FALSE; LPSTR s; LPSTR CountryCode = NULL; LPSTR AreaCode = NULL; LPSTR SubscriberNumber = NULL; NcSTHandle status = NULL; ULONG statusCode; ULONG extCode; CHAR errorString[256]; CHAR extStatusVal[256]; LPWSTR ErrorStringW = NULL; size_t Size; NcFileType_t fileType; PhoneNumberStruct PhoneNumber = {0}; DWORD PollInterval = 15000;
errorString[0] = 0;
//
// parse the receiver's fax number
//
if (!ParsePhoneNumber( FaxSend->ReceiverNumber, &CountryCode, &AreaCode, &SubscriberNumber )) { DebugPrint(( L"FaxDevSend: bad phone number, %s", FaxSend->ReceiverNumber )); goto exit; }
//
// set the connection information
//
if (!JobInfo(FaxHandle)->faxJob->SetConnectionInfo( JobInfo(FaxHandle)->connInfo )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetConnectionInfo failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
//
// set the sender information
//
s = UnicodeStringToAnsiString( FaxSend->CallerName ); if (!JobInfo(FaxHandle)->sender->SetFirstName( s )) { MemFree( s ); Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetFirstName failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; } MemFree( s );
if (!ParsePhoneNumber( FaxSend->CallerNumber, &PhoneNumber.CC, &PhoneNumber.AC, &PhoneNumber.EX )) { goto exit; }
if (!JobInfo(FaxHandle)->sender->SetPhoneNumber( &PhoneNumber )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetPhoneNumber failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
//
// set the recipient information
//
s = UnicodeStringToAnsiString( FaxSend->ReceiverName ); if (!JobInfo(FaxHandle)->recipient->SetFirstName( s )) { MemFree( s ); Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetFirstName failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; } MemFree( s );
if (!JobInfo(FaxHandle)->recipient->SetFaxNumber( CountryCode, AreaCode, SubscriberNumber )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetFaxNumber failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
CHAR TempPath[256]; GetTempPathA( sizeof(TempPath), TempPath );
if (!JobInfo(FaxHandle)->faxJob->SetWorkingDirectory( TempPath, "NcFax", TRUE )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetWorkingDirectory failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); LPCSTR cwd = JobInfo(FaxHandle)->faxJob->GetWorkingDirectory(); goto exit; }
if (!JobInfo(FaxHandle)->faxJob->SetSender( JobInfo(FaxHandle)->sender )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetSender failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
if (!JobInfo(FaxHandle)->faxJob->SetRecipient( JobInfo(FaxHandle)->recipient)) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetRecipient failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
if (!JobInfo(FaxHandle)->faxJob->SetSubject( "" )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SetSubject failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
s = UnicodeStringToAnsiString( FaxSend->FileName );
if (!NcGetFileTypeFromFileData( s, &fileType )) { MemFree( s ); DebugPrint(( L"FaxDevSend: NcGetFileTypeFromFileData" )); goto exit; }
if (!JobInfo(FaxHandle)->faxJob->AddFile( s, fileType )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: AddFile failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); MemFree( s ); goto exit; } MemFree( s );
JobInfo(FaxHandle)->faxJob->SetNotifyByEmail( FALSE );
if (!JobInfo(FaxHandle)->faxJob->SendJob( &JobInfo(FaxHandle)->ServerId, &JobInfo(FaxHandle)->JobId )) { Size = sizeof(errorString); JobInfo(FaxHandle)->faxJob->GetLastErrorString( errorString, &Size ); DebugPrint(( L"FaxDevSend: SendJob failed, %s", ErrorStringW = AnsiStringToUnicodeString(errorString) )); goto exit; }
//
// poll the netcentric fax server for status
// information. we sit in this loop until the
// fax is sent.
//
status = STCreateFaxStatusObject( JobInfo(FaxHandle)->ServerId, JobInfo(FaxHandle)->JobId );
STSetConnectionInfo( status, JobInfo(FaxHandle)->connInfo );
while( TRUE ) {
if (!STFaxUpdate( status )) { statusCode = STGetLastError( status ); if (statusCode == ST_MIN_POLL_NOT_EXCEEDED) { Sleep( PollInterval ); continue; } FaxDevPrintErrorMsg( FaxHandle, L"STFaxUpdate() failed" ); break; }
statusCode = STGetStatusCode( status );
Size = sizeof( extStatusVal ); STGetExtendedStatus( status, &extCode, extStatusVal, &Size );
DebugPrint(( L"statusCode=%04x, extCode=%04x", statusCode, extCode ));
FaxDevPostStatus( statusCode, extCode, JobInfo(FaxHandle)->CompletionPortHandle, JobInfo(FaxHandle)->CompletionKey );
if (IS_DONE_STATUS(statusCode)) { DebugPrint(( L"Job finished, returning from FaxDevSend()" )); break; }
// PollInterval = STGetNextRecommendedUpdate(status) * 1000;
DebugPrint(( L"Next poll in %dms", PollInterval )); Sleep( PollInterval ); }
rVal = TRUE;
exit:
if (status) { STDestroyFaxStatusObject( status ); }
MemFree( CountryCode ); MemFree( AreaCode ); MemFree( SubscriberNumber );
MemFree( PhoneNumber.CC ); MemFree( PhoneNumber.AC ); MemFree( PhoneNumber.EX );
MemFree( ErrorStringW );
if (!rVal && errorString[0]) { }
return rVal; }
BOOL WINAPI FaxDevReceive( IN HANDLE FaxHandle, IN HCALL CallHandle, IN OUT PFAX_RECEIVE FaxReceive ) { return TRUE; }
BOOL WINAPI FaxDevReportStatus( IN HANDLE FaxHandle OPTIONAL, OUT PFAX_DEV_STATUS FaxStatus, IN DWORD FaxStatusSize, OUT LPDWORD FaxStatusSizeRequired ) { NcSTHandle status; ULONG statusCode; ULONG extCode; CHAR extStatusVal[256]; size_t Size;
if (FaxStatus == NULL && FaxStatusSize == 0) { //
// caller wants to know how big to allocate
//
if (FaxStatusSizeRequired) { *FaxStatusSizeRequired = 4096; } SetLastError( ERROR_INSUFFICIENT_BUFFER ); return FALSE; }
if (FaxStatus == NULL || FaxStatusSize == 0) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; }
status = STCreateFaxStatusObject( JobInfo(FaxHandle)->ServerId, JobInfo(FaxHandle)->JobId );
STSetConnectionInfo( status, JobInfo(FaxHandle)->connInfo );
if (!STFaxUpdate( status )) { STDestroyFaxStatusObject( status ); return FALSE; }
statusCode = STGetStatusCode( status );
Size = sizeof( extStatusVal ); STGetExtendedStatus( status, &extCode, extStatusVal, &Size );
SetStatusValues( FaxStatus, statusCode, extCode );
STDestroyFaxStatusObject( status );
return TRUE; }
BOOL WINAPI FaxDevAbortOperation( IN HANDLE FaxHandle ) { if (!JobInfo(FaxHandle)->faxJob->StopJob( JobInfo(FaxHandle)->connInfo, JobInfo(FaxHandle)->ServerId, JobInfo(FaxHandle)->JobId )) { FaxDevPrintErrorMsg( FaxHandle, L"CNcFaxJob::StopJob() failed" ); return FALSE; }
return TRUE; }
|