windows-nt/Source/XPSP1/NT/printscan/fax/samples/ncfsp/netcntrc.cpp
2020-09-26 16:20:57 +08:00

728 lines
18 KiB
C++

#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;
}