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.

1004 lines
28 KiB

  1. /*******************************************************
  2. MultiUsr.cpp
  3. Code for handling multiple user functionality in
  4. Outlook Express.
  5. Initially by Christopher Evans (cevans) 4/28/98
  6. ********************************************************/
  7. #include "pch.hxx"
  8. #include "multiusr.h"
  9. #include "demand.h"
  10. #include "instance.h"
  11. #include "acctutil.h"
  12. #include "options.h"
  13. #include "conman.h"
  14. #include <..\help\mailnews.h>
  15. #include "msident.h"
  16. #include "menures.h"
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[]=__FILE__;
  20. #define new DEBUG_NEW
  21. #endif
  22. #ifndef THOR_SETUP
  23. #include <shlwapi.h>
  24. #define strstr StrStr
  25. #define RegDeleteKeyRecursive SHDeleteKey
  26. #endif // THOR_SETUP
  27. TCHAR g_szRegRoot[MAX_PATH] = "";
  28. static TCHAR g_szCharsetRegRoot[MAX_PATH] = "";
  29. static TCHAR g_szIdentityName[CCH_USERNAME_MAX_LENGTH+1];
  30. static BOOL g_fUsingDefaultId = FALSE;
  31. static IUserIdentityManager *g_pIdMan = NULL;
  32. static HKEY g_hkeyIdentity = HKEY_CURRENT_USER;
  33. static BOOL g_fIdentitiesDisabled = FALSE;
  34. extern DWORD g_dwIcwFlags;
  35. GUID *PGUIDCurrentOrDefault(void) {
  36. return (g_fUsingDefaultId ? (GUID *)&UID_GIBC_DEFAULT_USER : (GUID *)&UID_GIBC_CURRENT_USER);
  37. }
  38. static void SafeIdentityRelease()
  39. {
  40. if (g_pIdMan && 0 == (g_pIdMan)->Release())
  41. {
  42. g_pIdMan = NULL;
  43. RegCloseKey(g_hkeyIdentity);
  44. g_hkeyIdentity = HKEY_CURRENT_USER;
  45. }
  46. }
  47. /*
  48. MU_RegisterIdentityNotifier
  49. Handles the dirty work of registering an identity notifier.
  50. Caller needs to hold on to dwCookie and use it to unadvise.
  51. */
  52. HRESULT MU_RegisterIdentityNotifier(IUnknown *punk, DWORD *pdwCookie)
  53. {
  54. IConnectionPoint *pConnectPt = NULL;
  55. HRESULT hr = S_OK;
  56. Assert(pdwCookie);
  57. Assert(punk);
  58. Assert(g_pIdMan);
  59. if (SUCCEEDED(hr = g_pIdMan->QueryInterface(IID_IConnectionPoint, (void **)&pConnectPt)))
  60. {
  61. Assert(pConnectPt);
  62. SideAssert(SUCCEEDED(hr = pConnectPt->Advise(punk, pdwCookie)));
  63. SafeRelease(pConnectPt);
  64. g_pIdMan->AddRef();
  65. }
  66. return hr;
  67. }
  68. /*
  69. MU_RegisterIdentityNotifier
  70. Handles the dirty work of unregistering an identity notifier.
  71. dwCookie is the cookie returned from MU_RegisterIdentityNotifier.
  72. */
  73. HRESULT MU_UnregisterIdentityNotifier(DWORD dwCookie)
  74. {
  75. IConnectionPoint *pConnectPt = NULL;
  76. HRESULT hr = S_OK;
  77. Assert(g_pIdMan);
  78. if (SUCCEEDED(hr = g_pIdMan->QueryInterface(IID_IConnectionPoint, (void **)&pConnectPt)))
  79. {
  80. Assert(pConnectPt);
  81. SideAssert(SUCCEEDED(hr = pConnectPt->Unadvise(dwCookie)));
  82. SafeRelease(pConnectPt);
  83. SafeIdentityRelease();
  84. }
  85. return hr;
  86. }
  87. /*
  88. MU_CheckForIdentitySwitch
  89. Check to see if the switch is actually a logout, or just a switch.
  90. Then tell the COutlookExpress object so that it can restart if
  91. necessary
  92. */
  93. BOOL MU_CheckForIdentityLogout()
  94. {
  95. HRESULT hr;
  96. IUserIdentity *pIdentity = NULL;
  97. BOOL fIsLogout = TRUE;
  98. GUID uidCookie;
  99. Assert(g_pIdMan);
  100. if (SUCCEEDED(hr = g_pIdMan->GetIdentityByCookie((GUID *)&UID_GIBC_INCOMING_USER, &pIdentity)))
  101. {
  102. if (pIdentity)
  103. {
  104. pIdentity->GetCookie(&uidCookie);
  105. fIsLogout = (uidCookie == GUID_NULL);
  106. pIdentity->Release();
  107. }
  108. }
  109. return fIsLogout;
  110. }
  111. /*
  112. MU_ShowErrorMessage
  113. Simple wrapper around resource string table based call to MessageBox
  114. */
  115. void MU_ShowErrorMessage(HINSTANCE hInst,
  116. HWND hwnd,
  117. UINT iMsgID,
  118. UINT iTitleID)
  119. {
  120. char szMsg[255], szTitle[63];
  121. LoadString(g_hLocRes, iMsgID, szMsg, sizeof(szMsg));
  122. LoadString(g_hLocRes, iTitleID, szTitle, sizeof(szTitle));
  123. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  124. }
  125. // --------------------------------------------------------------------------------
  126. // Functions to convert GUIDs to ascii strings
  127. // --------------------------------------------------------------------------------
  128. static int AStringFromGUID(GUID *puid, TCHAR *lpsz, int cch)
  129. {
  130. WCHAR wsz[255];
  131. int i;
  132. i = StringFromGUID2(*puid, wsz, 255);
  133. if (WideCharToMultiByte(CP_ACP, 0, wsz, -1, lpsz, cch, NULL, NULL) == 0)
  134. return 0;
  135. return (lstrlen(lpsz) + 1);
  136. }
  137. static HRESULT GUIDFromAString(TCHAR *lpsz, GUID *puid)
  138. {
  139. WCHAR wsz[255];
  140. HRESULT hr;
  141. if (MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, 255) == 0)
  142. return GetLastError();
  143. hr = CLSIDFromString(wsz, puid);
  144. return hr;
  145. }
  146. /*
  147. MU_GetCurrentUserInfo
  148. return the current user's id (guid) and username as strings
  149. */
  150. HRESULT MU_GetCurrentUserInfo(LPSTR pszId, UINT cchId, LPSTR pszName, UINT cchName)
  151. {
  152. HRESULT hr = E_UNEXPECTED;
  153. IUserIdentity *pIdentity = NULL;
  154. GUID uidUserId;
  155. WCHAR szwName[CCH_USERNAME_MAX_LENGTH+1];
  156. Assert(g_pIdMan);
  157. // we have to have the IUserIdentityManager
  158. if (!g_pIdMan)
  159. goto exit;
  160. // Get the current user
  161. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(PGUIDCurrentOrDefault(), &pIdentity)))
  162. goto exit;
  163. // if the caller wants the id
  164. if (pszId)
  165. {
  166. // get the cookie (id) as a guid
  167. if (FAILED(hr = pIdentity->GetCookie(&uidUserId)))
  168. goto exit;
  169. // turn it into a string
  170. if (0 == AStringFromGUID(&uidUserId, pszId, cchId))
  171. hr = E_OUTOFMEMORY;
  172. else
  173. hr = S_OK;
  174. }
  175. // if the caller wants the user's name
  176. if (pszName)
  177. {
  178. // get the name as a wide string
  179. if (FAILED(hr = pIdentity->GetName(szwName, cchName)))
  180. goto exit;
  181. // convert it to an ascii string
  182. if (WideCharToMultiByte(CP_ACP, 0, szwName, -1, pszName, cchName, NULL, NULL) == 0)
  183. hr = GetLastError();
  184. }
  185. exit:
  186. // clean up
  187. SafeRelease(pIdentity);
  188. return hr;
  189. }
  190. /*
  191. MU_GetCurrentUserHKey
  192. Return the current user's HKEY.
  193. If no one has logged on yet (this happens when coming in from SMAPI)
  194. then do the login first. If the user cancels the login, just return
  195. the hkey for the default user.
  196. Caller should not close this key. It is a common key. If it is going
  197. to be passed out to another library or something, caller should call
  198. MU_OpenCurrentUserHkey.
  199. */
  200. HKEY MU_GetCurrentUserHKey()
  201. {
  202. IUserIdentity *pIdentity = NULL;
  203. HRESULT hr;
  204. HKEY hkey;
  205. // g_hkeyIdentity is initialized to HKEY_CURRENT_USER
  206. if (g_hkeyIdentity == HKEY_CURRENT_USER)
  207. {
  208. // we haven't logged in yet. Lets try now
  209. if (!MU_Login(GetDesktopWindow(), FALSE, ""))
  210. {
  211. Assert(g_pIdMan);
  212. if (NULL == g_pIdMan)
  213. goto exit;
  214. // if they cancelled or whatever, try to get the
  215. // default user
  216. if (FAILED(hr = g_pIdMan->GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, &pIdentity)))
  217. goto exit;
  218. }
  219. else
  220. {
  221. // login succeeded, get the current identity
  222. Assert(g_pIdMan);
  223. if (NULL == g_pIdMan)
  224. goto exit;
  225. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(PGUIDCurrentOrDefault(), &pIdentity)))
  226. goto exit;
  227. }
  228. if (g_hkeyIdentity != HKEY_CURRENT_USER)
  229. RegCloseKey(g_hkeyIdentity);
  230. // open a new all access reg key. Caller must close it
  231. if (pIdentity && SUCCEEDED(hr = pIdentity->OpenIdentityRegKey(KEY_ALL_ACCESS, &hkey)))
  232. g_hkeyIdentity = hkey;
  233. else
  234. g_hkeyIdentity = HKEY_CURRENT_USER;
  235. }
  236. exit:
  237. // Clean up
  238. SafeRelease(pIdentity);
  239. return g_hkeyIdentity;
  240. }
  241. /*
  242. MU_OpenCurrentUserHkey
  243. Open a new reg key for the current user.
  244. */
  245. HRESULT MU_OpenCurrentUserHkey(HKEY *pHkey)
  246. {
  247. HRESULT hr = E_UNEXPECTED;
  248. IUserIdentity *pIdentity = NULL;
  249. GUID uidUserId;
  250. Assert(g_pIdMan);
  251. // we have to have the IUserIdentityManager
  252. if (!g_pIdMan)
  253. goto exit;
  254. // Get the current identity. If we can't get it, bail.
  255. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(PGUIDCurrentOrDefault(), &pIdentity)))
  256. goto exit;
  257. // If passed in an hkey pointer, open a new all access key
  258. if (pHkey)
  259. hr = pIdentity->OpenIdentityRegKey(KEY_ALL_ACCESS, pHkey);
  260. exit:
  261. // Clean up
  262. SafeRelease(pIdentity);
  263. return hr;
  264. }
  265. /*
  266. MU_GetCurrentUserDirectoryRoot
  267. Return the path to the top of the current user's root directory.
  268. This is the directory where the mail store should be located.
  269. It is in a subfolder the App Data folder.
  270. lpszUserRoot is a pointer to a character buffer that is cch chars
  271. in size.
  272. */
  273. HRESULT MU_GetCurrentUserDirectoryRoot(TCHAR *lpszUserRoot, int cch)
  274. {
  275. HRESULT hr = E_FAIL;
  276. IUserIdentity *pIdentity = NULL;
  277. Assert(g_pIdMan);
  278. Assert(lpszUserRoot != NULL);
  279. Assert(cch >= MAX_PATH);
  280. if (g_pIdMan == NULL)
  281. goto exit;
  282. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(PGUIDCurrentOrDefault(), &pIdentity)))
  283. goto exit;
  284. hr = MU_GetIdentityDirectoryRoot(pIdentity, lpszUserRoot, cch);
  285. exit:
  286. SafeRelease(pIdentity);
  287. return hr;
  288. }
  289. HRESULT MU_GetIdentityDirectoryRoot(IUserIdentity *pIdentity, LPSTR lpszUserRoot, int cch)
  290. {
  291. HRESULT hr;
  292. TCHAR szSubDir[MAX_PATH], *psz;
  293. WCHAR szwUserRoot[MAX_PATH];
  294. int cb;
  295. Assert(pIdentity);
  296. Assert(lpszUserRoot != NULL);
  297. Assert(cch >= MAX_PATH);
  298. hr = pIdentity->GetIdentityFolder(GIF_NON_ROAMING_FOLDER, szwUserRoot, MAX_PATH);
  299. if (FAILED(hr))
  300. return(hr);
  301. if (WideCharToMultiByte(CP_ACP, 0, szwUserRoot, -1, lpszUserRoot, cch, NULL, NULL) == 0)
  302. return(E_FAIL);
  303. AthLoadString(idsMicrosoft, szSubDir, ARRAYSIZE(szSubDir));
  304. psz = PathAddBackslash(szSubDir);
  305. AthLoadString(idsAthena, psz, ARRAYSIZE(szSubDir)-(DWORD)(psz-szSubDir));
  306. cb = lstrlen(lpszUserRoot) + lstrlen(szSubDir) + 3;
  307. if (cb < cch)
  308. {
  309. psz = PathAddBackslash(lpszUserRoot);
  310. if (psz)
  311. {
  312. StrCpyN(psz, szSubDir, cch - (DWORD)(psz-lpszUserRoot));
  313. psz = PathAddBackslash(lpszUserRoot);
  314. }
  315. hr = S_OK;
  316. }
  317. return(hr);
  318. }
  319. DWORD MU_CountUsers()
  320. {
  321. IEnumUserIdentity *pEnum = NULL;
  322. HRESULT hr;
  323. ULONG cUsers = 0;
  324. Assert(g_pIdMan);
  325. if (SUCCEEDED(hr = g_pIdMan->EnumIdentities(&pEnum)) && pEnum)
  326. {
  327. pEnum->GetCount(&cUsers);
  328. SafeRelease(pEnum);
  329. }
  330. return cUsers;
  331. }
  332. /*
  333. MU_Login
  334. Wrapper routine for logging in to OE. Asks the user to choose a username
  335. and, if necessary, enter the password for that user. The user can also
  336. create an account at this point.
  337. lpszUsername should contain the name of the person who should be the default
  338. selection in the list. If the name is empty ("") then it will look up the
  339. default from the registry.
  340. Returns the username that was selected in lpszUsername. Returns true
  341. if that username is valid.
  342. */
  343. BOOL MU_Login(HWND hwnd, BOOL fForceUI, char *lpszUsername)
  344. {
  345. HRESULT hr = S_OK;
  346. IUserIdentity *pIdentity = NULL;
  347. if (g_fUsingDefaultId)
  348. goto exit;
  349. if (NULL == g_pIdMan)
  350. {
  351. hr = MU_Init(FALSE);
  352. if (FAILED(hr))
  353. goto exit;
  354. }
  355. #pragma prefast(suppress:11, "noise")
  356. g_pIdMan->AddRef();
  357. #pragma prefast(suppress:11, "noise")
  358. hr = g_pIdMan->Logon(hwnd, (fForceUI ? UIL_FORCE_UI : 0), &pIdentity);
  359. if (SUCCEEDED(hr))
  360. {
  361. g_fIdentitiesDisabled = (hr == S_IDENTITIES_DISABLED);
  362. if (!fForceUI)
  363. {
  364. if (g_hkeyIdentity != HKEY_CURRENT_USER)
  365. RegCloseKey(g_hkeyIdentity);
  366. hr = pIdentity->OpenIdentityRegKey(KEY_ALL_ACCESS,&g_hkeyIdentity);
  367. }
  368. SafeRelease(pIdentity);
  369. }
  370. SafeIdentityRelease();
  371. exit:
  372. return SUCCEEDED(hr);
  373. }
  374. BOOL MU_Logoff(HWND hwnd)
  375. {
  376. HRESULT hr=E_FAIL;
  377. Assert(g_pIdMan);
  378. if (g_pIdMan)
  379. hr = g_pIdMan->Logoff(hwnd);
  380. return SUCCEEDED(hr);
  381. }
  382. /*
  383. MU_MigrateFirstUserSettings
  384. This should only be called once, when there are no users configured yet.
  385. */
  386. #define MAXDATA_LENGTH 16L*1024L
  387. void MU_MigrateFirstUserSettings(void)
  388. {
  389. /* OEUSERINFO vCurrentUser;
  390. TCHAR szLM[255];
  391. HKEY hDestinationKey = NULL;
  392. HKEY hSourceKey = NULL;
  393. FILETIME ftCU = {0,1}, ftLM = {0,0}; //default CU to just later than LM
  394. DWORD dwType, dwSize, dwStatus;
  395. if (MU_GetCurrentUserInfo(&vCurrentUser))
  396. {
  397. TCHAR szRegPath[MAX_PATH], szAcctPath[MAX_PATH];
  398. Assert(vCurrentUser.idUserID != -1);
  399. MU_GetRegRootForUserID(vCurrentUser.idUserID, szRegPath);
  400. Assert(*szRegPath);
  401. MU_GetAccountRegRootForUserID(vCurrentUser.idUserID, szAcctPath);
  402. Assert(*szAcctPath);
  403. hDestinationKey = NULL;
  404. if (RegCreateKey(HKEY_CURRENT_USER, szAcctPath, &hDestinationKey) == ERROR_SUCCESS)
  405. {
  406. if (RegOpenKey(HKEY_CURRENT_USER, c_szInetAcctMgrRegKey, &hSourceKey) == ERROR_SUCCESS)
  407. {
  408. CopyRegistry(hSourceKey, hDestinationKey);
  409. RegCloseKey(hSourceKey);
  410. }
  411. RegCloseKey(hDestinationKey);
  412. }
  413. if (RegCreateKey(HKEY_CURRENT_USER, szRegPath, &hDestinationKey) == ERROR_SUCCESS)
  414. {
  415. if (RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hSourceKey) == ERROR_SUCCESS)
  416. {
  417. DWORD EnumIndex;
  418. DWORD cbValueName;
  419. DWORD cbValueData;
  420. DWORD Type;
  421. CHAR ValueNameBuffer[MAXKEYNAME];
  422. BYTE ValueDataBuffer[MAXDATA_LENGTH];
  423. //
  424. // Copy all of the value names and their data.
  425. //
  426. EnumIndex = 0;
  427. while (TRUE) {
  428. cbValueName = sizeof(ValueNameBuffer);
  429. cbValueData = MAXDATA_LENGTH;
  430. if (RegEnumValue(hSourceKey, EnumIndex++, ValueNameBuffer,
  431. &cbValueName, NULL, &Type, ValueDataBuffer, &cbValueData) !=
  432. ERROR_SUCCESS)
  433. break;
  434. RegSetValueEx(hDestinationKey, ValueNameBuffer, 0, Type,
  435. ValueDataBuffer, cbValueData);
  436. }
  437. RegSetValueEx(hDestinationKey, c_szUserID, 0, REG_DWORD, (BYTE *)&vCurrentUser.idUserID, sizeof(DWORD));
  438. //
  439. // Copy all of the subkeys and recurse into them.
  440. //
  441. EnumIndex = 0;
  442. while (TRUE)
  443. {
  444. HKEY hSourceSubKey, hDestinationSubKey;
  445. if (RegEnumKey(hSourceKey, EnumIndex++, ValueNameBuffer, MAXKEYNAME) !=
  446. ERROR_SUCCESS)
  447. break;
  448. // don't recursively copy the Profiles key into the profiles key.
  449. if (lstrcmpi(ValueNameBuffer, "Profiles") != 0)
  450. {
  451. if (RegOpenKey(hSourceKey, ValueNameBuffer, &hSourceSubKey) ==
  452. ERROR_SUCCESS)
  453. {
  454. if (RegCreateKey(hDestinationKey, ValueNameBuffer,
  455. &hDestinationSubKey) == ERROR_SUCCESS)
  456. {
  457. CopyRegistry(hSourceSubKey, hDestinationSubKey);
  458. RegCloseKey(hDestinationSubKey);
  459. }
  460. RegCloseKey(hSourceSubKey);
  461. }
  462. }
  463. }
  464. RegCloseKey(hSourceKey);
  465. }
  466. RegCloseKey(hDestinationKey);
  467. }
  468. }
  469. */
  470. }
  471. /*
  472. MU_ShutdownCurrentUser
  473. Do everything necessary to get the app to the point where
  474. calling CoDecrementInit will tear everything else down.
  475. */
  476. BOOL MU_ShutdownCurrentUser(void)
  477. {
  478. HWND hWnd, hNextWnd = NULL;
  479. BOOL bResult = true;
  480. LRESULT lResult;
  481. DWORD dwProcessId, dwWndProcessId;
  482. HINITREF hInitRef;
  483. /*
  484. g_pInstance->SetSwitchingUsers(true);
  485. dwProcessId = GetCurrentProcessId();
  486. g_pInstance->CoIncrementInit(0, "", &hInitRef);
  487. hWnd = GetTopWindow(NULL);
  488. if (g_pConMan->IsConnected())
  489. {
  490. if (IDNO == AthMessageBoxW(hWnd, MAKEINTRESOURCEW(idsSwitchUser),MAKEINTRESOURCEW(idsMaintainConnection),
  491. NULL, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON1 | MB_APPLMODAL))
  492. g_pConMan->Disconnect(hWnd, TRUE, FALSE, FALSE );
  493. }
  494. while (hWnd)
  495. {
  496. hNextWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
  497. GetWindowThreadProcessId(hWnd,&dwWndProcessId);
  498. if (dwProcessId == dwWndProcessId && IsWindowVisible(hWnd))
  499. {
  500. TCHAR szWndClassName[255];
  501. GetClassName( hWnd, szWndClassName, sizeof(szWndClassName));
  502. if (lstrcmp(szWndClassName, g_szDBNotifyWndProc) != 0 &&
  503. lstrcmp(szWndClassName, g_szDBListenWndProc) != 0)
  504. {
  505. lResult = SendMessage(hWnd, WM_CLOSE, 0, 0);
  506. // if the window is still there, something is wrong
  507. if(lResult != ERROR_SUCCESS || GetTopWindow(NULL) == hWnd)
  508. {
  509. Assert(GetTopWindow(NULL) != hWnd);
  510. return false;
  511. }
  512. }
  513. }
  514. hWnd = hNextWnd;
  515. }
  516. g_pInstance->CoDecrementInit(&hInitRef);
  517. */
  518. return bResult;
  519. }
  520. /*
  521. _GetRegRootForUserID
  522. HACK ALERT
  523. The proper way to store registry things with identities is to use the
  524. HKEY that is returned from IUserIdentity::OpenIdentityRegKey. This is
  525. here only because some old interfaces assume HKEY_CURRENT_USER. Those
  526. that do, need to be fixed. In the meantime, we have this
  527. */
  528. HRESULT _GetRegRootForUserID(GUID *puidUserId, LPSTR pszPath, DWORD cch)
  529. {
  530. HRESULT hr = S_OK;
  531. IUserIdentity *pIdentity = NULL;
  532. TCHAR szPath[MAX_PATH];
  533. HKEY hkey;
  534. TCHAR szUid[255];
  535. GUID uidIdentityId;
  536. Assert(pszPath);
  537. Assert(g_pIdMan);
  538. Assert(puidUserId);
  539. if (g_pIdMan == NULL)
  540. {
  541. hr = E_FAIL;
  542. goto exit;
  543. }
  544. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(puidUserId, &pIdentity)))
  545. goto exit;
  546. if (FAILED(hr = pIdentity->GetCookie(&uidIdentityId)))
  547. goto exit;
  548. AStringFromGUID(&uidIdentityId, szUid, 255);
  549. wnsprintf(pszPath, cch, "%s\\%s\\%s", "Identities", szUid, c_szRegRoot);
  550. exit:
  551. SafeRelease(pIdentity);
  552. return hr;
  553. }
  554. LPCTSTR MU_GetRegRoot()
  555. {
  556. if (*g_szRegRoot)
  557. return g_szRegRoot;
  558. if (FAILED(_GetRegRootForUserID(PGUIDCurrentOrDefault(), g_szRegRoot, ARRAYSIZE(g_szRegRoot))))
  559. _GetRegRootForUserID((GUID *)&UID_GIBC_DEFAULT_USER, g_szRegRoot, ARRAYSIZE(g_szRegRoot));
  560. return g_szRegRoot;
  561. }
  562. LPCSTR MU_GetCurrentIdentityName()
  563. {
  564. HRESULT hr;
  565. IUserIdentity *pIdentity = NULL;
  566. WCHAR szwName[CCH_USERNAME_MAX_LENGTH+1];
  567. Assert(g_pIdMan);
  568. if (g_pIdMan == NULL)
  569. return NULL;
  570. if (*g_szIdentityName)
  571. return g_szIdentityName;
  572. if (MU_CountUsers() == 1)
  573. g_szIdentityName[0] = 0;
  574. else
  575. {
  576. if (FAILED(hr = g_pIdMan->GetIdentityByCookie(PGUIDCurrentOrDefault(), &pIdentity)))
  577. goto exit;
  578. if (!pIdentity)
  579. goto exit;
  580. if (FAILED(hr = pIdentity->GetName(szwName, CCH_USERNAME_MAX_LENGTH)))
  581. goto exit;
  582. if (WideCharToMultiByte(CP_ACP, 0, szwName, -1, g_szIdentityName, CCH_USERNAME_MAX_LENGTH, NULL, NULL) == 0)
  583. {
  584. g_szIdentityName[0] = 0;
  585. goto exit;
  586. }
  587. }
  588. exit:
  589. SafeRelease(pIdentity);
  590. return g_szIdentityName;
  591. }
  592. void MU_ResetRegRoot()
  593. {
  594. RegCloseKey(g_hkeyIdentity);
  595. g_hkeyIdentity = HKEY_CURRENT_USER;
  596. g_szRegRoot[0] = 0;
  597. g_szIdentityName[0] = 0;
  598. g_dwIcwFlags = 0;
  599. }
  600. void MigrateOEMultiUserToIdentities(void)
  601. {
  602. TCHAR szProfilesPath[] = "Software\\Microsoft\\Outlook Express\\5.0\\Profiles";
  603. TCHAR szCheckKeyPath[] = "Software\\Microsoft\\Outlook Express\\5.0\\Shared Settings\\Setup";
  604. TCHAR szPath[MAX_PATH], szProfilePath[MAX_PATH];
  605. HKEY hOldKey, hOldSubkey, hNewTopKey, hNewOEKey, hNewIAMKey, hCheckKey = NULL;
  606. DWORD EnumIndex;
  607. DWORD cbKeyName, cUsers;
  608. DWORD dwType, dwValue, dwStatus, dwSize;
  609. CHAR KeyNameBuffer[1024];
  610. IPrivateIdentityManager *pPrivIdMgr;
  611. HRESULT hr;
  612. if (NULL == g_pIdMan)
  613. {
  614. hr = CoCreateInstance(CLSID_UserIdentityManager, NULL, CLSCTX_INPROC_SERVER, IID_IUserIdentityManager, (LPVOID *)&g_pIdMan);
  615. if (FAILED(hr))
  616. return;
  617. }
  618. Assert(g_pIdMan);
  619. if (FAILED(g_pIdMan->QueryInterface(IID_IPrivateIdentityManager, (void **)&pPrivIdMgr)))
  620. return;
  621. if (RegOpenKey(HKEY_CURRENT_USER, szProfilesPath, &hOldKey) == ERROR_SUCCESS)
  622. {
  623. dwStatus = RegCreateKey(HKEY_CURRENT_USER, szCheckKeyPath, &hCheckKey);
  624. dwSize = sizeof(dwValue);
  625. if (dwStatus != ERROR_SUCCESS ||
  626. (dwStatus = RegQueryValueEx(hCheckKey, "MigToLWP", NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) != ERROR_SUCCESS ||
  627. (1 != dwValue))
  628. {
  629. //
  630. // Copy all of the value names and their data.
  631. //
  632. dwStatus = RegQueryInfoKey(hOldKey, NULL, NULL, 0, &cUsers, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  633. EnumIndex = 0;
  634. while (TRUE && cUsers > 0)
  635. {
  636. cbKeyName = sizeof(KeyNameBuffer);
  637. if (RegEnumKey(hOldKey, EnumIndex++, KeyNameBuffer, cbKeyName) !=
  638. ERROR_SUCCESS)
  639. break;
  640. wnsprintf(szProfilePath, ARRAYSIZE(szProfilePath), "%s\\Application Data", KeyNameBuffer);
  641. if (ERROR_SUCCESS == RegOpenKey(hOldKey, szProfilePath, &hOldSubkey))
  642. {
  643. TCHAR szUserName[CCH_USERNAME_MAX_LENGTH+1];
  644. WCHAR szwUserName[CCH_USERNAME_MAX_LENGTH+1];
  645. IUserIdentity *pIdentity = NULL;
  646. dwSize = sizeof(szUserName);
  647. if ((dwStatus = RegQueryValueEx(hOldSubkey, "Current Username", NULL, &dwType, (LPBYTE)szUserName, &dwSize)) == ERROR_SUCCESS &&
  648. (0 != *szUserName))
  649. {
  650. if (MultiByteToWideChar(CP_ACP, 0, szUserName, -1, szwUserName, CCH_USERNAME_MAX_LENGTH) == 0)
  651. goto UserFailed;
  652. if (cUsers == 1)
  653. {
  654. if (FAILED(g_pIdMan->GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, &pIdentity)) || !pIdentity)
  655. goto UserFailed;
  656. }
  657. else
  658. {
  659. if (FAILED(pPrivIdMgr->CreateIdentity(szwUserName, &pIdentity)) || !pIdentity)
  660. goto UserFailed;
  661. }
  662. if (FAILED(pIdentity->OpenIdentityRegKey(KEY_ALL_ACCESS, &hNewTopKey)))
  663. goto UserFailed;
  664. if (ERROR_SUCCESS == RegCreateKey(hNewTopKey, c_szRegRoot, &hNewOEKey))
  665. {
  666. CopyRegistry(hOldSubkey, hNewOEKey);
  667. RegCloseKey(hNewOEKey);
  668. }
  669. // now copy the IAM settings
  670. wnsprintf(szProfilePath, ARRAYSIZE(szProfilePath), "%s\\Internet Accounts", KeyNameBuffer);
  671. RegCloseKey(hOldSubkey);
  672. hOldSubkey = NULL;
  673. if (ERROR_SUCCESS == RegOpenKey(hOldKey, szProfilePath, &hOldSubkey))
  674. {
  675. if (ERROR_SUCCESS == RegCreateKey(hNewTopKey, c_szInetAcctMgrRegKey, &hNewIAMKey))
  676. {
  677. CopyRegistry(hOldSubkey, hNewIAMKey);
  678. RegCloseKey(hNewIAMKey);
  679. }
  680. }
  681. UserFailed:
  682. RegCloseKey(hNewTopKey);
  683. SafeRelease(pIdentity);
  684. if (hOldSubkey)
  685. {
  686. RegCloseKey(hOldSubkey);
  687. hOldSubkey = NULL;
  688. }
  689. }
  690. }
  691. }
  692. dwValue = 1;
  693. RegSetValueEx(hCheckKey, "MigToLWP", 0, REG_DWORD, (BYTE *)&dwValue, sizeof(DWORD));
  694. }
  695. if (hCheckKey != NULL)
  696. RegCloseKey(hCheckKey);
  697. RegCloseKey(hOldKey);
  698. }
  699. pPrivIdMgr->Release();
  700. }
  701. BOOL MU_IdentitiesDisabled()
  702. {
  703. return g_fIdentitiesDisabled || (g_dwAthenaMode & MODE_NOIDENTITIES && !g_fPluralIDs);
  704. }
  705. void MU_UpdateIdentityMenus(HMENU hMenu)
  706. {
  707. DWORD cItems, dwIndex;
  708. MENUITEMINFO mii;
  709. TCHAR szLogoffString[255];
  710. TCHAR szRes[255];
  711. if (MU_IdentitiesDisabled())
  712. {
  713. // Delete the switch identity menu
  714. DeleteMenu(hMenu, ID_SWITCH_IDENTITY, MF_BYCOMMAND);
  715. DeleteMenu(hMenu, ID_EXIT_LOGOFF, MF_BYCOMMAND);
  716. // loop through the other menu items looking for logoff
  717. cItems = GetMenuItemCount(hMenu);
  718. mii.cbSize = sizeof(MENUITEMINFO);
  719. mii.fMask = MIIM_ID;
  720. for (dwIndex = cItems; dwIndex > 0; --dwIndex)
  721. {
  722. GetMenuItemInfo(hMenu, dwIndex, TRUE, &mii);
  723. // if this is the logoff item, delete it and the separator
  724. // line that follows
  725. if (mii.wID == ID_IDENTITIES)
  726. {
  727. DeleteMenu(hMenu, ID_IDENTITIES, MF_BYCOMMAND);
  728. DeleteMenu(hMenu, dwIndex, MF_BYPOSITION);
  729. break;
  730. }
  731. }
  732. }
  733. else
  734. {
  735. // Load a new menu string from the resources
  736. AthLoadString(idsLogoffFormat, szRes, ARRAYSIZE(szRes));
  737. // Format it
  738. wnsprintf(szLogoffString, ARRAYSIZE(szLogoffString), szRes, MU_GetCurrentIdentityName());
  739. // Splat it on the menu
  740. ModifyMenu(hMenu, ID_LOGOFF_IDENTITY, MF_BYCOMMAND | MF_STRING, ID_LOGOFF_IDENTITY, szLogoffString);
  741. }
  742. }
  743. void MU_NewIdentity(HWND hwnd)
  744. {
  745. if (g_pIdMan)
  746. {
  747. g_pIdMan->ManageIdentities(hwnd, UIMI_CREATE_NEW_IDENTITY);
  748. }
  749. }
  750. void MU_ManageIdentities(HWND hwnd)
  751. {
  752. if (g_pIdMan)
  753. {
  754. g_pIdMan->ManageIdentities(hwnd, 0);
  755. }
  756. }
  757. void MU_IdentityChanged()
  758. {
  759. // flush the cached name so we reload it
  760. *g_szIdentityName = 0;
  761. }
  762. HRESULT MU_Init(BOOL fDefaultId)
  763. {
  764. HRESULT hr = S_OK;
  765. g_fUsingDefaultId = fDefaultId;
  766. if (NULL == g_pIdMan)
  767. {
  768. hr = CoCreateInstance(CLSID_UserIdentityManager, NULL, CLSCTX_INPROC_SERVER, IID_IUserIdentityManager, (LPVOID *)&g_pIdMan);
  769. if (FAILED(hr))
  770. MU_ShowErrorMessage(g_hLocRes, GetDesktopWindow(), idsCantLoadMsident,idsAthenaTitle);
  771. }
  772. else
  773. g_pIdMan->AddRef();
  774. return hr;
  775. }
  776. void MU_Shutdown()
  777. {
  778. Assert(g_pIdMan);
  779. if (g_pIdMan == NULL)
  780. return;
  781. SafeIdentityRelease();
  782. }