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.

936 lines
32 KiB

  1. /*
  2. -
  3. -
  4. - WABImprt.c - Contains code for importing another WAB into the currently opened WAB
  5. *
  6. *
  7. */
  8. #include "_apipch.h"
  9. /*
  10. -
  11. - PromptForWABFile
  12. *
  13. * Shows the OpenFileName dialog to prompt for the WAB file to import
  14. * <TBD>:Cache the last imported WAB file in the registry
  15. *
  16. * bOpen - if TRUE, calls GetOpenFileName; if false, calls GetSaveFileName
  17. */
  18. BOOL PromptForWABFile(HWND hWnd, LPTSTR pszFile, DWORD cchSizeFile, BOOL bOpen)
  19. {
  20. OPENFILENAME ofn;
  21. LPTSTR lpFilter = FormatAllocFilter(idsWABImportString, TEXT("*.WAB"),0,NULL,0,NULL);
  22. TCHAR szFileName[MAX_PATH + 1] = TEXT("");
  23. TCHAR szTitle[MAX_PATH] = TEXT("");
  24. BOOL bRet = FALSE;
  25. LoadString( hinstMapiX, bOpen ? idsSelectWABToImport : idsSelectWABToExport, szTitle, ARRAYSIZE(szTitle));
  26. ofn.lStructSize = sizeof(ofn);
  27. ofn.hwndOwner = hWnd;
  28. ofn.hInstance = hinstMapiX;
  29. ofn.lpstrFilter = lpFilter;
  30. ofn.lpstrCustomFilter = NULL;
  31. ofn.nMaxCustFilter = 0;
  32. ofn.nFilterIndex = 0;
  33. ofn.lpstrFile = szFileName;
  34. ofn.nMaxFile = ARRAYSIZE(szFileName);
  35. ofn.lpstrFileTitle = NULL;
  36. ofn.nMaxFileTitle = 0;
  37. ofn.lpstrInitialDir = NULL;
  38. ofn.lpstrTitle = szTitle;
  39. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  40. ofn.nFileOffset = 0;
  41. ofn.nFileExtension = 0;
  42. ofn.lpstrDefExt = TEXT("wab");
  43. ofn.lCustData = 0;
  44. ofn.lpfnHook = NULL;
  45. ofn.lpTemplateName = NULL;
  46. if(bOpen)
  47. bRet = GetOpenFileName(&ofn);
  48. else
  49. bRet = GetSaveFileName(&ofn);
  50. if(bRet)
  51. StrCpyN(pszFile, szFileName, cchSizeFile);
  52. LocalFreeAndNull(&lpFilter);
  53. return bRet;
  54. }
  55. /*
  56. - MapOldNamedPropsToNewNamedProps
  57. -
  58. * Takes all the props from the wab being imported and finds or creates appropriate
  59. * named props from the store being imported into
  60. * *lpulOldNP and *lpulNewNP are LocalAlloced and should be freed by caller
  61. typedef struct _NamedProp
  62. {
  63. ULONG ulPropTag; // Contains the proptag for this named prop
  64. LPTSTR lpsz; // Contains the string for this named prop
  65. } NAMED_PROP, * LPNAMED_PROP;
  66. typedef struct _tagGuidNamedProps
  67. {
  68. LPGUID lpGUID; // Application GUID for which these named props are
  69. ULONG cValues; // Number of entries in the lpmn array
  70. LPNAMED_PROP lpnm; // Array of Named Props for this Guid.
  71. } GUID_NAMED_PROPS, * LPGUID_NAMED_PROPS;
  72. */
  73. HRESULT MapOldNamedPropsToNewNamedProps(HANDLE hPropertyStore, LPADRBOOK lpAdrBook, ULONG * lpulPropCount,
  74. LPULONG * lppulOldNP, LPULONG * lppulNewNP)
  75. {
  76. ULONG ulcGUIDCount = 0,i=0,j=0,ulCount=0;
  77. LPGUID_NAMED_PROPS lpgnp = NULL;
  78. HRESULT hr = S_OK;
  79. LPULONG lpulOldNP = NULL, lpulNewNP = NULL;
  80. ULONG ulcOldNPCount = 0;
  81. LPSPropTagArray lpta = NULL;
  82. LPMAPINAMEID * lppPropNames = NULL;
  83. SCODE sc ;
  84. if(HR_FAILED(hr = GetNamedPropsFromPropStore(hPropertyStore, &ulcGUIDCount, &lpgnp)))
  85. goto exit;
  86. if(ulcGUIDCount)
  87. {
  88. for(i=0;i<ulcGUIDCount;i++)
  89. ulcOldNPCount += lpgnp[i].cValues;
  90. lpulOldNP = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG) * ulcOldNPCount);
  91. lpulNewNP = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG) * ulcOldNPCount);
  92. if(!lpulOldNP || !lpulNewNP)
  93. {
  94. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  95. goto exit;
  96. }
  97. ulCount = 0;
  98. for(i=0;i<ulcGUIDCount;i++)
  99. {
  100. for(j=0;j<lpgnp[i].cValues;j++)
  101. {
  102. lpulOldNP[ulCount++] = lpgnp[i].lpnm[j].ulPropTag;
  103. }
  104. }
  105. sc = MAPIAllocateBuffer(sizeof(LPMAPINAMEID) * ulcOldNPCount, (LPVOID *) &lppPropNames);
  106. if(sc)
  107. {
  108. hr = ResultFromScode(sc);
  109. goto exit;
  110. }
  111. ulCount = 0;
  112. for(i=0;i<ulcGUIDCount;i++)
  113. {
  114. for(j=0;j<lpgnp[i].cValues;j++)
  115. {
  116. if(sc = MAPIAllocateMore(sizeof(MAPINAMEID), lppPropNames, &(lppPropNames[ulCount])))
  117. {
  118. hr = ResultFromScode(sc);
  119. goto exit;
  120. }
  121. lppPropNames[ulCount]->lpguid = lpgnp[i].lpGUID;
  122. lppPropNames[ulCount]->ulKind = MNID_STRING;
  123. {
  124. int nSize = lstrlen(lpgnp[i].lpnm[j].lpsz);
  125. if(!nSize)
  126. continue;
  127. else
  128. {
  129. nSize++;
  130. if(sc = MAPIAllocateMore(sizeof(WCHAR)*nSize, lppPropNames, &(lppPropNames[ulCount]->Kind.lpwstrName)))
  131. {
  132. hr = ResultFromScode(sc);
  133. goto exit;
  134. }
  135. }
  136. StrCpyN(lppPropNames[ulCount]->Kind.lpwstrName,lpgnp[i].lpnm[j].lpsz, nSize);
  137. ulCount++;
  138. }
  139. }
  140. }
  141. // [PaulHi] 3/25/99 Use the actual count of the lppPropNames array, or we will walk off
  142. // into unknown memory and crash.
  143. ulcOldNPCount = ulCount;
  144. hr = lpAdrBook->lpVtbl->GetIDsFromNames(lpAdrBook, ulcOldNPCount, lppPropNames, MAPI_CREATE, &lpta);
  145. if(HR_FAILED(hr))
  146. goto exit;
  147. // Note that of the tags that are returned, we don't know the tag type .. this we will have
  148. // to infer based on the original tags when we see them being used
  149. ulCount = 0;
  150. for(i=0;i<ulcGUIDCount;i++)
  151. {
  152. for(j=0;j<lpgnp[i].cValues;j++)
  153. {
  154. lpulNewNP[ulCount++] = lpta->aulPropTag[ulCount];
  155. }
  156. }
  157. }
  158. *lppulNewNP = lpulNewNP;
  159. *lppulOldNP = lpulOldNP;
  160. *lpulPropCount = ulcOldNPCount;
  161. hr = S_OK;
  162. exit:
  163. if(lpta)
  164. MAPIFreeBuffer(lpta);
  165. if(lppPropNames)
  166. MAPIFreeBuffer(lppPropNames);
  167. if(HR_FAILED(hr))
  168. {
  169. LocalFreeAndNull(&lpulNewNP);
  170. LocalFreeAndNull(&lpulOldNP);
  171. }
  172. FreeGuidnamedprops(ulcGUIDCount, lpgnp);
  173. return hr;
  174. }
  175. /***************************************************************************
  176. ****************************************************************************/
  177. void ChangeOldNamedPropsToNewNamedProps(ULONG ulcProps, LPSPropValue lpProps,
  178. ULONG ulcNPCount, ULONG * lpulOldNP, ULONG *lpulNewNP)
  179. {
  180. ULONG i,j;
  181. for(i=0;i<ulcProps;i++)
  182. {
  183. ULONG ulPropId = PROP_ID(lpProps[i].ulPropTag);
  184. if(ulPropId >= 0x8000) //this is a named prop
  185. {
  186. ULONG ulType = PROP_TYPE(lpProps[i].ulPropTag);
  187. for(j=0;j<ulcNPCount;j++)
  188. {
  189. if(ulPropId == PROP_ID(lpulOldNP[j]))
  190. {
  191. lpProps[i].ulPropTag = CHANGE_PROP_TYPE(lpulNewNP[j], ulType);
  192. break;
  193. }
  194. }
  195. }
  196. }
  197. return;
  198. }
  199. enum
  200. {
  201. eidOld=0,
  202. eidTemp,
  203. eidNew,
  204. eidMax
  205. };
  206. void SetTempSBinary(LPSBinary lpsbTemp, LPSBinary lpsbOld)
  207. {
  208. DWORD dwTemp = 0;
  209. if(lpsbOld->cb != SIZEOF_WAB_ENTRYID)
  210. {
  211. // perhaps this is a Folder EID in it's formal proper form ..
  212. // We should try to reduce it to a DWORD...
  213. // this may be a WAB container .. reset the entryid to a WAB entryid
  214. if(WAB_CONTAINER == IsWABEntryID(lpsbTemp->cb, (LPENTRYID)lpsbTemp->lpb,
  215. NULL,NULL,NULL,NULL,NULL))
  216. {
  217. SBinary sbEID = {0};
  218. IsWABEntryID(lpsbTemp->cb, (LPENTRYID)lpsbTemp->lpb,
  219. (LPVOID*)&sbEID.lpb,(LPVOID*)&sbEID.cb,NULL,NULL,NULL);
  220. if(sbEID.cb == SIZEOF_WAB_ENTRYID)
  221. CopyMemory(&dwTemp, sbEID.lpb, min(sbEID.cb, sizeof(dwTemp)));
  222. else return;
  223. }
  224. }
  225. else
  226. CopyMemory(&dwTemp, lpsbOld->lpb, min(lpsbOld->cb, sizeof(dwTemp)));
  227. dwTemp = 0xFFFFFFFF - dwTemp;
  228. SetSBinary(lpsbTemp, lpsbOld->cb, (LPBYTE)&dwTemp);
  229. }
  230. /*
  231. - GetNewEID
  232. -
  233. * Finds a new entryid or a temp entryid for a given old entryid
  234. * When bTemp is true, only looks in the temp entryid column
  235. */
  236. LPSBinary GetNewEID(LPSBinary lpsbOldEID, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp)
  237. {
  238. DWORD dw = 0;
  239. while(lppsbEIDs[eidOld][dw].cb && dw < dwCount)
  240. {
  241. if( lppsbEIDs[eidOld][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp
  242. !memcmp(lppsbEIDs[eidOld][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb))
  243. {
  244. if(bTemp)
  245. return lpsbOldEID;
  246. if(lppsbEIDs[eidNew][dw].cb)
  247. return &(lppsbEIDs[eidNew][dw]);
  248. else if(lppsbEIDs[eidTemp][dw].cb)
  249. return &(lppsbEIDs[eidTemp][dw]);
  250. else
  251. return lpsbOldEID;
  252. }
  253. else
  254. if( lppsbEIDs[eidTemp][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp
  255. !memcmp(lppsbEIDs[eidTemp][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb))
  256. {
  257. if(lppsbEIDs[eidNew][dw].cb)
  258. return &(lppsbEIDs[eidNew][dw]);
  259. else
  260. return lpsbOldEID;
  261. }
  262. dw++;
  263. }
  264. // if we reached here, then we haven't cached an appropriate temp or new eid for the current one
  265. // so add the current one to this table
  266. if(dw<dwCount && !lppsbEIDs[eidOld][dw].cb)
  267. {
  268. SetSBinary(&(lppsbEIDs[eidOld][dw]), lpsbOldEID->cb, lpsbOldEID->lpb);
  269. SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID);
  270. return(&(lppsbEIDs[eidTemp][dw]));
  271. }
  272. return lpsbOldEID;
  273. }
  274. /*
  275. - SetNewEID
  276. -
  277. *
  278. */
  279. void SetNewEID(LPSBinary lpsbOldEID, LPSBinary lpsbNewEID, DWORD dwCount, LPSBinary * lppsbEIDs)
  280. {
  281. DWORD dw = 0;
  282. while(lppsbEIDs[eidOld][dw].cb && dw < dwCount)
  283. {
  284. if( lppsbEIDs[eidOld][dw].cb == lpsbOldEID->cb && // if it's an old eid, return a new or a temp
  285. !memcmp(lppsbEIDs[eidOld][dw].lpb, lpsbOldEID->lpb, lpsbOldEID->cb))
  286. {
  287. SetSBinary(&(lppsbEIDs[eidNew][dw]), lpsbNewEID->cb, lpsbNewEID->lpb);
  288. if(!lppsbEIDs[eidTemp][dw].cb)
  289. SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID);
  290. return;
  291. }
  292. dw++;
  293. }
  294. if(dw<dwCount && !lppsbEIDs[eidOld][dw].cb)
  295. {
  296. SetSBinary(&lppsbEIDs[eidOld][dw], lpsbOldEID->cb, lpsbOldEID->lpb);
  297. SetSBinary(&lppsbEIDs[eidNew][dw], lpsbNewEID->cb, lpsbNewEID->lpb);
  298. SetTempSBinary(&(lppsbEIDs[eidTemp][dw]), lpsbOldEID);
  299. }
  300. }
  301. /*
  302. -
  303. - Replace EID
  304. *
  305. */
  306. void ReplaceEID(LPSBinary lpsb, LPSPropValue lpProps, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp)
  307. {
  308. LPSBinary lpsbOldEID = lpsb;
  309. LPSBinary lpsbNewEID = GetNewEID(lpsbOldEID, dwCount, lppsbEIDs, bTemp);
  310. if(lpsbOldEID == lpsbNewEID)
  311. return;
  312. if(lpsbOldEID->cb != lpsbNewEID->cb)
  313. {
  314. if(!bTemp)
  315. {
  316. // this is a prop array read from a WAB file using readrecord
  317. LocalFree(lpsbOldEID->lpb);
  318. lpsbOldEID->lpb = LocalAlloc(LMEM_ZEROINIT, lpsbNewEID->cb);
  319. }
  320. else
  321. {
  322. // this was called from GetProps and is a MAPI Array
  323. lpsbOldEID->lpb = NULL;
  324. MAPIAllocateMore(lpsbNewEID->cb, lpProps, (LPVOID *) (&(lpsbOldEID->lpb)));
  325. }
  326. }
  327. if(lpsbOldEID->lpb)
  328. {
  329. lpsbOldEID->cb = lpsbNewEID->cb;
  330. CopyMemory(lpsbOldEID->lpb, lpsbNewEID->lpb, lpsbNewEID->cb);
  331. }
  332. }
  333. /*
  334. - UpdateEntryIDReferences
  335. -
  336. * Updates entryids in the given prop array
  337. *
  338. * The first time the function is called, btemp is FALSE and we replace all EIDs in the
  339. * array with temp or new eids
  340. * The second time this function is called, bTemp is TRUE and we replace all temp EIDS in
  341. * the array with the new EIDs
  342. *
  343. */
  344. void UpdateEntryIDReferences(ULONG ulcProps, LPSPropValue lpProps, DWORD dwCount, LPSBinary * lppsbEIDs, BOOL bTemp)
  345. {
  346. ULONG i, j, k, l;
  347. ULONG ulEntryIDTags[] =
  348. {
  349. PR_WAB_DL_ENTRIES,
  350. PR_WAB_FOLDER_PARENT,
  351. PR_WAB_FOLDER_PARENT_OLDPROP,
  352. PR_WAB_USER_SUBFOLDERS,
  353. };
  354. DWORD dwEntryIDTagCount = 4; //keep in sync with above array
  355. for(i=0;i<ulcProps;i++)
  356. {
  357. ULONG ulType = PROP_TYPE(lpProps[i].ulPropTag);
  358. // Props containing entryids will be of Binary or MV_Binary type
  359. if(ulType == PT_BINARY || ulType == PT_MV_BINARY)
  360. {
  361. // Check against the known set of props dealing with entryids
  362. for(j=0;j<dwEntryIDTagCount;j++)
  363. {
  364. if(lpProps[i].ulPropTag == ulEntryIDTags[j])
  365. {
  366. LPSBinary lpsbOldEID = NULL, lpsbNewEID = NULL;
  367. switch(ulType)
  368. {
  369. case PT_BINARY:
  370. //if(lpProps[i].Value.bin.cb == SIZEOF_WAB_ENTRYID)
  371. {
  372. ReplaceEID(&(lpProps[i].Value.bin), lpProps, dwCount, lppsbEIDs, bTemp);
  373. }
  374. break;
  375. case PT_MV_BINARY:
  376. for(k=0;k<lpProps[i].Value.MVbin.cValues;k++)
  377. {
  378. //if(lpProps[i].Value.MVbin.lpbin[k].cb == SIZEOF_WAB_ENTRYID)
  379. {
  380. ReplaceEID(&(lpProps[i].Value.MVbin.lpbin[k]), lpProps, dwCount, lppsbEIDs, bTemp);
  381. }
  382. }
  383. break;
  384. }
  385. break;
  386. }
  387. }
  388. }
  389. }
  390. }
  391. /***************************************************************************
  392. Name : HrImportWABFile
  393. Purpose : Merges an external WAB file with the current on
  394. Parameters: hwnd = hwnd
  395. lpIAB -> IAddrBook object
  396. ulFlags = 0 or MAPI_DIALOG - MAPI_DIALOG means show msgs and progress bar
  397. lpszFileName - file name to open, if 0 prompts with GetOpenFileName dialog
  398. Returns : HRESULT
  399. Comment :
  400. ***************************************************************************/
  401. HRESULT HrImportWABFile(HWND hWnd, LPADRBOOK lpAdrBook, ULONG ulFlags, LPTSTR lpszFileName)
  402. {
  403. LPIAB lpIAB = (LPIAB) lpAdrBook;
  404. BOOL bFoldersImported = FALSE;
  405. HRESULT hr = E_FAIL;
  406. HRESULT hrDeferred = S_OK;
  407. TCHAR szWABFile[MAX_PATH+1] = TEXT("");
  408. TCHAR szFile[MAX_PATH+1] = TEXT(""), szPath[MAX_PATH] = TEXT("");
  409. HANDLE hPropertyStore = NULL;
  410. DWORD dwWABEntryCount = 0;
  411. LPSBinary * lppsbWABEIDs = NULL;
  412. ULONG ulcNPCount = 0;
  413. LPULONG lpulOldNP = NULL,lpulNewNP = NULL;
  414. ULONG i,j,k,n;
  415. BOOL bShowUI = (hWnd && (ulFlags & MAPI_DIALOG));
  416. ULONG rgObj[] = { MAPI_MAILUSER, MAPI_DISTLIST, MAPI_ABCONT };
  417. #ifdef IMPORT_FOLDERS
  418. #define ulrgObjMax 3
  419. #else
  420. #define ulrgObjMax 2
  421. #endif
  422. SBinary sbPAB = {0};
  423. SPropertyRestriction PropRes = {0};
  424. //HCURSOR hOldCur = NULL;
  425. SPropValue sp = {0};
  426. ULONG ulcOldProps = 0;
  427. LPSPropValue lpOldProps = NULL;
  428. LPMAPIPROP lpObject = NULL;
  429. ULONG ulEIDCount = 0;
  430. LPSBinary rgsbEntryIDs = NULL;
  431. TCHAR szBuf[MAX_UI_STR];
  432. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  433. if(lpszFileName && lstrlen(lpszFileName))
  434. StrCpyN(szWABFile, lpszFileName, ARRAYSIZE(szWABFile));
  435. else if (!PromptForWABFile(hWnd, szWABFile, ARRAYSIZE(szWABFile), TRUE))
  436. {
  437. hr = MAPI_E_USER_CANCEL;
  438. goto exit;
  439. }
  440. //hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  441. // when importing old format files, there is always a possibility that the file data may get
  442. // munged when opening the file ..
  443. // therefore, before we attempt to import it, we will try to make a copy of the file
  444. if(GetFileAttributes(szWABFile) == 0xFFFFFFFF)
  445. goto exit;
  446. if (!GetTempPath(ARRAYSIZE(szPath), szPath))
  447. goto exit;
  448. if(!GetTempFileName(szPath, TEXT("WAB"), 0, szFile))
  449. goto exit;
  450. if(!CopyFile(szWABFile, szFile, FALSE))
  451. goto exit;
  452. if(GetFileAttributes(szFile) == 0xFFFFFFFF)
  453. goto exit;
  454. // First let's open this file
  455. hr = OpenPropertyStore(szFile, AB_OPEN_EXISTING | AB_DONT_RESTORE | AB_IGNORE_OUTLOOK, hWnd, &hPropertyStore);
  456. if(HR_FAILED(hr) || (!hPropertyStore))
  457. {
  458. //if(bShowUI)
  459. // ShowMessageBoxParam(hWnd, IDE_VCARD_IMPORT_FILE_ERROR, MB_ICONEXCLAMATION, szFile);
  460. goto exit;
  461. }
  462. // get a count of how many entries exist in this new .wab file
  463. if(!(dwWABEntryCount = GetWABFileEntryCount(hPropertyStore)))
  464. {
  465. hr = S_OK;
  466. goto exit;
  467. }
  468. if(bShowUI)
  469. {
  470. EnableWindow(hWnd, FALSE);
  471. CreateShowAbortDialog(hWnd, idsImporting, IDI_ICON_IMPORT, dwWABEntryCount*2 + 1, 0);
  472. }
  473. if(lppsbWABEIDs = LocalAlloc(LMEM_ZEROINIT, sizeof(LPSBinary) * eidMax))
  474. {
  475. for(i=0;i<eidMax;i++)
  476. {
  477. lppsbWABEIDs [i] = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary) * dwWABEntryCount);
  478. if(!lppsbWABEIDs [i])
  479. {
  480. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  481. goto exit;
  482. }
  483. }
  484. }
  485. else
  486. {
  487. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  488. goto exit;
  489. }
  490. // Before we start doing anything we need to get the appropriate named properties
  491. // from the importee so that we can correctly map them to stuff in the new store ..
  492. // By calling GetIDsFromNames, all the old GUIDs etc will automatically be migrated into the
  493. // final file from the importee
  494. if(HR_FAILED(hr = MapOldNamedPropsToNewNamedProps(hPropertyStore, lpAdrBook, &ulcNPCount,
  495. &lpulOldNP, &lpulNewNP)))
  496. goto exit;
  497. if(HR_FAILED(lpAdrBook->lpVtbl->GetPAB(lpAdrBook, &sbPAB.cb, (LPENTRYID *)&sbPAB.lpb)))
  498. goto exit;
  499. for(n=0;n<ulrgObjMax;n++)
  500. {
  501. // Next we want to get a list of all the contacts in the WAB ...
  502. PropRes.ulPropTag = PR_OBJECT_TYPE;
  503. PropRes.relop = RELOP_EQ;
  504. sp.ulPropTag = PR_OBJECT_TYPE;
  505. sp.Value.l = rgObj[n];
  506. PropRes.lpProp = &sp;
  507. // skip doing folders for Outlook
  508. if(pt_bIsWABOpenExSession && rgObj[n]==MAPI_ABCONT)
  509. continue;
  510. if(HR_FAILED(hr = FindRecords(hPropertyStore, NULL, AB_IGNORE_OUTLOOK, TRUE, &PropRes, &ulEIDCount, &rgsbEntryIDs)))
  511. goto exit;
  512. if(bTimeToAbort())
  513. {
  514. hr = MAPI_E_USER_CANCEL;
  515. goto exit;
  516. }
  517. // Now that we have a list of all contacts we want to open them one by one and
  518. // - change named props to new named props
  519. // - tag all existing entryid properties in it
  520. // - remove existing entryid from it
  521. // - do a save changes with create merge
  522. // - get the new entryid and cache it
  523. //
  524. for(i=0;i<ulEIDCount;i++)
  525. {
  526. SBinary sbOldEID = {0};
  527. SBinary sbNewEID = {0};
  528. BOOL bIsFolderMember = FALSE;
  529. if(bTimeToAbort())
  530. {
  531. hr = MAPI_E_USER_CANCEL;
  532. goto exit;
  533. }
  534. if(HR_FAILED(hr = ReadRecord(hPropertyStore, &rgsbEntryIDs[i], AB_IGNORE_OUTLOOK, &ulcOldProps, &lpOldProps)))
  535. continue; // ignore errors
  536. // just make sure no container has snuck in here
  537. if(rgObj[n] != MAPI_ABCONT)
  538. {
  539. for(j=0;j<ulcOldProps;j++)
  540. {
  541. if( lpOldProps[j].ulPropTag == PR_OBJECT_TYPE &&
  542. lpOldProps[j].Value.l == MAPI_ABCONT)
  543. {
  544. goto endofthisloop;
  545. }
  546. }
  547. }
  548. for(j=0;j<ulcOldProps;j++)
  549. {
  550. if(lpOldProps[j].ulPropTag == PR_DISPLAY_NAME)
  551. {
  552. if(bShowUI)
  553. SetPrintDialogMsg(0, idsImportingName, lpOldProps[j].Value.LPSZ);
  554. }
  555. if(lpOldProps[j].ulPropTag == PR_WAB_FOLDER_PARENT_OLDPROP && PR_WAB_FOLDER_PARENT)
  556. lpOldProps[j].ulPropTag = PR_WAB_FOLDER_PARENT;
  557. if(lpOldProps[j].ulPropTag == PR_WAB_FOLDER_PARENT)
  558. {
  559. #ifdef IMPORT_FOLDERS
  560. bIsFolderMember = TRUE;
  561. #else
  562. // remove any folder parent info on this entry
  563. ULONG k = 0;
  564. lpOldProps[j].ulPropTag = PR_NULL;
  565. for(k=0;k<lpOldProps[j].Value.MVbin.cValues;k++)
  566. LocalFreeAndNull((LPVOID *) (&(lpOldProps[j].Value.MVbin.lpbin[k].lpb)));
  567. LocalFreeAndNull((LPVOID *) (&(lpOldProps[j].Value.MVbin.lpbin)));
  568. #endif
  569. }
  570. }
  571. // Scan these props and change any old named props in them
  572. ChangeOldNamedPropsToNewNamedProps(ulcOldProps, lpOldProps, ulcNPCount, lpulOldNP, lpulNewNP);
  573. // Update any references to entryids in any of the properties
  574. UpdateEntryIDReferences(ulcOldProps, lpOldProps, dwWABEntryCount, lppsbWABEIDs, FALSE);
  575. // negate the old eid after caching it
  576. for(j=0;j<ulcOldProps;j++)
  577. {
  578. if(lpOldProps[j].ulPropTag == PR_ENTRYID)
  579. {
  580. Assert(lpOldProps[j].Value.bin.cb == SIZEOF_WAB_ENTRYID);
  581. SetSBinary(&sbOldEID, lpOldProps[j].Value.bin.cb, lpOldProps[j].Value.bin.lpb);
  582. LocalFreeAndNull((LPVOID *) (&(lpOldProps[j].Value.bin.lpb)));
  583. lpOldProps[j].Value.bin.cb = 0;
  584. lpOldProps[j].ulPropTag = PR_NULL;
  585. break;
  586. }
  587. }
  588. #ifdef IMPORT_FOLDERS
  589. // if these are containers, they may have ProfileIDs in them .. negate the profile ids
  590. // to some random number so they don't cause problems with the existing profile ids in this contact
  591. if(rgObj[n]==MAPI_ABCONT)
  592. {
  593. bFoldersImported = TRUE;
  594. bIsFolderMember = FALSE; //folders shouldnt end up nested.. all should be at top level
  595. for(j=0;j<ulcOldProps;j++)
  596. {
  597. if( lpOldProps[j].ulPropTag == PR_WAB_USER_PROFILEID )
  598. {
  599. // This is some kind of user-folder .. well we don't know how this relates
  600. // to the users of the WAB into which this is being imported, so we hide this value
  601. lpOldProps[j].ulPropTag = PR_NULL;
  602. LocalFreeAndNull(&(lpOldProps[j].Value.LPSZ));
  603. // If we were importing a User Folder, and there is no current user, this folder
  604. // is going to get lost .. so instead we set the SHARED flag to true on it and it
  605. // will show up under Shared Contacts
  606. if(!bIsThereACurrentUser(lpIAB) && bDoesThisWABHaveAnyUsers(lpIAB))
  607. {
  608. lpOldProps[j].ulPropTag = PR_WAB_SHAREDFOLDER;
  609. lpOldProps[j].Value.l = FOLDER_SHARED;
  610. }
  611. }
  612. else
  613. if( lpOldProps[j].ulPropTag == PR_WAB_FOLDEROWNER) // folder-owner info is meaningless here ..
  614. {
  615. lpOldProps[j].ulPropTag = PR_NULL;
  616. LocalFreeAndNull(&(lpOldProps[j].Value.LPSZ));
  617. }
  618. else
  619. if( lpOldProps[j].ulPropTag == PR_WAB_FOLDER_PARENT) // don't want a folder parent here.
  620. {
  621. ULONG k = 0;
  622. lpOldProps[j].ulPropTag = PR_NULL;
  623. for(k=0;k<lpOldProps[j].Value.MVbin.cValues;k++)
  624. LocalFreeAndNull(&(lpOldProps[j].Value.MVbin.lpbin[k].lpb));
  625. LocalFreeAndNull(&(lpOldProps[j].Value.MVbin.lpbin));
  626. }
  627. }
  628. }
  629. #endif
  630. {
  631. LPSBinary lpsb = NULL;
  632. #ifdef IMPORT_FOLDERS
  633. lpsb = bIsFolderMember ? NULL : &sbPAB;//if this is already a member of some folder, don't reset parenthood on it
  634. #else
  635. lpsb = &sbPAB;
  636. #endif
  637. // Create a new mailuser for this entry
  638. if(HR_FAILED(hr = HrCreateNewObject(lpAdrBook, lpsb,
  639. MAPI_MAILUSER,
  640. CREATE_CHECK_DUP_STRICT | CREATE_REPLACE | CREATE_MERGE,
  641. &lpObject)))
  642. {
  643. hrDeferred = hr;
  644. hr = S_OK;
  645. goto endofthisloop;
  646. }
  647. }
  648. // Set the old guys props on the new guy - note that this overwrites any common props on
  649. // potential duplicates when calling savechanges
  650. if(HR_FAILED(hr = lpObject->lpVtbl->SetProps(lpObject, ulcOldProps, lpOldProps, NULL)))
  651. {
  652. hrDeferred = hr;
  653. hr = S_OK;
  654. goto endofthisloop;
  655. }
  656. // SaveChanges
  657. if(HR_FAILED(hr = lpObject->lpVtbl->SaveChanges(lpObject, KEEP_OPEN_READONLY)))
  658. {
  659. hrDeferred = hr;
  660. hr = S_OK;
  661. goto endofthisloop;
  662. }
  663. // By now the object has a new or existin EID .. if so, use this EID
  664. {
  665. ULONG ulcNewProps = 0;
  666. LPSPropValue lpNewProps = NULL;
  667. if(HR_FAILED(hr = lpObject->lpVtbl->GetProps(lpObject, NULL, MAPI_UNICODE, &ulcNewProps, &lpNewProps)))
  668. {
  669. hrDeferred = hr;
  670. hr = S_OK;
  671. goto endofthisloop;
  672. }
  673. for(j=0;j<ulcNewProps;j++)
  674. {
  675. if(lpNewProps[j].ulPropTag == PR_ENTRYID)
  676. {
  677. if(rgObj[n] != MAPI_ABCONT)
  678. SetSBinary(&sbNewEID, lpNewProps[j].Value.bin.cb, lpNewProps[j].Value.bin.lpb);
  679. #ifdef IMPORT_FOLDERS
  680. else
  681. {
  682. ULONG cb = 0; LPENTRYID lpb = NULL;
  683. if(!HR_FAILED(CreateWABEntryID( WAB_CONTAINER,
  684. lpNewProps[j].Value.bin.lpb, NULL, NULL,
  685. lpNewProps[j].Value.bin.cb, 0,
  686. NULL, &cb, &lpb)))
  687. {
  688. // Add the entryids to this prop - ignore errors
  689. SetSBinary(&sbNewEID, cb, (LPBYTE)lpb);
  690. MAPIFreeBuffer(lpb);
  691. }
  692. }
  693. if(rgObj[n] == MAPI_ABCONT && bIsThereACurrentUser(lpIAB))
  694. hr = HrAddRemoveFolderFromUserFolder(lpIAB, NULL, &sbNewEID, NULL, TRUE);
  695. #endif
  696. break;
  697. }
  698. }
  699. MAPIFreeBuffer(lpNewProps);
  700. }
  701. SetNewEID(&sbOldEID, &sbNewEID, dwWABEntryCount, lppsbWABEIDs);
  702. endofthisloop:
  703. if(sbOldEID.lpb)
  704. LocalFree(sbOldEID.lpb);
  705. if(sbNewEID.lpb)
  706. LocalFree(sbNewEID.lpb);
  707. ReadRecordFreePropArray(NULL, ulcOldProps, &lpOldProps);
  708. ulcOldProps = 0;
  709. lpOldProps = NULL;
  710. if(lpObject)
  711. lpObject->lpVtbl->Release(lpObject);
  712. lpObject = NULL;
  713. } //for i..
  714. FreeEntryIDs(NULL, ulEIDCount, rgsbEntryIDs);
  715. rgsbEntryIDs = NULL;
  716. ulEIDCount = 0;
  717. } // for n..
  718. if(bShowUI)
  719. SetPrintDialogMsg(idsImportProcessing, 0, szEmpty);
  720. // Now that we have opened all the entries, we need to reopen the new entries in the new WAB and
  721. // reset any temp entryids we might have put in them
  722. for(n=0;n<dwWABEntryCount;n++)
  723. {
  724. ULONG ulObjType = 0;
  725. if(bShowUI)
  726. SetPrintDialogMsg(0, 0, szEmpty);
  727. if(bTimeToAbort())
  728. {
  729. hr = MAPI_E_USER_CANCEL;
  730. goto exit;
  731. }
  732. if(!lppsbWABEIDs[eidNew][n].cb)
  733. continue;
  734. if(HR_FAILED(hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook, lppsbWABEIDs[eidNew][n].cb,
  735. (LPENTRYID) lppsbWABEIDs[eidNew][n].lpb,
  736. NULL, MAPI_BEST_ACCESS, &ulObjType,
  737. (LPUNKNOWN *)&lpObject)))
  738. {
  739. hrDeferred = hr;
  740. hr = S_OK;
  741. continue;
  742. }
  743. if(ulObjType == MAPI_ABCONT)
  744. goto endloop;
  745. if(HR_FAILED(hr = lpObject->lpVtbl->GetProps(lpObject, NULL, MAPI_UNICODE, &ulcOldProps, &lpOldProps)))
  746. {
  747. hrDeferred = hr;
  748. hr = S_OK;
  749. goto endloop;
  750. }
  751. // open the record and reset any temp eids in it
  752. UpdateEntryIDReferences(ulcOldProps, lpOldProps, dwWABEntryCount, lppsbWABEIDs, TRUE);
  753. // SaveChanges
  754. if(HR_FAILED(hr = lpObject->lpVtbl->SaveChanges(lpObject, KEEP_OPEN_READONLY)))
  755. {
  756. hrDeferred = hr;
  757. hr = S_OK;
  758. }
  759. endloop:
  760. if(lpOldProps)
  761. {
  762. MAPIFreeBuffer(lpOldProps);
  763. ulcOldProps = 0;
  764. lpOldProps = NULL;
  765. }
  766. if(lpObject)
  767. {
  768. lpObject->lpVtbl->Release(lpObject);
  769. lpObject = NULL;
  770. }
  771. } // for n...
  772. hr = S_OK;
  773. exit:
  774. if(lstrlen(szFile))
  775. DeleteFile(szFile);
  776. if(sbPAB.lpb)
  777. MAPIFreeBuffer(sbPAB.lpb);
  778. if(ulcOldProps && lpOldProps)
  779. LocalFreePropArray(NULL, ulcOldProps, &lpOldProps);
  780. if(lpObject)
  781. lpObject->lpVtbl->Release(lpObject);
  782. if(lppsbWABEIDs)
  783. {
  784. for(i=0;i<eidMax;i++)
  785. {
  786. for(j=0;j<dwWABEntryCount;j++)
  787. LocalFreeAndNull((LPVOID *) (&lppsbWABEIDs[i][j].lpb));
  788. LocalFreeAndNull(&lppsbWABEIDs[i]);
  789. }
  790. LocalFree(lppsbWABEIDs);
  791. }
  792. if(hPropertyStore)
  793. ClosePropertyStore(hPropertyStore,AB_DONT_BACKUP | AB_IGNORE_OUTLOOK);
  794. FreeEntryIDs(NULL, ulEIDCount, rgsbEntryIDs);
  795. //if(hOldCur)
  796. // SetCursor(hOldCur);
  797. LocalFreeAndNull(&lpulNewNP);
  798. LocalFreeAndNull(&lpulOldNP);
  799. if(bShowUI)
  800. {
  801. EnableWindow(hWnd, TRUE);
  802. CloseAbortDlg();
  803. if(hr!=MAPI_E_USER_CANCEL)
  804. ShowMessageBox(hWnd, ( HR_FAILED(hr) ? idsImportError :
  805. (HR_FAILED(hrDeferred) ? idsImportCompleteError : idsImportComplete) ),
  806. MB_OK | MB_ICONINFORMATION);
  807. }
  808. if(!hr && HR_FAILED(hrDeferred))
  809. hr = MAPI_W_ERRORS_RETURNED;
  810. if(!HR_FAILED(hr) && bFoldersImported)
  811. HrGetWABProfiles(lpIAB);
  812. return(hr);
  813. }