text: // MessageFolder.cpp: implementation of the CMessageFolder class.
  //
  //////////////////////////////////////////////////////////////////////
  
  #include "stdafx.h"
  #define __FILE_ID__     14
  
  #ifdef _DEBUG
  #undef THIS_FILE
  static char THIS_FILE[]=__FILE__;
  #define new DEBUG_NEW
  #endif
  
  //////////////////////////////////////////////////////////////////////
  // Construction/Destruction
  //////////////////////////////////////////////////////////////////////
  
  #define DEFAULT_NUM_MSGS_PER_CALL       100
  
  
  DWORD  CMessageFolder::m_sdwNumMessagesPerRPCCall = 0;
  
  void 
  CMessageFolder::ReadConfiguration ()
  /*++
  
  Routine name : CMessageFolder::ReadConfiguration
  
  Routine description:
  
      Reads the Messages-Per-RPC-Call parameters from the registry
  
  Author:
  
      Eran Yariv (EranY), Jan, 2000
  
  Arguments:
  
  
  Return Value:
  
      None.
  
  --*/
  {
      m_sdwNumMessagesPerRPCCall = 
          AfxGetApp ()->GetProfileInt (CLIENT_ARCHIVE_KEY, 
                                       CLIENT_ARCHIVE_MSGS_PER_CALL, 
                                       DEFAULT_NUM_MSGS_PER_CALL);
  }
  
  DWORD
  CMessageFolder::Refresh ()
  /*++
  
  Routine name : CMessageFolder::Refresh
  
  Routine description:
  
      Rebuilds the map of the message using the client API.
      This function is always called in the context of a worker thread.
  
      This function must be called when the data critical section is held.
  
  Author:
  
      Eran Yariv (EranY), Jan, 2000
  
  Arguments:
  
  
  Return Value:
  
      Standard Win32 error code
  
  --*/
  {
      DWORD dwRes = ERROR_SUCCESS;
      DBG_ENTER(TEXT("CMessageFolder::Refresh"), dwRes, TEXT("Type=%d"), Type());
      //
      // Enumerate archived messages from the server
      //
      ASSERTION (m_pServer);
      HANDLE              hFax;
      HANDLE              hEnum;
      DWORD               dwIndex;
      DWORD               dwNumMsgs = 0;
      PFAX_MESSAGE        pMsgs = NULL;
      MSGS_MAP            mapChunk;
  
  
      ASSERTION (m_sdwNumMessagesPerRPCCall);
      dwRes = m_pServer->GetConnectionHandle (hFax);
      if (ERROR_SUCCESS != dwRes)
      {
          CALL_FAIL (RPC_ERR, TEXT("CFolder::GetConnectionHandle"), dwRes);
          return dwRes;
      }
      if (m_bStopRefresh)
      {
          //
          // Quit immediately
          //
          return dwRes;
      }
      START_RPC_TIME(TEXT("FaxStartMessagesEnum")); 
      if (!FaxStartMessagesEnum (hFax, m_Folder, &hEnum))
      {
          dwRes = GetLastError ();
          END_RPC_TIME(TEXT("FaxStartMessagesEnum"));
          if (ERROR_NO_MORE_ITEMS == dwRes)
          {
              //
              // This is not a real error - the folder is simply empty
              //
              VERBOSE (DBG_MSG, TEXT("Folder is empty"));
              dwRes = ERROR_SUCCESS;
              return dwRes;
          }
          m_pServer->SetLastRPCError (dwRes);
          CALL_FAIL (RPC_ERR, TEXT("FaxStartMessagesEnum"), dwRes);
          return dwRes;
      }
      END_RPC_TIME(TEXT("FaxStartMessagesEnum"));
      if (m_bStopRefresh)
      {
          //
          // Quit immediately
          //
          goto exit;
      }
      //
      // Make sure our list is empty
      //
      ASSERTION (!m_Msgs.size()); 
      //
      // Get the messages in bunches
      //
      while (ERROR_SUCCESS == dwRes)
      {
          DWORD dwReturnedMsgs;
          START_RPC_TIME(TEXT("FaxEnumMessages")); 
          if (!FaxEnumMessages (hEnum, m_sdwNumMessagesPerRPCCall, &pMsgs, &dwReturnedMsgs))
          {
              dwRes = GetLastError ();
              END_RPC_TIME(TEXT("FaxEnumMessages"));
              if (ERROR_NO_MORE_ITEMS != dwRes)
              {   
                  //
                  // Really an error
                  //
                  m_pServer->SetLastRPCError (dwRes);
                  CALL_FAIL (RPC_ERR, TEXT("FaxEnumMessages"), dwRes);
                  goto exit;
              }
              else
              {
                  //
                  // Not an error - just a "end of data" sign
                  //
                  break;
              }
          }
          END_RPC_TIME(TEXT("FaxEnumMessages"));
          if (m_bStopRefresh)
          {
              //
              // Quit immediately
              //
              goto exit;
          }
          //
          // Success in enumeration
          //
          mapChunk.clear();
          for (dwIndex = 0; dwIndex < dwReturnedMsgs; dwIndex++)
          {
              CArchiveMsg *pMsg = NULL;
              //
              // Create a new message 
              //
              try
              {
                  pMsg = new CArchiveMsg;
              }
              catch (...)
              {
                  dwRes = ERROR_NOT_ENOUGH_MEMORY;
                  CALL_FAIL (MEM_ERR, TEXT("new CArchiveMsg"), dwRes);
                  goto exit;
              }
              //
              // Init the message 
              //
              dwRes = pMsg->Init (&pMsgs[dwIndex], m_pServer);
              if (ERROR_SUCCESS != dwRes)
              {
                  CALL_FAIL (MEM_ERR, TEXT("CArchiveMsg::Init"), dwRes);
                  SAFE_DELETE (pMsg);
                  goto exit;
              }
              //
              // Enter the message into the map
              //
              EnterData();
              try
              {
                  m_Msgs[pMsgs[dwIndex].dwlMessageId] = pMsg;
                  mapChunk[pMsgs[dwIndex].dwlMessageId] = pMsg;
              }
              catch (...)
              {
                  dwRes = ERROR_NOT_ENOUGH_MEMORY;
                  CALL_FAIL (MEM_ERR, TEXT("map::operator[]"), dwRes);
                  SAFE_DELETE (pMsg);
                  LeaveData ();
                  goto exit;
              }
              LeaveData ();
  
              if (m_bStopRefresh)
              {
                  //
                  // Quit immediately
                  //
                  goto exit;
              }
          }
          //
          // Free current chunk of messages
          //
          FaxFreeBuffer ((LPVOID)pMsgs);
          pMsgs = NULL;
  
          AttachView();
          if (m_pAssignedView)
          {
              //
              // Folder has a view attached
              //
              m_pAssignedView->SendMessage (
                             WM_FOLDER_ADD_CHUNK,
                             WPARAM (dwRes), 
                             LPARAM (&mapChunk));
          }
          else
          {
              //
              //  Shutdown in progress
              //
              goto exit;
          }
      }
      if (ERROR_NO_MORE_ITEMS == dwRes)
      {
          //
          // Not a real error
          //
          dwRes = ERROR_SUCCESS;
      }
      ASSERTION (ERROR_SUCCESS == dwRes);
  
  exit:
  
      //
      // Close enumeration handle
      //
      ASSERTION (hEnum);
      {
          START_RPC_TIME(TEXT("FaxEndMessagesEnum")); 
          if (!FaxEndMessagesEnum (hEnum))
          {
              dwRes = GetLastError ();
              END_RPC_TIME(TEXT("FaxEndMessagesEnum"));
              m_pServer->SetLastRPCError (dwRes);
              CALL_FAIL (RPC_ERR, TEXT("FaxEndMessagesEnum"), dwRes);
          }
          else
          {
              END_RPC_TIME(TEXT("FaxEndMessagesEnum"));
          }
      }
      //
      // Free left overs (if exist)
      //
      FaxFreeBuffer ((LPVOID)pMsgs);
      return dwRes;
  }   // CMessageFolder::Refresh
  
  
  
  DWORD 
  CMessageFolder::OnJobAdded (
      DWORDLONG dwlMsgId
  )
  /*++
  
  Routine name : CMessageFolder::OnJobAdded
  
  Routine description:
  
  	Handles notification of a message added to the archive
  
  Author:
  
  	Eran Yariv (EranY),	Feb, 2000
  
  Arguments:
  
  	dwlMsgId   [in]     - New message unique id
  
  Return Value:
  
      Standard Win32 error code
  
  --*/
  {
      DWORD dwRes = ERROR_SUCCESS;
      DBG_ENTER(TEXT("CMessageFolder::OnJobAdded"), 
                dwRes, 
                TEXT("MsgId=0x%016I64x, Type=%d"), 
                dwlMsgId,
                Type());
  
      HANDLE              hFax;
      PFAX_MESSAGE        pFaxMsg = NULL;
      CArchiveMsg           *pMsg = NULL;
  
      EnterData ();
      pMsg = (CArchiveMsg*)FindMessage (dwlMsgId);
      if (pMsg)
      {
          //
          // This message is already in the archive
          //
          VERBOSE (DBG_MSG, TEXT("Message is already known and visible"));
          goto exit;
      }
      //
      // Get information about this message
      //
      dwRes = m_pServer->GetConnectionHandle (hFax);
      if (ERROR_SUCCESS != dwRes)
      {
          CALL_FAIL (RPC_ERR, TEXT("CFolder::GetConnectionHandle"), dwRes);
          goto exit;
      }
      {
          START_RPC_TIME(TEXT("FaxGetMessage")); 
          if (!FaxGetMessage (hFax, dwlMsgId, m_Folder, &pFaxMsg))
          {
              dwRes = GetLastError ();
              END_RPC_TIME(TEXT("FaxGetMessage"));
              m_pServer->SetLastRPCError (dwRes);
              CALL_FAIL (RPC_ERR, TEXT("FaxGetMessage"), dwRes);
              goto exit;
          }
          END_RPC_TIME(TEXT("FaxGetMessage"));
      }
      //
      // Enter a new message to the map
      //
      try
      {
          pMsg = new CArchiveMsg;
          ASSERTION (pMsg);
          m_Msgs[pFaxMsg->dwlMessageId] = pMsg;
      }
      catch (...)
      {
          dwRes = ERROR_NOT_ENOUGH_MEMORY;
          SAFE_DELETE (pMsg);
          goto exit;
      }
      //
      // Init the message 
      //
      dwRes = pMsg->Init (pFaxMsg, m_pServer);
      if (ERROR_SUCCESS != dwRes)
      {
          CALL_FAIL (MEM_ERR, TEXT("CArchiveMsg::Init"), dwRes);
          //
          // Remove message from map and delete it
          //
          if (pMsg)
          {
              try
              {
                  m_Msgs.erase (pFaxMsg->dwlMessageId);
              }
              catch (...)
              {
                  dwRes = ERROR_NOT_ENOUGH_MEMORY;
                  CALL_FAIL (MEM_ERR, TEXT("map::erase"), dwRes);
              }
              SAFE_DELETE (pMsg);
          }
          goto exit;
      }
      if (m_pAssignedView)
      {
          //
          // If this folder is alive - tell our view to add the message
          //
          m_pAssignedView->OnUpdate (NULL, UPDATE_HINT_ADD_ITEM, pMsg);
      }
      
      ASSERTION (ERROR_SUCCESS == dwRes);
  
  exit:
      if(pFaxMsg)
      {
          FaxFreeBuffer(pFaxMsg);
      }
      LeaveData ();
      return dwRes;
  }   // CMessageFolder::OnJobAdded
  
  