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.

418 lines
10 KiB

  1. // MessageFolder.cpp: implementation of the CMessageFolder class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #define __FILE_ID__ 14
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. #define DEFAULT_NUM_MSGS_PER_CALL 100
  15. DWORD CMessageFolder::m_sdwNumMessagesPerRPCCall = 0;
  16. void
  17. CMessageFolder::ReadConfiguration ()
  18. /*++
  19. Routine name : CMessageFolder::ReadConfiguration
  20. Routine description:
  21. Reads the Messages-Per-RPC-Call parameters from the registry
  22. Author:
  23. Eran Yariv (EranY), Jan, 2000
  24. Arguments:
  25. Return Value:
  26. None.
  27. --*/
  28. {
  29. m_sdwNumMessagesPerRPCCall =
  30. AfxGetApp ()->GetProfileInt (CLIENT_ARCHIVE_KEY,
  31. CLIENT_ARCHIVE_MSGS_PER_CALL,
  32. DEFAULT_NUM_MSGS_PER_CALL);
  33. }
  34. DWORD
  35. CMessageFolder::Refresh ()
  36. /*++
  37. Routine name : CMessageFolder::Refresh
  38. Routine description:
  39. Rebuilds the map of the message using the client API.
  40. This function is always called in the context of a worker thread.
  41. This function must be called when the data critical section is held.
  42. Author:
  43. Eran Yariv (EranY), Jan, 2000
  44. Arguments:
  45. Return Value:
  46. Standard Win32 error code
  47. --*/
  48. {
  49. DWORD dwRes = ERROR_SUCCESS;
  50. DBG_ENTER(TEXT("CMessageFolder::Refresh"), dwRes, TEXT("Type=%d"), Type());
  51. //
  52. // Enumerate archived messages from the server
  53. //
  54. ASSERTION (m_pServer);
  55. HANDLE hFax;
  56. HANDLE hEnum;
  57. DWORD dwIndex;
  58. DWORD dwNumMsgs = 0;
  59. PFAX_MESSAGE pMsgs = NULL;
  60. MSGS_MAP mapChunk;
  61. ASSERTION (m_sdwNumMessagesPerRPCCall);
  62. dwRes = m_pServer->GetConnectionHandle (hFax);
  63. if (ERROR_SUCCESS != dwRes)
  64. {
  65. CALL_FAIL (RPC_ERR, TEXT("CFolder::GetConnectionHandle"), dwRes);
  66. return dwRes;
  67. }
  68. if (m_bStopRefresh)
  69. {
  70. //
  71. // Quit immediately
  72. //
  73. return dwRes;
  74. }
  75. START_RPC_TIME(TEXT("FaxStartMessagesEnum"));
  76. if (!FaxStartMessagesEnum (hFax, m_Folder, &hEnum))
  77. {
  78. dwRes = GetLastError ();
  79. END_RPC_TIME(TEXT("FaxStartMessagesEnum"));
  80. if (ERROR_NO_MORE_ITEMS == dwRes)
  81. {
  82. //
  83. // This is not a real error - the folder is simply empty
  84. //
  85. VERBOSE (DBG_MSG, TEXT("Folder is empty"));
  86. dwRes = ERROR_SUCCESS;
  87. return dwRes;
  88. }
  89. m_pServer->SetLastRPCError (dwRes);
  90. CALL_FAIL (RPC_ERR, TEXT("FaxStartMessagesEnum"), dwRes);
  91. return dwRes;
  92. }
  93. END_RPC_TIME(TEXT("FaxStartMessagesEnum"));
  94. if (m_bStopRefresh)
  95. {
  96. //
  97. // Quit immediately
  98. //
  99. goto exit;
  100. }
  101. //
  102. // Make sure our list is empty
  103. //
  104. ASSERTION (!m_Msgs.size());
  105. //
  106. // Get the messages in bunches
  107. //
  108. while (ERROR_SUCCESS == dwRes)
  109. {
  110. DWORD dwReturnedMsgs;
  111. START_RPC_TIME(TEXT("FaxEnumMessages"));
  112. if (!FaxEnumMessages (hEnum, m_sdwNumMessagesPerRPCCall, &pMsgs, &dwReturnedMsgs))
  113. {
  114. dwRes = GetLastError ();
  115. END_RPC_TIME(TEXT("FaxEnumMessages"));
  116. if (ERROR_NO_MORE_ITEMS != dwRes)
  117. {
  118. //
  119. // Really an error
  120. //
  121. m_pServer->SetLastRPCError (dwRes);
  122. CALL_FAIL (RPC_ERR, TEXT("FaxEnumMessages"), dwRes);
  123. goto exit;
  124. }
  125. else
  126. {
  127. //
  128. // Not an error - just a "end of data" sign
  129. //
  130. break;
  131. }
  132. }
  133. END_RPC_TIME(TEXT("FaxEnumMessages"));
  134. if (m_bStopRefresh)
  135. {
  136. //
  137. // Quit immediately
  138. //
  139. goto exit;
  140. }
  141. //
  142. // Success in enumeration
  143. //
  144. mapChunk.clear();
  145. for (dwIndex = 0; dwIndex < dwReturnedMsgs; dwIndex++)
  146. {
  147. CArchiveMsg *pMsg = NULL;
  148. //
  149. // Create a new message
  150. //
  151. try
  152. {
  153. pMsg = new CArchiveMsg;
  154. }
  155. catch (...)
  156. {
  157. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  158. CALL_FAIL (MEM_ERR, TEXT("new CArchiveMsg"), dwRes);
  159. goto exit;
  160. }
  161. //
  162. // Init the message
  163. //
  164. dwRes = pMsg->Init (&pMsgs[dwIndex], m_pServer);
  165. if (ERROR_SUCCESS != dwRes)
  166. {
  167. CALL_FAIL (MEM_ERR, TEXT("CArchiveMsg::Init"), dwRes);
  168. SAFE_DELETE (pMsg);
  169. goto exit;
  170. }
  171. //
  172. // Enter the message into the map
  173. //
  174. EnterData();
  175. try
  176. {
  177. m_Msgs[pMsgs[dwIndex].dwlMessageId] = pMsg;
  178. mapChunk[pMsgs[dwIndex].dwlMessageId] = pMsg;
  179. }
  180. catch (...)
  181. {
  182. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  183. CALL_FAIL (MEM_ERR, TEXT("map::operator[]"), dwRes);
  184. SAFE_DELETE (pMsg);
  185. LeaveData ();
  186. goto exit;
  187. }
  188. LeaveData ();
  189. if (m_bStopRefresh)
  190. {
  191. //
  192. // Quit immediately
  193. //
  194. goto exit;
  195. }
  196. }
  197. //
  198. // Free current chunk of messages
  199. //
  200. FaxFreeBuffer ((LPVOID)pMsgs);
  201. pMsgs = NULL;
  202. AttachView();
  203. if (m_pAssignedView)
  204. {
  205. //
  206. // Folder has a view attached
  207. //
  208. m_pAssignedView->SendMessage (
  209. WM_FOLDER_ADD_CHUNK,
  210. WPARAM (dwRes),
  211. LPARAM (&mapChunk));
  212. }
  213. else
  214. {
  215. //
  216. // Shutdown in progress
  217. //
  218. goto exit;
  219. }
  220. }
  221. if (ERROR_NO_MORE_ITEMS == dwRes)
  222. {
  223. //
  224. // Not a real error
  225. //
  226. dwRes = ERROR_SUCCESS;
  227. }
  228. ASSERTION (ERROR_SUCCESS == dwRes);
  229. exit:
  230. //
  231. // Close enumeration handle
  232. //
  233. ASSERTION (hEnum);
  234. {
  235. START_RPC_TIME(TEXT("FaxEndMessagesEnum"));
  236. if (!FaxEndMessagesEnum (hEnum))
  237. {
  238. dwRes = GetLastError ();
  239. END_RPC_TIME(TEXT("FaxEndMessagesEnum"));
  240. m_pServer->SetLastRPCError (dwRes);
  241. CALL_FAIL (RPC_ERR, TEXT("FaxEndMessagesEnum"), dwRes);
  242. }
  243. else
  244. {
  245. END_RPC_TIME(TEXT("FaxEndMessagesEnum"));
  246. }
  247. }
  248. //
  249. // Free left overs (if exist)
  250. //
  251. FaxFreeBuffer ((LPVOID)pMsgs);
  252. return dwRes;
  253. } // CMessageFolder::Refresh
  254. DWORD
  255. CMessageFolder::OnJobAdded (
  256. DWORDLONG dwlMsgId
  257. )
  258. /*++
  259. Routine name : CMessageFolder::OnJobAdded
  260. Routine description:
  261. Handles notification of a message added to the archive
  262. Author:
  263. Eran Yariv (EranY), Feb, 2000
  264. Arguments:
  265. dwlMsgId [in] - New message unique id
  266. Return Value:
  267. Standard Win32 error code
  268. --*/
  269. {
  270. DWORD dwRes = ERROR_SUCCESS;
  271. DBG_ENTER(TEXT("CMessageFolder::OnJobAdded"),
  272. dwRes,
  273. TEXT("MsgId=0x%016I64x, Type=%d"),
  274. dwlMsgId,
  275. Type());
  276. HANDLE hFax;
  277. PFAX_MESSAGE pFaxMsg = NULL;
  278. CArchiveMsg *pMsg = NULL;
  279. EnterData ();
  280. pMsg = (CArchiveMsg*)FindMessage (dwlMsgId);
  281. if (pMsg)
  282. {
  283. //
  284. // This message is already in the archive
  285. //
  286. VERBOSE (DBG_MSG, TEXT("Message is already known and visible"));
  287. goto exit;
  288. }
  289. //
  290. // Get information about this message
  291. //
  292. dwRes = m_pServer->GetConnectionHandle (hFax);
  293. if (ERROR_SUCCESS != dwRes)
  294. {
  295. CALL_FAIL (RPC_ERR, TEXT("CFolder::GetConnectionHandle"), dwRes);
  296. goto exit;
  297. }
  298. {
  299. START_RPC_TIME(TEXT("FaxGetMessage"));
  300. if (!FaxGetMessage (hFax, dwlMsgId, m_Folder, &pFaxMsg))
  301. {
  302. dwRes = GetLastError ();
  303. END_RPC_TIME(TEXT("FaxGetMessage"));
  304. m_pServer->SetLastRPCError (dwRes);
  305. CALL_FAIL (RPC_ERR, TEXT("FaxGetMessage"), dwRes);
  306. goto exit;
  307. }
  308. END_RPC_TIME(TEXT("FaxGetMessage"));
  309. }
  310. //
  311. // Enter a new message to the map
  312. //
  313. try
  314. {
  315. pMsg = new CArchiveMsg;
  316. ASSERTION (pMsg);
  317. m_Msgs[pFaxMsg->dwlMessageId] = pMsg;
  318. }
  319. catch (...)
  320. {
  321. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  322. SAFE_DELETE (pMsg);
  323. goto exit;
  324. }
  325. //
  326. // Init the message
  327. //
  328. dwRes = pMsg->Init (pFaxMsg, m_pServer);
  329. if (ERROR_SUCCESS != dwRes)
  330. {
  331. CALL_FAIL (MEM_ERR, TEXT("CArchiveMsg::Init"), dwRes);
  332. //
  333. // Remove message from map and delete it
  334. //
  335. if (pMsg)
  336. {
  337. try
  338. {
  339. m_Msgs.erase (pFaxMsg->dwlMessageId);
  340. }
  341. catch (...)
  342. {
  343. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  344. CALL_FAIL (MEM_ERR, TEXT("map::erase"), dwRes);
  345. }
  346. SAFE_DELETE (pMsg);
  347. }
  348. goto exit;
  349. }
  350. if (m_pAssignedView)
  351. {
  352. //
  353. // If this folder is alive - tell our view to add the message
  354. //
  355. m_pAssignedView->OnUpdate (NULL, UPDATE_HINT_ADD_ITEM, pMsg);
  356. }
  357. ASSERTION (ERROR_SUCCESS == dwRes);
  358. exit:
  359. if(pFaxMsg)
  360. {
  361. FaxFreeBuffer(pFaxMsg);
  362. }
  363. LeaveData ();
  364. return dwRes;
  365. } // CMessageFolder::OnJobAdded