Source code of Windows XP (NT5)
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.

1139 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. xplogon.cpp
  5. Abstract:
  6. This module contains the XPLOGON class implementation.
  7. Author:
  8. Wesley Witt (wesw) 13-Aug-1996
  9. --*/
  10. #include "faxxp.h"
  11. #pragma hdrstop
  12. CHAR gszProviderName[] = FAX_TRANSPORT_NAME;
  13. LPSTR gszFAXAddressType = FAX_ADDRESS_TYPE;
  14. LPSTR *gpszXPAddressTypes;
  15. CXPLogon::CXPLogon(
  16. HINSTANCE hInstance,
  17. LPMAPISUP pSupObj,
  18. LPSTR ProfileName
  19. )
  20. /*++
  21. Routine Description:
  22. Constructor of the object. Parameters are passed to initialize the
  23. data members with the appropiate values.
  24. Arguments:
  25. hInstance - Instance of the provider DLL
  26. pSupObj - Pointer to IMAPISupport object used in
  27. CXPLogon methods
  28. Return Value:
  29. None.
  30. --*/
  31. {
  32. m_cRef = 1;
  33. m_hInstance = hInstance;
  34. m_pSupObj = pSupObj;
  35. m_fABWDSInstalled = FALSE;
  36. strcpy( m_ProfileName, ProfileName );
  37. m_pSupObj->AddRef();
  38. }
  39. CXPLogon::~CXPLogon()
  40. /*++
  41. Routine Description:
  42. Destructor of CXPLogon. Releases memory allocated for internal
  43. properties during the life of this transport logon object.
  44. Arguments:
  45. None.
  46. Return Value:
  47. None.
  48. --*/
  49. {
  50. // Release the IMAPISupport object
  51. m_pSupObj->Release();
  52. m_pSupObj = NULL;
  53. }
  54. STDMETHODIMP
  55. CXPLogon::QueryInterface(
  56. REFIID riid,
  57. LPVOID * ppvObj
  58. )
  59. /*++
  60. Routine Description:
  61. Returns a pointer to a interface requested if the interface is
  62. supported and implemented by this object. If it is not supported, it
  63. returns NULL.
  64. Arguments:
  65. Refer to OLE Documentation on this method.
  66. Return Value:
  67. An HRESULT.
  68. --*/
  69. {
  70. // OLE requires NULLing parameter
  71. *ppvObj = NULL;
  72. // If this is one of the two IID return an interface pointer to it
  73. if (riid == IID_IXPLogon || riid == IID_IUnknown) {
  74. *ppvObj = (LPVOID)this;
  75. // Increase usage count of this object
  76. AddRef();
  77. return S_OK;
  78. }
  79. // This object does not support the interface requested
  80. return E_NOINTERFACE;
  81. }
  82. STDMETHODIMP
  83. CXPLogon::AddressTypes(
  84. ULONG * pulFlags,
  85. ULONG * pcAdrType,
  86. LPTSTR ** pppAdrTypeArray,
  87. ULONG * pcMAPIUID,
  88. LPMAPIUID ** pppMAPIUIDArray
  89. )
  90. /*++
  91. Routine Description:
  92. Called by the MAPI Spooler when initializing this XP logon object to
  93. allow the transport to register the address it will handle.
  94. Arguments:
  95. Refer to OLE Documentation on this method.
  96. Return Value:
  97. S_OK always
  98. --*/
  99. {
  100. *pcAdrType = 1;
  101. *pulFlags = 0;
  102. gpszXPAddressTypes = &gszFAXAddressType;
  103. *pppAdrTypeArray = gpszXPAddressTypes;
  104. *pcMAPIUID = 0;
  105. *pppMAPIUIDArray = NULL;
  106. return S_OK;
  107. }
  108. STDMETHODIMP
  109. CXPLogon::RegisterOptions(
  110. ULONG * pulFlags,
  111. ULONG * pcOptions,
  112. LPOPTIONDATA * ppOptions
  113. )
  114. /*++
  115. Routine Description:
  116. This transport does not registers any per-recipient or per-message
  117. option processing, so we return 0 options. And NULL in the OPTIONDATA
  118. structure pointer.
  119. Arguments:
  120. Refer to OLE Documentation on this method.
  121. Return Value:
  122. An HRESULT.
  123. --*/
  124. {
  125. *pulFlags = 0;
  126. *pcOptions = 0;
  127. *ppOptions = NULL;
  128. return S_OK;
  129. }
  130. STDMETHODIMP
  131. CXPLogon::InitializeStatusRow(
  132. ULONG ulFlags
  133. )
  134. /*++
  135. Routine Description:
  136. To initialize or modify the status properties of a CXPLogon
  137. object. This function allocates an array with NUM_STATUS_ROW_PROPS
  138. properties and initializes them.
  139. Arguments:
  140. ulFlags - 0 if the properties are being created the first time.
  141. MODIFY_FLAGS if a change is being made to the properties
  142. Return Value:
  143. An HRESULT.
  144. --*/
  145. {
  146. #define NUM_STATUS_ROW_PROPS 10
  147. SPropValue spvStatusRow[NUM_STATUS_ROW_PROPS] = { 0 };
  148. ULONG i = 0;
  149. ///////////////////////////////////////////////////////////////////////////
  150. // Set the PR_PROVIDER_DISPLAY property: The transport readable name
  151. spvStatusRow[i].ulPropTag = PR_PROVIDER_DISPLAY;
  152. spvStatusRow[i++].Value.LPSZ = TRANSPORT_DISPLAY_NAME_STRING;
  153. ///////////////////////////////////////////////////////////////////////////
  154. // Set the PR_RESOURCE_METHODS property. These are the methods implemented
  155. // in the our IMAPIStatus implementation (CMAPIStatus class.)
  156. spvStatusRow[i].ulPropTag = PR_RESOURCE_METHODS;
  157. // we support ALL the methods in our implementation of IMAPIStatus interface (except the WRITABLE ones)
  158. spvStatusRow[i++].Value.l = STATUS_SETTINGS_DIALOG |
  159. STATUS_FLUSH_QUEUES |
  160. STATUS_VALIDATE_STATE;
  161. ///////////////////////////////////////////////////////////////////////////
  162. // Set the PR_STATUS_CODE property.
  163. spvStatusRow[i].ulPropTag = PR_STATUS_CODE;
  164. spvStatusRow[i++].Value.l = GetTransportStatusCode();
  165. ///////////////////////////////////////////////////////////////////////////
  166. // Set the PR_STATUS_STRING property
  167. TCHAR szStatus[64];
  168. LoadStatusString (szStatus, sizeof(szStatus));
  169. spvStatusRow[i].ulPropTag = PR_STATUS_STRING;
  170. spvStatusRow[i++].Value.LPSZ = szStatus;
  171. ///////////////////////////////////////////////////////////////////////////
  172. // Set the PR_DISPLAY_NAME property
  173. spvStatusRow[i].ulPropTag = PR_DISPLAY_NAME;
  174. spvStatusRow[i++].Value.LPSZ = TRANSPORT_DISPLAY_NAME_STRING;
  175. ///////////////////////////////////////////////////////////////////////////
  176. // Set the PR_REMOTE_PROGRESS property
  177. spvStatusRow[i].ulPropTag = PR_REMOTE_PROGRESS;
  178. spvStatusRow[i++].Value.l = -1; // Not initialized
  179. ///////////////////////////////////////////////////////////////////////////
  180. // Set the PR_REMOTE_VALIDATE_OK property
  181. spvStatusRow[i].ulPropTag = PR_REMOTE_VALIDATE_OK;
  182. spvStatusRow[i++].Value.b = TRUE;
  183. // Write the entries on the provider's session status row
  184. HRESULT hResult = m_pSupObj->ModifyStatusRow (i, spvStatusRow, ulFlags);
  185. return hResult;
  186. }
  187. VOID WINAPI
  188. CXPLogon::UpdateStatus(
  189. BOOL fAddValidate,
  190. BOOL fValidateOkState
  191. )
  192. /*++
  193. Routine Description:
  194. Updates the transport status row of this transport in the MAPI Mail
  195. subsystem. Updates the flags according the internal state flags
  196. maintained in status code of the transport and loads a readable status
  197. string to reset the status row. The caller of this method should update
  198. the status code member variable prior to calling UpdateStatus()
  199. Arguments:
  200. fAddValidate
  201. fValidateOkState
  202. Return Value:
  203. None.
  204. --*/
  205. {
  206. ULONG cProps = 1;
  207. SPropValue rgProps[1] = { 0 };
  208. rgProps[0].ulPropTag = PR_STATUS_CODE;
  209. rgProps[0].Value.l = GetTransportStatusCode();
  210. HRESULT hResult = m_pSupObj->ModifyStatusRow( cProps, rgProps, STATUSROW_UPDATE );
  211. }
  212. BOOL WINAPI
  213. CXPLogon::LoadStatusString(
  214. LPTSTR pString,
  215. UINT uStringSize
  216. )
  217. /*++
  218. Routine Description:
  219. Loads a string from the transport's stringtable. This method is called
  220. by the CXPLogon::UpdateStatus method when updating a status row. This
  221. method loads the string based on the status bits of the transport
  222. status code
  223. Arguments:
  224. pString - Pointer to a string which will hold the status string
  225. uStringSize - Maximum number of characters allowed in the string
  226. Return Value:
  227. TRUE - If the string was found in the string table.
  228. FALSE - The string was not found. The String indicated by
  229. pString is set to hold 0 characters
  230. --*/
  231. {
  232. strcpy( pString, "Status String" );
  233. return TRUE;
  234. }
  235. STDMETHODIMP
  236. CXPLogon::TransportNotify(
  237. ULONG * pulFlags,
  238. LPVOID * ppvData
  239. )
  240. /*++
  241. Routine Description:
  242. Update the status row registered by this transport with MAPI.
  243. Arguments:
  244. Refer to MAPI Documentation on this method.
  245. Return Value:
  246. An HRESULT.
  247. --*/
  248. {
  249. ULONG ulOldStatus = GetTransportStatusCode();
  250. if (*pulFlags & NOTIFY_BEGIN_INBOUND) {
  251. AddStatusBits( STATUS_INBOUND_ENABLED );
  252. }
  253. if (*pulFlags & NOTIFY_END_INBOUND) {
  254. RemoveStatusBits( STATUS_INBOUND_ENABLED );
  255. }
  256. if (*pulFlags & NOTIFY_BEGIN_OUTBOUND) {
  257. AddStatusBits( STATUS_OUTBOUND_ENABLED );
  258. }
  259. if (*pulFlags & NOTIFY_END_OUTBOUND) {
  260. RemoveStatusBits( STATUS_OUTBOUND_ENABLED );
  261. }
  262. if (*pulFlags & NOTIFY_BEGIN_OUTBOUND_FLUSH) {
  263. m_pSupObj->SpoolerNotify( NOTIFY_SENTDEFERRED, NULL );
  264. }
  265. if (*pulFlags & NOTIFY_END_OUTBOUND_FLUSH) {
  266. RemoveStatusBits( STATUS_OUTBOUND_FLUSH );
  267. }
  268. if (*pulFlags & NOTIFY_END_INBOUND_FLUSH) {
  269. RemoveStatusBits( STATUS_INBOUND_FLUSH );
  270. }
  271. if (ulOldStatus != GetTransportStatusCode()) {
  272. UpdateStatus();
  273. }
  274. return S_OK;
  275. }
  276. STDMETHODIMP
  277. CXPLogon::Idle(
  278. ULONG ulFlags
  279. )
  280. /*++
  281. Routine Description:
  282. Stub method. We should not get called here, because we told
  283. the spooler not to call us here.
  284. Arguments:
  285. Refer to MAPI Documentation on this method.
  286. Return Value:
  287. S_OK always.
  288. --*/
  289. {
  290. return S_OK;
  291. }
  292. STDMETHODIMP
  293. CXPLogon::TransportLogoff(
  294. ULONG ulFlags
  295. )
  296. /*++
  297. Routine Description:
  298. This method is called by the spooler when the transport should do final
  299. arragements before it gets released.
  300. Arguments:
  301. Refer to MAPI Documentation on this method.
  302. Return Value:
  303. An HRESULT.
  304. --*/
  305. {
  306. //
  307. // We should attempt to remove the transport's status row from
  308. // the system, but if we fail we won't fail the call.
  309. //
  310. HRESULT hResult = m_pSupObj->ModifyStatusRow (0, NULL, 0);
  311. return S_OK;
  312. }
  313. STDMETHODIMP
  314. CXPLogon::SubmitMessage(
  315. ULONG ulFlags,
  316. LPMESSAGE pMsgObj,
  317. ULONG * pulMsgRef,
  318. ULONG * pulReturnParm
  319. )
  320. /*++
  321. Routine Description:
  322. This method is called by the spooler when a client submits a
  323. message to a recipient whose address type this transport handles.
  324. The spooler calls this method twice for each deferred message.
  325. The first time (before the delivery time) when the message is
  326. submitted by the client, we simply return. The message is then queued
  327. by the spooler for later delivery. We keep track of when it's time
  328. to send deferred messages.
  329. The second time we're called, the state variable will be 'READY' and
  330. we go ahead and start the actual transmission. While we're in the
  331. body of this function, the implied state is 'SENDING'
  332. If the client logs out of this session, any pending messages get
  333. queued again the next time it logs in.
  334. In this transport we get a recipient table, we restrict the table for
  335. unmarked recipients. After the table is ready we invoke a helper
  336. method to do the actual transmission.
  337. Arguments:
  338. Refer to MAPI Documentation on this method.
  339. Return Value:
  340. An HRESULT.
  341. --*/
  342. {
  343. LPADRLIST pAdrList = NULL, pAdrListFailed = NULL;
  344. ULONG ulRow, ulCount1 = 0 , ulCount2 = 0;
  345. LPSPropValue pProps;
  346. FILETIME ft;
  347. SYSTEMTIME st;
  348. BOOL fSentSuccessfully;
  349. ULONG cValues;
  350. LPSPropValue pMsgProps = NULL;
  351. BOOL NeedDeliveryReport;
  352. CHAR szHeaderText[1024];
  353. LPSTREAM lpstmT = NULL;
  354. DWORD Rslt;
  355. CHAR ErrorText[256];
  356. BOOL UseRichText = FALSE;
  357. LPMAPITABLE AttachmentTable = NULL;
  358. LPSRowSet pAttachmentRows = NULL;
  359. LPMAPITABLE pTable = NULL;
  360. SPropValue spvRecipUnsent;
  361. SRestriction srRecipientUnhandled;
  362. LPSRowSet pRecipRows = NULL;
  363. CheckSpoolerYield( TRUE );
  364. // Get the recipient table from the message
  365. HRESULT hResult = pMsgObj->GetRecipientTable( FALSE, &pTable );
  366. if (hResult) {
  367. goto ErrorExit;
  368. }
  369. // The spooler marks all the message recipients this transport has to
  370. // handle with PR_RESPONSIBILITY set to FALSE
  371. spvRecipUnsent.ulPropTag = PR_RESPONSIBILITY;
  372. spvRecipUnsent.Value.b = FALSE;
  373. srRecipientUnhandled.rt = RES_PROPERTY;
  374. srRecipientUnhandled.res.resProperty.relop = RELOP_EQ;
  375. srRecipientUnhandled.res.resProperty.ulPropTag = PR_RESPONSIBILITY;
  376. srRecipientUnhandled.res.resProperty.lpProp = &spvRecipUnsent;
  377. hResult = pTable->Restrict( &srRecipientUnhandled, 0 );
  378. if (hResult) {
  379. goto ErrorExit;
  380. }
  381. // Let the MAPI spooler do other things
  382. CheckSpoolerYield();
  383. hResult = HrAddColumns(
  384. pTable,
  385. (LPSPropTagArray) &sptRecipTable,
  386. gpfnAllocateBuffer,
  387. gpfnFreeBuffer
  388. );
  389. if (FAILED(hResult)) {
  390. goto ErrorExit;
  391. }
  392. hResult = HrQueryAllRows(
  393. pTable,
  394. NULL,
  395. NULL,
  396. NULL,
  397. 0,
  398. &pRecipRows
  399. );
  400. if (FAILED(hResult)) {
  401. goto ErrorExit;
  402. }
  403. //
  404. // Let the MAPI spooler do other things
  405. //
  406. CheckSpoolerYield();
  407. hResult = pMsgObj->GetProps(
  408. (LPSPropTagArray) &sptPropsForHeader,
  409. 0,
  410. &cValues,
  411. &pMsgProps
  412. );
  413. if (FAILED(hResult)) {
  414. goto ErrorExit;
  415. }
  416. hResult = pMsgObj->OpenProperty(
  417. PR_RTF_COMPRESSED,
  418. &IID_IStream,
  419. 0,
  420. 0,
  421. (LPUNKNOWN*) &lpstmT
  422. );
  423. if (FAILED(hResult)) {
  424. hResult = pMsgObj->OpenProperty(
  425. PR_BODY,
  426. &IID_IStream,
  427. 0,
  428. 0,
  429. (LPUNKNOWN*) &lpstmT
  430. );
  431. if (FAILED(hResult)) {
  432. //
  433. // the message body is empty
  434. //
  435. lpstmT = NULL;
  436. }
  437. } else {
  438. UseRichText = TRUE;
  439. }
  440. // We need to check if the sender requeste a delivery report or not.
  441. if (PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED == pMsgProps[MSG_DR_REPORT].ulPropTag && pMsgProps[MSG_DR_REPORT].Value.b) {
  442. NeedDeliveryReport = TRUE;
  443. } else {
  444. NeedDeliveryReport = FALSE;
  445. }
  446. GetSystemTime (&st);
  447. SystemTimeToFileTime (&st, &ft);
  448. for (ulRow=0; ulRow<pRecipRows->cRows; ulRow++) {
  449. pProps = pRecipRows->aRow[ulRow].lpProps;
  450. pProps[RECIP_RESPONSIBILITY].ulPropTag = PR_RESPONSIBILITY;
  451. pProps[RECIP_RESPONSIBILITY].Value.b = TRUE;
  452. Rslt = SendFaxDocument( pMsgObj, lpstmT, UseRichText, pMsgProps, pProps );
  453. fSentSuccessfully = Rslt == 0;
  454. if (!fSentSuccessfully) {
  455. // Make the spooler generate an NDR instead of DR
  456. pProps[RECIP_DELIVER_TIME].ulPropTag = PR_NULL;
  457. LoadString( FaxXphInstance, Rslt, ErrorText, sizeof(ErrorText) );
  458. wsprintf( szHeaderText,
  459. "\tThe Fax transport service failed to deliver the message to this recipient.\r\n%s\r\n",
  460. ErrorText
  461. );
  462. LPTSTR pStr;
  463. hResult = gpfnAllocateMore( Cbtszsize(szHeaderText), pProps, (LPVOID *)&pStr );
  464. if (SUCCEEDED(hResult)) {
  465. // Copy the formatted string and hook it into the
  466. // pre-allocated (by MAPI) column
  467. lstrcpy (pStr, szHeaderText);
  468. pProps[RECIP_REPORT_TEXT].ulPropTag = PR_REPORT_TEXT;
  469. pProps[RECIP_REPORT_TEXT].Value.LPSZ = pStr;
  470. } else {
  471. pProps[RECIP_REPORT_TEXT].ulPropTag = PROP_TAG (PT_ERROR, PROP_ID (PR_REPORT_TEXT));
  472. pProps[RECIP_REPORT_TEXT].Value.err = hResult;
  473. }
  474. } else {
  475. // For delivery report, each recipient must have this property set.
  476. // Otherwise the spooler will default to generate an NDR instead.
  477. pProps[RECIP_DELIVER_TIME].ulPropTag = PR_DELIVER_TIME;
  478. pProps[RECIP_DELIVER_TIME].Value.ft = ft;
  479. pProps[RECIP_REPORT_TEXT].ulPropTag = PROP_TAG (PT_ERROR, PROP_ID (PR_REPORT_TEXT));
  480. pProps[RECIP_REPORT_TEXT].Value.err = S_OK;
  481. }
  482. //
  483. // manage the lists
  484. //
  485. LPADRLIST * ppTmpList = (fSentSuccessfully ? &pAdrList : &pAdrListFailed);
  486. ULONG ulTmpCount = (fSentSuccessfully ? ulCount1 : ulCount2);
  487. //
  488. // Does the list where this recipient goes have enough room for one more entry?
  489. // If not, resize the address list to hold QUERY_SIZE more entries.
  490. //
  491. if (!(*ppTmpList) || ((*ppTmpList)->cEntries + 1 > ulTmpCount)) {
  492. hResult= GrowAddressList( ppTmpList, 10, &ulTmpCount );
  493. if (hResult) {
  494. goto ErrorExit;
  495. }
  496. ulCount1 = (fSentSuccessfully ? ulTmpCount : ulCount1);
  497. ulCount2 = (!fSentSuccessfully ? ulTmpCount : ulCount2);
  498. }
  499. //
  500. // We have room now so store the new ADRENTRY. As part of the
  501. // storage, we're going to copy the SRow pointer from the SRowSet
  502. // into the ADRENTRY. Once we've done this, we won't need the
  503. // SRowSet any more ... and the SRow will be released when
  504. // we unwind the ADRLIST
  505. //
  506. (*ppTmpList)->aEntries[(*ppTmpList)->cEntries].cValues = pRecipRows->aRow[ulRow].cValues;
  507. (*ppTmpList)->aEntries[(*ppTmpList)->cEntries].rgPropVals = pRecipRows->aRow[ulRow].lpProps;
  508. //
  509. // Increase the number of entries in the address list
  510. //
  511. (*ppTmpList)->cEntries++;
  512. //
  513. // Now that we are finished with this row (it is in the right
  514. // adrlist) we want to disassociate it from the rowset
  515. // so we don't delete this before we modify the recipients list
  516. //
  517. pRecipRows->aRow[ulRow].lpProps = NULL;
  518. pRecipRows->aRow[ulRow].cValues = 0;
  519. }
  520. if (!(FAILED(hResult))) {
  521. // Now we need to save changes on the message and close it.
  522. // After this, the message object can't be used.
  523. hResult = pMsgObj->SaveChanges(0);
  524. }
  525. // Let the MAPI spooler do other things
  526. CheckSpoolerYield();
  527. // Do we have some recipients that the message arrived to?
  528. if (pAdrList) {
  529. hResult = pMsgObj->ModifyRecipients( MODRECIP_MODIFY, pAdrList );
  530. hResult = S_OK; // We'll drop the error code from the modify recipients call
  531. if (NeedDeliveryReport) {
  532. hResult = m_pSupObj->StatusRecips( pMsgObj, pAdrList );
  533. if (!HR_FAILED(hResult)) {
  534. // If we were successful, we should null out the pointer becase MAPI released
  535. // the memory for this structure. And we should not try to release it
  536. // again in the cleanup code.
  537. pAdrList = NULL;
  538. }
  539. }
  540. }
  541. // Do we have some recipients that the message DID NOT arrived to?
  542. if (pAdrListFailed) {
  543. hResult = pMsgObj->ModifyRecipients( MODRECIP_MODIFY, pAdrListFailed );
  544. // We'll drop the error code from the modify recipients call
  545. // The address list has the entries with the PR_RESPONSIBILITY set, so the
  546. // spooler will know if it has to generate NDR reports.
  547. hResult = m_pSupObj->StatusRecips( pMsgObj, pAdrListFailed );
  548. if (!HR_FAILED(hResult)) {
  549. // If we were successful, we should null out the pointer becase MAPI released
  550. // the memory for this structure. And we should not try to release it
  551. // again in the cleanup code.
  552. pAdrListFailed = NULL;
  553. }
  554. }
  555. ErrorExit:
  556. // Release the table, we're finished with it
  557. if (pTable) {
  558. pTable->Release();
  559. }
  560. // Release the spooler's message if needed to
  561. if (pMsgObj) {
  562. pMsgObj->Release ();
  563. }
  564. if (pRecipRows) {
  565. FreeProws( pRecipRows );
  566. }
  567. if (pMsgProps) {
  568. MemFree( pMsgProps );
  569. }
  570. if (lpstmT) {
  571. lpstmT->Release();
  572. }
  573. // In case there is a warning or error floating around, don't let it escape to the spooler.
  574. if (FAILED(hResult)) {
  575. // We default to MAPI_E_NOT_ME so that the spooler would attempt handle
  576. // the message to other transport (currently running in this profile)
  577. // that handle the same address type as ours.
  578. hResult = MAPI_E_NOT_ME;
  579. } else {
  580. hResult = S_OK;
  581. }
  582. return hResult;
  583. }
  584. STDMETHODIMP
  585. CXPLogon::GrowAddressList(
  586. LPADRLIST *ppAdrList,
  587. ULONG ulResizeBy,
  588. ULONG *pulOldAndNewCount
  589. )
  590. /*++
  591. Routine Description:
  592. In this function, given an address list with pulOldAndNewCount of
  593. entries, we resize the address list to hold the old number of
  594. entries plus the ulResizeBy entries. The old address list contents
  595. are copied to the new list and the count reset. The memory for the
  596. old address list is released here.
  597. Arguments:
  598. ppAdrList - Pointer to an address where the old address list
  599. is and where the new resized address list will
  600. be returned
  601. ulResizeBy - Number of new address entries to add to the list
  602. pulOldAndNewCount - Number of entries in the old address list. In
  603. this parameter, upon sucessful return, will have
  604. the number of in the new address list
  605. Return Value:
  606. An HRESULT.
  607. --*/
  608. {
  609. LPADRLIST pNewAdrList;
  610. // Calculate how big the new buffer for the expanded address list should be
  611. ULONG cbSize = CbNewADRLIST ((*pulOldAndNewCount) + ulResizeBy);
  612. // Allocate the memory for it
  613. HRESULT hResult = gpfnAllocateBuffer (cbSize, (LPVOID *)&pNewAdrList);
  614. if (hResult) {
  615. // We can't continue
  616. return hResult;
  617. }
  618. // Zero-out all memory for neatness
  619. ZeroMemory (pNewAdrList, cbSize);
  620. // If we had entries in the old address list, copy the memory from
  621. // the old addres list into the new expanded list
  622. if ((*pulOldAndNewCount)) {
  623. CopyMemory( pNewAdrList, *ppAdrList, CbNewADRLIST ((*pulOldAndNewCount)) );
  624. }
  625. // Set the number of entries in the new address list to the OLD size
  626. pNewAdrList->cEntries = (*pulOldAndNewCount);
  627. // We must return the number of available entries in the new expanded address list
  628. (*pulOldAndNewCount) += ulResizeBy;
  629. // Free the old memory and put the new pointer in place
  630. gpfnFreeBuffer (*ppAdrList);
  631. *ppAdrList = pNewAdrList;
  632. return hResult;
  633. }
  634. STDMETHODIMP
  635. CXPLogon::EndMessage(
  636. ULONG ulMsgRef,
  637. ULONG *pulFlags
  638. )
  639. /*++
  640. Routine Description:
  641. This method is called by the spooler for each message we're to
  642. deliver. It's the mate to SubmitMessage. We're called here twice
  643. for each deferred message and once for non-deferred (realtime)
  644. messages.
  645. We first check the transport state, and if we're
  646. WAITING for the scheduled delivery time to arrive, we return
  647. END_DONT_RESEND in *pulFlags, which tells the spooler to queue this
  648. message for deferred delivery.
  649. If the state is SENDING, we're getting called here after
  650. a message has been dequeued and delivered. Return 0 in *pulFlags
  651. to tell the spooler the message has been delivered.
  652. Arguments:
  653. Refer to MAPI Documentation on this method.
  654. Return Value:
  655. An HRESULT.
  656. --*/
  657. {
  658. *pulFlags = 0;
  659. return S_OK;
  660. }
  661. STDMETHODIMP
  662. CXPLogon::Poll(
  663. ULONG *pulIncoming
  664. )
  665. /*++
  666. Routine Description:
  667. Stub method. We should not get called here, because we told
  668. the spooler not to call us here.
  669. Arguments:
  670. Refer to MAPI Documentation on this method.
  671. Return Value:
  672. An HRESULT.
  673. --*/
  674. {
  675. return S_OK;
  676. }
  677. STDMETHODIMP
  678. CXPLogon::StartMessage(
  679. ULONG ulFlags,
  680. LPMESSAGE pMsgObj,
  681. ULONG * pulMsgRef
  682. )
  683. /*++
  684. Routine Description:
  685. This method gets called when an incoming message is pending to be
  686. processed.
  687. Arguments:
  688. Refer to MAPI Documentation on this method.
  689. Return Value:
  690. An HRESULT.
  691. --*/
  692. {
  693. return S_OK;
  694. }
  695. STDMETHODIMP
  696. CXPLogon::OpenStatusEntry(
  697. LPCIID pInterface,
  698. ULONG ulFlags,
  699. ULONG * pulObjType,
  700. LPMAPISTATUS * ppEntry
  701. )
  702. /*++
  703. Routine Description:
  704. This method is called to get an IMAPIStatus object for this XPLOGON
  705. session.
  706. Arguments:
  707. Refer to MAPI Documentation on this method.
  708. Return Value:
  709. An HRESULT.
  710. --*/
  711. {
  712. if (MAPI_MODIFY & ulFlags) {
  713. return E_ACCESSDENIED;
  714. }
  715. *pulObjType = MAPI_STATUS;
  716. return S_OK;
  717. }
  718. STDMETHODIMP
  719. CXPLogon::ValidateState(
  720. ULONG ulUIParam,
  721. ULONG ulFlags
  722. )
  723. /*++
  724. Routine Description:
  725. This function gets caller by a client in order to validate the
  726. transport logon properties. This function open the profile with the
  727. most up-to-date properties and then compares them to what the transport
  728. has stored internally.
  729. Arguments:
  730. Refer to MAPI Documentation on this method.
  731. Return Value:
  732. An HRESULT.
  733. --*/
  734. {
  735. return S_OK;
  736. }
  737. STDMETHODIMP
  738. CXPLogon::FlushQueues(
  739. ULONG ulUIParam,
  740. ULONG cbTargetTransport,
  741. LPENTRYID pTargetTransport,
  742. ULONG ulFlags
  743. )
  744. /*++
  745. Routine Description:
  746. Called by the MAPI spooler when, upon request of the client or
  747. ourselves, we need to flush the inbound or outbound queue.
  748. Here we make connections to the server to download messages, refresh
  749. the remote message headers, and request the spooler to send us any
  750. deferred messages.
  751. Transport connecting only in FlushQueues() allow the MAPI spooler to
  752. better manage contention of multiple transport accessing common
  753. communication resources (such as COM ports) and let the spooler give us
  754. messages to process when is best for the overall subsystem.
  755. Arguments:
  756. Refer to MAPI Documentation on this method.
  757. Return Value:
  758. An HRESULT.
  759. --*/
  760. {
  761. return S_OK;
  762. }
  763. void WINAPI
  764. CXPLogon::CheckSpoolerYield(
  765. BOOL fReset
  766. )
  767. /*++
  768. Routine Description:
  769. Enforce the 0.2 second rule for transport that need to yield to the
  770. MAPI spooler. Called periodically while processing a message to
  771. determine if we have used more than 0.2 seconds. If so, then call
  772. SpoolerYield(), else just continue.
  773. This is called with fReset set to TRUE when we first enter one
  774. of the Transport Logon methods (usually one that is known to
  775. take a long time like StartMessage() or SubmitMessage(). )
  776. Arguments:
  777. Refer to MAPI Documentation on this method.
  778. Return Value:
  779. An HRESULT.
  780. --*/
  781. {
  782. DWORD dwStop;
  783. static DWORD dwStart;
  784. if (fReset)
  785. {
  786. dwStart = GetTickCount();
  787. }
  788. else
  789. {
  790. dwStop = GetTickCount();
  791. if ((dwStop - dwStart) > 200) // 200 milliseconds
  792. {
  793. m_pSupObj->SpoolerYield (0);
  794. dwStart = GetTickCount();
  795. }
  796. }
  797. }
  798. STDMETHODIMP_(ULONG)
  799. CXPLogon::AddRef()
  800. /*++
  801. Routine Description:
  802. Arguments:
  803. Refer to MAPI Documentation on this method.
  804. Return Value:
  805. An HRESULT.
  806. --*/
  807. {
  808. ++m_cRef;
  809. return m_cRef;
  810. }
  811. STDMETHODIMP_(ULONG)
  812. CXPLogon::Release()
  813. /*++
  814. Routine Description:
  815. Arguments:
  816. Refer to MAPI Documentation on this method.
  817. Return Value:
  818. An HRESULT.
  819. --*/
  820. {
  821. ULONG ulCount = --m_cRef;
  822. if (!ulCount) {
  823. delete this;
  824. }
  825. return ulCount;
  826. }