identmgr.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 25k
Category:

Windows Kernel

Development Platform:

Visual C++

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