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.

1125 lines
28 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. config.cpp
  5. Abstract:
  6. This module contains routines for the fax config dialog.
  7. Author:
  8. Wesley Witt (wesw) 13-Aug-1996
  9. --*/
  10. #define INITGUID
  11. #define USES_IID_IExchExt
  12. #define USES_IID_IExchExtAdvancedCriteria
  13. #define USES_IID_IExchExtAttachedFileEvents
  14. #define USES_IID_IExchExtCommands
  15. #define USES_IID_IExchExtMessageEvents
  16. #define USES_IID_IExchExtPropertySheets
  17. #define USES_IID_IExchExtSessionEvents
  18. #define USES_IID_IExchExtUserEvents
  19. #define USES_IID_IMAPIFolder
  20. #define USES_IID_IProfAdmin
  21. #define USES_IID_IProfSect
  22. #define USES_IID_IMAPISession
  23. #define USES_PS_PUBLIC_STRINGS
  24. #define USES_IID_IDistList
  25. #include "faxext.h"
  26. #include <initguid.h>
  27. HINSTANCE hInstance;
  28. BOOL WINAPI
  29. DllMain(
  30. HINSTANCE hinstDLL,
  31. DWORD fdwReason,
  32. LPVOID lpvReserved
  33. )
  34. {
  35. if (fdwReason == DLL_PROCESS_ATTACH) {
  36. hInstance = hinstDLL;
  37. HeapInitialize( NULL, MapiMemAlloc, MapiMemFree, HEAPINIT_NO_VALIDATION | HEAPINIT_NO_STRINGS );
  38. }
  39. if (fdwReason == DLL_PROCESS_DETACH) {
  40. }
  41. return TRUE;
  42. }
  43. BOOL
  44. VerifyDistributionList(
  45. LPEXCHEXTCALLBACK pmecb,
  46. DWORD EntryIdSize,
  47. LPENTRYID EntryId
  48. )
  49. {
  50. HRESULT hr = S_OK;
  51. LPMAPISESSION Session = NULL;
  52. LPDISTLIST DistList = NULL;
  53. DWORD ObjType = 0;
  54. LPMAPITABLE DistTable = NULL;
  55. LPSRowSet DistRows = NULL;
  56. LPSPropValue Dist = NULL;
  57. DWORD i,j;
  58. BOOL FaxAddress = FALSE;
  59. hr = pmecb->GetSession( &Session, NULL );
  60. if (FAILED(hr)) {
  61. goto exit;
  62. }
  63. hr = Session->OpenEntry(
  64. EntryIdSize,
  65. EntryId,
  66. &IID_IDistList,
  67. MAPI_DEFERRED_ERRORS,
  68. &ObjType,
  69. (LPUNKNOWN *) &DistList
  70. );
  71. if (FAILED(hr)) {
  72. goto exit;
  73. }
  74. hr = DistList->GetContentsTable(
  75. MAPI_DEFERRED_ERRORS,
  76. &DistTable
  77. );
  78. if (FAILED(hr)) {
  79. goto exit;
  80. }
  81. hr = HrQueryAllRows( DistTable, NULL, NULL, NULL, 0, &DistRows );
  82. if (FAILED(hr)) {
  83. goto exit;
  84. }
  85. for (i=0; i<DistRows->cRows; i++) {
  86. Dist = DistRows->aRow[i].lpProps;
  87. for (j=0; j<DistRows->aRow[i].cValues; j++) {
  88. if (Dist[j].ulPropTag == PR_ADDRTYPE) {
  89. if (strcmp( Dist[j].Value.LPSZ, "FAX" ) == 0) {
  90. FaxAddress = TRUE;
  91. }
  92. }
  93. }
  94. }
  95. exit:
  96. if (Session) {
  97. Session->Release();
  98. }
  99. if (DistList) {
  100. DistList->Release();
  101. }
  102. if (DistTable) {
  103. MemFree( DistTable );
  104. }
  105. if (DistRows) {
  106. FreeProws( DistRows );
  107. }
  108. return FaxAddress;
  109. }
  110. HRESULT
  111. EnableMenuAndToolbar(
  112. LPEXCHEXTCALLBACK pmecb,
  113. HWND hwndToolbar,
  114. DWORD CmdId
  115. )
  116. {
  117. HRESULT hr = S_OK;
  118. LPADRLIST AdrList = NULL;
  119. DWORD i,j;
  120. BOOL FaxAddress = FALSE;
  121. HMENU hMenu;
  122. LPENTRYID EntryId = NULL;
  123. DWORD EntryIdSize;
  124. OutputDebugString( TEXT("-----------------------\nEnableMenuAndToolbar called\n") );
  125. hr = pmecb->GetRecipients( &AdrList );
  126. if (FAILED(hr)) {
  127. OutputDebugString( TEXT("GetRecipients failed\n") );
  128. goto exit;
  129. }
  130. if (AdrList) {
  131. for (i=0; i<AdrList->cEntries; i++) {
  132. EntryId = NULL;
  133. for (j=0; j<AdrList->aEntries[i].cValues; j++) {
  134. if (AdrList->aEntries[i].rgPropVals[j].ulPropTag == PR_ENTRYID) {
  135. EntryId = (LPENTRYID) AdrList->aEntries[i].rgPropVals[j].Value.bin.lpb;
  136. EntryIdSize = AdrList->aEntries[i].rgPropVals[j].Value.bin.cb;
  137. } else
  138. if (AdrList->aEntries[i].rgPropVals[j].ulPropTag == PR_ADDRTYPE) {
  139. if (strcmp( AdrList->aEntries[i].rgPropVals[j].Value.LPSZ, "FAX" ) == 0) {
  140. FaxAddress = TRUE;
  141. } else
  142. if ((strcmp( AdrList->aEntries[i].rgPropVals[j].Value.LPSZ, "MAPIPDL" ) == 0) && (EntryId)) {
  143. FaxAddress = VerifyDistributionList( pmecb, EntryIdSize, EntryId );
  144. }
  145. }
  146. }
  147. }
  148. }
  149. hr = pmecb->GetMenu( &hMenu );
  150. if (FaxAddress) {
  151. OutputDebugString( TEXT("Enabling menu\n") );
  152. EnableMenuItem( hMenu, CmdId, MF_BYCOMMAND | MF_ENABLED );
  153. SendMessage( hwndToolbar, TB_ENABLEBUTTON, (WPARAM) CmdId, MAKELONG(TRUE,0) );
  154. } else {
  155. OutputDebugString( TEXT("Disabling menu\n") );
  156. EnableMenuItem( hMenu, CmdId, MF_BYCOMMAND | MF_GRAYED );
  157. SendMessage( hwndToolbar, TB_ENABLEBUTTON, (WPARAM) CmdId, MAKELONG(FALSE,0) );
  158. }
  159. exit:
  160. MemFree( AdrList );
  161. return hr;
  162. }
  163. HRESULT
  164. GetFaxConfig(
  165. LPEXCHEXTCALLBACK pmecb,
  166. PFAXXP_CONFIG FaxConfig
  167. )
  168. {
  169. HRESULT hr = S_OK;
  170. LPMAPISESSION lpSession = NULL;
  171. LPPROFSECT pProfileObj = NULL;
  172. ULONG PropCount = 0;
  173. LPSPropValue pProps = NULL;
  174. LPSERVICEADMIN lpServiceAdmin = NULL;
  175. LPPROVIDERADMIN lpProviderAdmin = NULL;
  176. LPMAPITABLE ptblSvc = NULL;
  177. LPSRowSet pSvcRows = NULL;
  178. LPSPropValue pSvc = NULL;
  179. DWORD i,j;
  180. BOOL FoundIt = FALSE;
  181. LPBYTE FaxXpGuid = NULL;
  182. MAPIUID FaxGuid = FAX_XP_GUID;
  183. hr = pmecb->GetSession( &lpSession, NULL );
  184. if (FAILED(hr)) {
  185. goto exit;
  186. }
  187. hr = lpSession->AdminServices( 0, &lpServiceAdmin );
  188. if (FAILED(hr)) {
  189. goto exit;
  190. }
  191. hr = lpServiceAdmin->GetMsgServiceTable( 0, &ptblSvc );
  192. if (FAILED(hr)) {
  193. goto exit;
  194. }
  195. hr = HrQueryAllRows( ptblSvc, NULL, NULL, NULL, 0, &pSvcRows );
  196. if (FAILED(hr)) {
  197. goto exit;
  198. }
  199. for (i=0; i<pSvcRows->cRows; i++) {
  200. pSvc = pSvcRows->aRow[i].lpProps;
  201. for (j=0; j<pSvcRows->aRow[i].cValues; j++) {
  202. if (pSvc[j].ulPropTag == PR_SERVICE_NAME) {
  203. if (_stricmp( pSvc[j].Value.LPSZ, "MSFAX XP" ) == 0) {
  204. FoundIt = TRUE;
  205. }
  206. }
  207. if (pSvc[j].ulPropTag == PR_SERVICE_UID) {
  208. FaxXpGuid = pSvc[j].Value.bin.lpb;
  209. }
  210. }
  211. if (FoundIt) {
  212. break;
  213. }
  214. }
  215. if (!FoundIt) {
  216. goto exit;
  217. }
  218. hr = lpServiceAdmin->AdminProviders( (LPMAPIUID) FaxXpGuid, 0, &lpProviderAdmin );
  219. if (FAILED(hr)) {
  220. goto exit;
  221. }
  222. hr = lpProviderAdmin->OpenProfileSection(
  223. &FaxGuid,
  224. NULL,
  225. 0,
  226. &pProfileObj
  227. );
  228. if (FAILED(hr)) {
  229. goto exit;
  230. }
  231. hr = pProfileObj->GetProps(
  232. (LPSPropTagArray) &sptFaxProps,
  233. 0,
  234. &PropCount,
  235. &pProps
  236. );
  237. if (FAILED(hr)) {
  238. goto exit;
  239. }
  240. FaxConfig->PrinterName = StringDup( pProps[PROP_FAX_PRINTER_NAME].Value.LPSZ );
  241. FaxConfig->CoverPageName = StringDup( pProps[PROP_COVERPAGE_NAME].Value.LPSZ );
  242. FaxConfig->UseCoverPage = pProps[PROP_USE_COVERPAGE].Value.ul;
  243. FaxConfig->ServerCoverPage = pProps[PROP_SERVER_COVERPAGE].Value.ul;
  244. CopyMemory( &FaxConfig->FontStruct, pProps[PROP_FONT].Value.bin.lpb, pProps[PROP_FONT].Value.bin.cb );
  245. FaxConfig->ServerName = GetServerName(FaxConfig->PrinterName);
  246. FaxConfig->ServerCpOnly = FALSE;
  247. //
  248. // nice idea, but we need to postpone this till we actually open the dialog so
  249. // we don't force the fax service to startup everytime we compose a message.
  250. //
  251. #if 0
  252. HANDLE hFax;
  253. PFAX_CONFIGURATION pFaxConfiguration;
  254. if (FaxConnectFaxServer(FaxConfig->ServerName,&hFax) ){
  255. if (FaxGetConfiguration(hFax,&pFaxConfiguration) ){
  256. FaxConfig->ServerCpOnly = pFaxConfiguration->ServerCp;
  257. FaxFreeBuffer(pFaxConfiguration);
  258. }
  259. FaxClose(hFax);
  260. }
  261. #endif
  262. exit:
  263. if (pSvcRows) {
  264. FreeProws( pSvcRows );
  265. }
  266. if (pProps) {
  267. MAPIFreeBuffer( pProps );
  268. }
  269. if (pProfileObj) {
  270. pProfileObj->Release();
  271. }
  272. if (ptblSvc) {
  273. ptblSvc->Release();
  274. }
  275. if (lpProviderAdmin) {
  276. lpProviderAdmin->Release();
  277. }
  278. if (lpServiceAdmin) {
  279. lpServiceAdmin->Release();
  280. }
  281. if (lpSession) {
  282. lpSession->Release();
  283. }
  284. return hr;
  285. }
  286. ///////////////////////////////////////////////////////////////////////////////
  287. // FUNCTION: ExchEntryPoint
  288. //
  289. // Parameters - none
  290. //
  291. // Purpose
  292. // The entry point which Exchange calls.
  293. //
  294. // Return Value
  295. // Pointer to Exchange Extension Object
  296. //
  297. // Comments
  298. // This is called for each context entry. Create a new MyExchExt object
  299. // every time so each context will get its own MyExchExt interface.
  300. //
  301. LPEXCHEXT CALLBACK ExchEntryPoint(void)
  302. {
  303. LPEXCHEXT pExt;
  304. __try {
  305. pExt = new MyExchExt;
  306. } __except (EXCEPTION_EXECUTE_HANDLER) {
  307. pExt = NULL;
  308. }
  309. return pExt;
  310. }
  311. ///////////////////////////////////////////////////////////////////////////////
  312. // MyExchExt::MyExchExt()
  313. //
  314. // Parameters - none
  315. //
  316. // Purpose
  317. // Constructor. Initialize members and create supporting interface objects
  318. //
  319. // Comments
  320. // Each context of Exchange gets its own set of interface objects.
  321. // Furthermore, interface objects per context are kept track of by Exchange
  322. // and the interface methods are called in the proper context.
  323. //
  324. MyExchExt::MyExchExt ()
  325. {
  326. m_cRef = 1;
  327. m_context = 0;
  328. m_pExchExtCommands = new MyExchExtCommands;
  329. m_pExchExtUserEvents = new MyExchExtUserEvents;
  330. // in MyExchExtUserEvents methods I need a reference to MyExchExt
  331. m_pExchExtUserEvents->SetIExchExt( this );
  332. }
  333. ///////////////////////////////////////////////////////////////////////////////
  334. // IExchExt virtual member functions implementation
  335. //
  336. ///////////////////////////////////////////////////////////////////////////////
  337. // MyExchExt::QueryInterface()
  338. //
  339. // Parameters
  340. // riid -- Interface ID.
  341. // ppvObj -- address of interface object pointer.
  342. //
  343. // Purpose
  344. // Called by Exchage to request for interfaces
  345. //
  346. // Return Value
  347. // S_OK -- interface is supported and returned in ppvObj pointer
  348. // E_NOINTERFACE -- interface is not supported and ppvObj is NULL
  349. //
  350. // Comments
  351. // Exchange client calls QueryInterface for each object. Only
  352. // Need to support objects that apply to the extension. QueryInterface
  353. // is called onces for each IID for each context. We support two
  354. // contexts in this example so QueryInterface is called twice for
  355. // each IID.
  356. //
  357. STDMETHODIMP
  358. MyExchExt::QueryInterface(
  359. REFIID riid,
  360. LPVOID * ppvObj
  361. )
  362. {
  363. HRESULT hr = S_OK;
  364. *ppvObj = NULL;
  365. if ( (IID_IUnknown == riid) || (IID_IExchExt == riid) ) {
  366. *ppvObj = (LPUNKNOWN) this;
  367. } else if ( IID_IExchExtCommands == riid) {
  368. if (!m_pExchExtCommands) {
  369. hr = E_UNEXPECTED;
  370. } else {
  371. *ppvObj = (LPUNKNOWN)m_pExchExtCommands;
  372. m_pExchExtCommands->SetContext( m_context );
  373. }
  374. } else if ( IID_IExchExtUserEvents == riid) {
  375. *ppvObj = (LPUNKNOWN)m_pExchExtUserEvents;
  376. m_pExchExtUserEvents->SetContext( m_context );
  377. } else {
  378. hr = E_NOINTERFACE;
  379. }
  380. if (NULL != *ppvObj) {
  381. ((LPUNKNOWN)*ppvObj)->AddRef();
  382. }
  383. return hr;
  384. }
  385. ///////////////////////////////////////////////////////////////////////////////
  386. // MyExchExt::Install()
  387. //
  388. // Parameters
  389. // peecb -- pointer to Exchange Extension callback function
  390. // eecontext -- context code at time of being called.
  391. // ulFlags -- flag to say if install is for modal or not
  392. //
  393. // Purpose
  394. // Called once for each new contexted that is entered. Proper version
  395. // number is checked here.
  396. //
  397. // Return Value
  398. // S_OK -- object supported in the requested context
  399. // S_FALSE -- object is not supported in teh requested context
  400. //
  401. // Comments
  402. //
  403. STDMETHODIMP
  404. MyExchExt::Install(
  405. LPEXCHEXTCALLBACK pmecb,
  406. ULONG mecontext,
  407. ULONG ulFlags
  408. )
  409. {
  410. ULONG ulBuildVersion;
  411. HRESULT hr;
  412. m_context = mecontext;
  413. // make sure this is the right version
  414. pmecb->GetVersion( &ulBuildVersion, EECBGV_GETBUILDVERSION );
  415. if (EECBGV_BUILDVERSION_MAJOR != (ulBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK)) {
  416. return S_FALSE;
  417. }
  418. switch (mecontext) {
  419. case EECONTEXT_SENDNOTEMESSAGE:
  420. hr = S_OK;
  421. break;
  422. default:
  423. hr = S_FALSE;
  424. break;
  425. }
  426. return hr;
  427. }
  428. MyExchExtCommands::MyExchExtCommands()
  429. {
  430. m_cRef = 0;
  431. m_context = 0;
  432. m_cmdid = 0;
  433. m_itbb = 0;
  434. m_itbm = 0;
  435. m_hWnd = 0;
  436. m_hwndToolbar = NULL;
  437. memset(&FaxConfig,0,sizeof(FaxConfig));
  438. }
  439. MyExchExtCommands::~MyExchExtCommands()
  440. {
  441. MemFree( FaxConfig.PrinterName );
  442. MemFree( FaxConfig.CoverPageName );
  443. }
  444. ///////////////////////////////////////////////////////////////////////////////
  445. // MyExchExtCommands::QueryInterface()
  446. //
  447. // Parameters
  448. // riid -- Interface ID.
  449. // ppvObj -- address of interface object pointer.
  450. //
  451. // Purpose
  452. // Exchange Client does not call IExchExtCommands::QueryInterface().
  453. // So return nothing.
  454. //
  455. // Return Value - none
  456. //
  457. STDMETHODIMP
  458. MyExchExtCommands::QueryInterface(
  459. REFIID riid,
  460. LPVOID FAR * ppvObj
  461. )
  462. {
  463. *ppvObj = NULL;
  464. if ( (riid == IID_IExchExtCommands) || (riid == IID_IUnknown) ) {
  465. *ppvObj = (LPVOID)this;
  466. // Increase usage count of this object
  467. AddRef();
  468. return S_OK;
  469. }
  470. return E_NOINTERFACE;
  471. }
  472. ///////////////////////////////////////////////////////////////////////////////
  473. // MyExchExtCommands::InstallCommands()
  474. //
  475. // Parameters
  476. // pmecb -- Exchange Callback Interface
  477. // hWnd -- window handle to main window of context
  478. // hMenu -- menu handle to main menu of context
  479. // lptbeArray -- array of toolbar button entries
  480. // ctbe -- count of button entries in array
  481. // ulFlags -- reserved
  482. //
  483. // Purpose
  484. // This function is called when commands are installed for each context
  485. // the extension services.
  486. //
  487. // Return Value
  488. // S_FALSE means the commands have been handled.
  489. //
  490. // Comments
  491. // The hWnd and hMenu are in context. If the context is for the SENDNOTE
  492. // dialog, then the hWnd is the window handle to the dialog and the hMenu is
  493. // the main menu of the dialog.
  494. //
  495. // Call ResetToolbar so that Exchange will show it's toolbar
  496. //
  497. STDMETHODIMP
  498. MyExchExtCommands::InstallCommands(
  499. LPEXCHEXTCALLBACK pmecb,
  500. HWND hWnd,
  501. HMENU hMenu,
  502. UINT FAR * pcmdidBase,
  503. LPTBENTRY lptbeArray,
  504. UINT ctbe,
  505. ULONG ulFlags
  506. )
  507. {
  508. HRESULT hr = S_FALSE;
  509. TCHAR MenuItem[64];
  510. if (m_context == EECONTEXT_SENDNOTEMESSAGE) {
  511. int tbindx;
  512. HMENU hMenu;
  513. pmecb->GetMenuPos( EECMDID_ToolsCustomizeToolbar, &hMenu, NULL, NULL, 0 );
  514. AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
  515. LoadString( hInstance, IDS_FAX_ATTRIBUTES_MENU, MenuItem, 64);
  516. AppendMenu( hMenu, MF_BYPOSITION | MF_STRING, *pcmdidBase, MenuItem );
  517. m_hWnd = hWnd;
  518. m_cmdid = *pcmdidBase;
  519. (*pcmdidBase)++;
  520. for (tbindx = ctbe-1; (int) tbindx > -1; --tbindx) {
  521. if (lptbeArray[tbindx].tbid == EETBID_STANDARD) {
  522. m_hwndToolbar = lptbeArray[tbindx].hwnd;
  523. m_itbb = lptbeArray[tbindx].itbbBase++;
  524. break;
  525. }
  526. }
  527. if (m_hwndToolbar) {
  528. TBADDBITMAP tbab;
  529. tbab.hInst = hInstance;
  530. tbab.nID = IDB_EXTBTN;
  531. m_itbm = (INT)SendMessage( m_hwndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab );
  532. // EnableMenuAndToolbar( pmecb, m_hwndToolbar, m_cmdid );
  533. ResetToolbar( EETBID_STANDARD, 0 );
  534. }
  535. GetFaxConfig( pmecb, &FaxConfig );
  536. }
  537. return hr;
  538. }
  539. ///////////////////////////////////////////////////////////////////////////////
  540. // MyExchExtCommands::DoCommand()
  541. //
  542. // Parameters
  543. // pmecb -- pointer to Exchange Callback Interface
  544. //
  545. // Purpose7
  546. // This method is called by Exchange for each WM_COMMAND is sent to the
  547. // window in context.
  548. //
  549. // Return Value
  550. // S_OK if command is handled
  551. // S_FALSE if command is not handled
  552. //
  553. // Comments
  554. // Use this function to either respond to the command item (menu or toolbar)
  555. // added or modify an existing command in Exchange. Return S_OK to let
  556. // Exchange know the command was handled. Return S_OK on commands you are
  557. // taking over from Exchange. Return S_FALSE to let Exchange know you want
  558. // it to carry out its command, even if you modify its action.
  559. //
  560. STDMETHODIMP
  561. MyExchExtCommands::DoCommand(
  562. LPEXCHEXTCALLBACK pmecb,
  563. UINT cmdid
  564. )
  565. {
  566. HRESULT hr = S_OK;
  567. HWND hwnd = NULL;
  568. INT_PTR Rslt;
  569. LPMESSAGE pMessage = NULL;
  570. LPMDB pMDB = NULL;
  571. LPSPropProblemArray lpProblems = NULL;
  572. SPropValue MsgProps[4];
  573. LPSPropTagArray MsgPropTags = NULL;
  574. MAPINAMEID NameIds[NUM_FAX_MSG_PROPS];
  575. MAPINAMEID *pNameIds[NUM_FAX_MSG_PROPS] = {&NameIds[0], &NameIds[1], &NameIds[2], &NameIds[3]};
  576. LPADRLIST AdrList = NULL;
  577. DWORD i,j;
  578. BOOL FaxAddress = FALSE;
  579. LPENTRYID EntryId = NULL;
  580. DWORD EntryIdSize;
  581. if (m_cmdid != cmdid) {
  582. return S_FALSE;
  583. }
  584. hr = pmecb->GetRecipients( &AdrList );
  585. if (FAILED(hr)) {
  586. goto exit;
  587. }
  588. if (AdrList) {
  589. for (i=0; i<AdrList->cEntries; i++) {
  590. EntryId = NULL;
  591. for (j=0; j<AdrList->aEntries[i].cValues; j++) {
  592. if (AdrList->aEntries[i].rgPropVals[j].ulPropTag == PR_ENTRYID) {
  593. EntryId = (LPENTRYID) AdrList->aEntries[i].rgPropVals[j].Value.bin.lpb;
  594. EntryIdSize = AdrList->aEntries[i].rgPropVals[j].Value.bin.cb;
  595. } else
  596. if (AdrList->aEntries[i].rgPropVals[j].ulPropTag == PR_ADDRTYPE) {
  597. if (strcmp( AdrList->aEntries[i].rgPropVals[j].Value.LPSZ, "FAX" ) == 0) {
  598. FaxAddress = TRUE;
  599. } else
  600. if ((strcmp( AdrList->aEntries[i].rgPropVals[j].Value.LPSZ, "MAPIPDL" ) == 0) && (EntryId)) {
  601. FaxAddress = VerifyDistributionList( pmecb, EntryIdSize, EntryId );
  602. }
  603. }
  604. }
  605. }
  606. }
  607. hr = pmecb->GetWindow( &hwnd );
  608. if (FAILED(hr)) {
  609. goto exit;
  610. }
  611. if (!FaxAddress) {
  612. TCHAR CaptionString[1024];
  613. TCHAR MessageString[1024];
  614. LoadString( hInstance, IDS_MSGBOXCAPTION, &CaptionString[0], 1024 );
  615. LoadString( hInstance, IDS_NOFAXADDR, &MessageString[0], 1024 );
  616. Rslt = MessageBox( hwnd, MessageString, CaptionString, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL );
  617. goto exit;
  618. }
  619. Rslt = DialogBoxParam(
  620. hInstance,
  621. MAKEINTRESOURCE(FAX_CONFIG_DIALOG),
  622. hwnd,
  623. ConfigDlgProc,
  624. (LPARAM) &FaxConfig
  625. );
  626. if (Rslt == IDOK) {
  627. hr = pmecb->GetObject( &pMDB, (LPMAPIPROP *) &pMessage );
  628. if (FAILED(hr)) {
  629. goto exit;
  630. }
  631. NameIds[MSGPI_FAX_PRINTER_NAME].lpguid = (LPGUID)&PS_PUBLIC_STRINGS;
  632. NameIds[MSGPI_FAX_PRINTER_NAME].ulKind = MNID_STRING;
  633. NameIds[MSGPI_FAX_PRINTER_NAME].Kind.lpwstrName = MSGPS_FAX_PRINTER_NAME;
  634. NameIds[MSGPI_FAX_COVERPAGE_NAME].lpguid = (LPGUID)&PS_PUBLIC_STRINGS;
  635. NameIds[MSGPI_FAX_COVERPAGE_NAME].ulKind = MNID_STRING;
  636. NameIds[MSGPI_FAX_COVERPAGE_NAME].Kind.lpwstrName = MSGPS_FAX_COVERPAGE_NAME;
  637. NameIds[MSGPI_FAX_USE_COVERPAGE].lpguid = (LPGUID)&PS_PUBLIC_STRINGS;
  638. NameIds[MSGPI_FAX_USE_COVERPAGE].ulKind = MNID_STRING;
  639. NameIds[MSGPI_FAX_USE_COVERPAGE].Kind.lpwstrName = MSGPS_FAX_USE_COVERPAGE;
  640. NameIds[MSGPI_FAX_SERVER_COVERPAGE].lpguid = (LPGUID)&PS_PUBLIC_STRINGS;
  641. NameIds[MSGPI_FAX_SERVER_COVERPAGE].ulKind = MNID_STRING;
  642. NameIds[MSGPI_FAX_SERVER_COVERPAGE].Kind.lpwstrName = MSGPS_FAX_SERVER_COVERPAGE;
  643. hr = pMessage->GetIDsFromNames( NUM_FAX_MSG_PROPS, pNameIds, MAPI_CREATE, &MsgPropTags );
  644. if (FAILED(hr)) {
  645. goto exit;
  646. }
  647. MsgPropTags->aulPropTag[MSGPI_FAX_PRINTER_NAME] = PROP_TAG( PT_TSTRING, PROP_ID(MsgPropTags->aulPropTag[MSGPI_FAX_PRINTER_NAME]) );
  648. MsgPropTags->aulPropTag[MSGPI_FAX_COVERPAGE_NAME] = PROP_TAG( PT_TSTRING, PROP_ID(MsgPropTags->aulPropTag[MSGPI_FAX_COVERPAGE_NAME]) );
  649. MsgPropTags->aulPropTag[MSGPI_FAX_USE_COVERPAGE] = PROP_TAG( PT_LONG, PROP_ID(MsgPropTags->aulPropTag[MSGPI_FAX_USE_COVERPAGE]) );
  650. MsgPropTags->aulPropTag[MSGPI_FAX_SERVER_COVERPAGE] = PROP_TAG( PT_LONG, PROP_ID(MsgPropTags->aulPropTag[MSGPI_FAX_SERVER_COVERPAGE]) );
  651. MsgProps[MSGPI_FAX_PRINTER_NAME].ulPropTag = MsgPropTags->aulPropTag[MSGPI_FAX_PRINTER_NAME];
  652. MsgProps[MSGPI_FAX_COVERPAGE_NAME].ulPropTag = MsgPropTags->aulPropTag[MSGPI_FAX_COVERPAGE_NAME];
  653. MsgProps[MSGPI_FAX_USE_COVERPAGE].ulPropTag = MsgPropTags->aulPropTag[MSGPI_FAX_USE_COVERPAGE];
  654. MsgProps[MSGPI_FAX_SERVER_COVERPAGE].ulPropTag = MsgPropTags->aulPropTag[MSGPI_FAX_SERVER_COVERPAGE];
  655. MsgProps[MSGPI_FAX_PRINTER_NAME].Value.LPSZ = FaxConfig.PrinterName;
  656. MsgProps[MSGPI_FAX_COVERPAGE_NAME].Value.LPSZ = FaxConfig.CoverPageName;
  657. MsgProps[MSGPI_FAX_USE_COVERPAGE].Value.ul = FaxConfig.UseCoverPage;
  658. MsgProps[MSGPI_FAX_SERVER_COVERPAGE].Value.ul = FaxConfig.ServerCoverPage;
  659. hr = pMessage->SetProps( NUM_FAX_MSG_PROPS, MsgProps, &lpProblems );
  660. if (FAILED(hr)) {
  661. goto exit;
  662. }
  663. if (lpProblems) {
  664. hr = MAPI_E_NOT_FOUND;
  665. goto exit;
  666. }
  667. }
  668. exit:
  669. if (AdrList) {
  670. MemFree( AdrList );
  671. }
  672. if (MsgPropTags) {
  673. MemFree( MsgPropTags );
  674. }
  675. if (lpProblems) {
  676. MemFree( lpProblems );
  677. }
  678. if (pMessage) {
  679. pMessage->Release();
  680. }
  681. return hr;
  682. }
  683. ///////////////////////////////////////////////////////////////////////////////
  684. // MyExchExtCommands::InitMenu()
  685. //
  686. // Parameters
  687. // pmecb -- pointer to Exchange Callback Interface
  688. //
  689. // Purpose
  690. // This method is called by Exchange when the menu of context is about to
  691. // be activated. See WM_INITMENU in the Windows API Reference for more
  692. // information.
  693. //
  694. // Return Value - none
  695. //
  696. STDMETHODIMP_(VOID)
  697. MyExchExtCommands::InitMenu(
  698. LPEXCHEXTCALLBACK pmecb
  699. )
  700. {
  701. return;
  702. }
  703. ///////////////////////////////////////////////////////////////////////////////
  704. // MyExchExtCommands::Help()
  705. //
  706. // Parameters
  707. // pmecb -- pointer to Exchange Callback Interface
  708. // cmdid -- command id
  709. //
  710. // Purpose
  711. // Respond when user presses F1 while custom menu item is selected.
  712. //
  713. // Return Value
  714. // S_OK -- recognized the command and provided help
  715. // S_FALSE -- not our command and we didn't provide help
  716. //
  717. STDMETHODIMP MyExchExtCommands::Help(
  718. LPEXCHEXTCALLBACK pmecb,
  719. UINT cmdid
  720. )
  721. {
  722. return S_FALSE;
  723. }
  724. ///////////////////////////////////////////////////////////////////////////////
  725. // MyExchExtCommands::QueryHelpText()
  726. //
  727. // Parameters
  728. // cmdid -- command id corresponding to menu item activated
  729. // ulFlags -- identifies either EECQHT_STATUS or EECQHT_TOOLTIP
  730. // psz -- pointer to buffer to be populated with text to display
  731. // cch -- count of characters available in psz buffer
  732. //
  733. // Purpose
  734. // Exchange calls this function each time it requires to update the status
  735. // bar text or if it is to display a tooltip on the toolbar.
  736. //
  737. // Return Value
  738. // S_OK to indicate our command was handled
  739. // S_FALSE to tell Exchange it can continue with its function
  740. //
  741. STDMETHODIMP
  742. MyExchExtCommands::QueryHelpText(
  743. UINT cmdid,
  744. ULONG ulFlags,
  745. LPTSTR psz,
  746. UINT cch
  747. )
  748. {
  749. HRESULT hr;
  750. TCHAR HelpText[64];
  751. LoadString(hInstance,IDS_FAX_ATTRIBUTES_TOOLTIP,HelpText,64);
  752. if (cmdid == m_cmdid) {
  753. if (ulFlags == EECQHT_STATUS) {
  754. lstrcpyn( psz, HelpText, cch );
  755. }
  756. if (ulFlags == EECQHT_TOOLTIP) {
  757. lstrcpyn( psz, HelpText, cch );
  758. }
  759. hr = S_OK;
  760. } else {
  761. hr = S_FALSE;
  762. }
  763. return hr;
  764. }
  765. ///////////////////////////////////////////////////////////////////////////////
  766. // MyExchExtCommands::QueryButtonInfo()
  767. //
  768. // Parameters
  769. // tbid -- toolbar identifier
  770. // itbb -- toolbar button index
  771. // ptbb -- pointer to toolbar button structure -- see TBBUTTON structure
  772. // lpsz -- point to string describing button
  773. // cch -- maximum size of lpsz buffer
  774. // ulFlags -- EXCHEXT_UNICODE may be specified
  775. //
  776. // Purpose
  777. // For Exchange to find out about toolbar button information.
  778. //
  779. // Return Value
  780. // S_FALSE - not our button
  781. // S_OK - we filled information about our button
  782. //
  783. // Comments
  784. // Called for every button installed for toolbars when IExchExtCommands
  785. // is installed for each context. The lpsz text is used when the Customize
  786. // Toolbar dialog is displayed. The text will be displayed next to the
  787. // button.
  788. //
  789. STDMETHODIMP MyExchExtCommands::QueryButtonInfo(
  790. ULONG tbid,
  791. UINT itbb,
  792. LPTBBUTTON ptbb,
  793. LPTSTR lpsz,
  794. UINT cch,
  795. ULONG ulFlags
  796. )
  797. {
  798. HRESULT hr = S_FALSE;
  799. TCHAR CustText[64];
  800. LoadString(hInstance,IDS_FAX_ATTRIBUTES_CUST,CustText,64);
  801. if (m_itbb == itbb) {
  802. ptbb->iBitmap = m_itbm;
  803. ptbb->idCommand = m_cmdid;
  804. ptbb->fsState = TBSTATE_ENABLED;
  805. ptbb->fsStyle = TBSTYLE_BUTTON;
  806. ptbb->dwData = 0;
  807. ptbb->iString = -1;
  808. lstrcpyn( lpsz, CustText , cch );
  809. hr = S_OK;
  810. }
  811. return hr;
  812. }
  813. ///////////////////////////////////////////////////////////////////////////////
  814. // MyExchExtCommands::ResetToolbar()
  815. //
  816. // Parameters
  817. // tbid
  818. // ulFlags
  819. //
  820. // Purpose
  821. //
  822. // Return Value S_OK always
  823. //
  824. STDMETHODIMP
  825. MyExchExtCommands::ResetToolbar(
  826. ULONG tbid,
  827. ULONG ulFlags
  828. )
  829. {
  830. return S_OK;
  831. }
  832. ///////////////////////////////////////////////////////////////////////////////
  833. // IExchExtUserEvents virtual member functions implementation
  834. //
  835. ///////////////////////////////////////////////////////////////////////////////
  836. // MyExchExtUserEvents::QueryInterface()
  837. //
  838. // Parameters
  839. // riid -- Interface ID.
  840. // ppvObj -- address of interface object pointer.
  841. //
  842. // Purpose
  843. // Exchange Client does not call IExchExtUserEvents::QueryInterface().
  844. // So return nothing.
  845. //
  846. // Return Value - none
  847. //
  848. STDMETHODIMP
  849. MyExchExtUserEvents::QueryInterface(
  850. REFIID riid,
  851. LPVOID FAR * ppvObj
  852. )
  853. {
  854. *ppvObj = NULL;
  855. if (( riid == IID_IExchExtUserEvents) || (riid == IID_IUnknown) ) {
  856. *ppvObj = (LPVOID)this;
  857. // Increase usage count of this object
  858. AddRef();
  859. return S_OK;
  860. }
  861. return E_NOINTERFACE;
  862. }
  863. ///////////////////////////////////////////////////////////////////////////////
  864. // MyExchExtUserEvents::OnSelectionChange()
  865. //
  866. // Parameters
  867. // pmecb -- pointer to Exchange Callback Object
  868. //
  869. //
  870. // Purpose
  871. // This function is called when the selection in the UI is changed.
  872. //
  873. // Return Value - none
  874. //
  875. // Comments
  876. // OnSelectionChange is called whenever the selection changes either within
  877. // a pane or is changed between panes.
  878. //
  879. STDMETHODIMP_(VOID)
  880. MyExchExtUserEvents::OnSelectionChange(
  881. LPEXCHEXTCALLBACK pmecb
  882. )
  883. {
  884. }
  885. ///////////////////////////////////////////////////////////////////////////////
  886. // MyExchExtUserEvents::OnObjectChange()
  887. //
  888. // Parameters
  889. // pmecb -- pointer to Exchange Callback Object
  890. //
  891. //
  892. // Purpose
  893. // This function is called when the selection in the UI is to a different
  894. // of object on the left pane.
  895. //
  896. // Return Value - none
  897. //
  898. // Comments
  899. // OnObjectChange is called whenever the selection is changed between
  900. // objects in the left pane only. Change in selection between folders,
  901. // subfolders or container object in the left pane will be reflected with a
  902. // call to OnObjectChange. Change in selection between objects (messages,
  903. // subfolders) in the right pane will not call OnObjectChange, only
  904. // OnSelectionChange.
  905. //
  906. STDMETHODIMP_(VOID)
  907. MyExchExtUserEvents::OnObjectChange(
  908. LPEXCHEXTCALLBACK pmecb
  909. )
  910. {
  911. }
  912. LPSTR
  913. GetServerName(
  914. LPSTR PrinterName
  915. )
  916. /*++
  917. Routine Description:
  918. retrieve the servername given a printer name
  919. Arguments:
  920. PrinterName - Identifies the printer in question
  921. Return Value:
  922. Pointer to a string, NULL if there is an error
  923. --*/
  924. {
  925. PPRINTER_INFO_2 PrinterInfo = NULL;
  926. LPSTR ServerName = NULL;
  927. if (!PrinterName) {
  928. goto exit;
  929. }
  930. if (!(PrinterInfo = (PPRINTER_INFO_2) MyGetPrinter(PrinterName,2))) {
  931. goto exit;
  932. }
  933. if (PrinterInfo->pServerName) {
  934. ServerName = StringDup(PrinterInfo->pServerName);
  935. }
  936. exit:
  937. if (PrinterInfo) {
  938. MemFree(PrinterInfo);
  939. }
  940. return ServerName;
  941. }