R
Robert Freas
Hi,
I have declared a bunch of WinFax.DLL exports as static externs in
..NET using the DllImportAttribute(). I am basing my code off the
Simple.c found in the Platform SDK in the Samples\netds\fax\SampleSend
directory. All the defined externs/structures/code is at the bottom
of this message.
As you can see below, the SendFax() method is based on the
SimpleSend.c sample in the Platform SDK. Everything works up until
the FaxSendDocument() API call. GetLastWin32Error returns 87--Invalid
parameter. The documentation suggests that I am missing a required
parameter--but, there are only 3:
jobParam.RecipientNumber = "5551212";
jobParam.ScheduleAction = (int) FAX_ENUM_JOB_SEND_ATTRIBUTES.JSA_NOW;
jobParam.CallHandle = new IntPtr(0);
....and I've set them all; NOTE: the documentation says that CALLHANDLE
must be NULL--so I set it to a "null" IntPtr.
Anyone have any ideas what is going on?
BTW, using the legacy WinFax.dll APIs are a requirement for me as I
need to leverage IOCompletionPorts in order to make sending a Fax a
synchronous operation; therefore, I cannot use the FaxCom COM objects.
Thanks for any help!
Rob
--
public abstract class Win32
{
public static readonly int INFINITE = -1;
public static readonly int INVALID_HANDLE_VALUE = -1;
[DllImport("kernel32")]
public static extern int CreateIoCompletionPort(int FileHandle, int
ExistingCompletionPort, int CompletionKey, int
NumberOfConcurrentThreads);
[DllImport("kernel32")]
public static extern int GetQueuedCompletionStatus(int
CompletionPort, ref int
lpNumberOfBytesTransferred, ref int lpCompletionKey, IntPtr
lpOverlapped, int dwMilliseconds);
[DllImport("kernel32")]
public static extern int CloseHandle(int hObject);
}
public abstract class WinFax
{
#region Enumerations
public enum FAX_PORT_OPEN_TYPE
{
PORT_OPEN_QUERY = 1,
PORT_OPEN_MODIFY = 2
}
public enum FAX_ENUM_JOB_SEND_ATTRIBUTES
{
JSA_NOW = 0, // Send now
JSA_SPECIFIC_TIME, // Send at specific time
JSA_DISCOUNT_PERIOD // Send at server configured
discount period
}
[FlagsAttribute()]
public enum WinFaxEvent
{
FEI_DIALING = 0x00000001,
FEI_SENDING = 0x00000002,
FEI_RECEIVING = 0x00000003,
FEI_COMPLETED = 0x00000004,
FEI_BUSY = 0x00000005,
FEI_NO_ANSWER = 0x00000006,
FEI_BAD_ADDRESS = 0x00000007,
FEI_NO_DIAL_TONE = 0x00000008,
FEI_DISCONNECTED = 0x00000009,
FEI_FATAL_ERROR = 0x0000000a,
FEI_NOT_FAX_CALL = 0x0000000b,
FEI_CALL_DELAYED = 0x0000000c,
FEI_CALL_BLACKLISTED = 0x0000000d,
FEI_RINGING = 0x0000000e,
FEI_ABORTING = 0x0000000f,
FEI_ROUTING = 0x00000010,
FEI_MODEM_POWERED_ON = 0x00000011,
FEI_MODEM_POWERED_OFF = 0x00000012,
FEI_IDLE = 0x00000013,
FEI_FAXSVC_ENDED = 0x00000014,
FEI_ANSWERED = 0x00000015,
FEI_JOB_QUEUED = 0x00000016,
FEI_DELETED = 0x00000017,
FEI_INITIALIZING = 0x00000018,
FEI_LINE_UNAVAILABLE = 0x00000019,
FEI_HANDLED = 0x0000001a,
FEI_FAXSVC_STARTED = 0x0000001b
}
#endregion
#region Structs
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_DEVICE_STATUS
{
public int SizeOfStruct; // size
of this structure
public string CallerId; // caller id
string
public string Csid; // station
identifier
public int CurrentPage; //
current page
public int DeviceId; //
permanent line id
public string DeviceName; // device name
public string DocumentName; // document name
public int JobType; // send
or receive?
public string PhoneNumber; // sending phone
number
public string RoutingString; // routing
information
public string SenderName; // sender name
public string RecipientName; // recipient
name
public int Size; // size
in bytes of the document
public FILETIME StartTime; // starting
time of the fax
send/receive
public int Status; //
current status of the device, see FPS_??? masks
public string StatusString; // status string
if the Status field is zero. this may be NULL.
public FILETIME SubmittedTime; // time the
document was submitted
public int TotalPages; // total
number of pages in this job
public string Tsid; // transmitting
station identifier
public string UserName; // user that
submitted the active job
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_COVERPAGE_INFO
{
public int SizeOfStruct; // Size of
this structure
//
// general
//
public string CoverPageName; // coverpage
document name
public bool UseServerCoverPage; // coverpage
exists on the fax
server
//
// Recipient information
//
public string RecName; //
public string RecFaxNumber; //
public string RecCompany; //
public string RecStreetAddress; //
public string RecCity; //
public string RecState; //
public string RecZip; //
public string RecCountry; //
public string RecTitle; //
public string RecDepartment; //
public string RecOfficeLocation; //
public string RecHomePhone; //
public string RecOfficePhone; //
//
// Sender information
//
public string SdrName; //
public string SdrFaxNumber; //
public string SdrCompany; //
public string SdrAddress; //
public string SdrTitle; //
public string SdrDepartment; //
public string SdrOfficeLocation; //
public string SdrHomePhone; //
public string SdrOfficePhone; //
//
// Misc information
//
public string Note; // public
string Subject; //
public SYSTEMTIME TimeSent; // Time the fax
was
sent
public int PageCount; // Number of
pages
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_EVENT
{
public int SizeOfStruct; // Size of
this structure
public FILETIME TimeStamp; // Timestamp
for when the event
was generated
public int DeviceId; // Permanent
line id
public int EventId; // Current
event id
public int JobId; // Fax Job Id,
0xffffffff
indicates inactive job
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct FAX_JOB_PARAM
{
public int SizeOfStruct; // size
of this structure
public string RecipientNumber; // recipient fax
number
public string RecipientName; // recipient
name
public string Tsid; // transmitter's
id
public string SenderName; // sender name
public string SenderCompany; // sender
company
public string SenderDept; // sender
department
public string BillingCode; // billing code
public int ScheduleAction; // when
to schedule the fax, see JSA defines
public SYSTEMTIME ScheduleTime; // time to
send the fax when
JSA_SPECIFIC_TIME is used (must be local time)
public int DeliveryReportType; //
delivery report type, see DRT defines
public string DeliveryReportAddress; // email address
for delivery report (ndr or dr) thru MAPI / SMTP
public string DocumentName; // document name
(optional)
public IntPtr CallHandle; // optional call
handle
//[MarshalAs(UnmanagedType., SizeConst=3)]
public IntPtr[] Reserved; // reserved
for ms use only
}
#endregion
#region Externs
[DllImport("winfax.dll", SetLastError=true)]
public static extern int FaxConnectFaxServer(string MachineName,
[Out] out int FaxHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxInitializeEventQueue(int FaxHandle, int
CompletionPort, int
CompletionKey, int hWnd, int MessageStart);
[DllImport("winfax.dll", SetLastError=true)]
public static extern void FaxFreeBuffer(IntPtr Buffer);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxClose(int FaxHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxCompleteJobParams([In, Out] ref
FAX_JOB_PARAM JobParams, [In,
Out] ref FAX_COVERPAGE_INFO CoverpageInfo);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxSendDocument(int FaxHandle, string
FileName, [In] ref
FAX_JOB_PARAM JobParams, [In] ref FAX_COVERPAGE_INFO CoverpageInfo,
[Out] out int FaxJobId);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxSendDocument(int FaxHandle, string
FileName, [In] ref
FAX_JOB_PARAM JobParams, [In] ref IntPtr CoverpageInfo, [Out] out int
FaxJobId);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxOpenPort(int FaxHandle, int DeviceId,
int Flags, [Out] int
FaxPortHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxGetDeviceStatus(int FaxPortHandle,
[Out] out FAX_DEVICE_STATUS
DeviceStatus);
#endregion
public static bool SendFax(string faxDocument)
{
bool bTerminate = false;
int hCompletionPort = 0;
int completionKey = 0;
int bytesSent = 0;
int hFax = 0;
//IntPtr hFax = new IntPtr(0);
//IntPtr hPort = new IntPtr(0);
int hPort = 0;
int faxJobID = 0;
FAX_DEVICE_STATUS deviceStatus;
FAX_EVENT faxEvent = new FAX_EVENT();
FAX_JOB_PARAM jobParam = new FAX_JOB_PARAM();
FAX_COVERPAGE_INFO coverPageInfo = new FAX_COVERPAGE_INFO();
faxEvent.SizeOfStruct = Marshal.SizeOf(typeof(FAX_EVENT));
IntPtr pFaxEvent = Marshal.AllocHGlobal(faxEvent.SizeOfStruct);
Marshal.StructureToPtr(faxEvent, pFaxEvent, true);
jobParam.SizeOfStruct = Marshal.SizeOf(typeof(FAX_JOB_PARAM));
IntPtr pJobParam = Marshal.AllocHGlobal(jobParam.SizeOfStruct);
Marshal.StructureToPtr(jobParam, pJobParam, true);
coverPageInfo.SizeOfStruct =
Marshal.SizeOf(typeof(FAX_COVERPAGE_INFO));
IntPtr pCoverPageInfo =
Marshal.AllocHGlobal(coverPageInfo.SizeOfStruct);
Marshal.StructureToPtr(coverPageInfo, pCoverPageInfo, true);
// connect to fax service
if(FaxConnectFaxServer(null, out hFax) == 0)
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("FaxConnectFaxServer failed, ec =
%d\n"),GetLastError() );
return false;
}
// create completion port to poll against while waiting for fax
completion
hCompletionPort =
Win32.CreateIoCompletionPort(Win32.INVALID_HANDLE_VALUE, 0, 0, 0);
if(hCompletionPort == 0)
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("CreateIoCompletionPort failed, ec = %d\n"),
GetLastError()
);
FaxClose(hFax);
return false;
}
if (!FaxInitializeEventQueue(
hFax,
hCompletionPort,
0,
0,
0))
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("FaxInitializeEventQueue failed, ec = %d\n"),
GetLastError() );
FaxClose(hFax);
return false;
}
FaxCompleteJobParams(ref jobParam, ref coverPageInfo);
jobParam.RecipientNumber = "5551212";
jobParam.ScheduleAction = (int)
FAX_ENUM_JOB_SEND_ATTRIBUTES.JSA_NOW;
jobParam.CallHandle = new IntPtr(0);
IntPtr coverPageNull = new IntPtr(0);
if(!FaxSendDocument(hFax, faxDocument, ref jobParam, ref
coverPageNull, out
faxJobID))
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//jobParam = (FAX_JOB_PARAM) Marshal.PtrToStructure(pJobParam,
typeof(FAX_JOB_PARAM));
//coverPageInfo = (FAX_COVERPAGE_INFO)
Marshal.PtrToStructure(pCoverPageInfo, typeof(FAX_COVERPAGE_INFO));
//_tprintf( TEXT("FaxSendDocument failed, ec = %d \n"),
GetLastError() );
FaxClose(hFax);
Win32.CloseHandle(hCompletionPort);
FaxFreeBuffer(pJobParam);
FaxFreeBuffer(pCoverPageInfo);
return false;
}
//_tprintf(TEXT("Queued document %s for transmition to %s, JobID =
%d\n"), Document,
Number, JobId);
FaxFreeBuffer(pJobParam);
FaxFreeBuffer(pCoverPageInfo);
Marshal.StructureToPtr(faxEvent, pFaxEvent, true);
while (!bTerminate &&
(Win32.GetQueuedCompletionStatus(
hCompletionPort,
ref bytesSent,
ref completionKey,
pFaxEvent,
Win32.INFINITE) != 0))
{
faxEvent = (FAX_EVENT) Marshal.PtrToStructure(pFaxEvent,
typeof(FAX_EVENT));
//_tprintf( TEXT("Received event 0x%x\n"),FaxEvent->EventId);
switch ((WinFaxEvent) faxEvent.EventId)
{
case WinFaxEvent.FEI_IDLE:
case WinFaxEvent.FEI_COMPLETED:
case WinFaxEvent.FEI_MODEM_POWERED_ON:
case WinFaxEvent.FEI_MODEM_POWERED_OFF:
case WinFaxEvent.FEI_FAXSVC_ENDED:
bTerminate = true;
break;
case WinFaxEvent.FEI_JOB_QUEUED:
//_tprintf( TEXT("JobId 0x%x queued\n"),FaxEvent->JobId );
break;
case WinFaxEvent.FEI_DIALING:
case WinFaxEvent.FEI_SENDING:
case WinFaxEvent.FEI_RECEIVING:
case WinFaxEvent.FEI_BUSY:
case WinFaxEvent.FEI_NO_ANSWER:
case WinFaxEvent.FEI_BAD_ADDRESS:
case WinFaxEvent.FEI_NO_DIAL_TONE:
case WinFaxEvent.FEI_DISCONNECTED:
case WinFaxEvent.FEI_FATAL_ERROR:
if (FaxOpenPort(hFax, faxEvent.DeviceId, (int)
FAX_PORT_OPEN_TYPE.PORT_OPEN_QUERY, hPort) )
{
if (FaxGetDeviceStatus(hPort, out deviceStatus) )
{
IntPtr pDeviceStatus = new IntPtr();
deviceStatus.SizeOfStruct =
Marshal.SizeOf(typeof(FAX_DEVICE_STATUS));
Marshal.StructureToPtr(deviceStatus,
pDeviceStatus, true);
//PrintDeviceStatus(deviceStatus);
FaxFreeBuffer(pDeviceStatus);
}
FaxClose(hPort);
}
break;
}
}
FaxClose(hFax);
Win32.CloseHandle(hCompletionPort);
return true;
}
}
I have declared a bunch of WinFax.DLL exports as static externs in
..NET using the DllImportAttribute(). I am basing my code off the
Simple.c found in the Platform SDK in the Samples\netds\fax\SampleSend
directory. All the defined externs/structures/code is at the bottom
of this message.
As you can see below, the SendFax() method is based on the
SimpleSend.c sample in the Platform SDK. Everything works up until
the FaxSendDocument() API call. GetLastWin32Error returns 87--Invalid
parameter. The documentation suggests that I am missing a required
parameter--but, there are only 3:
jobParam.RecipientNumber = "5551212";
jobParam.ScheduleAction = (int) FAX_ENUM_JOB_SEND_ATTRIBUTES.JSA_NOW;
jobParam.CallHandle = new IntPtr(0);
....and I've set them all; NOTE: the documentation says that CALLHANDLE
must be NULL--so I set it to a "null" IntPtr.
Anyone have any ideas what is going on?
BTW, using the legacy WinFax.dll APIs are a requirement for me as I
need to leverage IOCompletionPorts in order to make sending a Fax a
synchronous operation; therefore, I cannot use the FaxCom COM objects.
Thanks for any help!
Rob
--
public abstract class Win32
{
public static readonly int INFINITE = -1;
public static readonly int INVALID_HANDLE_VALUE = -1;
[DllImport("kernel32")]
public static extern int CreateIoCompletionPort(int FileHandle, int
ExistingCompletionPort, int CompletionKey, int
NumberOfConcurrentThreads);
[DllImport("kernel32")]
public static extern int GetQueuedCompletionStatus(int
CompletionPort, ref int
lpNumberOfBytesTransferred, ref int lpCompletionKey, IntPtr
lpOverlapped, int dwMilliseconds);
[DllImport("kernel32")]
public static extern int CloseHandle(int hObject);
}
public abstract class WinFax
{
#region Enumerations
public enum FAX_PORT_OPEN_TYPE
{
PORT_OPEN_QUERY = 1,
PORT_OPEN_MODIFY = 2
}
public enum FAX_ENUM_JOB_SEND_ATTRIBUTES
{
JSA_NOW = 0, // Send now
JSA_SPECIFIC_TIME, // Send at specific time
JSA_DISCOUNT_PERIOD // Send at server configured
discount period
}
[FlagsAttribute()]
public enum WinFaxEvent
{
FEI_DIALING = 0x00000001,
FEI_SENDING = 0x00000002,
FEI_RECEIVING = 0x00000003,
FEI_COMPLETED = 0x00000004,
FEI_BUSY = 0x00000005,
FEI_NO_ANSWER = 0x00000006,
FEI_BAD_ADDRESS = 0x00000007,
FEI_NO_DIAL_TONE = 0x00000008,
FEI_DISCONNECTED = 0x00000009,
FEI_FATAL_ERROR = 0x0000000a,
FEI_NOT_FAX_CALL = 0x0000000b,
FEI_CALL_DELAYED = 0x0000000c,
FEI_CALL_BLACKLISTED = 0x0000000d,
FEI_RINGING = 0x0000000e,
FEI_ABORTING = 0x0000000f,
FEI_ROUTING = 0x00000010,
FEI_MODEM_POWERED_ON = 0x00000011,
FEI_MODEM_POWERED_OFF = 0x00000012,
FEI_IDLE = 0x00000013,
FEI_FAXSVC_ENDED = 0x00000014,
FEI_ANSWERED = 0x00000015,
FEI_JOB_QUEUED = 0x00000016,
FEI_DELETED = 0x00000017,
FEI_INITIALIZING = 0x00000018,
FEI_LINE_UNAVAILABLE = 0x00000019,
FEI_HANDLED = 0x0000001a,
FEI_FAXSVC_STARTED = 0x0000001b
}
#endregion
#region Structs
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_DEVICE_STATUS
{
public int SizeOfStruct; // size
of this structure
public string CallerId; // caller id
string
public string Csid; // station
identifier
public int CurrentPage; //
current page
public int DeviceId; //
permanent line id
public string DeviceName; // device name
public string DocumentName; // document name
public int JobType; // send
or receive?
public string PhoneNumber; // sending phone
number
public string RoutingString; // routing
information
public string SenderName; // sender name
public string RecipientName; // recipient
name
public int Size; // size
in bytes of the document
public FILETIME StartTime; // starting
time of the fax
send/receive
public int Status; //
current status of the device, see FPS_??? masks
public string StatusString; // status string
if the Status field is zero. this may be NULL.
public FILETIME SubmittedTime; // time the
document was submitted
public int TotalPages; // total
number of pages in this job
public string Tsid; // transmitting
station identifier
public string UserName; // user that
submitted the active job
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_COVERPAGE_INFO
{
public int SizeOfStruct; // Size of
this structure
//
// general
//
public string CoverPageName; // coverpage
document name
public bool UseServerCoverPage; // coverpage
exists on the fax
server
//
// Recipient information
//
public string RecName; //
public string RecFaxNumber; //
public string RecCompany; //
public string RecStreetAddress; //
public string RecCity; //
public string RecState; //
public string RecZip; //
public string RecCountry; //
public string RecTitle; //
public string RecDepartment; //
public string RecOfficeLocation; //
public string RecHomePhone; //
public string RecOfficePhone; //
//
// Sender information
//
public string SdrName; //
public string SdrFaxNumber; //
public string SdrCompany; //
public string SdrAddress; //
public string SdrTitle; //
public string SdrDepartment; //
public string SdrOfficeLocation; //
public string SdrHomePhone; //
public string SdrOfficePhone; //
//
// Misc information
//
public string Note; // public
string Subject; //
public SYSTEMTIME TimeSent; // Time the fax
was
sent
public int PageCount; // Number of
pages
}
[StructLayout(LayoutKind.Sequential)]
public struct FAX_EVENT
{
public int SizeOfStruct; // Size of
this structure
public FILETIME TimeStamp; // Timestamp
for when the event
was generated
public int DeviceId; // Permanent
line id
public int EventId; // Current
event id
public int JobId; // Fax Job Id,
0xffffffff
indicates inactive job
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct FAX_JOB_PARAM
{
public int SizeOfStruct; // size
of this structure
public string RecipientNumber; // recipient fax
number
public string RecipientName; // recipient
name
public string Tsid; // transmitter's
id
public string SenderName; // sender name
public string SenderCompany; // sender
company
public string SenderDept; // sender
department
public string BillingCode; // billing code
public int ScheduleAction; // when
to schedule the fax, see JSA defines
public SYSTEMTIME ScheduleTime; // time to
send the fax when
JSA_SPECIFIC_TIME is used (must be local time)
public int DeliveryReportType; //
delivery report type, see DRT defines
public string DeliveryReportAddress; // email address
for delivery report (ndr or dr) thru MAPI / SMTP
public string DocumentName; // document name
(optional)
public IntPtr CallHandle; // optional call
handle
//[MarshalAs(UnmanagedType., SizeConst=3)]
public IntPtr[] Reserved; // reserved
for ms use only
}
#endregion
#region Externs
[DllImport("winfax.dll", SetLastError=true)]
public static extern int FaxConnectFaxServer(string MachineName,
[Out] out int FaxHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxInitializeEventQueue(int FaxHandle, int
CompletionPort, int
CompletionKey, int hWnd, int MessageStart);
[DllImport("winfax.dll", SetLastError=true)]
public static extern void FaxFreeBuffer(IntPtr Buffer);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxClose(int FaxHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxCompleteJobParams([In, Out] ref
FAX_JOB_PARAM JobParams, [In,
Out] ref FAX_COVERPAGE_INFO CoverpageInfo);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxSendDocument(int FaxHandle, string
FileName, [In] ref
FAX_JOB_PARAM JobParams, [In] ref FAX_COVERPAGE_INFO CoverpageInfo,
[Out] out int FaxJobId);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxSendDocument(int FaxHandle, string
FileName, [In] ref
FAX_JOB_PARAM JobParams, [In] ref IntPtr CoverpageInfo, [Out] out int
FaxJobId);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxOpenPort(int FaxHandle, int DeviceId,
int Flags, [Out] int
FaxPortHandle);
[DllImport("winfax.dll", SetLastError=true)]
public static extern bool FaxGetDeviceStatus(int FaxPortHandle,
[Out] out FAX_DEVICE_STATUS
DeviceStatus);
#endregion
public static bool SendFax(string faxDocument)
{
bool bTerminate = false;
int hCompletionPort = 0;
int completionKey = 0;
int bytesSent = 0;
int hFax = 0;
//IntPtr hFax = new IntPtr(0);
//IntPtr hPort = new IntPtr(0);
int hPort = 0;
int faxJobID = 0;
FAX_DEVICE_STATUS deviceStatus;
FAX_EVENT faxEvent = new FAX_EVENT();
FAX_JOB_PARAM jobParam = new FAX_JOB_PARAM();
FAX_COVERPAGE_INFO coverPageInfo = new FAX_COVERPAGE_INFO();
faxEvent.SizeOfStruct = Marshal.SizeOf(typeof(FAX_EVENT));
IntPtr pFaxEvent = Marshal.AllocHGlobal(faxEvent.SizeOfStruct);
Marshal.StructureToPtr(faxEvent, pFaxEvent, true);
jobParam.SizeOfStruct = Marshal.SizeOf(typeof(FAX_JOB_PARAM));
IntPtr pJobParam = Marshal.AllocHGlobal(jobParam.SizeOfStruct);
Marshal.StructureToPtr(jobParam, pJobParam, true);
coverPageInfo.SizeOfStruct =
Marshal.SizeOf(typeof(FAX_COVERPAGE_INFO));
IntPtr pCoverPageInfo =
Marshal.AllocHGlobal(coverPageInfo.SizeOfStruct);
Marshal.StructureToPtr(coverPageInfo, pCoverPageInfo, true);
// connect to fax service
if(FaxConnectFaxServer(null, out hFax) == 0)
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("FaxConnectFaxServer failed, ec =
%d\n"),GetLastError() );
return false;
}
// create completion port to poll against while waiting for fax
completion
hCompletionPort =
Win32.CreateIoCompletionPort(Win32.INVALID_HANDLE_VALUE, 0, 0, 0);
if(hCompletionPort == 0)
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("CreateIoCompletionPort failed, ec = %d\n"),
GetLastError()
);
FaxClose(hFax);
return false;
}
if (!FaxInitializeEventQueue(
hFax,
hCompletionPort,
0,
0,
0))
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//_tprintf( TEXT("FaxInitializeEventQueue failed, ec = %d\n"),
GetLastError() );
FaxClose(hFax);
return false;
}
FaxCompleteJobParams(ref jobParam, ref coverPageInfo);
jobParam.RecipientNumber = "5551212";
jobParam.ScheduleAction = (int)
FAX_ENUM_JOB_SEND_ATTRIBUTES.JSA_NOW;
jobParam.CallHandle = new IntPtr(0);
IntPtr coverPageNull = new IntPtr(0);
if(!FaxSendDocument(hFax, faxDocument, ref jobParam, ref
coverPageNull, out
faxJobID))
{
Console.WriteLine("GetLastWin32Error: " +
Marshal.GetLastWin32Error().ToString());
//jobParam = (FAX_JOB_PARAM) Marshal.PtrToStructure(pJobParam,
typeof(FAX_JOB_PARAM));
//coverPageInfo = (FAX_COVERPAGE_INFO)
Marshal.PtrToStructure(pCoverPageInfo, typeof(FAX_COVERPAGE_INFO));
//_tprintf( TEXT("FaxSendDocument failed, ec = %d \n"),
GetLastError() );
FaxClose(hFax);
Win32.CloseHandle(hCompletionPort);
FaxFreeBuffer(pJobParam);
FaxFreeBuffer(pCoverPageInfo);
return false;
}
//_tprintf(TEXT("Queued document %s for transmition to %s, JobID =
%d\n"), Document,
Number, JobId);
FaxFreeBuffer(pJobParam);
FaxFreeBuffer(pCoverPageInfo);
Marshal.StructureToPtr(faxEvent, pFaxEvent, true);
while (!bTerminate &&
(Win32.GetQueuedCompletionStatus(
hCompletionPort,
ref bytesSent,
ref completionKey,
pFaxEvent,
Win32.INFINITE) != 0))
{
faxEvent = (FAX_EVENT) Marshal.PtrToStructure(pFaxEvent,
typeof(FAX_EVENT));
//_tprintf( TEXT("Received event 0x%x\n"),FaxEvent->EventId);
switch ((WinFaxEvent) faxEvent.EventId)
{
case WinFaxEvent.FEI_IDLE:
case WinFaxEvent.FEI_COMPLETED:
case WinFaxEvent.FEI_MODEM_POWERED_ON:
case WinFaxEvent.FEI_MODEM_POWERED_OFF:
case WinFaxEvent.FEI_FAXSVC_ENDED:
bTerminate = true;
break;
case WinFaxEvent.FEI_JOB_QUEUED:
//_tprintf( TEXT("JobId 0x%x queued\n"),FaxEvent->JobId );
break;
case WinFaxEvent.FEI_DIALING:
case WinFaxEvent.FEI_SENDING:
case WinFaxEvent.FEI_RECEIVING:
case WinFaxEvent.FEI_BUSY:
case WinFaxEvent.FEI_NO_ANSWER:
case WinFaxEvent.FEI_BAD_ADDRESS:
case WinFaxEvent.FEI_NO_DIAL_TONE:
case WinFaxEvent.FEI_DISCONNECTED:
case WinFaxEvent.FEI_FATAL_ERROR:
if (FaxOpenPort(hFax, faxEvent.DeviceId, (int)
FAX_PORT_OPEN_TYPE.PORT_OPEN_QUERY, hPort) )
{
if (FaxGetDeviceStatus(hPort, out deviceStatus) )
{
IntPtr pDeviceStatus = new IntPtr();
deviceStatus.SizeOfStruct =
Marshal.SizeOf(typeof(FAX_DEVICE_STATUS));
Marshal.StructureToPtr(deviceStatus,
pDeviceStatus, true);
//PrintDeviceStatus(deviceStatus);
FaxFreeBuffer(pDeviceStatus);
}
FaxClose(hPort);
}
break;
}
}
FaxClose(hFax);
Win32.CloseHandle(hCompletionPort);
return true;
}
}