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.

4147 lines
121 KiB

  1. // ===========================================================================
  2. // I P A B . C P P
  3. // ===========================================================================
  4. #include "pch.hxx"
  5. #include "ipab.h"
  6. #include "error.h"
  7. #include "xpcomm.h"
  8. #include <strconst.h>
  9. #include "ourguid.h"
  10. #include <wabguid.h> // IID_IDistList etc.
  11. #include <certs.h>
  12. #include <shlwapi.h>
  13. #include <shlwapip.h>
  14. #include <mimeole.h>
  15. #include <secutil.h>
  16. #include "demand.h"
  17. #include "conman.h"
  18. #include "multiusr.h"
  19. #include "instance.h"
  20. // ===========================================================================
  21. // G L O B A L S - The globals are set int HrInitWab
  22. // ===========================================================================
  23. static BOOL g_fWabInit = FALSE;
  24. static BOOL g_fWabLoaded = FALSE;
  25. static HINSTANCE g_hWab32Dll = NULL;
  26. static LPWABOPEN g_lpfnWabOpen = NULL;
  27. static LPWABOBJECT g_lpWabObject = NULL;
  28. static LPADRBOOK g_lpAdrBook = NULL;
  29. static CRITICAL_SECTION g_rWabCritSect = {0};
  30. static CWab *g_pWab = NULL;
  31. static TCHAR c_szOEThis[] = "OE_ThisPtr";
  32. // ===========================================================================
  33. // P R O T O T Y P E S
  34. // ===========================================================================
  35. HRESULT HrLoadWab (VOID);
  36. BOOL FUnloadWab (VOID);
  37. VOID ReleaseWabObjects (LPWABOBJECT lpWabObject, LPADRBOOK lpAdrBook);
  38. void SerialAdrInfoString(LPWSTR *ppwszDest, ULONG cchDest, LPWSTR pwszSrc, ULONG *pcbOff,
  39. LPBYTE *ppbData);
  40. HRESULT HrAddrInfoListToHGlobal (LPADRINFOLIST lpAdrInfoList,
  41. HGLOBAL *phGlobal);
  42. HRESULT HrHGlobalToAddrInfoList (HGLOBAL hGlobal, LPADRINFOLIST *lplpAdrInfoList); // caller frees with MemFree
  43. ULONG CbAdrInfoSize (LPADRINFO lpAdrInfo);
  44. HRESULT HrSetAdrEntry (LPWABOBJECT lpWab, LPADRENTRY lpAdrEntry,
  45. LPADRINFO lpAdrInfo, DWORD mask);
  46. LPTSTR SzWabStringDup (LPWABOBJECT lpWab, LPCSTR lpcsz, LPVOID lpParentObject);
  47. LPWSTR SzWabStringDupW(LPWABOBJECT lpWab, LPCWSTR lpcwsz, LPVOID lpParentObject);
  48. LPBYTE LpbWabBinaryDup (LPWABOBJECT lpWab, LPBYTE lpbSrc, ULONG cb, LPVOID lpParentObject);
  49. void STDMETHODCALLTYPE DismissWabWindow(ULONG_PTR ulUIParam, LPVOID lpvContext);
  50. #ifdef DEBUG
  51. void DEBUGDumpAdrList(LPADRLIST pal);
  52. #endif
  53. // ===========================================================================
  54. // HrInitWab
  55. // ===========================================================================
  56. HRESULT HrInitWab (BOOL fInit)
  57. {
  58. // Locals
  59. HRESULT hr = S_OK;
  60. // Initialize the WAB
  61. if (fInit)
  62. {
  63. // Have we already been initialized ?
  64. if (g_fWabInit)
  65. goto exit;
  66. // Wab has been inited, doesn't imply success
  67. g_fWabInit = TRUE;
  68. // Init Critical Section
  69. InitializeCriticalSection (&g_rWabCritSect);
  70. // Load the WAB
  71. CHECKHR (hr = HrLoadWab ());
  72. }
  73. // Unload Wab
  74. else
  75. {
  76. // Not inited ?
  77. if (!g_fWabInit)
  78. goto exit;
  79. // Unload Wab
  80. if (FUnloadWab () == TRUE)
  81. {
  82. // Kill critical section
  83. DeleteCriticalSection (&g_rWabCritSect);
  84. // Not inited
  85. g_fWabInit = FALSE;
  86. }
  87. }
  88. exit:
  89. // Done
  90. if (fInit && FAILED (hr))
  91. AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrLoadingWAB), NULL, MB_OK);
  92. return hr;
  93. }
  94. const static TCHAR lpszWABDLLRegPathKey[] = TEXT("Software\\Microsoft\\WAB\\DLLPath");
  95. const static TCHAR lpszWABEXERegPathKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
  96. const static TCHAR lpszWABEXE[] = TEXT("wab.exe");
  97. // =============================================================================
  98. // HrLoadPathWABEXE - creaetd vikramm 5/14/97 - loads the registered path of the
  99. // latest wab.exe
  100. // szPath - pointer to a buffer
  101. // cbPath - sizeof buffer
  102. // =============================================================================
  103. // ~~~~ @TODO dhaws Might need to convert this
  104. HRESULT HrLoadPathWABEXE(LPTSTR szPath, ULONG cbPath)
  105. {
  106. DWORD dwType;
  107. ULONG cbData = cbPath;
  108. HKEY hKey;
  109. Assert(szPath != NULL);
  110. Assert(cbPath > 0);
  111. *szPath = '\0';
  112. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABEXERegPathKey, 0, KEY_READ, &hKey))
  113. {
  114. SHQueryValueEx( hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szPath, &cbData);
  115. RegCloseKey(hKey);
  116. }
  117. if(!lstrlen(szPath))
  118. StrCpyN(szPath, lpszWABEXE,cbPath/sizeof(szPath[0]));
  119. return S_OK;
  120. }
  121. // ===========================================================================
  122. // HrLoadLibraryWabDLL - added vikramm 5/14 - new wab setup needs this
  123. // ===========================================================================
  124. HINSTANCE LoadLibraryWabDLL (VOID)
  125. {
  126. TCHAR szWABDllPath[MAX_PATH];
  127. DWORD dwType;
  128. ULONG cbData = sizeof(szWABDllPath);
  129. HKEY hKey;
  130. *szWABDllPath = '\0';
  131. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABDLLRegPathKey, 0, KEY_READ, &hKey))
  132. {
  133. SHQueryValueEx( hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
  134. RegCloseKey(hKey);
  135. }
  136. if(!lstrlen(szWABDllPath))
  137. StrCpyN(szWABDllPath, WAB_DLL_NAME, ARRAYSIZE(szWABDllPath));
  138. return(LoadLibrary(szWABDllPath));
  139. }
  140. // ===========================================================================
  141. // HrLoadWab
  142. // ===========================================================================
  143. HRESULT HrLoadWab (VOID)
  144. {
  145. // Locals
  146. HRESULT hr = S_OK;
  147. WAB_PARAM wp = {0};
  148. LPWAB pWab;
  149. // We better be init'ed
  150. Assert (g_fWabInit == TRUE);
  151. // Enter Critical Section
  152. EnterCriticalSection (&g_rWabCritSect);
  153. // Load the WAB Dll
  154. g_hWab32Dll = LoadLibraryWabDLL();
  155. // Did it load
  156. if (g_hWab32Dll == NULL)
  157. {
  158. hr = TRAPHR (hrUnableToLoadWab32Dll);
  159. goto exit;
  160. }
  161. // Get WABOpen proc
  162. IF_WIN32(g_lpfnWabOpen = (LPWABOPEN)GetProcAddress (g_hWab32Dll, "WABOpen");)
  163. IF_WIN16(g_lpfnWabOpen = (LPWABOPEN)GetProcAddress (g_hWab32Dll, "_WABOpen");)
  164. // Did we get the proc ?
  165. if (g_lpfnWabOpen == NULL)
  166. {
  167. hr = TRAPHR (hrUnableToLoadWab32Dll);
  168. goto exit;
  169. }
  170. // get the current user id to open the right view in the WAB.
  171. wp.cbSize = sizeof(WAB_PARAM);
  172. wp.guidPSExt = CLSID_AddrObject; // was CLSID_OEBAControl, bug 99652;
  173. wp.ulFlags = (g_dwAthenaMode & MODE_NEWSONLY) ? WAB_ENABLE_PROFILES | MAPI_UNICODE:
  174. WAB_ENABLE_PROFILES | MAPI_UNICODE | WAB_USE_OE_SENDMAIL;
  175. // Open the wab and get the objects
  176. CHECKHR (hr = (*g_lpfnWabOpen)(&g_lpAdrBook, &g_lpWabObject, &wp, 0));
  177. pWab = new CWab;
  178. if (pWab == NULL)
  179. {
  180. hr = TRAPHR (hrMemory);
  181. goto exit;
  182. }
  183. else
  184. {
  185. g_pWab = pWab;
  186. }
  187. // Yee-hah, the wab is loaded
  188. g_fWabLoaded = TRUE;
  189. exit:
  190. // Leave Critical Section
  191. LeaveCriticalSection (&g_rWabCritSect);
  192. // Done
  193. return hr;
  194. }
  195. // ===========================================================================
  196. // UnloadWab
  197. // ===========================================================================
  198. BOOL FUnloadWab (VOID)
  199. {
  200. // Locals
  201. ULONG cWabObjectRefs = 0, cAdrBookRefs = 0, cWabRefs = 0;
  202. BOOL fResult = FALSE;
  203. // We better have been inited
  204. Assert (g_fWabInit == TRUE);
  205. // Enter Critical Section
  206. EnterCriticalSection (&g_rWabCritSect);
  207. // Release global objects
  208. if (g_lpAdrBook && g_lpWabObject && g_pWab)
  209. {
  210. if (g_pWab)
  211. g_pWab->OnClose(); // the close callback will release it.
  212. // Get Ref Counts and cleanup
  213. cWabRefs = g_pWab->Release ();
  214. g_pWab = NULL;
  215. cAdrBookRefs = g_lpAdrBook->Release ();
  216. g_lpAdrBook = NULL;
  217. cWabObjectRefs = g_lpWabObject->Release ();
  218. g_lpWabObject = NULL;
  219. g_fWabLoaded = FALSE;
  220. fResult = TRUE;
  221. // These better be the same
  222. //Assert (cWabObjectRefs == cAdrBookRefs);
  223. // Can we unload now ?
  224. if (cWabObjectRefs == 0 && cAdrBookRefs == 0 && cWabRefs == 0)
  225. {
  226. // Unload the dll
  227. if (g_hWab32Dll)
  228. {
  229. FreeLibrary (g_hWab32Dll);
  230. g_hWab32Dll = NULL;
  231. }
  232. // Reset the proc pointer to NULL
  233. g_lpfnWabOpen = NULL;
  234. }
  235. }
  236. // Leave Critical Section
  237. LeaveCriticalSection (&g_rWabCritSect);
  238. // Done
  239. return fResult;
  240. }
  241. // ===========================================================================
  242. // ReleaseWabObjects
  243. // ===========================================================================
  244. VOID ReleaseWabObjects (LPWABOBJECT lpWabObject, LPADRBOOK lpAdrBook)
  245. {
  246. // Locals
  247. ULONG cWabObjectRefs = 0, cAdrBookRefs = 0;
  248. // We better have been inited
  249. Assert (g_fWabInit == TRUE);
  250. // Check Params
  251. if (lpWabObject == NULL || lpAdrBook == NULL)
  252. {
  253. Assert (FALSE);
  254. return;
  255. }
  256. // Enter Critical Section
  257. EnterCriticalSection (&g_rWabCritSect);
  258. // Release objects
  259. Assert (g_lpAdrBook && g_lpWabObject)
  260. // Release the wab
  261. cAdrBookRefs = lpAdrBook->Release ();
  262. cWabObjectRefs = lpWabObject->Release ();
  263. // Ref counts should hit zero at the same time
  264. #ifdef DEBUG
  265. if (cWabObjectRefs==0)
  266. Assert(cAdrBookRefs==0);
  267. if (cAdrBookRefs==0)
  268. Assert(cWabObjectRefs==0);
  269. #endif
  270. // If both counts are zero, we can unload the dll
  271. if (cWabObjectRefs == 0 && cAdrBookRefs == 0)
  272. {
  273. // Set globals
  274. g_lpWabObject = NULL;
  275. g_lpAdrBook = NULL;
  276. // Unload the WAB
  277. if (g_hWab32Dll)
  278. {
  279. FreeLibrary (g_hWab32Dll);
  280. g_hWab32Dll = NULL;
  281. }
  282. // Reset the proc pointer to NULL
  283. g_lpfnWabOpen = NULL;
  284. // Not loaded, not inited
  285. g_fWabLoaded = FALSE;
  286. // Not inited
  287. g_fWabInit = FALSE;
  288. // Leave Critical Section
  289. LeaveCriticalSection (&g_rWabCritSect);
  290. // Kill critical section
  291. DeleteCriticalSection (&g_rWabCritSect);
  292. }
  293. else
  294. {
  295. // Leave Critical Section
  296. LeaveCriticalSection (&g_rWabCritSect);
  297. }
  298. // Done
  299. return;
  300. }
  301. /***************************************************************************
  302. Name : FWABTranslateAccelerator
  303. Purpose : Give an open WAB window a change to look for accelerators.
  304. Parameters: lpmsg -> lpmsg from the current event
  305. Returns : BOOL - was the event used
  306. ***************************************************************************/
  307. BOOL FWABTranslateAccelerator(LPMSG lpmsg)
  308. {
  309. if (g_pWab)
  310. return g_pWab->FTranslateAccelerator(lpmsg);
  311. else
  312. return FALSE;
  313. }
  314. // ===========================================================================
  315. // HrCreateWabObject
  316. // ===========================================================================
  317. HRESULT HrCreateWabObject (LPWAB *lppWab)
  318. {
  319. // Locals
  320. HRESULT hr = S_OK;
  321. // Check Params
  322. Assert (lppWab);
  323. hr=HrInitWab(TRUE);
  324. if (FAILED(hr))
  325. return hr;
  326. // Verify Globals
  327. if (g_fWabLoaded == FALSE || g_fWabInit == FALSE)
  328. {
  329. return TRAPHR (hrWabNotLoaded);
  330. }
  331. // Enter Critical Section
  332. EnterCriticalSection (&g_rWabCritSect);
  333. // Verify globals
  334. Assert (g_lpfnWabOpen && g_hWab32Dll && g_lpAdrBook && g_lpWabObject && g_pWab);
  335. // Inst it
  336. g_pWab->AddRef();
  337. *lppWab = g_pWab;
  338. // Leave Critical Section
  339. LeaveCriticalSection (&g_rWabCritSect);
  340. // Done
  341. return hr;
  342. }
  343. // ===========================================================================
  344. // DismissWabWindow
  345. // ===========================================================================
  346. void STDMETHODCALLTYPE DismissWabWindow(ULONG_PTR ulUIParam, LPVOID lpvContext)
  347. {
  348. CWab *pWab = (CWab *) lpvContext;
  349. Assert(pWab == g_pWab);
  350. if (pWab == g_pWab)
  351. {
  352. g_pWab->BrowseWindowClosed();
  353. }
  354. }
  355. /*
  356. -
  357. - Checks for the existence of a Contact with a specific e-mail address
  358. *
  359. */
  360. HRESULT HrCheckEMailExistence(LPADRBOOK lpAdrBook, LPWABOBJECT lpWabObject, LPWSTR lpwszLookup)
  361. {
  362. HRESULT hr = NOERROR;
  363. ULONG i = 0, j=0;
  364. LPADRLIST lpAdrList = NULL;
  365. BOOL fFound = FALSE;
  366. Assert(lpAdrBook && lpWabObject);
  367. hr = lpWabObject->AllocateBuffer(sizeof(ADRLIST), (LPVOID *)&lpAdrList);
  368. if(FAILED(hr))
  369. goto Cleanup;
  370. Assert(lpAdrList);
  371. lpAdrList->cEntries = 1;
  372. lpAdrList->aEntries[0].ulReserved1 = 0;
  373. lpAdrList->aEntries[0].cValues = 1;
  374. hr = lpWabObject->AllocateBuffer(sizeof(SPropValue), (LPVOID *)&lpAdrList->aEntries[0].rgPropVals);
  375. if(FAILED(hr))
  376. goto Cleanup;
  377. lpAdrList->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS_W;
  378. lpAdrList->aEntries[0].rgPropVals[0].Value.lpszW = lpwszLookup;
  379. hr = lpAdrBook->ResolveName ( 0,
  380. WAB_RESOLVE_LOCAL_ONLY |
  381. WAB_RESOLVE_ALL_EMAILS |
  382. WAB_RESOLVE_USE_CURRENT_PROFILE |
  383. WAB_RESOLVE_UNICODE,
  384. NULL, lpAdrList);
  385. if(FAILED(hr))
  386. goto Cleanup;
  387. for(j=0; j<lpAdrList->aEntries[0].cValues; j++)
  388. {
  389. if(lpAdrList->aEntries[0].rgPropVals[j].ulPropTag == PR_ENTRYID)
  390. {
  391. fFound = TRUE;
  392. break;
  393. }
  394. }
  395. if(!fFound)
  396. hr = MAPI_E_NOT_FOUND;
  397. Cleanup:
  398. if (lpAdrList)
  399. {
  400. for (ULONG ul = 0; ul < lpAdrList->cEntries; ul++)
  401. lpWabObject->FreeBuffer(lpAdrList->aEntries[ul].rgPropVals);
  402. lpWabObject->FreeBuffer(lpAdrList);
  403. }
  404. return hr;
  405. }
  406. /***************************************************************************
  407. Name : HrWABCreateEntry
  408. Purpose : Create a new entry in the WAB
  409. Parameters: lpAdrBook -> ADDRBOOK object
  410. lpWabObject -> WABOBJECT for allocators
  411. lpszDisplay -> display name to set [optional]
  412. lpszAddress -> email address to set [optional]
  413. ulFlags = flags for CreateEntry
  414. CREATE_CHECK_DUP_STRICT
  415. lppMailUser -> returned MAILUSER object. [optional]
  416. Returns : HRESULT
  417. Comment :
  418. ***************************************************************************/
  419. HRESULT HrWABCreateEntry(LPADRBOOK lpAdrBook, LPWABOBJECT lpWabObject,
  420. LPWSTR lpwszDisplay, LPWSTR lpwszAddress, ULONG ulFlags,
  421. LPMAILUSER *lppMailUser, ULONG ulSaveFlags)
  422. {
  423. LPABCONT pabcWAB = NULL;
  424. ULONG cbEidWAB;
  425. LPENTRYID peidWAB = NULL;
  426. LPMAILUSER lpMailUser = NULL;
  427. SPropValue rgpv[3];
  428. SPropTagArray ptaEID = {1, {PR_ENTRYID}};
  429. LPSPropValue ppvDefMailUser=0;
  430. SizedSPropTagArray(1, ptaDefMailUser)=
  431. { 1, {PR_DEF_CREATE_MAILUSER} };
  432. ULONG cProps,
  433. ulObjectType;
  434. HRESULT hr;
  435. Assert(lpwszDisplay);
  436. Assert(lpAdrBook);
  437. Assert(lpWabObject);
  438. if(lpwszAddress && *lpwszAddress)
  439. {
  440. // Check if the e-mail exists before auto-adding-to-wab
  441. hr = HrCheckEMailExistence(lpAdrBook, lpWabObject, lpwszAddress);
  442. if(hr != MAPI_E_NOT_FOUND)
  443. {
  444. //either it's found or it's an error
  445. //if it's found, then this function should generate a collision error
  446. if(hr == NOERROR)
  447. hr = MAPI_E_COLLISION;
  448. goto error;
  449. }
  450. }
  451. // Create a new contact with these properties
  452. // First, create the basic contact with only a display name
  453. hr = lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
  454. if (FAILED(hr))
  455. goto error;
  456. hr = lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL, 0, &ulObjectType, (LPUNKNOWN *)&pabcWAB);
  457. if (FAILED(hr))
  458. goto error;
  459. Assert(ulObjectType == MAPI_ABCONT);
  460. lpWabObject->FreeBuffer(peidWAB);
  461. hr = pabcWAB->GetProps((LPSPropTagArray)&ptaDefMailUser, 0, &cProps, &ppvDefMailUser);
  462. if (FAILED(hr) || ! ppvDefMailUser || ppvDefMailUser->ulPropTag != PR_DEF_CREATE_MAILUSER)
  463. goto error;
  464. hr = pabcWAB->CreateEntry(ppvDefMailUser->Value.bin.cb, (LPENTRYID)ppvDefMailUser->Value.bin.lpb,
  465. ulFlags, (LPMAPIPROP *)&lpMailUser);
  466. if (FAILED(hr))
  467. goto error;
  468. rgpv[0].ulPropTag = PR_DISPLAY_NAME_W;
  469. rgpv[0].Value.lpszW = lpwszDisplay;
  470. cProps = 1;
  471. if (lpwszAddress)
  472. {
  473. rgpv[1].ulPropTag = PR_ADDRTYPE_W;
  474. rgpv[1].Value.lpszW = L"SMTP";
  475. cProps++;
  476. rgpv[2].ulPropTag = PR_EMAIL_ADDRESS_W;
  477. rgpv[2].Value.lpszW = lpwszAddress;
  478. cProps++;
  479. }
  480. hr = lpMailUser->SetProps(cProps, rgpv, NULL);
  481. if (FAILED(hr))
  482. goto error;
  483. hr = lpMailUser->SaveChanges(ulSaveFlags /*KEEP_OPEN_READONLY*/);
  484. if (FAILED(hr))
  485. goto error;
  486. // Return the new object if it was asked for
  487. if (lppMailUser)
  488. {
  489. *lppMailUser = lpMailUser;
  490. lpMailUser = NULL; // short circuit the release below.
  491. }
  492. error:
  493. ReleaseObj(lpMailUser);
  494. ReleaseObj(pabcWAB);
  495. if (ppvDefMailUser)
  496. lpWabObject->FreeBuffer(ppvDefMailUser);
  497. return(hr);
  498. }
  499. // ===========================================================================
  500. // CWab::CWab
  501. // ===========================================================================
  502. CWab::CWab ()
  503. {
  504. DOUT ("CWab::CWab");
  505. m_cRef = 1;
  506. m_lpWabObject = g_lpWabObject;
  507. m_lpWabObject->AddRef();
  508. m_lpAdrBook = g_lpAdrBook;
  509. m_lpAdrBook->AddRef();
  510. m_hwnd = NULL;
  511. m_pfnWabWndProc = NULL;
  512. ZeroMemory(&m_adrParm, sizeof(m_adrParm));
  513. m_fInternal = FALSE;
  514. ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST));
  515. }
  516. // ===========================================================================
  517. // CWab::CWab
  518. // ===========================================================================
  519. CWab::~CWab ()
  520. {
  521. DOUT ("CWab::~CWab");
  522. ReleaseWabObjects (m_lpWabObject, m_lpAdrBook);
  523. }
  524. // =============================================================================
  525. // CWab::AddRef
  526. // =============================================================================
  527. ULONG CWab::AddRef (VOID)
  528. {
  529. DOUT("CWab::AddRef %lx ==> %d", this, m_cRef+1);
  530. return ++m_cRef;
  531. }
  532. // =============================================================================
  533. // CWab::Release
  534. // =============================================================================
  535. ULONG CWab::Release (VOID)
  536. {
  537. DOUT("CWab::Release %lx ==> %d", this, m_cRef-1);
  538. if (--m_cRef == 0)
  539. {
  540. delete this;
  541. return 0;
  542. }
  543. return m_cRef;
  544. }
  545. // =============================================================================
  546. // CWab::FVerifyState
  547. // =============================================================================
  548. BOOL CWab::FVerifyState (VOID)
  549. {
  550. // We need these things !
  551. if (m_lpWabObject == NULL || m_lpAdrBook == NULL)
  552. {
  553. Assert (FALSE);
  554. return FALSE;
  555. }
  556. // Done
  557. return TRUE;
  558. }
  559. // =============================================================================
  560. // CWab::HrPickNames
  561. // =============================================================================
  562. HRESULT CWab::HrPickNames (HWND hwndParent, ULONG *rgulTypes, int cWells, int iFocus, BOOL fNews, LPADRLIST *lppal)
  563. {
  564. // Locals
  565. int i, ids;
  566. HRESULT hr = S_OK;
  567. WCHAR wsz[CCHMAX_STRINGRES],
  568. wsz2[CCHMAX_STRINGRES];
  569. ADRPARM AdrParms = {0};
  570. LPWSTR *ppwszWells = NULL;
  571. // Check Parameters
  572. Assert (lppal);
  573. Assert(cWells > 0);
  574. // Have we been initialized
  575. if (FVerifyState () == FALSE)
  576. {
  577. hr = TRAPHR (E_FAIL);
  578. return hr;
  579. }
  580. if (!MemAlloc((LPVOID *)&ppwszWells, cWells*sizeof(LPWSTR)))
  581. {
  582. hr = E_OUTOFMEMORY;
  583. goto error;
  584. }
  585. ZeroMemory(ppwszWells, cWells * sizeof(LPWSTR));
  586. AthLoadStringW(idsMsgRecipients, wsz2, ARRAYSIZE(wsz2));
  587. AthLoadStringW(idsPickRecipientsTT, wsz, ARRAYSIZE(wsz));
  588. AdrParms.ulFlags=DIALOG_MODAL|MAPI_UNICODE;
  589. AdrParms.lpszCaption=(LPTSTR)wsz;
  590. AdrParms.cDestFields = cWells;
  591. AdrParms.nDestFieldFocus = iFocus;
  592. AdrParms.lpulDestComps = rgulTypes;
  593. AdrParms.lpszDestWellsTitle = (LPTSTR)wsz2;
  594. for (i = 0; i < cWells; i++)
  595. {
  596. switch (rgulTypes[i])
  597. {
  598. case MAPI_TO:
  599. if (!fNews)
  600. {
  601. ids = idsToWell;
  602. break;
  603. }
  604. // fall thru...
  605. case MAPI_CC:
  606. ids = idsCcWell;
  607. break;
  608. case MAPI_ORIG:
  609. ids = idsFromWell;
  610. break;
  611. case MAPI_REPLYTO:
  612. ids = idsReplyToWell;
  613. break;
  614. case MAPI_BCC:
  615. ids = idsBccWell;
  616. break;
  617. default:
  618. Assert(FALSE);
  619. break;
  620. }
  621. if (!MemAlloc((LPVOID *)&ppwszWells[i], CCHMAX_STRINGRES * sizeof(WCHAR)))
  622. {
  623. hr = E_OUTOFMEMORY;
  624. goto error;
  625. }
  626. AthLoadStringW(ids, ppwszWells[i], CCHMAX_STRINGRES);
  627. }
  628. AdrParms.lppszDestTitles = (LPTSTR *)ppwszWells;
  629. // Show the dialog
  630. hr = m_lpAdrBook->Address ((ULONG_PTR *)&hwndParent, &AdrParms, lppal);
  631. #ifdef DEBUG
  632. DEBUGDumpAdrList(*lppal);
  633. #endif
  634. // Cleanup
  635. if (ppwszWells)
  636. {
  637. for (i=0; i<cWells; i++)
  638. SafeMemFree(ppwszWells[i]);
  639. MemFree(ppwszWells);
  640. }
  641. error:
  642. // Done
  643. return hr;
  644. }
  645. // =============================================================================
  646. // CWab::HrGeneralPickNames
  647. // =============================================================================
  648. HRESULT CWab::HrGeneralPickNames(HWND hwndParent, ADRPARM *pAdrParms, LPADRLIST *lppal)
  649. {
  650. // Locals
  651. HRESULT hr = S_OK;
  652. // Check Parameters
  653. Assert (lppal);
  654. // Have we been initialized
  655. if (FVerifyState () == FALSE)
  656. {
  657. hr = TRAPHR (E_FAIL);
  658. return hr;
  659. }
  660. // Show the dialog
  661. hr = m_lpAdrBook->Address ((ULONG_PTR *)&hwndParent, pAdrParms, lppal);
  662. // Cleanup
  663. if (FAILED (hr))
  664. {
  665. if (*lppal)
  666. {
  667. m_lpWabObject->FreeBuffer (*lppal);
  668. *lppal = NULL;
  669. }
  670. }
  671. // Done
  672. return hr;
  673. }
  674. // =============================================================================
  675. // CWab::HrBrowse
  676. // =============================================================================
  677. HRESULT CWab::HrBrowse (HWND hwndParent, BOOL fModal)
  678. {
  679. ULONG_PTR uiParam = (ULONG_PTR)hwndParent;
  680. LPADRLIST pAdrList = NULL;
  681. HRESULT hr;
  682. TCHAR szWabCaption[CCHMAX_STRINGRES];
  683. // Change to use IAddrBook::Address
  684. Assert(m_lpAdrBook);
  685. AthLoadString(idsAddressBook, szWabCaption, sizeof(szWabCaption));
  686. ZeroMemory(&m_adrParm, sizeof(m_adrParm));
  687. m_adrParm.ulFlags = fModal ? DIALOG_MODAL : DIALOG_SDI;
  688. if (!fModal)
  689. {
  690. //m_adrParm.lpszCaption = szWabCaption;
  691. m_adrParm.lpfnDismiss = &DismissWabWindow;
  692. m_adrParm.lpvDismissContext = (void *)this;
  693. }
  694. hr = m_lpAdrBook->Address(&uiParam, &m_adrParm, &pAdrList);
  695. if (SUCCEEDED(hr) && g_pInstance && !fModal)
  696. {
  697. // subclass the wab window, if there isn't one already up
  698. if (GetProp((HWND)uiParam, c_szOEThis) == 0)
  699. {
  700. m_pfnWabWndProc = (WNDPROC)SetWindowLongPtr((HWND)uiParam, GWLP_WNDPROC, (LONG_PTR)WabSubProc);
  701. SetProp((HWND)uiParam, c_szOEThis, (HANDLE)this);
  702. SetProp((HWND)uiParam, c_szOETopLevel, (HANDLE)TRUE);
  703. CoIncrementInit("WabWindow", MSOEAPI_START_SHOWERRORS, NULL, NULL);
  704. AddRef();
  705. }
  706. }
  707. m_hwnd = (HWND)uiParam;
  708. return NOERROR;
  709. }
  710. // =============================================================================
  711. // CWab::HrAddNewEntry
  712. // =============================================================================
  713. HRESULT CWab::HrAddNewEntryA(LPTSTR lpszDisplay, LPTSTR lpszAddress)
  714. {
  715. LPWSTR pwszDisplay = NULL,
  716. pwszAddress = NULL;
  717. HRESULT hr = S_OK;
  718. Assert(lpszDisplay);
  719. IF_NULLEXIT(pwszDisplay = PszToUnicode(CP_ACP, lpszDisplay));
  720. // If lpszAddress is null, we have an incomplete Entry. This is ok.
  721. pwszAddress = PszToUnicode(CP_ACP, lpszAddress);
  722. if (lpszAddress && !pwszAddress)
  723. IF_NULLEXIT(NULL);
  724. hr = HrAddNewEntry(pwszDisplay, pwszAddress);
  725. exit:
  726. MemFree(pwszDisplay);
  727. MemFree(pwszAddress);
  728. return hr;
  729. }
  730. HRESULT CWab::HrAddNewEntry(LPWSTR lpwszDisplay, LPWSTR lpwszAddress)
  731. {
  732. return(HrWABCreateEntry(m_lpAdrBook,
  733. m_lpWabObject,
  734. lpwszDisplay,
  735. lpwszAddress,
  736. CREATE_CHECK_DUP_STRICT|MAPI_UNICODE,
  737. NULL));
  738. }
  739. VOID CWab::FreeLPSRowSet(LPSRowSet lpsrs)
  740. {
  741. UINT i;
  742. if(NULL == m_lpWabObject)
  743. return;
  744. if(lpsrs)
  745. {
  746. for(i=0;i<lpsrs->cRows;i++)
  747. m_lpWabObject->FreeBuffer(lpsrs->aRow[i].lpProps);
  748. m_lpWabObject->FreeBuffer(lpsrs);
  749. }
  750. }
  751. VOID CWab::FreePadrlist(LPADRLIST lpAdrList)
  752. {
  753. if(NULL == m_lpWabObject)
  754. return;
  755. if(lpAdrList)
  756. {
  757. for (ULONG iEntry = 0; iEntry < lpAdrList->cEntries; ++iEntry)
  758. {
  759. if(lpAdrList->aEntries[iEntry].rgPropVals)
  760. m_lpWabObject->FreeBuffer(lpAdrList->aEntries[iEntry].rgPropVals);
  761. }
  762. m_lpWabObject->FreeBuffer(lpAdrList);
  763. }
  764. }
  765. HRESULT CWab::HrFind(HWND hwnd, LPWSTR lpwszLookup)
  766. {
  767. HRESULT hr = NOERROR;
  768. ULONG i = 0, j=0;
  769. LPSRowSet lpsrs = NULL;
  770. ULONG cbEntryID=0;
  771. LPENTRYID lpEntryID=NULL;
  772. ULONG ulObjType = 0;
  773. LPADRLIST lpAdrList = NULL;
  774. BOOL fFound = FALSE;
  775. Assert(m_lpAdrBook && m_lpWabObject);
  776. if (lpwszLookup == NULL)
  777. return E_INVALIDARG;
  778. hr = m_lpWabObject->AllocateBuffer(sizeof(ADRLIST), (LPVOID *)&lpAdrList);
  779. if(FAILED(hr))
  780. goto Cleanup;
  781. Assert(lpAdrList);
  782. lpAdrList->cEntries = 1;
  783. lpAdrList->aEntries[0].ulReserved1 = 0;
  784. lpAdrList->aEntries[0].cValues = 1;
  785. hr = m_lpWabObject->AllocateBuffer(sizeof(SPropValue), (LPVOID *)&lpAdrList->aEntries[0].rgPropVals);
  786. if(FAILED(hr))
  787. goto Cleanup;
  788. lpAdrList->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS_W;
  789. lpAdrList->aEntries[0].rgPropVals[0].Value.lpszW = lpwszLookup;
  790. hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwnd, WAB_RESOLVE_NO_NOT_FOUND_UI |
  791. WAB_RESOLVE_ALL_EMAILS |
  792. WAB_RESOLVE_USE_CURRENT_PROFILE |
  793. MAPI_DIALOG |
  794. WAB_RESOLVE_UNICODE,
  795. NULL, lpAdrList);
  796. if(FAILED(hr))
  797. goto Cleanup;
  798. for(j=0; j<lpAdrList->aEntries[0].cValues; j++)
  799. {
  800. if(lpAdrList->aEntries[0].rgPropVals[j].ulPropTag == PR_ENTRYID)
  801. {
  802. cbEntryID = lpAdrList->aEntries[0].rgPropVals[j].Value.bin.cb;
  803. lpEntryID = (LPENTRYID)lpAdrList->aEntries[0].rgPropVals[j].Value.bin.lpb;
  804. fFound = TRUE;
  805. hr = g_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, cbEntryID, lpEntryID, NULL, NULL, NULL, DIALOG_MODAL);
  806. if(FAILED(hr) && hr!=MAPI_E_USER_CANCEL)
  807. goto Cleanup;
  808. hr = NOERROR;
  809. break;
  810. }
  811. }
  812. Cleanup:
  813. FreePadrlist(lpAdrList);
  814. if(!fFound && hr!=MAPI_E_USER_CANCEL)
  815. hr = E_FAIL;
  816. if(hr==MAPI_E_USER_CANCEL)
  817. hr = NOERROR;
  818. return hr;
  819. }
  820. enum
  821. {
  822. ieidPR_DISPLAY_NAME = 0,
  823. ieidPR_ENTRYID,
  824. ieidPR_OBJECT_TYPE,
  825. ieidMax
  826. };
  827. static const SizedSPropTagArray(ieidMax, ptaEid_A)=
  828. {
  829. ieidMax,
  830. {
  831. PR_DISPLAY_NAME_A,
  832. PR_ENTRYID,
  833. PR_OBJECT_TYPE
  834. }
  835. };
  836. static const SizedSPropTagArray(ieidMax, ptaEid_W)=
  837. {
  838. ieidMax,
  839. {
  840. PR_DISPLAY_NAME_W,
  841. PR_ENTRYID,
  842. PR_OBJECT_TYPE
  843. }
  844. };
  845. HRESULT CWab::HrFillComboWithPABNames(HWND hwnd, int* pcRows)
  846. {
  847. ULONG ulObjType = 0;
  848. LPMAPITABLE lpTable = NULL;
  849. LPSRowSet lpRow = NULL;
  850. LPABCONT lpContainer = NULL;
  851. HRESULT hr=NOERROR;
  852. ULONG cbEID=0;
  853. LPENTRYID lpEID = NULL;
  854. int cNumRows = 0;
  855. int nRows=0;
  856. LPSTR psz = NULL;
  857. LPWSTR lpwsz = NULL;
  858. #if defined(FIX_75835)
  859. COMBOBOXEXITEMW cbeiw;
  860. SSortOrderSet ssos;
  861. #endif
  862. if(NULL==hwnd || NULL==pcRows)
  863. return E_INVALIDARG;
  864. IF_FAILEXIT(hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID));
  865. IF_FAILEXIT(hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer));
  866. // Request UNICODE strings in table
  867. IF_FAILEXIT(hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS | MAPI_UNICODE, &lpTable));
  868. // We only care about a few columns
  869. IF_FAILEXIT(hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_W, 0));
  870. #if defined(FIX_75835)
  871. // Sort the list (synchronously) on display name as ComboBoxEx doesn't support CBS_SORT
  872. ssos.cCategories = ssos.cExpanded = 0;
  873. ssos.cSorts = 1;
  874. ssos.aSort[0].ulPropTag = PR_DISPLAY_NAME_W;
  875. ssos.aSort[0].ulOrder = TABLE_SORT_ASCEND;
  876. IF_FAILEXIT(hr = lpTable->SortTable(&ssos, 0));
  877. #endif
  878. // We will add the display names in order, starting with the first
  879. IF_FAILEXIT(hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL));
  880. nRows = 0;
  881. do
  882. {
  883. lpRow = NULL;
  884. hr = lpTable->QueryRows(1, 0, &lpRow);
  885. if(FAILED(hr))
  886. goto CleanLoop;
  887. cNumRows = lpRow->cRows;
  888. if(cNumRows)
  889. {
  890. // If we have a mailuser and their display name is valid
  891. if((lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_MAILUSER) &&
  892. (PROP_TYPE(lpRow->aRow[0].lpProps[ieidPR_DISPLAY_NAME].ulPropTag) != PT_ERROR))
  893. {
  894. lpwsz = lpRow->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszW;
  895. #if defined(FIX_75835)
  896. if(NULL != lpwsz)
  897. {
  898. // display name
  899. cbeiw.pszText = lpwsz;
  900. cbeiw.mask = CBEIF_TEXT;
  901. cbeiw.iItem = -1;
  902. SendMessage(hwnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbeiw);
  903. nRows++;
  904. }
  905. #else
  906. if (psz = PszToANSI(CP_ACP, lpwsz))
  907. {
  908. ComboBox_AddString(hwnd, (LPARAM)psz);
  909. MemFree(psz);
  910. }
  911. #endif
  912. }
  913. }
  914. CleanLoop:
  915. if(lpRow)
  916. FreeLPSRowSet(lpRow);
  917. }while(cNumRows);
  918. *pcRows = nRows;
  919. exit:
  920. ReleaseObj(lpTable);
  921. ReleaseObj(lpContainer);
  922. if(lpEID)
  923. m_lpWabObject->FreeBuffer(lpEID);
  924. return hr;
  925. }
  926. HRESULT CWab::HrFromIDToName(LPTSTR pszName, DWORD cchSize, ULONG cbEID, LPENTRYID lpEID)
  927. {
  928. ULONG ulObjType = 0, ulResult=0;
  929. LPMAPITABLE lpTable = NULL;
  930. LPSRowSet lpRow = NULL;
  931. LPABCONT lpContainer = NULL;
  932. ULONG cbEIDPAB = 0;
  933. LPENTRYID lpEIDPAB = NULL;
  934. HRESULT hr = NOERROR;
  935. int cNumRows = 0;
  936. int nRows = 0;
  937. if((0 == cbEID) || (NULL == lpEID) || (pszName == NULL))
  938. return E_INVALIDARG;
  939. pszName[0] = 0;
  940. hr = m_lpAdrBook->GetPAB(&cbEIDPAB, &lpEIDPAB);
  941. if(FAILED(hr))
  942. goto error;
  943. hr = m_lpAdrBook->OpenEntry(cbEIDPAB, (LPENTRYID)lpEIDPAB, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
  944. if(FAILED(hr))
  945. goto error;
  946. hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS, &lpTable);
  947. if(FAILED(hr))
  948. goto error;
  949. hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_A, 0);
  950. if(FAILED(hr))
  951. goto error;
  952. hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  953. if(FAILED(hr))
  954. goto error;
  955. nRows = 0;
  956. do
  957. {
  958. lpRow = NULL;
  959. hr = lpTable->QueryRows(1, 0, &lpRow);
  960. if(FAILED(hr))
  961. goto CleanLoop;
  962. cNumRows = lpRow->cRows;
  963. if(cNumRows)
  964. {
  965. if(lpRow->aRow[0].lpProps[2].Value.l == MAPI_MAILUSER)
  966. {
  967. hr=m_lpAdrBook->CompareEntryIDs(cbEID, (LPENTRYID)lpEID,
  968. lpRow->aRow[0].lpProps[1].Value.bin.cb,
  969. (LPENTRYID)lpRow->aRow[0].lpProps[1].Value.bin.lpb, 0, &ulResult);
  970. if ( (!FAILED(hr)) && ulResult &&
  971. PROP_TYPE(lpRow->aRow[0].lpProps[0].ulPropTag) != PT_ERROR )
  972. {
  973. StrCpyN(pszName, lpRow->aRow[0].lpProps[0].Value.lpszA, cchSize);
  974. goto CleanLoop;
  975. }
  976. }
  977. }
  978. CleanLoop:
  979. if(lpRow)
  980. {
  981. FreeLPSRowSet(lpRow);
  982. lpRow = NULL;
  983. }
  984. if(FAILED(hr))
  985. goto error;
  986. if (pszName[0])
  987. break;
  988. }while(cNumRows);
  989. if (pszName[0] == 0)
  990. hr = E_FAIL;
  991. error:
  992. ReleaseObj(lpTable);
  993. ReleaseObj(lpContainer);
  994. if(lpEIDPAB)
  995. m_lpWabObject->FreeBuffer(lpEIDPAB);
  996. return hr;
  997. }
  998. HRESULT CWab::HrFromNameToIDs(LPCTSTR lpszVCardName, ULONG* pcbEID, LPENTRYID* lppEID)
  999. {
  1000. ULONG ulObjType = 0;
  1001. LPMAPITABLE lpTable = NULL;
  1002. LPSRowSet lpRow = NULL;
  1003. LPABCONT lpContainer = NULL;
  1004. HRESULT hr = NOERROR;
  1005. ULONG cbEID = 0, cbEIDFound = 0;
  1006. LPENTRYID lpEID = NULL, lpEIDFound = NULL;
  1007. int cNumRows = 0;
  1008. int nRows = 0;
  1009. LPTSTR lpsz = NULL;
  1010. BOOL fFound = FALSE;
  1011. if(NULL==pcbEID || NULL==lppEID)
  1012. return E_INVALIDARG;
  1013. *pcbEID = NULL;
  1014. *lppEID = NULL;
  1015. hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
  1016. if(FAILED(hr))
  1017. goto error;
  1018. hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
  1019. if(FAILED(hr))
  1020. goto error;
  1021. hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS, &lpTable);
  1022. if(FAILED(hr))
  1023. goto error;
  1024. hr =lpTable->SetColumns((LPSPropTagArray)&ptaEid_A, 0);
  1025. if(FAILED(hr))
  1026. goto error;
  1027. hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  1028. if(FAILED(hr))
  1029. goto error;
  1030. nRows = 0;
  1031. do
  1032. {
  1033. lpRow = NULL;
  1034. hr = lpTable->QueryRows(1, 0, &lpRow);
  1035. if(FAILED(hr))
  1036. goto CleanLoop;
  1037. cNumRows = lpRow->cRows;
  1038. if(cNumRows)
  1039. {
  1040. if(lpRow->aRow[0].lpProps[2].Value.l == MAPI_MAILUSER)
  1041. {
  1042. lpsz = lpRow->aRow[0].lpProps[0].Value.lpszA; //display name
  1043. if( PROP_TYPE(lpRow->aRow[0].lpProps[0].ulPropTag) != PT_ERROR &&
  1044. lpsz &&
  1045. 0 == lstrcmp(lpsz, lpszVCardName) )
  1046. {
  1047. cbEIDFound = lpRow->aRow[0].lpProps[1].Value.bin.cb;
  1048. lpEIDFound = (LPENTRYID)lpRow->aRow[0].lpProps[1].Value.bin.lpb;
  1049. if(0!=cbEIDFound && NULL!=lpEIDFound)
  1050. {
  1051. *lppEID = (LPENTRYID)LpbWabBinaryDup(m_lpWabObject, (LPBYTE)lpEIDFound, cbEIDFound, NULL);
  1052. if(NULL == *lppEID)
  1053. {
  1054. hr = E_OUTOFMEMORY;
  1055. goto CleanLoop;
  1056. }
  1057. *pcbEID = cbEIDFound;
  1058. fFound = TRUE;
  1059. }
  1060. else
  1061. hr = E_FAIL;
  1062. goto CleanLoop;
  1063. }
  1064. }
  1065. }
  1066. CleanLoop:
  1067. if(lpRow)
  1068. {
  1069. FreeLPSRowSet(lpRow);
  1070. lpRow = NULL;
  1071. }
  1072. if(FAILED(hr))
  1073. goto error;
  1074. if(fFound)
  1075. break;
  1076. }while(cNumRows);
  1077. if(!fFound)
  1078. hr = E_FAIL;
  1079. error:
  1080. ReleaseObj(lpTable);
  1081. ReleaseObj(lpContainer);
  1082. if(lpEID)
  1083. m_lpWabObject->FreeBuffer(lpEID);
  1084. return hr;
  1085. }
  1086. const static SizedSPropTagArray(4, Cols)=
  1087. {
  1088. 4,
  1089. {
  1090. PR_DISPLAY_NAME_W,
  1091. PR_EMAIL_ADDRESS_W,
  1092. PR_NICKNAME_W,
  1093. PR_ENTRYID,
  1094. }
  1095. };
  1096. HRESULT CWab::HrGetPABTable(LPMAPITABLE* ppTable)
  1097. {
  1098. ULONG ulObjType = 0;
  1099. LPMAPITABLE lpTable = NULL;
  1100. LPABCONT lpContainer = NULL;
  1101. ULONG cbEID = 0;
  1102. LPENTRYID lpEID = NULL;
  1103. HRESULT hr;
  1104. if(NULL == ppTable)
  1105. return E_INVALIDARG;
  1106. *ppTable = NULL;
  1107. hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
  1108. if(FAILED(hr))
  1109. goto error;
  1110. hr = m_lpAdrBook->OpenEntry(cbEID, (LPENTRYID)lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpContainer);
  1111. if(FAILED(hr))
  1112. goto error;
  1113. hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS|MAPI_UNICODE, &lpTable);
  1114. if(FAILED(hr))
  1115. goto error;
  1116. hr =lpTable->SetColumns((LPSPropTagArray)&Cols, 0);
  1117. if(FAILED(hr))
  1118. goto error;
  1119. *ppTable = lpTable;
  1120. lpTable = NULL;//avoid releasing it.
  1121. error:
  1122. ReleaseObj(lpTable);
  1123. ReleaseObj(lpContainer);
  1124. if(lpEID)
  1125. m_lpWabObject->FreeBuffer(lpEID);
  1126. return hr;
  1127. }
  1128. HRESULT CWab::SearchPABTable(LPMAPITABLE lpTable, LPWSTR pszValue, LPWSTR pszFound, INT cch)
  1129. {
  1130. LPSRowSet lpRow = NULL;
  1131. SRestriction Res;
  1132. SPropValue propSearch;
  1133. HRESULT hr=E_FAIL;
  1134. int cNumRows = 0;
  1135. if(NULL==lpTable || NULL==pszValue || NULL==*pszValue || NULL==pszFound)
  1136. return E_INVALIDARG;
  1137. ZeroMemory(&Res, sizeof(SRestriction));
  1138. ZeroMemory(&propSearch, sizeof(SPropValue));
  1139. *pszFound = 0;
  1140. for(int i = 0; i < (int)(Cols.cValues - 1); i++)
  1141. {
  1142. propSearch.ulPropTag = Cols.aulPropTag[i];
  1143. propSearch.Value.lpszW = pszValue;
  1144. Res.rt = RES_CONTENT;
  1145. Res.res.resContent.ulFuzzyLevel = FL_IGNORECASE | FL_PREFIX;
  1146. Res.res.resContent.ulPropTag = propSearch.ulPropTag;
  1147. Res.res.resContent.lpProp = &propSearch;
  1148. hr = lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  1149. if(FAILED(hr))
  1150. return hr;
  1151. do
  1152. {
  1153. hr = lpTable->FindRow(&Res, BOOKMARK_CURRENT, NULL);
  1154. if(FAILED(hr))
  1155. break;
  1156. lpRow = NULL;
  1157. cNumRows = 0;
  1158. lpTable->QueryRows(1, 0, &lpRow);
  1159. if(lpRow)
  1160. {
  1161. cNumRows = lpRow->cRows;
  1162. if(cNumRows)
  1163. {
  1164. LPWSTR lpsz = lpRow->aRow[0].lpProps[i].Value.lpszW;
  1165. if(lstrlenW(lpsz) > 0)
  1166. {
  1167. if(*pszFound == 0 || StrCmpIW(lpsz, pszFound) < 0)
  1168. StrCpyNW(pszFound, lpsz, cch);
  1169. }
  1170. }
  1171. FreeLPSRowSet(lpRow);
  1172. }
  1173. } while(i!=0 && cNumRows);
  1174. if(*pszFound)
  1175. break;
  1176. }
  1177. return hr;
  1178. }
  1179. HRESULT CWab::HrCreateVCardFile(LPCTSTR lpszVCardName, LPCTSTR lpszFileName)
  1180. {
  1181. ULONG ulObjType = 0;
  1182. HRESULT hr=NOERROR;
  1183. ULONG cbEID=0;
  1184. LPENTRYID lpEID = NULL;
  1185. LPMAILUSER lpMailUser = NULL;
  1186. if(NULL==lpszVCardName || NULL==lpszFileName)
  1187. return E_INVALIDARG;
  1188. hr = HrFromNameToIDs(lpszVCardName, &cbEID, &lpEID);
  1189. if(FAILED(hr))
  1190. goto error;
  1191. hr = m_lpAdrBook->OpenEntry(cbEID, lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&lpMailUser);
  1192. if(FAILED(hr))
  1193. goto error;
  1194. hr = m_lpWabObject->VCardCreate(m_lpAdrBook, 0, (LPTSTR)lpszFileName, lpMailUser);
  1195. if(FAILED(hr))
  1196. goto error;
  1197. error:
  1198. ReleaseObj(lpMailUser);
  1199. if(lpEID)
  1200. m_lpWabObject->FreeBuffer(lpEID);
  1201. return hr;
  1202. }
  1203. HRESULT CWab::HrNewEntry(HWND hwnd, LPTSTR pszName, DWORD cchSize)
  1204. {
  1205. ULONG cbEID=0, cbEIDRet=0;
  1206. LPENTRYID lpEID = NULL, lpEIDRet = NULL;
  1207. HRESULT hr=NOERROR;
  1208. hr = m_lpAdrBook->GetPAB(&cbEID, &lpEID);
  1209. if(FAILED(hr))
  1210. goto error;
  1211. hr = m_lpAdrBook->NewEntry((ULONG_PTR)hwnd, 0, cbEID, lpEID, 0, NULL, &cbEIDRet, &lpEIDRet);
  1212. if(FAILED(hr))
  1213. goto error;
  1214. HrFromIDToName(pszName, cchSize, cbEIDRet, lpEIDRet);
  1215. error:
  1216. if(lpEID)
  1217. m_lpWabObject->FreeBuffer(lpEID);
  1218. if(lpEIDRet)
  1219. m_lpWabObject->FreeBuffer(lpEIDRet);
  1220. return hr;
  1221. }
  1222. LRESULT CWab::WabSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1223. {
  1224. CWab *pWab;
  1225. HWND hwndActive;
  1226. LRESULT lResult;
  1227. pWab = (CWab *)GetProp(hwnd, c_szOEThis);
  1228. if (!pWab)
  1229. return 0;
  1230. switch (uMsg)
  1231. {
  1232. case WM_NCDESTROY:
  1233. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)pWab->m_pfnWabWndProc);
  1234. RemoveProp(hwnd, c_szOEThis);
  1235. RemoveProp(hwnd, c_szOETopLevel);
  1236. lResult = CallWindowProc(pWab->m_pfnWabWndProc, hwnd, uMsg, wParam, lParam);
  1237. pWab->Release();
  1238. // bug #59420, can't freelibrary the wab inside the wndproc
  1239. PostMessage(g_hwndInit, ITM_WAB_CO_DECREMENT, 0, 0);
  1240. return lResult;
  1241. case WM_ENABLE:
  1242. if (!pWab->m_fInternal)
  1243. {
  1244. Assert (wParam || (pWab->m_hlDisabled.cHwnd == NULL && pWab->m_hlDisabled.rgHwnd == NULL));
  1245. EnableThreadWindows(&pWab->m_hlDisabled, (0 != wParam), ETW_OE_WINDOWS_ONLY, hwnd);
  1246. g_hwndActiveModal = wParam ? NULL : hwnd;
  1247. }
  1248. break;
  1249. case WM_OE_ENABLETHREADWINDOW:
  1250. pWab->m_fInternal = 1;
  1251. EnableWindow(hwnd, (BOOL)wParam);
  1252. pWab->m_fInternal = 0;
  1253. break;
  1254. case WM_OE_ACTIVATETHREADWINDOW:
  1255. hwndActive = GetLastActivePopup(hwnd);
  1256. if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive))
  1257. ActivatePopupWindow(hwndActive);
  1258. break;
  1259. case WM_ACTIVATEAPP:
  1260. if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd &&
  1261. !IsWindowEnabled(hwnd))
  1262. {
  1263. // $MODAL
  1264. // if we are getting activated, and are disabled then
  1265. // bring our 'active' window to the top
  1266. Assert (IsWindow(g_hwndActiveModal));
  1267. PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0);
  1268. }
  1269. break;
  1270. }
  1271. return CallWindowProc(pWab->m_pfnWabWndProc, hwnd, uMsg, wParam, lParam);
  1272. }
  1273. HRESULT CWab::HrEditEntry(HWND hwnd, LPTSTR pszName, DWORD cchSize)
  1274. {
  1275. ULONG cbEID = 0;
  1276. LPENTRYID lpEID = NULL;
  1277. HRESULT hr = NOERROR;
  1278. if(NULL == pszName)
  1279. return E_INVALIDARG;
  1280. hr = HrFromNameToIDs(pszName, &cbEID, &lpEID);
  1281. if(FAILED(hr))
  1282. goto error;
  1283. hr=m_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, cbEID, lpEID, NULL, NULL, NULL, DIALOG_MODAL);
  1284. if(FAILED(hr))
  1285. goto error;
  1286. HrFromIDToName(pszName, cchSize, cbEID, lpEID);
  1287. error:
  1288. if(lpEID)
  1289. m_lpWabObject->FreeBuffer(lpEID);
  1290. return hr;
  1291. }
  1292. // =============================================================================
  1293. // HrCreateWabalObject
  1294. // =============================================================================
  1295. HRESULT HrCreateWabalObject (LPWABAL *lppWabal)
  1296. {
  1297. // Locals
  1298. HRESULT hr = S_OK;
  1299. // Check Params
  1300. Assert (lppWabal);
  1301. hr=HrInitWab(TRUE);
  1302. if (FAILED(hr))
  1303. return hr;
  1304. // Verify Globals
  1305. if (g_fWabLoaded == FALSE || g_fWabInit == FALSE)
  1306. {
  1307. return TRAPHR (hrWabNotLoaded);
  1308. }
  1309. // Enter Critical Section
  1310. EnterCriticalSection (&g_rWabCritSect);
  1311. // Verify globals
  1312. Assert (g_lpfnWabOpen && g_hWab32Dll && g_lpAdrBook && g_lpWabObject);
  1313. // Inst it
  1314. *lppWabal = new CWabal;
  1315. if (*lppWabal == NULL)
  1316. {
  1317. hr = TRAPHR (hrMemory);
  1318. goto exit;
  1319. }
  1320. exit:
  1321. // Leave Critical Section
  1322. LeaveCriticalSection (&g_rWabCritSect);
  1323. // Done
  1324. return hr;
  1325. }
  1326. // ===========================================================================
  1327. // CWabal::CWabal
  1328. // ===========================================================================
  1329. CWabal::CWabal ()
  1330. {
  1331. DOUT ("CWabal::CWabal");
  1332. m_cRef = 1;
  1333. m_cActualEntries = 0;
  1334. m_lpAdrList = NULL;
  1335. m_lpWabObject = g_lpWabObject;
  1336. m_lpWabObject->AddRef();
  1337. m_lpAdrBook = g_lpAdrBook;
  1338. m_lpAdrBook->AddRef();
  1339. m_cMemberEnum=0;
  1340. m_cMembers = 0;
  1341. m_lprwsMembers = NULL;
  1342. m_pMsg = NULL;
  1343. }
  1344. // ===========================================================================
  1345. // CWabal::CWabal
  1346. // ===========================================================================
  1347. CWabal::~CWabal ()
  1348. {
  1349. DOUT ("CWabal::~CWabal");
  1350. Reset ();
  1351. ReleaseWabObjects (m_lpWabObject, m_lpAdrBook);
  1352. }
  1353. // =============================================================================
  1354. // CWabal::AddRef
  1355. // =============================================================================
  1356. ULONG CWabal::AddRef (VOID)
  1357. {
  1358. DOUT("CWabal::AddRef %lx ==> %d", this, m_cRef+1);
  1359. return ++m_cRef;
  1360. }
  1361. // =============================================================================
  1362. // CWabal::Release
  1363. // =============================================================================
  1364. ULONG CWabal::Release (VOID)
  1365. {
  1366. DOUT("CWabal::Release %lx ==> %d", this, m_cRef-1);
  1367. if (--m_cRef == 0)
  1368. {
  1369. delete this;
  1370. return 0;
  1371. }
  1372. return m_cRef;
  1373. }
  1374. // =============================================================================
  1375. // CWabal::FVerifyState
  1376. // =============================================================================
  1377. BOOL CWabal::FVerifyState (VOID)
  1378. {
  1379. // We need these things !
  1380. if (m_lpWabObject == NULL || m_lpAdrBook == NULL)
  1381. {
  1382. Assert (FALSE);
  1383. return FALSE;
  1384. }
  1385. // Done
  1386. return TRUE;
  1387. }
  1388. // =============================================================================
  1389. // CWabal::HrAddEntry
  1390. // =============================================================================
  1391. HRESULT CWabal::HrAddEntryA(LPTSTR lpszDisplay, LPTSTR lpszAddress, LONG lRecipType)
  1392. {
  1393. LPWSTR pwszDisplay = NULL,
  1394. pwszAddress = NULL;
  1395. HRESULT hr = S_OK;
  1396. Assert(lpszDisplay);
  1397. IF_NULLEXIT(pwszDisplay = PszToUnicode(CP_ACP, lpszDisplay));
  1398. // If lpszAddress is null, we have an incomplete Entry. This is ok.
  1399. pwszAddress = PszToUnicode(CP_ACP, lpszAddress);
  1400. if (lpszAddress && !pwszAddress)
  1401. IF_NULLEXIT(NULL);
  1402. hr = HrAddEntry(pwszDisplay, pwszAddress, lRecipType);
  1403. exit:
  1404. MemFree(pwszDisplay);
  1405. MemFree(pwszAddress);
  1406. return hr;
  1407. }
  1408. HRESULT CWabal::HrAddEntry (LPWSTR lpwszDisplay, LPWSTR lpwszAddress, LONG lRecipType)
  1409. {
  1410. // Locals
  1411. HRESULT hr = S_OK;
  1412. ADRINFO rAdrInfo;
  1413. // Verify State
  1414. if (FVerifyState () == FALSE)
  1415. return TRAPHR (E_FAIL);
  1416. // Zero
  1417. ZeroMemory (&rAdrInfo, sizeof (ADRINFO));
  1418. // Set adrinfo items
  1419. rAdrInfo.lpwszDisplay = lpwszDisplay;
  1420. rAdrInfo.lpwszAddress = lpwszAddress;
  1421. rAdrInfo.lRecipType = lRecipType;
  1422. rAdrInfo.fDistList = FALSE;
  1423. if (lRecipType == MAPI_ORIG) {
  1424. rAdrInfo.pMsg = m_pMsg; // only on senders
  1425. }
  1426. // Do we need to grow m_lpAdrList ?
  1427. if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
  1428. {
  1429. // Lets grow my current address list by GROW_SIZE
  1430. CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
  1431. }
  1432. // Put new entry into m_cActualEntries
  1433. CHECKHR (hr = HrSetAdrEntry (m_lpWabObject, &m_lpAdrList->aEntries[m_cActualEntries], &rAdrInfo, 0));
  1434. // Increment actual entries
  1435. m_cActualEntries++;
  1436. exit:
  1437. // Done
  1438. return hr;
  1439. }
  1440. // =============================================================================
  1441. // CWabal::HrAddEntry
  1442. // =============================================================================
  1443. HRESULT CWabal::HrAddEntry (LPADRINFO lpAdrInfo, BOOL fCheckDupes)
  1444. {
  1445. // Locals
  1446. HRESULT hr = S_OK;
  1447. // Check Params
  1448. Assert (lpAdrInfo);
  1449. // Verify State
  1450. if (FVerifyState () == FALSE)
  1451. return TRAPHR (E_FAIL);
  1452. // Do we need to grow m_lpAdrList ?
  1453. if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
  1454. {
  1455. // Lets grow my current address list by GROW_SIZE
  1456. CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
  1457. }
  1458. BOOL fSameType,
  1459. fSameEmail;
  1460. if (fCheckDupes)
  1461. {
  1462. for(ULONG ul=0; ul<m_cActualEntries; ul++)
  1463. {
  1464. fSameType=fSameEmail=FALSE;
  1465. for(ULONG ulProp=0; ulProp<m_lpAdrList->aEntries[ul].cValues; ulProp++)
  1466. {
  1467. if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag==PR_EMAIL_ADDRESS_W &&
  1468. StrCmpIW(m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.lpszW, lpAdrInfo->lpwszAddress)==0)
  1469. fSameEmail=TRUE;
  1470. if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag==PR_RECIPIENT_TYPE &&
  1471. (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.l == lpAdrInfo->lRecipType))
  1472. fSameType=TRUE;
  1473. }
  1474. if (fSameEmail && fSameType)
  1475. {
  1476. DOUTL(4, " -- Already in cache");
  1477. return NOERROR;
  1478. }
  1479. }
  1480. DOUTL(4, " -- Adding.");
  1481. }
  1482. // Put new entry into m_cActualEntries
  1483. CHECKHR (hr = HrSetAdrEntry (m_lpWabObject, &m_lpAdrList->aEntries[m_cActualEntries], lpAdrInfo, 0));
  1484. // Increment actual entries
  1485. m_cActualEntries++;
  1486. exit:
  1487. // Done
  1488. return hr;
  1489. }
  1490. #define FOUND_ENTRYID 0x01
  1491. #define FOUND_DISTLIST 0x02
  1492. #define FOUND_EMAIL 0x04
  1493. // =============================================================================
  1494. // CWabal::ValidateForSending()
  1495. // =============================================================================
  1496. HRESULT CWabal::IsValidForSending()
  1497. {
  1498. DWORD dwMask = 0;
  1499. ADRENTRY *pAE = NULL;
  1500. if (m_cActualEntries == 0)
  1501. return hrNoRecipients;
  1502. // walk thro' the list and make sure everyone has an entry-id and email name
  1503. AssertSz(m_lpAdrList, "How can this be NULL with >0 entries?");
  1504. for (ULONG ul=0; ul < m_cActualEntries; ul++)
  1505. {
  1506. dwMask = 0;
  1507. pAE = &m_lpAdrList->aEntries[ul];
  1508. for (ULONG ulProp=0; ulProp < pAE->cValues; ulProp++)
  1509. {
  1510. switch (pAE->rgPropVals[ulProp].ulPropTag)
  1511. {
  1512. case PR_ENTRYID:
  1513. dwMask |= FOUND_ENTRYID;
  1514. break;
  1515. case PR_OBJECT_TYPE:
  1516. if (pAE->rgPropVals[ulProp].Value.l==MAPI_DISTLIST)
  1517. dwMask |= FOUND_DISTLIST;
  1518. break;
  1519. case PR_RECIPIENT_TYPE:
  1520. if ((pAE->rgPropVals[ulProp].Value.l==MAPI_ORIG) &&
  1521. (m_cActualEntries == 1))
  1522. return hrNoRecipients;
  1523. break;
  1524. case PR_EMAIL_ADDRESS:
  1525. case PR_EMAIL_ADDRESS_W:
  1526. dwMask |= FOUND_EMAIL;
  1527. break;
  1528. }
  1529. }
  1530. // Fail if we don't have and email address, or we don't have a distList and an entryID
  1531. if (!((dwMask & FOUND_EMAIL) || ((dwMask & FOUND_ENTRYID) && (dwMask & FOUND_DISTLIST))))
  1532. return hrEmptyRecipientAddress;
  1533. }
  1534. return S_OK;
  1535. }
  1536. // =============================================================================
  1537. // CWabal::HrCopyTo
  1538. // =============================================================================
  1539. HRESULT CWabal::HrCopyTo (LPWABAL lpWabal)
  1540. {
  1541. // Locals
  1542. HRESULT hr = S_OK;
  1543. ADRINFO rAdrInfo;
  1544. BOOL fFound;
  1545. // Reset the destination
  1546. lpWabal->Reset ();
  1547. // Iterate through addresses
  1548. fFound = FGetFirst (&rAdrInfo);
  1549. while (fFound)
  1550. {
  1551. // Add it into lpWabal
  1552. CHECKHR (hr = lpWabal->HrAddEntry (&rAdrInfo));
  1553. // Get the next address
  1554. fFound = FGetNext (&rAdrInfo);
  1555. }
  1556. exit:
  1557. // Done
  1558. return hr;
  1559. }
  1560. // =============================================================================
  1561. // CWabal::Reset
  1562. // =============================================================================
  1563. VOID CWabal::Reset (VOID)
  1564. {
  1565. // Are we ready
  1566. if (FVerifyState () == FALSE)
  1567. return;
  1568. // If we have an address list, blow it away
  1569. if (m_lpAdrList)
  1570. {
  1571. // Free propvals
  1572. for (ULONG i=0; i<m_lpAdrList->cEntries; i++)
  1573. m_lpWabObject->FreeBuffer (m_lpAdrList->aEntries[i].rgPropVals);
  1574. // Free Address List
  1575. m_lpWabObject->FreeBuffer (m_lpAdrList);
  1576. m_lpAdrList = NULL;
  1577. }
  1578. // Reset actual entries
  1579. m_cActualEntries = 0;
  1580. }
  1581. // =============================================================================
  1582. // CWabal::HrGetFirst
  1583. // =============================================================================
  1584. BOOL CWabal::FGetFirst (LPADRINFO lpAdrInfo)
  1585. {
  1586. // Verify State
  1587. if (FVerifyState () == FALSE)
  1588. return FALSE;
  1589. // Nothing in my list
  1590. if (m_lpAdrList == NULL || m_cActualEntries == 0)
  1591. return FALSE;
  1592. // Set cookie in addrinfo
  1593. lpAdrInfo->dwReserved = 0;
  1594. AdrEntryToAdrInfo(&m_lpAdrList->aEntries[lpAdrInfo->dwReserved], lpAdrInfo);
  1595. // Set associated message
  1596. lpAdrInfo->pMsg = (lpAdrInfo->lRecipType == MAPI_ORIG) ? m_pMsg : NULL;
  1597. return TRUE;
  1598. }
  1599. // =============================================================================
  1600. // CWabal::HrGetNext
  1601. // =============================================================================
  1602. BOOL CWabal::FGetNext (LPADRINFO lpAdrInfo)
  1603. {
  1604. // Verify State
  1605. if (FVerifyState () == FALSE)
  1606. return NULL;
  1607. // Go to next address
  1608. lpAdrInfo->dwReserved++;
  1609. // Anymore
  1610. if (lpAdrInfo->dwReserved >= m_cActualEntries)
  1611. return FALSE;
  1612. AdrEntryToAdrInfo(&m_lpAdrList->aEntries[lpAdrInfo->dwReserved], lpAdrInfo);
  1613. // Set associated message
  1614. lpAdrInfo->pMsg = (lpAdrInfo->lRecipType == MAPI_ORIG) ? m_pMsg : NULL;
  1615. // Done
  1616. return TRUE;
  1617. }
  1618. BOOL CWabal::FFindFirst(LPADRINFO lpAdrInfo, LONG lRecipType)
  1619. {
  1620. if (FGetFirst(lpAdrInfo))
  1621. do
  1622. if (lpAdrInfo->lRecipType==lRecipType)
  1623. return TRUE;
  1624. while(FGetNext(lpAdrInfo));
  1625. return FALSE;
  1626. }
  1627. // =============================================================================
  1628. // CWabal::LpGetNext
  1629. // =============================================================================
  1630. HRESULT CWabal::HrResolveNames (HWND hwndParent, BOOL fShowDialog)
  1631. {
  1632. // Locals
  1633. HRESULT hr = S_OK;
  1634. HCURSOR hcur=NULL;
  1635. HWND hwndFocus = GetFocus();
  1636. ULONG ulFlags = WAB_RESOLVE_USE_CURRENT_PROFILE | WAB_RESOLVE_ALL_EMAILS | WAB_RESOLVE_UNICODE;
  1637. // Have we been initialized
  1638. if (FVerifyState () == FALSE)
  1639. return TRAPHR (E_FAIL);
  1640. hcur = HourGlass();
  1641. if(g_pConMan && g_pConMan->IsGlobalOffline())
  1642. ulFlags |= WAB_RESOLVE_LOCAL_ONLY;
  1643. // BUG: 23760: ResolveNames pumps messages against an LDAP server
  1644. if (fShowDialog)
  1645. {
  1646. Assert(IsWindow(hwndParent));
  1647. EnableWindow(GetTopMostParent(hwndParent), FALSE);
  1648. ulFlags |= MAPI_DIALOG;
  1649. hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, ulFlags, NULL, m_lpAdrList);
  1650. EnableWindow(GetTopMostParent(hwndParent), TRUE);
  1651. //BUG: user can't put focus back on our dialog wnd for us as we disabled
  1652. // the window and the progress dialog got a wm_destroy before we return
  1653. // so we cache the focus and set ut back
  1654. if (hwndFocus)
  1655. SetFocus(hwndFocus);
  1656. }
  1657. else
  1658. hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, ulFlags, NULL, m_lpAdrList);
  1659. if (hcur)
  1660. SetCursor(hcur);
  1661. // Done
  1662. return hr;
  1663. }
  1664. // =============================================================================
  1665. // SzWabStringDup
  1666. // =============================================================================
  1667. LPTSTR SzWabStringDup (LPWABOBJECT lpWab, LPCTSTR pcsz, LPVOID lpParentObject)
  1668. {
  1669. // Locals
  1670. LPTSTR pszDup;
  1671. ULONG cb;
  1672. HRESULT hr;
  1673. Assert (lpWab);
  1674. if (pcsz == NULL)
  1675. return NULL;
  1676. INT nLen = lstrlen(pcsz) + 1;
  1677. cb = nLen * sizeof(TCHAR);
  1678. if (lpParentObject == NULL)
  1679. hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pszDup);
  1680. else
  1681. hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pszDup);
  1682. if (!FAILED (hr) && pszDup)
  1683. CopyMemory (pszDup, pcsz, cb);
  1684. return pszDup;
  1685. }
  1686. LPWSTR SzWabStringDupW(LPWABOBJECT lpWab, LPCWSTR pcwsz, LPVOID lpParentObject)
  1687. {
  1688. // Locals
  1689. LPWSTR pwszDup;
  1690. ULONG cb;
  1691. HRESULT hr;
  1692. Assert (lpWab);
  1693. if (pcwsz == NULL)
  1694. return NULL;
  1695. INT nLen = lstrlenW(pcwsz) + 1;
  1696. cb = nLen * sizeof(WCHAR);
  1697. if (lpParentObject == NULL)
  1698. hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pwszDup);
  1699. else
  1700. hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pwszDup);
  1701. if (!FAILED (hr) && pwszDup)
  1702. CopyMemory (pwszDup, pcwsz, cb);
  1703. return pwszDup;
  1704. }
  1705. // =============================================================================
  1706. // LpbWabBinaryDup
  1707. // =============================================================================
  1708. LPBYTE LpbWabBinaryDup(LPWABOBJECT lpWab, LPBYTE lpbSrc, ULONG cb, LPVOID lpParentObject)
  1709. {
  1710. // Locals
  1711. HRESULT hr;
  1712. LPBYTE pb=0;
  1713. Assert (lpWab);
  1714. Assert (lpbSrc);
  1715. if (lpParentObject == NULL)
  1716. hr = lpWab->AllocateBuffer (cb, (LPVOID *)&pb);
  1717. else
  1718. hr = lpWab->AllocateMore (cb, lpParentObject, (LPVOID *)&pb);
  1719. if (pb)
  1720. CopyMemory (pb, lpbSrc, cb);
  1721. return pb;
  1722. }
  1723. // =============================================================================
  1724. // CWabal::HrAddUnresolved
  1725. // =============================================================================
  1726. HRESULT CWabal::HrAddUnresolved(LPWSTR lpwszDisplayName, LONG lRecipType)
  1727. {
  1728. HRESULT hr=NOERROR;
  1729. ULONG cb;
  1730. LPADRENTRY lpAdrEntry;
  1731. ULONG cchDisplayName;
  1732. Assert(lpwszDisplayName);
  1733. // Do we need to grow m_lpAdrList ?
  1734. if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
  1735. {
  1736. // Lets grow my current address list by GROW_SIZE
  1737. CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
  1738. }
  1739. // Put new entry into m_cActualEntries
  1740. lpAdrEntry=&m_lpAdrList->aEntries[m_cActualEntries];
  1741. lpAdrEntry->cValues=2;
  1742. cchDisplayName = lstrlenW(lpwszDisplayName)+1;
  1743. cb = (2*sizeof(SPropValue)) + (cchDisplayName) * sizeof(WCHAR);
  1744. // Allocate some memory
  1745. hr = m_lpWabObject->AllocateBuffer (cb, (LPVOID *)&lpAdrEntry->rgPropVals);
  1746. // Alloc failed ?
  1747. if (FAILED (hr))
  1748. {
  1749. hr = TRAPHR (hrMemory);
  1750. goto exit;
  1751. }
  1752. // Set the Properties
  1753. lpAdrEntry->rgPropVals[0].ulPropTag = PR_DISPLAY_NAME_W;
  1754. lpAdrEntry->rgPropVals[0].Value.lpszW=(LPWSTR)((DWORD_PTR)(lpAdrEntry->rgPropVals) + (DWORD)(2*sizeof(SPropValue)));
  1755. StrCpyNW(lpAdrEntry->rgPropVals[0].Value.lpszW, lpwszDisplayName, cchDisplayName);
  1756. lpAdrEntry->rgPropVals[1].ulPropTag = PR_RECIPIENT_TYPE;
  1757. lpAdrEntry->rgPropVals[1].Value.l= lRecipType;
  1758. m_cActualEntries++;
  1759. exit:
  1760. // Done
  1761. return hr;
  1762. }
  1763. // =============================================================================
  1764. // HrSetAdrEntry
  1765. // =============================================================================
  1766. HRESULT HrSetAdrEntry (LPWABOBJECT lpWab, LPADRENTRY lpAdrEntry,
  1767. LPADRINFO lpAdrInfo, DWORD mask)
  1768. {
  1769. // Locals
  1770. HRESULT hr = S_OK;
  1771. ULONG cValues;
  1772. DWORD dwAlloc;
  1773. DWORD cMaskBits;
  1774. DWORD mask2;
  1775. // Allocate properties
  1776. Assert (lpAdrEntry->rgPropVals == NULL);
  1777. // BrettM laughed at me that I was passing the bit count into this function.
  1778. // So, lets count them
  1779. mask2 = mask;
  1780. for (cMaskBits=0; mask2; cMaskBits++)
  1781. mask2&=mask2-1;
  1782. // Allocate some memory
  1783. dwAlloc = ((cMaskBits) ? cMaskBits : AE_colLast) * sizeof (SPropValue);
  1784. hr = lpWab->AllocateBuffer (dwAlloc, (LPVOID *)&lpAdrEntry->rgPropVals);
  1785. // Alloc failed ?
  1786. if (FAILED (hr))
  1787. {
  1788. hr = TRAPHR (hrMemory);
  1789. goto exit;
  1790. }
  1791. // Zero init
  1792. ZeroMemory (lpAdrEntry->rgPropVals, dwAlloc);
  1793. // Set the Properties
  1794. // Init Properties ?
  1795. cValues = 0;
  1796. if (lpAdrInfo)
  1797. {
  1798. // If the mask is empty, then we're doing all properties;
  1799. // else, if the mask has the bit set, test for emptiness
  1800. // and bang in a default; else skip it
  1801. if (!mask || mask & AIM_DISPLAY)
  1802. {
  1803. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_DISPLAY_NAME_W;
  1804. if (FIsStringEmptyW(lpAdrInfo->lpwszDisplay))
  1805. {
  1806. LPWSTR pwszDisplay;
  1807. if (!FIsStringEmptyW(lpAdrInfo->lpwszAddress))
  1808. pwszDisplay = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddress, lpAdrEntry->rgPropVals);
  1809. else
  1810. {
  1811. WCHAR szUnknown[255];
  1812. AthLoadStringW(idsUnknown, szUnknown, ARRAYSIZE(szUnknown));
  1813. pwszDisplay = SzWabStringDupW(lpWab, szUnknown, lpAdrEntry->rgPropVals);
  1814. }
  1815. lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, pwszDisplay, lpAdrEntry->rgPropVals);
  1816. }
  1817. else
  1818. {
  1819. lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszDisplay, lpAdrEntry->rgPropVals);
  1820. }
  1821. cValues++;
  1822. }
  1823. if (!mask || mask & AIM_ADDRESS)
  1824. {
  1825. if (!FIsStringEmptyW(lpAdrInfo->lpwszAddress))
  1826. {
  1827. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_EMAIL_ADDRESS_W;
  1828. lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddress, lpAdrEntry->rgPropVals);
  1829. cValues++;
  1830. }
  1831. }
  1832. if (!mask || mask & AIM_ADDRTYPE)
  1833. {
  1834. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_ADDRTYPE_W;
  1835. if (FIsStringEmptyW(lpAdrInfo->lpwszAddrType))
  1836. lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, (LPWSTR)c_wszSMTP, lpAdrEntry->rgPropVals);
  1837. else
  1838. lpAdrEntry->rgPropVals[cValues].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszAddrType, lpAdrEntry->rgPropVals);
  1839. cValues++;
  1840. }
  1841. if (lpAdrInfo->lpwszSurName && (!mask || mask & AIM_SURNAME))
  1842. {
  1843. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_SURNAME_W;
  1844. lpAdrEntry->rgPropVals[cValues++].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszSurName, lpAdrEntry->rgPropVals);
  1845. }
  1846. if (lpAdrInfo->lpwszGivenName && (!mask || mask & AIM_GIVENNAME))
  1847. {
  1848. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_GIVEN_NAME_W;
  1849. lpAdrEntry->rgPropVals[cValues++].Value.lpszW = SzWabStringDupW(lpWab, lpAdrInfo->lpwszGivenName, lpAdrEntry->rgPropVals);
  1850. }
  1851. if (!mask || mask & AIM_RECIPTYPE)
  1852. {
  1853. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_RECIPIENT_TYPE;
  1854. lpAdrEntry->rgPropVals[cValues++].Value.l = lpAdrInfo->lRecipType;
  1855. }
  1856. if (lpAdrInfo->tbCertificate.pBlobData && (!mask || mask & AIM_CERTIFICATE))
  1857. {
  1858. ThumbprintToPropValue(&lpAdrEntry->rgPropVals[cValues],
  1859. &lpAdrInfo->tbCertificate,
  1860. &lpAdrInfo->blSymCaps,
  1861. lpAdrInfo->ftSigningTime,
  1862. lpAdrInfo->fDefCertificate);
  1863. cValues++;
  1864. }
  1865. if (lpAdrInfo->cbEID && (!mask || mask & AIM_EID))
  1866. {
  1867. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_ENTRYID;
  1868. lpAdrEntry->rgPropVals[cValues].Value.bin.cb = lpAdrInfo->cbEID;
  1869. lpAdrEntry->rgPropVals[cValues].Value.bin.lpb =
  1870. LpbWabBinaryDup(lpWab, lpAdrInfo->lpbEID, lpAdrInfo->cbEID, lpAdrEntry->rgPropVals);
  1871. if (lpAdrEntry->rgPropVals[cValues].Value.bin.lpb==NULL)
  1872. {
  1873. hr=E_OUTOFMEMORY;
  1874. goto exit;
  1875. }
  1876. cValues++;
  1877. }
  1878. if (!mask || mask & AIM_OBJECTTYPE)
  1879. {
  1880. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_OBJECT_TYPE;
  1881. lpAdrEntry->rgPropVals[cValues++].Value.l=lpAdrInfo->fDistList?MAPI_DISTLIST:MAPI_MAILUSER;
  1882. }
  1883. if (!mask || mask & AIM_INTERNETENCODING)
  1884. {
  1885. lpAdrEntry->rgPropVals[cValues].ulPropTag = PR_SEND_INTERNET_ENCODING;
  1886. lpAdrEntry->rgPropVals[cValues++].Value.l=lpAdrInfo->fPlainText?BODY_ENCODING_TEXT:BODY_ENCODING_TEXT_AND_HTML;
  1887. }
  1888. }
  1889. #ifdef DEBUG
  1890. if (cMaskBits && cValues > cMaskBits)
  1891. AssertSz(0, TEXT("Bad... the mask bits don't cover our mem usage"));
  1892. #endif
  1893. DOUTL(4, "HrSetAdrEntry: lRecip=%d", lpAdrInfo->lRecipType);
  1894. // Set number of values
  1895. // use cValues since we may have skipped some due to null params and therefore
  1896. // cMaskBits >= cValues (t-erikne)
  1897. lpAdrEntry->cValues = cValues;
  1898. exit:
  1899. // Done
  1900. return hr;
  1901. }
  1902. // =============================================================================
  1903. // CWabal::HrAllocAdrList
  1904. // =============================================================================
  1905. HRESULT CWabal::HrGrowAdrlist (LPADRLIST *lppalCurr, ULONG caeToAdd)
  1906. {
  1907. // Locals
  1908. HRESULT hr = S_OK;
  1909. ULONG i, j, cbNew, cbCurr = 0;
  1910. LPADRLIST lpalNew = NULL;
  1911. // Determine number of bytes needed
  1912. cbNew = sizeof(ADRLIST) + caeToAdd * sizeof(ADRENTRY);
  1913. // Determine number of entries currently in address list
  1914. if (*lppalCurr)
  1915. {
  1916. cbCurr = (UINT)((*lppalCurr)->cEntries * sizeof(ADRENTRY));
  1917. }
  1918. // Add current cb
  1919. cbNew += cbCurr;
  1920. // Allocate new buffer
  1921. hr = m_lpWabObject->AllocateBuffer (cbNew, (LPVOID *)&lpalNew);
  1922. if (FAILED (hr))
  1923. {
  1924. hr = TRAPHR (hrMemory);
  1925. goto exit;
  1926. }
  1927. // If current address list ?
  1928. if (*lppalCurr)
  1929. {
  1930. // Copy Current Address list into new address list
  1931. CopyMemory (lpalNew, *lppalCurr, sizeof (ADRLIST) + cbCurr);
  1932. // Free current buffer
  1933. m_lpWabObject->FreeBuffer (*lppalCurr);
  1934. // Reset pointer
  1935. *lppalCurr = NULL;
  1936. }
  1937. else
  1938. lpalNew->cEntries = 0;
  1939. // Update entries count
  1940. //N seems like we don't need j, just offset the i count by this much?
  1941. j = lpalNew->cEntries;
  1942. lpalNew->cEntries += caeToAdd;
  1943. // Mark new ADRENTRY's as empty and allocate the propvalue array
  1944. for (i=0; i<caeToAdd; i++)
  1945. {
  1946. // Zero init adrentry
  1947. ZeroMemory (&lpalNew->aEntries[j+i], sizeof (ADRENTRY));
  1948. }
  1949. // Assume new pointer
  1950. *lppalCurr = lpalNew;
  1951. exit:
  1952. // Done
  1953. return hr;
  1954. }
  1955. void CWabal::AdrEntryToAdrInfo(LPADRENTRY lpAdrEntry, LPADRINFO lpAdrInfo)
  1956. {
  1957. ULONG ul,
  1958. cValues;
  1959. LPSPropValue ppv;
  1960. //N look at some kind of {} init
  1961. lpAdrInfo->lpwszAddress = NULL;
  1962. lpAdrInfo->lpwszAddrType = NULL;
  1963. lpAdrInfo->lpwszDisplay = NULL;
  1964. lpAdrInfo->lpwszSurName = NULL;
  1965. lpAdrInfo->lpwszGivenName = NULL;
  1966. lpAdrInfo->lRecipType = -1;
  1967. lpAdrInfo->fResolved = FALSE;
  1968. lpAdrInfo->fDistList = FALSE;
  1969. lpAdrInfo->fPlainText = FALSE;
  1970. lpAdrInfo->fDefCertificate = FALSE;
  1971. lpAdrInfo->tbCertificate.pBlobData = (BYTE*)0;
  1972. lpAdrInfo->tbCertificate.cbSize = 0;
  1973. lpAdrInfo->blSymCaps.pBlobData = (BYTE*)0;
  1974. lpAdrInfo->blSymCaps.cbSize = 0;
  1975. lpAdrInfo->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime = 0;
  1976. lpAdrInfo->cbEID=0;
  1977. lpAdrInfo->lpbEID=0;
  1978. cValues=lpAdrEntry->cValues;
  1979. AssertSz(cValues, "An empty addrentry?");
  1980. ppv=lpAdrEntry->rgPropVals;
  1981. for(ul=0; ul<cValues; ul++, ppv++)
  1982. PropValToAdrInfo(ppv, lpAdrInfo);
  1983. DOUTL(4, "AddrEntry2AddrInfo: lRecip=%d", lpAdrInfo->lRecipType);
  1984. AssertSz(lpAdrInfo->lpwszAddress==NULL ||
  1985. lpAdrInfo->lRecipType != -1, "A resolved entry should have a recip type!");
  1986. }
  1987. HRESULT CWab::HrDetails(HWND hwndOwner, LPADRINFO *lplpAdrInfo)
  1988. {
  1989. HRESULT hr;
  1990. HWND hwnd=hwndOwner;
  1991. LPADRINFO lpAdrInfoNew=0;
  1992. ADRINFO adrInfo;
  1993. LPMAPIPROP pmp=0;
  1994. LPSPropValue ppv=0;
  1995. ULONG ul;
  1996. HCURSOR hcur=NULL;
  1997. SizedSPropTagArray(2, tagNewProps)=
  1998. {2, {PR_EMAIL_ADDRESS_W, PR_DISPLAY_NAME_W}};
  1999. if (!m_lpAdrBook)
  2000. return E_FAIL;
  2001. if (!lplpAdrInfo || !*lplpAdrInfo)
  2002. return E_INVALIDARG;
  2003. hcur = HourGlass();
  2004. hr=m_lpAdrBook->Details((ULONG_PTR *)&hwnd, NULL, NULL, (*lplpAdrInfo)->cbEID, (LPENTRYID)(*lplpAdrInfo)->lpbEID, NULL, NULL, NULL, 0);
  2005. // re-read the props that may have changed...
  2006. CopyMemory(&adrInfo, *lplpAdrInfo, sizeof(ADRINFO));
  2007. hr=m_lpAdrBook->OpenEntry((*lplpAdrInfo)->cbEID, (LPENTRYID)(*lplpAdrInfo)->lpbEID,
  2008. &IID_IMAPIProp, 0, &ul, (LPUNKNOWN *)&pmp);
  2009. if (FAILED(hr))
  2010. goto error;
  2011. hr=pmp->GetProps((LPSPropTagArray)&tagNewProps, 0, &ul, &ppv);
  2012. if (FAILED(hr))
  2013. goto error;
  2014. adrInfo.lpwszAddress = ppv[0].ulPropTag == PR_EMAIL_ADDRESS_W ? ppv[0].Value.lpszW : NULL;
  2015. adrInfo.lpwszDisplay = ppv[1].ulPropTag == PR_DISPLAY_NAME_W ? ppv[1].Value.lpszW : NULL;
  2016. hr=HrDupeAddrInfo(&adrInfo, &lpAdrInfoNew);
  2017. if (FAILED(hr))
  2018. goto error;
  2019. // release the old, and replace with the new
  2020. MemFree(*lplpAdrInfo);
  2021. *lplpAdrInfo=lpAdrInfoNew;
  2022. error:
  2023. ReleaseObj(pmp);
  2024. if (ppv)
  2025. m_lpWabObject->FreeBuffer(ppv);
  2026. if (hcur)
  2027. SetCursor(hcur);
  2028. return hr;
  2029. }
  2030. HRESULT HrDupeAddrInfo(LPADRINFO lpAdrInfo, LPADRINFO *lplpAdrInfo)
  2031. {
  2032. ULONG cb=0;
  2033. LPBYTE pb;
  2034. if (!lpAdrInfo || !lplpAdrInfo)
  2035. return E_INVALIDARG;
  2036. *lplpAdrInfo=NULL;
  2037. cb=CbAdrInfoSize(lpAdrInfo);
  2038. #ifdef _WIN64
  2039. cb = LcbAlignLcb(cb);
  2040. #endif
  2041. if (!MemAlloc((LPVOID *)lplpAdrInfo, cb))
  2042. return E_OUTOFMEMORY;
  2043. ZeroMemory(*lplpAdrInfo, cb);
  2044. pb=(LPBYTE)*lplpAdrInfo + sizeof(ADRINFO);
  2045. #ifdef _WIN64
  2046. pb = MyPbAlignPb(pb);
  2047. #endif // _WIN64
  2048. if (lpAdrInfo->lpwszAddress)
  2049. {
  2050. StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszAddress, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
  2051. (*lplpAdrInfo)->lpwszAddress=(LPWSTR)pb;
  2052. pb+=(lstrlenW(lpAdrInfo->lpwszAddress)+1)*sizeof(WCHAR);
  2053. #ifdef _WIN64
  2054. pb = MyPbAlignPb(pb);
  2055. #endif // _WIN64
  2056. }
  2057. if (lpAdrInfo->lpwszDisplay)
  2058. {
  2059. StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszDisplay, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
  2060. (*lplpAdrInfo)->lpwszDisplay=(LPWSTR)pb;
  2061. pb+=(lstrlenW(lpAdrInfo->lpwszDisplay)+1)*sizeof(WCHAR);
  2062. #ifdef _WIN64
  2063. pb = MyPbAlignPb(pb);
  2064. #endif // _WIN64
  2065. }
  2066. if (lpAdrInfo->lpwszAddrType)
  2067. {
  2068. StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszAddrType, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
  2069. (*lplpAdrInfo)->lpwszAddrType=(LPWSTR)pb;
  2070. pb+=(lstrlenW(lpAdrInfo->lpwszAddrType)+1)*sizeof(WCHAR);
  2071. #ifdef _WIN64
  2072. pb = MyPbAlignPb(pb);
  2073. #endif // _WIN64
  2074. }
  2075. if (lpAdrInfo->lpwszSurName)
  2076. {
  2077. StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszSurName, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
  2078. (*lplpAdrInfo)->lpwszSurName=(LPWSTR)pb;
  2079. pb+=(lstrlenW(lpAdrInfo->lpwszSurName)+1)*sizeof(WCHAR);
  2080. #ifdef _WIN64
  2081. pb = MyPbAlignPb(pb);
  2082. #endif // _WIN64
  2083. }
  2084. if (lpAdrInfo->lpwszGivenName)
  2085. {
  2086. StrCpyNW((LPWSTR)pb, lpAdrInfo->lpwszGivenName, (cb - (pb - (LPBYTE)*lplpAdrInfo))/sizeof(WCHAR));
  2087. (*lplpAdrInfo)->lpwszGivenName=(LPWSTR)pb;
  2088. pb+=(lstrlenW(lpAdrInfo->lpwszGivenName)+1)*sizeof(WCHAR);
  2089. #ifdef _WIN64
  2090. pb = MyPbAlignPb(pb);
  2091. #endif // _WIN64
  2092. }
  2093. // Certificate properties
  2094. (*lplpAdrInfo)->tbCertificate.cbSize = lpAdrInfo->tbCertificate.cbSize;
  2095. (*lplpAdrInfo)->tbCertificate.pBlobData = lpAdrInfo->tbCertificate.pBlobData;
  2096. (*lplpAdrInfo)->blSymCaps.cbSize = lpAdrInfo->blSymCaps.cbSize;
  2097. (*lplpAdrInfo)->blSymCaps.pBlobData = lpAdrInfo->blSymCaps.pBlobData;
  2098. (*lplpAdrInfo)->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwLowDateTime;
  2099. (*lplpAdrInfo)->ftSigningTime.dwHighDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime;
  2100. (*lplpAdrInfo)->fDefCertificate = lpAdrInfo->fDefCertificate;
  2101. (*lplpAdrInfo)->lRecipType=lpAdrInfo->lRecipType;
  2102. (*lplpAdrInfo)->fResolved=lpAdrInfo->fResolved;
  2103. (*lplpAdrInfo)->fDistList=lpAdrInfo->fDistList;
  2104. (*lplpAdrInfo)->fPlainText=lpAdrInfo->fPlainText;
  2105. (*lplpAdrInfo)->pMsg =lpAdrInfo->pMsg;
  2106. if (lpAdrInfo->cbEID)
  2107. {
  2108. (*lplpAdrInfo)->lpbEID=(LPBYTE)pb;
  2109. (*lplpAdrInfo)->cbEID=lpAdrInfo->cbEID;
  2110. CopyMemory(pb, lpAdrInfo->lpbEID, lpAdrInfo->cbEID);
  2111. }
  2112. return NOERROR;
  2113. }
  2114. ULONG CbAdrInfoSize(LPADRINFO lpAdrInfo)
  2115. {
  2116. ULONG cb=sizeof(ADRINFO);
  2117. #ifdef _WIN64
  2118. cb = LcbAlignLcb(cb);
  2119. #endif
  2120. Assert(lpAdrInfo);
  2121. if (lpAdrInfo->lpwszAddress)
  2122. {
  2123. cb+=(lstrlenW(lpAdrInfo->lpwszAddress)+1)*sizeof(WCHAR);
  2124. #ifdef _WIN64
  2125. cb = LcbAlignLcb(cb);
  2126. #endif
  2127. }
  2128. if (lpAdrInfo->lpwszDisplay)
  2129. {
  2130. cb+=(lstrlenW(lpAdrInfo->lpwszDisplay)+1)*sizeof(WCHAR);
  2131. #ifdef _WIN64
  2132. cb = LcbAlignLcb(cb);
  2133. #endif
  2134. }
  2135. if (lpAdrInfo->lpwszAddrType)
  2136. {
  2137. cb+=(lstrlenW(lpAdrInfo->lpwszAddrType)+1)*sizeof(WCHAR);
  2138. #ifdef _WIN64
  2139. cb = LcbAlignLcb(cb);
  2140. #endif
  2141. }
  2142. if (lpAdrInfo->lpwszSurName)
  2143. {
  2144. cb+=(lstrlenW(lpAdrInfo->lpwszSurName)+1)*sizeof(WCHAR);
  2145. #ifdef _WIN64
  2146. cb = LcbAlignLcb(cb);
  2147. #endif
  2148. }
  2149. if (lpAdrInfo->lpwszGivenName)
  2150. {
  2151. cb+=(lstrlenW(lpAdrInfo->lpwszGivenName)+1)*sizeof(WCHAR);
  2152. #ifdef _WIN64
  2153. cb = LcbAlignLcb(cb);
  2154. #endif
  2155. }
  2156. cb+=lpAdrInfo->cbEID;
  2157. return cb;
  2158. }
  2159. void SerialAdrInfoString(LPWSTR *ppwszDest, ULONG cchDest, LPWSTR pwszSrc, ULONG *pcbOff, LPBYTE *ppbData)
  2160. {
  2161. ULONG cb;
  2162. if (pwszSrc)
  2163. {
  2164. (*ppwszDest)=(LPWSTR)((ULONG_PTR)(*pcbOff));
  2165. StrCpyNW((LPWSTR)(*ppbData), pwszSrc, cchDest);
  2166. cb=(lstrlenW(pwszSrc)+1)*sizeof(WCHAR);
  2167. (*ppbData)+=cb;
  2168. (*pcbOff)+=cb;
  2169. }
  2170. }
  2171. HRESULT HrCreateWabalObjectFromHGlobal(HGLOBAL hGlobal, LPWABAL *lplpWabal)
  2172. {
  2173. HRESULT hr;
  2174. LPWABAL lpWabal=0;
  2175. LPADRINFOLIST lpAdrInfoList;
  2176. LPADRINFOLIST lpAdrInfoListNew;
  2177. LPADRINFO lpAdrInfo;
  2178. ULONG cb,
  2179. uRow;
  2180. if (!lplpWabal)
  2181. return E_INVALIDARG;
  2182. if (!hGlobal)
  2183. return E_INVALIDARG;
  2184. hr=HrCreateWabalObject(&lpWabal);
  2185. if (FAILED(hr))
  2186. return hr;
  2187. cb = (ULONG) GlobalSize(hGlobal);
  2188. // create a new 'unflattened' addr info list
  2189. if (!MemAlloc((LPVOID *)&lpAdrInfoListNew, cb))
  2190. return E_OUTOFMEMORY;
  2191. ZeroMemory(lpAdrInfoListNew, cb);
  2192. lpAdrInfoList=(LPADRINFOLIST)GlobalLock(hGlobal);
  2193. if (!lpAdrInfoList)
  2194. {
  2195. MemFree(lpAdrInfoListNew);
  2196. return E_FAIL;
  2197. }
  2198. // copy the flat data
  2199. CopyMemory(lpAdrInfoListNew, lpAdrInfoList, cb);
  2200. lpAdrInfoListNew->rgAdrInfo=(LPADRINFO)((DWORD_PTR)lpAdrInfoListNew->rgAdrInfo + (DWORD_PTR)lpAdrInfoListNew);
  2201. lpAdrInfo=lpAdrInfoListNew->rgAdrInfo;
  2202. // patch the pointers...
  2203. for(uRow=0; uRow<lpAdrInfoListNew->cValues; uRow++, lpAdrInfo++)
  2204. {
  2205. // All the address offsets are in bytes. Make sure we convert to chars.
  2206. if (lpAdrInfo->lpwszAddress)
  2207. lpAdrInfo->lpwszAddress += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
  2208. if (lpAdrInfo->lpwszDisplay)
  2209. lpAdrInfo->lpwszDisplay += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
  2210. if (lpAdrInfo->lpwszAddrType)
  2211. lpAdrInfo->lpwszAddrType += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
  2212. if (lpAdrInfo->lpwszSurName)
  2213. lpAdrInfo->lpwszSurName += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
  2214. if (lpAdrInfo->lpwszGivenName)
  2215. lpAdrInfo->lpwszGivenName += (DWORD_PTR)lpAdrInfoListNew/sizeof(WCHAR);
  2216. if (lpAdrInfo->lpbEID)
  2217. lpAdrInfo->lpbEID+=(DWORD_PTR)lpAdrInfoListNew;
  2218. }
  2219. // now add it all to the wabal
  2220. lpAdrInfo=lpAdrInfoListNew->rgAdrInfo;
  2221. for(uRow=0; uRow<lpAdrInfoListNew->cValues; uRow++, lpAdrInfo++)
  2222. {
  2223. if (lpAdrInfo->fResolved)
  2224. lpWabal->HrAddEntry(lpAdrInfo);
  2225. else
  2226. lpWabal->HrAddUnresolved(lpAdrInfo->lpwszDisplay, -1);
  2227. }
  2228. *lplpWabal=lpWabal;
  2229. GlobalUnlock(hGlobal);
  2230. MemFree(lpAdrInfoListNew);
  2231. return NOERROR;
  2232. }
  2233. HRESULT CWabal::HrBuildHGlobal(HGLOBAL *phGlobal)
  2234. {
  2235. HGLOBAL hGlobal=0;
  2236. ADRINFO adrInfo;
  2237. ULONG cbAlloc,
  2238. #ifdef DEBUG
  2239. cFound=0,
  2240. #endif
  2241. cb;
  2242. LPADRINFOLIST lpAdrInfoList;
  2243. ULONG cbOff;
  2244. LPADRINFO lpAdrInfo;
  2245. LPBYTE pbData;
  2246. if (!phGlobal)
  2247. return E_INVALIDARG;
  2248. *phGlobal=0;
  2249. cbAlloc=sizeof(ADRINFOLIST);
  2250. if (FGetFirst(&adrInfo))
  2251. {
  2252. do
  2253. cbAlloc+=CbAdrInfoSize(&adrInfo);
  2254. while(FGetNext(&adrInfo));
  2255. }
  2256. else
  2257. return E_FAIL;
  2258. hGlobal=GlobalAlloc(GMEM_SHARE|GHND, cbAlloc);
  2259. if (!hGlobal)
  2260. return E_OUTOFMEMORY;
  2261. lpAdrInfoList=(LPADRINFOLIST)GlobalLock(hGlobal);
  2262. if (!lpAdrInfoList)
  2263. {
  2264. GlobalFree(hGlobal);
  2265. return E_FAIL;
  2266. }
  2267. cbOff=sizeof(ADRINFOLIST);
  2268. lpAdrInfoList->rgAdrInfo=(LPADRINFO)((ULONG_PTR)cbOff);
  2269. lpAdrInfo=(LPADRINFO)((DWORD_PTR)lpAdrInfoList+cbOff);
  2270. cbOff+=m_cActualEntries*sizeof(ADRINFO);
  2271. lpAdrInfoList->cValues=m_cActualEntries;
  2272. pbData=(LPBYTE)((DWORD_PTR)lpAdrInfoList+cbOff);
  2273. SideAssert(FGetFirst(&adrInfo)); // there HAS to be entries at this point!
  2274. do
  2275. {
  2276. // copy the flat data
  2277. CopyMemory(lpAdrInfo, &adrInfo, sizeof(ADRINFO));
  2278. // patch the pointers...
  2279. SerialAdrInfoString(&lpAdrInfo->lpwszAddress, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszAddress, &cbOff, &pbData);
  2280. SerialAdrInfoString(&lpAdrInfo->lpwszDisplay, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszDisplay, &cbOff, &pbData);
  2281. SerialAdrInfoString(&lpAdrInfo->lpwszAddrType, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszAddrType, &cbOff, &pbData);
  2282. SerialAdrInfoString(&lpAdrInfo->lpwszSurName, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszSurName, &cbOff, &pbData);
  2283. SerialAdrInfoString(&lpAdrInfo->lpwszGivenName, (cbAlloc-cbOff)/sizeof(WCHAR), adrInfo.lpwszGivenName, &cbOff, &pbData);
  2284. AssertSz(lpAdrInfo->cbEID==adrInfo.cbEID, "this should have been copied already");
  2285. cb=lpAdrInfo->cbEID;
  2286. if (cb)
  2287. {
  2288. lpAdrInfo->lpbEID=(LPBYTE)((ULONG_PTR)cbOff);
  2289. CopyMemory(pbData, adrInfo.lpbEID, cb);
  2290. cbOff+=cb;
  2291. pbData+=cb;
  2292. }
  2293. lpAdrInfo++;
  2294. #ifdef DEBUG
  2295. cFound++;
  2296. #endif
  2297. }
  2298. while(FGetNext(&adrInfo));
  2299. #ifdef DEBUG
  2300. Assert(cFound==m_cActualEntries);
  2301. #endif
  2302. GlobalUnlock(hGlobal);
  2303. *phGlobal=hGlobal;
  2304. return NOERROR;
  2305. }
  2306. HRESULT CWabal::HrRulePickNames(HWND hwndParent, LONG lRecipType, UINT uidsCaption, UINT uidsWell, UINT uidsWellButton)
  2307. {
  2308. // Locals
  2309. HRESULT hr=S_OK;
  2310. ADRPARM rAdrParms={0};
  2311. LPWAB lpWab=0;
  2312. WCHAR wszRes1[255],
  2313. wszRes2[255],
  2314. wszRes3[255];
  2315. ULONG uRow;
  2316. LPWSTR rgwszWells[1] = { wszRes3 };
  2317. if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
  2318. {
  2319. // Lets grow my current address list by GROW_SIZE
  2320. CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
  2321. }
  2322. AthLoadStringW(uidsCaption, wszRes1, ARRAYSIZE(wszRes1));
  2323. AthLoadStringW(uidsWell, wszRes2, ARRAYSIZE(wszRes2));
  2324. AthLoadStringW(uidsWellButton, wszRes3, ARRAYSIZE(wszRes3));
  2325. rAdrParms.ulFlags = DIALOG_MODAL|MAPI_UNICODE;
  2326. rAdrParms.lpszCaption = (LPTSTR)wszRes1;
  2327. rAdrParms.lpszDestWellsTitle = (LPTSTR)wszRes2;
  2328. rAdrParms.cDestFields = 1;
  2329. rAdrParms.nDestFieldFocus = 0;
  2330. rAdrParms.lppszDestTitles = (LPTSTR*)rgwszWells;
  2331. rAdrParms.lpulDestComps = (ULONG *)&lRecipType;
  2332. CHECKHR(hr=HrCreateWabObject(&lpWab));
  2333. hr=lpWab->HrGeneralPickNames(hwndParent, &rAdrParms, &m_lpAdrList);
  2334. CHECKHR(hr);
  2335. //HACKHACK: ugh, this is nasty, the pal mayhave been realloced, or maybe
  2336. // our old pal, need to figure out how many real entries are in it...
  2337. m_cActualEntries=0;
  2338. if (m_lpAdrList)
  2339. {
  2340. for(uRow=0; uRow<m_lpAdrList->cEntries; uRow++)
  2341. if (m_lpAdrList->aEntries[uRow].cValues)
  2342. m_cActualEntries++;
  2343. }
  2344. exit:
  2345. ReleaseObj(lpWab);
  2346. return hr;
  2347. }
  2348. HRESULT CWabal::HrPickNames (HWND hwndParent, ULONG *rgulTypes, int cWells, int iFocus, BOOL fNews)
  2349. {
  2350. HRESULT hr;
  2351. LPWAB lpWab=0;
  2352. ULONG uRow;
  2353. if (m_lpAdrList == NULL || m_cActualEntries == m_lpAdrList->cEntries)
  2354. {
  2355. // Lets grow my current address list by GROW_SIZE
  2356. CHECKHR (hr = HrGrowAdrlist (&m_lpAdrList, GROW_SIZE));
  2357. }
  2358. CHECKHR(hr=HrCreateWabObject(&lpWab));
  2359. hr=lpWab->HrPickNames(hwndParent, rgulTypes, cWells, iFocus, fNews, &m_lpAdrList);
  2360. CHECKHR(hr);
  2361. //HACKHACK: ugh, this is nasty, the pal mayhave been realloced, or maybe
  2362. // our old pal, need to figure out how many real entries are in it...
  2363. m_cActualEntries=0;
  2364. if (m_lpAdrList)
  2365. {
  2366. for(uRow=0; uRow<m_lpAdrList->cEntries; uRow++)
  2367. if (m_lpAdrList->aEntries[uRow].cValues)
  2368. m_cActualEntries++;
  2369. }
  2370. exit:
  2371. ReleaseObj(lpWab);
  2372. return hr;
  2373. }
  2374. #ifdef ADDTOWAB_COPYENTRIES
  2375. HRESULT CWab::HrAddToWAB(HWND hwndOwner, LPADRINFO lpAdrInfo)
  2376. {
  2377. HRESULT hr;
  2378. HCURSOR hcur;
  2379. LPABCONT pabcWAB=NULL;
  2380. ULONG cbEidWAB,
  2381. ul;
  2382. LPENTRYID peidWAB=0;
  2383. SBinary bin;
  2384. ENTRYLIST el={0, &bin};
  2385. if (!lpAdrInfo)
  2386. return E_INVALIDARG;
  2387. hcur=SetCursor(LoadCursor(NULL, IDC_WAIT));
  2388. hr=m_lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
  2389. if (FAILED(hr))
  2390. goto error;
  2391. hr=m_lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL,
  2392. 0, &ul, (LPUNKNOWN *)&pabcWAB);
  2393. if (FAILED(hr))
  2394. goto error;
  2395. m_lpWabObject->FreeBuffer(peidWAB);
  2396. Assert(ul == MAPI_ABCONT);
  2397. bin.cb=lpAdrInfo->cbEID;
  2398. bin.lpb=lpAdrInfo->lpbEID;
  2399. hr=pabcWAB->CopyEntries(&el, (ULONG)hwndOwner, NULL, CREATE_CHECK_DUP_STRICT);
  2400. if (FAILED(hr))
  2401. goto error;
  2402. error:
  2403. ReleaseObj(pabcWAB);
  2404. if (hcur)
  2405. SetCursor(hcur);
  2406. return hr;
  2407. }
  2408. #endif
  2409. HRESULT CWab::HrAddToWAB(HWND hwndOwner, LPADRINFO lpAdrInfo, LPMAPIPROP * lppMailUser)
  2410. {
  2411. HRESULT hr;
  2412. HCURSOR hcur;
  2413. LPABCONT pabcWAB=NULL;
  2414. ULONG cbEidWAB,
  2415. ul;
  2416. LPENTRYID peidWAB=0;
  2417. LPMAPIPROP lpProps=0,
  2418. lpPropsUser=0;
  2419. DWORD cUsedValues;
  2420. SPropValue rgpv[3];
  2421. SPropTagArray ptaEID = {1, {PR_ENTRYID}};
  2422. LPSPropValue ppv=0,
  2423. ppvDefMailUser=0,
  2424. ppvUser=0;
  2425. ULONG cUserProps=0;
  2426. ENTRYLIST el;
  2427. SBinary sbin;
  2428. SizedSPropTagArray(1, ptaDefMailUser)=
  2429. { 1, {PR_DEF_CREATE_MAILUSER} };
  2430. if (!lpAdrInfo)
  2431. return E_INVALIDARG;
  2432. hcur=SetCursor(LoadCursor(NULL, IDC_WAIT));
  2433. hr=m_lpAdrBook->GetPAB(&cbEidWAB, &peidWAB);
  2434. if (FAILED(hr))
  2435. goto error;
  2436. hr=m_lpAdrBook->OpenEntry(cbEidWAB, peidWAB, NULL,
  2437. 0, &ul, (LPUNKNOWN *)&pabcWAB);
  2438. if (FAILED(hr))
  2439. goto error;
  2440. m_lpWabObject->FreeBuffer(peidWAB);
  2441. Assert(ul == MAPI_ABCONT);
  2442. hr=pabcWAB->GetProps((LPSPropTagArray)&ptaDefMailUser, 0, &ul, &ppvDefMailUser);
  2443. if (FAILED(hr) || !ppvDefMailUser || ppvDefMailUser->ulPropTag!=PR_DEF_CREATE_MAILUSER)
  2444. goto error;
  2445. hr=pabcWAB->CreateEntry(ppvDefMailUser->Value.bin.cb, (LPENTRYID)ppvDefMailUser->Value.bin.lpb,
  2446. CREATE_CHECK_DUP_STRICT, &lpProps);
  2447. if (FAILED(hr))
  2448. goto error;
  2449. if (lpAdrInfo->lpbEID)
  2450. {
  2451. // if we have an entry for the user (could be an LDAP search), then let's copy across all the props
  2452. // note. we still override these with the displayname props and possible cert props later on.
  2453. if (m_lpAdrBook->OpenEntry(lpAdrInfo->cbEID, (LPENTRYID)lpAdrInfo->lpbEID, &IID_IMAPIProp, 0, &ul, (LPUNKNOWN *)&lpPropsUser)==S_OK)
  2454. {
  2455. Assert (ul == MAPI_MAILUSER);
  2456. if (lpPropsUser->GetProps(NULL, 0, &cUserProps, &ppvUser)==S_OK)
  2457. {
  2458. for (ULONG u=0; u<cUserProps; u++)
  2459. if (ppvUser[u].ulPropTag == PR_ENTRYID)
  2460. ppvUser[u].ulPropTag = PR_NULL;
  2461. lpProps->SetProps(cUserProps, ppvUser, NULL);
  2462. m_lpWabObject->FreeBuffer(ppvUser);
  2463. }
  2464. lpPropsUser->Release();
  2465. }
  2466. }
  2467. rgpv[0].ulPropTag = PR_DISPLAY_NAME_W;
  2468. rgpv[0].Value.lpszW = lpAdrInfo->lpwszDisplay;
  2469. rgpv[1].ulPropTag = PR_EMAIL_ADDRESS_W;
  2470. rgpv[1].Value.lpszW = lpAdrInfo->lpwszAddress;
  2471. cUsedValues = 2;
  2472. if (lpAdrInfo->pMsg)
  2473. {
  2474. HCERTSTORE hc, hcMsg;
  2475. THUMBBLOB tbSigner = {0};
  2476. BLOB blSymCaps = {0};
  2477. FILETIME ftSigningTime = {0};
  2478. PCCERT_CONTEXT pcSigningCert = NULL;
  2479. PROPVARIANT var;
  2480. IMimeBody *pBody = NULL;
  2481. HBODY hBody = NULL;
  2482. // Does this message have a sender cert?
  2483. if (SUCCEEDED(GetSigningCert(lpAdrInfo->pMsg, &pcSigningCert, &tbSigner, &blSymCaps, &ftSigningTime)))
  2484. {
  2485. // Get the sender's cert from the message and add it to the AddressBook cert store
  2486. if (hc = CertOpenStore(CERT_STORE_PROV_SYSTEM_A,
  2487. X509_ASN_ENCODING, NULL,
  2488. CERT_SYSTEM_STORE_CURRENT_USER, c_szWABCertStore))
  2489. {
  2490. CertAddCertificateContextToStore(hc, pcSigningCert,
  2491. CERT_STORE_ADD_REPLACE_EXISTING, NULL);
  2492. CertFreeCertificateContext(pcSigningCert);
  2493. CertCloseStore(hc, 0);
  2494. }
  2495. // Add the CA certs
  2496. // Get the hcMsg property from the message
  2497. if(FAILED(hr = HrGetInnerLayer(lpAdrInfo->pMsg, &hBody)))
  2498. goto ex;
  2499. if (SUCCEEDED(lpAdrInfo->pMsg->BindToObject(hBody ? hBody : HBODY_ROOT, IID_IMimeBody, (void **)&pBody)))
  2500. {
  2501. #ifdef _WIN64
  2502. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE_64, &var)))
  2503. {
  2504. hcMsg = (HCERTSTORE)(var.pulVal); // Closed in WM_DESTROY
  2505. #else // !_WIN64
  2506. if (SUCCEEDED(pBody->GetOption(OID_SECURITY_HCERTSTORE, &var)))
  2507. {
  2508. hcMsg = (HCERTSTORE) var.ulVal; // Closed in WM_DESTROY
  2509. #endif
  2510. if (hcMsg) // message store containing certs
  2511. {
  2512. hc = CertOpenStore(CERT_STORE_PROV_SYSTEM_A,
  2513. X509_ASN_ENCODING, NULL,
  2514. CERT_SYSTEM_STORE_CURRENT_USER, c_szCACertStore);
  2515. if (hc)
  2516. {
  2517. HrSaveCACerts(hc, hcMsg);
  2518. CertCloseStore(hc, 0);
  2519. }
  2520. CertCloseStore(hcMsg, 0); // was addref'd when we got it.
  2521. }
  2522. }
  2523. ReleaseObj(pBody);
  2524. }
  2525. ex:
  2526. if (SUCCEEDED(hr=ThumbprintToPropValue(&rgpv[cUsedValues],
  2527. &tbSigner,
  2528. &blSymCaps,
  2529. ftSigningTime,
  2530. TRUE))) // Since we are creating the entry, this must be default.
  2531. cUsedValues++;
  2532. if (tbSigner.pBlobData)
  2533. MemFree(tbSigner.pBlobData);
  2534. if (blSymCaps.pBlobData)
  2535. MemFree(blSymCaps.pBlobData);
  2536. }
  2537. }
  2538. hr=lpProps->SetProps(cUsedValues, rgpv, NULL);
  2539. if (FAILED(hr))
  2540. goto error;
  2541. hr=lpProps->SaveChanges(KEEP_OPEN_READONLY);
  2542. if (FAILED(hr))
  2543. {
  2544. // if (tbSigner.pBlobData)
  2545. // { // There is a cert. We should try to merge it into the existing entry.
  2546. // BUGBUG: NYI
  2547. //
  2548. // }
  2549. // else
  2550. goto error;
  2551. }
  2552. hr=lpProps->GetProps(&ptaEID, 0, &ul, &ppv);
  2553. if (!FAILED(hr) && ppv && ppv->ulPropTag==PR_ENTRYID)
  2554. {
  2555. hr=m_lpAdrBook->Details((ULONG_PTR *)&hwndOwner, NULL, NULL, ppv->Value.bin.cb, (LPENTRYID)ppv->Value.bin.lpb, NULL, NULL, NULL, 0);
  2556. }
  2557. if (lppMailUser)
  2558. {
  2559. *lppMailUser = lpProps;
  2560. }
  2561. else
  2562. {
  2563. ReleaseObj(lpProps);
  2564. }
  2565. if (hr==MAPI_E_USER_CANCEL)
  2566. {
  2567. // the user canceled details, blow away the new entry, silent fail
  2568. el.cValues=1;
  2569. el.lpbin=&ppv->Value.bin;
  2570. pabcWAB->DeleteEntries(&el, 0);
  2571. }
  2572. error:
  2573. ReleaseObj(pabcWAB);
  2574. if (ppv)
  2575. m_lpWabObject->FreeBuffer(ppv);
  2576. if (ppvDefMailUser)
  2577. m_lpWabObject->FreeBuffer(ppvDefMailUser);
  2578. if (hcur)
  2579. SetCursor(hcur);
  2580. return hr;
  2581. }
  2582. HRESULT CWab::HrUpdateWABEntry(LPADRINFO lpAdrInfo, DWORD mask)
  2583. {
  2584. HRESULT hr;
  2585. LPMAILUSER lpMailUser = NULL;
  2586. ULONG ulObjType;
  2587. ADRENTRY adrentry = {0};
  2588. if (!(lpAdrInfo->cbEID && lpAdrInfo->lpbEID))
  2589. return E_INVALIDARG;
  2590. if (FAILED(hr=m_lpAdrBook->OpenEntry(lpAdrInfo->cbEID, (LPENTRYID)lpAdrInfo->lpbEID,
  2591. NULL, MAPI_MODIFY, &ulObjType,
  2592. (LPUNKNOWN *)&lpMailUser)))
  2593. goto exit;
  2594. Assert(lpMailUser);
  2595. if (FAILED(hr = HrSetAdrEntry (m_lpWabObject, &adrentry, lpAdrInfo, mask)))
  2596. goto exit;
  2597. if (FAILED(hr = lpMailUser->SetProps(adrentry.cValues, adrentry.rgPropVals, NULL)))
  2598. goto exit;
  2599. hr = lpMailUser->SaveChanges(KEEP_OPEN_READONLY);
  2600. exit:
  2601. ReleaseObj(lpMailUser);
  2602. return hr;
  2603. }
  2604. HRESULT CWab::HrUpdateWABEntryNoEID(HWND hwndParent, LPADRINFO lpAdrInfo, DWORD mask)
  2605. {
  2606. HRESULT hr;
  2607. SizedADRLIST (1, adrlist) = {1, {0,0,NULL}};
  2608. DWORD i;
  2609. if (lpAdrInfo->lpbEID)
  2610. return E_INVALIDARG;
  2611. if (FAILED(hr = HrSetAdrEntry (m_lpWabObject, &adrlist.aEntries[0], lpAdrInfo, AIM_DISPLAY)))
  2612. goto exit;
  2613. if (FAILED(hr = m_lpAdrBook->ResolveName ((ULONG_PTR)hwndParent, MAPI_DIALOG, NULL, (LPADRLIST)&adrlist)))
  2614. goto exit;
  2615. for (i=0; i<adrlist.aEntries[0].cValues; i++)
  2616. {
  2617. if (PR_ENTRYID == adrlist.aEntries[0].rgPropVals[i].ulPropTag)
  2618. {
  2619. lpAdrInfo->cbEID = adrlist.aEntries[0].rgPropVals[i].Value.bin.cb;
  2620. lpAdrInfo->lpbEID = adrlist.aEntries[0].rgPropVals[i].Value.bin.lpb;
  2621. break;
  2622. }
  2623. }
  2624. if (!lpAdrInfo->lpbEID)
  2625. {
  2626. hr = TrapError(E_FAIL);
  2627. goto exit;
  2628. }
  2629. hr = HrUpdateWABEntry(lpAdrInfo, mask);
  2630. exit:
  2631. if (adrlist.aEntries[0].rgPropVals)
  2632. m_lpWabObject->FreeBuffer(adrlist.aEntries[0].rgPropVals);
  2633. lpAdrInfo->cbEID = 0;
  2634. lpAdrInfo->lpbEID = NULL;
  2635. return hr;
  2636. }
  2637. // =============================================================================
  2638. // CWab::HrGetAdrBook
  2639. // =============================================================================
  2640. HRESULT CWab::HrGetAdrBook(LPADRBOOK* lppAdrBook)
  2641. {
  2642. Assert(lppAdrBook);
  2643. if (!lppAdrBook)
  2644. return E_INVALIDARG;
  2645. *lppAdrBook = m_lpAdrBook;
  2646. return NOERROR;
  2647. }
  2648. // =============================================================================
  2649. // CWab::HrGetWabObject
  2650. // =============================================================================
  2651. HRESULT CWab::HrGetWabObject(LPWABOBJECT* lppWabObject)
  2652. {
  2653. Assert(lppWabObject);
  2654. if (!lppWabObject)
  2655. return E_INVALIDARG;
  2656. *lppWabObject = m_lpWabObject;
  2657. return NOERROR;
  2658. }
  2659. /***************************************************************************
  2660. Name : FTranslateAccelerator
  2661. Purpose : Give an open WAB window a change to look for accelerators.
  2662. Parameters: lpmsg -> lpmsg from the current event
  2663. Returns : BOOL - was the event used
  2664. ***************************************************************************/
  2665. BOOL CWab::FTranslateAccelerator(LPMSG lpmsg)
  2666. {
  2667. if (m_adrParm.lpfnABSDI && m_hwnd && GetActiveWindow() == m_hwnd)
  2668. return ((m_adrParm.lpfnABSDI)((ULONG_PTR)m_hwnd, (LPVOID)lpmsg));
  2669. return FALSE;
  2670. }
  2671. /***************************************************************************
  2672. Name : OnClose
  2673. Purpose : We are closing the application. If the window is open, tell
  2674. it to close.
  2675. Parameters: none
  2676. Returns : HRESULT
  2677. ***************************************************************************/
  2678. HRESULT CWab::OnClose()
  2679. {
  2680. DOUT ("CWab::OnClose");
  2681. if (m_hwnd)
  2682. SendMessage(m_hwnd, WM_CLOSE, 0, 0);
  2683. return S_OK;
  2684. }
  2685. HRESULT HrCloseWabWindow()
  2686. {
  2687. HRESULT hr = S_OK;
  2688. if (g_pWab)
  2689. hr = g_pWab->OnClose();
  2690. return hr;
  2691. }
  2692. #ifdef DEBUG
  2693. void DEBUGDumpAdrList(LPADRLIST pal)
  2694. {
  2695. char sz[2048];
  2696. WCHAR wsz[2048];
  2697. ULONG ul,
  2698. ulProp;
  2699. if (!pal)
  2700. {
  2701. OutputDebugString("<Empty Adrlist>\n\r");
  2702. return;
  2703. }
  2704. wnsprintf(sz, ARRAYSIZE(sz), "AdrList:: (%d entries)", pal->cEntries);
  2705. OutputDebugString(sz);
  2706. for(ul=0; ul<pal->cEntries; ul++)
  2707. {
  2708. wnsprintf(sz, ARRAYSIZE(sz), "\n\r %d) {cVal=%d, {", ul, pal->aEntries[ul].cValues);
  2709. OutputDebugString(sz);
  2710. for(ulProp=0; ulProp<pal->aEntries[ul].cValues; ulProp++)
  2711. {
  2712. switch(pal->aEntries[ul].rgPropVals[ulProp].ulPropTag)
  2713. {
  2714. case PR_ENTRYID:
  2715. OutputDebugString("EID");
  2716. break;
  2717. case PR_EMAIL_ADDRESS:
  2718. OutputDebugString("ADDRESS");
  2719. break;
  2720. case PR_EMAIL_ADDRESS_W:
  2721. OutputDebugString("ADDRESS_W");
  2722. break;
  2723. case PR_ADDRTYPE:
  2724. OutputDebugString("ADDRTYPE");
  2725. break;
  2726. case PR_ADDRTYPE_W:
  2727. OutputDebugString("ADDRTYPE_W");
  2728. break;
  2729. // If the prop is ansi, the output might be funky.
  2730. case PR_DISPLAY_NAME:
  2731. wnsprintf(sz, ARRAYSIZE(sz), "DISP(%s)", pal->aEntries[ul].rgPropVals[ulProp].Value.lpszA);
  2732. OutputDebugString(sz);
  2733. break;
  2734. case PR_DISPLAY_NAME_W:
  2735. wnsprintfW(wsz, ARRAYSIZE(wsz), L"DISP(%s)", pal->aEntries[ul].rgPropVals[ulProp].Value.lpszW);
  2736. OutputDebugStringWrapW(wsz);
  2737. break;
  2738. case PR_SURNAME:
  2739. OutputDebugString("SURNAME");
  2740. break;
  2741. case PR_SURNAME_W:
  2742. OutputDebugString("SURNAME_W");
  2743. break;
  2744. case PR_GIVEN_NAME:
  2745. OutputDebugString("GIVENNAME");
  2746. break;
  2747. case PR_GIVEN_NAME_W:
  2748. OutputDebugString("GIVENNAME_W");
  2749. break;
  2750. case PROP_ID(PR_RECIPIENT_TYPE):
  2751. wnsprintf(sz, ARRAYSIZE(sz), "RECIPTYPE(%d)", pal->aEntries[ul].rgPropVals[ulProp].Value.l);
  2752. OutputDebugString(sz);
  2753. break;
  2754. case PROP_ID(PR_SEARCH_KEY):
  2755. OutputDebugString("SEARCHKEY");
  2756. break;
  2757. case PROP_ID(PR_OBJECT_TYPE):
  2758. OutputDebugString("OBJTYPE");
  2759. break;
  2760. default:
  2761. wnsprintf(sz, ARRAYSIZE(sz), "<unknown> 0x%x", pal->aEntries[ul].rgPropVals[ulProp].ulPropTag);
  2762. OutputDebugString(sz);
  2763. break;
  2764. }
  2765. if (ulProp+1<pal->aEntries[ul].cValues)
  2766. OutputDebugString(", ");
  2767. }
  2768. OutputDebugString("}}");
  2769. }
  2770. OutputDebugString("\n\r");
  2771. }
  2772. #endif
  2773. HRESULT CWabal::HrAdrInfoFromRow(LPSRow lpsrw, LPADRINFO lpAdrInfo, LONG lRecipType)
  2774. {
  2775. LPSPropValue ppv;
  2776. ULONG ul,
  2777. cValues;
  2778. Assert(lpsrw);
  2779. Assert(lpAdrInfo);
  2780. lpAdrInfo->lpwszAddress = NULL;
  2781. lpAdrInfo->lpwszAddrType = NULL;
  2782. lpAdrInfo->lpwszDisplay = NULL;
  2783. lpAdrInfo->lpwszSurName = NULL;
  2784. lpAdrInfo->lpwszGivenName = NULL;
  2785. lpAdrInfo->lRecipType = lRecipType;
  2786. lpAdrInfo->fResolved = FALSE;
  2787. lpAdrInfo->fDistList = FALSE;
  2788. lpAdrInfo->fDefCertificate = FALSE;
  2789. lpAdrInfo->tbCertificate.pBlobData = (BYTE*)0;
  2790. lpAdrInfo->tbCertificate.cbSize = 0;
  2791. lpAdrInfo->blSymCaps.pBlobData = (BYTE*)0;
  2792. lpAdrInfo->blSymCaps.cbSize = 0;
  2793. lpAdrInfo->ftSigningTime.dwLowDateTime = lpAdrInfo->ftSigningTime.dwHighDateTime = 0;
  2794. lpAdrInfo->cbEID=0;
  2795. lpAdrInfo->lpbEID=0;
  2796. cValues=lpsrw->cValues;
  2797. ppv=lpsrw->lpProps;
  2798. AssertSz(cValues, "empty address??");
  2799. for(ul=0; ul<cValues; ul++, ppv++)
  2800. PropValToAdrInfo(ppv, lpAdrInfo);
  2801. DOUTL(4, "AddrEntry2AddrInfo: lRecip=%d", lpAdrInfo->lRecipType);
  2802. AssertSz(lpAdrInfo->lpwszAddress==NULL ||
  2803. lpAdrInfo->lRecipType != -1, "A resolved entry should have a recip type!");
  2804. return NOERROR;
  2805. }
  2806. void CWabal::PropValToAdrInfo(LPSPropValue ppv, LPADRINFO lpAdrInfo)
  2807. {
  2808. switch(ppv->ulPropTag)
  2809. {
  2810. case PR_SEND_INTERNET_ENCODING:
  2811. lpAdrInfo->fPlainText = (ppv->Value.l == BODY_ENCODING_TEXT);
  2812. break;
  2813. case PR_OBJECT_TYPE:
  2814. Assert(ppv->Value.l==MAPI_MAILUSER || ppv->Value.l==MAPI_DISTLIST);
  2815. lpAdrInfo->fDistList=(ppv->Value.l==MAPI_DISTLIST);
  2816. break;
  2817. case PR_EMAIL_ADDRESS:
  2818. AssertSz(FALSE, "Have to take care of this case.");
  2819. //Assert(!lpAdrInfo->lpszAddress);
  2820. //lpAdrInfo->lpszAddress = ppv->Value.lpszA;
  2821. break;
  2822. case PR_EMAIL_ADDRESS_W:
  2823. Assert(!lpAdrInfo->lpwszAddress);
  2824. lpAdrInfo->lpwszAddress = ppv->Value.lpszW;
  2825. break;
  2826. case PR_ADDRTYPE:
  2827. AssertSz(FALSE, "Have to take care of this case.");
  2828. //Assert(!lpAdrInfo->lpszAddrType);
  2829. //lpAdrInfo->lpszAddrType = ppv->Value.lpszA;
  2830. break;
  2831. case PR_ADDRTYPE_W:
  2832. Assert(!lpAdrInfo->lpwszAddrType);
  2833. lpAdrInfo->lpwszAddrType = ppv->Value.lpszW;
  2834. break;
  2835. case PR_RECIPIENT_TYPE:
  2836. Assert(lpAdrInfo->lRecipType==-1);
  2837. lpAdrInfo->lRecipType = ppv->Value.l;
  2838. break;
  2839. case PR_DISPLAY_NAME:
  2840. AssertSz(FALSE, "Have to take care of this case.");
  2841. //Assert(!lpAdrInfo->lpszDisplay);
  2842. //lpAdrInfo->lpszDisplay = ppv->Value.lpszA;
  2843. break;
  2844. case PR_DISPLAY_NAME_W:
  2845. Assert(!lpAdrInfo->lpwszDisplay);
  2846. lpAdrInfo->lpwszDisplay = ppv->Value.lpszW;
  2847. break;
  2848. case PR_SURNAME:
  2849. AssertSz(FALSE, "Have to take care of this case.");
  2850. //Assert(!lpAdrInfo->lpszSurName);
  2851. //lpAdrInfo->lpszSurName = ppv->Value.lpszA;
  2852. break;
  2853. case PR_GIVEN_NAME:
  2854. AssertSz(FALSE, "Have to take care of this case.");
  2855. //Assert(!lpAdrInfo->lpszGivenName);
  2856. //lpAdrInfo->lpszGivenName = ppv->Value.lpszA;
  2857. break;
  2858. case PR_SURNAME_W:
  2859. Assert(!lpAdrInfo->lpwszSurName);
  2860. lpAdrInfo->lpwszSurName = ppv->Value.lpszW;
  2861. break;
  2862. case PR_GIVEN_NAME_W:
  2863. Assert(!lpAdrInfo->lpwszGivenName);
  2864. lpAdrInfo->lpwszGivenName = ppv->Value.lpszW;
  2865. break;
  2866. case PR_ENTRYID:
  2867. lpAdrInfo->cbEID=ppv->Value.bin.cb;
  2868. lpAdrInfo->lpbEID=ppv->Value.bin.lpb;
  2869. lpAdrInfo->fResolved=TRUE; // it's resolved if it has an entryid
  2870. break;
  2871. case PR_USER_X509_CERTIFICATE:
  2872. // Assume only one value in cert array.
  2873. Assert(ppv->Value.MVbin.cValues == 1);
  2874. if (ppv->Value.MVbin.cValues)
  2875. {
  2876. BOOL fDefault = FALSE;
  2877. GetX509CertTags(&ppv->Value.MVbin.lpbin[0], &lpAdrInfo->tbCertificate, &lpAdrInfo->blSymCaps,
  2878. &lpAdrInfo->ftSigningTime, &fDefault);
  2879. lpAdrInfo->fDefCertificate = fDefault;
  2880. }
  2881. break;
  2882. }
  2883. }
  2884. HRESULT CWabal::HrExpandTo(LPWABAL lpWabal)
  2885. {
  2886. ADRINFO adrInfo;
  2887. LPSRowSet prwsDL=0;
  2888. HRESULT hr=S_OK;
  2889. SBinary eidDL;
  2890. DLSEARCHINFO DLSearch={0};
  2891. if (!lpWabal)
  2892. return E_INVALIDARG;
  2893. if (FGetFirst(&adrInfo))
  2894. do
  2895. {
  2896. if (adrInfo.fDistList)
  2897. {
  2898. eidDL.cb=adrInfo.cbEID;
  2899. eidDL.lpb=adrInfo.lpbEID;
  2900. if (!FDLVisted(eidDL, &DLSearch))
  2901. {
  2902. // this is a new distribution list, let's open it and scan..
  2903. // add this distlist to our searchlist, and recurse...
  2904. hr=HrAddToSearchList(eidDL, &DLSearch);
  2905. if (FAILED(hr))
  2906. goto error;
  2907. hr=HrGetDistListRows(eidDL, &prwsDL);
  2908. if (FAILED(hr))
  2909. {
  2910. hr = hrEmptyDistList;
  2911. goto error;
  2912. }
  2913. hr=HrAddDistributionList(lpWabal, prwsDL, adrInfo.lRecipType, &DLSearch);
  2914. if (FAILED(hr))
  2915. goto error;
  2916. m_lpWabObject->FreeBuffer(prwsDL);
  2917. prwsDL=NULL;
  2918. }
  2919. }
  2920. else
  2921. {
  2922. hr=lpWabal->HrAddEntry(&adrInfo, TRUE);
  2923. if (FAILED(hr))
  2924. goto error;
  2925. }
  2926. }
  2927. while(FGetNext(&adrInfo));
  2928. error:
  2929. if (prwsDL)
  2930. m_lpWabObject->FreeBuffer(prwsDL);
  2931. FreeSearchList(&DLSearch);
  2932. return hr;
  2933. }
  2934. HRESULT CWabal::HrAddDistributionList(LPWABAL lpWabal, LPSRowSet lprws, LONG lRecipType, PDLSEARCHINFO pDLSearch)
  2935. {
  2936. HRESULT hr=NOERROR;
  2937. ULONG ul;
  2938. LPSRowSet prwsDL=0;
  2939. ADRINFO adrInfo;
  2940. for(ul=0; ul<lprws->cRows; ul++)
  2941. {
  2942. if (lprws->aRow[ul].lpProps[AE_colObjectType].ulPropTag==PR_OBJECT_TYPE &&
  2943. lprws->aRow[ul].lpProps[AE_colObjectType].Value.l == MAPI_DISTLIST &&
  2944. lprws->aRow[ul].lpProps[AE_colEntryID].ulPropTag==PR_ENTRYID)
  2945. {
  2946. if (!FDLVisted(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, pDLSearch))
  2947. {
  2948. // this is a new distribution list, let's open it and scan..
  2949. // add this distlist to our searchlist, and recurse...
  2950. hr=HrAddToSearchList(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, pDLSearch);
  2951. if (FAILED(hr))
  2952. goto error;
  2953. hr=HrGetDistListRows(lprws->aRow[ul].lpProps[AE_colEntryID].Value.bin, &prwsDL);
  2954. if (FAILED(hr))
  2955. goto error;
  2956. hr=HrAddDistributionList(lpWabal, prwsDL, lRecipType, pDLSearch);
  2957. if (FAILED(hr))
  2958. goto error;
  2959. m_lpWabObject->FreeBuffer(prwsDL);
  2960. prwsDL=NULL;
  2961. }
  2962. }
  2963. else
  2964. if ( lprws->aRow[ul].lpProps[AE_colObjectType].ulPropTag==PR_OBJECT_TYPE &&
  2965. lprws->aRow[ul].lpProps[AE_colObjectType].Value.l == MAPI_MAILUSER )
  2966. {
  2967. // just a regular user...
  2968. hr=HrAdrInfoFromRow(&lprws->aRow[ul], &adrInfo, lRecipType);
  2969. if (FAILED(hr))
  2970. goto error;
  2971. hr=lpWabal->HrAddEntry(&adrInfo, TRUE);
  2972. if (FAILED(hr))
  2973. goto error;
  2974. }
  2975. }
  2976. error:
  2977. if (prwsDL)
  2978. m_lpWabObject->FreeBuffer(prwsDL);
  2979. return hr;
  2980. }
  2981. BOOL CWabal::FDLVisted(SBinary eidDL, PDLSEARCHINFO pDLSearch)
  2982. {
  2983. ULONG ul,
  2984. ulResult=0;
  2985. HRESULT hr;
  2986. for(ul=0; ul<pDLSearch->cValues; ul++)
  2987. {
  2988. hr=m_lpAdrBook->CompareEntryIDs(eidDL.cb, (LPENTRYID)eidDL.lpb,
  2989. pDLSearch->rgEid[ul].cb,
  2990. (LPENTRYID)pDLSearch->rgEid[ul].lpb, 0, &ulResult);
  2991. if ((!FAILED(hr)) && ulResult)
  2992. return TRUE;
  2993. }
  2994. return FALSE;
  2995. }
  2996. HRESULT CWabal::HrAddToSearchList(SBinary eidDL, PDLSEARCHINFO pDLSearch)
  2997. {
  2998. ULONG ulResult=0;
  2999. LPBYTE lpb=0;
  3000. if (pDLSearch->cValues==pDLSearch->cAlloc)
  3001. {
  3002. // time to grow...
  3003. if (!MemRealloc((LPVOID *)&pDLSearch->rgEid, sizeof(SBinary)*(pDLSearch->cAlloc+GROW_SIZE)))
  3004. return E_OUTOFMEMORY;
  3005. //ZeroInit the new stuff...
  3006. ZeroMemory(&pDLSearch->rgEid[pDLSearch->cAlloc], sizeof(SBinary)*GROW_SIZE);
  3007. pDLSearch->cAlloc+=GROW_SIZE;
  3008. }
  3009. if (!MemAlloc((LPVOID *)&lpb, eidDL.cb))
  3010. return E_OUTOFMEMORY;
  3011. pDLSearch->rgEid[pDLSearch->cValues].cb=eidDL.cb;
  3012. pDLSearch->rgEid[pDLSearch->cValues].lpb=lpb;
  3013. CopyMemory(lpb, eidDL.lpb, eidDL.cb);
  3014. pDLSearch->cValues++;
  3015. return NOERROR;
  3016. }
  3017. HRESULT CWabal::FreeSearchList(PDLSEARCHINFO pDLSearch)
  3018. {
  3019. ULONG ul;
  3020. if (pDLSearch)
  3021. {
  3022. for(ul=0; ul<pDLSearch->cValues; ul++)
  3023. if (pDLSearch->rgEid[ul].lpb)
  3024. MemFree(pDLSearch->rgEid[ul].lpb);
  3025. #ifdef DEBUG
  3026. for(ul=pDLSearch->cValues; ul<pDLSearch->cAlloc; ul++)
  3027. AssertSz(pDLSearch->rgEid[ul].cb==NULL && pDLSearch->rgEid[ul].lpb==NULL, "should be null!");
  3028. #endif
  3029. if (pDLSearch->rgEid)
  3030. MemFree(pDLSearch->rgEid);
  3031. }
  3032. return NOERROR;
  3033. }
  3034. HRESULT CWabal::HrGetDistListRows(SBinary eidDL, LPSRowSet *psrws)
  3035. {
  3036. HRESULT hr;
  3037. LPMAPITABLE ptblDistList=0;
  3038. ULONG ulObjType,
  3039. cRows=0;
  3040. LPDISTLIST pDistList=0;
  3041. Assert(m_lpAdrBook);
  3042. hr=m_lpAdrBook->OpenEntry(eidDL.cb, (LPENTRYID)eidDL.lpb, &IID_IDistList, 0, &ulObjType, (LPUNKNOWN *)&pDistList);
  3043. if (FAILED(hr))
  3044. goto cleanup;
  3045. Assert(pDistList);
  3046. hr=pDistList->GetContentsTable(MAPI_UNICODE, &ptblDistList);
  3047. if (FAILED(hr))
  3048. goto cleanup;
  3049. Assert(ptblDistList);
  3050. hr=ptblDistList->GetRowCount(0, &cRows);
  3051. if (FAILED(hr))
  3052. goto cleanup;
  3053. hr=ptblDistList->SetColumns((LPSPropTagArray)&AE_props, 0);
  3054. if (FAILED(hr))
  3055. goto cleanup;
  3056. hr=ptblDistList->QueryRows(cRows, 0, psrws);
  3057. if (FAILED(hr))
  3058. goto cleanup;
  3059. cleanup:
  3060. ReleaseObj(ptblDistList);
  3061. ReleaseObj(pDistList);
  3062. return hr;
  3063. }
  3064. HRESULT CWabal::HrGetPMP(ULONG cbEntryID, LPENTRYID lpEntryID, ULONG *lpul, LPMAPIPROP *lppmp)
  3065. {
  3066. return m_lpAdrBook->OpenEntry(cbEntryID, lpEntryID, &IID_IMAPIProp, 0, lpul, (LPUNKNOWN *)lppmp);
  3067. }
  3068. /***************************************************************************
  3069. Name : HrBuildCertSBinaryData
  3070. Purpose : Takes as input all the data needed for a cert entry
  3071. in PR_USER_X509_CERTIFICATE and returns a pointer to
  3072. memory that contains all the input data in the correct
  3073. format to be plugged in to the lpb member of an SBinary
  3074. structure. This memory should be Freed by the caller.
  3075. Parameters: bIsDefault - TRUE if this is the default cert
  3076. pblobCertThumbPrint - The actual certificate thumbprint
  3077. pblobSymCaps - symcaps blob
  3078. ftSigningTime - Signing time
  3079. lplpbData - receives the buffer with the data
  3080. lpcbData - receives size of the data
  3081. Returns : HRESULT
  3082. Comment :
  3083. ***************************************************************************/
  3084. HRESULT HrBuildCertSBinaryData(
  3085. BOOL bIsDefault,
  3086. THUMBBLOB* pPrint,
  3087. BLOB * pSymCaps,
  3088. FILETIME ftSigningTime,
  3089. LPBYTE UNALIGNED FAR* lplpbData,
  3090. ULONG UNALIGNED FAR* lpcbData)
  3091. {
  3092. DWORD cbDefault, cbPrint, cbSymCaps;
  3093. HRESULT hr = S_OK;
  3094. LPCERTTAGS lpCurrentTag;
  3095. ULONG cbSize, cProps;
  3096. LPBYTE lpb = NULL;
  3097. cbDefault = sizeof(bIsDefault);
  3098. cbPrint = pPrint->cbSize;
  3099. cbSymCaps = pSymCaps->cbSize;
  3100. cProps = 2;
  3101. cbSize = LcbAlignLcb(cbDefault) + LcbAlignLcb(cbPrint);
  3102. if (cbSymCaps) {
  3103. cProps++;
  3104. cbSize += LcbAlignLcb(cbSymCaps);
  3105. }
  3106. if (ftSigningTime.dwLowDateTime || ftSigningTime.dwHighDateTime) {
  3107. cProps++;
  3108. cbSize += LcbAlignLcb(sizeof(FILETIME));
  3109. }
  3110. cbSize += LcbAlignLcb(cProps * SIZE_CERTTAGS);
  3111. if (!MemAlloc((LPVOID *)&lpb, cbSize))
  3112. {
  3113. hr = E_OUTOFMEMORY;
  3114. goto exit;
  3115. }
  3116. // Set the default property
  3117. lpCurrentTag = (LPCERTTAGS)lpb;
  3118. lpCurrentTag->tag = CERT_TAG_DEFAULT;
  3119. lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + cbDefault);
  3120. memcpy(&lpCurrentTag->rgbData,
  3121. &bIsDefault,
  3122. cbDefault);
  3123. // Set the thumbprint property
  3124. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
  3125. lpCurrentTag->tag = CERT_TAG_THUMBPRINT;
  3126. lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + cbPrint);
  3127. memcpy(&lpCurrentTag->rgbData, pPrint->pBlobData, cbPrint);
  3128. // Set the SymCaps property
  3129. if (cbSymCaps) {
  3130. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
  3131. lpCurrentTag->tag = CERT_TAG_SYMCAPS;
  3132. lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + pSymCaps->cbSize);
  3133. memcpy(&lpCurrentTag->rgbData, pSymCaps->pBlobData, cbSymCaps);
  3134. }
  3135. // Signing time property
  3136. if (ftSigningTime.dwLowDateTime || ftSigningTime.dwHighDateTime) {
  3137. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + LcbAlignLcb(lpCurrentTag->cbData));
  3138. lpCurrentTag->tag = CERT_TAG_SIGNING_TIME;
  3139. lpCurrentTag->cbData = (WORD) (SIZE_CERTTAGS + sizeof(FILETIME));
  3140. memcpy(&lpCurrentTag->rgbData, &ftSigningTime, sizeof(FILETIME));
  3141. }
  3142. *lpcbData = cbSize;
  3143. *lplpbData = lpb;
  3144. exit:
  3145. return(hr);
  3146. }
  3147. HRESULT ThumbprintToPropValue(LPSPropValue ppv,
  3148. THUMBBLOB *pPrint,
  3149. BLOB *pSymCaps,
  3150. FILETIME ftSigningTime,
  3151. BOOL fDefPrint)
  3152. {
  3153. SBinary UNALIGNED *pSBin;
  3154. DWORD cbDefault, cbPrint, cbSymCaps;
  3155. HRESULT hr = S_OK;
  3156. LPCERTTAGS lpCurrentTag;
  3157. ULONG cbSize, cProps;
  3158. Assert(ppv && pPrint);
  3159. if (!pPrint->pBlobData)
  3160. return E_INVALIDARG;
  3161. ppv->ulPropTag = PR_USER_X509_CERTIFICATE;
  3162. ppv->Value.MVbin.cValues = 1;
  3163. if (!MemAlloc((LPVOID *)&ppv->Value.MVbin.lpbin, sizeof(SBinary)*ppv->Value.MVbin.cValues))
  3164. {
  3165. hr = E_OUTOFMEMORY;
  3166. goto exit;
  3167. }
  3168. pSBin = ppv->Value.MVbin.lpbin;
  3169. hr = HrBuildCertSBinaryData(
  3170. fDefPrint,
  3171. pPrint,
  3172. pSymCaps,
  3173. ftSigningTime,
  3174. &pSBin->lpb,
  3175. &pSBin->cb);
  3176. exit:
  3177. return hr;
  3178. }
  3179. ULONG CWabal::DeleteRecipType(LONG lRecipType)
  3180. {
  3181. ULONG ulNew = 0, ulRemoved;
  3182. for (ULONG ul = 0; ul < m_cActualEntries; ul++)
  3183. {
  3184. for (ULONG ulProp = 0; ulProp < m_lpAdrList->aEntries[ul].cValues; ulProp++)
  3185. {
  3186. if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].ulPropTag == PR_RECIPIENT_TYPE)
  3187. {
  3188. if (m_lpAdrList->aEntries[ul].rgPropVals[ulProp].Value.l != lRecipType)
  3189. m_lpAdrList->aEntries[ulNew++] = m_lpAdrList->aEntries[ul];
  3190. else
  3191. m_lpWabObject->FreeBuffer(m_lpAdrList->aEntries[ul].rgPropVals);
  3192. break;
  3193. }
  3194. }
  3195. }
  3196. ulRemoved = m_cActualEntries - ulNew;
  3197. if (ulRemoved)
  3198. ZeroMemory(&m_lpAdrList->aEntries[ulNew], ulRemoved * sizeof(ADRENTRY));
  3199. m_cActualEntries = ulNew;
  3200. return ulRemoved;
  3201. }
  3202. void CWabal::UnresolveOneOffs()
  3203. {
  3204. ULONG ulEntry, ulProp;
  3205. LPADRENTRY pae;
  3206. LPSPropValue pPropDisp, pPropEmail, pProp;
  3207. for (ulEntry = 0, pae = m_lpAdrList->aEntries; ulEntry < m_cActualEntries; ulEntry++, pae++)
  3208. {
  3209. pPropDisp = NULL;
  3210. pPropEmail = NULL;
  3211. for (ulProp = 0, pProp = pae->rgPropVals; ulProp < pae->cValues && !(pPropDisp && pPropEmail); ulProp++, pProp++)
  3212. {
  3213. AssertSz(pProp->ulPropTag != PR_DISPLAY_NAME, "Have more cases to find.");
  3214. AssertSz(pProp->ulPropTag != PR_EMAIL_ADDRESS, "Have more cases to find.");
  3215. if (pProp->ulPropTag == PR_DISPLAY_NAME_W)
  3216. pPropDisp = pProp;
  3217. else if (pProp->ulPropTag == PR_EMAIL_ADDRESS_W)
  3218. pPropEmail = pProp;
  3219. }
  3220. if (pPropDisp && pPropEmail)
  3221. {
  3222. if (!StrCmpW(pPropDisp->Value.lpszW, pPropEmail->Value.lpszW))
  3223. pPropEmail->ulPropTag = PR_NULL;
  3224. }
  3225. }
  3226. }
  3227. /***************************************************************************
  3228. Name : FindX509CertTag
  3229. Purpose : Finds a tag inside the USER_X509_CERTIFICATE SBinary
  3230. Parameters: lpsb -> SBinary for a particular cert
  3231. ulTag = tag to search for
  3232. pcbReturn -> returned size (data only).
  3233. Returns : pointer into SBinary data location for the tag.
  3234. Comment :
  3235. ***************************************************************************/
  3236. LPBYTE FindX509CertTag(LPSBinary lpsb, ULONG ulTag, ULONG * pcbReturn) {
  3237. LPCERTTAGS lpCurrentTag = NULL;
  3238. LPBYTE lpbTagEnd = NULL;
  3239. LPBYTE lpbReturn = NULL;
  3240. *pcbReturn = 0;
  3241. Assert(lpsb->lpb[0] != 0x30); // Should have found this out before we got here.
  3242. if (lpsb && lpsb->cb && (lpsb->lpb[0] != 0x30))
  3243. {
  3244. lpCurrentTag = (LPCERTTAGS)lpsb->lpb;
  3245. lpbTagEnd = (LPBYTE)lpCurrentTag + lpsb->cb;
  3246. while ((LPBYTE)lpCurrentTag < lpbTagEnd && (ulTag != lpCurrentTag->tag))
  3247. {
  3248. if (lpCurrentTag->cbData == 0)
  3249. {
  3250. DOUTL(4, "Bad CertTag in PR_USER_X509_CERTIFICATE");
  3251. break; // Safety valve, prevent infinite loop if bad data
  3252. }
  3253. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + lpCurrentTag->cbData);
  3254. #ifdef _WIN64
  3255. lpCurrentTag = (LPCERTTAGS)MyPbAlignPb((BYTE*)lpCurrentTag);
  3256. #endif // _WIN64
  3257. }
  3258. // Did we find it?
  3259. if ((LPBYTE)lpCurrentTag < lpbTagEnd && ulTag == lpCurrentTag->tag && lpCurrentTag->cbData >= SIZE_CERTTAGS)
  3260. {
  3261. lpbReturn = (LPBYTE)lpCurrentTag->rgbData;
  3262. *pcbReturn = lpCurrentTag->cbData - SIZE_CERTTAGS;
  3263. }
  3264. }
  3265. return(lpbReturn);
  3266. }
  3267. /***************************************************************************
  3268. Name : GetX509CertTags
  3269. Purpose : Parses the PR_USER_X509_CERTIFICATE property value into
  3270. thumbprint, symcaps and signing time.
  3271. Parameters: lpsb -> SBinary for a particular cert
  3272. ptbCertificate -> returned thumbblob to write to. (required)
  3273. pblSymCaps -> returned symcaps blob. (optional)
  3274. pftSigningTime -> returned signing time (optional)
  3275. pfDefault -> returned default flag (optional)
  3276. Returns : HRESULT
  3277. Comment : Note that the blob props will be returned with pointers into
  3278. the lpsb data. Don't free them! Don't free the propvalue
  3279. prior to use!
  3280. ***************************************************************************/
  3281. HRESULT GetX509CertTags(LPSBinary lpsb, THUMBBLOB * ptbCertificate, BLOB * pblSymCaps, LPFILETIME pftSigningTime, BOOL * pfDefault) {
  3282. HRESULT hr = S_OK;
  3283. LPBYTE pbData;
  3284. ULONG cbData = 0;
  3285. Assert(ptbCertificate);
  3286. // Initialize the return values
  3287. ptbCertificate->pBlobData = NULL;
  3288. ptbCertificate->cbSize = 0;
  3289. if (pblSymCaps) {
  3290. pblSymCaps->pBlobData = NULL;
  3291. pblSymCaps->cbSize = 0;
  3292. }
  3293. if (pftSigningTime) {
  3294. pftSigningTime->dwLowDateTime = pftSigningTime->dwHighDateTime = 0;
  3295. }
  3296. if (pfDefault) {
  3297. *pfDefault = FALSE;
  3298. }
  3299. // Find the thumbprint. No thumbprint, no use trying other tags.
  3300. if (pbData = FindX509CertTag(lpsb, CERT_TAG_THUMBPRINT, &cbData)) {
  3301. ptbCertificate->pBlobData = pbData;
  3302. ptbCertificate->cbSize = cbData;
  3303. // Symcaps tag
  3304. if (pblSymCaps && (pbData = FindX509CertTag(lpsb, CERT_TAG_SYMCAPS, &cbData))) {
  3305. pblSymCaps->pBlobData = pbData;
  3306. pblSymCaps->cbSize = cbData;
  3307. }
  3308. // Signing time tag
  3309. if (pftSigningTime && (pbData = FindX509CertTag(lpsb, CERT_TAG_SIGNING_TIME, &cbData))) {
  3310. memcpy(pftSigningTime, &pbData, min(sizeof(FILETIME), cbData));
  3311. }
  3312. // scan for "default" tag
  3313. if (pfDefault && (pbData = FindX509CertTag(lpsb, CERT_TAG_DEFAULT, &cbData))) {
  3314. memcpy((void*)pfDefault, pbData, min(cbData, sizeof(*pfDefault)));
  3315. }
  3316. }
  3317. return(hr);
  3318. }
  3319. void ImportWAB(HWND hwnd)
  3320. {
  3321. WABIMPORTPARAM wip;
  3322. HRESULT hr;
  3323. hr = HrInitWab(TRUE);
  3324. if (FAILED(hr))
  3325. return;
  3326. // Verify Globals
  3327. if (!g_fWabLoaded || !g_fWabInit)
  3328. return;
  3329. EnterCriticalSection (&g_rWabCritSect);
  3330. if (g_lpWabObject != NULL && g_lpAdrBook != NULL)
  3331. {
  3332. wip.cbSize = sizeof(WABIMPORTPARAM);
  3333. wip.lpAdrBook = g_lpAdrBook;
  3334. wip.hWnd = hwnd;
  3335. wip.ulFlags = MAPI_DIALOG;
  3336. wip.lpszFileName = NULL;
  3337. // this is really intuitive. let's cast a struct to a string! yippee!
  3338. g_lpWabObject->Import((LPSTR)&wip);
  3339. }
  3340. LeaveCriticalSection (&g_rWabCritSect);
  3341. }
  3342. void Wab_CoDecrement()
  3343. {
  3344. // bug #59420, can't freelibrary the wab inside the wndproc
  3345. // so we post a decrement message to our init window and cleanup
  3346. // when the stack is unwound
  3347. if (g_pInstance)
  3348. CoDecrementInit("WabWindow", NULL);
  3349. }