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.

778 lines
16 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. cmapiabobj.cpp
  5. Abstract:
  6. Interface to the MAPI address book.
  7. Environment:
  8. Fax send wizard
  9. Revision History:
  10. --*/
  11. #include <windows.h>
  12. #include <prsht.h>
  13. #include <tchar.h>
  14. #include <mapiwin.h>
  15. #include <mapix.h>
  16. #include <mapiutil.h>
  17. #include <mapi.h>
  18. #include "faxui.h"
  19. #include "mapiabobj.h"
  20. #include <mapitags.h>
  21. #include "edkmdb.h"
  22. #define STRSAFE_NO_DEPRECATE
  23. #include <strsafe.h>
  24. // initialize static variables
  25. HINSTANCE CMAPIabObj::m_hInstMapi = NULL;
  26. LPMAPISESSION CMAPIabObj::m_lpMapiSession = NULL;
  27. LPMAPILOGONEX CMAPIabObj::m_lpfnMAPILogonEx = NULL;
  28. LPMAPILOGOFF CMAPIabObj::m_lpfnMAPILogoff = NULL;
  29. LPMAPIADDRESS CMAPIabObj::m_lpfnMAPIAddress = NULL;
  30. LPMAPIFREEBUFFER CMAPIabObj::m_lpfnMAPIFreeBuffer = NULL;
  31. LPMAPIINITIALIZE CMAPIabObj::m_lpfnMAPIInitialize = NULL;
  32. LPMAPIUNINITIALIZE CMAPIabObj::m_lpfnMAPIUninitialize = NULL;
  33. LPMAPIALLOCATEBUFFER CMAPIabObj::m_lpfnMAPIAllocateBuffer = NULL;
  34. LPMAPIALLOCATEMORE CMAPIabObj::m_lpfnMAPIAllocateMore = NULL;
  35. LPMAPIADMINPROFILES CMAPIabObj::m_lpfnMAPIAdminProfiles = NULL;
  36. LPHrQueryAllRows CMAPIabObj::m_lpfnHrQueryAllRows = NULL;
  37. BOOL CMAPIabObj::m_Initialized = FALSE;
  38. CMAPIabObj::CMAPIabObj(
  39. HINSTANCE hInstance,
  40. HWND hDlg
  41. ) : CCommonAbObj(hInstance)
  42. /*++
  43. Routine Description:
  44. Constructor for CMAPIabObj class
  45. Arguments:
  46. hInstance - Instance handle
  47. Return Value:
  48. NONE
  49. --*/
  50. {
  51. m_Initialized = InitMapiService(hDlg);
  52. }
  53. VOID
  54. CMAPIabObj::FreeProws(
  55. LPSRowSet prows
  56. )
  57. /*++
  58. Routine Description:
  59. Destroy SRowSet structure. Copied from MAPI.
  60. Arguments:
  61. hFile - Pointer to SRowSet
  62. Return value:
  63. NONE
  64. --*/
  65. {
  66. ULONG irow;
  67. if (!prows) {
  68. return;
  69. }
  70. for (irow = 0; irow < prows->cRows; ++irow) {
  71. m_lpfnMAPIFreeBuffer(prows->aRow[irow].lpProps);
  72. }
  73. m_lpfnMAPIFreeBuffer( prows );
  74. }
  75. BOOL
  76. CMAPIabObj::GetDefaultMapiProfile(
  77. OUT LPSTR ProfileName,
  78. IN UINT cchProfileName
  79. )
  80. {
  81. BOOL rVal = FALSE;
  82. LPMAPITABLE pmt = NULL;
  83. LPSRowSet prws = NULL;
  84. LPSPropValue pval;
  85. LPPROFADMIN lpProfAdmin;
  86. DWORD i;
  87. DWORD j;
  88. if (FAILED(m_lpfnMAPIAdminProfiles(0, &lpProfAdmin )))
  89. {
  90. goto exit;
  91. }
  92. //
  93. // get the mapi profile table object
  94. //
  95. if (FAILED(lpProfAdmin->GetProfileTable(0, &pmt )))
  96. {
  97. goto exit;
  98. }
  99. //
  100. // get the actual profile data, FINALLY
  101. //
  102. if (FAILED(pmt->QueryRows( 4000, 0, &prws )))
  103. {
  104. goto exit;
  105. }
  106. //
  107. // enumerate the profiles looking for the default profile
  108. //
  109. for (i=0; i<prws->cRows; i++)
  110. {
  111. pval = prws->aRow[i].lpProps;
  112. for (j = 0; j < 2; j++)
  113. {
  114. if (pval[j].ulPropTag == PR_DEFAULT_PROFILE && pval[j].Value.b)
  115. {
  116. //
  117. // this is the default profile
  118. //
  119. if(FAILED(StringCchCopyA(ProfileName, cchProfileName, pval[0].Value.lpszA)))
  120. {
  121. goto exit;
  122. }
  123. rVal = TRUE;
  124. break;
  125. }
  126. }
  127. }
  128. exit:
  129. FreeProws( prws );
  130. if (pmt)
  131. {
  132. pmt->Release();
  133. }
  134. if (lpProfAdmin)
  135. {
  136. lpProfAdmin->Release();
  137. }
  138. return rVal;
  139. }
  140. BOOL
  141. CMAPIabObj::DoMapiLogon(
  142. HWND hDlg
  143. )
  144. /*++
  145. Routine Description:
  146. Logon MAPI to in order to access address book
  147. Arguments:
  148. hDlg - Handle to the send fax wizard window
  149. Return Value:
  150. TRUE if successful, FALSE if there is an error
  151. --*/
  152. {
  153. CHAR strProfileName[MAX_PROFILE_NAME];
  154. HRESULT status;
  155. status = m_lpfnMAPIInitialize(NULL);
  156. if (status != SUCCESS_SUCCESS)
  157. return FALSE;
  158. if (!GetDefaultMapiProfile(strProfileName, ARR_SIZE(strProfileName)))
  159. {
  160. m_lpfnMAPIUninitialize();
  161. return FALSE;
  162. }
  163. status = m_lpfnMAPILogonEx((ULONG_PTR) hDlg,
  164. (LPTSTR)strProfileName,
  165. NULL,
  166. MAPI_USE_DEFAULT,
  167. &m_lpMapiSession);
  168. if (status != SUCCESS_SUCCESS || !m_lpMapiSession )
  169. {
  170. m_lpfnMAPIUninitialize();
  171. return FALSE;
  172. }
  173. OpenExchangeStore(); // If it fails it might just indicate that exchagne is not here.
  174. // We don't fail the function in this case.
  175. status = m_lpMapiSession->OpenAddressBook((ULONG_PTR) hDlg,
  176. NULL,
  177. 0,
  178. &m_lpAdrBook);
  179. if (HR_FAILED(status) || !m_lpAdrBook)
  180. {
  181. if (m_lpMapiSession)
  182. {
  183. m_lpMapiSession->Logoff(0,0,0);
  184. m_lpMapiSession->Release();
  185. m_lpIMsgStore->Release();
  186. }
  187. m_lpIMsgStore=NULL;
  188. m_lpMapiSession = NULL;
  189. m_lpfnMAPIUninitialize();
  190. return FALSE;
  191. }
  192. return TRUE;
  193. }
  194. BOOL CMAPIabObj::OpenExchangeStore()
  195. {
  196. /*++
  197. Routine Description:
  198. Open the Exchange message store and place a pointer to the IMsgStore interface
  199. in CMAPIabObj::m_lpIMsgStore.
  200. This is done to keep the store loaded as long as we have the address book opened.
  201. This resolves an exchange issue where sometimes the address book is released
  202. alrhough we still have reference count on its interfaces.
  203. Arguments:
  204. None
  205. Return Value:
  206. TRUE if successful, FALSE if there is an error
  207. --*/
  208. ULONG ulRow=0;
  209. HRESULT hr = S_OK;
  210. LPMAPITABLE lpStoreTable = NULL;
  211. LPSRowSet lprowsStores = NULL;
  212. SizedSPropTagArray(3, propStoreProperties)=
  213. {
  214. 3,
  215. {PR_DISPLAY_NAME_A, PR_ENTRYID, PR_MDB_PROVIDER}
  216. };
  217. hr = m_lpMapiSession->GetMsgStoresTable(
  218. 0, // NO UNICODE
  219. &lpStoreTable);
  220. if (FAILED(hr))
  221. {
  222. Error(("IMAPISession::GetMsgStoresTable failed. hr = 0x%08X", hr));
  223. goto Exit;
  224. }
  225. //
  226. // Now we have a pointer to the message store table. Lets find the exchange store.
  227. //
  228. Assert(NULL!=lpStoreTable);
  229. hr = m_lpfnHrQueryAllRows
  230. (
  231. lpStoreTable, // pointer to the table being queried
  232. (LPSPropTagArray)&propStoreProperties, // properties to return in each row
  233. NULL, // no restrictions get the entire table
  234. NULL, // use default sort order
  235. 0, // No limit on the number of rows retrieved
  236. &lprowsStores
  237. );
  238. if (FAILED(hr))
  239. {
  240. Error(("HrQueryAllRows on the stores table failed. hr = 0x%08X", hr));
  241. goto Exit;
  242. }
  243. //
  244. // Go over the rows and look for the one with PR_MDB_PROVIDER = pbExchangeProviderPrimaryUserGuid
  245. //
  246. for (ulRow=0;ulRow<lprowsStores->cRows;ulRow++)
  247. {
  248. if ( (sizeof(pbExchangeProviderPrimaryUserGuid)-1 == lprowsStores->aRow[ulRow].lpProps[2].Value.bin.cb))
  249. {
  250. if (!memcmp(lprowsStores->aRow[ulRow].lpProps[2].Value.bin.lpb, pbExchangeProviderPrimaryUserGuid, lprowsStores->aRow[ulRow].lpProps[2].Value.bin.cb))
  251. {
  252. //
  253. // If this is the Exchange store.
  254. // Open the information store using the value of PR_ENTRYID
  255. //
  256. hr = m_lpMapiSession->OpenMsgStore(
  257. NULL,
  258. lprowsStores->aRow[ulRow].lpProps[1].Value.bin.cb,
  259. (LPENTRYID)lprowsStores->aRow[ulRow].lpProps[1].Value.bin.lpb,
  260. NULL, // get the standard interface IMsgStore
  261. MAPI_BEST_ACCESS,
  262. &m_lpIMsgStore);
  263. {
  264. if (FAILED(hr))
  265. {
  266. Error(("OpenMsgStore failed for store [%s]. hr = 0x%08X",
  267. lprowsStores->aRow[ulRow].lpProps[0].Value.lpszA,
  268. hr));
  269. goto Exit;
  270. }
  271. }
  272. }
  273. }
  274. }
  275. Exit:
  276. if (lpStoreTable)
  277. {
  278. lpStoreTable->Release();
  279. lpStoreTable = NULL;
  280. }
  281. if (lprowsStores)
  282. {
  283. FreeProws(lprowsStores);
  284. lprowsStores = NULL;
  285. }
  286. return SUCCEEDED(hr);
  287. }
  288. BOOL
  289. CMAPIabObj::InitMapiService(
  290. HWND hDlg
  291. )
  292. /*++
  293. Routine Description:
  294. Initialize Simple MAPI services
  295. Arguments:
  296. hDlg - Handle to the send fax wizard window
  297. Return Value:
  298. TRUE if successful, FALSE otherwise
  299. NOTE:
  300. Every successful call to this function must be balanced
  301. by a call to DeinitMapiService.
  302. --*/
  303. {
  304. BOOL result = FALSE;
  305. m_lpIMsgStore=NULL;
  306. if(!IsOutlookDefaultClient())
  307. {
  308. return result;
  309. }
  310. //
  311. // Load MAPI32.DLL into memory if necessary
  312. //
  313. if ((m_hInstMapi == NULL) &&
  314. (m_hInstMapi = LoadLibrary(TEXT("MAPI32.DLL"))))
  315. {
  316. //
  317. // Get pointers to various Simple MAPI functions
  318. //
  319. m_lpfnMAPILogonEx = (LPMAPILOGONEX) GetProcAddress(m_hInstMapi, "MAPILogonEx");
  320. m_lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress(m_hInstMapi, "MAPILogoff");
  321. m_lpfnMAPIAddress = (LPMAPIADDRESS) GetProcAddress(m_hInstMapi, "MAPIAddress");
  322. m_lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress(m_hInstMapi, "MAPIFreeBuffer");
  323. m_lpfnMAPIInitialize = (LPMAPIINITIALIZE) GetProcAddress(m_hInstMapi, "MAPIInitialize");
  324. m_lpfnMAPIUninitialize = (LPMAPIUNINITIALIZE) GetProcAddress(m_hInstMapi, "MAPIUninitialize");
  325. m_lpfnMAPIAllocateBuffer = (LPMAPIALLOCATEBUFFER) GetProcAddress(m_hInstMapi, "MAPIAllocateBuffer");
  326. m_lpfnMAPIAllocateMore = (LPMAPIALLOCATEMORE) GetProcAddress(m_hInstMapi, "MAPIAllocateMore");
  327. m_lpfnMAPIAdminProfiles = (LPMAPIADMINPROFILES)GetProcAddress( m_hInstMapi,"MAPIAdminProfiles" );
  328. m_lpfnHrQueryAllRows = (LPHrQueryAllRows)GetProcAddress(m_hInstMapi,"HrQueryAllRows@24");
  329. //
  330. // Begins a simple MAPI session and obtain session handle and pointer
  331. //
  332. if (m_lpfnMAPILogonEx == NULL ||
  333. m_lpfnMAPILogoff == NULL ||
  334. m_lpfnMAPIAddress == NULL ||
  335. m_lpfnMAPIFreeBuffer == NULL ||
  336. m_lpfnMAPIInitialize == NULL ||
  337. m_lpfnMAPIUninitialize == NULL ||
  338. m_lpfnMAPIAllocateBuffer == NULL ||
  339. m_lpfnMAPIAllocateMore == NULL ||
  340. m_lpfnMAPIAdminProfiles == NULL ||
  341. m_lpfnHrQueryAllRows == NULL ||
  342. !DoMapiLogon(hDlg))
  343. {
  344. //
  345. // Clean up properly in case of error
  346. //
  347. m_lpMapiSession = NULL;
  348. FreeLibrary(m_hInstMapi);
  349. m_hInstMapi = NULL;
  350. }
  351. else
  352. {
  353. result = TRUE;
  354. }
  355. }
  356. #ifdef UNICODE
  357. //
  358. // The Outlook Address Book supports Unicode since version 10 (Office XP)
  359. // So we check the version
  360. //
  361. HKEY hRegKey = NULL;
  362. hRegKey = OpenRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_OUTLOOK_CUR_VER, FALSE, KEY_READ);
  363. if(!hRegKey)
  364. {
  365. return result;
  366. }
  367. LPWSTR szCurVer = NULL;
  368. szCurVer = GetRegistryString(hRegKey, TEXT(""), TEXT(""));
  369. RegCloseKey(hRegKey);
  370. if(!szCurVer)
  371. {
  372. return result;
  373. }
  374. //
  375. // The Outlook version string is Outlook.Application.X
  376. // Where is X the version
  377. //
  378. LPWSTR ptr = wcsrchr(szCurVer, TEXT('.'));
  379. if(ptr)
  380. {
  381. ptr = _wcsinc(ptr);
  382. DWORD dwVer = _wtoi(ptr);
  383. if(dwVer >= 10)
  384. {
  385. m_bUnicode = TRUE;
  386. }
  387. }
  388. MemFree (szCurVer);
  389. #endif // UNICODE
  390. return result;
  391. }
  392. VOID
  393. CMAPIabObj::DeinitMapiService(
  394. VOID
  395. )
  396. /*++
  397. Routine Description:
  398. Deinitialize Simple MAPI services if necessary
  399. Arguments:
  400. NONE
  401. Return Value:
  402. NONE
  403. --*/
  404. {
  405. if (m_hInstMapi != NULL)
  406. {
  407. if (m_lpAdrBook)
  408. {
  409. m_lpAdrBook->Release();
  410. m_lpAdrBook = NULL;
  411. }
  412. if (m_lpIMsgStore)
  413. {
  414. m_lpIMsgStore->Release();
  415. m_lpIMsgStore = NULL;
  416. }
  417. if (m_lpMapiSession)
  418. {
  419. m_lpMapiSession->Logoff(0,0,0);
  420. m_lpMapiSession->Release();
  421. m_lpMapiSession = NULL;
  422. }
  423. m_lpfnMAPIUninitialize();
  424. FreeLibrary(m_hInstMapi);
  425. m_hInstMapi = NULL;
  426. }
  427. }
  428. CMAPIabObj::~CMAPIabObj()
  429. /*++
  430. Routine Description:
  431. Destructor for CMAPIabObj class
  432. Arguments:
  433. NONE
  434. Return Value:
  435. NONE
  436. --*/
  437. {
  438. DeinitMapiService();
  439. }
  440. HRESULT
  441. CMAPIabObj::ABAllocateBuffer(
  442. ULONG cbSize,
  443. LPVOID FAR * lppBuffer
  444. )
  445. /*++
  446. Routine Description:
  447. Arguments:
  448. Return Value:
  449. --*/
  450. {
  451. return m_lpfnMAPIAllocateBuffer( cbSize, lppBuffer );
  452. }
  453. ULONG
  454. CMAPIabObj::ABFreeBuffer(
  455. LPVOID lpBuffer
  456. )
  457. {
  458. return m_lpfnMAPIFreeBuffer(lpBuffer);
  459. }
  460. extern "C"
  461. VOID
  462. FreeMapiEntryID(
  463. PWIZARDUSERMEM pWizardUserMem,
  464. LPENTRYID lpEntryId
  465. )
  466. /*++
  467. Routine Description:
  468. C wrapper for MAPI Free
  469. Arguments:
  470. pWizardUserMem - pointer to WIZARDUSERMEM structure
  471. lpEntryID - pointer to EntryId
  472. Return Value:
  473. NONE
  474. --*/
  475. {
  476. CMAPIabObj * lpCMAPIabObj = (CMAPIabObj *) pWizardUserMem->lpMAPIabInit;
  477. lpCMAPIabObj->ABFreeBuffer(lpEntryId);
  478. }
  479. extern "C"
  480. BOOL
  481. CallMAPIabAddress(
  482. HWND hDlg,
  483. PWIZARDUSERMEM pWizardUserMem,
  484. PRECIPIENT * ppNewRecipient
  485. )
  486. /*++
  487. Routine Description:
  488. C wrapper for CMAPIabObj->Address
  489. Arguments:
  490. hDlg - parent window handle.
  491. pWizardUserMem - pointer to WIZARDUSERMEM structure
  492. ppNewRecipient - list to add new recipients to.
  493. Return Value:
  494. TRUE if all of the entries have a fax number.
  495. FALSE otherwise.
  496. --*/
  497. {
  498. CMAPIabObj * lpCMAPIabObj = (CMAPIabObj *) pWizardUserMem->lpMAPIabInit;
  499. return lpCMAPIabObj->Address(
  500. hDlg,
  501. pWizardUserMem->pRecipients,
  502. ppNewRecipient
  503. );
  504. }
  505. extern "C"
  506. LPTSTR
  507. CallMAPIabAddressEmail(
  508. HWND hDlg,
  509. PWIZARDUSERMEM pWizardUserMem
  510. )
  511. /*++
  512. Routine Description:
  513. C wrapper for CMAPIabObj->AddressEmail
  514. Arguments:
  515. hDlg - parent window handle.
  516. pWizardUserMem - pointer to WIZARDUSERMEM structure
  517. Return Value:
  518. TRUE if found one appropriate E-mail
  519. FALSE otherwise.
  520. --*/
  521. {
  522. CMAPIabObj * lpCMAPIabObj = (CMAPIabObj *) pWizardUserMem->lpMAPIabInit;
  523. return lpCMAPIabObj->AddressEmail(
  524. hDlg
  525. );
  526. }
  527. extern "C"
  528. LPVOID
  529. InitializeMAPIAB(
  530. HINSTANCE hInstance,
  531. HWND hDlg
  532. )
  533. /*++
  534. Routine Description:
  535. Initialize the MAPI.
  536. Arguments:
  537. hInstance - instance handle.
  538. Return Value:
  539. NONE
  540. --*/
  541. {
  542. CMAPIabObj * lpCMAPIabObj = new (std::nothrow) CMAPIabObj ( hInstance, hDlg );
  543. if ((lpCMAPIabObj!=NULL) && (!lpCMAPIabObj->isInitialized())) // constructor failed
  544. {
  545. delete lpCMAPIabObj;
  546. lpCMAPIabObj = NULL;
  547. }
  548. return (LPVOID) lpCMAPIabObj ;
  549. }
  550. extern "C"
  551. VOID
  552. UnInitializeMAPIAB(
  553. LPVOID lpVoid
  554. )
  555. /*++
  556. Routine Description:
  557. UnInitialize the MAPI.
  558. Arguments:
  559. NONE
  560. Return Value:
  561. NONE
  562. --*/
  563. {
  564. CMAPIabObj * lpCMAPIabObj = (CMAPIabObj *) lpVoid;
  565. delete lpCMAPIabObj;
  566. }