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.
 
 
 
 
 
 

917 lines
20 KiB

// 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 doesn’t 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;
}