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.

1112 lines
30 KiB

  1. //
  2. // ident.cpp - implementation of CIdentity class
  3. //
  4. #include "private.h"
  5. #include "multiusr.h"
  6. #include "multiui.h"
  7. #include "strconst.h"
  8. #include "resource.h"
  9. #include "mluisup.h"
  10. extern HINSTANCE g_hInst;
  11. BOOL g_fReleasedMutex = true;
  12. //
  13. // Constructor / destructor
  14. //
  15. CUserIdentityManager::CUserIdentityManager()
  16. {
  17. m_cRef = 1;
  18. m_fWndRegistered = FALSE;
  19. m_hwnd = NULL;
  20. m_pAdviseRegistry = NULL;
  21. InitializeCriticalSection(&m_rCritSect);
  22. DllAddRef();
  23. }
  24. CUserIdentityManager::~CUserIdentityManager()
  25. {
  26. if (m_pAdviseRegistry)
  27. m_pAdviseRegistry->Release();
  28. DeleteCriticalSection(&m_rCritSect);
  29. DllRelease();
  30. }
  31. //
  32. // IUnknown members
  33. //
  34. STDMETHODIMP CUserIdentityManager::QueryInterface(
  35. REFIID riid, void **ppv)
  36. {
  37. if (NULL == ppv)
  38. {
  39. return E_INVALIDARG;
  40. }
  41. *ppv=NULL;
  42. // Validate requested interface
  43. if (IID_IUnknown == riid)
  44. {
  45. *ppv = (IUserIdentityManager *)this;
  46. }
  47. else if (IID_IUserIdentityManager == riid)
  48. {
  49. *ppv = (IUserIdentityManager *)this;
  50. }
  51. else if (IID_IConnectionPoint == riid)
  52. {
  53. *ppv = (IConnectionPoint *)this;
  54. }
  55. else if (IID_IPrivateIdentityManager == riid)
  56. {
  57. *ppv = (IPrivateIdentityManager *)this;
  58. }
  59. else if (IID_IPrivateIdentityManager2 == riid)
  60. {
  61. *ppv = (IPrivateIdentityManager2 *)this;
  62. }
  63. // Addref through the interface
  64. if (NULL != *ppv) {
  65. ((LPUNKNOWN)*ppv)->AddRef();
  66. return S_OK;
  67. }
  68. return E_NOINTERFACE;
  69. }
  70. STDMETHODIMP_(ULONG) CUserIdentityManager::AddRef()
  71. {
  72. return ++m_cRef;
  73. }
  74. STDMETHODIMP_(ULONG) CUserIdentityManager::Release()
  75. {
  76. if (0L != --m_cRef)
  77. return m_cRef;
  78. delete this;
  79. return 0L;
  80. }
  81. STDMETHODIMP CUserIdentityManager::CreateIdentity(WCHAR *pszName, IUserIdentity **ppIdentity)
  82. {
  83. return CreateIdentity2(pszName, NULL, ppIdentity);
  84. }
  85. STDMETHODIMP CUserIdentityManager::CreateIdentity2(WCHAR *pszName, WCHAR *pszPassword, IUserIdentity **ppIdentity)
  86. {
  87. CUserIdentity *pIdentity;
  88. HRESULT hr;
  89. TCHAR szName[CCH_IDENTITY_NAME_MAX_LENGTH+1];
  90. *ppIdentity = NULL;
  91. if (MU_IdentitiesDisabled())
  92. return E_IDENTITIES_DISABLED;
  93. if (WideCharToMultiByte(CP_ACP, 0, pszName, -1, szName, CCH_IDENTITY_NAME_MAX_LENGTH, NULL, NULL) == 0)
  94. return GetLastError();
  95. if (MU_UsernameExists(szName))
  96. return E_IDENTITY_EXISTS;
  97. pIdentity = new CUserIdentity;
  98. Assert(pIdentity);
  99. if (!pIdentity)
  100. return E_OUTOFMEMORY;
  101. hr = pIdentity->SetName(pszName);
  102. if (SUCCEEDED(hr))
  103. {
  104. if (pszPassword)
  105. {
  106. hr = pIdentity->SetPassword(pszPassword);
  107. }
  108. }
  109. if (SUCCEEDED(hr))
  110. {
  111. *ppIdentity = pIdentity;
  112. }
  113. else
  114. {
  115. pIdentity->Release();
  116. }
  117. PostMessage(HWND_BROADCAST, WM_IDENTITY_INFO_CHANGED, 0, IIC_IDENTITY_ADDED);
  118. return hr;
  119. }
  120. STDMETHODIMP CUserIdentityManager::ConfirmPassword(GUID *uidCookie, WCHAR *pszPassword)
  121. {
  122. TCHAR szPwd[CCH_USERPASSWORD_MAX_LENGTH+1];
  123. HRESULT hr = E_FAIL;
  124. USERINFO userInfo;
  125. if (WideCharToMultiByte(CP_ACP, 0, pszPassword, -1, szPwd, CCH_USERPASSWORD_MAX_LENGTH, NULL, NULL) == 0)
  126. return E_FAIL;
  127. if (MU_GetUserInfo(uidCookie, &userInfo))
  128. {
  129. if (userInfo.fPasswordValid)
  130. {
  131. if (!userInfo.fUsePassword)
  132. userInfo.szPassword[0] = 0;
  133. if (lstrcmp(szPwd, userInfo.szPassword) == 0)
  134. hr = S_OK;
  135. else
  136. hr = E_FAIL;
  137. }
  138. else
  139. {
  140. hr = E_FAIL;
  141. }
  142. }
  143. return hr;
  144. }
  145. STDMETHODIMP CUserIdentityManager::DestroyIdentity(GUID *uidCookie)
  146. {
  147. if (MU_IdentitiesDisabled())
  148. return E_IDENTITIES_DISABLED;
  149. return MU_DeleteUser(uidCookie);
  150. }
  151. STDMETHODIMP CUserIdentityManager::EnumIdentities(IEnumUserIdentity **ppEnumIdentity)
  152. {
  153. CEnumUserIdentity *pEnumIdentity;
  154. *ppEnumIdentity = NULL;
  155. pEnumIdentity = new CEnumUserIdentity;
  156. if (!pEnumIdentity)
  157. return E_OUTOFMEMORY;
  158. *ppEnumIdentity = pEnumIdentity;
  159. return S_OK;
  160. }
  161. STDMETHODIMP CUserIdentityManager::SetDefaultIdentity(GUID *puidCookie)
  162. {
  163. if (MU_IdentitiesDisabled())
  164. return E_IDENTITIES_DISABLED;
  165. return MU_MakeDefaultUser(puidCookie);
  166. }
  167. STDMETHODIMP CUserIdentityManager::GetDefaultIdentity(GUID *puidCookie)
  168. {
  169. if (MU_IdentitiesDisabled())
  170. return E_IDENTITIES_DISABLED;
  171. return MU_GetDefaultUserID(puidCookie) ? S_OK : S_FALSE;
  172. }
  173. STDMETHODIMP CUserIdentityManager::ManageIdentities(HWND hwndParent, DWORD dwFlags)
  174. {
  175. TCHAR szUsername[CCH_USERNAME_MAX_LENGTH+1];
  176. if (MU_IdentitiesDisabled())
  177. return E_IDENTITIES_DISABLED;
  178. *szUsername = 0;
  179. MU_ManageUsers(hwndParent, szUsername, dwFlags);
  180. // if the user created a new user and said they want to switch to them now,
  181. // we should do so.
  182. if (*szUsername)
  183. {
  184. BOOL fGotUser;
  185. USERINFO rUser;
  186. GUID uidUserID;
  187. HRESULT hr;
  188. fGotUser = MU_GetUserInfo(NULL, &rUser);
  189. if (!fGotUser)
  190. {
  191. *rUser.szUsername = 0;
  192. ZeroMemory(&rUser.uidUserID, sizeof(GUID));
  193. }
  194. MU_UsernameToUserId(szUsername, &uidUserID);
  195. if (FAILED(hr = _SwitchToUser(&rUser.uidUserID, &uidUserID)))
  196. {
  197. SetForegroundWindow(hwndParent);
  198. if (hr != E_USER_CANCELLED)
  199. MU_ShowErrorMessage(hwndParent, idsSwitchCancelled, idsSwitchCancelCaption);
  200. }
  201. }
  202. return S_OK;
  203. }
  204. STDMETHODIMP CUserIdentityManager::_PersistChangingIdentities()
  205. {
  206. HRESULT hr = E_FAIL;
  207. HKEY hKeyIdentities = NULL;
  208. if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities))
  209. {
  210. goto exit;
  211. }
  212. if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szOutgoingID, 0, REG_BINARY, (LPBYTE)&g_uidOldUserId, sizeof(GUID)))
  213. {
  214. goto exit;
  215. }
  216. if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szIncomingID, 0, REG_BINARY, (LPBYTE)&g_uidNewUserId, sizeof(GUID)))
  217. {
  218. goto exit;
  219. }
  220. if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szChanging, 0, REG_BINARY, (LPBYTE)&g_fNotifyComplete, sizeof(g_fNotifyComplete)))
  221. {
  222. goto exit;
  223. }
  224. hr = S_OK;
  225. exit:
  226. if (hKeyIdentities)
  227. {
  228. RegCloseKey(hKeyIdentities);
  229. }
  230. return hr;
  231. }
  232. STDMETHODIMP CUserIdentityManager::_LoadChangingIdentities()
  233. {
  234. HRESULT hr = E_FAIL;
  235. HKEY hKeyIdentities = NULL;
  236. DWORD dwType, dwSize;
  237. if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities))
  238. {
  239. goto exit;
  240. }
  241. dwType = REG_BINARY;
  242. dwSize = sizeof(GUID);
  243. if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szOutgoingID, 0, &dwType, (LPBYTE)&g_uidOldUserId, &dwSize))
  244. {
  245. goto exit;
  246. }
  247. dwSize = sizeof(GUID);
  248. if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szIncomingID, 0, &dwType, (LPBYTE)&g_uidNewUserId, &dwSize))
  249. {
  250. goto exit;
  251. }
  252. dwSize = sizeof(g_fNotifyComplete);
  253. if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szChanging, 0, &dwType, (LPBYTE)&g_fNotifyComplete, &dwSize))
  254. {
  255. goto exit;
  256. }
  257. hr = S_OK;
  258. exit:
  259. if (FAILED(hr))
  260. {
  261. g_uidOldUserId = GUID_NULL;
  262. g_uidNewUserId = GUID_NULL;
  263. g_fNotifyComplete = TRUE;
  264. }
  265. if (hKeyIdentities)
  266. {
  267. RegCloseKey(hKeyIdentities);
  268. }
  269. return hr;
  270. }
  271. STDMETHODIMP CUserIdentityManager::ClearChangingIdentities()
  272. {
  273. HRESULT hr = E_FAIL;
  274. HKEY hKeyIdentities = NULL;
  275. if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities))
  276. {
  277. goto exit;
  278. }
  279. RegDeleteValue(hKeyIdentities, c_szChanging);
  280. RegDeleteValue(hKeyIdentities, c_szIncomingID);
  281. RegDeleteValue(hKeyIdentities, c_szOutgoingID);
  282. hr = S_OK;
  283. exit:
  284. if (hKeyIdentities)
  285. {
  286. RegCloseKey(hKeyIdentities);
  287. }
  288. return hr;
  289. }
  290. STDMETHODIMP CUserIdentityManager::Logon(HWND hwndParent, DWORD dwFlags, IUserIdentity **ppIdentity)
  291. {
  292. CUserIdentity *pIdentity;
  293. HRESULT hr = E_FAIL;
  294. USERINFO rUser;
  295. GUID uidUserID, uidNewUserID;
  296. BOOL fGotUser;
  297. TCHAR szOldUsername[CCH_USERNAME_MAX_LENGTH+1], szLogoffName[CCH_USERNAME_MAX_LENGTH+1];
  298. TCHAR szRes[MAX_PATH];
  299. // if identities are disabled, always return the default identity.
  300. // if they are forcing the UI, return an error, otherwise succeed and
  301. // send the message back that identities are disabled.
  302. if (MU_IdentitiesDisabled())
  303. {
  304. if (!!(dwFlags & UIL_FORCE_UI))
  305. return E_IDENTITIES_DISABLED;
  306. hr = GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, ppIdentity);
  307. return (SUCCEEDED(hr) ? S_IDENTITIES_DISABLED : hr);
  308. }
  309. if (!g_hMutex)
  310. return E_UNEXPECTED;
  311. _LoadChangingIdentities();
  312. if (g_uidOldUserId != GUID_NULL || g_uidNewUserId != GUID_NULL)
  313. {
  314. // we are in the middle of a switch
  315. if (!g_fNotifyComplete)
  316. {
  317. // and we are not done checking to see if a switch is ok.
  318. if (!!(dwFlags & UIL_FORCE_UI)) //if its a force ui, then just fail.
  319. return E_IDENTITY_CHANGING;
  320. //otherwise, we need to do something here, but since they could be
  321. //calling Login from the notifier proc, this could create a deadlock,
  322. //but returning either the old or the new could be wrong. Return the
  323. //same error here unless we can come up with a better solution.
  324. return E_IDENTITY_CHANGING;
  325. }
  326. }
  327. DWORD dwWaitResult;
  328. dwWaitResult = WaitForSingleObject(g_hMutex, 5000);
  329. g_fReleasedMutex = false;
  330. if (dwWaitResult == WAIT_TIMEOUT)
  331. {
  332. char szMsg[255], szTitle[63];
  333. // someone else seems to have a login dialog up. Notify the user
  334. // about this problem and bail.
  335. if (!!(dwFlags & UIL_FORCE_UI))
  336. {
  337. MLLoadStringA(idsSwitchInProgressSwitch, szMsg, ARRAYSIZE(szMsg));
  338. MLLoadStringA(idsSwitchIdentities, szTitle, ARRAYSIZE(szTitle));
  339. }
  340. else
  341. {
  342. MLLoadStringA(idsSwitchInProgressLaunch, szMsg, ARRAYSIZE(szMsg));
  343. MLLoadStringA(idsIdentityLogin, szTitle, ARRAYSIZE(szTitle));
  344. }
  345. MessageBox(hwndParent, szMsg, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  346. return E_UNEXPECTED;
  347. }
  348. *ppIdentity = NULL;
  349. fGotUser = MU_GetUserInfo(NULL, &rUser);
  350. if (!fGotUser)
  351. {
  352. *rUser.szUsername = 0;
  353. ZeroMemory(&rUser.uidUserID, sizeof(GUID));
  354. }
  355. lstrcpy(szOldUsername, rUser.szUsername);
  356. // if we don't have to do the UI and there is a current
  357. // user, then just return that identity
  358. if (!(dwFlags & UIL_FORCE_UI) && fGotUser)
  359. {
  360. pIdentity = new CUserIdentity;
  361. if (!pIdentity)
  362. hr = E_OUTOFMEMORY;
  363. if (pIdentity && SUCCEEDED(hr = pIdentity->InitFromUsername(rUser.szUsername)))
  364. *ppIdentity = pIdentity;
  365. }
  366. else
  367. {
  368. if (0 == *rUser.szUsername)
  369. {
  370. GUID uidStart;
  371. MU_GetLoginOption(&uidStart);
  372. if (GUID_NULL != uidStart)
  373. {
  374. MU_GetUserInfo(&uidStart, &rUser);
  375. rUser.uidUserID = GUID_NULL;
  376. }
  377. }
  378. if (MU_Login(hwndParent, dwFlags, rUser.szUsername))
  379. {
  380. MLLoadStringA(idsLogoff, szLogoffName, sizeof(szLogoffName));
  381. if (lstrcmp(szLogoffName, rUser.szUsername) == 0)
  382. {
  383. MLLoadStringA(idsConfirmLogoff, szRes, sizeof(szRes));
  384. if (MessageBox(hwndParent, szRes, szLogoffName, MB_YESNO) == IDYES)
  385. {
  386. ReleaseMutex(g_hMutex);
  387. g_fReleasedMutex = true;
  388. Logoff(hwndParent);
  389. }
  390. }
  391. else
  392. {
  393. pIdentity = new CUserIdentity;
  394. if (pIdentity)
  395. {
  396. hr = pIdentity->InitFromUsername(rUser.szUsername);
  397. if (SUCCEEDED(hr))
  398. {
  399. pIdentity->GetCookie(&uidNewUserID);
  400. hr = _SwitchToUser(&rUser.uidUserID, &uidNewUserID);
  401. *ppIdentity = pIdentity;
  402. }
  403. if (FAILED(hr))
  404. {
  405. UINT iMsgId = idsSwitchCancelled;
  406. pIdentity->Release();
  407. *ppIdentity = NULL;
  408. SetForegroundWindow(hwndParent);
  409. // could switch on some error codes to set iMsgId to
  410. // other error messages. For now, skip showing the
  411. // message if a user did the cancelling
  412. if (hr != E_USER_CANCELLED)
  413. MU_ShowErrorMessage(hwndParent, iMsgId, idsSwitchCancelCaption);
  414. }
  415. }
  416. }
  417. }
  418. else
  419. hr = E_USER_CANCELLED;
  420. }
  421. if (!g_fReleasedMutex)
  422. ReleaseMutex(g_hMutex);
  423. return hr;
  424. }
  425. STDMETHODIMP CUserIdentityManager::Logoff(HWND hwndParent)
  426. {
  427. GUID uidToID = GUID_NULL;
  428. HRESULT hr;
  429. USERINFO rUser;
  430. BOOL fGotUser;
  431. if (!g_hMutex)
  432. return E_UNEXPECTED;
  433. DWORD dwWaitResult;
  434. dwWaitResult = WaitForSingleObject(g_hMutex, INFINITE);
  435. if (dwWaitResult != WAIT_OBJECT_0)
  436. return E_UNEXPECTED;
  437. fGotUser = MU_GetUserInfo(NULL, &rUser);
  438. if (!fGotUser)
  439. rUser.uidUserID = GUID_NULL;
  440. // switch to the null user
  441. hr = _SwitchToUser(&rUser.uidUserID, &uidToID);
  442. if (FAILED(hr))
  443. {
  444. UINT iMsgId = idsLogoutCancelled;
  445. SetForegroundWindow(hwndParent);
  446. // could switch on some error codes to set iMsgId to
  447. // other error messages. For now, skip showing the
  448. // message if a user did the cancelling
  449. if (hr != E_USER_CANCELLED)
  450. MU_ShowErrorMessage(hwndParent, iMsgId, idsSwitchCancelCaption);
  451. }
  452. ReleaseMutex(g_hMutex);
  453. return hr;
  454. }
  455. STDMETHODIMP CUserIdentityManager::_SwitchToUser(GUID *puidFromUser, GUID *puidToUser)
  456. {
  457. TCHAR szUsername[CCH_USERNAME_MAX_LENGTH+1] = "";
  458. HRESULT hr;
  459. // switching to the same user is automatically OK.
  460. if (*puidFromUser == *puidToUser)
  461. return S_OK;
  462. // Set up the from and to users
  463. g_uidOldUserId = *puidFromUser;
  464. g_uidNewUserId = *puidToUser;
  465. g_fNotifyComplete = FALSE;
  466. _PersistChangingIdentities();
  467. if (*puidToUser != GUID_NULL)
  468. MU_UserIdToUsername(puidToUser, szUsername, CCH_USERNAME_MAX_LENGTH);
  469. // Notify window's that a switch is coming
  470. if (SUCCEEDED(hr = _QueryProcessesCanSwitch()))
  471. {
  472. if (SUCCEEDED(hr = MU_SwitchToUser(szUsername)))
  473. {
  474. if (!g_fReleasedMutex)
  475. {
  476. g_fReleasedMutex = true;
  477. g_fNotifyComplete = true;
  478. ReleaseMutex(g_hMutex);
  479. }
  480. _NotifyIdentitiesSwitched();
  481. }
  482. }
  483. g_fNotifyComplete = TRUE;
  484. // clear these back out again
  485. g_uidOldUserId = GUID_NULL;
  486. g_uidNewUserId = GUID_NULL;
  487. ClearChangingIdentities();
  488. return hr;
  489. }
  490. STDMETHODIMP CUserIdentityManager::GetIdentityByCookie(GUID *uidCookie, IUserIdentity **ppIdentity)
  491. {
  492. CUserIdentity *pIdentity;
  493. HRESULT hr = E_IDENTITY_NOT_FOUND;
  494. GUID uidUserCookie = *uidCookie;
  495. *ppIdentity = NULL;
  496. if (MU_IdentitiesDisabled())
  497. {
  498. // if disabled, they can only get the default identity.
  499. // if asking for the current, they will get the defalt.
  500. // if asking for default by the constant or the default's guid, then succeed.
  501. // otherwise return an error.
  502. if (!MU_GetDefaultUserID(&uidUserCookie))
  503. return E_IDENTITY_NOT_FOUND;
  504. if (UID_GIBC_CURRENT_USER == uidUserCookie)
  505. uidUserCookie = UID_GIBC_DEFAULT_USER;
  506. if (!(uidUserCookie == uidUserCookie || UID_GIBC_DEFAULT_USER == uidUserCookie))
  507. return E_IDENTITIES_DISABLED;
  508. }
  509. if (uidUserCookie == UID_GIBC_DEFAULT_USER)
  510. {
  511. if (!MU_GetDefaultUserID(&uidUserCookie))
  512. return E_IDENTITY_NOT_FOUND;
  513. }
  514. else if (uidUserCookie == UID_GIBC_CURRENT_USER)
  515. {
  516. if (!MU_GetCurrentUserID(&uidUserCookie))
  517. return E_NO_CURRENT_IDENTITY;
  518. }
  519. else if (uidUserCookie == UID_GIBC_OUTGOING_USER)
  520. {
  521. _LoadChangingIdentities();
  522. if (g_uidOldUserId == GUID_NULL)
  523. return E_IDENTITY_NOT_FOUND;
  524. else
  525. uidUserCookie = g_uidOldUserId;
  526. }
  527. else if (uidUserCookie == UID_GIBC_INCOMING_USER)
  528. {
  529. _LoadChangingIdentities();
  530. if (g_uidNewUserId == GUID_NULL)
  531. return E_IDENTITY_NOT_FOUND;
  532. else
  533. uidUserCookie = g_uidNewUserId;
  534. }
  535. pIdentity = new CUserIdentity;
  536. if (pIdentity)
  537. {
  538. hr = pIdentity->InitFromCookie(&uidUserCookie);
  539. if (SUCCEEDED(hr))
  540. *ppIdentity = pIdentity;
  541. else
  542. {
  543. // Cleanup
  544. delete pIdentity;
  545. }
  546. }
  547. return hr;
  548. }
  549. STDMETHODIMP CUserIdentityManager::GetConnectionInterface(IID *pIID)
  550. {
  551. return E_NOTIMPL;
  552. }
  553. STDMETHODIMP CUserIdentityManager::GetConnectionPointContainer(IConnectionPointContainer **ppCPC)
  554. {
  555. *ppCPC = NULL;
  556. return E_NOTIMPL;
  557. }
  558. STDMETHODIMP CUserIdentityManager::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
  559. {
  560. HRESULT hr;
  561. EnterCriticalSection(&m_rCritSect);
  562. AddRef();
  563. if (!m_pAdviseRegistry)
  564. m_pAdviseRegistry = new CNotifierList;
  565. Assert(m_pAdviseRegistry);
  566. if (m_pAdviseRegistry)
  567. {
  568. if (!m_fWndRegistered)
  569. _CreateWindowClass();
  570. hr = m_pAdviseRegistry->Add(pUnkSink, pdwCookie);
  571. }
  572. else
  573. hr = E_OUTOFMEMORY;
  574. LeaveCriticalSection(&m_rCritSect);
  575. return hr;
  576. }
  577. STDMETHODIMP CUserIdentityManager::Unadvise(DWORD dwCookie)
  578. {
  579. HRESULT hr;
  580. EnterCriticalSection(&m_rCritSect);
  581. if (m_pAdviseRegistry)
  582. {
  583. hr = m_pAdviseRegistry->RemoveCookie(dwCookie);
  584. }
  585. else
  586. hr = E_FAIL;
  587. LeaveCriticalSection(&m_rCritSect);
  588. Release();
  589. return hr;
  590. }
  591. STDMETHODIMP CUserIdentityManager::EnumConnections(IEnumConnections **ppEnum)
  592. {
  593. *ppEnum = NULL;
  594. return E_NOTIMPL;
  595. }
  596. STDMETHODIMP CUserIdentityManager::QuerySwitchIdentities()
  597. {
  598. HRESULT hr = S_OK;
  599. DWORD dwLength, dwIndex;
  600. if (!m_pAdviseRegistry)
  601. return S_OK;
  602. TraceCall("Identity - CUserIdentityManager::QuerySwitchIdentities");
  603. dwLength = m_pAdviseRegistry->GetLength();
  604. for (dwIndex = 0; dwIndex < dwLength; dwIndex++)
  605. {
  606. IUnknown *punk;
  607. IIdentityChangeNotify *pICNotify;
  608. if (SUCCEEDED(m_pAdviseRegistry->GetAtIndex(dwIndex, &punk)) && punk)
  609. {
  610. if (SUCCEEDED(punk->QueryInterface(IID_IIdentityChangeNotify, (void **)&pICNotify)) && pICNotify)
  611. {
  612. if (FAILED(hr = pICNotify->QuerySwitchIdentities()))
  613. {
  614. punk->Release();
  615. pICNotify->Release();
  616. goto exit;
  617. }
  618. pICNotify->Release();
  619. }
  620. punk->Release();
  621. }
  622. }
  623. exit:
  624. return hr;
  625. }
  626. STDMETHODIMP CUserIdentityManager::NotifySwitchIdentities()
  627. {
  628. HRESULT hr = S_OK;
  629. DWORD dwLength, dwIndex;
  630. if (!m_pAdviseRegistry)
  631. return S_OK;
  632. TraceCall("Identity - CUserIdentityManager::NotifySwitchIdentities");
  633. dwLength = m_pAdviseRegistry->GetLength();
  634. for (dwIndex = 0; dwIndex < dwLength; dwIndex++)
  635. {
  636. IUnknown *punk;
  637. IIdentityChangeNotify *pICNotify;
  638. if (SUCCEEDED(m_pAdviseRegistry->GetAtIndex(dwIndex, &punk)) && punk)
  639. {
  640. if (SUCCEEDED(punk->QueryInterface(IID_IIdentityChangeNotify, (void **)&pICNotify)) && pICNotify)
  641. {
  642. if (FAILED(hr = pICNotify->SwitchIdentities()))
  643. {
  644. punk->Release();
  645. pICNotify->Release();
  646. goto exit;
  647. }
  648. pICNotify->Release();
  649. }
  650. punk->Release();
  651. }
  652. }
  653. exit:
  654. return hr;
  655. }
  656. STDMETHODIMP CUserIdentityManager::_QueryProcessesCanSwitch()
  657. {
  658. HWND hWnd, hNextWnd = NULL;
  659. LRESULT lResult;
  660. HWND *prghwnd = NULL;
  661. DWORD chwnd = 0, cAllocHwnd = 0, dw;
  662. HRESULT hr;
  663. TraceCall("Identity - CUserIdentityManager::_QueryProcessesCanSwitch");
  664. cAllocHwnd = 10;
  665. if (!MemAlloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND)))
  666. return E_OUTOFMEMORY;
  667. hWnd = GetTopWindow(NULL);
  668. while (hWnd)
  669. {
  670. hNextWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
  671. if (!IsWindowVisible(hWnd))
  672. {
  673. TCHAR szWndClassName[255];
  674. GetClassName(hWnd, szWndClassName, sizeof(szWndClassName));
  675. if (lstrcmp(szWndClassName, c_szNotifyWindowClass) == 0)
  676. {
  677. if (chwnd == cAllocHwnd)
  678. {
  679. cAllocHwnd += 10;
  680. if (!MemRealloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND)))
  681. {
  682. hr = E_OUTOFMEMORY;
  683. goto exit;
  684. }
  685. }
  686. prghwnd[chwnd++] = hWnd;
  687. }
  688. }
  689. hWnd = hNextWnd;
  690. }
  691. hr = S_OK;
  692. for (dw = 0; dw < chwnd; dw++)
  693. {
  694. if (IsWindow(prghwnd[dw]))
  695. {
  696. lResult = SendMessage(prghwnd[dw], WM_QUERY_IDENTITY_CHANGE, 0, 0);
  697. if (FAILED((HRESULT)lResult))
  698. {
  699. hr = (HRESULT)lResult;
  700. goto exit;
  701. }
  702. }
  703. }
  704. exit:
  705. MemFree(prghwnd);
  706. prghwnd = NULL;
  707. return hr;
  708. }
  709. STDMETHODIMP CUserIdentityManager::_NotifyIdentitiesSwitched()
  710. {
  711. HWND hWnd, hNextWnd = NULL;
  712. LRESULT lResult;
  713. HWND *prghwnd = NULL;
  714. DWORD chwnd = 0, cAllocHwnd = 0, dw;
  715. TraceCall("Identity - CUserIdentityManager::_NotifyIdentitiesSwitched");
  716. cAllocHwnd = 10;
  717. if (!MemAlloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND)))
  718. return E_OUTOFMEMORY;
  719. hWnd = GetTopWindow(NULL);
  720. while (hWnd)
  721. {
  722. hNextWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
  723. if (!IsWindowVisible(hWnd))
  724. {
  725. TCHAR szWndClassName[255];
  726. GetClassName(hWnd, szWndClassName, sizeof(szWndClassName));
  727. if (lstrcmp(szWndClassName, c_szNotifyWindowClass) == 0)
  728. {
  729. if (chwnd == cAllocHwnd)
  730. {
  731. cAllocHwnd += 10;
  732. if (!MemRealloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND)))
  733. goto exit;
  734. }
  735. prghwnd[chwnd++] = hWnd;
  736. }
  737. }
  738. hWnd = hNextWnd;
  739. }
  740. for (dw = 0; dw < chwnd; dw++)
  741. {
  742. DWORD_PTR dwResult;
  743. if (IsWindow(prghwnd[dw]))
  744. // lResult = PostMessage(prghwnd[dw], WM_IDENTITY_CHANGED, 0, 0); //Raid 48054
  745. SendMessageTimeout(prghwnd[dw], WM_IDENTITY_CHANGED, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 1500, &dwResult);
  746. }
  747. exit:
  748. MemFree(prghwnd);
  749. prghwnd = NULL;
  750. return S_OK;
  751. }
  752. STDMETHODIMP CUserIdentityManager::_CreateWindowClass()
  753. {
  754. WNDCLASS wc;
  755. if (!m_fWndRegistered) /*set up window class and register it */
  756. {
  757. wc.lpszClassName = c_szNotifyWindowClass;
  758. wc.hInstance = g_hInst;
  759. wc.lpfnWndProc = CUserIdentityManager::WndProc;
  760. wc.hCursor = NULL;
  761. wc.hIcon = NULL;
  762. wc.lpszMenuName = NULL;
  763. wc.hbrBackground = NULL;
  764. wc.style = CS_DBLCLKS;
  765. wc.cbClsExtra = 0;
  766. wc.cbWndExtra = 0;
  767. if (!RegisterClassA(&wc))
  768. return E_FAIL;
  769. m_fWndRegistered = TRUE;
  770. }
  771. return S_OK;
  772. }
  773. LRESULT CALLBACK CUserIdentityManager::WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
  774. {
  775. CNotifierList *pList = NULL;
  776. HRESULT hr;
  777. if (messg == WM_QUERY_IDENTITY_CHANGE ||
  778. messg == WM_IDENTITY_CHANGED ||
  779. messg == WM_IDENTITY_INFO_CHANGED)
  780. {
  781. #if defined(DEBUG)
  782. DebugStrf("Identity - CUserIdentityManager::WndProc() called for notification.\r\n");
  783. #endif
  784. pList = (CNotifierList *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  785. if (pList)
  786. {
  787. hr = pList->SendNotification(messg, (DWORD)lParam);
  788. return hr;
  789. }
  790. }
  791. else
  792. {
  793. switch(messg)
  794. {
  795. case WM_CREATE:
  796. LPCREATESTRUCT pcs;
  797. pcs = (LPCREATESTRUCT)lParam;
  798. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LRESULT)pcs->lpCreateParams);
  799. return(DefWindowProc(hWnd, messg, wParam, lParam));
  800. break;
  801. /*
  802. case WM_QUERY_IDENTITY_CHANGE:
  803. case WM_IDENTITY_CHANGED:
  804. case WM_IDENTITY_INFO_CHANGED:
  805. DebugStrf("Identity - CUserIdentityManager::WndProc() called for notification.\r\n");
  806. pList = (CNotifierList *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
  807. if (pList)
  808. {
  809. hr = pList->SendNotification(messg, (DWORD)lParam);
  810. return hr;
  811. }
  812. break;
  813. */
  814. case WM_CLOSE:
  815. SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
  816. return(DefWindowProc(hWnd, messg, wParam, lParam));
  817. break;
  818. default:
  819. return(DefWindowProc(hWnd, messg, wParam, lParam));
  820. }
  821. }
  822. return 0;
  823. }
  824. //----------------------------------------------------------------------------
  825. // Logon the specified user.
  826. // - Checks password
  827. //----------------------------------------------------------------------------
  828. STDMETHODIMP CUserIdentityManager::LogonAs(WCHAR *pszName, WCHAR *pszPassword, IUserIdentity **ppIdentity)
  829. {
  830. CUserIdentity *pIdentity;
  831. HRESULT hr = E_FAIL;
  832. USERINFO rUser;
  833. GUID uidNewUserID;
  834. BOOL fGotUser;
  835. TCHAR szName[CCH_USERNAME_MAX_LENGTH+1];
  836. if (WideCharToMultiByte(CP_ACP, 0, pszName, -1, szName, CCH_USERNAME_MAX_LENGTH, NULL, NULL) == 0)
  837. {
  838. return E_FAIL;
  839. }
  840. // if identities are disabled, always return the default identity.
  841. if (MU_IdentitiesDisabled())
  842. {
  843. hr = GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, ppIdentity);
  844. return (SUCCEEDED(hr) ? S_IDENTITIES_DISABLED : hr);
  845. }
  846. if (!g_hMutex)
  847. return E_UNEXPECTED;
  848. if (g_uidOldUserId != GUID_NULL || g_uidOldUserId != GUID_NULL)
  849. {
  850. // we are in the middle of a switch
  851. if (!g_fNotifyComplete)
  852. {
  853. return E_IDENTITY_CHANGING;
  854. }
  855. }
  856. *ppIdentity = NULL;
  857. //
  858. // Grab info on the current user
  859. //
  860. fGotUser = MU_GetUserInfo(NULL, &rUser);
  861. if (!fGotUser)
  862. {
  863. *rUser.szUsername = 0;
  864. ZeroMemory(&rUser.uidUserID, sizeof(GUID));
  865. }
  866. if (0 == *rUser.szUsername)
  867. {
  868. GUID uidStart;
  869. MU_GetLoginOption(&uidStart);
  870. if (GUID_NULL != uidStart)
  871. {
  872. MU_GetUserInfo(&uidStart, &rUser);
  873. rUser.uidUserID = GUID_NULL;
  874. }
  875. }
  876. pIdentity = new CUserIdentity;
  877. if (pIdentity)
  878. {
  879. hr = pIdentity->InitFromUsername(szName);
  880. if (SUCCEEDED(hr))
  881. {
  882. pIdentity->GetCookie(&uidNewUserID);
  883. hr= ConfirmPassword(&uidNewUserID, pszPassword);
  884. if (SUCCEEDED(hr))
  885. {
  886. hr = _SwitchToUser(&rUser.uidUserID, &uidNewUserID);
  887. if (SUCCEEDED(hr))
  888. {
  889. *ppIdentity = pIdentity;
  890. }
  891. else
  892. {
  893. UINT iMsgId = idsSwitchCancelled;
  894. pIdentity->Release();
  895. *ppIdentity = NULL;
  896. // could switch on some error codes to set iMsgId to
  897. // other error messages. For now, skip showing the
  898. // message if a user did the cancelling
  899. if (hr != E_USER_CANCELLED)
  900. MU_ShowErrorMessage(NULL, iMsgId, idsSwitchCancelCaption);
  901. }
  902. } // ConfirmPassword()
  903. } // InitFromUsername()
  904. }
  905. if (!g_fReleasedMutex)
  906. ReleaseMutex(g_hMutex);
  907. return hr;
  908. }