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.

1955 lines
60 KiB

  1. /*
  2. * Profiles.C - Stuff dealing with WAB Profile Handling
  3. *
  4. */
  5. #include <_apipch.h>
  6. enum {
  7. proDisplayName=0,
  8. proObjectType,
  9. proFolderEntries,
  10. proFolderShared,
  11. proFolderOwner, // upto this many props are common to all folders
  12. proUserSubFolders,
  13. proUserProfileID, // these are used by User Folders only
  14. proUserFolderMax,
  15. };
  16. #define proFolderMax proUserSubFolders
  17. /*
  18. - helper function for quick saving of folder props
  19. -
  20. */
  21. HRESULT HrSaveFolderProps(LPADRBOOK lpAdrBook, BOOL bCreateUserFolder, ULONG ulcProps, LPSPropValue lpProps, LPMAPIPROP * lppObject)
  22. {
  23. HRESULT hr = S_OK;
  24. LPMAPIPROP lpObject = NULL;
  25. ULONG ulFlags = CREATE_CHECK_DUP_STRICT;
  26. BOOL bTryAgain = FALSE;
  27. TryAgain:
  28. // Create a new mailuser for this entry
  29. if(HR_FAILED(hr = HrCreateNewObject(lpAdrBook, NULL, MAPI_MAILUSER, ulFlags, &lpObject)))
  30. goto out;
  31. if(HR_FAILED(hr = lpObject->lpVtbl->SetProps( lpObject, ulcProps, lpProps,NULL)))
  32. goto out;
  33. if(bCreateUserFolder)
  34. {
  35. // if we are creating a user folder, we can't rely on the currently loaded folder-
  36. // container info so we will forcibly reset the parent folder item on the MailUser/Folder
  37. // object we are savign
  38. ((LPMailUser)lpObject)->pmbinOlk = NULL;
  39. }
  40. // SaveChanges
  41. if(HR_FAILED(hr = lpObject->lpVtbl->SaveChanges(lpObject, KEEP_OPEN_READWRITE)))
  42. {
  43. if(!bCreateUserFolder || hr != MAPI_E_COLLISION)
  44. goto out;
  45. // If something already exists with this same exact name, we want to merge with it
  46. // without losing any info on it, since most likely, the original dupe is also a contact
  47. if(!bTryAgain)
  48. {
  49. bTryAgain = TRUE;
  50. ulFlags |= CREATE_REPLACE | CREATE_MERGE;
  51. lpObject->lpVtbl->Release(lpObject);
  52. lpObject = NULL;
  53. lpProps[proFolderEntries].ulPropTag = PR_NULL; // don't overwrite the folder's contents
  54. goto TryAgain;
  55. }
  56. }
  57. if(lppObject)
  58. {
  59. *lppObject = lpObject;
  60. lpObject = NULL;
  61. }
  62. out:
  63. if(lpObject)
  64. lpObject->lpVtbl->Release(lpObject);
  65. return hr;
  66. }
  67. /*
  68. -
  69. - FreeProfileContainerInfo(lpIAB)
  70. *
  71. *
  72. *
  73. */
  74. void FreeProfileContainerInfo(LPIAB lpIAB)
  75. {
  76. if( lpIAB &&
  77. lpIAB->cwabci &&
  78. lpIAB->rgwabci)
  79. {
  80. //ULONG i = 0;
  81. //for(i=0;i<lpIAB->cwabci;i++)
  82. // LocalFreeAndNull(&(lpIAB->rgwabci[i].lpszName));
  83. if( lpIAB->rgwabci[0].lpEntryID &&
  84. !lpIAB->rgwabci[0].lpEntryID->cb &&
  85. !lpIAB->rgwabci[0].lpEntryID->lpb &&
  86. lpIAB->rgwabci[0].lpszName &&
  87. lstrlen(lpIAB->rgwabci[0].lpszName))
  88. {
  89. LocalFree(lpIAB->rgwabci[0].lpEntryID);
  90. LocalFree(lpIAB->rgwabci[0].lpszName);
  91. }
  92. LocalFreeAndNull(&(lpIAB->rgwabci));
  93. lpIAB->cwabci = 0;
  94. }
  95. }
  96. /*
  97. -
  98. - FindWABFolder - Searches the list of cached folders for a specific WAB folder
  99. -
  100. * The search is based on either the EID or the Name or the ProfileID
  101. * If ProfileID is specified, we only search for user folders
  102. *
  103. */
  104. LPWABFOLDER FindWABFolder(LPIAB lpIAB, LPSBinary lpsb, LPTSTR lpName, LPTSTR lpProfileID)
  105. {
  106. LPWABFOLDER lpFolder = lpIAB->lpWABFolders;
  107. BOOL bUserFolders = FALSE;
  108. if(!lpFolder || lpProfileID)
  109. {
  110. lpFolder = lpIAB->lpWABUserFolders;
  111. bUserFolders = TRUE;
  112. }
  113. while(lpFolder)
  114. {
  115. if(lpsb)
  116. {
  117. if( lpsb->cb == lpFolder->sbEID.cb &&
  118. !memcmp(lpsb->lpb, lpFolder->sbEID.lpb, lpsb->cb) )
  119. return lpFolder;
  120. }
  121. else
  122. if(lpName)
  123. {
  124. if(!lstrcmpi(lpFolder->lpFolderName, lpName))
  125. return lpFolder;
  126. }
  127. else
  128. if(lpProfileID)
  129. {
  130. if( lpFolder->lpProfileID &&
  131. !lstrcmpi(lpFolder->lpProfileID, lpProfileID))
  132. return lpFolder;
  133. }
  134. lpFolder = lpFolder->lpNext;
  135. if(!lpFolder && !bUserFolders)
  136. {
  137. lpFolder = lpIAB->lpWABUserFolders;
  138. bUserFolders = TRUE;
  139. }
  140. }
  141. return NULL;
  142. }
  143. /*
  144. -
  145. - HrGetWABProfileContainerInfo
  146. *
  147. * Looks up all the folders for the current user and tabulates
  148. * them into a list of container names and entry ids for easy access
  149. * similar to Outlook ...
  150. * If there is no current user, we'll include all the folders for now
  151. *
  152. */
  153. HRESULT HrGetWABProfileContainerInfo(LPIAB lpIAB)
  154. {
  155. HRESULT hr = E_FAIL;
  156. ULONG j = 0, i = 0, cVal = 0, cUserFolders = 0, cOtherFolders = 0;
  157. LPWABFOLDER lpFolder = NULL;
  158. LPWABFOLDERLIST lpFolderItem = NULL;
  159. if(lpIAB->cwabci)
  160. FreeProfileContainerInfo(lpIAB);
  161. if(!bIsThereACurrentUser(lpIAB))
  162. {
  163. // No specific user specified .. need to add ALL folders
  164. // Count all the folders
  165. lpFolder = lpIAB->lpWABUserFolders;
  166. while(lpFolder)
  167. {
  168. cUserFolders++;
  169. lpFolder = lpFolder->lpNext;
  170. }
  171. lpFolder = lpIAB->lpWABFolders;
  172. while(lpFolder)
  173. {
  174. cOtherFolders++;
  175. lpFolder = lpFolder->lpNext;
  176. }
  177. cVal = cUserFolders + cOtherFolders + 1; // +1 for Virtual PAB
  178. }
  179. else
  180. {
  181. // For a user, we add all the user's folders except shared ones followed by
  182. // all the shared folders...
  183. lpFolderItem = lpIAB->lpWABCurrentUserFolder->lpFolderList;
  184. while(lpFolderItem)
  185. {
  186. if(!lpFolderItem->lpFolder->bShared)
  187. cVal++;
  188. lpFolderItem = lpFolderItem->lpNext;
  189. }
  190. lpFolder = lpIAB->lpWABFolders;
  191. while(lpFolder)
  192. {
  193. if(lpFolder->bShared)
  194. cVal++;
  195. lpFolder = lpFolder->lpNext;
  196. }
  197. cVal++; // add 1 for the user folder itself
  198. cVal++; // add 1 for a virtual root item for this user TEXT("All Contacts")
  199. }
  200. if(cVal)
  201. {
  202. if(!(lpIAB->rgwabci = LocalAlloc(LMEM_ZEROINIT, sizeof(struct _OlkContInfo)*cVal)))
  203. {
  204. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  205. goto out;
  206. }
  207. cUserFolders = 0;
  208. // Add the TEXT("All Contacts") item to the root - entryid is 0, NULL
  209. {
  210. TCHAR sz[MAX_PATH];
  211. ULONG cchSize;
  212. int nID = (bDoesThisWABHaveAnyUsers(lpIAB)) ? idsSharedContacts : idsContacts;
  213. LoadString(hinstMapiX, nID, sz, CharSizeOf(sz));
  214. cchSize = lstrlen(sz)+1;
  215. if(!(lpIAB->rgwabci[cUserFolders].lpszName = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize)))
  216. {
  217. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  218. goto out;
  219. }
  220. StrCpyN(lpIAB->rgwabci[cUserFolders].lpszName, sz, cchSize);
  221. lpIAB->rgwabci[cUserFolders].lpEntryID = LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
  222. cUserFolders++;
  223. }
  224. if(!lpIAB->lpWABCurrentUserFolder)
  225. {
  226. lpFolder = lpIAB->lpWABUserFolders;
  227. while(lpFolder)
  228. {
  229. lpIAB->rgwabci[cUserFolders].lpEntryID = &(lpFolder->sbEID);
  230. lpIAB->rgwabci[cUserFolders].lpszName = lpFolder->lpFolderName;
  231. cUserFolders++;
  232. lpFolder = lpFolder->lpNext;
  233. }
  234. lpFolder = lpIAB->lpWABFolders;
  235. while(lpFolder)
  236. {
  237. lpIAB->rgwabci[cUserFolders].lpEntryID = &(lpFolder->sbEID);
  238. lpIAB->rgwabci[cUserFolders].lpszName = lpFolder->lpFolderName;
  239. cUserFolders++;
  240. lpFolder = lpFolder->lpNext;
  241. }
  242. }
  243. else
  244. {
  245. // Add the first folder and then find the other folders one by one
  246. lpIAB->rgwabci[cUserFolders].lpEntryID = &(lpIAB->lpWABCurrentUserFolder->sbEID);
  247. lpIAB->rgwabci[cUserFolders].lpszName = lpIAB->lpWABCurrentUserFolder->lpFolderName;
  248. cUserFolders++;
  249. lpFolderItem = lpIAB->lpWABCurrentUserFolder->lpFolderList;
  250. while(lpFolderItem)
  251. {
  252. if(!lpFolderItem->lpFolder->bShared)
  253. {
  254. lpIAB->rgwabci[cUserFolders].lpEntryID = &(lpFolderItem->lpFolder->sbEID);
  255. lpIAB->rgwabci[cUserFolders].lpszName = lpFolderItem->lpFolder->lpFolderName;
  256. cUserFolders++;
  257. }
  258. lpFolderItem = lpFolderItem->lpNext;
  259. }
  260. lpFolder = lpIAB->lpWABFolders;
  261. while(lpFolder)
  262. {
  263. if(lpFolder->bShared)
  264. {
  265. lpIAB->rgwabci[cUserFolders].lpEntryID = &(lpFolder->sbEID);
  266. lpIAB->rgwabci[cUserFolders].lpszName = lpFolder->lpFolderName;
  267. cUserFolders++;
  268. }
  269. lpFolder = lpFolder->lpNext;
  270. }
  271. }
  272. lpIAB->cwabci = cUserFolders;
  273. }
  274. hr = S_OK;
  275. out:
  276. if(HR_FAILED(hr) && lpIAB->rgwabci)
  277. FreeProfileContainerInfo(lpIAB);
  278. return hr;
  279. }
  280. /*
  281. - FreeWABFoldersList
  282. -
  283. -
  284. * Clears up existing Profile Folders info from the IAB object
  285. */
  286. void FreeFolderItem(LPWABFOLDER lpFolder)
  287. {
  288. LPWABFOLDERLIST lpFolderItem = NULL;
  289. if(!lpFolder)
  290. return;
  291. LocalFreeAndNull(&lpFolder->lpFolderName);
  292. LocalFreeAndNull(&lpFolder->lpProfileID);
  293. LocalFreeAndNull((LPVOID *) (&lpFolder->sbEID.lpb));
  294. LocalFreeAndNull(&lpFolder->lpFolderOwner);
  295. lpFolderItem = lpFolder->lpFolderList;
  296. while(lpFolderItem)
  297. {
  298. lpFolder->lpFolderList = lpFolderItem->lpNext;
  299. LocalFree(lpFolderItem);
  300. lpFolderItem = lpFolder->lpFolderList;
  301. }
  302. LocalFree(lpFolder);
  303. }
  304. void FreeWABFoldersList(LPIAB lpIAB)
  305. {
  306. LPWABFOLDER lpFolder = lpIAB->lpWABFolders;
  307. while(lpFolder)
  308. {
  309. lpIAB->lpWABFolders = lpFolder->lpNext;
  310. FreeFolderItem(lpFolder);
  311. lpFolder = lpIAB->lpWABFolders;
  312. }
  313. lpFolder = lpIAB->lpWABUserFolders;
  314. while(lpFolder)
  315. {
  316. lpIAB->lpWABFolders = lpFolder->lpNext;
  317. FreeFolderItem(lpFolder);
  318. lpFolder = lpIAB->lpWABFolders;
  319. }
  320. lpIAB->lpWABUserFolders = NULL;
  321. lpIAB->lpWABCurrentUserFolder = NULL;
  322. lpIAB->lpWABFolders = NULL;
  323. }
  324. /*
  325. - SetCurrentUserFolder - scans list and updates pointer
  326. -
  327. *
  328. */
  329. void SetCurrentUserFolder(LPIAB lpIAB, LPTSTR lpszProfileID)
  330. {
  331. LPWABUSERFOLDER lpFolder = lpIAB->lpWABUserFolders;
  332. while(lpFolder && lpszProfileID && lstrlen(lpszProfileID))
  333. {
  334. if(!lstrcmpi(lpFolder->lpProfileID, lpszProfileID))
  335. {
  336. lpIAB->lpWABCurrentUserFolder = lpFolder;
  337. break;
  338. }
  339. lpFolder = lpFolder->lpNext;
  340. }
  341. }
  342. /*
  343. -
  344. - CreateUserFolderName
  345. *
  346. */
  347. void CreateUserFolderName(LPTSTR lpProfile, LPTSTR * lppszName)
  348. {
  349. LPTSTR lpName = NULL;
  350. TCHAR sz[MAX_PATH];
  351. LoadString(hinstMapiX, idsUsersContacts, sz, CharSizeOf(sz));
  352. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  353. sz, 0, 0, (LPTSTR)&lpName, 0, (va_list *)&lpProfile);
  354. *lppszName = lpName;
  355. }
  356. /*
  357. - HrLinkOrphanFoldersToDefaultUser(lpIAB)
  358. -
  359. * If there are any folders that are associated with deleted users or that have
  360. * no parent and are orphaned, we want to associate them with the default user
  361. *
  362. * This function is dependent on lpFolder->bOwned being correctly set in the
  363. * HrLinkUserFoldersToWABFolders
  364. *
  365. */
  366. HRESULT HrLinkOrphanFoldersToDefaultUser(LPIAB lpIAB)
  367. {
  368. HRESULT hr = S_OK;
  369. LPWABUSERFOLDER lpDefUser = NULL;
  370. LPWABFOLDER lpFolder = NULL;
  371. TCHAR szDefProfile[MAX_PATH + 1];
  372. // First detect the user folder corresponding to the Default User
  373. *szDefProfile = '\0';
  374. if( HR_FAILED(hr = HrGetDefaultIdentityInfo(lpIAB, DEFAULT_ID_PROFILEID, NULL, szDefProfile, ARRAYSIZE(szDefProfile), NULL, 0)))
  375. {
  376. if(hr == 0x80040154) // E_CLASS_NOT_REGISTERD means no IDentity Manager
  377. hr = S_OK;
  378. else
  379. goto out;
  380. }
  381. if(lstrlen(szDefProfile))
  382. {
  383. lpDefUser = FindWABFolder(lpIAB, NULL, NULL, szDefProfile);
  384. }
  385. else
  386. {
  387. // can't find the default user so just fall back to picking someone at random
  388. lpDefUser = lpIAB->lpWABUserFolders;
  389. }
  390. // see if there are any orphan folders
  391. // To qualify as an orphan, the lpFolder->bOwned should be FALSE and the folder must
  392. // also not be shared because if it's shared it will show up as part of Shared Contacts
  393. lpFolder = lpIAB->lpWABFolders;
  394. while(lpFolder)
  395. {
  396. if(!lpFolder->bOwned && !lpFolder->bShared)
  397. {
  398. LPWABUSERFOLDER lpOwnerFolder = lpDefUser;
  399. if(lpFolder->lpFolderOwner)
  400. {
  401. // Someone created this folder .. we need to make sure this is associated back to that original
  402. // creator and only if that doesn't work should we append it to the default user
  403. if(!(lpOwnerFolder = FindWABFolder(lpIAB, NULL, NULL, lpFolder->lpFolderOwner)))
  404. lpOwnerFolder = lpDefUser;
  405. }
  406. if(lpOwnerFolder)
  407. {
  408. if(HR_FAILED(hr = HrAddRemoveFolderFromUserFolder( lpIAB, lpDefUser,
  409. &lpFolder->sbEID, NULL, FALSE ) ))
  410. goto out;
  411. }
  412. }
  413. lpFolder = lpFolder->lpNext;
  414. }
  415. out:
  416. return hr;
  417. }
  418. /*
  419. - HrLinkUserFoldersToWABFolders
  420. -
  421. *
  422. * Cross-links the user folder contents with the regular folders
  423. * This makes accessing folder info much easier ..
  424. */
  425. HRESULT HrLinkUserFoldersToWABFolders(LPIAB lpIAB)
  426. {
  427. HRESULT hr = S_OK;
  428. LPWABUSERFOLDER lpUserFolder = NULL;
  429. LPWABFOLDER lpFolder = NULL;
  430. ULONG ulcPropCount = 0, i = 0, j = 0;
  431. LPSPropValue lpProp = NULL;
  432. if(!lpIAB->lpWABUserFolders || !lpIAB->lpWABFolders)
  433. goto out;
  434. lpUserFolder = lpIAB->lpWABUserFolders;
  435. while(lpUserFolder)
  436. {
  437. if(HR_FAILED(hr = ReadRecord(lpIAB->lpPropertyStore->hPropertyStore, &lpUserFolder->sbEID,
  438. 0, &ulcPropCount, &lpProp)))
  439. goto out;
  440. for(i=0;i<ulcPropCount;i++)
  441. {
  442. if(lpProp[i].ulPropTag == PR_WAB_USER_SUBFOLDERS)
  443. {
  444. for(j=0;j<lpProp[i].Value.MVbin.cValues;j++)
  445. {
  446. lpFolder = FindWABFolder(lpIAB, &(lpProp[i].Value.MVbin.lpbin[j]), NULL, NULL);
  447. if(lpFolder)
  448. {
  449. LPWABFOLDERLIST lpFolderItem = LocalAlloc(LMEM_ZEROINIT, sizeof(WABFOLDERLIST));
  450. if(lpFolderItem)
  451. {
  452. lpFolderItem->lpFolder = lpFolder;
  453. lpFolder->bOwned = TRUE;
  454. lpFolderItem->lpNext = lpUserFolder->lpFolderList;
  455. lpUserFolder->lpFolderList = lpFolderItem;
  456. }
  457. }
  458. }
  459. break;
  460. }
  461. }
  462. ReadRecordFreePropArray(NULL, ulcPropCount, &lpProp);
  463. ulcPropCount = 0;
  464. lpProp = NULL;
  465. lpUserFolder = lpUserFolder->lpNext;
  466. }
  467. out:
  468. ReadRecordFreePropArray(NULL, ulcPropCount, &lpProp);
  469. return hr;
  470. }
  471. /*
  472. - HrGetFolderInfo()
  473. -
  474. * Reads a folder name directly from the prop store
  475. * Also checks if this is a user folder and what the profile is
  476. * Returns LocalAlloced LPTSTRs which caller needs to free
  477. */
  478. HRESULT HrGetFolderInfo(LPIAB lpIAB, LPSBinary lpsbEID, LPWABFOLDER lpFolder)
  479. {
  480. LPTSTR lpName = NULL, lpProfileID = NULL, lpOwner = NULL;
  481. HRESULT hr = S_OK;
  482. ULONG ulcPropCount = 0, j=0;
  483. LPSPropValue lpProp = NULL;
  484. BOOL bShared = FALSE;
  485. if(!bIsWABSessionProfileAware(lpIAB) || !lpsbEID)
  486. goto out;
  487. if(!lpsbEID->cb && !lpsbEID->lpb)
  488. {
  489. // special case - read the address book item
  490. lpName = LocalAlloc(LMEM_ZEROINIT, MAX_PATH);
  491. if(lpName)
  492. LoadString(hinstMapiX, idsContacts/*IDS_ADDRBK_CAPTION*/, lpName, MAX_PATH-1);
  493. }
  494. else
  495. {
  496. hr = ReadRecord(lpIAB->lpPropertyStore->hPropertyStore, lpsbEID,
  497. 0, &ulcPropCount, &lpProp);
  498. if(HR_FAILED(hr))
  499. goto out;
  500. for(j=0;j<ulcPropCount;j++)
  501. {
  502. ULONG cchSize;
  503. if(lpProp[j].ulPropTag == PR_DISPLAY_NAME)
  504. {
  505. cchSize = lstrlen(lpProp[j].Value.LPSZ)+1;
  506. if(lpName = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize))
  507. StrCpyN(lpName, lpProp[j].Value.LPSZ, cchSize);
  508. else
  509. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  510. }
  511. if(lpProp[j].ulPropTag == PR_WAB_USER_PROFILEID)
  512. {
  513. cchSize = lstrlen(lpProp[j].Value.LPSZ)+1;
  514. if(lpProfileID = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize))
  515. StrCpyN(lpProfileID, lpProp[j].Value.LPSZ, cchSize);
  516. else
  517. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  518. }
  519. if(lpProp[j].ulPropTag == PR_WAB_FOLDEROWNER)
  520. {
  521. TCHAR szName[CCH_IDENTITY_NAME_MAX_LENGTH];
  522. *szName = '\0';
  523. if( !HR_FAILED(HrGetIdentityName(lpIAB, lpProp[j].Value.LPSZ, szName, ARRAYSIZE(szName))) &&
  524. lstrlen(szName))
  525. {
  526. cchSize = lstrlen(szName)+1;
  527. if(lpOwner = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize))
  528. StrCpyN(lpOwner, szName, cchSize);
  529. else
  530. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  531. }
  532. }
  533. if(lpProp[j].ulPropTag == PR_WAB_SHAREDFOLDER)
  534. {
  535. bShared = (lpProp[j].Value.l==FOLDER_SHARED?TRUE:FALSE);
  536. }
  537. }
  538. // ideally, we should be reading in a new name for all user folders at this point
  539. //if(lpProfileID && lstrlen(lpProfileID))
  540. //{
  541. // if(lpName)
  542. // LocalFree(lpName);
  543. // CreateUserFolderName(lpProfileID, &lpName);
  544. //}
  545. }
  546. lpFolder->lpFolderName = lpName;
  547. lpFolder->lpProfileID = lpProfileID;
  548. lpFolder->bShared = bShared;
  549. lpFolder->lpFolderOwner = lpOwner;
  550. out:
  551. ReadRecordFreePropArray(NULL, ulcPropCount, &lpProp);
  552. return hr;
  553. }
  554. /*
  555. - HrLoadWABFolders
  556. -
  557. * Gets a list of all the folders from the WAB and sorts them out based on
  558. * whether they are user folders or ordinary folders
  559. *
  560. */
  561. HRESULT HrLoadWABFolders(LPIAB lpIAB)
  562. {
  563. SCODE sc;
  564. HRESULT hr = E_FAIL;
  565. SPropertyRestriction PropRes = {0};
  566. SPropValue sp = {0};
  567. ULONG ulCount = 0;
  568. LPSBinary rgsbEntryIDs = NULL;
  569. ULONG i = 0;
  570. int nID = IDM_VIEW_FOLDERS1;
  571. // Now we will search the WAB for all objects of PR_OBJECT_TYPE = MAPI_ABCONT
  572. //
  573. sp.ulPropTag = PR_OBJECT_TYPE;
  574. sp.Value.l = MAPI_ABCONT;
  575. PropRes.ulPropTag = PR_OBJECT_TYPE;
  576. PropRes.relop = RELOP_EQ;
  577. PropRes.lpProp = &sp;
  578. hr = FindRecords( lpIAB->lpPropertyStore->hPropertyStore,
  579. NULL, 0, TRUE,
  580. &PropRes, &ulCount, &rgsbEntryIDs);
  581. if (HR_FAILED(hr))
  582. goto out;
  583. if(ulCount && rgsbEntryIDs)
  584. {
  585. for(i=0;i<ulCount;i++)
  586. {
  587. ULONG cb = 0;
  588. LPENTRYID lpb = NULL;
  589. LPWABFOLDER lpFolder = NULL;
  590. lpFolder = LocalAlloc(LMEM_ZEROINIT, sizeof(WABFOLDER));
  591. if(!lpFolder)
  592. goto out;
  593. if(HR_FAILED(HrGetFolderInfo(lpIAB, &rgsbEntryIDs[i], lpFolder)))
  594. goto out;
  595. if(!HR_FAILED(CreateWABEntryID( WAB_CONTAINER,
  596. rgsbEntryIDs[i].lpb, NULL, NULL,
  597. rgsbEntryIDs[i].cb, 0,
  598. NULL, &cb, &lpb)))
  599. {
  600. // Add the entryids to this prop - ignore errors
  601. SetSBinary(&(lpFolder->sbEID), cb, (LPBYTE)lpb);
  602. MAPIFreeBuffer(lpb);
  603. }
  604. if(lpFolder->lpProfileID)
  605. {
  606. // this is a user folder
  607. lpFolder->lpNext = lpIAB->lpWABUserFolders;
  608. lpIAB->lpWABUserFolders = lpFolder;
  609. }
  610. else
  611. {
  612. lpFolder->lpNext = lpIAB->lpWABFolders;
  613. lpFolder->nMenuCmdID = nID++;
  614. lpIAB->lpWABFolders = lpFolder;
  615. }
  616. }
  617. }
  618. if(HR_FAILED(hr = HrLinkUserFoldersToWABFolders(lpIAB)))
  619. goto out;
  620. HrLinkOrphanFoldersToDefaultUser(lpIAB); // we can ignore errors in this call since it's not life-and-death
  621. out:
  622. if(ulCount && rgsbEntryIDs)
  623. {
  624. FreeEntryIDs(lpIAB->lpPropertyStore->hPropertyStore,
  625. ulCount,
  626. rgsbEntryIDs);
  627. }
  628. return hr;
  629. }
  630. /*
  631. -
  632. - HrCreateNewFolder
  633. *
  634. * Takes a profile ID, uses it to create a folder in the WAB
  635. * and sticks the new user folder onto the IAB
  636. * Can create a user folder or an ordinary folder
  637. * For ordinary folders, we can also specify a parent folder to which the item can be added
  638. *
  639. */
  640. HRESULT HrCreateNewFolder(LPIAB lpIAB, LPTSTR lpName, LPTSTR lpProfileID, BOOL bUserFolder,
  641. LPWABFOLDER lpParentFolder, BOOL bShared, LPSBinary lpsbNew)
  642. {
  643. HRESULT hr = S_OK;
  644. SPropValue spv[proUserFolderMax];
  645. LPSBinary lpsb = NULL;
  646. SBinary sb = {0};
  647. LPMAPIPROP lpObject = NULL;
  648. ULONG ulcProps = 0, j = 0;
  649. LPSPropValue lpProps = NULL;
  650. LPWABFOLDER lpFolder = NULL;
  651. ULONG ulPropCount = 0;
  652. ULONG cchSize;
  653. if(!(lpFolder = LocalAlloc(LMEM_ZEROINIT, sizeof(WABFOLDER))))
  654. return MAPI_E_NOT_ENOUGH_MEMORY;
  655. if(bUserFolder)
  656. {
  657. CreateUserFolderName(lpName ? lpName : lpProfileID, &lpFolder->lpFolderName);
  658. cchSize = lstrlen(lpProfileID)+1;
  659. if(!(lpFolder->lpProfileID = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize)))
  660. return MAPI_E_NOT_ENOUGH_MEMORY;
  661. StrCpyN(lpFolder->lpProfileID, lpProfileID, cchSize);
  662. }
  663. else
  664. {
  665. cchSize = lstrlen(lpName)+1;
  666. if(!(lpFolder->lpFolderName = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize)))
  667. return MAPI_E_NOT_ENOUGH_MEMORY;
  668. StrCpyN(lpFolder->lpFolderName, lpName, cchSize);
  669. }
  670. // if there isn't a current user, all new folders should go into the shared contacts folder
  671. if(!bIsThereACurrentUser(lpIAB) && !lpProfileID && !lpParentFolder)
  672. bShared = TRUE;
  673. spv[ulPropCount].ulPropTag = PR_DISPLAY_NAME;
  674. spv[ulPropCount++].Value.LPSZ = lpFolder->lpFolderName;
  675. spv[ulPropCount].ulPropTag = PR_OBJECT_TYPE;
  676. spv[ulPropCount++].Value.l = MAPI_ABCONT;
  677. spv[ulPropCount].ulPropTag = PR_WAB_FOLDER_ENTRIES;
  678. spv[ulPropCount].Value.MVbin.cValues = 1;
  679. spv[ulPropCount++].Value.MVbin.lpbin = &sb;
  680. spv[ulPropCount].ulPropTag = PR_WAB_SHAREDFOLDER;
  681. spv[ulPropCount++].Value.l = (bUserFolder ? FOLDER_PRIVATE : (bShared ? FOLDER_SHARED : FOLDER_PRIVATE));
  682. if(lpProfileID)
  683. {
  684. spv[ulPropCount].ulPropTag = PR_WAB_FOLDEROWNER;
  685. spv[ulPropCount++].Value.LPSZ = lpProfileID;
  686. }
  687. if(bUserFolder)
  688. {
  689. spv[ulPropCount].ulPropTag = PR_WAB_USER_SUBFOLDERS;
  690. spv[ulPropCount].Value.MVbin.cValues = 1;
  691. spv[ulPropCount++].Value.MVbin.lpbin = &sb;
  692. spv[ulPropCount].ulPropTag = PR_WAB_USER_PROFILEID;
  693. spv[ulPropCount++].Value.LPSZ = lpFolder->lpProfileID;
  694. }
  695. if(HR_FAILED(hr = HrSaveFolderProps((LPADRBOOK)lpIAB, bUserFolder,
  696. ulPropCount,
  697. spv, &lpObject)))
  698. goto out;
  699. if(HR_FAILED(hr = lpObject->lpVtbl->GetProps(lpObject, NULL, MAPI_UNICODE, &ulcProps, &lpProps)))
  700. goto out;
  701. for(j=0;j<ulcProps;j++)
  702. {
  703. if(lpProps[j].ulPropTag == PR_ENTRYID)
  704. {
  705. lpsb = &(lpProps[j].Value.bin);
  706. break;
  707. }
  708. }
  709. if(lpsb)
  710. {
  711. ULONG cb = 0;
  712. LPENTRYID lpb = NULL;
  713. if(!HR_FAILED(CreateWABEntryID( WAB_CONTAINER,
  714. lpsb->lpb, NULL, NULL,
  715. lpsb->cb, 0,
  716. NULL, &cb, &lpb)))
  717. {
  718. // Add the entryids to this prop - ignore errors
  719. SetSBinary(&(lpFolder->sbEID), cb, (LPBYTE) lpb);
  720. MAPIFreeBuffer(lpb);
  721. }
  722. }
  723. if(bUserFolder)
  724. {
  725. lpFolder->lpNext = lpIAB->lpWABUserFolders;
  726. lpIAB->lpWABUserFolders = lpFolder;
  727. }
  728. else
  729. {
  730. lpFolder->lpNext = lpIAB->lpWABFolders;
  731. lpIAB->lpWABFolders = lpFolder;
  732. // Add this folder to the current user's profile
  733. HrAddRemoveFolderFromUserFolder(lpIAB, lpParentFolder, &(lpFolder->sbEID), NULL, FALSE);
  734. }
  735. if(lpsbNew)
  736. SetSBinary(lpsbNew, lpFolder->sbEID.cb, lpFolder->sbEID.lpb);
  737. hr = HrGetWABProfiles(lpIAB);
  738. out:
  739. if(lpObject)
  740. lpObject->lpVtbl->Release(lpObject);
  741. FreeBufferAndNull(&lpProps);
  742. return hr;
  743. }
  744. /*
  745. - HrAddAllContactsToFolder
  746. -
  747. * Adds all existing contacts and groups to the current user folder
  748. *
  749. */
  750. HRESULT HrAddAllContactsToFolder(LPIAB lpIAB)
  751. {
  752. HRESULT hr = 0;
  753. SPropertyRestriction PropRes;
  754. LPSBinary rgsbEntryIDs = NULL;
  755. ULONG ulCount = 0, i,j;
  756. ULONG rgObj[] = {MAPI_MAILUSER, MAPI_DISTLIST};
  757. // This can be a labor intesive process
  758. HCURSOR hOldC = NULL;
  759. if(!bIsThereACurrentUser(lpIAB))
  760. return hr;
  761. hOldC = SetCursor(LoadCursor(NULL, IDC_WAIT));
  762. //for(j=0;j<2;j++)
  763. {
  764. SPropValue sp = {0};
  765. sp.ulPropTag = PR_WAB_FOLDER_PARENT;
  766. //sp.Value.l = rgObj[j];
  767. PropRes.ulPropTag = PR_WAB_FOLDER_PARENT;
  768. PropRes.relop = RELOP_NE;
  769. PropRes.lpProp = &sp;
  770. // Find stuff that isn't in any folder
  771. if(!HR_FAILED(hr = FindRecords( lpIAB->lpPropertyStore->hPropertyStore,
  772. NULL, AB_MATCH_PROP_ONLY, TRUE, &PropRes, &ulCount, &rgsbEntryIDs)))
  773. {
  774. for(i=0;i<ulCount;i++)
  775. {
  776. AddEntryToFolder((LPADRBOOK)lpIAB,NULL,
  777. lpIAB->lpWABCurrentUserFolder->sbEID.cb,
  778. (LPENTRYID) lpIAB->lpWABCurrentUserFolder->sbEID.lpb,
  779. rgsbEntryIDs[i].cb,
  780. (LPENTRYID) rgsbEntryIDs[i].lpb);
  781. }
  782. FreeEntryIDs(lpIAB->lpPropertyStore->hPropertyStore, ulCount, rgsbEntryIDs);
  783. }
  784. }
  785. if(hOldC)
  786. SetCursor(hOldC);
  787. return hr;
  788. }
  789. /*
  790. - UpdateCurrentUserFolderName
  791. -
  792. *
  793. */
  794. void UpdateCurrentUserFolderName(LPIAB lpIAB)
  795. {
  796. LPTSTR lpsz = NULL;
  797. CreateUserFolderName(lpIAB->szProfileName, &lpsz);
  798. if(lstrcmpi(lpsz, lpIAB->lpWABCurrentUserFolder->lpFolderName))
  799. {
  800. LocalFree(lpIAB->lpWABCurrentUserFolder->lpFolderName);
  801. lpIAB->lpWABCurrentUserFolder->lpFolderName = lpsz;
  802. HrUpdateFolderInfo(lpIAB, &lpIAB->lpWABCurrentUserFolder->sbEID, FOLDER_UPDATE_NAME, FALSE, lpIAB->lpWABCurrentUserFolder->lpFolderName);
  803. }
  804. else
  805. LocalFree(lpsz);
  806. }
  807. /*
  808. - HrGetWABProfiles
  809. -
  810. * Collates information about the WAB User Folders etc from the WAB
  811. * Creates a list of User Folders and generic Folders and caches these on the Address Book
  812. * Matches the provided profile to the user folders .. if it matches, points to the
  813. * corresponding folder .. if it doesn't match, creates a new User Folder for the
  814. * Profile ID.
  815. *
  816. * <TBD> when the account manager is profile ready, use the profile ID to pull in the
  817. * users name from the account manager and then use that to call it TEXT("UserName's Contacts")
  818. * For now, we'll just use the profile id to do that
  819. */
  820. HRESULT HrGetWABProfiles(LPIAB lpIAB)
  821. {
  822. HRESULT hr = E_FAIL;
  823. EnterCriticalSection(&lpIAB->cs);
  824. if(!bIsWABSessionProfileAware(lpIAB))
  825. goto out;
  826. if(!lstrlen(lpIAB->szProfileID))
  827. HrGetUserProfileID(&lpIAB->guidCurrentUser, lpIAB->szProfileID, CharSizeOf(lpIAB->szProfileID));
  828. if(!lstrlen(lpIAB->szProfileName))
  829. HrGetIdentityName(lpIAB, NULL, lpIAB->szProfileName, ARRAYSIZE(lpIAB->szProfileName));
  830. // Clear out old data
  831. if(lpIAB->lpWABUserFolders || lpIAB->lpWABFolders)
  832. FreeWABFoldersList(lpIAB);
  833. // Get a list of all the folders in the WAB
  834. if(HR_FAILED(hr = HrLoadWABFolders(lpIAB)))
  835. goto out;
  836. SetCurrentUserFolder(lpIAB, lpIAB->szProfileID);
  837. if(!bIsThereACurrentUser(lpIAB) && lstrlen(lpIAB->szProfileID) && lstrlen(lpIAB->szProfileName))
  838. {
  839. // Not Found!!!
  840. // Create a new user folder ..
  841. BOOL bFirstUser = bDoesThisWABHaveAnyUsers(lpIAB) ? FALSE : TRUE;
  842. if(HR_FAILED(hr = HrCreateNewFolder(lpIAB, lpIAB->szProfileName, lpIAB->szProfileID, TRUE, NULL, FALSE, NULL)))
  843. goto out;
  844. SetCurrentUserFolder(lpIAB, lpIAB->szProfileID);
  845. if(bFirstUser)
  846. {
  847. if(lpIAB->lpWABFolders)
  848. {
  849. // we want to put all existing folders under this user
  850. LPWABFOLDER lpFolder = lpIAB->lpWABFolders;
  851. while(lpFolder)
  852. {
  853. // There is a weird case where a preexisting folder with the same name as
  854. // a user's folder becomes nested under itself .. so don't add this folder to the
  855. // User Folder
  856. if(lstrcmpi(lpIAB->lpWABCurrentUserFolder->lpFolderName, lpFolder->lpFolderName))
  857. HrAddRemoveFolderFromUserFolder(lpIAB, NULL, &lpFolder->sbEID, NULL, FALSE);
  858. lpFolder = lpFolder->lpNext;
  859. }
  860. hr = HrLinkUserFoldersToWABFolders(lpIAB);
  861. }
  862. //We also want to put all existing contacts into this user folder
  863. hr = HrAddAllContactsToFolder(lpIAB);
  864. }
  865. }
  866. if( lpIAB->szProfileID && lstrlen(lpIAB->szProfileID) && lpIAB->szProfileName && lstrlen(lpIAB->szProfileName) && bIsThereACurrentUser(lpIAB))
  867. {
  868. // Use the latest name for this entry
  869. UpdateCurrentUserFolderName(lpIAB);
  870. }
  871. if(HR_FAILED(hr = HrGetWABProfileContainerInfo(lpIAB)))
  872. goto out;
  873. hr = S_OK;
  874. out:
  875. LeaveCriticalSection(&lpIAB->cs);
  876. return hr;
  877. }
  878. /*
  879. - bIsProfileMember
  880. -
  881. *
  882. */
  883. BOOL bIsProfileMember(LPIAB lpIAB, LPSBinary lpsb, LPWABFOLDER lpWABFolder, LPWABUSERFOLDER lpUserFolder)
  884. {
  885. LPWABFOLDERLIST lpFolderItem = NULL;
  886. LPWABFOLDER lpFolder = lpWABFolder;
  887. if(!lpUserFolder && !lpIAB->lpWABCurrentUserFolder)
  888. return FALSE;
  889. lpFolderItem = lpUserFolder ? lpUserFolder->lpFolderList : lpIAB->lpWABCurrentUserFolder->lpFolderList;
  890. if(!lpFolder && lpsb)
  891. lpFolder = FindWABFolder(lpIAB, lpsb, NULL, NULL);
  892. while(lpFolderItem && lpFolder)
  893. {
  894. if(lpFolderItem->lpFolder == lpFolder)
  895. return TRUE;
  896. lpFolderItem = lpFolderItem->lpNext;
  897. }
  898. return FALSE;
  899. }
  900. /*
  901. - bDoesEntryNameAlreadyExist
  902. -
  903. * Checks if a given name already exists in the WAB
  904. * Used for preventing duplicate folder and group names
  905. */
  906. BOOL bDoesEntryNameAlreadyExist(LPIAB lpIAB, LPTSTR lpsz)
  907. {
  908. SPropertyRestriction PropRes;
  909. SPropValue Prop = {0};
  910. LPSBinary rgsbEntryIDs = NULL;
  911. ULONG ulCount = 0;
  912. BOOL bRet = FALSE;
  913. // Verify that the new name doesn't actually exist
  914. Prop.ulPropTag = PR_DISPLAY_NAME;
  915. Prop.Value.LPSZ = lpsz;
  916. PropRes.lpProp = &Prop;
  917. PropRes.relop = RELOP_EQ;
  918. PropRes.ulPropTag = PR_DISPLAY_NAME;
  919. if (HR_FAILED(FindRecords(lpIAB->lpPropertyStore->hPropertyStore,
  920. NULL, // pmbinFolder
  921. 0, // ulFlags
  922. TRUE, // Always TRUE
  923. &PropRes, // Propertyrestriction
  924. &ulCount, // IN: number of matches to find, OUT: number found
  925. &rgsbEntryIDs)))
  926. goto out;
  927. FreeEntryIDs(lpIAB->lpPropertyStore->hPropertyStore, ulCount, rgsbEntryIDs);
  928. if(ulCount >=1)
  929. bRet = TRUE;
  930. out:
  931. return bRet;
  932. }
  933. /*
  934. - UpdateFolderName
  935. -
  936. *
  937. */
  938. HRESULT HrUpdateFolderInfo(LPIAB lpIAB, LPSBinary lpsbEID, ULONG ulFlags, BOOL bShared, LPTSTR lpsz)
  939. {
  940. LPSPropValue lpProp = NULL, lpPropNew = NULL;
  941. ULONG ulcPropCount = 0, i =0, ulcPropNew = 0;
  942. HRESULT hr = S_OK;
  943. BOOL bUpdate = FALSE, bFoundShare = FALSE;//, bOldShareState = FALSE;
  944. ULONG cchSize;
  945. if(!lpsbEID || !lpsbEID->cb || !lpsbEID->lpb)
  946. return MAPI_E_INVALID_PARAMETER;
  947. if(!HR_FAILED(hr = ReadRecord( lpIAB->lpPropertyStore->hPropertyStore,
  948. lpsbEID, 0, &ulcPropCount, &lpProp)))
  949. {
  950. for(i=0;i<ulcPropCount;i++)
  951. {
  952. if( (ulFlags & FOLDER_UPDATE_NAME) &&
  953. lpProp[i].ulPropTag == PR_DISPLAY_NAME)
  954. {
  955. BOOL bCaseChangeOnly = (!lstrcmpi(lpsz, lpProp[i].Value.LPSZ) &&
  956. lstrcmp(lpsz, lpProp[i].Value.LPSZ) );
  957. LocalFree(lpProp[i].Value.LPSZ);
  958. cchSize = lstrlen(lpsz)+1;
  959. lpProp[i].Value.LPSZ = LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)*cchSize);
  960. if(lpProp[i].Value.LPSZ)
  961. {
  962. StrCpyN(lpProp[i].Value.LPSZ, lpsz, cchSize);
  963. if(!bCaseChangeOnly) // if this isn't just a case change, look for the name (if it's a case change, there will be a spurious error) //bug 33067
  964. {
  965. if(bDoesEntryNameAlreadyExist(lpIAB, lpProp[i].Value.LPSZ))
  966. {
  967. hr = MAPI_E_COLLISION;
  968. goto out;
  969. }
  970. }
  971. bUpdate = TRUE;
  972. }
  973. }
  974. if( (ulFlags & FOLDER_UPDATE_SHARE) &&
  975. lpProp[i].ulPropTag == PR_WAB_SHAREDFOLDER)
  976. {
  977. bFoundShare = TRUE;
  978. //bOldShareState = (lpProp[i].Value.l == FOLDER_SHARED) ? TRUE : FALSE;
  979. lpProp[i].Value.l = bShared ? FOLDER_SHARED : FOLDER_PRIVATE;
  980. bUpdate = TRUE;
  981. }
  982. }
  983. }
  984. if(!bFoundShare && (ulFlags & FOLDER_UPDATE_SHARE)) // this value doesnt already exist on the contact so update it
  985. {
  986. SPropValue Prop = {0};
  987. Prop.ulPropTag = PR_WAB_SHAREDFOLDER;
  988. Prop.Value.l = bShared ? FOLDER_SHARED : FOLDER_PRIVATE;
  989. // Create a new prop array with this additional property
  990. if(!(ScMergePropValues( 1, &Prop, ulcPropCount, lpProp,
  991. &ulcPropNew, &lpPropNew)))
  992. {
  993. ReadRecordFreePropArray(NULL, ulcPropCount, &lpProp);
  994. ulcPropCount = ulcPropNew;
  995. lpProp = lpPropNew;
  996. bUpdate = TRUE;
  997. }
  998. }
  999. if(bUpdate)
  1000. {
  1001. if(HR_FAILED(hr = HrSaveFolderProps((LPADRBOOK)lpIAB, FALSE, ulcPropCount, lpProp, NULL)))
  1002. goto out;
  1003. }
  1004. out:
  1005. if(lpProp)
  1006. {
  1007. if(lpProp == lpPropNew)
  1008. FreeBufferAndNull(&lpProp);
  1009. else
  1010. ReadRecordFreePropArray(NULL, ulcPropCount, &lpProp);
  1011. }
  1012. return hr;
  1013. }
  1014. /*
  1015. - HrAddRemoveFolderFromCurrentUserFolder
  1016. -
  1017. * Given a folder EID, adds or removes the folder EID from the current users
  1018. * user folder
  1019. * If there is no current user folder then use the lpUserFolder provided
  1020. * else return
  1021. *
  1022. * lpUFolder - parent folder to / from which to add / remove
  1023. * lpsbEID - EID of folder we want to add / remove
  1024. * lpName - Name to look for if we don't have an EID
  1025. */
  1026. HRESULT HrAddRemoveFolderFromUserFolder(LPIAB lpIAB, LPWABFOLDER lpUFolder,
  1027. LPSBinary lpsbEID, LPTSTR lpName,
  1028. BOOL bRefreshProfiles)
  1029. {
  1030. HRESULT hr = S_OK;
  1031. ULONG ulcPropsNew = 0, ulcProps = 0, i = 0;
  1032. LPSPropValue lpPropArrayNew = NULL;
  1033. LPSPropValue lpProps = NULL;
  1034. LPWABFOLDER lpUserFolder = NULL;
  1035. if(!lpsbEID && lpName)
  1036. {
  1037. LPWABFOLDER lpFolder = FindWABFolder(lpIAB, NULL, lpName, NULL);
  1038. lpsbEID = &lpFolder->sbEID;
  1039. }
  1040. if(lpIAB->lpWABCurrentUserFolder)
  1041. lpUserFolder = lpIAB->lpWABCurrentUserFolder;
  1042. else if(lpUFolder)
  1043. lpUserFolder = lpUFolder;
  1044. else
  1045. goto out;
  1046. {
  1047. // open the current user folder
  1048. if(!HR_FAILED(hr = ReadRecord(lpIAB->lpPropertyStore->hPropertyStore, &(lpUserFolder->sbEID),
  1049. 0, &ulcProps, &lpProps)))
  1050. {
  1051. SPropValue spv = {0};
  1052. spv.ulPropTag = PR_NULL;
  1053. // Copy the props into a MAPI proparray
  1054. if(!(ScMergePropValues( 1, &spv, ulcProps, lpProps,
  1055. &ulcPropsNew, &lpPropArrayNew)))
  1056. {
  1057. for(i=0;i<ulcPropsNew;i++)
  1058. {
  1059. if(lpProps[i].ulPropTag == PR_WAB_USER_SUBFOLDERS)
  1060. {
  1061. if(bIsProfileMember(lpIAB, lpsbEID, NULL, lpUserFolder))
  1062. RemovePropFromMVBin( lpPropArrayNew, ulcPropsNew, i, lpsbEID->lpb, lpsbEID->cb);
  1063. else
  1064. AddPropToMVPBin( lpPropArrayNew, i, lpsbEID->lpb, lpsbEID->cb, TRUE);
  1065. break;
  1066. }
  1067. }
  1068. }
  1069. if(HR_FAILED(hr = HrSaveFolderProps((LPADRBOOK)lpIAB, FALSE, ulcPropsNew, lpPropArrayNew, NULL)))
  1070. goto out;
  1071. }
  1072. }
  1073. if(bRefreshProfiles)
  1074. hr = HrGetWABProfiles(lpIAB);
  1075. out:
  1076. ReadRecordFreePropArray(NULL, ulcProps, &lpProps);
  1077. MAPIFreeBuffer(lpPropArrayNew);
  1078. return hr;
  1079. }
  1080. /*
  1081. -
  1082. - bDoesThisWABHaveAnyUsers
  1083. *
  1084. * TRUE if some user folders exist .. FALSE if NO user folders exist
  1085. */
  1086. BOOL bDoesThisWABHaveAnyUsers(LPIAB lpIAB)
  1087. {
  1088. return (lpIAB->lpWABUserFolders != NULL);
  1089. }
  1090. /*
  1091. -
  1092. - bIsThereACurrentUser
  1093. *
  1094. * TRUE if there is a current user .. FALSE if not
  1095. */
  1096. BOOL bIsThereACurrentUser(LPIAB lpIAB)
  1097. {
  1098. // Don't change this test since success of this test implies that lpIAB->lpWABCurrentUserFolder is not NULL
  1099. // and can be dereferenced
  1100. return (lpIAB->lpWABCurrentUserFolder != NULL);
  1101. }
  1102. /*
  1103. -
  1104. - bAreWABAPIProfileAware
  1105. *
  1106. * TRUE if the WAB API should behave with profile-awareness, false if they should revert to old behaviour
  1107. */
  1108. BOOL bAreWABAPIProfileAware(LPIAB lpIAB)
  1109. {
  1110. return (lpIAB->bProfilesAPIEnabled);
  1111. }
  1112. /*
  1113. -
  1114. - bIsWABSessionProfileAware
  1115. *
  1116. * TRUE if the WAB should behave with profile-awareness, false if they should revert to old behaviour
  1117. * This is also used to differentiate between Outlook sessions which are not at all profile aware
  1118. */
  1119. BOOL bIsWABSessionProfileAware(LPIAB lpIAB)
  1120. {
  1121. return (lpIAB->bProfilesEnabled);
  1122. }
  1123. /**************************************/
  1124. /******* Identity Manager Stuff *******/
  1125. // Global place to store the account manager object
  1126. //IUserIdentityManager * g_lpUserIdentityManager = NULL;
  1127. //BOOL fCoInitUserIdentityManager = FALSE;
  1128. //ULONG cIdentInit = 0;
  1129. //*******************************************************************
  1130. //
  1131. // FUNCTION: HrWrappedCreateIdentityManager
  1132. //
  1133. // PURPOSE: Load identity manager dll and create the object.
  1134. //
  1135. // PARAMETERS: lppIdentityManager -> returned pointer to Identity manager
  1136. // object.
  1137. //
  1138. // RETURNS: HRESULT
  1139. //
  1140. //*******************************************************************
  1141. HRESULT HrWrappedCreateUserIdentityManager(LPIAB lpIAB, IUserIdentityManager **lppUserIdentityManager)
  1142. {
  1143. HRESULT hResult = E_FAIL;
  1144. if (! lppUserIdentityManager) {
  1145. return(ResultFromScode(E_INVALIDARG));
  1146. }
  1147. *lppUserIdentityManager = NULL;
  1148. if (CoInitialize(NULL) == S_FALSE)
  1149. {
  1150. // Already initialized, undo the extra.
  1151. CoUninitialize();
  1152. } else
  1153. {
  1154. lpIAB->fCoInitUserIdentityManager = TRUE;
  1155. }
  1156. if (HR_FAILED(hResult = CoCreateInstance(&CLSID_UserIdentityManager,
  1157. NULL,
  1158. CLSCTX_INPROC_SERVER,
  1159. &IID_IUserIdentityManager,
  1160. (LPVOID *)lppUserIdentityManager)))
  1161. {
  1162. DebugTrace(TEXT("CoCreateInstance(IID_IUserIdentityManager) -> %x\n"), GetScode(hResult));
  1163. }
  1164. return(hResult);
  1165. }
  1166. //*******************************************************************
  1167. //
  1168. // FUNCTION: InitUserIdentityManager
  1169. //
  1170. // PURPOSE: Load and initialize the account manager
  1171. //
  1172. // PARAMETERS: lppUserIdentityManager -> returned pointer to account manager
  1173. // object.
  1174. //
  1175. // RETURNS: HRESULT
  1176. //
  1177. // COMMENTS: The first time through here, we will save the hResult.
  1178. // On subsequent calls, we will check this saved value
  1179. // and return it right away if there was an error, thus
  1180. // preventing repeated time consuming LoadLibrary calls.
  1181. //
  1182. //*******************************************************************
  1183. HRESULT InitUserIdentityManager(LPIAB lpIAB, IUserIdentityManager ** lppUserIdentityManager)
  1184. {
  1185. static hResultSave = hrSuccess;
  1186. HRESULT hResult = hResultSave;
  1187. if (! lpIAB->lpUserIdentityManager && ! HR_FAILED(hResultSave))
  1188. {
  1189. #ifdef DEBUG
  1190. DWORD dwTickCount = GetTickCount();
  1191. DebugTrace(TEXT(">>>>> Initializing User Identity Manager...\n"));
  1192. #endif // DEBUG
  1193. if (hResult = HrWrappedCreateUserIdentityManager(lpIAB, &lpIAB->lpUserIdentityManager))
  1194. {
  1195. DebugTrace(TEXT("HrWrappedCreateUserIdentityManager -> %x\n"), GetScode(hResult));
  1196. goto end;
  1197. }
  1198. Assert(lpIAB->lpUserIdentityManager);
  1199. lpIAB->cIdentInit++; // +1 here to match the release in IAB_Neuter
  1200. #ifdef DEBUG
  1201. DebugTrace( TEXT(">>>>> Done Initializing User Identity Manager... %u milliseconds\n"), GetTickCount() - dwTickCount);
  1202. #endif // DEBUG
  1203. }
  1204. lpIAB->cIdentInit++;
  1205. end:
  1206. if (HR_FAILED(hResult))
  1207. {
  1208. *lppUserIdentityManager = NULL;
  1209. // Save the result
  1210. hResultSave = hResult;
  1211. } else
  1212. {
  1213. *lppUserIdentityManager = lpIAB->lpUserIdentityManager;
  1214. }
  1215. return(hResult);
  1216. }
  1217. //*******************************************************************
  1218. //
  1219. // FUNCTION: UninitUserIdentityManager
  1220. //
  1221. // PURPOSE: Release and unLoad the account manager
  1222. //
  1223. // PARAMETERS: none
  1224. //
  1225. // RETURNS: none
  1226. //
  1227. //*******************************************************************
  1228. void UninitUserIdentityManager(LPIAB lpIAB)
  1229. {
  1230. lpIAB->cIdentInit--;
  1231. if (lpIAB->lpUserIdentityManager && lpIAB->cIdentInit==0) {
  1232. #ifdef DEBUG
  1233. DWORD dwTickCount = GetTickCount();
  1234. DebugTrace( TEXT(">>>>> Uninitializing Account Manager...\n"));
  1235. #endif // DEBUG
  1236. lpIAB->lpUserIdentityManager->lpVtbl->Release(lpIAB->lpUserIdentityManager);
  1237. lpIAB->lpUserIdentityManager = NULL;
  1238. if (lpIAB->fCoInitUserIdentityManager)
  1239. CoUninitialize();
  1240. #ifdef DEBUG
  1241. DebugTrace( TEXT(">>>>> Done Uninitializing Account Manager... %u milliseconds\n"), GetTickCount() - dwTickCount);
  1242. #endif // DEBUG
  1243. }
  1244. }
  1245. /*
  1246. - HrGetDefaultIdentityInfo
  1247. -
  1248. * Get's the hKey corresponding to the default identity
  1249. */
  1250. HRESULT HrGetDefaultIdentityInfo(LPIAB lpIAB, ULONG ulFlags, HKEY * lphKey, LPTSTR lpProfileID, ULONG cchProfileID, LPTSTR lpName, ULONG cchName)
  1251. {
  1252. IUserIdentityManager * lpUserIdentityManager = NULL;
  1253. IUserIdentity * lpUserIdentity = NULL;
  1254. HRESULT hr = S_OK;
  1255. BOOL fInit = FALSE;
  1256. if(HR_FAILED(hr = InitUserIdentityManager(lpIAB, &lpUserIdentityManager)))
  1257. goto out;
  1258. fInit = TRUE;
  1259. Assert(lpUserIdentityManager);
  1260. if(HR_FAILED(hr = lpUserIdentityManager->lpVtbl->GetIdentityByCookie(lpUserIdentityManager,
  1261. (GUID *)&UID_GIBC_DEFAULT_USER,
  1262. &lpUserIdentity)))
  1263. goto out;
  1264. Assert(lpUserIdentity);
  1265. if(ulFlags & DEFAULT_ID_HKEY && lphKey)
  1266. {
  1267. if(HR_FAILED(hr = lpUserIdentity->lpVtbl->OpenIdentityRegKey(lpUserIdentity,
  1268. KEY_ALL_ACCESS,
  1269. lphKey)))
  1270. goto out;
  1271. }
  1272. if(ulFlags & DEFAULT_ID_PROFILEID && lpProfileID)
  1273. {
  1274. GUID guidCookie = {0};
  1275. TCHAR sz[MAX_PATH];
  1276. // update this key for the account manager
  1277. if(HR_FAILED(hr = lpUserIdentity->lpVtbl->GetCookie(lpUserIdentity, &guidCookie)))
  1278. goto out;
  1279. if(HR_FAILED(hr = HrGetUserProfileID(&guidCookie, sz, CharSizeOf(sz))))
  1280. goto out;
  1281. StrCpyN(lpProfileID, sz, cchProfileID);
  1282. }
  1283. if(ulFlags & DEFAULT_ID_NAME && lpName && lpProfileID)
  1284. {
  1285. if(HR_FAILED(hr = HrGetIdentityName(lpIAB, lpProfileID, lpName, cchName)))
  1286. goto out;
  1287. }
  1288. out:
  1289. if(lpUserIdentity)
  1290. lpUserIdentity->lpVtbl->Release(lpUserIdentity);
  1291. if(fInit)
  1292. UninitUserIdentityManager(lpIAB);
  1293. return hr;
  1294. }
  1295. /*
  1296. - HrGetIdentityName
  1297. -
  1298. * Gets the name string corresponding to the current user unless a specific profile ID is specified
  1299. * (which is nothing but a string version of the GUID to use)
  1300. * szName - buffer long enough for the user name (CCH_IDENTITY_NAME_MAX_LENGTH)
  1301. */
  1302. HRESULT HrGetIdentityName(LPIAB lpIAB, LPTSTR lpID, LPTSTR szUserName, ULONG cchUserName)
  1303. {
  1304. IUserIdentityManager * lpUserIdentityManager = NULL;
  1305. IUserIdentity * lpUserIdentity = NULL;
  1306. WCHAR szNameW[CCH_IDENTITY_NAME_MAX_LENGTH];
  1307. TCHAR szName[CCH_IDENTITY_NAME_MAX_LENGTH];
  1308. HRESULT hr = S_OK;
  1309. GUID guidCookie = {0};
  1310. BOOL fInit = FALSE;
  1311. if(!lpID && !bAreWABAPIProfileAware(lpIAB))
  1312. goto out;
  1313. if(HR_FAILED(hr = InitUserIdentityManager(lpIAB, &lpUserIdentityManager)))
  1314. goto out;
  1315. fInit = TRUE;
  1316. Assert(lpUserIdentityManager);
  1317. if(lpIAB && !lpID)
  1318. memcpy(&guidCookie, &lpIAB->guidCurrentUser, sizeof(GUID));
  1319. else
  1320. {
  1321. if( (HR_FAILED(hr = CLSIDFromString(lpID, &guidCookie))) )
  1322. goto out;
  1323. }
  1324. if(HR_FAILED(hr = lpUserIdentityManager->lpVtbl->GetIdentityByCookie(lpUserIdentityManager, &guidCookie, &lpUserIdentity)))
  1325. goto out;
  1326. Assert(lpUserIdentity);
  1327. if(HR_FAILED(hr = lpUserIdentity->lpVtbl->GetName(lpUserIdentity, szNameW, CharSizeOf(szNameW))))
  1328. goto out;
  1329. StrCpyN(szName, szNameW, ARRAYSIZE(szName));
  1330. if(!lstrcmp(szUserName, szName))
  1331. {
  1332. hr = E_FAIL;
  1333. goto out;
  1334. }
  1335. StrCpyN(szUserName, szName, cchUserName);
  1336. out:
  1337. if(fInit)
  1338. UninitUserIdentityManager(lpIAB);
  1339. if(lpUserIdentity)
  1340. lpUserIdentity->lpVtbl->Release(lpUserIdentity);
  1341. if(HR_FAILED(hr))
  1342. szUserName[0] = TEXT('\0');
  1343. return hr;
  1344. }
  1345. /*
  1346. - HrGetUserProfileID
  1347. -
  1348. * Gets the profile string corresponding to the current user
  1349. * The profile ID is nothing but a string represenatation of the user's Cookie (GUID)
  1350. *
  1351. * szProfileID - buffer long enough for the user name
  1352. */
  1353. HRESULT HrGetUserProfileID(LPGUID lpguidUser, LPTSTR szProfileID, ULONG cbProfileID)
  1354. {
  1355. HRESULT hr = S_OK;
  1356. LPOLESTR lpszW= 0 ;
  1357. if (HR_FAILED(hr = StringFromCLSID(lpguidUser, &lpszW)))
  1358. goto out;
  1359. StrCpyN(szProfileID,(LPCWSTR)lpszW,cbProfileID);
  1360. out:
  1361. if (lpszW)
  1362. {
  1363. LPMALLOC pMalloc = NULL;
  1364. CoGetMalloc(1, &pMalloc);
  1365. if (pMalloc) {
  1366. pMalloc->lpVtbl->Free(pMalloc, lpszW);
  1367. pMalloc->lpVtbl->Release(pMalloc);
  1368. }
  1369. }
  1370. if(HR_FAILED(hr))
  1371. szProfileID[0] = TEXT('\0');
  1372. return hr;
  1373. }
  1374. /*
  1375. -
  1376. - HrLogonAndGetCurrentUserProfile - Inits the User Identity Manger and calls into the Logon ..
  1377. - Gets a user, either by showing UI or getting the current user and then gets a
  1378. - profile ID ( TEXT("Cookie")) for that user ..
  1379. *
  1380. * bForceUI - forces the Logon dialog so user can switch users .. TRUE only when user wants to switch
  1381. *
  1382. * bSwitchUser - True only after user has switched .. tells us to refresh and get details ont he new user
  1383. *
  1384. */
  1385. HRESULT HrLogonAndGetCurrentUserProfile(HWND hWndParent, LPIAB lpIAB, BOOL bForceUI, BOOL bSwitchUser)
  1386. {
  1387. HRESULT hr = S_OK;
  1388. IUserIdentityManager * lpUserIdentityManager = NULL;
  1389. IUserIdentity * lpUserIdentity = NULL;
  1390. GUID guidCookie = {0};
  1391. BOOL fInit = FALSE;
  1392. if(!bAreWABAPIProfileAware(lpIAB))
  1393. goto out;
  1394. if(HR_FAILED(hr = InitUserIdentityManager(lpIAB, &lpUserIdentityManager)))
  1395. goto out;
  1396. fInit = TRUE;
  1397. Assert(lpUserIdentityManager);
  1398. // Logon will get the currently logged on user, or if there is a single user, it will return
  1399. // that user, or if there are multiple users, it will prompt for a logon
  1400. //
  1401. if(!bSwitchUser)
  1402. {
  1403. hr = lpUserIdentityManager->lpVtbl->Logon(lpUserIdentityManager,
  1404. hWndParent,
  1405. bForceUI ? UIL_FORCE_UI : 0,
  1406. &lpUserIdentity);
  1407. #ifdef NEED
  1408. if(hr == S_IDENTITIES_DISABLED)
  1409. hr = E_FAIL;
  1410. #endif
  1411. if(HR_FAILED(hr))
  1412. goto out;
  1413. }
  1414. else
  1415. {
  1416. // just switching users, thats all
  1417. if(HR_FAILED(hr = lpUserIdentityManager->lpVtbl->GetIdentityByCookie(lpUserIdentityManager,
  1418. (GUID *)&UID_GIBC_CURRENT_USER,
  1419. &lpUserIdentity)))
  1420. goto out;
  1421. }
  1422. Assert(lpUserIdentity);
  1423. if(lpIAB->hKeyCurrentUser)
  1424. RegCloseKey(lpIAB->hKeyCurrentUser);
  1425. // get the identity's hkey for the wab
  1426. if(HR_FAILED(hr = lpUserIdentity->lpVtbl->OpenIdentityRegKey(lpUserIdentity, KEY_ALL_ACCESS, &lpIAB->hKeyCurrentUser)))
  1427. goto out;
  1428. // get anothor one for the account manager (it will free it)
  1429. if(HR_FAILED(hr = lpUserIdentity->lpVtbl->GetCookie(lpUserIdentity, &guidCookie)))
  1430. goto out;
  1431. else
  1432. {
  1433. IImnAccountManager2 * lpAccountManager = NULL;
  1434. // [PaulHi] 1/13/99 Changed to initialize the account manager with
  1435. // user guid cookie inside the InitAccountManager() function.
  1436. InitAccountManager(lpIAB, &lpAccountManager, &guidCookie);
  1437. }
  1438. if(!memcmp(&lpIAB->guidCurrentUser, &guidCookie, sizeof(GUID)))
  1439. {
  1440. //current user is identical to the one we have so don't update anything here
  1441. return S_OK;
  1442. }
  1443. memcpy(&lpIAB->guidCurrentUser, &guidCookie, sizeof(GUID));
  1444. lpIAB->szProfileID[0] = TEXT('\0');
  1445. lpIAB->szProfileName[0] = TEXT('\0');
  1446. HrGetIdentityName(lpIAB, NULL, lpIAB->szProfileName, ARRAYSIZE(lpIAB->szProfileName));
  1447. HrGetUserProfileID(&lpIAB->guidCurrentUser, lpIAB->szProfileID, CharSizeOf(lpIAB->szProfileID));
  1448. /*
  1449. //register for changes
  1450. if( !bSwitchUser && !bForceUI && !lpIAB->lpWABIDCN
  1451. //&& !memcmp(&lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID))
  1452. ) // register for notifications only if this is the WAB.exe process
  1453. {
  1454. HrRegisterUnregisterForIDNotifications( lpIAB, TRUE);
  1455. }
  1456. */
  1457. out:
  1458. if(fInit)
  1459. UninitUserIdentityManager(lpIAB);
  1460. if(lpUserIdentity)
  1461. lpUserIdentity->lpVtbl->Release(lpUserIdentity);
  1462. return hr;
  1463. }
  1464. /*
  1465. - HRESULT HrRegisterUnregisterForIDNotifications()
  1466. -
  1467. * Creates/Releases a WABIDENTITYCHANGENOTIFY object
  1468. *
  1469. */
  1470. HRESULT HrRegisterUnregisterForIDNotifications( LPIAB lpIAB, BOOL bRegister)
  1471. {
  1472. HRESULT hr = S_OK;
  1473. IUserIdentityManager * lpUserIdentityManager = NULL;
  1474. IConnectionPoint * lpConnectionPoint = NULL;
  1475. BOOL fInit = FALSE;
  1476. // Need to register for notifications even if running under Outlook
  1477. // Assume that relevant tests have occured before this is called ....
  1478. // if(bRegister && !bAreWABAPIProfileAware(lpIAB))
  1479. // goto out;
  1480. if( (!bRegister && !lpIAB->lpWABIDCN) ||
  1481. (bRegister && lpIAB->lpWABIDCN) )
  1482. goto out;
  1483. if(HR_FAILED(hr = InitUserIdentityManager(lpIAB, &lpUserIdentityManager)))
  1484. goto out;
  1485. fInit = TRUE;
  1486. Assert(lpUserIdentityManager);
  1487. if(HR_FAILED(hr = lpUserIdentityManager->lpVtbl->QueryInterface(lpUserIdentityManager,
  1488. &IID_IConnectionPoint,
  1489. (LPVOID *)&lpConnectionPoint)))
  1490. goto out;
  1491. if(bRegister)
  1492. {
  1493. if(lpIAB->lpWABIDCN)
  1494. {
  1495. lpIAB->lpWABIDCN->lpVtbl->Release(lpIAB->lpWABIDCN);
  1496. lpIAB->lpWABIDCN = NULL;
  1497. }
  1498. if(HR_FAILED(hr = HrCreateIdentityChangeNotifyObject(lpIAB, &lpIAB->lpWABIDCN)))
  1499. goto out;
  1500. if(HR_FAILED(hr = lpConnectionPoint->lpVtbl->Advise(lpConnectionPoint, (LPUNKNOWN) lpIAB->lpWABIDCN, &lpIAB->dwWABIDCN)))
  1501. goto out;
  1502. }
  1503. else
  1504. {
  1505. if(lpIAB->lpWABIDCN)
  1506. {
  1507. if(HR_FAILED(hr = lpConnectionPoint->lpVtbl->Unadvise(lpConnectionPoint, lpIAB->dwWABIDCN)))
  1508. goto out;
  1509. lpIAB->dwWABIDCN = 0;
  1510. lpIAB->lpWABIDCN->lpVtbl->Release(lpIAB->lpWABIDCN);
  1511. lpIAB->lpWABIDCN = NULL;
  1512. }
  1513. }
  1514. out:
  1515. if(fInit)
  1516. UninitUserIdentityManager(lpIAB);
  1517. if(lpConnectionPoint)
  1518. lpConnectionPoint->lpVtbl->Release(lpConnectionPoint);
  1519. return hr;
  1520. }
  1521. /*--------------------------------------------------------------------------------------------------*/
  1522. WAB_IDENTITYCHANGENOTIFY_Vtbl vtblWABIDENTITYCHANGENOTIFY = {
  1523. VTABLE_FILL
  1524. WAB_IDENTITYCHANGENOTIFY_QueryInterface,
  1525. WAB_IDENTITYCHANGENOTIFY_AddRef,
  1526. WAB_IDENTITYCHANGENOTIFY_Release,
  1527. WAB_IDENTITYCHANGENOTIFY_QuerySwitchIdentities,
  1528. WAB_IDENTITYCHANGENOTIFY_SwitchIdentities,
  1529. WAB_IDENTITYCHANGENOTIFY_IdentityInformationChanged
  1530. };
  1531. /*
  1532. - HrCreateIdentityChangeNotifyObject
  1533. -
  1534. * The ChangeNotificationObject is created only on the LPIAB object and on the
  1535. * main browse window. Depending on where it's called from, we will pass in either the
  1536. * lpIAB pointer or the hWnd of the Window.
  1537. * THen when we get the callback notification, we can figure out what we want to do
  1538. * based on which of the 2 are available to us ..
  1539. *
  1540. */
  1541. HRESULT HrCreateIdentityChangeNotifyObject(LPIAB lpIAB, LPWABIDENTITYCHANGENOTIFY * lppWABIDCN)
  1542. {
  1543. LPWABIDENTITYCHANGENOTIFY lpIWABIDCN = NULL;
  1544. SCODE sc;
  1545. HRESULT hr = hrSuccess;
  1546. //
  1547. // Allocate space for the IAB structure
  1548. //
  1549. if (FAILED(sc = MAPIAllocateBuffer(sizeof(WABIDENTITYCHANGENOTIFY), (LPVOID *) &lpIWABIDCN)))
  1550. {
  1551. hr = ResultFromScode(sc);
  1552. goto err;
  1553. }
  1554. MAPISetBufferName(lpIWABIDCN, TEXT("WAB IdentityChangeNotify Object"));
  1555. ZeroMemory(lpIWABIDCN, sizeof(WABIDENTITYCHANGENOTIFY));
  1556. lpIWABIDCN->lpVtbl = &vtblWABIDENTITYCHANGENOTIFY;
  1557. lpIWABIDCN->lpIAB = lpIAB;
  1558. lpIWABIDCN->lpVtbl->AddRef(lpIWABIDCN);
  1559. *lppWABIDCN = lpIWABIDCN;
  1560. return(hrSuccess);
  1561. err:
  1562. FreeBufferAndNull(&lpIWABIDCN);
  1563. return(hr);
  1564. }
  1565. void ReleaseWABIdentityChangeNotifyObj(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN)
  1566. {
  1567. MAPIFreeBuffer(lpIWABIDCN);
  1568. }
  1569. STDMETHODIMP_(ULONG)
  1570. WAB_IDENTITYCHANGENOTIFY_AddRef(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN)
  1571. {
  1572. return(++(lpIWABIDCN->lcInit));
  1573. }
  1574. STDMETHODIMP_(ULONG)
  1575. WAB_IDENTITYCHANGENOTIFY_Release(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN)
  1576. {
  1577. ULONG ulc = (--(lpIWABIDCN->lcInit));
  1578. if(ulc==0)
  1579. ReleaseWABIdentityChangeNotifyObj(lpIWABIDCN);
  1580. return(ulc);
  1581. }
  1582. STDMETHODIMP
  1583. WAB_IDENTITYCHANGENOTIFY_QueryInterface(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN,
  1584. REFIID lpiid,
  1585. LPVOID * lppNewObj)
  1586. {
  1587. LPVOID lp = NULL;
  1588. if(!lppNewObj)
  1589. return MAPI_E_INVALID_PARAMETER;
  1590. *lppNewObj = NULL;
  1591. if(IsEqualIID(lpiid, &IID_IUnknown))
  1592. lp = (LPVOID) lpIWABIDCN;
  1593. if(IsEqualIID(lpiid, &IID_IIdentityChangeNotify))
  1594. lp = (LPVOID) lpIWABIDCN;
  1595. if(!lp)
  1596. return E_NOINTERFACE;
  1597. ((LPWABIDENTITYCHANGENOTIFY) lp)->lpVtbl->AddRef((LPWABIDENTITYCHANGENOTIFY) lp);
  1598. *lppNewObj = lp;
  1599. return S_OK;
  1600. }
  1601. STDMETHODIMP
  1602. WAB_IDENTITYCHANGENOTIFY_QuerySwitchIdentities(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN)
  1603. {
  1604. HRESULT hr = S_OK;
  1605. DebugTrace( TEXT("WAB: IDChangeNotify::QuerySwitchIdentities: 0x%.8x\n"), GetCurrentThreadId());
  1606. if(lpIWABIDCN->lpIAB->hWndBrowse)
  1607. {
  1608. // if this relates to a window, then just make sure that the window is not deactivated
  1609. // because that would imply that the window has a dialog in front of it.
  1610. if (!IsWindowEnabled(lpIWABIDCN->lpIAB->hWndBrowse))
  1611. {
  1612. Assert(IsWindowVisible(lpIWABIDCN->lpIAB->hWndBrowse));
  1613. return E_PROCESS_CANCELLED_SWITCH;
  1614. }
  1615. }
  1616. return hr;
  1617. }
  1618. // MAJOR HACK WARNING
  1619. // [PaulHi] 12/22/98 See comment below. We need to disable the "close WAB window
  1620. // on identity switch for when the client is OE5. We don't want to change this code
  1621. // at this point for other clients. I copied the OE5 PSExt GUID from the OE5 code
  1622. // base.
  1623. static const GUID OEBAControl_GUID =
  1624. { 0x233a9694, 0x667e, 0x11d1, { 0x9d, 0xfb, 0x00, 0x60, 0x97, 0xd5, 0x04, 0x08 } };
  1625. STDMETHODIMP
  1626. WAB_IDENTITYCHANGENOTIFY_SwitchIdentities(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN)
  1627. {
  1628. HRESULT hr = S_OK;
  1629. DebugTrace( TEXT("WAB: IDChangeNotify::SwitchIdentities: 0x%.8x\n"), GetCurrentThreadId());
  1630. if(memcmp(&lpIWABIDCN->lpIAB->guidPSExt, &MPSWab_GUID_V4, sizeof(GUID)) ) //if not a wab.exe process .. shutdown
  1631. {
  1632. // [PaulHi] 12/22/98 Raid #63231, 48054
  1633. // Don't close the WAB window here when OE is the host. OE needs to shut
  1634. // down the WAB in the correct order during identity switches or serious problems occur.
  1635. if ( memcmp(&lpIWABIDCN->lpIAB->guidPSExt, &OEBAControl_GUID , sizeof(GUID)) != 0 )
  1636. SendMessage(lpIWABIDCN->lpIAB->hWndBrowse, WM_CLOSE, 0, 0);
  1637. return S_OK;
  1638. }
  1639. if(!HR_FAILED(HrLogonAndGetCurrentUserProfile(NULL, lpIWABIDCN->lpIAB, FALSE, TRUE)))
  1640. HrGetWABProfiles(lpIWABIDCN->lpIAB);
  1641. else //they did a logoff
  1642. {
  1643. SendMessage(lpIWABIDCN->lpIAB->hWndBrowse, WM_CLOSE, 0, 0);
  1644. return S_OK;
  1645. }
  1646. if(lpIWABIDCN->lpIAB->hWndBrowse) //hWndBrowse could be any window (main or find)
  1647. SendMessage(lpIWABIDCN->lpIAB->hWndBrowse, WM_COMMAND, (WPARAM) IDM_NOTIFY_REFRESHUSER, 0);
  1648. return hr;
  1649. }
  1650. STDMETHODIMP
  1651. WAB_IDENTITYCHANGENOTIFY_IdentityInformationChanged(LPWABIDENTITYCHANGENOTIFY lpIWABIDCN, DWORD dwType)
  1652. {
  1653. HRESULT hr = S_OK;
  1654. DebugTrace( TEXT("WAB: IDChangeNotify::IdentityInformationChanged: %d 0x%.8x\n"), dwType, GetCurrentThreadId());
  1655. if(dwType == IIC_CURRENT_IDENTITY_CHANGED)
  1656. {
  1657. // only thing we care about is a change in the name
  1658. if(!HR_FAILED(HrGetIdentityName(lpIWABIDCN->lpIAB, NULL, lpIWABIDCN->lpIAB->szProfileName, ARRAYSIZE(lpIWABIDCN->lpIAB->szProfileName))))
  1659. {
  1660. UpdateCurrentUserFolderName(lpIWABIDCN->lpIAB);
  1661. if(lpIWABIDCN->lpIAB->hWndBrowse)
  1662. SendMessage(lpIWABIDCN->lpIAB->hWndBrowse, WM_COMMAND, (WPARAM) IDM_NOTIFY_REFRESHUSER, 0);
  1663. }
  1664. }
  1665. return hr;
  1666. }