Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2400 lines
55 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
FaxServer.cpp
Abstract:
Implementation of CFaxServer
Author:
Iv Garber (IvG) Apr, 2000
Revision History:
--*/
#include "stdafx.h"
#include "FaxComEx.h"
#include "FaxServer.h"
#include "FaxDevices.h"
#include "FaxDeviceProviders.h"
#include <new>
//
//================== GET API VERSION ==============================
//
STDMETHODIMP
CFaxServer::get_APIVersion(
/*[out, retval]*/ FAX_SERVER_APIVERSION_ENUM *pAPIVersion
)
/*++
Routine name : CFaxServer::get_APIVersion
Routine description:
Return API Version of the Fax Server.
Author:
Iv Garber (IvG), May, 2001
Arguments:
pAPIVersion [out] - ptr to the place to put the API Version of the Fax Server
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_APIVersion"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Check the pointer we have got
//
if (::IsBadWritePtr(pAPIVersion, sizeof(FAX_SERVER_APIVERSION_ENUM)))
{
//
// Got a bad return pointer
//
hr = E_POINTER;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
return hr;
}
*pAPIVersion = m_APIVersion;
return hr;
}
//
//====================== CLEAR NOTIFY WINDOW ============================
//
void
CFaxServer::ClearNotifyWindow(void)
/*++
Routine name : CFaxServer::ClearNotifyWindow
Routine description:
Clear Notify Window.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
None.
Return Value:
None.
--*/
{
if (m_pNotifyWindow && ::IsWindow(m_pNotifyWindow->m_hWnd))
{
m_pNotifyWindow->DestroyWindow();
}
if (m_pNotifyWindow)
{
delete m_pNotifyWindow;
m_pNotifyWindow = NULL;
}
return;
}
//
//====================== PROCESS JOB NOTIFICATION =======================
//
HRESULT
CFaxServer::ProcessJobNotification(
/*[in]*/ DWORDLONG dwlJobId,
/*[in]*/ FAX_ENUM_JOB_EVENT_TYPE eventType,
/*[in]*/ LOCATION place,
/*[in]*/ FAX_JOB_STATUS *pJobStatus
)
/*++
Routine name : CFaxServer::ProcessJobNotification
Routine description:
Call appropriate Fire Method, for Jobs/Messages in Queues/Archives.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
dwlJobId [in] - Id of the Job/Message
eventType [in] - Type of the Event
place [in] - Where the Job/Message sits
pJobStatus [in] - FAX_JOB_STATUS structure
Return Value:
Standard HRESULT value.
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::ProcessJobNotification"),
hr,
_T("JOBID=%ld EVENTTYPE=%ld PLACE=%d"),
dwlJobId,
eventType,
place);
//
// Convert JobId from DWORDLONG into BSTR
//
CComBSTR bstrJobId;
hr = GetBstrFromDwordlong(dwlJobId, &bstrJobId);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("GetBstrFromDwordlong(dwlJobId, &bstrJobId)"), hr);
return hr;
}
//
// Check Type of the Event that happened
//
switch (eventType)
{
case FAX_JOB_EVENT_TYPE_ADDED:
switch (place)
{
case IN_QUEUE:
hr = Fire_OnIncomingJobAdded(this, bstrJobId);
break;
case OUT_QUEUE:
hr = Fire_OnOutgoingJobAdded(this, bstrJobId);
break;
case IN_ARCHIVE:
hr = Fire_OnIncomingMessageAdded(this, bstrJobId);
break;
case OUT_ARCHIVE:
hr = Fire_OnOutgoingMessageAdded(this, bstrJobId);
break;
default:
//
// assert (FALSE)
//
ATLASSERT(place == IN_QUEUE);
hr = E_FAIL;
return hr;
}
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out Job/Message Added(this, bstrJobId)"), hr);
return hr;
}
break;
case FAX_JOB_EVENT_TYPE_REMOVED:
switch (place)
{
case IN_QUEUE:
hr = Fire_OnIncomingJobRemoved(this, bstrJobId);
break;
case OUT_QUEUE:
hr = Fire_OnOutgoingJobRemoved(this, bstrJobId);
break;
case IN_ARCHIVE:
hr = Fire_OnIncomingMessageRemoved(this, bstrJobId);
break;
case OUT_ARCHIVE:
hr = Fire_OnOutgoingMessageRemoved(this, bstrJobId);
break;
default:
//
// assert (FALSE)
//
ATLASSERT(place == IN_QUEUE);
hr = E_FAIL;
return hr;
}
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out Job/Message Removed(this, bstrJobId)"), hr);
return hr;
}
break;
case FAX_JOB_EVENT_TYPE_STATUS:
{
if (!pJobStatus)
{
ATLASSERT(pJobStatus);
hr = E_FAIL;
return hr;
}
//
// Create Job Status Object to pass to the Events
//
CComObject<CFaxJobStatus> *pJobStatusClass = NULL;
pJobStatusClass = new (std::nothrow) CComObject<CFaxJobStatus>;
if (!pJobStatusClass)
{
//
// Out of Memory
//
CALL_FAIL(MEM_ERR, _T("new CComObject<CFaxJobStatus>"), hr);
return hr;
}
//
// Init the Object
//
hr = pJobStatusClass->Init(pJobStatus);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("pJobStatusClass->Init(pJobStatus)"), hr);
delete pJobStatusClass;
return hr;
}
//
// Query the Interface from the Object
//
CComPtr<IFaxJobStatus> pFaxJobStatus = NULL;
hr = pJobStatusClass->QueryInterface(IID_IFaxJobStatus, (void **) &pFaxJobStatus);
if (FAILED(hr) || !pFaxJobStatus)
{
CALL_FAIL(GENERAL_ERR, _T("pJobStatusClass->QueryInterface(pFaxJobStatus)"), hr);
delete pJobStatusClass;
return hr;
}
switch (place)
{
case IN_QUEUE:
hr = Fire_OnIncomingJobChanged(this, bstrJobId, pFaxJobStatus);
break;
case OUT_QUEUE:
hr = Fire_OnOutgoingJobChanged(this, bstrJobId, pFaxJobStatus);
break;
default:
//
// assert (FALSE)
//
ATLASSERT(place == IN_QUEUE);
hr = E_FAIL;
return hr;
}
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_On In/Out JobChanged(this, bstrJobId)"), hr);
return hr;
}
}
break;
default:
//
// assert (FALSE)
//
ATLASSERT(eventType == FAX_JOB_EVENT_TYPE_STATUS);
hr = E_FAIL;
return hr;
}
return hr;
}
//
//================= PROCESS MESSAGE ============================================
//
HRESULT
CFaxServer::ProcessMessage(
FAX_EVENT_EX *pFaxEventInfo
)
/*++
Routine name : CFaxServer::ProcessMessage
Routine description:
Fire appropriate Message
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
pFaxEventInfo [TBD] - Information about current Event
Return Value:
None.
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::ProcessMessage"), hr);
if (!m_faxHandle)
{
//
// Fax Server already disconnected
//
VERBOSE(DBG_WARNING, _T("FaxServer already disconnected."));
return hr;
}
switch (pFaxEventInfo->EventType)
{
case FAX_EVENT_TYPE_IN_QUEUE:
ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
pFaxEventInfo->EventInfo.JobInfo.Type,
IN_QUEUE,
pFaxEventInfo->EventInfo.JobInfo.pJobData);
break;
case FAX_EVENT_TYPE_OUT_QUEUE:
ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
pFaxEventInfo->EventInfo.JobInfo.Type,
OUT_QUEUE,
pFaxEventInfo->EventInfo.JobInfo.pJobData);
break;
case FAX_EVENT_TYPE_IN_ARCHIVE:
ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
pFaxEventInfo->EventInfo.JobInfo.Type,
IN_ARCHIVE);
break;
case FAX_EVENT_TYPE_OUT_ARCHIVE:
ProcessJobNotification(pFaxEventInfo->EventInfo.JobInfo.dwlMessageId,
pFaxEventInfo->EventInfo.JobInfo.Type,
OUT_ARCHIVE);
break;
case FAX_EVENT_TYPE_CONFIG:
switch (pFaxEventInfo->EventInfo.ConfigType)
{
case FAX_CONFIG_TYPE_RECEIPTS:
hr = Fire_OnReceiptOptionsChange(this);
break;
case FAX_CONFIG_TYPE_ACTIVITY_LOGGING:
hr = Fire_OnActivityLoggingConfigChange(this);
break;
case FAX_CONFIG_TYPE_OUTBOX:
hr = Fire_OnOutgoingQueueConfigChange(this);
break;
case FAX_CONFIG_TYPE_SENTITEMS:
hr = Fire_OnOutgoingArchiveConfigChange(this);
break;
case FAX_CONFIG_TYPE_INBOX:
hr = Fire_OnIncomingArchiveConfigChange(this);
break;
case FAX_CONFIG_TYPE_SECURITY:
hr = Fire_OnSecurityConfigChange(this);
break;
case FAX_CONFIG_TYPE_EVENTLOGS:
hr = Fire_OnEventLoggingConfigChange(this);
break;
case FAX_CONFIG_TYPE_DEVICES:
hr = Fire_OnDevicesConfigChange(this);
break;
case FAX_CONFIG_TYPE_OUT_GROUPS:
hr = Fire_OnOutboundRoutingGroupsConfigChange(this);
break;
case FAX_CONFIG_TYPE_OUT_RULES:
hr = Fire_OnOutboundRoutingRulesConfigChange(this);
break;
default:
//
// assert (FALSE)
//
ATLASSERT(pFaxEventInfo->EventInfo.ConfigType == FAX_CONFIG_TYPE_OUT_RULES);
hr = E_FAIL;
return hr;
}
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_On <...> ConfigChange(this)"), hr);
return hr;
}
break;
case FAX_EVENT_TYPE_ACTIVITY:
hr = Fire_OnServerActivityChange(this,
pFaxEventInfo->EventInfo.ActivityInfo.dwIncomingMessages,
pFaxEventInfo->EventInfo.ActivityInfo.dwRoutingMessages,
pFaxEventInfo->EventInfo.ActivityInfo.dwOutgoingMessages,
pFaxEventInfo->EventInfo.ActivityInfo.dwQueuedMessages);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_OnServerActivityChange(this, ...)"), hr);
return hr;
}
break;
case FAX_EVENT_TYPE_QUEUE_STATE:
hr = Fire_OnQueuesStatusChange(this,
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_OUTBOX_BLOCKED),
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_OUTBOX_PAUSED),
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.dwQueueStates & FAX_INCOMING_BLOCKED));
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_OnQueueStatusChange(this, ...)"), hr);
return hr;
}
break;
case FAX_EVENT_TYPE_NEW_CALL:
{
CComBSTR bstrCallerId = pFaxEventInfo->EventInfo.NewCall.lptstrCallerId;
if (pFaxEventInfo->EventInfo.NewCall.lptstrCallerId && !bstrCallerId)
{
CALL_FAIL(MEM_ERR, _T("CComBSTR::operator=()"), E_OUTOFMEMORY);
return hr;
}
hr = Fire_OnNewCall(this,
pFaxEventInfo->EventInfo.NewCall.hCall,
pFaxEventInfo->EventInfo.NewCall.dwDeviceId,
bstrCallerId);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_OnNewCall(this, ...)"), hr);
return hr;
}
}
break;
case FAX_EVENT_TYPE_FXSSVC_ENDED:
hr = Fire_OnServerShutDown(this);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_OnServerShutDown(this)"), hr);
return hr;
}
break;
case FAX_EVENT_TYPE_DEVICE_STATUS:
hr = Fire_OnDeviceStatusChange(this,
pFaxEventInfo->EventInfo.DeviceStatus.dwDeviceId,
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_POWERED_OFF),
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_SENDING),
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_RECEIVING),
bool2VARIANT_BOOL(pFaxEventInfo->EventInfo.DeviceStatus.dwNewStatus & FAX_DEVICE_STATUS_RINGING));
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("Fire_OnDeviceStatusChange(this, dwDeviceId, ...)"), hr);
return hr;
}
break;
default:
//
// assert (FALSE)
//
ATLASSERT(pFaxEventInfo->EventType == FAX_EVENT_TYPE_FXSSVC_ENDED);
hr = E_FAIL;
return hr;
}
return hr;
}
//
//========== MESSAGE HANDLER FUNCTION ======================================
//
LRESULT
CNotifyWindow::OnMessage(UINT uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL& bHandled
)
/*++
Routine name : CNotifyWindow::OnMessage
Routine description:
Get the Message and call Server's ProcessMessage.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
uMsg [in] - Msg Id
wParam [in] - wParam
lParam [in] - LParam
bHandled [in,out] - bHandled
Return Value:
Standard result code
--*/
{
DBG_ENTER(_T("CNotifyWindow::OnMessage"));
//
// Check that lParam is valid
//
if (!lParam)
{
CALL_FAIL(GENERAL_ERR, _T("(!lParam)"), E_FAIL);
return 0;
}
if (::IsBadReadPtr((FAX_EVENT_EX *)lParam, sizeof(FAX_EVENT_EX)))
{
CALL_FAIL(GENERAL_ERR, _T("(::IsBadReadPtr((FAX_EVENT_EX *)lParam, sizeof(FAX_EVENT_EX))"), E_FAIL);
return 0;
}
if (((FAX_EVENT_EX *)lParam)->dwSizeOfStruct != sizeof(FAX_EVENT_EX))
{
CALL_FAIL(GENERAL_ERR, _T("(((FAX_EVENT_EX *)lParam)->dwSizeOfStruct != sizeof(FAX_EVENT_EX))"), E_FAIL);
return 0;
}
//
// Call Server to Process the Message
//
if (m_pServer)
{
HRESULT hr = S_OK;
hr = m_pServer->ProcessMessage((FAX_EVENT_EX *)lParam);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("m_pServer->ProcessMessage()"), hr);
}
}
//
// Free the Buffer
//
FaxFreeBuffer((void *)lParam);
return 0;
}
//
//================ GET METHOD DATA ================================================
//
void
CFaxServer::GetMethodData(
/*[in]*/ BSTR bstrAllString,
/*[out]*/ LPWSTR strWhereToPut
)
/*++
Routine name : CFaxServer::GetMethodData
Routine description:
Read from bstrAllString data upto DELIMITER and store it in strWhereToPut.
Used in GetRegisteredData for Extension Method Registration.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
bstrAllString [TBD] - in subsequent calls
strWhereToPut [TBD] - where to put the value that was readed from the bstrAllString.
--*/
{
BOOL bRes = TRUE;
DBG_ENTER(_T("CFaxServer::GetMethodData()"));
//
// Find Method Name
//
BSTR bstrTmp;
bstrTmp = _tcstok(bstrAllString, DELIMITER);
if (!bstrTmp)
{
CALL_FAIL(MEM_ERR, _T("_tcstok(bstrAllString, DELIMITER))"), bRes);
RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
}
//
// Check that length of the readen data
//
if (_tcslen(bstrTmp) > 100)
{
//
// Error : exceeds the limit
//
CALL_FAIL(GENERAL_ERR, _T("(_tcslen(bstrTmp) > 100)"), E_FAIL);
RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
}
memcpy(strWhereToPut, bstrTmp, (sizeof(TCHAR) * (_tcslen(bstrTmp) + 1)));
return;
}
//
//============= GET REGISTERED DATA =========================================
//
BOOL
CFaxServer::GetRegisteredData(
/*[out]*/ LPWSTR MethodName,
/*[out]*/ LPWSTR FriendlyName,
/*[out]*/ LPWSTR FunctionName,
/*[out]*/ LPWSTR Guid
)
/*++
Routine name : CFaxServer::GetRegisteredData
Routine description:
Return data about specific Method being registered.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
MethodName [TBD] - Name of the Method
FriendlyName [TBD] - Friendly Name of the Method
FunctionName [TBD] - Function Name of the Method
Guid [TBD] - GUID of the Method
Return Value:
TRUE if Method Data is filled ok, FALSE if all the methods already registered.
Notes:
The function raises an exception when any error happens.
--*/
{
BOOL bRes = TRUE;
DBG_ENTER(_T("CFaxServer::GetRegisteredData"), bRes);
//
// Check if we already finished the array
//
if (m_pRegMethods->rgsabound[0].cElements == m_lLastRegisteredMethod)
{
bRes = FALSE;
CALL_FAIL(GENERAL_ERR, _T("We have reached the End of the Array"), bRes);
return bRes;
}
CComBSTR bstrMethodData;
HRESULT hr = SafeArrayGetElement(m_pRegMethods, &m_lLastRegisteredMethod, &bstrMethodData);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetElement(m_pRegMethods, ...)"), hr);
RaiseException(EXCEPTION_INVALID_METHOD_DATA, 0, 0, 0);
}
GetMethodData(bstrMethodData, MethodName);
GetMethodData(NULL, FriendlyName);
GetMethodData(NULL, FunctionName);
GetMethodData(NULL, Guid);
//
// Increase the Index of the SafeArray
//
m_lLastRegisteredMethod++;
return bRes;
}
//
//=================== REGISTER METHOD CALLBACK ===============================
//
BOOL CALLBACK RegisterMethodCallback(
/*[in]*/ HANDLE FaxHandle,
/*[in]*/ LPVOID Context,
/*[out]*/ LPWSTR MethodName,
/*[out]*/ LPWSTR FriendlyName,
/*[out]*/ LPWSTR FunctionName,
/*[out]*/ LPWSTR Guid
)
{
BOOL bRes = TRUE;
DBG_ENTER(_T("RegisterMethodCallback"), bRes);
bRes = ((CFaxServer *)Context)->GetRegisteredData(MethodName, FriendlyName, FunctionName, Guid);
return bRes;
}
//
//=================== LISTEN TO SERVER EVENTS ===============================
//
STDMETHODIMP
CFaxServer::ListenToServerEvents(
/*[in]*/ FAX_SERVER_EVENTS_TYPE_ENUM EventTypes
)
/*++
Routine name : CFaxServer::ListenToServerEvents
Routine description:
Starts or stops listening to Server Events.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
EventTypes [in] - Events to listen to.
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::ListenToServerEvents"), hr, _T("Events=%ld"), EventTypes);
//
// Check Fax Handle
//
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
HANDLE hEvent = NULL;
if (EventTypes > fsetNONE)
{
if (!m_pNotifyWindow)
{
//
// Create new Window
//
m_pNotifyWindow = new (std::nothrow) CNotifyWindow(this);
if (!m_pNotifyWindow)
{
//
// Out of Memory
//
hr = E_OUTOFMEMORY;
Error(IDS_ERROR_OUTOFMEMORY, IID_IFaxServer, hr);
CALL_FAIL(MEM_ERR, _T("new CNotifyWindow(this)"), hr);
return hr;
}
RECT rcRect;
ZeroMemory(&rcRect, sizeof(rcRect));
m_pNotifyWindow->Create(NULL, rcRect, NULL, WS_POPUP, 0x0, 0);
if (!::IsWindow(m_pNotifyWindow->m_hWnd))
{
//
// Failed to Create Window
//
hr = E_FAIL;
CALL_FAIL(GENERAL_ERR, _T("m_pNotifyWindow->Create(NULL, rcRect)"), hr);
ClearNotifyWindow();
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
}
//
// Register for new Set of Events
//
if (!FaxRegisterForServerEvents(m_faxHandle,
EventTypes,
NULL,
0,
m_pNotifyWindow->m_hWnd,
m_pNotifyWindow->GetMessageId(),
&hEvent))
{
//
// Failed to Register given Set of Events
//
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxRegisterForServerEvents(m_faxHandle, lEventTypes, ...)"), hr);
ClearNotifyWindow();
return hr;
}
}
//
// Unregister from the previous set of Events, if there was one
//
if (m_hEvent)
{
if (!FaxUnregisterForServerEvents(m_hEvent))
{
//
// Failed to Unregister given Set of Events
//
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterForServerEvents(m_hEvent)"), hr);
//
// Return Error only when Caller specially wanted to Unregister.
// Otherwise, debug Warning is enough.
//
if (EventTypes == fsetNONE)
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
}
}
}
//
// store the new Listening HANDLE for future UNRegistration
//
m_hEvent = hEvent;
if (m_hEvent == NULL)
{
//
// We're not listening to any events - dismiss the hidden window
//
ClearNotifyWindow();
}
m_EventTypes = EventTypes;
return hr;
}
//
//=================== GET REGISTERED EVENTS ===============================
//
STDMETHODIMP
CFaxServer::get_RegisteredEvents(
/*[out, retval]*/ FAX_SERVER_EVENTS_TYPE_ENUM *pEventTypes
)
/*++
Routine name : CFaxServer::get_RegisteredEvents
Routine description:
Return Bit-Wise Combination of Events the Fax Server is Listening to
Author:
Iv Garber (IvG), Dec, 2000
Arguments:
pEventTypes [out] - the Event Types to return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_RegisteredEvents"), hr);
//
// Check the Fax Service Handle
//
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Check the pointer we have got
//
if (::IsBadWritePtr(pEventTypes, sizeof(FAX_SERVER_EVENTS_TYPE_ENUM)))
{
//
// Got a bad return pointer
//
hr = E_POINTER;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
return hr;
}
*pEventTypes = m_EventTypes;
return hr;
}
//
//=================== REGISTER DEVICE PROVIDER ===============================
//
STDMETHODIMP
CFaxServer::RegisterDeviceProvider(
/*[in]*/ BSTR bstrGUID,
/*[in]*/ BSTR bstrFriendlyName,
/*[in]*/ BSTR bstrImageName,
/*[in]*/ BSTR bstrTspName,
/*[in]*/ long lFSPIVersion
)
/*++
Routine name : CFaxServer::RegisterDeviceProvider
Routine description:
Register the FSP
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrGUID [in] - GUID of the FSP
bstrFriendlyName [in] - Frienly Name of the FSP
bstrImageName [in] - Image Name of the FSP
TspName [in] - TspName of the FSP
FSPIVersion [in] - Version of the FSP interface
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::RegisterDeviceProvider"),
hr,
_T("GUID=%s FriendlyName=%s ImageName=%s TspNameName=%s Version=%d"),
bstrGUID,
bstrFriendlyName,
bstrImageName,
bstrTspName,
lFSPIVersion);
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Check if GUID is valid
//
hr = IsValidGUID(bstrGUID);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("IsValidGUID(bstrGUID)"), hr);
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
//
// Register the FSP
//
if (!FaxRegisterServiceProviderEx(m_faxHandle,
bstrGUID,
bstrFriendlyName,
bstrImageName,
bstrTspName,
lFSPIVersion,
0)) // capabilities
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxRegisterServiceProviderEx(m_faxHandle, bstrUniqueName, ...)"), hr);
return hr;
}
return hr;
}
//
//================= REGISTER INBOUND ROUTING EXTENSION ================================
//
STDMETHODIMP
CFaxServer::RegisterInboundRoutingExtension(
/*[in]*/ BSTR bstrExtensionName,
/*[in]*/ BSTR bstrFriendlyName,
/*[in]*/ BSTR bstrImageName,
/*[in]*/ VARIANT vMethods
)
/*++
Routine name : CFaxServer::RegisterInboundRoutingExtension
Routine description:
Register Inbound Routing Extension.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrExtensionName [in] - Extension Name
bstrFriendlyName [in] - Friendly Name
bstrImageName [in] - Image Name
vMethods [in] - SafeArray of the Methods Data
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::RegisterInboundRoutingExtension"), hr, _T("Name=%s Friendly=%s Image=%s"),bstrExtensionName, bstrFriendlyName, bstrImageName);
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Check the Validity of the SafeArray
//
if (vMethods.vt != (VT_ARRAY | VT_BSTR))
{
hr = E_INVALIDARG;
Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("(vMethods.vt != VT_ARRAY | VT_BSTR)"), hr);
return hr;
}
m_pRegMethods = vMethods.parray;
if (!m_pRegMethods)
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("!m_pRegMethods ( = vMethods.parray )"), hr);
Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
return hr;
}
if (SafeArrayGetDim(m_pRegMethods) != 1)
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetDim(m_pRegMethods) != 1"), hr);
Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
return hr;
}
if (m_pRegMethods->rgsabound[0].lLbound != 0)
{
hr = E_INVALIDARG;
Error(IDS_ERROR_METHODSNOTARRAY, IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_pRegMethods->rgsabound[0].lLbound != 0"), hr);
return hr;
}
//
// Register the IR Extension
//
m_lLastRegisteredMethod = 0;
if (!FaxRegisterRoutingExtension(m_faxHandle,
bstrExtensionName,
bstrFriendlyName,
bstrImageName,
RegisterMethodCallback,
this))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxRegisterRoutingExtension(m_faxHandle, bstrExtensionName, ...)"), hr);
return hr;
}
return hr;
}
//
//========== UNREGISTER INBOUND ROUTING EXTENSION ==============================================
//
STDMETHODIMP
CFaxServer::UnregisterInboundRoutingExtension(
/*[in]*/ BSTR bstrExtensionUniqueName
)
/*++
Routine name : CFaxServer::UnregisterExtensionUniqueName
Routine description:
Unregister the Inbound Routing Extension
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrExtensionUniqueName - Unique Name of the IR Extension to Unregister
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::UnregisterInboundRoutingExtension"), hr, _T("Unique Name =%s"), bstrExtensionUniqueName);
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Unregister the given Routing Extension
//
if (!FaxUnregisterRoutingExtension(m_faxHandle, bstrExtensionUniqueName))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterRoutingExtension(m_faxHandle, bstrExtensionUniqueName)"), hr);
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//========== UNREGISTER DEVICE PROVIDER ==============================================
//
STDMETHODIMP
CFaxServer::UnregisterDeviceProvider(
/*[in]*/ BSTR bstrUniqueName
)
/*++
Routine name : CFaxServer::UnregisterDeviceProvider
Routine description:
Unregister the Device Provider
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrUniqueName [in] - UniqueName of the Device Provider to Unregister
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::UnregisterDeviceProvider"), hr, _T("UniqueName=%s"), bstrUniqueName);
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Unregister the given Device Provider
//
if (!FaxUnregisterServiceProviderEx(m_faxHandle, bstrUniqueName))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL(GENERAL_ERR, _T("FaxUnregisterServiceProviderEx(m_faxHandle, bstrUniqueName)"), hr);
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//===================== GET EXTENSION PROPERTY ===============================================
//
STDMETHODIMP
CFaxServer::GetExtensionProperty(
/*[in]*/ BSTR bstrGUID,
/*[out, retval]*/ VARIANT *pvProperty
)
/*++
Routine name : CFaxServer::GetExtensionProperty
Routine description:
Retrieves the global Extension Data from the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrGUID [in] -- Extension's Data GUID
pvProperty [out] -- Variant with the Blob to Return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::GetExtensionProperty()"), hr, _T("GUID=%s"), bstrGUID);
hr = ::GetExtensionProperty(this, 0, bstrGUID, pvProperty);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
};
//
//============= SET EXTENSION PROPERTY =============================
//
STDMETHODIMP
CFaxServer::SetExtensionProperty(
/*[in]*/ BSTR bstrGUID,
/*[in]*/ VARIANT vProperty
)
/*++
Routine name : CFaxServer::SetExtensionProperty
Routine description:
Stores Extension Configuration Property at Server level.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
bstrGUID [in] - GUID of the Property
vProperty [in] - the Property to Store : SafeArray of Bytes
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::SetExtensionProperty()"), hr, _T("GUID=%s"), bstrGUID);
hr = ::SetExtensionProperty(this, 0, bstrGUID, vProperty);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET DEBUG ==============================
//
STDMETHODIMP
CFaxServer::get_Debug(
/*[out, retval]*/ VARIANT_BOOL *pbDebug
)
/*++
Routine name : CFaxServer::get_Debug
Routine description:
Return Whether Server is in Debug Mode.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
pbDebug [out] - the result
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_Debug"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Return the Value
//
hr = GetVariantBool(pbDebug, bool2VARIANT_BOOL((m_Version.dwFlags & FAX_VER_FLAG_CHECKED) ? true : false));
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET MINOR BUILD ==============================
//
STDMETHODIMP
CFaxServer::get_MinorBuild(
/*[out, retval]*/ long *plMinorBuild
)
/*++
Routine name : CFaxServer::get_MinorBuild
Routine description:
Return Minor Build of the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
plMinorBuild [out] - the result
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_MinorBuild"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Return the Value
//
hr = GetLong(plMinorBuild, m_Version.wMinorBuildNumber);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET MAJOR BUILD ==============================
//
STDMETHODIMP
CFaxServer::get_MajorBuild(
/*[out, retval]*/ long *plMajorBuild
)
/*++
Routine name : CFaxServer::get_MajorBuild
Routine description:
Return Major Build of the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
plMajorBuild [out] - the result
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_MajorBuild"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Return the Value
//
hr = GetLong(plMajorBuild, m_Version.wMajorBuildNumber);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET MINOR VERSION ==============================
//
STDMETHODIMP
CFaxServer::get_MinorVersion(
/*[out, retval]*/ long *plMinorVersion
)
/*++
Routine name : CFaxServer::get_MinorVersion
Routine description:
Return Minor Version of the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
plMinorVersion [out] - the result
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_MinorVersion"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Return the Value
//
hr = GetLong(plMinorVersion, m_Version.wMinorVersion);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET VERSION ==============================
//
STDMETHODIMP
CFaxServer::GetVersion()
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::GetVersion"), hr);
if (m_faxHandle == NULL)
{
//
// Server not Connected
//
hr = E_HANDLE;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_FaxHandle == NULL"), hr);
return hr;
}
//
// Get Version from the Fax Server
//
ZeroMemory(&m_Version, sizeof(FAX_VERSION));
m_Version.dwSizeOfStruct = sizeof(FAX_VERSION);
if (!FaxGetVersion(m_faxHandle, &m_Version))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxGetVersion(m_faxHandle, &m_Version))"), hr);
return hr;
}
//
// Check that we have got good Version struct
//
if (m_Version.dwSizeOfStruct != sizeof(FAX_VERSION))
{
hr = E_FAIL;
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("m_Version.dwSizeOfStruct != sizeof(FAX_VERSION)"), hr);
return hr;
}
ATLASSERT(m_Version.bValid);
//
// Get API Version from the Fax Server
//
if (!FaxGetReportedServerAPIVersion(m_faxHandle, LPDWORD(&m_APIVersion)))
{
hr = HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxGetReportedServerAPIVersion(m_faxHandle, &m_APIVersion))"), hr);
return hr;
}
//
// m_Version & m_APIVersion are valid and OK
//
m_bVersionValid = true;
return hr;
}
//
//================== GET MAJOR VERSION ==============================
//
STDMETHODIMP
CFaxServer::get_MajorVersion(
/*[out, retval]*/ long *plMajorVersion
)
/*++
Routine name : CFaxServer::get_MajorVersion
Routine description:
Return Major Version of the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
plMajorVersion [out] - the result
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_MajorVersion"), hr);
if (!m_bVersionValid)
{
//
// get Version of the Server
//
hr = GetVersion();
if (FAILED(hr))
{
return hr;
}
}
//
// Return the Value
//
hr = GetLong(plMajorVersion, m_Version.wMajorVersion);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET OUTBOUND ROUTING OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_OutboundRouting(
IFaxOutboundRouting **ppOutboundRouting
)
/*++
Routine name : CFaxServer::get_OutboundRouting
Routine description:
Return Outbound Routing Shortcut Object
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
ppOutboundRouting [out] - the Outbound Routing Object
Return Value:
Standard HRESULT code
Notes:
FaxOutboundRouting is Contained Object, because of :
a) It needs Ptr to Fax Server, to create Groups/Rules Collections
each time it is asked to.
b) Fax Server caches it, to allow fast dot notation ( Server.OutboundRouting.<...> )
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_OutboundRouting"), hr);
CObjectHandler<CFaxOutboundRouting, IFaxOutboundRouting> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppOutboundRouting, &m_pOutboundRouting, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET DEVICES OBJECT ==============================
//
STDMETHODIMP
CFaxServer::GetDevices(
IFaxDevices **ppDevices
)
/*++
Routine name : CFaxServer::get_Devices
Routine description:
Return Devices Collection Object
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
ppDevices [out] - the Devices Collection Object
Return Value:
Standard HRESULT code
Notes:
Devices is a collection. It is not cached by the Server.
Each time the function is called, the new collection is created.
This enables the user to refresh the collection.
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_Devices"), hr);
CObjectHandler<CFaxDevices, IFaxDevices> ObjectCreator;
hr = ObjectCreator.GetObject(ppDevices, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET DEVICE PROVIDERS OBJECT ==============================
//
STDMETHODIMP
CFaxServer::GetDeviceProviders(
IFaxDeviceProviders **ppDeviceProviders
)
/*++
Routine name : CFaxServer::get_DeviceProviders
Routine description:
Return Device Providers Collection Object
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
ppDeviceProviders [out] - the Device Providers Collection Object
Return Value:
Standard HRESULT code
Notes:
Device Providers is a collection. It is not cached by the Server.
Each time the function is called, the new collection is created.
This enables the user to refresh the collection.
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_DeviceProviders"), hr);
CObjectHandler<CFaxDeviceProviders, IFaxDeviceProviders> ObjectCreator;
hr = ObjectCreator.GetObject(ppDeviceProviders, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET INBOUND ROUTING OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_InboundRouting(
IFaxInboundRouting **ppInboundRouting
)
/*++
Routine name : CFaxServer::get_InboundRouting
Routine description:
Return Inbound Routing Shortcut Object
Author:
Iv Garber (IvG), June, 2000
Arguments:
ppInboundRouting [out] - the Inbound Routing Object
Return Value:
Standard HRESULT code
Notes:
FaxInboundRouting is Contained Object, because of :
a) It needs Ptr to Fax Server, to create Extensions/Methods Collections
each time it is asked to.
b) Fax Server caches it, to allow fast dot notation ( Server.InboundRouting.<...> )
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_InboundRouting"), hr);
CObjectHandler<CFaxInboundRouting, IFaxInboundRouting> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppInboundRouting, &m_pInboundRouting, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET SECURITY OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_Security(
IFaxSecurity **ppSecurity
)
/*++
Routine name : CFaxServer::get_Security
Routine description:
Return Security Object
Author:
Iv Garber (IvG), June, 2000
Arguments:
ppSecurity [out] - the Security Object
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_Security"), hr);
CObjectHandler<CFaxSecurity, IFaxSecurity> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppSecurity, &m_pSecurity, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET ACTIVITY OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_Activity(
IFaxActivity **ppActivity
)
/*++
Routine name : CFaxServer::get_Activity
Routine description:
Return Activity Object
Author:
Iv Garber (IvG), June, 2000
Arguments:
ppActivity [out] - the Activity Object
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_Activity"), hr);
CObjectHandler<CFaxActivity, IFaxActivity> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppActivity, &m_pActivity, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== GET LOGGING OPTIONS OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_LoggingOptions(
IFaxLoggingOptions **ppLoggingOptions
)
/*++
Routine name : CFaxServer::get_LoggingOptions
Routine description:
Return Logging Options Object
Author:
Iv Garber (IvG), June, 2000
Arguments:
ppLoggingOptions [out] - the Logging Options Object
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_LoggingOptions"), hr);
CObjectHandler<CFaxLoggingOptions, IFaxLoggingOptions> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppLoggingOptions, &m_pLoggingOptions, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//==================== GET HANDLE =====================================
//
STDMETHODIMP
CFaxServer::GetHandle(
/*[out, retval]*/ HANDLE* pFaxHandle
)
/*++
Routine name : CFaxServer::GetHandle
Routine description:
Return Handle to the Fax Server, if possible
Author:
Iv Garber (IvG), Apr, 2000
Arguments:
seqId [in] - the seqId of the Caller
Return Value:
HANDLE to the Fax Server
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::GetHandle"), hr);
if (::IsBadWritePtr(pFaxHandle, sizeof(HANDLE *)))
{
//
// Got a bad return pointer
//
hr = E_POINTER;
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr()"), hr);
return hr;
}
*pFaxHandle = m_faxHandle;
return hr;
} // CFaxServer::GetHandle
//
//==================== INTERFACE SUPPORT ERROR INFO =====================
//
STDMETHODIMP
CFaxServer::InterfaceSupportsErrorInfo(
REFIID riid
)
/*++
Routine name : CFaxServer::InterfaceSupportsErrorInfo
Routine description:
ATL's implementation of Support Error Info
Author:
Iv Garber (IvG), Apr, 2000
Arguments:
riid [in] - Reference to the Interface
Return Value:
Standard HRESULT code
--*/
{
static const IID* arr[] =
{
&IID_IFaxServer,
&IID_IFaxFolders, // Contained object
&IID_IFaxActivity, // Contained object
&IID_IFaxSecurity, // Contained object
&IID_IFaxReceiptOptions, // Contained object
&IID_IFaxLoggingOptions, // Contained object
&IID_IFaxInboundRouting, // Contained object
&IID_IFaxOutboundRouting // Contained object
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
//
//================== GET FOLDERS OBJECT ==============================
//
STDMETHODIMP
CFaxServer::get_Folders(
IFaxFolders **ppFolders
)
/*++
Routine name : CFaxServer::get_Folders
Routine description:
Return Folders Shortcut Object
Author:
Iv Garber (IvG), Apr, 2000
Arguments:
pFaxFolders [out] - Fax Folders Object
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_Folders"), hr);
CObjectHandler<CFaxFolders, IFaxFolders> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppFolders, &m_pFolders, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//================== DISCONNECT =============================================
// {CR}
STDMETHODIMP
CFaxServer::Disconnect()
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::Disconnect"), hr);
if (!m_faxHandle)
{
return hr;
}
//
// first UnListen, while we still connected
//
hr = ListenToServerEvents(fsetNONE);
if (FAILED(hr))
{
//
// Show the error, but continue
//
CALL_FAIL(GENERAL_ERR, _T("ListenToServerEvents(fsetNONE)"), hr);
}
if (!FaxClose(m_faxHandle))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(IDS_ERROR_OPERATION_FAILED, IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxClose()"), hr);
return hr;
}
m_faxHandle = NULL;
m_bstrServerName.Empty();
return hr;
}
//
//=================== CONNECT =======================================
//{CR}
STDMETHODIMP CFaxServer::Connect(
BSTR bstrServerName
)
/*++
Routine name : CFaxServer::Connect
Routine description:
Connect to the given Fax Server
Author:
Iv Garber (IvG), May, 2000
Arguments:
bstrServerName [in] - Name of the Fax Server to Connect to
Return Value:
Standard HRESULT code
--*/
{
HANDLE h_tmpFaxHandle;
DWORD dwServerAPIVersion;
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::Connect"), hr, _T("%s"), bstrServerName);
if (!FaxConnectFaxServer(m_bstrServerName, &h_tmpFaxHandle))
{
//
// Failed to Connect to the Server
//
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxConnectFaxServer()"), hr);
return hr;
}
ATLASSERT(h_tmpFaxHandle);
//
// Get API Version from the Fax Server
//
if (!FaxGetReportedServerAPIVersion(h_tmpFaxHandle, &dwServerAPIVersion))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("FaxGetReportedServerAPIVersion(h_tmpFaxHandle, &dwServerAPIVersion))"), hr);
FaxClose(h_tmpFaxHandle);
return hr;
}
//
// Block Whistler clients from connection to BOS servers
//
if (FAX_API_VERSION_1 > dwServerAPIVersion)
{
hr = Fax_HRESULT_FROM_WIN32(FAX_ERR_VERSION_MISMATCH);
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
CALL_FAIL(GENERAL_ERR, _T("Mismatch client and server versions"), hr);
FaxClose(h_tmpFaxHandle);
return hr;
}
if (m_faxHandle)
{
//
// Reconnect
//
hr = Disconnect();
if (FAILED(hr))
{
//
// Failed to DisConnect from the Previous Server
//
CALL_FAIL(DBG_MSG, _T("Disconnect()"), hr);
}
}
m_faxHandle = h_tmpFaxHandle;
m_bstrServerName = bstrServerName;
return hr;
}
//
//============== GET & PUT PROPERTIES ===============================
//
STDMETHODIMP CFaxServer::get_ServerName(
BSTR *pbstrServerName
)
/*++
Routine name : CFaxServer::get_ServerName
Routine description:
Return Name of the Server
Author:
Iv Garber (IvG), May, 2000
Arguments:
pbstrServerName [out] - Name of the Server to Return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("CFaxServer::get_ServerName"), hr);
hr = GetBstr(pbstrServerName, m_bstrServerName);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}
//
//============== MAIL OPTIONS OBJECT =========================================
//
STDMETHODIMP
CFaxServer::get_ReceiptOptions(
IFaxReceiptOptions **ppReceiptOptions
)
/*++
Routine name : CFaxServer::get_ReceiptOptions
Routine description:
Return Mail Options Object.
Author:
Iv Garber (IvG), May, 2000
Arguments:
ppReceiptOptions [out, retval] - Ptr to the place to put the object.
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (_T("CFaxServer::get_ReceiptOptions"), hr);
CObjectHandler<CFaxReceiptOptions, IFaxReceiptOptions> ObjectCreator;
hr = ObjectCreator.GetContainedObject(ppReceiptOptions, &m_pReceiptOptions, this);
if (FAILED(hr))
{
Error(GetErrorMsgId(hr), IID_IFaxServer, hr);
return hr;
}
return hr;
}