Windows2003-3790/printscan/faxsrv/clientconsole/clientconsoledoc.cpp
2020-09-30 16:53:55 +02:00

918 lines
20 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ClientConsoleDoc.cpp : implementation of the CClientConsoleDoc class
//
#include "stdafx.h"
#define __FILE_ID__ 2
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CClientConsoleApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CClientConsoleDoc
IMPLEMENT_DYNCREATE(CClientConsoleDoc, CDocument)
BEGIN_MESSAGE_MAP(CClientConsoleDoc, CDocument)
//{{AFX_MSG_MAP(CClientConsoleDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CClientConsoleDoc construction/destruction
//
// Static members:
//
HANDLE CClientConsoleDoc::m_hShutdownEvent = NULL;
BOOL CClientConsoleDoc::m_bShuttingDown = FALSE;
CClientConsoleDoc::CClientConsoleDoc() :
m_bRefreshingServers (FALSE),
m_bWin9xPrinterFormat(FALSE)
{}
CClientConsoleDoc::~CClientConsoleDoc()
{
//
// The list of servers is not freed and servers and their folders are not deleted.
// The background threads may still be alive and use the CServerNode and CFolder objects.
// The main thread doesnt wait for the background threads termination to prevent application hanging.
//
if (m_hShutdownEvent)
{
CloseHandle (m_hShutdownEvent);
m_hShutdownEvent = NULL;
}
}
DWORD
CClientConsoleDoc::Init ()
/*++
Routine name : CClientConsoleDoc::Init
Routine description:
Initializes document events and maps
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CClientConsoleDoc::Init"), dwRes);
//
// Create the shutdown event. This event will be signaled when the app is
// about to quit.
//
ASSERTION (NULL == m_hShutdownEvent);
m_hShutdownEvent = CreateEvent (NULL, // No security
TRUE, // Manual reset
FALSE, // Starts clear
NULL); // Unnamed
if (NULL == m_hShutdownEvent)
{
dwRes = GetLastError ();
CALL_FAIL (STARTUP_ERR, TEXT("CreateEvent"), dwRes);
PopupError (dwRes);
return dwRes;
}
//
// Init the map of notification messages from the servers
//
dwRes = CServerNode::InitMsgsMap ();
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (MEM_ERR, TEXT("CServerNode::InitMsgsMap"), dwRes);
PopupError (dwRes);
return dwRes;
}
ASSERTION (ERROR_SUCCESS == dwRes);
return dwRes;
} // CClientConsoleDoc::Init
BOOL CClientConsoleDoc::OnNewDocument()
{
BOOL bRes = FALSE;
DBG_ENTER(TEXT("CClientConsoleDoc::OnNewDocument"), bRes);
if (!CDocument::OnNewDocument())
{
return bRes;
}
if(theApp.IsCmdLineSingleServer())
{
//
// get command line server name
//
try
{
m_cstrSingleServer = theApp.GetCmdLineSingleServerName();
}
catch (...)
{
CALL_FAIL (MEM_ERR, TEXT("CString::operator ="), ERROR_NOT_ENOUGH_MEMORY);
PopupError (ERROR_NOT_ENOUGH_MEMORY);
return bRes;
}
}
DWORD dwRes = Init ();
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CClientConsoleDoc::Init"), dwRes);
return bRes;
}
bRes = TRUE;
return bRes;
}
/////////////////////////////////////////////////////////////////////////////
// CClientConsoleDoc serialization
void CClientConsoleDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CClientConsoleDoc diagnostics
#ifdef _DEBUG
void CClientConsoleDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CClientConsoleDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CClientConsoleDoc commands
DWORD
CClientConsoleDoc::AddServerNode (
LPCTSTR lpctstrServer
)
/*++
Routine name : CClientConsoleDoc::AddServerNode
Routine description:
Adds a new server node to the servers list and initializes it
Author:
Eran Yariv (EranY), Feb, 2000
Arguments:
lpctstrServer [in] - Server name
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CClientConsoleDoc::AddServerNode"), dwRes, TEXT("%s"), lpctstrServer);
CServerNode *pServerNode = NULL;
//
// Create the new server node
//
try
{
pServerNode = new CServerNode;
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT ("new CServerNode"), dwRes);
PopupError (dwRes);
return dwRes;
}
//
// Init the server
//
dwRes = pServerNode->Init (lpctstrServer);
if (ERROR_SUCCESS != dwRes)
{
pServerNode->Destroy ();
PopupError (dwRes);
return dwRes;
}
//
// Enter the (initialized) node at the end of the list
//
try
{
m_ServersList.push_back (pServerNode);
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("list::push_back"), dwRes);
PopupError (dwRes);
pServerNode->Destroy ();
return dwRes;
}
pServerNode->AttachFoldersToViews();
pServerNode->RefreshState();
CMainFrame *pFrm = GetFrm();
if (!pFrm)
{
//
// Shutdown in progress
//
return dwRes;
}
CLeftView* pLeftView = pFrm->GetLeftView();
ASSERTION(pLeftView);
CFolderListView* pListView = pLeftView->GetCurrentView();
if(NULL != pListView)
{
//
// refresh current folder
//
FolderType type = pListView->GetType();
CFolder* pFolder = pServerNode->GetFolder(type);
ASSERTION(pFolder);
pFolder->SetVisible();
}
return dwRes;
} // CClientConsoleDoc::AddServerNode
DWORD
CClientConsoleDoc::RefreshServersList()
/*++
Routine name : CClientConsoleDoc::RefreshServersList
Routine description:
Refreshes the list of servers
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
None.
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DWORD dwIndex;
PRINTER_INFO_2 *pPrinterInfo2 = NULL;
DWORD dwNumPrinters;
CServerNode* pServerNode;
DBG_ENTER(TEXT("CClientConsoleDoc::RefreshServersList"), dwRes);
//
// Prevent a new servers refresh request
//
if(m_bRefreshingServers )
{
return dwRes;
}
m_bRefreshingServers = TRUE;
if (m_cstrSingleServer.IsEmpty ())
{
SetAllServersInvalid();
//
// Working in a multiple-servers mode (normal mode)
// Enumerate the list of printers available on the system
//
dwRes = GetPrintersInfo(pPrinterInfo2, dwNumPrinters);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("GetPrintersInfo"), dwRes);
goto exit;
}
//
// Iterate the printers
//
for (dwIndex=0; dwIndex < dwNumPrinters; dwIndex++)
{
if(pPrinterInfo2[dwIndex].pDriverName)
{
if (_tcscmp(pPrinterInfo2[dwIndex].pDriverName, FAX_DRIVER_NAME))
{
//
// This printer does not use the Fax Server driver
//
continue;
}
}
//
// Init the node's share and server name
//
if( (NULL == pPrinterInfo2[dwIndex].pShareName ||
0 == _tcslen(pPrinterInfo2[dwIndex].pShareName)) &&
(NULL == pPrinterInfo2[dwIndex].pServerName ||
0 == _tcslen(pPrinterInfo2[dwIndex].pServerName)))
{
//
// On Win9x machine, the share name and server name are NULL
// or empty string but the
// port is valid and composed of \\servername\sharename
//
m_bWin9xPrinterFormat = TRUE;
if ((_tcsclen(pPrinterInfo2[dwIndex].pPortName) >= 5) &&
(_tcsncmp(pPrinterInfo2[dwIndex].pPortName, TEXT("\\\\"), 2) == 0))
{
//
// Port name is long enough and starts with "\\"
//
TCHAR* pServerStart = _tcsninc(pPrinterInfo2[dwIndex].pPortName,2);
TCHAR* pShareStart = _tcschr (pServerStart, TEXT('\\'));
if (pShareStart)
{
//
// Share was found after the server name.
// Seperate server from share and advance share name
//
TCHAR* ptcTmp = pShareStart;
pShareStart = _tcsinc(pShareStart);
*ptcTmp = TEXT('\0');
pPrinterInfo2[dwIndex].pShareName = pShareStart;
pPrinterInfo2[dwIndex].pServerName = pServerStart;
}
}
}
pServerNode = FindServerByName(pPrinterInfo2[dwIndex].pServerName);
if(NULL == pServerNode)
{
//
// Create new server node
//
dwRes = AddServerNode (pPrinterInfo2[dwIndex].pServerName);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("AddServerNode"), dwRes);
goto exit;
}
}
else
{
//
// the server node already exists
//
pServerNode->SetValid(TRUE);
}
} // End of printers loop
dwRes = RemoveAllInvalidServers();
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RemoveAllInvalidServers"), dwRes);
goto exit;
}
}
else
{
//
// Working in a single server mode (server name in m_cstrSingleServer).
// Create new server node.
//
int nSize = m_ServersList.size();
ASSERTION(0 == nSize || 1 == nSize);
if(0 == nSize)
{
dwRes = AddServerNode (m_cstrSingleServer);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("AddServerNode"), dwRes);
goto exit;
}
}
else
{
ASSERTION(FindServerByName(m_cstrSingleServer));
}
}
ASSERTION (ERROR_SUCCESS == dwRes);
exit:
SAFE_DELETE_ARRAY (pPrinterInfo2);
//
// Enable a new servers refresh request
//
m_bRefreshingServers = FALSE;
return dwRes;
} // CClientConsoleDoc::RefreshServersList
void CClientConsoleDoc::OnCloseDocument()
{
DBG_ENTER(TEXT("CClientConsoleDoc::OnCloseDocument"));
//
// Signal the event telling all our thread the app. is shutting down
//
SetEvent (m_hShutdownEvent);
m_bShuttingDown = TRUE;
CDocument::OnCloseDocument();
}
void
CClientConsoleDoc::ClearServersList()
/*++
Routine name : CClientConsoleDoc::ClearServersList
Routine description:
Clears the list of servers
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CClientConsoleDoc::ClearServersList"));
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
CServerNode *pServerNode = *it;
pServerNode->Destroy ();
}
m_ServersList.clear ();
} // CClientConsoleDoc::ClearServersList
void
CClientConsoleDoc::SetAllServersInvalid()
{
DBG_ENTER(TEXT("CClientConsoleDoc::SetAllServersInvalid"));
CServerNode *pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
pServerNode->SetValid(FALSE);
}
}
DWORD
CClientConsoleDoc::RemoveServerNode(
CServerNode* pServer
)
/*++
Routine name : CClientConsoleDoc::RemoveServerNode
Routine description:
remove the server from the servers list and from the tree view
Author:
Alexander Malysh (AlexMay), Mar, 2000
Arguments:
pServer [in] - server node
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CClientConsoleDoc::RemoveServerNode"), dwRes);
ASSERTION(pServer);
dwRes = pServer->InvalidateSubFolders(TRUE);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CServerNode::InvalidateSubFolders"), dwRes);
return dwRes;
}
//
// remove the server node from the list
//
try
{
m_ServersList.remove(pServer);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("list::remove"), dwRes);
return dwRes;
}
//
// delete the server node object
//
pServer->Destroy();
return dwRes;
}
DWORD
CClientConsoleDoc::RemoveAllInvalidServers()
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CClientConsoleDoc::RemoveAllInvalidServers"), dwRes);
BOOL bSrvFound;
CServerNode *pServerNode;
while(TRUE)
{
//
// find invalid server node
//
bSrvFound = FALSE;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
if(!pServerNode->IsValid())
{
bSrvFound = TRUE;
break;
}
}
if(bSrvFound)
{
//
// remove invalid server node
//
dwRes = RemoveServerNode(pServerNode);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RemoveServerNode"), dwRes);
break;
}
}
else
{
break;
}
}
return dwRes;
}
CServerNode*
CClientConsoleDoc::FindServerByName(
LPCTSTR lpctstrServer
)
/*++
Routine name : CClientConsoleDoc::FindServerByName
Routine description:
find CServerNode by machine name
Author:
Alexander Malysh (AlexMay), Mar, 2000
Arguments:
lpctstrServer [in] - machine name
Return Value:
CServerNode*
--*/
{
CServerNode *pServerNode = NULL;
CServerNode *pResultNode = NULL;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
if(pServerNode->Machine().Compare(lpctstrServer ? lpctstrServer : TEXT("")) == 0)
{
pResultNode = pServerNode;
break;
}
}
return pResultNode;
}
void
CClientConsoleDoc::SetInvalidFolder(
FolderType type
)
/*++
Routine name : CClientConsoleDoc::InvalidateFolder
Routine description:
invalidate specific folder content
Author:
Alexander Malysh (AlexMay), Apr, 2000
Arguments:
type [in] - folder type
Return Value:
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CClientConsoleDoc::InvalidateFolder"));
CFolder* pFolder;
CServerNode* pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
pFolder = pServerNode->GetFolder(type);
ASSERTION(pFolder);
if (pFolder)
{
pFolder->SetInvalid();
}
}
}
void
CClientConsoleDoc::ViewFolder(
FolderType type
)
/*++
Routine name : CClientConsoleDoc::ViewFolder
Routine description:
refresh specific folder in all servers
Author:
Alexander Malysh (AlexMay), Apr, 2000
Arguments:
type [in] - folder type
Return Value:
None.
--*/
{
DBG_ENTER(TEXT("CClientConsoleDoc::ViewFolder"));
CFolder* pFolder;
CServerNode *pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
pFolder = pServerNode->GetFolder(type);
ASSERTION(pFolder);
pFolder->SetVisible();
}
}
BOOL
CClientConsoleDoc::CanReceiveNow ()
/*++
Routine name : CClientConsoleDoc::CanReceiveNow
Routine description:
Can the user apply the 'Recieve now' option?
Author:
Eran Yariv (EranY), Mar, 2001
Arguments:
Return Value:
TRUE if the user apply the 'Recieve now' option, FALSE otherwise.
--*/
{
BOOL bEnable = FALSE;
//
// Locate the local fax server node
//
CServerNode* pServerNode = FindServerByName (NULL);
if (pServerNode)
{
if(pServerNode->IsOnline() && pServerNode->CanReceiveNow())
{
bEnable = TRUE;
}
}
return bEnable;
} // CClientConsoleDoc::CanReceiveNow
BOOL
CClientConsoleDoc::IsSendFaxEnable()
/*++
Routine name : CClientConsoleDoc::IsSendFaxEnable
Routine description:
does user anable to send fax
Author:
Alexander Malysh (AlexMay), Apr, 2000
Arguments:
Return Value:
TRUE if anable send fax, FALSE otherwise.
--*/
{
BOOL bEnable = FALSE;
CServerNode* pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
if(pServerNode->IsOnline() && pServerNode->CanSendFax())
{
bEnable = TRUE;
break;
}
}
return bEnable;
}
int
CClientConsoleDoc::GetFolderDataCount(
FolderType type
)
/*++
Routine name : CClientConsoleDoc::GetFolderDataCount
Routine description:
get total message number in specific folder from all servers
Author:
Alexander Malysh (AlexMay), Apr, 2000
Arguments:
type [in] - folder type
Return Value:
message number
--*/
{
int nCount=0;
CFolder* pFolder;
CServerNode* pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
pFolder = pServerNode->GetFolder(type);
nCount += pFolder->GetDataCount();
}
return nCount;
}
BOOL
CClientConsoleDoc::IsFolderRefreshing(
FolderType type
)
/*++
Routine name : CClientConsoleDoc::IsFolderRefreshing
Routine description:
if one of specific folders is refreshing
Author:
Alexander Malysh (AlexMay), Apr, 2000
Arguments:
type [TBD] - folder type
Return Value:
TRUE if one of specific folders is refreshing, FALSE otherwise.
--*/
{
CFolder* pFolder;
CServerNode* pServerNode;
for (SERVERS_LIST::iterator it = m_ServersList.begin(); it != m_ServersList.end(); ++it)
{
pServerNode = *it;
pFolder = pServerNode->GetFolder(type);
if (!pFolder)
{
DBG_ENTER(TEXT("CClientConsoleDoc::IsFolderRefreshing"));
ASSERTION_FAILURE;
}
if(pFolder->IsRefreshing())
{
return TRUE;
}
}
return FALSE;
}