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.

4439 lines
152 KiB

  1. /*
  2. * PAB.C
  3. *
  4. * Migrate PAB <-> WAB
  5. *
  6. * Copyright 1996-1997 Microsoft Corporation. All Rights Reserved.
  7. */
  8. #include "_comctl.h"
  9. #include <windows.h>
  10. #include <commctrl.h>
  11. #include <mapix.h>
  12. #include <wab.h>
  13. #include <wabguid.h>
  14. #include <wabdbg.h>
  15. #include <wabmig.h>
  16. #include <emsabtag.h>
  17. #include "..\..\wab32res\resrc2.h"
  18. #include "dbgutil.h"
  19. #include "wabimp.h"
  20. #include <shlwapi.h>
  21. void StateImportNextMU(HWND hwnd);
  22. void StateImportDL(HWND hwnd);
  23. void StateImportNextDL(HWND hwnd);
  24. void StateImportFinish(HWND hwnd);
  25. //void StateImportMU(HWND hwnd);
  26. void StateImportMU(HWND hwnd);
  27. void StateImportError(HWND hwnd);
  28. void StateImportCancel(HWND hwnd);
  29. BOOL HandleImportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
  30. LPTSTR lpEmailAddress, LPWAB_IMPORT_OPTIONS lpImportOptions);
  31. HRESULT ImportEntry(HWND hwnd,
  32. LPADRBOOK lpAdrBookMAPI,
  33. LPABCONT lpContainerWAB,
  34. LPSPropValue lpCreateEIDsWAB,
  35. ULONG ulObjectType,
  36. LPENTRYID lpEID,
  37. ULONG cbEID,
  38. LPENTRYID * lppEIDWAB,
  39. LPULONG lpcbEIDWAB,
  40. BOOL fInDL,
  41. BOOL fForceReplace);
  42. const UCHAR szQuote[] = "\"";
  43. LPPROP_NAME lpImportMapping = NULL;
  44. BOOL fError = FALSE;
  45. LPWABOBJECT lpWABObject = NULL;
  46. LPMAPISESSION lpMAPISession = NULL;
  47. LPADRBOOK lpAdrBookWAB = NULL, lpAdrBookMAPI = NULL;
  48. LPSPropValue lpCreateEIDsWAB = NULL, lpCreateEIDsMAPI = NULL;
  49. LPABCONT lpContainerWAB = NULL, lpContainerMAPI = NULL;
  50. LPMAPITABLE lpContentsTableWAB = NULL, lpContentsTableMAPI = NULL;
  51. ULONG ulcEntries = 0, ulcDone = 0;
  52. PAB_STATE State = STATE_IMPORT_FINISH;
  53. LPTSTR lpszWABFileName = NULL;
  54. LPWAB_PROGRESS_CALLBACK lpfnProgressCB = NULL;
  55. LPWAB_IMPORT_OPTIONS lpImportOptions = NULL;
  56. LPWAB_EXPORT_OPTIONS lpExportOptions = NULL;
  57. /*
  58. - The following IDs and tags are for the conferencing named properties
  59. -
  60. - The GUID for these props is PS_Conferencing
  61. */
  62. DEFINE_OLEGUID(PS_Conferencing, 0x00062004, 0, 0);
  63. #define CONF_SERVERS 0x8056
  64. #define OLK_NAMEDPROPS_START CONF_SERVERS
  65. ULONG PR_SERVERS;
  66. enum _ConferencingTags
  67. {
  68. prWABConfServers = 0,
  69. prWABConfMax
  70. };
  71. SizedSPropTagArray(prWABConfMax, ptaUIDetlsPropsConferencing);
  72. HRESULT HrLoadPrivateWABPropsForCSV(LPADRBOOK );
  73. // end conferencing duplication
  74. /***************************************************************************
  75. Name : NewState
  76. Purpose :
  77. Parameters: hwnd = window handle of Dialog (currently unused)
  78. NewState = new state to set
  79. Returns : none
  80. Comment :
  81. ***************************************************************************/
  82. __inline void NewState(HWND hwnd, PAB_STATE NewState) {
  83. // Old version
  84. // PostMessage(hwnd, WM_COMMAND, NewState, 0);
  85. State = NewState;
  86. UNREFERENCED_PARAMETER(hwnd);
  87. }
  88. /***************************************************************************
  89. Name : SetDialogMessage
  90. Purpose : Sets the message text for the dialog box item IDC_Message
  91. Parameters: hwnd = window handle of dialog
  92. ids = stringid of message resource
  93. Returns : none
  94. ***************************************************************************/
  95. void SetDialogMessage(HWND hwnd, int ids) {
  96. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  97. WAB_PROGRESS Progress = {0};
  98. Assert(lpfnProgressCB);
  99. if (lpfnProgressCB && LoadString(hInst, ids, szBuffer, ARRAYSIZE(szBuffer))) {
  100. DebugTrace("Status Message: %s\n", szBuffer);
  101. Progress.lpText = szBuffer;
  102. lpfnProgressCB(hwnd, &Progress);
  103. } else {
  104. DebugTrace("Cannot load resource string %u\n", ids);
  105. Assert(FALSE);
  106. }
  107. }
  108. /***************************************************************************
  109. Name : SetDialogProgress
  110. Purpose : Sets progress bar
  111. Parameters: hwnd = window handle of dialog
  112. ulTotal = total entries
  113. ulDone = finished entries
  114. Returns : none
  115. ***************************************************************************/
  116. void SetDialogProgress(HWND hwnd, ULONG ulTotal, ULONG ulDone) {
  117. WAB_PROGRESS Progress = {0};
  118. Assert(lpfnProgressCB);
  119. if (lpfnProgressCB) {
  120. Progress.denominator = ulTotal;
  121. Progress.numerator = ulDone;
  122. lpfnProgressCB(hwnd, &Progress);
  123. }
  124. }
  125. /***************************************************************************
  126. Name : AddEntryToImportList
  127. Purpose : Checks this entry against our "seen" list and adds it.
  128. Parameters: cbEID = size of lpEID
  129. lpEID -> EntryID of entry
  130. lplIndex -> returned list index (or -1 on error)
  131. Returns : TRUE if entry already exists
  132. Comment : Caller must mark the WAB entry!
  133. ***************************************************************************/
  134. #define GROW_SIZE 10
  135. BOOL AddEntryToImportList(ULONG cbEID, LPENTRYID lpEID, LPLONG lplIndex) {
  136. ULONG i;
  137. LPENTRY_SEEN lpEntrySeen;
  138. if (cbEID && lpEID) {
  139. for (i = 0; i < ulEntriesSeen; i++) {
  140. if (cbEID == lpEntriesSeen[i].sbinPAB.cb && (! memcmp(lpEID, lpEntriesSeen[i].sbinPAB.lpb, cbEID))) {
  141. // This one's in the list
  142. *lplIndex = i;
  143. // If cb 0, we must have recursed and are replacing, so this one is not a dup.
  144. return(lpEntriesSeen[i].sbinWAB.cb != 0);
  145. }
  146. }
  147. // Add to the end of the list
  148. if (++ulEntriesSeen > ulMaxEntries) {
  149. // Grow the array.
  150. ulMaxEntries += GROW_SIZE;
  151. if (lpEntriesSeen) {
  152. if (! (lpEntrySeen = LocalReAlloc(lpEntriesSeen, ulMaxEntries * sizeof(ENTRY_SEEN), LMEM_MOVEABLE | LMEM_ZEROINIT))) {
  153. DebugTrace("LocalReAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
  154. goto error;
  155. }
  156. lpEntriesSeen = lpEntrySeen;
  157. } else {
  158. if (! (lpEntriesSeen = LocalAlloc(LPTR, ulMaxEntries * sizeof(ENTRY_SEEN)))) {
  159. DebugTrace("LocalAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
  160. goto error;
  161. }
  162. }
  163. }
  164. lpEntrySeen = &lpEntriesSeen[ulEntriesSeen - 1];
  165. // Allocate space for data
  166. lpEntrySeen->sbinPAB.cb = cbEID;
  167. if (! (lpEntrySeen->sbinPAB.lpb = LocalAlloc(LPTR, cbEID))) {
  168. DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
  169. goto error;
  170. }
  171. // Mark as unknown WAB entry
  172. lpEntrySeen->sbinWAB.cb = 0;
  173. lpEntrySeen->sbinWAB.lpb = 0;
  174. // Copy in the data
  175. CopyMemory(lpEntrySeen->sbinPAB.lpb, lpEID, cbEID);
  176. *lplIndex = i;
  177. }
  178. return(FALSE);
  179. error:
  180. // undo the damage...
  181. --ulEntriesSeen;
  182. ulMaxEntries -= GROW_SIZE;
  183. *lplIndex = -1; // error
  184. if (! lpEntriesSeen) {
  185. ulEntriesSeen = 0; // pointer is null now, back to square one.
  186. ulMaxEntries = 0;
  187. }
  188. return(FALSE);
  189. }
  190. /***************************************************************************
  191. Name : MarkWABEntryInList
  192. Purpose : Marks the WAB entry fields in the list node
  193. Parameters: cbEID = size of lpEID
  194. lpEID -> EntryID of entry
  195. lIndex = list index (or -1 on error)
  196. Returns : none
  197. Comment :
  198. ***************************************************************************/
  199. void MarkWABEntryInList(ULONG cbEID, LPENTRYID lpEID, LONG lIndex) {
  200. if (lIndex != -1 && cbEID) {
  201. if (! (lpEntriesSeen[lIndex].sbinWAB.lpb = LocalAlloc(LPTR, cbEID))) {
  202. DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
  203. // leave it null
  204. } else {
  205. lpEntriesSeen[lIndex].sbinWAB.cb = cbEID;
  206. // Copy in the data
  207. CopyMemory(lpEntriesSeen[lIndex].sbinWAB.lpb, lpEID, cbEID);
  208. }
  209. }
  210. }
  211. /***************************************************************************
  212. Name : StateImportMU
  213. Purpose : Start the migration of MailUsers
  214. Parameters: hwnd = window handle of Import Dialog
  215. lpszFileName - FileName of WAB File to open
  216. Returns : none
  217. Comment : Login to MAPI
  218. Open the WAB
  219. Open the MAPI AB
  220. Open the WAB container
  221. Get the MAPI PAB contents table
  222. Restrict it to PR_OBJECTTYPE == MAPI_MAILUSER
  223. Post new state(STATE_NEXT_MU)
  224. ***************************************************************************/
  225. void StateImportMU(HWND hwnd) {
  226. HRESULT hResult;
  227. ULONG ulFlags;
  228. ULONG cbPABEID, cbWABEID;
  229. LPENTRYID lpPABEID = NULL;
  230. ULONG ulObjType;
  231. ULONG_PTR ulUIParam = (ULONG_PTR)(void *)hwnd;
  232. SRestriction restrictObjectType;
  233. SPropValue spvObjectType;
  234. ULONG cProps;
  235. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  236. WAB_PARAM wp = {0};
  237. LPWAB_PARAM lpwp = NULL;
  238. //
  239. // Logon to MAPI and open the MAPI Address book, if one exists
  240. //
  241. DebugTrace(">>> STATE_IMPORT_MU\n");
  242. SetDialogMessage(hwnd, IDS_STATE_LOGGING_IN);
  243. if (FAILED(hResult = MAPIInitialize(NULL))) {
  244. DebugTrace("MAPIInitialize -> %x\n", GetScode(hResult));
  245. switch (GetScode(hResult)) {
  246. case MAPI_E_NOT_ENOUGH_MEMORY:
  247. SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_MEMORY);
  248. break;
  249. case MAPI_E_NOT_ENOUGH_DISK:
  250. SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_DISK);
  251. break;
  252. default:
  253. case MAPI_E_NOT_FOUND:
  254. case MAPI_E_NOT_INITIALIZED:
  255. SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
  256. break;
  257. }
  258. #ifdef OLD_STUFF
  259. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
  260. #endif // OLD_STUFF
  261. fError = TRUE;
  262. hResult = hrSuccess;
  263. goto exit;
  264. }
  265. ulFlags = MAPI_LOGON_UI | MAPI_NO_MAIL | MAPI_EXTENDED;
  266. if (FAILED(hResult = MAPILogonEx(ulUIParam,
  267. NULL,
  268. NULL,
  269. ulFlags,
  270. (LPMAPISESSION FAR *)&lpMAPISession))) {
  271. DebugTrace("MAPILogonEx -> %x\n", GetScode(hResult));
  272. switch (GetScode(hResult)) {
  273. case MAPI_E_USER_CANCEL:
  274. SetDialogMessage(hwnd, IDS_STATE_IMPORT_IDLE);
  275. break;
  276. case MAPI_E_NOT_INITIALIZED:
  277. SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
  278. break;
  279. default:
  280. SetDialogMessage(hwnd, IDS_ERROR_MAPI_LOGON);
  281. break;
  282. }
  283. #ifdef OLD_STUFF
  284. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
  285. #endif // OLD_STUFF
  286. fError = TRUE;
  287. hResult = hrSuccess;
  288. goto exit;
  289. }
  290. if (hResult = lpMAPISession->lpVtbl->OpenAddressBook(lpMAPISession, (ULONG_PTR)(void *)hwnd,
  291. NULL,
  292. 0,
  293. &lpAdrBookMAPI)) {
  294. DebugTrace("OpenAddressBook(MAPI) -> %x", GetScode(hResult));
  295. if(FAILED(hResult)) {
  296. goto exit;
  297. }
  298. }
  299. if (! lpAdrBookMAPI) {
  300. DebugTrace("MAPILogonEx didn't return a valid AdrBook object\n");
  301. goto exit;
  302. }
  303. //
  304. // Open the MAPI PAB container
  305. //
  306. // [PaulHi] Raid #63578 1/7/98
  307. // Correctly check return code and provide user error message if
  308. // Exchange PAB cannot be opened.
  309. //
  310. hResult = lpAdrBookMAPI->lpVtbl->GetPAB(lpAdrBookMAPI,
  311. &cbPABEID,
  312. &lpPABEID);
  313. if (HR_FAILED(hResult))
  314. {
  315. DebugTrace("MAPI GetPAB -> %x\n", GetScode(hResult));
  316. goto exit;
  317. }
  318. hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
  319. cbPABEID, // size of EntryID to open
  320. lpPABEID, // EntryID to open
  321. NULL, // interface
  322. 0, // flags
  323. &ulObjType,
  324. (LPUNKNOWN *)&lpContainerMAPI);
  325. if (HR_FAILED(hResult))
  326. {
  327. DebugTrace("MAPI OpenEntry(PAB) -> %x\n", GetScode(hResult));
  328. goto exit;
  329. }
  330. Assert(lpAdrBookWAB);
  331. //
  332. // Open the WAB's PAB container: fills global lpCreateEIDsWAB
  333. //
  334. if (hResult = LoadWABEIDs(lpAdrBookWAB, &lpContainerWAB)) {
  335. goto exit;
  336. }
  337. HrLoadPrivateWABPropsForCSV(lpAdrBookWAB);
  338. //
  339. // All set... now loop through the PAB's entries, copying them to WAB
  340. //
  341. if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->GetContentsTable(lpContainerMAPI,
  342. 0, // ulFlags
  343. &lpContentsTableMAPI))) {
  344. DebugTrace("MAPI GetContentsTable(PAB Table) -> %x\n", GetScode(hResult));
  345. goto exit;
  346. }
  347. // Set the columns to those we're interested in
  348. if (hResult = lpContentsTableMAPI->lpVtbl->SetColumns(lpContentsTableMAPI,
  349. (LPSPropTagArray)&ptaColumns,
  350. 0)) {
  351. DebugTrace("MAPI SetColumns(PAB Table) -> %x\n", GetScode(hResult));
  352. goto exit;
  353. }
  354. // Restrict the table to MAPI_MAILUSERs
  355. // If the convenient depth flag was not specified we restrict on
  356. // PR_DEPTH == 1.
  357. spvObjectType.ulPropTag = PR_OBJECT_TYPE;
  358. spvObjectType.Value.l = MAPI_MAILUSER;
  359. restrictObjectType.rt = RES_PROPERTY;
  360. restrictObjectType.res.resProperty.relop = RELOP_EQ;
  361. restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
  362. restrictObjectType.res.resProperty.lpProp = &spvObjectType;
  363. if (HR_FAILED(hResult = lpContentsTableMAPI->lpVtbl->Restrict(lpContentsTableMAPI,
  364. &restrictObjectType,
  365. 0))) {
  366. DebugTrace("MAPI Restrict (MAPI_MAILUSER) -> %x\n", GetScode(hResult));
  367. goto exit;
  368. }
  369. SetDialogMessage(hwnd, IDS_STATE_IMPORT_MU);
  370. // Initialize the Progress Bar
  371. // How many MailUser entries are there?
  372. ulcEntries = CountRows(lpContentsTableMAPI, TRUE);
  373. ulcDone = 0;
  374. DebugTrace("PAB contains %u MailUser entries\n", ulcEntries);
  375. SetDialogProgress(hwnd, ulcEntries, 0);
  376. exit:
  377. if (lpPABEID) {
  378. MAPIFreeBuffer(lpPABEID);
  379. }
  380. // On error, set the state to STATE_ERROR
  381. if (HR_FAILED(hResult))
  382. {
  383. if (GetScode(hResult) == MAPI_E_USER_CANCEL)
  384. {
  385. NewState(hwnd, STATE_IMPORT_CANCEL);
  386. }
  387. else
  388. {
  389. // [PaulHi] 1/7/98 Error reporting is hosed
  390. // Display error message here to the user to ensure they
  391. // get it.
  392. {
  393. TCHAR tszBuffer[MAX_RESOURCE_STRING];
  394. TCHAR tszBufferTitle[MAX_RESOURCE_STRING];
  395. if ( !LoadString(hInst, IDS_STATE_IMPORT_ERROR_NOPAB, tszBuffer, MAX_RESOURCE_STRING-1) )
  396. {
  397. Assert(0);
  398. tszBuffer[0] = '\0';
  399. }
  400. if ( !LoadString(hInst, IDS_APP_TITLE, tszBufferTitle, MAX_RESOURCE_STRING-1) )
  401. {
  402. Assert(0);
  403. tszBufferTitle[0] = '\0';
  404. }
  405. MessageBox(hwnd, tszBuffer, tszBufferTitle, MB_ICONEXCLAMATION | MB_OK);
  406. }
  407. NewState(hwnd, STATE_IMPORT_ERROR);
  408. }
  409. }
  410. else if (fError)
  411. {
  412. NewState(hwnd, STATE_IMPORT_FINISH); // must be logon error
  413. }
  414. else
  415. {
  416. NewState(hwnd, STATE_IMPORT_NEXT_MU);
  417. }
  418. }
  419. /***************************************************************************
  420. Name : StateImportNextMU
  421. Purpose : Migrate the next MailUser object
  422. Parameters: hwnd = window handle of Import Dialog
  423. Returns : none
  424. Comment : QueryRows on the global MAPI contents table
  425. if there was a row
  426. Migrate the entry to the WAB
  427. Re-post STATE_NEXT_MU
  428. else
  429. Post STATE_IMPORT_DL
  430. ***************************************************************************/
  431. void StateImportNextMU(HWND hwnd) {
  432. ULONG cRows = 0;
  433. HRESULT hResult;
  434. LPSRowSet lpRow = NULL;
  435. DebugTrace(">>> STATE_NEXT_MU\n");
  436. // Get the next PAB entry
  437. if (hResult = lpContentsTableMAPI->lpVtbl->QueryRows(lpContentsTableMAPI,
  438. 1, // one row at a time
  439. 0, // ulFlags
  440. &lpRow)) {
  441. DebugTrace("QueryRows -> %x\n", GetScode(hResult));
  442. goto exit;
  443. }
  444. if (lpRow) {
  445. if (cRows = lpRow->cRows) { // Yes, single '='
  446. Assert(lpRow->cRows == 1);
  447. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  448. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  449. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  450. if (cRows = lpRow->cRows) { // yes, single '='
  451. hResult = ImportEntry(hwnd,
  452. lpAdrBookMAPI,
  453. lpContainerWAB,
  454. lpCreateEIDsWAB,
  455. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  456. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  457. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  458. NULL,
  459. NULL,
  460. FALSE,
  461. FALSE);
  462. // Update Progress Bar
  463. // ignore errors!
  464. SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
  465. if (hResult) {
  466. if (HandleImportError(hwnd,
  467. 0,
  468. hResult,
  469. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  470. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  471. lpImportOptions)) {
  472. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  473. } else {
  474. hResult = hrSuccess;
  475. }
  476. }
  477. } // else, drop out of loop, we're done.
  478. }
  479. FreeProws(lpRow);
  480. }
  481. exit:
  482. // On error, set the state to STATE_ERROR
  483. if (HR_FAILED(hResult)) {
  484. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  485. NewState(hwnd, STATE_IMPORT_CANCEL);
  486. } else {
  487. NewState(hwnd, STATE_IMPORT_ERROR);
  488. }
  489. } else {
  490. if (cRows) {
  491. NewState(hwnd, STATE_IMPORT_NEXT_MU);
  492. } else {
  493. NewState(hwnd, STATE_IMPORT_DL);
  494. }
  495. }
  496. }
  497. /***************************************************************************
  498. Name : StateImportDL
  499. Purpose : Start migration of DISTLIST objects
  500. Parameters: hwnd = window handle of Import Dialog
  501. Returns : none
  502. Comment : Set a new restriction on the contents table, selecting
  503. DISTLIST objects only.
  504. Post STATE_NEXT_DL
  505. ***************************************************************************/
  506. void StateImportDL(HWND hwnd) {
  507. HRESULT hResult;
  508. SRestriction restrictObjectType;
  509. SPropValue spvObjectType;
  510. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  511. DebugTrace(">>> STATE_IMPORT_DL\n");
  512. // Restrict the table to MAPI_MAILUSERs
  513. // If the convenient depth flag was not specified we restrict on
  514. // PR_DEPTH == 1.
  515. spvObjectType.ulPropTag = PR_OBJECT_TYPE;
  516. spvObjectType.Value.l = MAPI_DISTLIST;
  517. restrictObjectType.rt = RES_PROPERTY;
  518. restrictObjectType.res.resProperty.relop = RELOP_EQ;
  519. restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
  520. restrictObjectType.res.resProperty.lpProp = &spvObjectType;
  521. if (HR_FAILED(hResult = lpContentsTableMAPI->lpVtbl->Restrict(lpContentsTableMAPI,
  522. &restrictObjectType,
  523. 0))) {
  524. DebugTrace("MAPI Restrict (MAPI_DISTLIST) -> %x\n", GetScode(hResult));
  525. goto exit;
  526. }
  527. // Restrict resets the current position to the beginning of the table, by definition.
  528. SetDialogMessage(hwnd, IDS_STATE_IMPORT_DL);
  529. // Initialize the Progress Bar
  530. // How many entries are there?
  531. ulcEntries = CountRows(lpContentsTableMAPI, TRUE);
  532. ulcDone = 0;
  533. DebugTrace("PAB contains %u Distribution List entries\n", ulcEntries);
  534. if (ulcEntries) {
  535. SetDialogProgress(hwnd, ulcEntries, 0);
  536. }
  537. exit:
  538. // On error, set the state to STATE_ERROR
  539. if (HR_FAILED(hResult)) {
  540. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  541. NewState(hwnd, STATE_IMPORT_CANCEL);
  542. } else {
  543. NewState(hwnd, STATE_IMPORT_ERROR);
  544. }
  545. } else {
  546. NewState(hwnd, STATE_IMPORT_NEXT_DL);
  547. }
  548. }
  549. /***************************************************************************
  550. Name : StateImportNextDL
  551. Purpose : Migrate the next DISTLIST object
  552. Parameters: hwnd = window handle of Import Dialog
  553. Returns : none
  554. Comment : QueryRows on the global MAPI contents table
  555. if there was a row
  556. Migrate the DistList to the WAB
  557. Re-post STATE_NEXT_DL
  558. else
  559. Post STATE_FINISH
  560. ***************************************************************************/
  561. void StateImportNextDL(HWND hwnd) {
  562. ULONG cRows = 0;
  563. HRESULT hResult;
  564. LPSRowSet lpRow = NULL;
  565. DebugTrace(">>> STATE_NEXT_DL\n");
  566. // Get the next PAB entry
  567. if (hResult = lpContentsTableMAPI->lpVtbl->QueryRows(lpContentsTableMAPI,
  568. 1, // one row at a time
  569. 0, // ulFlags
  570. &lpRow)) {
  571. DebugTrace("QueryRows -> %x\n", GetScode(hResult));
  572. goto exit;
  573. }
  574. if (lpRow) {
  575. if (cRows = lpRow->cRows) { // Yes, single '='
  576. Assert(lpRow->cRows == 1);
  577. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  578. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  579. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  580. if (cRows = lpRow->cRows) { // yes, single '='
  581. hResult = ImportEntry(hwnd,
  582. lpAdrBookMAPI,
  583. lpContainerWAB,
  584. lpCreateEIDsWAB,
  585. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  586. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  587. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  588. NULL,
  589. NULL,
  590. FALSE,
  591. FALSE);
  592. // Update Progress Bar
  593. SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
  594. if (hResult) {
  595. if (HandleImportError(hwnd,
  596. 0,
  597. hResult,
  598. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  599. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  600. lpImportOptions)) {
  601. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  602. } else {
  603. hResult = hrSuccess;
  604. }
  605. }
  606. } // else, drop out of loop, we're done.
  607. }
  608. FreeProws(lpRow);
  609. }
  610. exit:
  611. // On error, set the state to STATE_ERROR
  612. if (HR_FAILED(hResult)) {
  613. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  614. NewState(hwnd, STATE_IMPORT_CANCEL);
  615. } else {
  616. NewState(hwnd, STATE_IMPORT_ERROR);
  617. }
  618. } else {
  619. if (cRows) {
  620. NewState(hwnd, STATE_IMPORT_NEXT_DL);
  621. } else {
  622. // Update Progress Bar to indicate completion
  623. SetDialogProgress(hwnd, ulcEntries, ulcEntries);
  624. NewState(hwnd, STATE_IMPORT_FINISH);
  625. }
  626. }
  627. }
  628. /***************************************************************************
  629. Name : StateImportFinish
  630. Purpose : Clean up after the migration process
  631. Parameters: hwnd = window handle of Import Dialog
  632. Returns : none
  633. Comment : Clean up the global MAPI objects and buffers
  634. Clean up the global WAB objects and buffers.
  635. Re-enable the Import button on the UI.
  636. ***************************************************************************/
  637. void StateImportFinish(HWND hwnd) {
  638. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  639. TCHAR szBufferTitle[MAX_RESOURCE_STRING + 1];
  640. DebugTrace(">>> STATE_FINISH\n");
  641. //
  642. // Cleanup MAPI
  643. //
  644. if (lpContentsTableMAPI) {
  645. lpContentsTableMAPI->lpVtbl->Release(lpContentsTableMAPI);
  646. lpContentsTableMAPI = NULL;
  647. }
  648. if (lpContainerMAPI) {
  649. lpContainerMAPI->lpVtbl->Release(lpContainerMAPI);
  650. lpContainerMAPI = NULL;
  651. }
  652. if (lpAdrBookMAPI) {
  653. lpAdrBookMAPI->lpVtbl->Release(lpAdrBookMAPI);
  654. lpAdrBookMAPI = NULL;
  655. }
  656. if(lpMAPISession){
  657. lpMAPISession->lpVtbl->Logoff(lpMAPISession, (ULONG_PTR)(void *)hwnd,
  658. MAPI_LOGOFF_UI,
  659. 0);
  660. lpMAPISession->lpVtbl->Release(lpMAPISession);
  661. lpMAPISession = NULL;
  662. }
  663. //
  664. // Cleanup the WAB
  665. //
  666. if (lpCreateEIDsWAB) {
  667. WABFreeBuffer(lpCreateEIDsWAB);
  668. lpCreateEIDsWAB = NULL;
  669. }
  670. if (lpContainerWAB) {
  671. lpContainerWAB->lpVtbl->Release(lpContainerWAB);
  672. lpContainerWAB = NULL;
  673. }
  674. #ifdef OLD_STUFF // Don't release the WABObject or AdrBook object. They
  675. // were passed in.
  676. if (lpAdrBookWAB) {
  677. lpAdrBookWAB->lpVtbl->Release(lpAdrBookWAB);
  678. lpAdrBookWAB = NULL;
  679. }
  680. if (lpWABObject) {
  681. lpWABObject->lpVtbl->Release(lpWABObject);
  682. lpWABObject = NULL;
  683. }
  684. #endif // OLD_STUFF
  685. // Cleanup the cache
  686. FreeSeenList();
  687. if (! fError) { // Leave error state displayed
  688. if (LoadString(hInst, IDS_STATE_IMPORT_COMPLETE, szBuffer, ARRAYSIZE(szBuffer))) {
  689. DebugTrace("Status Message: %s\n", szBuffer);
  690. SetDlgItemText(hwnd, IDC_Message, szBuffer);
  691. if (! LoadString(hInst, IDS_APP_TITLE, szBufferTitle, ARRAYSIZE(szBufferTitle))) {
  692. StrCpyN(szBufferTitle, "", ARRAYSIZE(szBufferTitle));
  693. }
  694. #ifdef OLD_STUFF
  695. // Display a dialog telling user it's over
  696. MessageBox(hwnd, szBuffer,
  697. szBufferTitle, MB_ICONINFORMATION | MB_OK);
  698. #endif // OLD_STUFF
  699. }
  700. #ifdef OLD_STUFF
  701. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE);
  702. #endif // OLD_STUFF
  703. }
  704. fError = FALSE;
  705. // Re-enable the Import button here.
  706. EnableWindow(GetDlgItem(hwnd, IDC_Import), TRUE);
  707. // Change the Cancel button to Close
  708. if (LoadString(hInst, IDS_BUTTON_CLOSE, szBuffer, ARRAYSIZE(szBuffer))) {
  709. SetDlgItemText(hwnd, IDCANCEL, szBuffer);
  710. }
  711. }
  712. /***************************************************************************
  713. Name : StateImportError
  714. Purpose : Report fatal error and cleanup.
  715. Parameters: hwnd = window handle of Import Dialog
  716. Returns : none
  717. Comment : Report error and post STATE_FINISH.
  718. ***************************************************************************/
  719. void StateImportError(HWND hwnd) {
  720. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  721. // Set some global flag and set state to finish
  722. DebugTrace(">>> STATE_ERROR\n");
  723. fError = TRUE;
  724. SetDialogMessage(hwnd, IDS_STATE_IMPORT_ERROR);
  725. NewState(hwnd, STATE_IMPORT_FINISH);
  726. }
  727. /***************************************************************************
  728. Name : StateImportCancel
  729. Purpose : Report cancel error and cleanup.
  730. Parameters: hwnd = window handle of Import Dialog
  731. Returns : none
  732. Comment : Report error and post STATE_FINISH.
  733. ***************************************************************************/
  734. void StateImportCancel(HWND hwnd) {
  735. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  736. // Set some global flag and set state to finish
  737. DebugTrace(">>> STATE_CANCEL\n");
  738. fError = TRUE;
  739. SetDialogMessage(hwnd, IDS_STATE_IMPORT_CANCEL);
  740. NewState(hwnd, STATE_IMPORT_FINISH);
  741. }
  742. /***************************************************************************
  743. Name : HrFilterImportMailUserProps
  744. Purpose : Filters out undesirable properties from the property array.
  745. Converts known email address types to SMTP.
  746. Moves FAX address to PR_BUSINESS_FAX_NUMBER.
  747. Parameters: lpcProps -> IN: Input number of properties
  748. OUT: Output number of properties
  749. lppProps -> IN: Input property array (MAPI allocation)
  750. OUT: Output property array (WAB allocation)
  751. lpObjectMAPI -> MAPI object (used to get extra props)
  752. lpfDL -> flag to set FALSE if we change a DL to a MAILUSER
  753. (ie, for an EXchange DL)
  754. Returns : HRESULT
  755. Comment : Setting the property tag in the array to PR_NULL effectively
  756. nulls this property out. We can re-use these in the second
  757. pass.
  758. Caller should use WABFreeBuffer to free *lppProps.
  759. This routine will free the input value of *lppProps.
  760. ***************************************************************************/
  761. HRESULT HrFilterImportMailUserProps(LPULONG lpcProps, LPSPropValue * lppProps,
  762. LPMAPIPROP lpObjectMAPI, LPBOOL lpfDL) {
  763. HRESULT hResult = hrSuccess;
  764. ULONG i;
  765. LPSPropValue lpPropsMAPI = *lppProps, lpPropsWAB = NULL;
  766. ULONG cbProps;
  767. SCODE sc;
  768. ULONG cProps = *lpcProps;
  769. ULONG iPR_ADDRTYPE = NOT_FOUND;
  770. ULONG iPR_EMAIL_ADDRESS = NOT_FOUND;
  771. ULONG iPR_PRIMARY_FAX_NUMBER = NOT_FOUND;
  772. ULONG iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
  773. ULONG iPR_MSNINET_DOMAIN = NOT_FOUND;
  774. ULONG iPR_MSNINET_ADDRESS = NOT_FOUND;
  775. ULONG iPR_DISPLAY_NAME = NOT_FOUND;
  776. ULONG iPR_OBJECT_TYPE = NOT_FOUND;
  777. LPSBinary lpEntryID = NULL;
  778. LPTSTR lpTemp;
  779. BOOL fBadAddress = FALSE;
  780. ULONG cbDisplayName;
  781. LPTSTR lpDisplayName = NULL;
  782. // MAPIDebugProperties(lpPropsMAPI, *lpcProps, "MailUser BEFORE");
  783. // First pass: Remove the junk
  784. for (i = 0; i < cProps; i++) {
  785. // Error value
  786. if (PROP_ERROR(lpPropsMAPI[i])) {
  787. lpPropsMAPI[i].ulPropTag = PR_NULL;
  788. continue;
  789. }
  790. // Named property
  791. if (PROP_ID(lpPropsMAPI[i].ulPropTag) >= MIN_NAMED_PROPID) {
  792. lpPropsMAPI[i].ulPropTag = PR_NULL;
  793. continue;
  794. }
  795. // Object property
  796. if (PROP_TYPE(lpPropsMAPI[i].ulPropTag) == PT_OBJECT) {
  797. lpPropsMAPI[i].ulPropTag = PR_NULL;
  798. continue;
  799. }
  800. switch (lpPropsMAPI[i].ulPropTag) {
  801. case PR_ENTRYID:
  802. lpEntryID = &lpPropsMAPI[i].Value.bin;
  803. // fall through
  804. case PR_PRIMARY_CAPABILITY:
  805. case PR_TEMPLATEID:
  806. case PR_SEARCH_KEY:
  807. case PR_INITIAL_DETAILS_PANE:
  808. case PR_RECORD_KEY:
  809. case PR_MAPPING_SIGNATURE:
  810. lpPropsMAPI[i].ulPropTag = PR_NULL;
  811. break;
  812. case PR_COMMENT:
  813. // Don't save PR_COMMENT if it is empty
  814. if (lstrlen(lpPropsMAPI[i].Value.LPSZ) == 0) {
  815. lpPropsMAPI[i].ulPropTag = PR_NULL;
  816. }
  817. break;
  818. // Keep track of the position of these for later
  819. case PR_ADDRTYPE:
  820. iPR_ADDRTYPE = i;
  821. break;
  822. case PR_OBJECT_TYPE:
  823. iPR_OBJECT_TYPE = i;
  824. break;
  825. case PR_EMAIL_ADDRESS:
  826. iPR_EMAIL_ADDRESS = i;
  827. break;
  828. case PR_PRIMARY_FAX_NUMBER:
  829. iPR_PRIMARY_FAX_NUMBER = i;
  830. break;
  831. case PR_BUSINESS_FAX_NUMBER:
  832. iPR_BUSINESS_FAX_NUMBER = i;
  833. break;
  834. case PR_MSNINET_ADDRESS:
  835. iPR_MSNINET_ADDRESS = i;
  836. break;
  837. case PR_MSNINET_DOMAIN:
  838. iPR_MSNINET_DOMAIN = i;
  839. break;
  840. case PR_DISPLAY_NAME:
  841. iPR_DISPLAY_NAME = i;
  842. // Make sure it isn't quoted.
  843. lpDisplayName = lpPropsMAPI[i].Value.LPSZ;
  844. if (lpDisplayName[0] == '\'') {
  845. cbDisplayName = lstrlen(lpDisplayName);
  846. if ((cbDisplayName > 1) && lpDisplayName[cbDisplayName - 1] == '\'') {
  847. // String is surrounded by apostrophes. Strip them.
  848. lpDisplayName[cbDisplayName - 1] = '\0';
  849. lpDisplayName++;
  850. lpPropsMAPI[i].Value.LPSZ = lpDisplayName;
  851. }
  852. } else {
  853. if (lpDisplayName[0] == '"') {
  854. cbDisplayName = lstrlen(lpDisplayName);
  855. if ((cbDisplayName > 1) && lpDisplayName[cbDisplayName - 1] == '"') {
  856. // String is surrounded by quotes. Strip them.
  857. lpDisplayName[cbDisplayName - 1] = '\0';
  858. lpDisplayName++;
  859. lpPropsMAPI[i].Value.LPSZ = lpDisplayName;
  860. }
  861. }
  862. }
  863. break;
  864. }
  865. // Put this after the switch since we do want to track a few props which fall in
  866. // the 0x6000 range but don't want to transfer them to the wab.
  867. if (PROP_ID(lpPropsMAPI[i].ulPropTag) >= MAX_SCHEMA_PROPID) {
  868. lpPropsMAPI[i].ulPropTag = PR_NULL;
  869. continue;
  870. }
  871. }
  872. // Second pass: Fix up the addresses
  873. if (iPR_ADDRTYPE != NOT_FOUND) {
  874. if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szFAX)) {
  875. DebugTrace("FAX address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  876. //
  877. // Handle MS-FAX Address conversion
  878. //
  879. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  880. // Rename the PR_EMAIL_ADDRESS to PR_BUSINESS_FAX_NUMBER
  881. lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_BUSINESS_FAX_NUMBER;
  882. // Get rid of any existing PR_BUSINESS_FAX_NUMBER
  883. if (iPR_BUSINESS_FAX_NUMBER != NOT_FOUND) {
  884. lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].ulPropTag = PR_NULL;
  885. iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
  886. }
  887. }
  888. // Nuke ADDRTYPE
  889. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  890. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSN)) {
  891. ULONG cchSize = lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ) + 1 + cbMSNpostfix ;
  892. DebugTrace("MSN address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  893. //
  894. // Handle MSN Address conversion
  895. //
  896. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  897. // Allocate a new, longer string
  898. if (FAILED(sc = MAPIAllocateMore(
  899. sizeof(TCHAR) * cchSize,
  900. lpPropsMAPI,
  901. &lpTemp))) {
  902. DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
  903. hResult = ResultFromScode(sc);
  904. goto exit;
  905. }
  906. // append the msn site
  907. StrCpyN(lpTemp, lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ, cchSize);
  908. StrCatBuff(lpTemp, szMSNpostfix, cchSize);
  909. lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
  910. // Convert MSN addrtype to SMTP
  911. lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
  912. } else {
  913. // No address, nuke ADDRTYPE
  914. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  915. }
  916. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szCOMPUSERVE)) {
  917. ULONG cchSize = lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ) + 1 + cbCOMPUSERVEpostfix;
  918. DebugTrace("COMPUSERVE address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  919. //
  920. // Handle COMPUSERVE Address conversion
  921. //
  922. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  923. // Allocate a new, longer string
  924. if (FAILED(sc = MAPIAllocateMore(
  925. sizeof(TCHAR)*cchSize,
  926. lpPropsMAPI,
  927. &lpTemp))) {
  928. DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
  929. hResult = ResultFromScode(sc);
  930. goto exit;
  931. }
  932. // append the Compuserve site
  933. StrCpyN(lpTemp, lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ, cchSize);
  934. StrCatBuff(lpTemp, szCOMPUSERVEpostfix, cchSize);
  935. lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
  936. // I need to convert the ',' to a '.'
  937. while (*lpTemp) {
  938. if (*lpTemp == ',') {
  939. *lpTemp = '.';
  940. break; // should only be one comma
  941. }
  942. lpTemp = CharNext(lpTemp);
  943. }
  944. // Convert COMPUSERVE addrtype to SMTP
  945. lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
  946. } else {
  947. // No address, nuke ADDRTYPE
  948. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  949. }
  950. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSNINET)) {
  951. ULONG cchSize =
  952. lstrlen(lpPropsMAPI[iPR_MSNINET_ADDRESS].Value.LPSZ) + cbAtSign +
  953. lstrlen(lpPropsMAPI[iPR_MSNINET_DOMAIN].Value.LPSZ) + 1;
  954. DebugTrace("MSINET address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  955. //
  956. // Handle MSN Internet address conversion. These are weird.
  957. // They often don't fill in the PR_EMAIL_ADDRESS at all, but do fill
  958. // in some private properties: 6001 and 6002 with the name and domain,
  959. // respectively. We should take these and append them with the '@' to
  960. // get our PR_EMAIL_ADDRESS. We will toss out any existing
  961. // PR_EMAIL_ADDRESS in favor of these values.
  962. //
  963. // Allocate a new string
  964. //
  965. if ((iPR_MSNINET_ADDRESS != NOT_FOUND) && (iPR_MSNINET_DOMAIN != NOT_FOUND)) {
  966. if (FAILED(sc = MAPIAllocateMore(sizeof(TCHAR)*cchSize,
  967. lpPropsMAPI,
  968. &lpTemp))) {
  969. DebugTrace("HrFilterImportMailUserProps:MAPIAllocateMore -> %x\n", sc);
  970. hResult = ResultFromScode(sc);
  971. goto exit;
  972. }
  973. // Build the address
  974. StrCpyN(lpTemp, lpPropsMAPI[iPR_MSNINET_ADDRESS].Value.LPSZ, cchSize);
  975. StrCatBuff(lpTemp, szAtSign, cchSize);
  976. StrCatBuff(lpTemp, lpPropsMAPI[iPR_MSNINET_DOMAIN].Value.LPSZ, cchSize);
  977. lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
  978. // Convert addrtype to SMTP
  979. lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
  980. } else if (iPR_EMAIL_ADDRESS && lstrlen(lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ)) {
  981. // keep existing PR_EMAIL_ADDRES and assume it's ok
  982. lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
  983. } else {
  984. // No address, nuke ADDRTYPE
  985. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  986. }
  987. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMS)) {
  988. DebugTrace("MS address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  989. // No SMTP form of a MSMail address. destroy it.
  990. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  991. lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
  992. fBadAddress = TRUE;
  993. }
  994. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  995. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szX400)) {
  996. DebugTrace("X400 address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  997. // No SMTP form of a X400 address. destroy it.
  998. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  999. lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
  1000. fBadAddress = TRUE;
  1001. }
  1002. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  1003. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMSA)) {
  1004. DebugTrace("MacMail address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  1005. // No SMTP form of a MacMail address. destroy it.
  1006. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  1007. lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
  1008. fBadAddress = TRUE;
  1009. }
  1010. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  1011. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szEX)) {
  1012. DebugTrace("EX address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  1013. if (lpTemp = GetEMSSMTPAddress(lpObjectMAPI, lpPropsMAPI)) {
  1014. lpPropsMAPI[iPR_EMAIL_ADDRESS].Value.LPSZ = lpTemp;
  1015. // Convert addrtype to SMTP
  1016. lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ = (LPTSTR)szSMTP;
  1017. // Make sure that caller doesn't think this is a Personal DL.
  1018. *lpfDL = FALSE;
  1019. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  1020. lpPropsMAPI[iPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  1021. lpPropsMAPI[iPR_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
  1022. }
  1023. } else {
  1024. if (iPR_EMAIL_ADDRESS != NOT_FOUND) {
  1025. lpPropsMAPI[iPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
  1026. fBadAddress = TRUE;
  1027. }
  1028. lpPropsMAPI[iPR_ADDRTYPE].ulPropTag = PR_NULL;
  1029. }
  1030. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szSMTP)) {
  1031. DebugTrace("SMTP address for %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  1032. } else if (! lstrcmpi(lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ, szMAPIPDL)) {
  1033. DebugTrace("MAPIPDL %s\n", lpPropsMAPI[iPR_DISPLAY_NAME].Value.LPSZ);
  1034. // Distribution list, ignore it.
  1035. } else {
  1036. MAPIDebugProperties(lpPropsMAPI, cProps, "Unknown address type");
  1037. DebugTrace("Found unknown PR_ADDRTYPE: %s\n", lpPropsMAPI[iPR_ADDRTYPE].Value.LPSZ);
  1038. Assert(FALSE);
  1039. }
  1040. }
  1041. // PR_BUSINESS_FAX_NUMBER?
  1042. // The PAB puts the Fax number in PR_PRIMARY_FAX_NUMBER, but the WAB UI splits it
  1043. // into PR_BUSINESS_FAX_NUMBER and PR_HOME_FAX_NUMBER. We always assume that the
  1044. // Primary fax number is business.
  1045. if ((iPR_PRIMARY_FAX_NUMBER != NOT_FOUND) && (iPR_BUSINESS_FAX_NUMBER == NOT_FOUND)) {
  1046. // We need to also have a PR_BUSINESS_FAX_NUMBER
  1047. // Find the next PR_NULL spot.
  1048. iPR_BUSINESS_FAX_NUMBER = iPR_PRIMARY_FAX_NUMBER; // overwrite this one if there isn't
  1049. // an available slot in the prop array.
  1050. for (i = 0; i < cProps; i++) {
  1051. if (lpPropsMAPI[i].ulPropTag == PR_NULL) {
  1052. iPR_BUSINESS_FAX_NUMBER = i;
  1053. lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].Value.LPSZ =
  1054. lpPropsMAPI[iPR_PRIMARY_FAX_NUMBER].Value.LPSZ;
  1055. break;
  1056. }
  1057. }
  1058. lpPropsMAPI[iPR_BUSINESS_FAX_NUMBER].ulPropTag = PR_BUSINESS_FAX_NUMBER;
  1059. }
  1060. // Get rid of PR_NULL props
  1061. for (i = 0; i < cProps; i++) {
  1062. if (lpPropsMAPI[i].ulPropTag == PR_NULL) {
  1063. // Slide the props down.
  1064. if (i + 1 < cProps) { // Are there any higher props to copy?
  1065. CopyMemory(&lpPropsMAPI[i], &lpPropsMAPI[i + 1], ((cProps - i) - 1) * sizeof(lpPropsMAPI[i]));
  1066. }
  1067. // decrement count
  1068. cProps--;
  1069. i--; // You overwrote the current propval. Look at it again.
  1070. }
  1071. }
  1072. // Reallocate as WAB memory.
  1073. if (sc = ScCountProps(cProps, lpPropsMAPI, &cbProps)) {
  1074. hResult = ResultFromScode(sc);
  1075. DebugTrace("ScCountProps -> %x\n", sc);
  1076. goto exit;
  1077. }
  1078. if (sc = WABAllocateBuffer(cbProps, &lpPropsWAB)) {
  1079. hResult = ResultFromScode(sc);
  1080. DebugTrace("WABAllocateBuffer -> %x\n", sc);
  1081. goto exit;
  1082. }
  1083. if (sc = ScCopyProps(cProps,
  1084. lpPropsMAPI,
  1085. lpPropsWAB,
  1086. NULL)) {
  1087. hResult = ResultFromScode(sc);
  1088. DebugTrace("ScCopyProps -> %x\n", sc);
  1089. goto exit;
  1090. }
  1091. exit:
  1092. if (lpPropsMAPI) {
  1093. MAPIFreeBuffer(lpPropsMAPI);
  1094. }
  1095. if (HR_FAILED(hResult)) {
  1096. if (lpPropsWAB) {
  1097. WABFreeBuffer(lpPropsWAB);
  1098. lpPropsWAB = NULL;
  1099. }
  1100. cProps = 0;
  1101. } else if (fBadAddress) {
  1102. hResult = ResultFromScode(WAB_W_BAD_EMAIL);
  1103. }
  1104. *lppProps = lpPropsWAB;
  1105. *lpcProps = cProps;
  1106. return(hResult);
  1107. }
  1108. /***************************************************************************
  1109. Name : HandleImportError
  1110. Purpose : Decides if a dialog needs to be displayed to
  1111. indicate the failure and does so.
  1112. Parameters: hwnd = main dialog window
  1113. ids = String ID (optional: calculated from hResult if 0)
  1114. hResult = Result of action
  1115. lpDisplayName = display name of object that failed
  1116. lpEmailAddress = email address of object that failed or NULL
  1117. lpImportOptions -> import options structure
  1118. Returns : TRUE if user requests ABORT.
  1119. Comment : Abort is not yet implemented in the dialog, but if you
  1120. ever want to, just make this routine return TRUE;
  1121. ***************************************************************************/
  1122. BOOL HandleImportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
  1123. LPTSTR lpEmailAddress, LPWAB_IMPORT_OPTIONS lpImportOptions) {
  1124. BOOL fAbort = FALSE;
  1125. ERROR_INFO EI;
  1126. if ((ids || hResult) && ! lpImportOptions->fNoErrors) {
  1127. if (ids == 0) {
  1128. switch (GetScode(hResult)) {
  1129. case WAB_W_BAD_EMAIL:
  1130. ids = lpEmailAddress ? IDS_ERROR_EMAIL_ADDRESS_2 : IDS_ERROR_EMAIL_ADDRESS_1;
  1131. break;
  1132. case MAPI_E_NO_SUPPORT:
  1133. // Propbably failed to open contents on a distribution list
  1134. ids = IDS_ERROR_NO_SUPPORT;
  1135. break;
  1136. case MAPI_E_USER_CANCEL:
  1137. return(TRUE);
  1138. default:
  1139. if (HR_FAILED(hResult)) {
  1140. DebugTrace("Error Box for Hresult: 0x%08x\n", GetScode(hResult));
  1141. Assert(FALSE); // want to know about it.
  1142. ids = IDS_ERROR_GENERAL;
  1143. }
  1144. break;
  1145. }
  1146. }
  1147. EI.lpszDisplayName = lpDisplayName;
  1148. EI.lpszEmailAddress = lpEmailAddress;
  1149. EI.ErrorResult = ERROR_OK;
  1150. EI.ids = ids;
  1151. EI.fExport = FALSE;
  1152. EI.lpImportOptions = lpImportOptions;
  1153. DialogBoxParam(hInst,
  1154. MAKEINTRESOURCE(IDD_ErrorImport),
  1155. hwnd,
  1156. ErrorDialogProc,
  1157. (LPARAM)&EI);
  1158. fAbort = EI.ErrorResult == ERROR_ABORT;
  1159. }
  1160. return(fAbort);
  1161. }
  1162. /***************************************************************************
  1163. Name : FindExistingWABEntry
  1164. Purpose : Finds an existing entry in the WAB
  1165. Parameters: lpProps -> PropArray of MAPI entry
  1166. cProps = number of props in lpProps
  1167. lpContainerWAB -> WAB Container object
  1168. lppEIDWAB -> returned EntryID (caller must WABFreeBuffer)
  1169. lpcbEIDWAB -> returned size of lppEID
  1170. Returns : HRESULT
  1171. Comment : At this point, we expect to find a match since
  1172. SaveChanges said we had a duplicate.
  1173. ***************************************************************************/
  1174. HRESULT FindExistingWABEntry(LPSPropValue lpProps,
  1175. ULONG cProps,
  1176. LPABCONT lpContainerWAB,
  1177. LPENTRYID * lppEIDWAB,
  1178. LPULONG lpcbEIDWAB) {
  1179. ULONG rgFlagList[2];
  1180. LPFlagList lpFlagList = (LPFlagList)rgFlagList;
  1181. LPADRLIST lpAdrListWAB = NULL;
  1182. SCODE sc;
  1183. HRESULT hResult = hrSuccess;
  1184. LPSBinary lpsbEntryID = NULL;
  1185. ULONG cbEID = 0;
  1186. *lpcbEIDWAB = 0;
  1187. *lppEIDWAB = NULL;
  1188. // find the existing WAB entry.
  1189. // Setup for ResolveNames on the WAB container.
  1190. if (sc = WABAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY), &lpAdrListWAB)) {
  1191. DebugTrace("WAB Allocation(ADRLIST) failed -> %x\n", sc);
  1192. hResult = ResultFromScode(sc);
  1193. goto exit;
  1194. }
  1195. lpAdrListWAB->cEntries = 1;
  1196. lpAdrListWAB->aEntries[0].ulReserved1 = 0;
  1197. lpAdrListWAB->aEntries[0].cValues = 1;
  1198. if (sc = WABAllocateBuffer(sizeof(SPropValue), &lpAdrListWAB->aEntries[0].rgPropVals)) {
  1199. DebugTrace("WAB Allocation(ADRENTRY propval) failed -> %x\n", sc);
  1200. hResult = ResultFromScode(sc);
  1201. goto exit;
  1202. }
  1203. lpAdrListWAB->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
  1204. if (! (lpAdrListWAB->aEntries[0].rgPropVals[0].Value.LPSZ =
  1205. FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME))) {
  1206. DebugTrace("Can't find PR_DISPLAY_NAME in entry\n");
  1207. // pretty weird if this caused a collision...
  1208. goto exit;
  1209. }
  1210. lpFlagList->cFlags = 1;
  1211. lpFlagList->ulFlag[0] = MAPI_UNRESOLVED;
  1212. if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->ResolveNames(lpContainerWAB,
  1213. NULL, // tag set
  1214. 0, // ulFlags
  1215. lpAdrListWAB,
  1216. lpFlagList))) {
  1217. DebugTrace("WAB ResolveNames -> %x\n", GetScode(hResult));
  1218. goto exit;
  1219. }
  1220. switch (lpFlagList->ulFlag[0]) {
  1221. case MAPI_UNRESOLVED:
  1222. DebugTrace("WAB ResolveNames didn't find the entry\n");
  1223. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  1224. goto exit;
  1225. case MAPI_AMBIGUOUS:
  1226. #ifdef NEW_STUFF
  1227. // Do it the hard way. Open a table, restrict, take the first match.
  1228. lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
  1229. if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
  1230. 0, // ulFlags
  1231. &lpTableWAB))) {
  1232. DebugTrace("ImportEntry:GetContentsTable(WAB) -> %x\n", GetScode(hResult));
  1233. goto exit;
  1234. }
  1235. lpTableWAB->lpVtbl->Restrict....... // just the ones that match our entry...
  1236. cRows = 1;
  1237. while (cRows) {
  1238. // Get the next DL entry
  1239. if (hResult = lpTableWAB->lpVtbl->QueryRows(lpTableWAB,
  1240. 1, // one row at a time
  1241. 0, // ulFlags
  1242. &lpRow)) {
  1243. DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
  1244. goto exit;
  1245. }
  1246. if (lpRow && lpRow->cRows) {
  1247. Assert(lpRow->cRows == 1);
  1248. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  1249. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  1250. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  1251. } else {
  1252. break; // done
  1253. }
  1254. }
  1255. #endif // NEW_STUFF
  1256. break;
  1257. }
  1258. // Find the PR_ENTRYID
  1259. if (! (lpsbEntryID = FindAdrEntryID(lpAdrListWAB, 0))) {
  1260. DebugTrace("WAB ResolveNames didn't give us an EntryID\n");
  1261. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  1262. goto exit;
  1263. }
  1264. *lpcbEIDWAB = lpsbEntryID->cb;
  1265. if (FAILED(sc = WABAllocateBuffer(*lpcbEIDWAB, lppEIDWAB))) {
  1266. DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
  1267. hResult = ResultFromScode(sc);
  1268. *lpcbEIDWAB = 0;
  1269. goto exit;
  1270. }
  1271. // Copy the new EntryID into the buffer
  1272. CopyMemory(*lppEIDWAB, lpsbEntryID->lpb, *lpcbEIDWAB);
  1273. exit:
  1274. if (lpAdrListWAB) {
  1275. WABFreePadrlist(lpAdrListWAB);
  1276. }
  1277. return(hResult);
  1278. }
  1279. /****************************************************************************
  1280. *
  1281. * CheckReversedDisplayName(lpDisplayName);
  1282. *
  1283. * PAB and outlook display names are "LastName, FirstName"
  1284. * We need to reverse this for the WAB to handle it correctly ...
  1285. *
  1286. *
  1287. *****************************************************************************/
  1288. void CheckReversedDisplayName(LPTSTR lpDisplayName)
  1289. {
  1290. TCHAR szTemp[MAX_PATH * 3];
  1291. LPTSTR lp1=NULL, lp2=NULL;
  1292. ULONG cchSize = lstrlen(lpDisplayName);
  1293. if(!lpDisplayName)
  1294. return;
  1295. lp1 = lp2 = lpDisplayName;
  1296. while(lp1 && *lp1)
  1297. {
  1298. if(*lp1 == ',')
  1299. {
  1300. // A comma means this is Last, First
  1301. // We will make an assumption here that "L, F" or "L,F" is longer than or equal to "F L" and so
  1302. // we can reverse the name in place without any problems
  1303. //
  1304. lp2 = CharNext(lp1);
  1305. //skip spaces
  1306. while (IsSpace(lp2)) {
  1307. lp2 = CharNext(lp2);
  1308. }
  1309. *lp1 = '\0';
  1310. StrCpyN(szTemp, lpDisplayName, ARRAYSIZE(szTemp));
  1311. StrCpyN(lpDisplayName, lp2, cchSize);
  1312. StrCatBuff(lpDisplayName, TEXT(" "), cchSize);
  1313. StrCatBuff(lpDisplayName, szTemp, cchSize);
  1314. break;
  1315. }
  1316. lp1 = CharNext(lp1);
  1317. }
  1318. return;
  1319. }
  1320. /***************************************************************************
  1321. Name : ImportEntry
  1322. Purpose : Migrates the entry from the PAB to the WAB
  1323. Parameters: hwnd = main dialog window
  1324. lpAdrBookMAPI -> MAPI AdrBook object
  1325. lpContainerWAB -> WAB PAB container
  1326. lpCreateEIDsWAB -> SPropValue of default object creation EIDs
  1327. ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
  1328. lpEID -> ENTYRID of the PAB entry
  1329. cbEID = sizeof lpEID
  1330. lppEIDWAB -> returned WAB ENTRYID: Caller must WABFreeBuffer.
  1331. May be NULL.
  1332. lpcbEIDWAB -> returned size of lppEIDWAB (ignored if lppEIDWAB
  1333. is NULL.
  1334. fInDL = TRUE if this entry is for creation in a Distribution List
  1335. fForceReplace = TRUE if this entry should replace any duplicate.
  1336. Returns : HRESULT
  1337. Comment : This routine is a MESS! Should break it up when we get time.
  1338. ***************************************************************************/
  1339. HRESULT ImportEntry(HWND hwnd,
  1340. LPADRBOOK lpAdrBookMAPI,
  1341. LPABCONT lpContainerWAB,
  1342. LPSPropValue lpCreateEIDsWAB,
  1343. ULONG ulObjectType,
  1344. LPENTRYID lpEID,
  1345. ULONG cbEID,
  1346. LPENTRYID * lppEIDWAB,
  1347. LPULONG lpcbEIDWAB,
  1348. BOOL fInDL,
  1349. BOOL fForceReplace) {
  1350. HRESULT hResult = hrSuccess;
  1351. SCODE sc;
  1352. BOOL fDistList = FALSE;
  1353. BOOL fDuplicate = FALSE;
  1354. BOOL fDuplicateEID;
  1355. BOOL fReturnEID = FALSE;
  1356. ULONG ulObjectTypeOpen;
  1357. LPDISTLIST lpDistListMAPI = NULL, lpDistListWAB = NULL;
  1358. LPMAPIPROP lpMailUserMAPI = NULL, lpMailUserWAB = NULL;
  1359. LPSPropValue lpProps = NULL;
  1360. ULONG cProps, cEIDPropWAB;
  1361. LPMAPITABLE lpDLTableMAPI = NULL;
  1362. ULONG cRows;
  1363. LPSRowSet lpRow = NULL;
  1364. LPENTRYID lpeidDLWAB = NULL;
  1365. ULONG cbeidDLWAB;
  1366. LPSPropValue lpEIDPropWAB = NULL;
  1367. LPMAPIPROP lpEntryWAB = NULL;
  1368. ULONG ulCreateFlags = CREATE_CHECK_DUP_STRICT;
  1369. REPLACE_INFO RI;
  1370. LPTSTR lpDisplayName = NULL, lpEmailAddress = NULL;
  1371. static TCHAR szBufferDLMessage[MAX_RESOURCE_STRING + 1] = "";
  1372. LPTSTR lpszMessage;
  1373. LONG lListIndex = -1;
  1374. LPENTRYID lpEIDNew = NULL;
  1375. DWORD cbEIDNew = 0;
  1376. LPIID lpIIDOpen;
  1377. ULONG iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  1378. // Check the entry against our "seen" list
  1379. fDuplicateEID = AddEntryToImportList(cbEID, lpEID, &lListIndex);
  1380. if (! fDuplicateEID) {
  1381. if ((fForceReplace || (lpImportOptions->ReplaceOption == WAB_REPLACE_ALWAYS)) && ! fInDL) {
  1382. ulCreateFlags |= CREATE_REPLACE;
  1383. }
  1384. // Set up some object type specific variables
  1385. switch (ulObjectType) {
  1386. default:
  1387. DebugTrace("ImportEntry got unknown object type %u, assuming MailUser\n", ulObjectType);
  1388. Assert(FALSE);
  1389. case MAPI_MAILUSER:
  1390. iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  1391. lpIIDOpen = NULL;
  1392. fDistList = FALSE;
  1393. break;
  1394. case MAPI_DISTLIST:
  1395. iCreateTemplate = iconPR_DEF_CREATE_DL;
  1396. lpIIDOpen = (LPIID)&IID_IDistList;
  1397. fDistList = TRUE;
  1398. break;
  1399. }
  1400. // Open the entry
  1401. if (HR_FAILED(hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
  1402. cbEID,
  1403. lpEID,
  1404. lpIIDOpen,
  1405. 0,
  1406. &ulObjectTypeOpen,
  1407. (LPUNKNOWN *)&lpMailUserMAPI))) {
  1408. DebugTrace("OpenEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
  1409. goto exit;
  1410. }
  1411. // If DISTLIST, assume we got lpMailUser until we need lpDistList.
  1412. Assert(lpMailUserMAPI);
  1413. Assert(ulObjectType == ulObjectTypeOpen);
  1414. // Get the properties from this entry
  1415. if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->GetProps(lpMailUserMAPI,
  1416. NULL,
  1417. 0,
  1418. &cProps,
  1419. &lpProps))) {
  1420. DebugTrace("ImportEntry:GetProps(MAPI) -> %x\n", GetScode(hResult));
  1421. goto exit;
  1422. }
  1423. //
  1424. // NOTE: Must not fail between here and HrFilterImportMailUserProps because
  1425. // we will end up freeing lpProps with WABFreeBuffer.
  1426. //
  1427. // Filter the property array here
  1428. if (hResult = HrFilterImportMailUserProps(&cProps, &lpProps, lpMailUserMAPI, &fDistList)) {
  1429. lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
  1430. lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
  1431. if (HandleImportError(hwnd,
  1432. 0,
  1433. hResult,
  1434. lpDisplayName,
  1435. lpEmailAddress,
  1436. lpImportOptions)) {
  1437. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  1438. goto exit;
  1439. }
  1440. }
  1441. lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
  1442. lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
  1443. CheckReversedDisplayName(lpDisplayName);
  1444. if (ulObjectType == MAPI_DISTLIST && ! fDistList) {
  1445. // Filter must have changed this to a mailuser.
  1446. ulObjectType = MAPI_MAILUSER;
  1447. iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  1448. lpIIDOpen = NULL;
  1449. }
  1450. //
  1451. // NOTE: lpProps after this point is WAB Allocated rather than MAPI allocated.
  1452. //
  1453. if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->CreateEntry(lpContainerWAB,
  1454. lpCreateEIDsWAB[iCreateTemplate].Value.bin.cb,
  1455. (LPENTRYID)lpCreateEIDsWAB[iCreateTemplate].Value.bin.lpb,
  1456. ulCreateFlags,
  1457. &lpMailUserWAB))) {
  1458. DebugTrace("CreateEntry(WAB MailUser) -> %x\n", GetScode(hResult));
  1459. goto exit;
  1460. }
  1461. if (fDistList) {
  1462. // Update status message
  1463. if (*szBufferDLMessage == '\0') { // only load once, then keep it.
  1464. LoadString(hInst, IDS_MESSAGE_IMPORTING_DL, szBufferDLMessage, ARRAYSIZE(szBufferDLMessage));
  1465. }
  1466. if (lpDisplayName) {
  1467. ULONG cchSize = lstrlen(szBufferDLMessage) + 1 + lstrlen(lpDisplayName);
  1468. if (lpszMessage = LocalAlloc(LMEM_FIXED, sizeof(TCHAR)*cchSize)) {
  1469. wnsprintf(lpszMessage, cchSize, szBufferDLMessage, lpDisplayName);
  1470. DebugTrace("Status Message: %s\n", lpszMessage);
  1471. if (! SetDlgItemText(hwnd, IDC_Message, lpszMessage)) {
  1472. DebugTrace("SetDlgItemText -> %u\n", GetLastError());
  1473. }
  1474. LocalFree(lpszMessage);
  1475. }
  1476. }
  1477. }
  1478. // Set the properties on the WAB entry
  1479. if (HR_FAILED(hResult = lpMailUserWAB->lpVtbl->SetProps(lpMailUserWAB,
  1480. cProps, // cValues
  1481. lpProps, // property array
  1482. NULL))) { // problems array
  1483. DebugTrace("ImportEntry:SetProps(WAB) -> %x\n", GetScode(hResult));
  1484. goto exit;
  1485. }
  1486. // Save the new wab mailuser or distlist
  1487. if (HR_FAILED(hResult = lpMailUserWAB->lpVtbl->SaveChanges(lpMailUserWAB,
  1488. KEEP_OPEN_READONLY | FORCE_SAVE))) {
  1489. if (GetScode(hResult) == MAPI_E_COLLISION) {
  1490. // Find the display name
  1491. if (! lpDisplayName) {
  1492. DebugTrace("Collision, but can't find PR_DISPLAY_NAME in entry\n");
  1493. goto exit;
  1494. }
  1495. // Do we need to prompt?
  1496. // if (! fInDL && lpImportOptions->ReplaceOption == WAB_REPLACE_PROMPT) {
  1497. if (lpImportOptions->ReplaceOption == WAB_REPLACE_PROMPT) {
  1498. // Prompt user with dialog. If they say YES, we should
  1499. // recurse with the FORCE flag set.
  1500. RI.lpszDisplayName = lpDisplayName;
  1501. RI.lpszEmailAddress = lpEmailAddress;
  1502. RI.ConfirmResult = CONFIRM_ERROR;
  1503. RI.fExport = FALSE;
  1504. RI.lpImportOptions = lpImportOptions;
  1505. DialogBoxParam(hInst,
  1506. MAKEINTRESOURCE(IDD_ImportReplace),
  1507. hwnd,
  1508. ReplaceDialogProc,
  1509. (LPARAM)&RI);
  1510. switch(RI.ConfirmResult) {
  1511. case CONFIRM_YES:
  1512. case CONFIRM_YES_TO_ALL:
  1513. // YES
  1514. // NOTE: recursive Migrate will fill in the SeenList entry
  1515. hResult = ImportEntry(hwnd,
  1516. lpAdrBookMAPI,
  1517. lpContainerWAB,
  1518. lpCreateEIDsWAB,
  1519. ulObjectType,
  1520. lpEID,
  1521. cbEID,
  1522. &lpEIDNew, // Need this for later
  1523. &cbEIDNew,
  1524. FALSE,
  1525. TRUE);
  1526. if (hResult) {
  1527. if (HandleImportError(hwnd,
  1528. 0,
  1529. hResult,
  1530. lpDisplayName,
  1531. lpEmailAddress,
  1532. lpImportOptions)) {
  1533. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  1534. } else {
  1535. hResult = hrSuccess;
  1536. }
  1537. }
  1538. break;
  1539. case CONFIRM_ABORT:
  1540. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  1541. goto exit;
  1542. default:
  1543. // NO
  1544. fDuplicate = TRUE;
  1545. break;
  1546. }
  1547. } else {
  1548. fDuplicate = TRUE;
  1549. }
  1550. hResult = hrSuccess;
  1551. } else {
  1552. DebugTrace("SaveChanges(WAB MailUser) -> %x\n", GetScode(hResult));
  1553. }
  1554. } else {
  1555. // What is the ENTRYID of our new entry?
  1556. if ((hResult = lpMailUserWAB->lpVtbl->GetProps(lpMailUserWAB,
  1557. (LPSPropTagArray)&ptaEid,
  1558. 0,
  1559. &cEIDPropWAB,
  1560. &lpEIDPropWAB))) {
  1561. DebugTrace("ImportEntry: GetProps(WAB ENTRYID) -> %x\n", GetScode(hResult));
  1562. goto exit;
  1563. }
  1564. Assert(cEIDPropWAB);
  1565. Assert(lpEIDPropWAB[ieidPR_ENTRYID].ulPropTag == PR_ENTRYID);
  1566. cbEIDNew = lpEIDPropWAB[0].Value.bin.cb;
  1567. if (FAILED(sc = WABAllocateBuffer(cbEIDNew, &lpEIDNew))) {
  1568. DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
  1569. hResult = ResultFromScode(sc);
  1570. goto exit;
  1571. }
  1572. // Copy the new EntryID into the buffer
  1573. CopyMemory(lpEIDNew, lpEIDPropWAB[0].Value.bin.lpb, cbEIDNew);
  1574. }
  1575. //
  1576. // If this is a DISTLIST, fill it in.
  1577. //
  1578. if (fDistList && ! fDuplicate && cbEIDNew) {
  1579. lpDistListMAPI = (LPDISTLIST)lpMailUserMAPI; // This is REALLY a DISTLIST object
  1580. // DO NOT Release this!
  1581. // Open the new WAB DL as a DISTLIST object
  1582. if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->OpenEntry(lpContainerWAB,
  1583. cbEIDNew,
  1584. lpEIDNew,
  1585. (LPIID)&IID_IDistList,
  1586. MAPI_MODIFY,
  1587. &ulObjectTypeOpen,
  1588. (LPUNKNOWN*)&lpDistListWAB))) {
  1589. DebugTrace("ImportEntry: WAB OpenEntry(IID_DistList) -> %x\n", GetScode(hResult));
  1590. goto exit;
  1591. }
  1592. Assert(lpDistListWAB);
  1593. // For each entry in the DL:
  1594. // Migrate the entry (MailUser or DL) recursively
  1595. // Add new entryid to DL contents
  1596. if (HR_FAILED(hResult = lpDistListMAPI->lpVtbl->GetContentsTable(lpDistListMAPI,
  1597. 0, // ulFlags
  1598. &lpDLTableMAPI ))) {
  1599. DebugTrace("ImportEntry:GetContentsTable(MAPI) -> %x\n", GetScode(hResult));
  1600. goto exit;
  1601. }
  1602. // Set the columns to those we're interested in
  1603. if (hResult = lpDLTableMAPI->lpVtbl->SetColumns(lpDLTableMAPI,
  1604. (LPSPropTagArray)&ptaColumns,
  1605. 0)) {
  1606. DebugTrace("MAPI SetColumns(DL Table) -> %x\n", GetScode(hResult));
  1607. goto exit;
  1608. }
  1609. cRows = 1;
  1610. while (cRows) {
  1611. // Get the next DL entry
  1612. if (hResult = lpDLTableMAPI->lpVtbl->QueryRows(lpDLTableMAPI,
  1613. 1, // one row at a time
  1614. 0, // ulFlags
  1615. &lpRow)) {
  1616. DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
  1617. goto exit;
  1618. }
  1619. if (lpRow && lpRow->cRows) {
  1620. Assert(lpRow->cRows == 1);
  1621. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  1622. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  1623. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  1624. if (lpRow) {
  1625. if (cRows = lpRow->cRows) { // yes, single '='
  1626. hResult = ImportEntry(hwnd,
  1627. lpAdrBookMAPI,
  1628. lpContainerWAB,
  1629. lpCreateEIDsWAB,
  1630. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  1631. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  1632. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  1633. &lpeidDLWAB, // returned new or existing entry
  1634. &cbeidDLWAB,
  1635. TRUE,
  1636. FALSE);
  1637. if (hResult) {
  1638. if (HandleImportError(hwnd,
  1639. 0,
  1640. hResult,
  1641. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  1642. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  1643. lpImportOptions)) {
  1644. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  1645. break; // out of loop
  1646. } else {
  1647. hResult = hrSuccess;
  1648. }
  1649. }
  1650. } // else, drop out of loop, we're done.
  1651. FreeProws(lpRow);
  1652. lpRow = NULL;
  1653. if (HR_FAILED(hResult)) {
  1654. // This entry couldn't be created. Ignore it.
  1655. DebugTrace("Coudln't create DL entry -> %x\n", GetScode(hResult));
  1656. hResult = hrSuccess;
  1657. continue;
  1658. }
  1659. // Add the Entry to the DL using the new entry's EntryID
  1660. if (cbeidDLWAB && lpeidDLWAB) {
  1661. // BUGBUG: Don't bother with this one if this is a duplicate entry.
  1662. if (HR_FAILED(hResult = lpDistListWAB->lpVtbl->CreateEntry(lpDistListWAB,
  1663. cbeidDLWAB,
  1664. lpeidDLWAB,
  1665. 0, // allow duplicates here
  1666. &lpEntryWAB))) {
  1667. DebugTrace("Couldn't create new entry in DL -> %x\n", GetScode(hResult));
  1668. break;
  1669. }
  1670. hResult = lpEntryWAB->lpVtbl->SaveChanges(lpEntryWAB, FORCE_SAVE);
  1671. if (lpEntryWAB) {
  1672. lpEntryWAB->lpVtbl->Release(lpEntryWAB);
  1673. lpEntryWAB = NULL;
  1674. }
  1675. }
  1676. if (lpeidDLWAB) {
  1677. WABFreeBuffer(lpeidDLWAB);
  1678. lpeidDLWAB = NULL;
  1679. }
  1680. }
  1681. } else {
  1682. break; // done
  1683. }
  1684. }
  1685. }
  1686. } else {
  1687. DebugTrace("Found a duplicate EntryID\n");
  1688. }
  1689. //
  1690. // Save the entryid to the list and return a buffer with it
  1691. //
  1692. if (cbEIDNew && lpEIDNew) { // We created one?
  1693. // created one
  1694. } else if (fDuplicateEID && lListIndex != -1) { // Was it in the list?
  1695. cbEIDNew = lpEntriesSeen[lListIndex].sbinWAB.cb;
  1696. if (FAILED(sc = WABAllocateBuffer(cbEIDNew, &lpEIDNew))) {
  1697. DebugTrace("ImportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
  1698. // ignore
  1699. cbEIDNew = 0;
  1700. } else {
  1701. // Copy the EntryID from the list into the buffer
  1702. CopyMemory(lpEIDNew, lpEntriesSeen[lListIndex].sbinWAB.lpb, cbEIDNew);
  1703. }
  1704. } else if (fDuplicate) { // Was it a duplicate
  1705. FindExistingWABEntry(lpProps, cProps, lpContainerWAB, &lpEIDNew, &cbEIDNew);
  1706. // ignore errors since the lpEIDNew and cbEIDNew will be nulled out
  1707. }
  1708. // Update the seen list
  1709. if (! fDuplicateEID) {
  1710. MarkWABEntryInList(cbEIDNew, lpEIDNew, lListIndex);
  1711. }
  1712. // If caller requested the entryid's, return them
  1713. if (lpcbEIDWAB && lppEIDWAB) {
  1714. *lpcbEIDWAB = cbEIDNew;
  1715. *lppEIDWAB = lpEIDNew;
  1716. fReturnEID = TRUE; // don't free it
  1717. }
  1718. exit:
  1719. //
  1720. // Cleanup WAB stuff
  1721. //
  1722. if (lpProps) {
  1723. WABFreeBuffer(lpProps);
  1724. }
  1725. if (lpEIDPropWAB) {
  1726. WABFreeBuffer(lpEIDPropWAB);
  1727. }
  1728. if (lpEIDNew && ! fReturnEID) {
  1729. WABFreeBuffer(lpEIDNew);
  1730. }
  1731. if (lpeidDLWAB) {
  1732. WABFreeBuffer(lpeidDLWAB);
  1733. }
  1734. if (lpMailUserWAB) {
  1735. lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
  1736. }
  1737. if (lpDistListWAB) {
  1738. lpDistListWAB->lpVtbl->Release(lpDistListWAB);
  1739. }
  1740. //
  1741. // Cleanup MAPI stuff
  1742. //
  1743. if (lpRow) {
  1744. FreeProws(lpRow);
  1745. }
  1746. if (lpDLTableMAPI) {
  1747. lpDLTableMAPI->lpVtbl->Release(lpDLTableMAPI);
  1748. }
  1749. if (lpMailUserMAPI) {
  1750. lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
  1751. }
  1752. // Do not release this... It is the same object as lpMailUserMAPI!
  1753. // if (lpDistListMAPI) {
  1754. // lpDistListMAPI->lpVtbl->Release(lpDistListMAPI);
  1755. // }
  1756. if (! HR_FAILED(hResult)) {
  1757. hResult = hrSuccess;
  1758. }
  1759. return(hResult);
  1760. }
  1761. /*
  1762. * PAB EXPORT
  1763. *
  1764. * Migrate WAB to PAB
  1765. */
  1766. BOOL HandleExportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
  1767. LPTSTR lpEmailAddress, LPWAB_EXPORT_OPTIONS lpExportOptions);
  1768. void StateExportNextMU(HWND hwnd);
  1769. void StateExportDL(HWND hwnd);
  1770. void StateExportNextDL(HWND hwnd);
  1771. void StateExportFinish(HWND hwnd);
  1772. void StateExportMU(HWND hwnd);
  1773. void StateExportError(HWND hwnd);
  1774. void StateExportCancel(HWND hwnd);
  1775. HRESULT ExportEntry(HWND hwnd,
  1776. LPADRBOOK lpAdrBookMAPI,
  1777. LPABCONT lpContainerWAB,
  1778. LPSPropValue lpCreateEIDsWAB,
  1779. ULONG ulObjectType,
  1780. LPENTRYID lpEID,
  1781. ULONG cbEID,
  1782. LPENTRYID * lppEIDWAB,
  1783. LPULONG lpcbEIDWAB,
  1784. BOOL fInDL,
  1785. BOOL fForceReplace);
  1786. LPSPropTagArray lpspta = NULL; // List of tags to export
  1787. LPTSTR * lppNames = NULL; // List of names of tags
  1788. //
  1789. // Map property tags to strings
  1790. //
  1791. PROP_NAME rgPropNames[NUM_MORE_EXPORT_PROPS] = {
  1792. // ulPropTag, fChosen, ids, lpszName lpszName
  1793. // Personal Pane
  1794. PR_GIVEN_NAME, FALSE, ids_ExportGivenName, NULL, NULL,
  1795. PR_SURNAME, FALSE, ids_ExportSurname, NULL, NULL,
  1796. PR_MIDDLE_NAME, FALSE, ids_ExportMiddleName, NULL, NULL,
  1797. PR_DISPLAY_NAME, TRUE, ids_ExportDisplayName, NULL, NULL,
  1798. PR_NICKNAME, FALSE, ids_ExportNickname, NULL, NULL,
  1799. PR_EMAIL_ADDRESS, TRUE, ids_ExportEmailAddress, NULL, NULL,
  1800. // Home Pane
  1801. PR_HOME_ADDRESS_STREET, TRUE, ids_ExportHomeAddressStreet, NULL, NULL,
  1802. PR_HOME_ADDRESS_CITY, TRUE, ids_ExportHomeAddressCity, NULL, NULL,
  1803. PR_HOME_ADDRESS_POSTAL_CODE, TRUE, ids_ExportHomeAddressPostalCode, NULL, NULL,
  1804. PR_HOME_ADDRESS_STATE_OR_PROVINCE, TRUE, ids_ExportHomeAddressState, NULL, NULL,
  1805. PR_HOME_ADDRESS_COUNTRY, TRUE, ids_ExportHomeAddressCountry, NULL, NULL,
  1806. PR_HOME_TELEPHONE_NUMBER, TRUE, ids_ExportHomeTelephoneNumber, NULL, NULL,
  1807. PR_HOME_FAX_NUMBER, FALSE, ids_ExportHomeFaxNumber, NULL, NULL,
  1808. PR_CELLULAR_TELEPHONE_NUMBER, FALSE, ids_ExportCellularTelephoneNumber, NULL, NULL,
  1809. PR_PERSONAL_HOME_PAGE, FALSE, ids_ExportPersonalHomePage, NULL, NULL,
  1810. // Business Pane
  1811. PR_BUSINESS_ADDRESS_STREET, TRUE, ids_ExportBusinessAddressStreet, NULL, NULL,
  1812. PR_BUSINESS_ADDRESS_CITY, TRUE, ids_ExportBusinessAddressCity, NULL, NULL,
  1813. PR_BUSINESS_ADDRESS_POSTAL_CODE, TRUE, ids_ExportBusinessAddressPostalCode, NULL, NULL,
  1814. PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE, TRUE, ids_ExportBusinessAddressStateOrProvince, NULL, NULL,
  1815. PR_BUSINESS_ADDRESS_COUNTRY, TRUE, ids_ExportBusinessAddressCountry, NULL, NULL,
  1816. PR_BUSINESS_HOME_PAGE, FALSE, ids_ExportBusinessHomePage, NULL, NULL,
  1817. PR_BUSINESS_TELEPHONE_NUMBER, TRUE, ids_ExportBusinessTelephoneNumber, NULL, NULL,
  1818. PR_BUSINESS_FAX_NUMBER, FALSE, ids_ExportBusinessFaxNumber, NULL, NULL,
  1819. PR_PAGER_TELEPHONE_NUMBER, FALSE, ids_ExportPagerTelephoneNumber, NULL, NULL,
  1820. PR_COMPANY_NAME, TRUE, ids_ExportCompanyName, NULL, NULL,
  1821. PR_TITLE, TRUE, ids_ExportTitle, NULL, NULL,
  1822. PR_DEPARTMENT_NAME, FALSE, ids_ExportDepartmentName, NULL, NULL,
  1823. PR_OFFICE_LOCATION, FALSE, ids_ExportOfficeLocation, NULL, NULL,
  1824. // Notes Pane
  1825. PR_COMMENT, FALSE, ids_ExportComment, NULL, NULL,
  1826. };
  1827. /***************************************************************************
  1828. Name : StateExportMU
  1829. Purpose : Start the migration of MailUsers
  1830. Parameters: hwnd = window handle of Export Dialog
  1831. Returns : none
  1832. Comment : Login to MAPI
  1833. Open the WAB
  1834. Open the MAPI AB
  1835. Open the WAB container
  1836. Get the WAB contents table
  1837. Restrict it to PR_OBJECTTYPE == MAPI_MAILUSER
  1838. Post new state(STATE_NEXT_MU)
  1839. ***************************************************************************/
  1840. void StateExportMU(HWND hwnd) {
  1841. HRESULT hResult;
  1842. ULONG ulFlags;
  1843. ULONG cbPABEID, cbWABEID;
  1844. LPENTRYID lpPABEID = NULL, lpWABEID = NULL;
  1845. ULONG ulObjType;
  1846. ULONG_PTR ulUIParam = (ULONG_PTR)(void *)hwnd;
  1847. SRestriction restrictObjectType;
  1848. SPropValue spvObjectType;
  1849. ULONG cProps;
  1850. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  1851. WAB_PARAM wp = {0};
  1852. LPWAB_PARAM lpwp = NULL;
  1853. //
  1854. // Logon to MAPI and open the MAPI Address book, if one exists
  1855. //
  1856. DebugTrace(">>> STATE_EXPORT_MU\n");
  1857. SetDialogMessage(hwnd, IDS_STATE_LOGGING_IN);
  1858. if (FAILED(hResult = MAPIInitialize(NULL))) {
  1859. DebugTrace("MAPIInitialize -> %x\n", GetScode(hResult));
  1860. switch (GetScode(hResult)) {
  1861. case MAPI_E_NOT_ENOUGH_MEMORY:
  1862. SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_MEMORY);
  1863. break;
  1864. case MAPI_E_NOT_ENOUGH_DISK:
  1865. SetDialogMessage(hwnd, IDS_ERROR_NOT_ENOUGH_DISK);
  1866. break;
  1867. default:
  1868. case MAPI_E_NOT_FOUND:
  1869. case MAPI_E_NOT_INITIALIZED:
  1870. SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
  1871. break;
  1872. }
  1873. #ifdef OLD_STUFF
  1874. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
  1875. #endif // OLD_STUFF
  1876. fError = TRUE;
  1877. hResult = hrSuccess;
  1878. goto exit;
  1879. }
  1880. ulFlags = MAPI_LOGON_UI | MAPI_NO_MAIL | MAPI_EXTENDED;
  1881. if (FAILED(hResult = MAPILogonEx(ulUIParam,
  1882. NULL,
  1883. NULL,
  1884. ulFlags,
  1885. (LPMAPISESSION FAR *)&lpMAPISession))) {
  1886. DebugTrace("MAPILogonEx -> %x\n", GetScode(hResult));
  1887. switch (GetScode(hResult)) {
  1888. case MAPI_E_USER_CANCEL:
  1889. SetDialogMessage(hwnd, IDS_STATE_EXPORT_IDLE);
  1890. break;
  1891. case MAPI_E_NOT_INITIALIZED:
  1892. SetDialogMessage(hwnd, IDS_ERROR_MAPI_DLL_NOT_FOUND);
  1893. break;
  1894. default:
  1895. SetDialogMessage(hwnd, IDS_ERROR_MAPI_LOGON);
  1896. break;
  1897. }
  1898. #ifdef OLD_STUFF
  1899. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE); // hide progress bar
  1900. #endif // OLD_STUFF
  1901. fError = TRUE;
  1902. hResult = hrSuccess;
  1903. goto exit;
  1904. }
  1905. if (hResult = lpMAPISession->lpVtbl->OpenAddressBook(lpMAPISession, (ULONG_PTR)(void *)hwnd,
  1906. NULL,
  1907. 0,
  1908. &lpAdrBookMAPI)) {
  1909. DebugTrace("OpenAddressBook(MAPI) -> %x", GetScode(hResult));
  1910. if(FAILED(hResult)) {
  1911. goto exit;
  1912. }
  1913. }
  1914. if (! lpAdrBookMAPI) {
  1915. DebugTrace("MAPILogonEx didn't return a valid AdrBook object\n");
  1916. goto exit;
  1917. }
  1918. //
  1919. // Open the MAPI PAB container
  1920. //
  1921. // [PaulHi] Raid #63578 1/7/98
  1922. // Correctly check return code and provide user error message if
  1923. // Exchange PAB cannot be opened.
  1924. //
  1925. hResult = lpAdrBookMAPI->lpVtbl->GetPAB(lpAdrBookMAPI,
  1926. &cbPABEID,
  1927. &lpPABEID);
  1928. if (HR_FAILED(hResult))
  1929. {
  1930. DebugTrace("MAPI GetPAB -> %x\n", GetScode(hResult));
  1931. goto exit;
  1932. }
  1933. else
  1934. {
  1935. hResult = lpAdrBookMAPI->lpVtbl->OpenEntry(lpAdrBookMAPI,
  1936. cbPABEID, // size of EntryID to open
  1937. lpPABEID, // EntryID to open
  1938. NULL, // interface
  1939. MAPI_MODIFY, // flags
  1940. &ulObjType,
  1941. (LPUNKNOWN *)&lpContainerMAPI);
  1942. if (HR_FAILED(hResult))
  1943. {
  1944. DebugTrace("MAPI OpenEntry(PAB) -> %x\n", GetScode(hResult));
  1945. goto exit;
  1946. }
  1947. }
  1948. Assert(lpAdrBookWAB);
  1949. //
  1950. // Open the WAB's PAB container
  1951. //
  1952. if (hResult = lpAdrBookWAB->lpVtbl->GetPAB(lpAdrBookWAB,
  1953. &cbWABEID,
  1954. &lpWABEID)) {
  1955. DebugTrace("WAB GetPAB -> %x\n", GetScode(hResult));
  1956. goto exit;
  1957. } else {
  1958. if (hResult = lpAdrBookWAB->lpVtbl->OpenEntry(lpAdrBookWAB,
  1959. cbWABEID, // size of EntryID to open
  1960. lpWABEID, // EntryID to open
  1961. NULL, // interface
  1962. 0, // flags
  1963. &ulObjType,
  1964. (LPUNKNOWN *)&lpContainerWAB)) {
  1965. DebugTrace("WAB OpenEntry(PAB) -> %x\n", GetScode(hResult));
  1966. goto exit;
  1967. }
  1968. }
  1969. // Get the PAB's creation entryids
  1970. hResult = lpContainerMAPI->lpVtbl->GetProps(lpContainerMAPI,
  1971. (LPSPropTagArray)&ptaCon,
  1972. 0,
  1973. &cProps,
  1974. &lpCreateEIDsMAPI);
  1975. if (HR_FAILED(hResult))
  1976. {
  1977. DebugTrace("Can't get container properties for PAB\n");
  1978. // Bad stuff here!
  1979. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  1980. goto exit;
  1981. }
  1982. // Validate the properites
  1983. if (lpCreateEIDsMAPI[iconPR_DEF_CREATE_MAILUSER].ulPropTag != PR_DEF_CREATE_MAILUSER ||
  1984. lpCreateEIDsMAPI[iconPR_DEF_CREATE_DL].ulPropTag != PR_DEF_CREATE_DL)
  1985. {
  1986. DebugTrace("MAPI: Container property errors\n");
  1987. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  1988. goto exit;
  1989. }
  1990. //
  1991. // All set... now loop through the WAB's entries, copying them to PAB
  1992. //
  1993. if (HR_FAILED(hResult = lpContainerWAB->lpVtbl->GetContentsTable(lpContainerWAB,
  1994. 0, // ulFlags
  1995. &lpContentsTableWAB))) {
  1996. DebugTrace("WAB GetContentsTable(PAB Table) -> %x\n", GetScode(hResult));
  1997. goto exit;
  1998. }
  1999. // Set the columns to those we're interested in
  2000. if (hResult = lpContentsTableWAB->lpVtbl->SetColumns(lpContentsTableWAB,
  2001. (LPSPropTagArray)&ptaColumns,
  2002. 0)) {
  2003. DebugTrace("WAB SetColumns(PAB Table) -> %x\n", GetScode(hResult));
  2004. goto exit;
  2005. }
  2006. // Restrict the table to MAPI_MAILUSERs
  2007. // If the convenient depth flag was not specified we restrict on
  2008. // PR_DEPTH == 1.
  2009. spvObjectType.ulPropTag = PR_OBJECT_TYPE;
  2010. spvObjectType.Value.l = MAPI_MAILUSER;
  2011. restrictObjectType.rt = RES_PROPERTY;
  2012. restrictObjectType.res.resProperty.relop = RELOP_EQ;
  2013. restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
  2014. restrictObjectType.res.resProperty.lpProp = &spvObjectType;
  2015. if (HR_FAILED(hResult = lpContentsTableWAB->lpVtbl->Restrict(lpContentsTableWAB,
  2016. &restrictObjectType,
  2017. 0))) {
  2018. DebugTrace("WAB Restrict (MAPI_MAILUSER) -> %x\n", GetScode(hResult));
  2019. goto exit;
  2020. }
  2021. SetDialogMessage(hwnd, IDS_STATE_EXPORT_MU);
  2022. // Initialize the Progress Bar
  2023. // How many MailUser entries are there?
  2024. ulcEntries = CountRows(lpContentsTableWAB, FALSE);
  2025. DebugTrace("WAB contains %u MailUser entries\n", ulcEntries);
  2026. SetDialogProgress(hwnd, ulcEntries, 0);
  2027. exit:
  2028. if (lpWABEID) {
  2029. WABFreeBuffer(lpWABEID);
  2030. }
  2031. if (lpPABEID) {
  2032. MAPIFreeBuffer(lpPABEID);
  2033. }
  2034. // On error, set the state to STATE_ERROR
  2035. if (HR_FAILED(hResult))
  2036. {
  2037. if (GetScode(hResult) == MAPI_E_USER_CANCEL)
  2038. {
  2039. NewState(hwnd, STATE_EXPORT_CANCEL);
  2040. }
  2041. else
  2042. {
  2043. // [PaulHi] 1/7/98 Error reporting is hosed
  2044. // Display error message here to the user to ensure they
  2045. // get it.
  2046. {
  2047. TCHAR tszBuffer[MAX_RESOURCE_STRING];
  2048. TCHAR tszBufferTitle[MAX_RESOURCE_STRING];
  2049. if ( !LoadString(hInst, IDS_STATE_EXPORT_ERROR_NOPAB, tszBuffer, MAX_RESOURCE_STRING-1) )
  2050. {
  2051. Assert(0);
  2052. tszBuffer[0] = '\0';
  2053. }
  2054. if ( !LoadString(hInst, IDS_APP_TITLE, tszBufferTitle, MAX_RESOURCE_STRING-1) )
  2055. {
  2056. Assert(0);
  2057. tszBufferTitle[0] = '\0';
  2058. }
  2059. MessageBox(hwnd, tszBuffer, tszBufferTitle, MB_ICONEXCLAMATION | MB_OK);
  2060. }
  2061. NewState(hwnd, STATE_EXPORT_ERROR);
  2062. }
  2063. }
  2064. else if (fError)
  2065. {
  2066. NewState(hwnd, STATE_EXPORT_FINISH); // must be logon error
  2067. }
  2068. else
  2069. {
  2070. NewState(hwnd, STATE_EXPORT_NEXT_MU);
  2071. }
  2072. }
  2073. /***************************************************************************
  2074. Name : StateExportNextMU
  2075. Purpose : Migrate the next MailUser object
  2076. Parameters: hwnd = window handle of Export Dialog
  2077. Returns : none
  2078. Comment : QueryRows on the global WAB contents table
  2079. if there was a row
  2080. Migrate the entry to the PAB
  2081. Re-post STATE_EXPORT_NEXT_MU
  2082. else
  2083. Post STATE_EXPORT_DL
  2084. ***************************************************************************/
  2085. void StateExportNextMU(HWND hwnd) {
  2086. ULONG cRows = 0;
  2087. HRESULT hResult;
  2088. LPSRowSet lpRow = NULL;
  2089. DebugTrace(">>> STATE_EXPORT_NEXT_MU\n");
  2090. Assert(lpContentsTableWAB);
  2091. // Get the next WAB entry
  2092. if (hResult = lpContentsTableWAB->lpVtbl->QueryRows(lpContentsTableWAB,
  2093. 1, // one row at a time
  2094. 0, // ulFlags
  2095. &lpRow)) {
  2096. DebugTrace("QueryRows -> %x\n", GetScode(hResult));
  2097. goto exit;
  2098. }
  2099. if (lpRow) {
  2100. if (cRows = lpRow->cRows) { // Yes, single '='
  2101. Assert(lpRow->cRows == 1);
  2102. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  2103. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  2104. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  2105. if (cRows = lpRow->cRows) { // yes, single '='
  2106. hResult = ExportEntry(hwnd,
  2107. lpAdrBookWAB,
  2108. lpContainerMAPI,
  2109. lpCreateEIDsMAPI,
  2110. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  2111. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  2112. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  2113. NULL,
  2114. NULL,
  2115. FALSE,
  2116. FALSE);
  2117. // Update Progress Bar
  2118. // ignore errors!
  2119. SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
  2120. if (hResult) {
  2121. if (HandleExportError(hwnd,
  2122. 0,
  2123. hResult,
  2124. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  2125. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  2126. lpExportOptions)) {
  2127. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  2128. } else {
  2129. hResult = hrSuccess;
  2130. }
  2131. }
  2132. } // else, drop out of loop, we're done.
  2133. }
  2134. WABFreeProws(lpRow);
  2135. }
  2136. exit:
  2137. // On error, set the state to STATE_ERROR
  2138. if (HR_FAILED(hResult)) {
  2139. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  2140. NewState(hwnd, STATE_EXPORT_CANCEL);
  2141. } else {
  2142. NewState(hwnd, STATE_EXPORT_ERROR);
  2143. }
  2144. } else {
  2145. if (cRows) {
  2146. NewState(hwnd, STATE_EXPORT_NEXT_MU);
  2147. } else {
  2148. NewState(hwnd, STATE_EXPORT_DL);
  2149. }
  2150. }
  2151. }
  2152. /***************************************************************************
  2153. Name : StateExportDL
  2154. Purpose : Start migration of DISTLIST objects
  2155. Parameters: hwnd = window handle of Export Dialog
  2156. Returns : none
  2157. Comment : Set a new restriction on the contents table, selecting
  2158. DISTLIST objects only.
  2159. Post STATE_EXPORT_NEXT_DL
  2160. ***************************************************************************/
  2161. void StateExportDL(HWND hwnd) {
  2162. HRESULT hResult;
  2163. SRestriction restrictObjectType;
  2164. SPropValue spvObjectType;
  2165. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  2166. DebugTrace(">>> STATE_EXPORT_DL\n");
  2167. // Restrict the table to MAPI_MAILUSERs
  2168. // If the convenient depth flag was not specified we restrict on
  2169. // PR_DEPTH == 1.
  2170. spvObjectType.ulPropTag = PR_OBJECT_TYPE;
  2171. spvObjectType.Value.l = MAPI_DISTLIST;
  2172. restrictObjectType.rt = RES_PROPERTY;
  2173. restrictObjectType.res.resProperty.relop = RELOP_EQ;
  2174. restrictObjectType.res.resProperty.ulPropTag = PR_OBJECT_TYPE;
  2175. restrictObjectType.res.resProperty.lpProp = &spvObjectType;
  2176. if (HR_FAILED(hResult = lpContentsTableWAB->lpVtbl->Restrict(lpContentsTableWAB,
  2177. &restrictObjectType,
  2178. 0))) {
  2179. DebugTrace("WAB Restrict (MAPI_DISTLIST) -> %x\n", GetScode(hResult));
  2180. goto exit;
  2181. }
  2182. // Restrict resets the current position to the beginning of the table, by definition.
  2183. SetDialogMessage(hwnd, IDS_STATE_EXPORT_DL);
  2184. // Initialize the Progress Bar
  2185. // How many entries are there?
  2186. ulcEntries = CountRows(lpContentsTableWAB, FALSE);
  2187. DebugTrace("WAB contains %u Distribution List entries\n", ulcEntries);
  2188. if (ulcEntries) {
  2189. SetDialogProgress(hwnd, ulcEntries, 0);
  2190. }
  2191. exit:
  2192. // On error, set the state to STATE_ERROR
  2193. if (HR_FAILED(hResult)) {
  2194. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  2195. NewState(hwnd, STATE_EXPORT_CANCEL);
  2196. } else {
  2197. NewState(hwnd, STATE_EXPORT_ERROR);
  2198. }
  2199. } else {
  2200. NewState(hwnd, STATE_EXPORT_NEXT_DL);
  2201. }
  2202. }
  2203. /***************************************************************************
  2204. Name : StateExportNextDL
  2205. Purpose : Migrate the next DISTLIST object
  2206. Parameters: hwnd = window handle of Export Dialog
  2207. Returns : none
  2208. Comment : QueryRows on the global WAB contents table
  2209. if there was a row
  2210. Migrate the DistList to the PAB
  2211. Re-post STATE_EXPORT_NEXT_DL
  2212. else
  2213. Post STATE_EXPORT_FINISH
  2214. ***************************************************************************/
  2215. void StateExportNextDL(HWND hwnd) {
  2216. ULONG cRows = 0;
  2217. HRESULT hResult;
  2218. LPSRowSet lpRow = NULL;
  2219. DebugTrace(">>> STATE_EXPORT_NEXT_DL\n");
  2220. // Get the next WAB entry
  2221. if (hResult = lpContentsTableWAB->lpVtbl->QueryRows(lpContentsTableWAB,
  2222. 1, // one row at a time
  2223. 0, // ulFlags
  2224. &lpRow)) {
  2225. DebugTrace("QueryRows -> %x\n", GetScode(hResult));
  2226. goto exit;
  2227. }
  2228. if (lpRow) {
  2229. if (cRows = lpRow->cRows) { // Yes, single '='
  2230. Assert(lpRow->cRows == 1);
  2231. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  2232. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  2233. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  2234. if (cRows = lpRow->cRows) { // yes, single '='
  2235. hResult = ExportEntry(hwnd,
  2236. lpAdrBookWAB,
  2237. lpContainerMAPI,
  2238. lpCreateEIDsMAPI,
  2239. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  2240. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  2241. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  2242. NULL,
  2243. NULL,
  2244. FALSE,
  2245. FALSE);
  2246. // Update Progress Bar
  2247. SetDialogProgress(hwnd, ulcEntries, ++ulcDone);
  2248. if (hResult) {
  2249. if (HandleExportError(hwnd,
  2250. 0,
  2251. hResult,
  2252. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  2253. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  2254. lpExportOptions)) {
  2255. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  2256. } else {
  2257. hResult = hrSuccess;
  2258. }
  2259. }
  2260. } // else, drop out of loop, we're done.
  2261. }
  2262. WABFreeProws(lpRow);
  2263. }
  2264. exit:
  2265. // On error, set the state to STATE_ERROR
  2266. if (HR_FAILED(hResult)) {
  2267. if (GetScode(hResult) == MAPI_E_USER_CANCEL) {
  2268. NewState(hwnd, STATE_EXPORT_CANCEL);
  2269. } else {
  2270. NewState(hwnd, STATE_EXPORT_ERROR);
  2271. }
  2272. } else {
  2273. if (cRows) {
  2274. NewState(hwnd, STATE_EXPORT_NEXT_DL);
  2275. } else {
  2276. // Update Progress Bar to indicate completion
  2277. SetDialogProgress(hwnd, ulcEntries, ulcEntries);
  2278. NewState(hwnd, STATE_EXPORT_FINISH);
  2279. }
  2280. }
  2281. }
  2282. /***************************************************************************
  2283. Name : StateExportFinish
  2284. Purpose : Clean up after the migration process
  2285. Parameters: hwnd = window handle of Export Dialog
  2286. Returns : none
  2287. Comment : Clean up the global MAPI objects and buffers
  2288. Clean up the global WAB objects and buffers.
  2289. Re-enable the Export button on the UI.
  2290. ***************************************************************************/
  2291. void StateExportFinish(HWND hwnd) {
  2292. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  2293. TCHAR szBufferTitle[MAX_RESOURCE_STRING + 1];
  2294. DebugTrace(">>> STATE_EXPORT_FINISH\n");
  2295. //
  2296. // Cleanup MAPI
  2297. //
  2298. if (lpContainerMAPI) {
  2299. lpContainerMAPI->lpVtbl->Release(lpContainerMAPI);
  2300. lpContainerMAPI = NULL;
  2301. }
  2302. if (lpAdrBookMAPI) {
  2303. lpAdrBookMAPI->lpVtbl->Release(lpAdrBookMAPI);
  2304. lpAdrBookMAPI = NULL;
  2305. }
  2306. if(lpMAPISession){
  2307. lpMAPISession->lpVtbl->Logoff(lpMAPISession, (ULONG_PTR)(void *)hwnd,
  2308. MAPI_LOGOFF_UI,
  2309. 0);
  2310. lpMAPISession->lpVtbl->Release(lpMAPISession);
  2311. lpMAPISession = NULL;
  2312. }
  2313. //
  2314. // Cleanup the WAB
  2315. //
  2316. if (lpContentsTableWAB) {
  2317. lpContentsTableWAB->lpVtbl->Release(lpContentsTableWAB);
  2318. lpContentsTableWAB = NULL;
  2319. }
  2320. if (lpCreateEIDsWAB) {
  2321. WABFreeBuffer(lpCreateEIDsWAB);
  2322. lpCreateEIDsWAB = NULL;
  2323. }
  2324. if (lpContainerWAB) {
  2325. lpContainerWAB->lpVtbl->Release(lpContainerWAB);
  2326. lpContainerWAB = NULL;
  2327. }
  2328. #ifdef OLD_STUFF // Don't release AdrBookWAB or WABObject
  2329. if (lpAdrBookWAB) {
  2330. lpAdrBookWAB->lpVtbl->Release(lpAdrBookWAB);
  2331. lpAdrBookWAB = NULL;
  2332. }
  2333. if (lpWABObject) {
  2334. lpWABObject->lpVtbl->Release(lpWABObject);
  2335. lpWABObject = NULL;
  2336. }
  2337. #endif // OLD_STUFF
  2338. // Cleanup the cache
  2339. FreeSeenList();
  2340. if (! fError) { // Leave error state displayed
  2341. if (LoadString(hInst, IDS_STATE_EXPORT_COMPLETE, szBuffer, ARRAYSIZE(szBuffer))) {
  2342. DebugTrace("Status Message: %s\n", szBuffer);
  2343. SetDlgItemText(hwnd, IDC_Message, szBuffer);
  2344. if (! LoadString(hInst, IDS_APP_TITLE, szBufferTitle, ARRAYSIZE(szBufferTitle))) {
  2345. StrCpyN(szBufferTitle, "", ARRAYSIZE(szBufferTitle));
  2346. }
  2347. #ifdef OLD_STUFF
  2348. // Display a dialog telling user it's over
  2349. MessageBox(hwnd, szBuffer,
  2350. szBufferTitle, MB_ICONINFORMATION | MB_OK);
  2351. #endif // OLD_STUFF
  2352. }
  2353. #ifdef OLD_STUFF
  2354. ShowWindow(GetDlgItem(hwnd, IDC_Progress), SW_HIDE);
  2355. #endif // OLD_STUFF
  2356. }
  2357. fError = FALSE;
  2358. // Re-enable the Export button here.
  2359. EnableWindow(GetDlgItem(hwnd, IDC_Export), TRUE);
  2360. // Change the Cancel button to Close
  2361. if (LoadString(hInst, IDS_BUTTON_CLOSE, szBuffer, ARRAYSIZE(szBuffer))) {
  2362. SetDlgItemText(hwnd, IDCANCEL, szBuffer);
  2363. }
  2364. }
  2365. /***************************************************************************
  2366. Name : StateExportError
  2367. Purpose : Report fatal error and cleanup.
  2368. Parameters: hwnd = window handle of Export Dialog
  2369. Returns : none
  2370. Comment : Report error and post STATE_EXPORT_FINISH.
  2371. ***************************************************************************/
  2372. void StateExportError(HWND hwnd) {
  2373. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  2374. // Set some global flag and set state to finish
  2375. DebugTrace(">>> STATE_EXPORT_ERROR\n");
  2376. fError = TRUE;
  2377. SetDialogMessage(hwnd, IDS_STATE_EXPORT_ERROR);
  2378. NewState(hwnd, STATE_EXPORT_FINISH);
  2379. }
  2380. /***************************************************************************
  2381. Name : StateExportCancel
  2382. Purpose : Report cancel error and cleanup.
  2383. Parameters: hwnd = window handle of Export Dialog
  2384. Returns : none
  2385. Comment : Report error and post STATE_EXPORT_FINISH.
  2386. ***************************************************************************/
  2387. void StateExportCancel(HWND hwnd) {
  2388. TCHAR szBuffer[MAX_RESOURCE_STRING + 1];
  2389. // Set some global flag and set state to finish
  2390. DebugTrace(">>> STATE_EXPORT_CANCEL\n");
  2391. fError = TRUE;
  2392. SetDialogMessage(hwnd, IDS_STATE_EXPORT_CANCEL);
  2393. NewState(hwnd, STATE_EXPORT_FINISH);
  2394. }
  2395. /***************************************************************************
  2396. Name : HrFilterExportMailUserProps
  2397. Purpose : Filters out undesirable properties from the property array.
  2398. Converts known email address types to SMTP.
  2399. Moves FAX address to PR_BUSINESS_FAX_NUMBER.
  2400. Parameters: lpcProps -> IN: Input number of properties
  2401. OUT: Output number of properties
  2402. lppProps -> IN: Input property array (MAPI allocation)
  2403. OUT: Output property array (WAB allocation)
  2404. lpObjectWAB -> WAB object (used to get extra props)
  2405. lpfDL -> flag to set FALSE if we change a DL to a MAILUSER
  2406. (ie, for an EXchange DL)
  2407. Returns : HRESULT
  2408. Comment : Setting the property tag in the array to PR_NULL effectively
  2409. nulls this property out. We can re-use these in the second
  2410. pass.
  2411. Caller should use MAPIFreeBuffer to free *lppProps.
  2412. This routine will free the input value of *lppProps.
  2413. WARNING: This routine will add dummy properties to the
  2414. input WAB object, so don't go doing SaveChanges on it!
  2415. ***************************************************************************/
  2416. #define MAX_ADD_PROPS 2
  2417. #define PR_DUMMY_1 PROP_TAG(PT_LONG, 0xF000)
  2418. #define PR_DUMMY_2 PROP_TAG(PT_LONG, 0xF001)
  2419. HRESULT HrFilterExportMailUserProps(LPULONG lpcProps, LPSPropValue * lppProps,
  2420. LPMAPIPROP lpObjectWAB, LPBOOL lpfDL) {
  2421. HRESULT hResult = hrSuccess;
  2422. ULONG i;
  2423. LPSPropValue lpPropsWAB, lpPropsMAPI = NULL;
  2424. ULONG cbProps;
  2425. SCODE sc;
  2426. ULONG cProps;
  2427. ULONG iPR_ADDRTYPE = NOT_FOUND;
  2428. ULONG iPR_EMAIL_ADDRESS = NOT_FOUND;
  2429. ULONG iPR_PRIMARY_FAX_NUMBER = NOT_FOUND;
  2430. ULONG iPR_BUSINESS_FAX_NUMBER = NOT_FOUND;
  2431. ULONG iPR_MSNINET_DOMAIN = NOT_FOUND;
  2432. ULONG iPR_MSNINET_ADDRESS = NOT_FOUND;
  2433. ULONG iPR_DISPLAY_NAME = NOT_FOUND;
  2434. ULONG iPR_OBJECT_TYPE = NOT_FOUND;
  2435. ULONG iPR_SEND_RICH_INFO = NOT_FOUND;
  2436. LPSBinary lpEntryID = NULL;
  2437. LPTSTR lpTemp;
  2438. BOOL fBadAddress = FALSE;
  2439. SPropValue rgPropsDummy[MAX_ADD_PROPS] = {
  2440. PR_DUMMY_1, 0, 1,
  2441. PR_DUMMY_2, 0, 2,
  2442. };
  2443. // Set extra bogus props on the object in case we need to add more props
  2444. // to the array later. These will be PR_NULL'ed out by the first pass.
  2445. if (HR_FAILED(hResult = lpObjectWAB->lpVtbl->SetProps(lpObjectWAB,
  2446. MAX_ADD_PROPS,
  2447. rgPropsDummy,
  2448. NULL))) {
  2449. DebugTrace("HrFilterExportMailUserProps:SetProps dummy props -> %x\n", GetScode(hResult));
  2450. // ignore the error
  2451. }
  2452. // Get the properties from this entry
  2453. if (HR_FAILED(hResult = lpObjectWAB->lpVtbl->GetProps(lpObjectWAB,
  2454. NULL,
  2455. 0,
  2456. &cProps,
  2457. &lpPropsWAB))) {
  2458. DebugTrace("HrFilterExportMailUserProps:GetProps(WAB) -> %x\n", GetScode(hResult));
  2459. return(hResult);
  2460. }
  2461. // WABDebugProperties(lpPropsWAB, *lpcProps, "MailUser BEFORE");
  2462. // First pass: Remove the junk
  2463. for (i = 0; i < cProps; i++) {
  2464. // Error value
  2465. if (PROP_ERROR(lpPropsWAB[i])) {
  2466. lpPropsWAB[i].ulPropTag = PR_NULL;
  2467. continue;
  2468. }
  2469. // Named property
  2470. if (PROP_ID(lpPropsWAB[i].ulPropTag) >= MIN_NAMED_PROPID) {
  2471. lpPropsWAB[i].ulPropTag = PR_NULL;
  2472. continue;
  2473. }
  2474. // Object property
  2475. if (PROP_TYPE(lpPropsWAB[i].ulPropTag) == PT_OBJECT) {
  2476. lpPropsWAB[i].ulPropTag = PR_NULL;
  2477. continue;
  2478. }
  2479. switch (lpPropsWAB[i].ulPropTag) {
  2480. case PR_ENTRYID:
  2481. lpEntryID = &lpPropsWAB[i].Value.bin;
  2482. // fall through
  2483. case PR_PRIMARY_CAPABILITY:
  2484. case PR_TEMPLATEID:
  2485. case PR_SEARCH_KEY:
  2486. case PR_INITIAL_DETAILS_PANE:
  2487. case PR_RECORD_KEY:
  2488. case PR_MAPPING_SIGNATURE:
  2489. lpPropsWAB[i].ulPropTag = PR_NULL;
  2490. break;
  2491. case PR_COMMENT:
  2492. // Don't save PR_COMMENT if it is empty
  2493. if (lstrlen(lpPropsWAB[i].Value.LPSZ) == 0) {
  2494. lpPropsWAB[i].ulPropTag = PR_NULL;
  2495. }
  2496. break;
  2497. // Keep track of the position of these for later
  2498. case PR_ADDRTYPE:
  2499. iPR_ADDRTYPE = i;
  2500. break;
  2501. case PR_OBJECT_TYPE:
  2502. iPR_OBJECT_TYPE = i;
  2503. break;
  2504. case PR_EMAIL_ADDRESS:
  2505. iPR_EMAIL_ADDRESS = i;
  2506. break;
  2507. case PR_PRIMARY_FAX_NUMBER:
  2508. iPR_PRIMARY_FAX_NUMBER = i;
  2509. break;
  2510. case PR_BUSINESS_FAX_NUMBER:
  2511. iPR_BUSINESS_FAX_NUMBER = i;
  2512. break;
  2513. case PR_MSNINET_ADDRESS:
  2514. iPR_MSNINET_ADDRESS = i;
  2515. break;
  2516. case PR_MSNINET_DOMAIN:
  2517. iPR_MSNINET_DOMAIN = i;
  2518. break;
  2519. case PR_DISPLAY_NAME:
  2520. iPR_DISPLAY_NAME = i;
  2521. break;
  2522. case PR_SEND_RICH_INFO:
  2523. iPR_SEND_RICH_INFO = i;
  2524. break;
  2525. }
  2526. // Put this after the switch since we do want to track a few props which fall in
  2527. // the 0x6000 range but don't want to transfer them to the wab.
  2528. if (PROP_ID(lpPropsWAB[i].ulPropTag) >= MAX_SCHEMA_PROPID) {
  2529. lpPropsWAB[i].ulPropTag = PR_NULL;
  2530. continue;
  2531. }
  2532. }
  2533. // Second pass: Fix up the addresses
  2534. if (iPR_ADDRTYPE != NOT_FOUND) {
  2535. if (! lstrcmpi(lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ, szSMTP)) {
  2536. DebugTrace("SMTP address for %s\n", lpPropsWAB[iPR_DISPLAY_NAME].Value.LPSZ);
  2537. } else if (! lstrcmpi(lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ, szMAPIPDL)) {
  2538. DebugTrace("MAPIPDL %s\n", lpPropsWAB[iPR_DISPLAY_NAME].Value.LPSZ);
  2539. // Distribution list, ignore it.
  2540. } else {
  2541. WABDebugProperties(lpPropsWAB, cProps, "Unknown address type");
  2542. DebugTrace("Found unknown PR_ADDRTYPE: %s\n", lpPropsWAB[iPR_ADDRTYPE].Value.LPSZ);
  2543. Assert(FALSE);
  2544. }
  2545. }
  2546. // PR_BUSINESS_FAX_NUMBER?
  2547. // The PAB puts the Fax number in PR_PRIMARY_FAX_NUMBER, but the WAB UI splits it
  2548. // into PR_BUSINESS_FAX_NUMBER and PR_HOME_FAX_NUMBER. We always map business to
  2549. // Primary fax number and ignore home fax number.
  2550. if ((iPR_BUSINESS_FAX_NUMBER != NOT_FOUND) && (iPR_PRIMARY_FAX_NUMBER == NOT_FOUND)) {
  2551. // We need to also have a PR_PRIMARY_FAX_NUMBER
  2552. // Find the next PR_NULL spot.
  2553. iPR_PRIMARY_FAX_NUMBER = iPR_BUSINESS_FAX_NUMBER; // overwrite this one if there isn't
  2554. // an available slot in the prop array.
  2555. for (i = 0; i < cProps; i++) {
  2556. if (lpPropsWAB[i].ulPropTag == PR_NULL) {
  2557. iPR_PRIMARY_FAX_NUMBER = i;
  2558. lpPropsWAB[iPR_PRIMARY_FAX_NUMBER].Value.LPSZ =
  2559. lpPropsWAB[iPR_BUSINESS_FAX_NUMBER].Value.LPSZ;
  2560. break;
  2561. }
  2562. }
  2563. lpPropsWAB[iPR_PRIMARY_FAX_NUMBER].ulPropTag = PR_PRIMARY_FAX_NUMBER;
  2564. }
  2565. // If there is no PR_SEND_RICH_INFO, make one and set it FALSE
  2566. if (iPR_SEND_RICH_INFO == NOT_FOUND) {
  2567. // Find the next PR_NULL and put it there.
  2568. for (i = 0; i < cProps; i++) {
  2569. if (lpPropsWAB[i].ulPropTag == PR_NULL) {
  2570. iPR_SEND_RICH_INFO = i;
  2571. lpPropsWAB[iPR_SEND_RICH_INFO].Value.b = FALSE;
  2572. lpPropsWAB[iPR_SEND_RICH_INFO].ulPropTag = PR_SEND_RICH_INFO;
  2573. break;
  2574. }
  2575. }
  2576. Assert(iPR_SEND_RICH_INFO != NOT_FOUND);
  2577. }
  2578. // Get rid of PR_NULL props
  2579. for (i = 0; i < cProps; i++) {
  2580. if (lpPropsWAB[i].ulPropTag == PR_NULL) {
  2581. // Slide the props down.
  2582. if (i + 1 < cProps) { // Are there any higher props to copy?
  2583. CopyMemory(&lpPropsWAB[i], &lpPropsWAB[i + 1], ((cProps - i) - 1) * sizeof(lpPropsWAB[i]));
  2584. }
  2585. // decrement count
  2586. cProps--;
  2587. i--; // You overwrote the current propval. Look at it again.
  2588. }
  2589. }
  2590. // Reallocate as MAPI memory.
  2591. if (sc = ScCountProps(cProps, lpPropsWAB, &cbProps)) {
  2592. hResult = ResultFromScode(sc);
  2593. DebugTrace("ScCountProps -> %x\n", sc);
  2594. goto exit;
  2595. }
  2596. if (sc = MAPIAllocateBuffer(cbProps, &lpPropsMAPI)) {
  2597. hResult = ResultFromScode(sc);
  2598. DebugTrace("WABAllocateBuffer -> %x\n", sc);
  2599. goto exit;
  2600. }
  2601. if (sc = ScCopyProps(cProps,
  2602. lpPropsWAB,
  2603. lpPropsMAPI,
  2604. NULL)) {
  2605. hResult = ResultFromScode(sc);
  2606. DebugTrace("ScCopyProps -> %x\n", sc);
  2607. goto exit;
  2608. }
  2609. exit:
  2610. if (lpPropsWAB) {
  2611. WABFreeBuffer(lpPropsWAB);
  2612. }
  2613. if (HR_FAILED(hResult)) {
  2614. if (lpPropsMAPI) {
  2615. MAPIFreeBuffer(lpPropsMAPI);
  2616. lpPropsMAPI = NULL;
  2617. }
  2618. cProps = 0;
  2619. } else if (fBadAddress) {
  2620. hResult = ResultFromScode(WAB_W_BAD_EMAIL);
  2621. }
  2622. *lppProps = lpPropsMAPI;
  2623. *lpcProps = cProps;
  2624. return(hResult);
  2625. }
  2626. /***************************************************************************
  2627. Name : HandleExportError
  2628. Purpose : Decides if a dialog needs to be displayed to
  2629. indicate the failure and does so.
  2630. Parameters: hwnd = main dialog window
  2631. ids = String ID (optional: calculated from hResult if 0)
  2632. hResult = Result of action
  2633. lpDisplayName = display name of object that failed
  2634. lpEmailAddress = email address of object that failed (or NULL)
  2635. Returns : TRUE if user requests ABORT.
  2636. Comment : Abort is not yet implemented in the dialog, but if you
  2637. ever want to, just make this routine return TRUE;
  2638. ***************************************************************************/
  2639. BOOL HandleExportError(HWND hwnd, ULONG ids, HRESULT hResult, LPTSTR lpDisplayName,
  2640. LPTSTR lpEmailAddress, LPWAB_EXPORT_OPTIONS lpExportOptions) {
  2641. BOOL fAbort = FALSE;
  2642. ERROR_INFO EI;
  2643. if ((ids || hResult) && ! lpExportOptions->fNoErrors) {
  2644. if (ids == 0) {
  2645. switch (GetScode(hResult)) {
  2646. case WAB_W_BAD_EMAIL:
  2647. ids = lpEmailAddress ? IDS_ERROR_EMAIL_ADDRESS_2 : IDS_ERROR_EMAIL_ADDRESS_1;
  2648. break;
  2649. case MAPI_E_NO_SUPPORT:
  2650. // Propbably failed to open contents on a distribution list
  2651. ids = IDS_ERROR_NO_SUPPORT;
  2652. break;
  2653. case MAPI_E_USER_CANCEL:
  2654. return(TRUE);
  2655. default:
  2656. if (HR_FAILED(hResult)) {
  2657. DebugTrace("Error Box for Hresult: 0x%08x\n", GetScode(hResult));
  2658. Assert(FALSE); // want to know about it.
  2659. ids = IDS_ERROR_GENERAL;
  2660. }
  2661. break;
  2662. }
  2663. }
  2664. EI.lpszDisplayName = lpDisplayName;
  2665. EI.lpszEmailAddress = lpEmailAddress;
  2666. EI.ErrorResult = ERROR_OK;
  2667. EI.ids = ids;
  2668. EI.fExport = TRUE;
  2669. EI.lpImportOptions = lpExportOptions;
  2670. DialogBoxParam(hInst,
  2671. MAKEINTRESOURCE(IDD_ErrorExport),
  2672. hwnd,
  2673. ErrorDialogProc,
  2674. (LPARAM)&EI);
  2675. fAbort = EI.ErrorResult == ERROR_ABORT;
  2676. }
  2677. return(fAbort);
  2678. }
  2679. /***************************************************************************
  2680. Name : AddEntryToExportList
  2681. Purpose : Checks this entry against our "seen" list and adds it.
  2682. Parameters: cbEID = size of lpEID
  2683. lpEID -> EntryID of entry
  2684. lplIndex -> returned list index (or -1 on error)
  2685. Returns : TRUE if entry already exists
  2686. Comment : Caller must mark the WAB entry!
  2687. ***************************************************************************/
  2688. #define GROW_SIZE 10
  2689. BOOL AddEntryToExportList(ULONG cbEID, LPENTRYID lpEID, LPLONG lplIndex) {
  2690. ULONG i;
  2691. LPENTRY_SEEN lpEntrySeen;
  2692. if (cbEID && lpEID) {
  2693. for (i = 0; i < ulEntriesSeen; i++) {
  2694. if (cbEID == lpEntriesSeen[i].sbinPAB.cb && (! memcmp(lpEID, lpEntriesSeen[i].sbinPAB.lpb, cbEID))) {
  2695. // This one's in the list
  2696. *lplIndex = i;
  2697. // If cb 0, we must have recursed and are replacing, so this one is not a dup.
  2698. return(lpEntriesSeen[i].sbinWAB.cb != 0);
  2699. }
  2700. }
  2701. // Add to the end of the list
  2702. if (++ulEntriesSeen > ulMaxEntries) {
  2703. // Grow the array.
  2704. ulMaxEntries += GROW_SIZE;
  2705. if (lpEntriesSeen) {
  2706. if (! (lpEntrySeen = LocalReAlloc(lpEntriesSeen, ulMaxEntries * sizeof(ENTRY_SEEN), LMEM_MOVEABLE | LMEM_ZEROINIT))) {
  2707. DebugTrace("LocalReAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
  2708. goto error;
  2709. }
  2710. lpEntriesSeen = lpEntrySeen;
  2711. } else {
  2712. if (! (lpEntriesSeen = LocalAlloc(LPTR, ulMaxEntries * sizeof(ENTRY_SEEN)))) {
  2713. DebugTrace("LocalAlloc(%u) -> %u\n", ulMaxEntries * sizeof(ENTRY_SEEN), GetLastError());
  2714. goto error;
  2715. }
  2716. }
  2717. }
  2718. lpEntrySeen = &lpEntriesSeen[ulEntriesSeen - 1];
  2719. // Allocate space for data
  2720. lpEntrySeen->sbinPAB.cb = cbEID;
  2721. if (! (lpEntrySeen->sbinPAB.lpb = LocalAlloc(LPTR, cbEID))) {
  2722. DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
  2723. goto error;
  2724. }
  2725. // Mark as unknown WAB entry
  2726. lpEntrySeen->sbinWAB.cb = 0;
  2727. lpEntrySeen->sbinWAB.lpb = 0;
  2728. // Copy in the data
  2729. CopyMemory(lpEntrySeen->sbinPAB.lpb, lpEID, cbEID);
  2730. *lplIndex = i;
  2731. }
  2732. return(FALSE);
  2733. error:
  2734. // undo the damage...
  2735. --ulEntriesSeen;
  2736. ulMaxEntries -= GROW_SIZE;
  2737. *lplIndex = -1; // error
  2738. if (! lpEntriesSeen) {
  2739. ulEntriesSeen = 0; // pointer is null now, back to square one.
  2740. ulMaxEntries = 0;
  2741. }
  2742. return(FALSE);
  2743. }
  2744. /***************************************************************************
  2745. Name : MarkPABEntryInList
  2746. Purpose : Marks the PAB entry fields in the list node
  2747. Parameters: cbEID = size of lpEID
  2748. lpEID -> EntryID of entry
  2749. lIndex = list index (or -1 on error)
  2750. Returns : none
  2751. Comment :
  2752. ***************************************************************************/
  2753. void MarkPABEntryInList(ULONG cbEID, LPENTRYID lpEID, LONG lIndex) {
  2754. if (lIndex != -1 && cbEID) {
  2755. if (! (lpEntriesSeen[lIndex].sbinWAB.lpb = LocalAlloc(LPTR, cbEID))) {
  2756. DebugTrace("LocalAlloc(%u) -> %u\n", cbEID, GetLastError());
  2757. // leave it null
  2758. } else {
  2759. lpEntriesSeen[lIndex].sbinWAB.cb = cbEID;
  2760. // Copy in the data
  2761. CopyMemory(lpEntriesSeen[lIndex].sbinWAB.lpb, lpEID, cbEID);
  2762. }
  2763. }
  2764. }
  2765. //
  2766. // Properties to get from the PAB Entry
  2767. //
  2768. enum {
  2769. ifePR_OBJECT_TYPE = 0,
  2770. ifePR_ENTRYID,
  2771. ifePR_DISPLAY_NAME,
  2772. ifePR_EMAIL_ADDRESS,
  2773. ifeMax
  2774. };
  2775. static const SizedSPropTagArray(ifeMax, ptaFind) =
  2776. {
  2777. ifeMax,
  2778. {
  2779. PR_OBJECT_TYPE,
  2780. PR_ENTRYID,
  2781. PR_DISPLAY_NAME,
  2782. PR_EMAIL_ADDRESS
  2783. }
  2784. };
  2785. /***************************************************************************
  2786. Name : FindPABEntry
  2787. Purpose : Finds the named entry in the PAB
  2788. Parameters: lpContainerPAB -> MAPI PAB container
  2789. ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
  2790. lpDisplayName = name of entry
  2791. lpEmailAddress = email address or NULL if none
  2792. lppEIDMAPI -> returned MAPI ENTRYID: Caller must MAPIFreeBuffer.
  2793. lpcbEIDMAPI -> returned size of lppEIDMAPI
  2794. Returns : HRESULT
  2795. Comment : At this point, we expect to find a match since
  2796. SaveChanges said we had a duplicate.
  2797. ***************************************************************************/
  2798. HRESULT FindPABEntry(LPABCONT lpContainerPAB,
  2799. ULONG ulObjectType,
  2800. LPTSTR lpDisplayName,
  2801. LPTSTR lpEmailAddress,
  2802. LPULONG lpcbEIDDup,
  2803. LPENTRYID * lppEIDDup) {
  2804. HRESULT hResult = hrSuccess;
  2805. SCODE sc;
  2806. SRestriction resAnd[3]; // 0 = object type, 1 = displayname, 2 = emailaddress
  2807. SRestriction resFind;
  2808. SPropValue spvObjectType, spvDisplayName, spvEmailAddress;
  2809. LPSRowSet lpRow = NULL;
  2810. LPMAPITABLE lpTable = NULL;
  2811. ULONG rgFlagList[2];
  2812. LPFlagList lpFlagList = (LPFlagList)rgFlagList;
  2813. LPADRLIST lpAdrListMAPI = NULL;
  2814. LPSBinary lpsbEntryID;
  2815. ULONG i;
  2816. // init return values
  2817. *lppEIDDup = NULL;
  2818. *lpcbEIDDup = 0;
  2819. // find the existing PAB entry.
  2820. // Setup for ResolveNames on the PAB container.
  2821. if (sc = MAPIAllocateBuffer(sizeof(ADRLIST) + sizeof(ADRENTRY), &lpAdrListMAPI)) {
  2822. DebugTrace("MAPI Allocation(ADRLIST) failed -> %x\n", sc);
  2823. hResult = ResultFromScode(sc);
  2824. goto restrict;
  2825. }
  2826. lpAdrListMAPI->cEntries = 1;
  2827. lpAdrListMAPI->aEntries[0].ulReserved1 = 0;
  2828. lpAdrListMAPI->aEntries[0].cValues = 1;
  2829. if (sc = MAPIAllocateBuffer(sizeof(SPropValue), &lpAdrListMAPI->aEntries[0].rgPropVals)) {
  2830. DebugTrace("MAPI Allocation(ADRENTRY propval) failed -> %x\n", sc);
  2831. hResult = ResultFromScode(sc);
  2832. goto restrict;
  2833. }
  2834. lpFlagList->cFlags = 1;
  2835. for (i = 0; i <= 1; i++) {
  2836. switch (i) {
  2837. case 0: // pass 0
  2838. lpAdrListMAPI->aEntries[0].rgPropVals[0].ulPropTag = PR_DISPLAY_NAME;
  2839. lpAdrListMAPI->aEntries[0].rgPropVals[0].Value.LPSZ = lpDisplayName;
  2840. break;
  2841. case 1:
  2842. if (lpEmailAddress) {
  2843. lpAdrListMAPI->aEntries[0].rgPropVals[0].ulPropTag = PR_EMAIL_ADDRESS;
  2844. lpAdrListMAPI->aEntries[0].rgPropVals[0].Value.LPSZ = lpEmailAddress;
  2845. } else {
  2846. continue; // no email address, don't bother with second pass
  2847. }
  2848. break;
  2849. default:
  2850. Assert(FALSE);
  2851. }
  2852. lpFlagList->ulFlag[0] = MAPI_UNRESOLVED;
  2853. if (HR_FAILED(hResult = lpContainerPAB->lpVtbl->ResolveNames(lpContainerPAB,
  2854. NULL, // tag set
  2855. 0, // ulFlags
  2856. lpAdrListMAPI,
  2857. lpFlagList))) {
  2858. DebugTrace("MAPI ResolveNames -> %x\n", GetScode(hResult));
  2859. continue;
  2860. }
  2861. switch (lpFlagList->ulFlag[0]) {
  2862. case MAPI_UNRESOLVED:
  2863. DebugTrace("WAB ResolveNames didn't find the entry %s\n", lpDisplayName);
  2864. continue;
  2865. case MAPI_AMBIGUOUS:
  2866. DebugTrace("WAB ResolveNames find ambiguous entry %s\n", lpDisplayName);
  2867. continue;
  2868. case MAPI_RESOLVED:
  2869. i = 2; // Found it, exit the loop
  2870. }
  2871. }
  2872. if (lpFlagList->ulFlag[0] == MAPI_RESOLVED) {
  2873. // Found one, find its PR_ENTRYID
  2874. if (! (lpsbEntryID = FindAdrEntryID(lpAdrListMAPI, 0))) {
  2875. DebugTrace("MAPI ResolveNames didn't give us an EntryID\n");
  2876. Assert(lpsbEntryID);
  2877. goto restrict;
  2878. }
  2879. *lpcbEIDDup = lpsbEntryID->cb;
  2880. if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
  2881. hResult = ResultFromScode(sc);
  2882. DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
  2883. goto exit;
  2884. }
  2885. memcpy(*lppEIDDup, lpsbEntryID->lpb, *lpcbEIDDup);
  2886. }
  2887. restrict:
  2888. if (! *lppEIDDup) {
  2889. //
  2890. // Last ditch effort... use a table restriction to try to find this entry.
  2891. //
  2892. // Get the contents table
  2893. if (HR_FAILED(hResult = lpContainerPAB->lpVtbl->GetContentsTable(lpContainerPAB,
  2894. 0, // ulFlags
  2895. &lpTable))) {
  2896. DebugTrace("PAB GetContentsTable -> %x\n", GetScode(hResult));
  2897. goto exit;
  2898. }
  2899. // Set the columns
  2900. if (HR_FAILED(hResult = lpTable->lpVtbl->SetColumns(lpTable,
  2901. (LPSPropTagArray)&ptaFind,
  2902. 0))) {
  2903. DebugTrace("PAB SetColumns-> %x\n", GetScode(hResult));
  2904. goto exit;
  2905. }
  2906. // Restrict to the object we care about
  2907. resAnd[0].rt = RES_PROPERTY; // Restriction type Property
  2908. resAnd[0].res.resProperty.relop = RELOP_EQ;
  2909. resAnd[0].res.resProperty.ulPropTag = PR_OBJECT_TYPE;
  2910. resAnd[0].res.resProperty.lpProp = &spvObjectType;
  2911. spvObjectType.ulPropTag = PR_OBJECT_TYPE;
  2912. spvObjectType.Value.ul = ulObjectType;
  2913. // Restrict to get correct display name
  2914. resAnd[1].rt = RES_PROPERTY; // Restriction type Property
  2915. resAnd[1].res.resProperty.relop = RELOP_EQ;
  2916. resAnd[1].res.resProperty.ulPropTag = PR_DISPLAY_NAME;
  2917. resAnd[1].res.resProperty.lpProp = &spvDisplayName;
  2918. spvDisplayName.ulPropTag = PR_DISPLAY_NAME;
  2919. spvDisplayName.Value.LPSZ = lpDisplayName;
  2920. if (lpEmailAddress) {
  2921. // Restrict to get correct email address
  2922. resAnd[2].rt = RES_PROPERTY; // Restriction type Property
  2923. resAnd[2].res.resProperty.relop = RELOP_EQ;
  2924. resAnd[2].res.resProperty.ulPropTag = PR_EMAIL_ADDRESS;
  2925. resAnd[2].res.resProperty.lpProp = &spvEmailAddress;
  2926. spvEmailAddress.ulPropTag = PR_EMAIL_ADDRESS;
  2927. spvEmailAddress.Value.LPSZ = lpEmailAddress;
  2928. }
  2929. resFind.rt = RES_AND;
  2930. resFind.res.resAnd.cRes = lpEmailAddress ? 3 : 2;
  2931. resFind.res.resAnd.lpRes = resAnd;
  2932. if (HR_FAILED(hResult = lpTable->lpVtbl->Restrict(lpTable,
  2933. &resFind,
  2934. 0))) {
  2935. DebugTrace("FindPABEntry: Restrict -> %x", hResult);
  2936. goto exit;
  2937. }
  2938. if (hResult = lpTable->lpVtbl->QueryRows(lpTable,
  2939. 1, // First row only
  2940. 0, // ulFlags
  2941. &lpRow)) {
  2942. DebugTrace("FindPABEntry: QueryRows -> %x\n", GetScode(hResult));
  2943. } else {
  2944. // Found it, copy entryid to new allocation
  2945. if (lpRow->cRows) {
  2946. *lpcbEIDDup = lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.cb;
  2947. if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
  2948. hResult = ResultFromScode(sc);
  2949. DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
  2950. goto exit;
  2951. }
  2952. memcpy(*lppEIDDup, lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.lpb, *lpcbEIDDup);
  2953. } else {
  2954. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  2955. }
  2956. }
  2957. // Still not found?!! Maybe the PAB has a different idea of what the Display name is.
  2958. // Search just by email address.
  2959. if (hResult && lpEmailAddress) {
  2960. resAnd[1] = resAnd[2]; // copy the email address res over the display name res.
  2961. resFind.res.resAnd.cRes = 2;
  2962. if (HR_FAILED(hResult = lpTable->lpVtbl->Restrict(lpTable,
  2963. &resFind,
  2964. 0))) {
  2965. DebugTrace("FindPABEntry: Restrict -> %x", hResult);
  2966. goto exit;
  2967. }
  2968. if (hResult = lpTable->lpVtbl->QueryRows(lpTable,
  2969. 1, // First row only
  2970. 0, // ulFlags
  2971. &lpRow)) {
  2972. DebugTrace("FindPABEntry: QueryRows -> %x\n", GetScode(hResult));
  2973. } else {
  2974. // Found it, copy entryid to new allocation
  2975. if (lpRow->cRows) {
  2976. *lpcbEIDDup = lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.cb;
  2977. if (FAILED(sc = MAPIAllocateBuffer(*lpcbEIDDup, lppEIDDup))) {
  2978. hResult = ResultFromScode(sc);
  2979. DebugTrace("FindPABEntry couldn't allocate duplicate entryid %x\n", sc);
  2980. goto exit;
  2981. }
  2982. memcpy(*lppEIDDup, lpRow->aRow[0].lpProps[ifePR_ENTRYID].Value.bin.lpb, *lpcbEIDDup);
  2983. } else {
  2984. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  2985. DebugTrace("FindPABEntry coudln't find %s %s <%s>\n",
  2986. ulObjectType == MAPI_MAILUSER ? "Mail User" : "Distribution List",
  2987. lpDisplayName,
  2988. lpEmailAddress ? lpEmailAddress : "");
  2989. }
  2990. }
  2991. }
  2992. }
  2993. exit:
  2994. if (lpAdrListMAPI) {
  2995. FreePadrlist(lpAdrListMAPI);
  2996. }
  2997. if (lpRow) {
  2998. FreeProws(lpRow);
  2999. }
  3000. if (lpTable) {
  3001. lpTable->lpVtbl->Release(lpTable);
  3002. }
  3003. if (HR_FAILED(hResult) && *lppEIDDup) {
  3004. MAPIFreeBuffer(*lppEIDDup);
  3005. *lpcbEIDDup = 0;
  3006. *lppEIDDup = NULL;
  3007. }
  3008. if (hResult) {
  3009. DebugTrace("FindPABEntry coudln't find %s %s <%s>\n",
  3010. ulObjectType == MAPI_MAILUSER ? "Mail User" : "Distribution List",
  3011. lpDisplayName,
  3012. lpEmailAddress ? lpEmailAddress : "");
  3013. }
  3014. return(hResult);
  3015. }
  3016. // enum for setting the created properties
  3017. enum {
  3018. irnPR_DISPLAY_NAME = 0,
  3019. irnPR_RECIPIENT_TYPE,
  3020. irnPR_ENTRYID,
  3021. irnPR_EMAIL_ADDRESS,
  3022. irnMax
  3023. };
  3024. /***************************************************************************
  3025. Name : ExportEntry
  3026. Purpose : Migrates the entry from the WAB to the PAB
  3027. Parameters: hwnd = main dialog window
  3028. lpAdrBookWAB -> WAB AdrBook object
  3029. lpContainerMAPI -> MAPI PAB container
  3030. lpCreateEIDsMAPI -> SPropValue of default object creation EIDs
  3031. ulObjectType = {MAPI_MAILUSER, MAPI_DISTLIST}
  3032. lpEID -> ENTYRID of the WAB entry
  3033. cbEID = sizeof lpEID
  3034. lppEIDMAPI -> returned MAPI ENTRYID: Caller must MAPIFreeBuffer.
  3035. May be NULL.
  3036. lpcbEIDMAPI -> returned size of lppEIDMAPI (ignored if lppEIDMAPI
  3037. is NULL.
  3038. fInDL = TRUE if this entry is for creation in a Distribution List
  3039. fForceReplace = TRUE if this entry should replace any duplicate.
  3040. Returns : HRESULT
  3041. Comment : This routine is a MESS! Should break it up when we get time.
  3042. ***************************************************************************/
  3043. HRESULT ExportEntry(HWND hwnd,
  3044. LPADRBOOK lpAdrBookWAB,
  3045. LPABCONT lpContainerMAPI,
  3046. LPSPropValue lpCreateEIDsMAPI,
  3047. ULONG ulObjectType,
  3048. LPENTRYID lpEID,
  3049. ULONG cbEID,
  3050. LPENTRYID * lppEIDMAPI,
  3051. LPULONG lpcbEIDMAPI,
  3052. BOOL fInDL,
  3053. BOOL fForceReplace) {
  3054. HRESULT hResult = hrSuccess;
  3055. SCODE sc;
  3056. BOOL fDistList = FALSE;
  3057. BOOL fDuplicate = FALSE;
  3058. BOOL fDuplicateEID;
  3059. BOOL fReturnEID = FALSE;
  3060. ULONG ulObjectTypeOpen;
  3061. LPDISTLIST lpDistListMAPI = NULL, lpDistListWAB = NULL;
  3062. LPMAPIPROP lpMailUserMAPI = NULL, lpMailUserWAB = NULL;
  3063. LPSPropValue lpProps = NULL;
  3064. ULONG cProps, cEIDPropMAPI;
  3065. LPMAPITABLE lpDLTableWAB = NULL;
  3066. ULONG cRows;
  3067. LPSRowSet lpRow = NULL;
  3068. LPENTRYID lpeidDLMAPI = NULL;
  3069. ULONG cbeidDLMAPI;
  3070. LPSPropValue lpEIDPropMAPI = NULL;
  3071. LPMAPIPROP lpEntryMAPI = NULL;
  3072. ULONG ulCreateFlags;
  3073. REPLACE_INFO RI;
  3074. LPTSTR lpDisplayName = NULL, lpEmailAddress = NULL;
  3075. static TCHAR szBufferDLMessage[MAX_RESOURCE_STRING + 1] = "";
  3076. LPTSTR lpszMessage;
  3077. LONG lListIndex = -1;
  3078. LPENTRYID lpEIDNew = NULL;
  3079. DWORD cbEIDNew = 0;
  3080. LPIID lpIIDOpen;
  3081. ULONG iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  3082. BOOL fCreatedNew = FALSE;
  3083. LPENTRYID lpEIDDup = NULL;
  3084. ULONG cbEIDDup;
  3085. // Check the entry against our "seen" list
  3086. fDuplicateEID = AddEntryToExportList(cbEID, lpEID, &lListIndex);
  3087. if (! fDuplicateEID) {
  3088. // Set up some object type specific variables
  3089. switch (ulObjectType) {
  3090. default:
  3091. DebugTrace("ExportEntry got unknown object type %u, assuming MailUser\n", ulObjectType);
  3092. Assert(FALSE);
  3093. case MAPI_MAILUSER:
  3094. iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  3095. lpIIDOpen = NULL;
  3096. fDistList = FALSE;
  3097. break;
  3098. case MAPI_DISTLIST:
  3099. iCreateTemplate = iconPR_DEF_CREATE_DL;
  3100. lpIIDOpen = (LPIID)&IID_IDistList;
  3101. fDistList = TRUE;
  3102. break;
  3103. }
  3104. // Open the entry
  3105. if (HR_FAILED(hResult = lpAdrBookWAB->lpVtbl->OpenEntry(lpAdrBookWAB,
  3106. cbEID,
  3107. lpEID,
  3108. lpIIDOpen,
  3109. MAPI_MODIFY, // need to do SetProps inside Filter routine, but won't save them.
  3110. &ulObjectTypeOpen,
  3111. (LPUNKNOWN *)&lpMailUserWAB))) {
  3112. DebugTrace("OpenEntry(WAB MailUser) -> %x\n", GetScode(hResult));
  3113. goto exit;
  3114. }
  3115. // If DISTLIST, assume we got lpMailUser until we need lpDistList.
  3116. Assert(lpMailUserWAB);
  3117. Assert(ulObjectType == ulObjectTypeOpen);
  3118. //
  3119. // NOTE: Must not fail between here and HrFilterExportMailUserProps because
  3120. // we will end up freeing lpProps with MAPIFreeBuffer.
  3121. //
  3122. // Get and filter the property array here
  3123. if (hResult = HrFilterExportMailUserProps(&cProps, &lpProps, lpMailUserWAB, &fDistList)) {
  3124. lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
  3125. lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
  3126. if (HandleExportError(hwnd,
  3127. 0,
  3128. hResult,
  3129. lpDisplayName,
  3130. lpEmailAddress,
  3131. lpExportOptions)) {
  3132. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  3133. goto exit;
  3134. }
  3135. }
  3136. // Find some interesting property values here
  3137. lpDisplayName = FindStringInProps(lpProps, cProps, PR_DISPLAY_NAME);
  3138. lpEmailAddress = FindStringInProps(lpProps, cProps, PR_EMAIL_ADDRESS);
  3139. if (ulObjectType == MAPI_DISTLIST && ! fDistList) {
  3140. // Filter must have changed this to a mailuser.
  3141. ulObjectType = MAPI_MAILUSER;
  3142. iCreateTemplate = iconPR_DEF_CREATE_MAILUSER;
  3143. lpIIDOpen = NULL;
  3144. }
  3145. if (fDistList) {
  3146. ulCreateFlags = CREATE_CHECK_DUP_LOOSE;
  3147. // PAB can't detect collisions on DL SaveChanges.
  3148. // See if this is a duplicate:
  3149. if (! HR_FAILED(hResult = FindPABEntry(lpContainerMAPI,
  3150. MAPI_DISTLIST,
  3151. lpDisplayName,
  3152. NULL,
  3153. &cbEIDDup,
  3154. &lpEIDDup))) {
  3155. // Found a duplicate. Keep track of it!
  3156. }
  3157. } else {
  3158. ulCreateFlags = CREATE_CHECK_DUP_STRICT;
  3159. }
  3160. //
  3161. // NOTE: lpProps after this point is MAPI Allocated rather than WAB allocated.
  3162. //
  3163. if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->CreateEntry(lpContainerMAPI,
  3164. lpCreateEIDsMAPI[iCreateTemplate].Value.bin.cb,
  3165. (LPENTRYID)lpCreateEIDsMAPI[iCreateTemplate].Value.bin.lpb,
  3166. ulCreateFlags,
  3167. &lpMailUserMAPI))) {
  3168. DebugTrace("CreateEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
  3169. goto exit;
  3170. }
  3171. if (fDistList) {
  3172. // Update status message
  3173. if (*szBufferDLMessage == '\0') { // only load once, then keep it.
  3174. LoadString(hInst, IDS_MESSAGE_EXPORTING_DL, szBufferDLMessage, ARRAYSIZE(szBufferDLMessage));
  3175. }
  3176. if (lpDisplayName) {
  3177. ULONG cchSize =lstrlen(szBufferDLMessage) + 1 + lstrlen(lpDisplayName);
  3178. if (lpszMessage = LocalAlloc(LMEM_FIXED, sizeof(TCHAR)*cchSize)) {
  3179. wnsprintf(lpszMessage, cchSize, szBufferDLMessage, lpDisplayName);
  3180. DebugTrace("Status Message: %s\n", lpszMessage);
  3181. if (! SetDlgItemText(hwnd, IDC_Message, lpszMessage)) {
  3182. DebugTrace("SetDlgItemText -> %u\n", GetLastError());
  3183. }
  3184. LocalFree(lpszMessage);
  3185. }
  3186. }
  3187. }
  3188. if (! lpEIDDup) {
  3189. // If this was a DL which we know already exists, don't even bother writing it,
  3190. // just fall through to the collision pass. Otherwise, try to set the props
  3191. // and save it... if it fails, we'll get an hResult=MAPI_E_COLLISION.
  3192. // Set the properties on the PAB entry
  3193. if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SetProps(lpMailUserMAPI,
  3194. cProps, // cValues
  3195. lpProps, // property array
  3196. NULL))) { // problems array
  3197. DebugTrace("ExportEntry:SetProps(MAPI) -> %x\n", GetScode(hResult));
  3198. goto exit;
  3199. }
  3200. // Save the new wab mailuser or distlist
  3201. if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SaveChanges(lpMailUserMAPI,
  3202. KEEP_OPEN_READONLY | FORCE_SAVE))) {
  3203. DebugTrace("SaveChanges -> %x\n", GetScode(hResult));
  3204. } else {
  3205. fCreatedNew = TRUE;
  3206. }
  3207. }
  3208. //
  3209. // Handle Collisions
  3210. //
  3211. if (lpEIDDup || GetScode(hResult) == MAPI_E_COLLISION) {
  3212. // Find the display name
  3213. if (! lpDisplayName) {
  3214. DebugTrace("Collision, but can't find PR_DISPLAY_NAME in entry\n");
  3215. goto exit;
  3216. }
  3217. // Do we need to prompt?
  3218. switch (lpExportOptions->ReplaceOption) {
  3219. case WAB_REPLACE_PROMPT:
  3220. // Prompt user with dialog. If they say YES, we should
  3221. // recurse with the FORCE flag set.
  3222. RI.lpszDisplayName = lpDisplayName;
  3223. RI.lpszEmailAddress = lpEmailAddress;
  3224. RI.ConfirmResult = CONFIRM_ERROR;
  3225. RI.fExport = TRUE;
  3226. RI.lpImportOptions = lpExportOptions;
  3227. DialogBoxParam(hInst,
  3228. MAKEINTRESOURCE(IDD_ExportReplace),
  3229. hwnd,
  3230. ReplaceDialogProc,
  3231. (LPARAM)&RI);
  3232. switch (RI.ConfirmResult) {
  3233. case CONFIRM_YES:
  3234. case CONFIRM_YES_TO_ALL:
  3235. fForceReplace = TRUE;
  3236. break;
  3237. case CONFIRM_ABORT:
  3238. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  3239. goto exit;
  3240. default:
  3241. // NO
  3242. break;
  3243. }
  3244. break;
  3245. case WAB_REPLACE_ALWAYS:
  3246. fForceReplace = TRUE;
  3247. break;
  3248. }
  3249. if (fForceReplace) {
  3250. SBinary sbEntry;
  3251. ENTRYLIST EntryList = {1, &sbEntry};
  3252. // Find the existing PAB entry and delete it.
  3253. if (! lpDisplayName) {
  3254. lpDisplayName = (LPTSTR)szEmpty;
  3255. }
  3256. if (! lpEIDDup) {
  3257. if (HR_FAILED(hResult = FindPABEntry(lpContainerMAPI,
  3258. ulObjectType,
  3259. lpDisplayName,
  3260. lpEmailAddress,
  3261. &cbEIDDup,
  3262. &lpEIDDup))) {
  3263. // Hey, couldn't find it. Just pretend it isn't there,
  3264. // go on and create the new one anyway.
  3265. }
  3266. }
  3267. if (lpEIDDup) {
  3268. // Delete this entry.
  3269. sbEntry.cb = cbEIDDup;
  3270. sbEntry.lpb = (LPBYTE)lpEIDDup;
  3271. if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->DeleteEntries(lpContainerMAPI,
  3272. &EntryList,
  3273. 0))) {
  3274. DebugTrace("PAB DeleteEntries(%s) -> %x\n", lpDisplayName);
  3275. }
  3276. if (lpEIDDup) {
  3277. MAPIFreeBuffer(lpEIDDup);
  3278. }
  3279. }
  3280. lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
  3281. lpMailUserMAPI = NULL;
  3282. // Create a new entry without the collision flags
  3283. if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->CreateEntry(lpContainerMAPI,
  3284. lpCreateEIDsMAPI[iCreateTemplate].Value.bin.cb,
  3285. (LPENTRYID)lpCreateEIDsMAPI[iCreateTemplate].Value.bin.lpb,
  3286. 0,
  3287. &lpMailUserMAPI))) {
  3288. DebugTrace("CreateEntry(MAPI MailUser) -> %x\n", GetScode(hResult));
  3289. goto exit;
  3290. }
  3291. // Set the properties on the PAB entry
  3292. if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SetProps(lpMailUserMAPI,
  3293. cProps, // cValues
  3294. lpProps, // property array
  3295. NULL))) { // problems array
  3296. DebugTrace("ExportEntry:SetProps(MAPI) -> %x\n", GetScode(hResult));
  3297. goto exit;
  3298. }
  3299. // Save the new wab mailuser or distlist
  3300. if (HR_FAILED(hResult = lpMailUserMAPI->lpVtbl->SaveChanges(lpMailUserMAPI,
  3301. KEEP_OPEN_READONLY | FORCE_SAVE))) {
  3302. DebugTrace("SaveChanges(WAB MailUser) -> %x\n", GetScode(hResult));
  3303. } else {
  3304. fCreatedNew = TRUE;
  3305. }
  3306. } else {
  3307. fDuplicate = TRUE;
  3308. }
  3309. hResult = hrSuccess;
  3310. }
  3311. if (fCreatedNew) {
  3312. // What is the ENTRYID of our new entry?
  3313. if ((hResult = lpMailUserMAPI->lpVtbl->GetProps(lpMailUserMAPI,
  3314. (LPSPropTagArray)&ptaEid,
  3315. 0,
  3316. &cEIDPropMAPI,
  3317. &lpEIDPropMAPI))) {
  3318. DebugTrace("ExportEntry: GetProps(MAPI ENTRYID) -> %x\n", GetScode(hResult));
  3319. goto exit;
  3320. }
  3321. Assert(cEIDPropMAPI);
  3322. Assert(lpEIDPropMAPI[ieidPR_ENTRYID].ulPropTag == PR_ENTRYID);
  3323. cbEIDNew = lpEIDPropMAPI[0].Value.bin.cb;
  3324. if (FAILED(sc = MAPIAllocateBuffer(cbEIDNew, &lpEIDNew))) {
  3325. DebugTrace("ExportEntry: MAPIAllocateBuffer(MAPI ENTRYID) -> %x\n", sc);
  3326. hResult = ResultFromScode(sc);
  3327. goto exit;
  3328. }
  3329. // Copy the new EntryID into the buffer
  3330. CopyMemory(lpEIDNew, lpEIDPropMAPI[0].Value.bin.lpb, cbEIDNew);
  3331. }
  3332. //
  3333. // If this is a DISTLIST, fill it in.
  3334. //
  3335. if (fDistList && ! fDuplicate && cbEIDNew) {
  3336. lpDistListWAB = (LPDISTLIST)lpMailUserWAB; // This is REALLY a DISTLIST object
  3337. // DO NOT Release this!
  3338. // Open the new WAB DL as a DISTLIST object
  3339. if (HR_FAILED(hResult = lpContainerMAPI->lpVtbl->OpenEntry(lpContainerMAPI,
  3340. cbEIDNew,
  3341. lpEIDNew,
  3342. (LPIID)&IID_IDistList,
  3343. MAPI_MODIFY,
  3344. &ulObjectTypeOpen,
  3345. (LPUNKNOWN*)&lpDistListMAPI))) {
  3346. DebugTrace("ExportEntry: MAPI OpenEntry(IID_DistList) -> %x\n", GetScode(hResult));
  3347. goto exit;
  3348. }
  3349. Assert(lpDistListMAPI);
  3350. // For each entry in the DL:
  3351. // Migrate the entry (MailUser or DL) recursively
  3352. // Add new entryid to DL contents
  3353. if (HR_FAILED(hResult = lpDistListWAB->lpVtbl->GetContentsTable(lpDistListWAB,
  3354. 0, // ulFlags
  3355. &lpDLTableWAB))) {
  3356. DebugTrace("ExportEntry:GetContentsTable(WAB) -> %x\n", GetScode(hResult));
  3357. goto exit;
  3358. }
  3359. // Set the columns to those we're interested in
  3360. if (hResult = lpDLTableWAB->lpVtbl->SetColumns(lpDLTableWAB,
  3361. (LPSPropTagArray)&ptaColumns,
  3362. 0)) {
  3363. DebugTrace("WAB SetColumns(DL Table) -> %x\n", GetScode(hResult));
  3364. goto exit;
  3365. }
  3366. cRows = 1;
  3367. while (cRows) {
  3368. // Get the next DL entry
  3369. if (hResult = lpDLTableWAB->lpVtbl->QueryRows(lpDLTableWAB,
  3370. 1, // one row at a time
  3371. 0, // ulFlags
  3372. &lpRow)) {
  3373. DebugTrace("DL: QueryRows -> %x\n", GetScode(hResult));
  3374. goto exit;
  3375. }
  3376. if (lpRow && lpRow->cRows) {
  3377. Assert(lpRow->cRows == 1);
  3378. Assert(lpRow->aRow[0].cValues == iptaColumnsMax);
  3379. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].ulPropTag == PR_ENTRYID);
  3380. Assert(lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].ulPropTag == PR_OBJECT_TYPE);
  3381. if (lpRow) {
  3382. if (cRows = lpRow->cRows) { // yes, single '='
  3383. hResult = ExportEntry(hwnd,
  3384. lpAdrBookWAB,
  3385. lpContainerMAPI,
  3386. lpCreateEIDsMAPI,
  3387. lpRow->aRow[0].lpProps[iptaColumnsPR_OBJECT_TYPE].Value.l,
  3388. (LPENTRYID)lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.lpb,
  3389. lpRow->aRow[0].lpProps[iptaColumnsPR_ENTRYID].Value.bin.cb,
  3390. &lpeidDLMAPI, // returned new or existing entry
  3391. &cbeidDLMAPI,
  3392. TRUE,
  3393. FALSE);
  3394. if (hResult) {
  3395. if (HandleExportError(hwnd,
  3396. 0,
  3397. hResult,
  3398. lpRow->aRow[0].lpProps[iptaColumnsPR_DISPLAY_NAME].Value.LPSZ,
  3399. PropStringOrNULL(&lpRow->aRow[0].lpProps[iptaColumnsPR_EMAIL_ADDRESS]),
  3400. lpExportOptions)) {
  3401. hResult = ResultFromScode(MAPI_E_USER_CANCEL);
  3402. break; // out of loop
  3403. } else {
  3404. hResult = hrSuccess;
  3405. }
  3406. }
  3407. } // else, drop out of loop, we're done.
  3408. WABFreeProws(lpRow);
  3409. lpRow = NULL;
  3410. if (HR_FAILED(hResult)) {
  3411. // This entry couldn't be created. Ignore it.
  3412. DebugTrace("Coudln't create DL entry -> %x\n", GetScode(hResult));
  3413. hResult = hrSuccess;
  3414. continue;
  3415. }
  3416. // Add the Entry to the DL using the new entry's EntryID
  3417. if (cbeidDLMAPI && lpeidDLMAPI) {
  3418. // BUGBUG: Don't bother with this one if this is a duplicate entry.
  3419. if (HR_FAILED(hResult = lpDistListMAPI->lpVtbl->CreateEntry(lpDistListMAPI,
  3420. cbeidDLMAPI,
  3421. lpeidDLMAPI,
  3422. 0, // allow duplicates here
  3423. &lpEntryMAPI))) {
  3424. DebugTrace("Couldn't create new entry in DL -> %x\n", GetScode(hResult));
  3425. break;
  3426. }
  3427. hResult = lpEntryMAPI->lpVtbl->SaveChanges(lpEntryMAPI, FORCE_SAVE);
  3428. if (lpEntryMAPI) {
  3429. lpEntryMAPI->lpVtbl->Release(lpEntryMAPI);
  3430. lpEntryMAPI = NULL;
  3431. }
  3432. }
  3433. if (lpeidDLMAPI) {
  3434. MAPIFreeBuffer(lpeidDLMAPI);
  3435. lpeidDLMAPI = NULL;
  3436. }
  3437. }
  3438. } else {
  3439. break; // done
  3440. }
  3441. }
  3442. }
  3443. } else {
  3444. DebugTrace("Found a duplicate EntryID\n");
  3445. }
  3446. //
  3447. // Save the entryid to the list and return a buffer with it
  3448. //
  3449. if (cbEIDNew && lpEIDNew) { // We created one?
  3450. // created one
  3451. } else if (fDuplicateEID && lListIndex != -1) { // Was it in the list?
  3452. cbEIDNew = lpEntriesSeen[lListIndex].sbinWAB.cb;
  3453. if (FAILED(sc = MAPIAllocateBuffer(cbEIDNew, &lpEIDNew))) {
  3454. DebugTrace("ExportEntry: WABAllocateBuffer(WAB ENTRYID) -> %x\n", sc);
  3455. // ignore
  3456. cbEIDNew = 0;
  3457. } else {
  3458. // Copy the EntryID from the list into the buffer
  3459. CopyMemory(lpEIDNew, lpEntriesSeen[lListIndex].sbinWAB.lpb, cbEIDNew);
  3460. }
  3461. } else if (fDuplicate) { // Was it a duplicate
  3462. FindPABEntry(lpContainerMAPI,
  3463. ulObjectType,
  3464. lpDisplayName,
  3465. lpEmailAddress,
  3466. &cbEIDNew,
  3467. &lpEIDNew);
  3468. #ifdef OLD_STUFF
  3469. FindExistingPABEntry(lpProps, cProps, lpContainerMAPI, &lpEIDNew, &cbEIDNew);
  3470. #endif // OLD_STUFF
  3471. // ignore errors since the lpEIDNew and cbEIDNew will be nulled out
  3472. }
  3473. // Update the seen list
  3474. if (! fDuplicateEID) {
  3475. MarkPABEntryInList(cbEIDNew, lpEIDNew, lListIndex);
  3476. }
  3477. // If caller requested the entryid's, return them
  3478. if (lpcbEIDMAPI && lppEIDMAPI) {
  3479. *lpcbEIDMAPI = cbEIDNew;
  3480. *lppEIDMAPI = lpEIDNew;
  3481. fReturnEID = TRUE; // don't free it
  3482. }
  3483. exit:
  3484. //
  3485. // Cleanup MAPI stuff
  3486. //
  3487. if (lpProps) {
  3488. MAPIFreeBuffer(lpProps);
  3489. }
  3490. if (lpEIDPropMAPI) {
  3491. MAPIFreeBuffer(lpEIDPropMAPI);
  3492. }
  3493. if (lpEIDNew && ! fReturnEID) {
  3494. MAPIFreeBuffer(lpEIDNew);
  3495. }
  3496. if (lpeidDLMAPI) {
  3497. MAPIFreeBuffer(lpeidDLMAPI);
  3498. }
  3499. if (lpMailUserMAPI) {
  3500. lpMailUserMAPI->lpVtbl->Release(lpMailUserMAPI);
  3501. }
  3502. if (lpDistListMAPI) {
  3503. lpDistListMAPI->lpVtbl->Release(lpDistListMAPI);
  3504. }
  3505. //
  3506. // Cleanup WAB stuff
  3507. //
  3508. if (lpRow) {
  3509. WABFreeProws(lpRow);
  3510. }
  3511. if (lpDLTableWAB) {
  3512. lpDLTableWAB->lpVtbl->Release(lpDLTableWAB);
  3513. }
  3514. if (lpMailUserWAB) {
  3515. lpMailUserWAB->lpVtbl->Release(lpMailUserWAB);
  3516. }
  3517. // Do not release this... It is the same object as lpMailUserWAB!
  3518. // if (lpDistListWAB) {
  3519. // lpDistListWAB->lpVtbl->Release(lpDistListWAB);
  3520. // }
  3521. if (! HR_FAILED(hResult)) {
  3522. hResult = hrSuccess;
  3523. }
  3524. return(hResult);
  3525. }
  3526. HRESULT PABExport(HWND hWnd,
  3527. LPADRBOOK lpAdrBook,
  3528. LPWABOBJECT lpWABObject,
  3529. LPWAB_PROGRESS_CALLBACK lpProgressCB,
  3530. LPWAB_EXPORT_OPTIONS lpOptions) {
  3531. BOOL fDone = FALSE;
  3532. HRESULT hResult = hrSuccess;
  3533. lpAdrBookWAB = lpAdrBook;
  3534. lpfnProgressCB = lpProgressCB;
  3535. lpExportOptions = lpOptions;
  3536. // Setup memory allocators
  3537. SetGlobalBufferFunctions(lpWABObject);
  3538. // Prime the state machine
  3539. State = STATE_EXPORT_MU;
  3540. while (! fDone) {
  3541. switch (State) {
  3542. case STATE_EXPORT_MU:
  3543. StateExportMU(hWnd);
  3544. break;
  3545. case STATE_EXPORT_NEXT_MU:
  3546. StateExportNextMU(hWnd);
  3547. break;
  3548. case STATE_EXPORT_DL:
  3549. StateExportDL(hWnd);
  3550. break;
  3551. case STATE_EXPORT_NEXT_DL:
  3552. StateExportNextDL(hWnd);
  3553. break;
  3554. case STATE_EXPORT_FINISH:
  3555. StateExportFinish(hWnd);
  3556. fDone = TRUE;
  3557. break;
  3558. case STATE_EXPORT_ERROR:
  3559. StateExportError(hWnd);
  3560. // BUGBUG: Should set hResult to something
  3561. break;
  3562. case STATE_EXPORT_CANCEL:
  3563. StateExportCancel(hWnd);
  3564. break;
  3565. default:
  3566. DebugTrace("Unknown state %u in PABExport\n", State);
  3567. Assert(FALSE);
  3568. break;
  3569. }
  3570. }
  3571. return(hResult);
  3572. }
  3573. HRESULT PABImport(HWND hWnd,
  3574. LPADRBOOK lpAdrBook,
  3575. LPWABOBJECT lpWABObject,
  3576. LPWAB_PROGRESS_CALLBACK lpProgressCB,
  3577. LPWAB_IMPORT_OPTIONS lpOptions) {
  3578. BOOL fDone = FALSE;
  3579. HRESULT hResult = hrSuccess;
  3580. lpAdrBookWAB = lpAdrBook;
  3581. lpfnProgressCB = lpProgressCB;
  3582. lpImportOptions = lpOptions;
  3583. // Setup memory allocators
  3584. SetGlobalBufferFunctions(lpWABObject);
  3585. // Prime the state machine
  3586. State = STATE_IMPORT_MU;
  3587. while (! fDone) {
  3588. switch (State) {
  3589. case STATE_IMPORT_MU:
  3590. StateImportMU(hWnd);
  3591. break;
  3592. case STATE_IMPORT_NEXT_MU:
  3593. StateImportNextMU(hWnd);
  3594. break;
  3595. case STATE_IMPORT_DL:
  3596. StateImportDL(hWnd);
  3597. break;
  3598. case STATE_IMPORT_NEXT_DL:
  3599. StateImportNextDL(hWnd);
  3600. break;
  3601. case STATE_IMPORT_FINISH:
  3602. StateImportFinish(hWnd);
  3603. fDone = TRUE;
  3604. break;
  3605. case STATE_IMPORT_ERROR:
  3606. StateImportError(hWnd);
  3607. // BUGBUG: Should set hResult to something
  3608. break;
  3609. case STATE_IMPORT_CANCEL:
  3610. StateImportCancel(hWnd);
  3611. break;
  3612. default:
  3613. DebugTrace("Unknown state %u in PABImport\n", State);
  3614. Assert(FALSE);
  3615. break;
  3616. }
  3617. }
  3618. return(hResult);
  3619. }
  3620. /*
  3621. - HrLoadPrivateWABProps
  3622. -
  3623. * Private function to load Conferencing Named properties
  3624. * as globals up front
  3625. *
  3626. *
  3627. */
  3628. HRESULT HrLoadPrivateWABPropsForCSV(LPADRBOOK lpIAB)
  3629. {
  3630. HRESULT hr = E_FAIL;
  3631. LPSPropTagArray lpta = NULL;
  3632. SCODE sc = 0;
  3633. ULONG i, uMax = prWABConfMax, nStartIndex = OLK_NAMEDPROPS_START;
  3634. LPMAPINAMEID *lppConfPropNames = NULL;
  3635. sc = WABAllocateBuffer(sizeof(LPMAPINAMEID) * uMax, (LPVOID *) &lppConfPropNames);
  3636. //sc = WABAllocateBuffer(sizeof(LPMAPINAMEID) * uMax, (LPVOID *) &lppConfPropNames);
  3637. if( (HR_FAILED(hr = ResultFromScode(sc))) )
  3638. goto err;
  3639. for(i=0;i< uMax;i++)
  3640. {
  3641. //sc = WABAllocateMore(sizeof(MAPINAMEID), lppConfPropNames, &(lppConfPropNames[i]));
  3642. sc = WABAllocateMore( sizeof(MAPINAMEID), lppConfPropNames, &(lppConfPropNames[i]));
  3643. if(sc)
  3644. {
  3645. hr = ResultFromScode(sc);
  3646. goto err;
  3647. }
  3648. lppConfPropNames[i]->lpguid = (LPGUID) &PS_Conferencing;
  3649. lppConfPropNames[i]->ulKind = MNID_ID;
  3650. lppConfPropNames[i]->Kind.lID = nStartIndex + i;
  3651. }
  3652. // Load the set of conferencing named props
  3653. //
  3654. if( HR_FAILED(hr = (lpIAB)->lpVtbl->GetIDsFromNames(lpIAB, uMax, lppConfPropNames,
  3655. MAPI_CREATE, &lpta) ))
  3656. goto err;
  3657. if(lpta)
  3658. {
  3659. // Set the property types on the returned props
  3660. PR_SERVERS = CHANGE_PROP_TYPE(lpta->aulPropTag[prWABConfServers], PT_MV_TSTRING);
  3661. }
  3662. rgPropNames[NUM_MORE_EXPORT_PROPS-1].ulPropTag = PR_SERVERS;
  3663. rgPropNames[NUM_MORE_EXPORT_PROPS-1].fChosen = FALSE;
  3664. rgPropNames[NUM_MORE_EXPORT_PROPS-1].ids = ids_ExportConfServer;
  3665. rgPropNames[NUM_MORE_EXPORT_PROPS-1].lpszName = NULL;
  3666. rgPropNames[NUM_MORE_EXPORT_PROPS-1].lpszCSVName = NULL;
  3667. err:
  3668. if(lpta)
  3669. WABFreeBuffer( lpta );
  3670. if( lppConfPropNames )
  3671. WABFreeBuffer( lppConfPropNames );
  3672. //WABFreeBuffer(lpta);
  3673. return hr;
  3674. }