#include "private.h" #include "multiusr.h" UINT WM_IDENTITY_CHANGED; UINT WM_QUERY_IDENTITY_CHANGE; UINT WM_IDENTITY_INFO_CHANGED; extern "C" int _fltused = 0; // define this so that floats and doubles don't bring in the CRT // Count number of objects and number of locks. ULONG g_cObj=0; ULONG g_cLock=0; // DLL Instance handle HINSTANCE g_hInst=0; // mutex for preventing logon re-entrancy HANDLE g_hMutex = NULL; #define IDENTITY_LOGIN_VALUE 0x00098053 #define DEFINE_STRING_CONSTANTS #include "StrConst.h" #define MLUI_SUPPORT #define MLUI_INIT #include "mluisup.h" BOOL g_fNotifyComplete = TRUE; GUID g_uidOldUserId = {0x0}; GUID g_uidNewUserId = {0x0}; TCHAR szHKCUPolicyPath[] = "Software\\Microsoft\\Outlook Express\\Identities"; void FixMissingIdentityNames(); void UnloadPStore(); PSECURITY_DESCRIPTOR CreateSd(void); // This is needed so we can link to libcmt.dll, because floating-point // initialization code is required. void __cdecl main() { } #ifdef DISABIDENT void DisableOnFirstRun(void) { // disable identities in Whistler HKEY hKey = NULL; DWORD dwVal = 0; DWORD dwType = 0; ULONG cbData = sizeof(DWORD); OSVERSIONINFO OSInfo = {0}; TCHAR szPolicyPath[] = "Identities"; TCHAR szPolicyKey[] = "Locked Down"; TCHAR szFirstRun[] = "FirstRun"; TCHAR szRegisteredVersion[] = "RegisteredVersion"; OSInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&OSInfo); if((OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (OSInfo.dwMajorVersion >= 5)) { if(!(((OSInfo.dwMajorVersion == 5) && (OSInfo.dwMinorVersion > 0)) || (OSInfo.dwMajorVersion > 5))) return; } else return; // No disabling on Win 9x and NT4 // Check: first time run? if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szHKCUPolicyPath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { RegQueryValueEx(hKey, szRegisteredVersion, NULL, &dwType, (LPBYTE) &dwVal, &cbData); RegCloseKey(hKey); if(dwVal != OSInfo.dwBuildNumber) return; // already checked. } else return; if (RegCreateKeyEx(HKEY_CURRENT_USER, szPolicyPath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { RegQueryValueEx(hKey, szFirstRun, NULL, &dwType, (LPBYTE) &dwVal, &cbData); if(dwVal != 1) { dwVal = 1; RegSetValueEx(hKey, szFirstRun, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData); } else { RegCloseKey(hKey); return; // already checked. } } else return; if(MU_CountUsers() < 2) RegSetValueEx(hKey, szPolicyKey, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData); RegCloseKey(hKey); } #endif // DISABIDENT ////////////////////////////////////////////////////////////////////////// // // DLL entry point // ////////////////////////////////////////////////////////////////////////// EXTERN_C BOOL WINAPI LibMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { WM_IDENTITY_CHANGED= RegisterWindowMessage("WM_IDENTITY_CHANGED"); WM_QUERY_IDENTITY_CHANGE= RegisterWindowMessage("WM_QUERY_IDENTITY_CHANGE"); WM_IDENTITY_INFO_CHANGED= RegisterWindowMessage("WM_IDENTITY_INFO_CHANGED"); switch (ulReason) { case DLL_PROCESS_ATTACH: // MessageBox(NULL, "Debug", "Debug", MB_OK); SHFusionInitializeFromModule(hInstance); MLLoadResources(hInstance, TEXT("msidntld.dll")); if (MLGetHinst() == NULL) return FALSE; if (g_hMutex == NULL) { SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR psd; psd = CreateSd(); if (psd) { sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = psd; sa.bInheritHandle = TRUE; g_hMutex = CreateMutex(&sa, FALSE, "MSIdent Logon"); LocalFree(psd); } else // in the worst case drop down to unshared object g_hMutex = CreateMutex(NULL, FALSE, "MSIdent Logon"); if (g_hMutex == NULL) // Try to open mutex, if we cannot create mutex IE6 32769 g_hMutex = OpenMutex(MUTEX_MODIFY_STATE, FALSE, "MSIdent Logon"); if (GetLastError() != ERROR_ALREADY_EXISTS) { GUID uidStart; USERINFO uiLogin; #ifdef DISABIDENT DisableOnFirstRun(); #endif // DISABIDENT // in case something got stuck in a switch, wipe it out here. CUserIdentityManager::ClearChangingIdentities(); FixMissingIdentityNames(); // we are the first instance to come up. // may need to reset the last user..... if (GetProp(GetDesktopWindow(),"IDENTITY_LOGIN") != (HANDLE)IDENTITY_LOGIN_VALUE) { _MigratePasswords(); MU_GetLoginOption(&uidStart); // if there is a password on this identity, we can't auto start as them if (uidStart != GUID_NULL && MU_GetUserInfo(&uidStart, &uiLogin) && (uiLogin.fUsePassword || !uiLogin.fPasswordValid)) { uidStart = GUID_NULL; } if (uidStart == GUID_NULL) { MU_SwitchToUser(""); SetProp(GetDesktopWindow(),"IDENTITY_LOGIN", (HANDLE)IDENTITY_LOGIN_VALUE); } else { if(MU_GetUserInfo(&uidStart, &uiLogin)) MU_SwitchToUser(uiLogin.szUsername); else MU_SwitchToUser(""); } SetProp(GetDesktopWindow(),"IDENTITY_LOGIN", (HANDLE)IDENTITY_LOGIN_VALUE); } } } DisableThreadLibraryCalls(hInstance); g_hInst = hInstance; break; case DLL_PROCESS_DETACH: MLFreeResources(hInstance); UnloadPStore(); CloseHandle(g_hMutex); g_hMutex = NULL; SHFusionUninitialize(); break; } return TRUE; } ////////////////////////////////////////////////////////////////////////// // // Standard OLE entry points // ////////////////////////////////////////////////////////////////////////// // Class factory - // For classes with no special needs these macros should take care of it. // If your class needs some special stuff just to get the ball rolling, // implement your own CreateInstance method. (ala, CConnectionAgent) #define DEFINE_CREATEINSTANCE(cls, iface) \ HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \ { \ *ppunk = (iface *)new cls; \ return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \ } #define DEFINE_AGGREGATED_CREATEINSTANCE(cls, iface) \ HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \ { \ *ppunk = (iface *)new cls(punkOuter); \ return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \ } DEFINE_CREATEINSTANCE(CUserIdentityManager, IUserIdentityManager) const CFactoryData g_FactoryData[] = { { &CLSID_UserIdentityManager, CUserIdentityManager_CreateInstance, 0 } }; HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { HRESULT hr = S_OK; IUnknown *punk = NULL; *ppv = NULL; MU_Init(); // Validate request for (int i = 0; i < ARRAYSIZE(g_FactoryData); i++) { if (rclsid == *g_FactoryData[i].m_pClsid) { punk = new CClassFactory(&g_FactoryData[i]); break; } } if (ARRAYSIZE(g_FactoryData) <= i) { hr = CLASS_E_CLASSNOTAVAILABLE; } else if (NULL == punk) { hr = E_OUTOFMEMORY; } else { hr = punk->QueryInterface(riid, ppv); punk->Release(); } return hr; } STDAPI DllCanUnloadNow(void) { // check objects and locks return (0L == DllGetRef() && 0L == DllGetLock()) ? S_OK : S_FALSE; } ////////////////////////////////////////////////////////////////////////// // // Autoregistration entry points // ////////////////////////////////////////////////////////////////////////// HRESULT CallRegInstall(LPSTR szSection) { HRESULT hr = E_FAIL; char szDll[MAX_PATH]; int cch; STRENTRY seReg[2]; STRTABLE stReg; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); if (hinstAdvPack) { REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, achREGINSTALL); if (pfnri) { // Get our location GetModuleFileName(g_hInst, szDll, sizeof(szDll)); // Setup special registration stuff // Do this instead of relying on _SYS_MOD_PATH which loses spaces under '95 stReg.cEntries = 0; seReg[stReg.cEntries].pszName = "SYS_MOD_PATH"; seReg[stReg.cEntries].pszValue = szDll; stReg.cEntries++; stReg.pse = seReg; hr = pfnri(g_hInst, szSection, &stReg); } FreeLibrary(hinstAdvPack); } return hr; } STDAPI DllRegisterServer(void) { // Delete any old registration entries, then add the new ones. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); HKEY hKey = NULL; DWORD dwVal = 1; ULONG cbData = sizeof(DWORD); OSVERSIONINFO OSInfo = {0}; TCHAR szPolicyPath[] = "Identities"; TCHAR szRegisteredVersion[] = "RegisteredVersion"; TCHAR szPolPath[] = "Software\\Policies\\Microsoft\\Windows\\CurrentVersion\\Identities"; TCHAR szPolicyKey[] = "Locked Down"; CallRegInstall("Reg"); if (hinstAdvPack) { FreeLibrary(hinstAdvPack); } #ifdef DISABIDENT OSInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&OSInfo); if((OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (OSInfo.dwMajorVersion >= 5)) { if(!(((OSInfo.dwMajorVersion == 5) && (OSInfo.dwMinorVersion > 0)) || (OSInfo.dwMajorVersion > 5))) return NOERROR; } else return NOERROR; // No disable for Win9x // Set registration value if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szHKCUPolicyPath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { dwVal = OSInfo.dwBuildNumber; RegSetValueEx(hKey, szRegisteredVersion, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData); RegCloseKey(hKey); } #endif // DISABIDENT // DISABLING identities in Win64 #ifdef _WIN64 // Set registration value if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szPolPath, 0, NULL, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hKey, NULL) == ERROR_SUCCESS) { RegSetValueEx(hKey, szPolicyKey, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData); } #endif // _WIN64 return NOERROR; } STDAPI DllUnregisterServer(void) { return NOERROR; } PSECURITY_DESCRIPTOR CreateSd(void) { PSID AuthenticatedUsers = NULL; PSID BuiltInAdministrators = NULL; PSID PowerUsers = NULL; PSECURITY_DESCRIPTOR RetVal = NULL; PSECURITY_DESCRIPTOR Sd = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; ULONG AclSize; // // Each RID represents a sub-unit of the authority. Two of the SIDs we // want to build, Local Administrators, and Power Users, are in the "built // in" domain. The other SID, for Authenticated users, is based directly // off of the authority. // // For examples of other useful SIDs consult the list in // \nt\public\sdk\inc\ntseapi.h. // if (!AllocateAndInitializeSid(&NtAuthority, 2, // 2 sub-authorities SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0, &BuiltInAdministrators)) goto ErrorExit; if (!AllocateAndInitializeSid(&NtAuthority, 2, // 2 sub-authorities SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0,0,0,0,0,0, &PowerUsers)) goto ErrorExit; if (!AllocateAndInitializeSid(&NtAuthority, 1, // 1 sub-authority SECURITY_AUTHENTICATED_USER_RID, 0,0,0,0,0,0,0, &AuthenticatedUsers)) goto ErrorExit; // // Calculate the size of and allocate a buffer for the DACL, we need // this value independently of the total alloc size for ACL init. // // "- sizeof (ULONG)" represents the SidStart field of the // ACCESS_ALLOWED_ACE. Since we're adding the entire length of the // SID, this field is counted twice. // AclSize = sizeof (ACL) + (3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) + GetLengthSid(AuthenticatedUsers) + GetLengthSid(BuiltInAdministrators) + GetLengthSid(PowerUsers); Sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize); if (Sd) { ACL *Acl; Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeAcl(Acl, AclSize, ACL_REVISION)) { // Error } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, SYNCHRONIZE | MUTEX_MODIFY_STATE, AuthenticatedUsers)) { // Failed to build the ACE granting "Authenticated users" // (SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE) access. } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, SYNCHRONIZE | MUTEX_MODIFY_STATE, PowerUsers)) { // Failed to build the ACE granting "Power users" // (SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE) access. } else if (!AddAccessAllowedAce(Acl, ACL_REVISION, MUTEX_ALL_ACCESS, BuiltInAdministrators)) { // Failed to build the ACE granting "Built-in Administrators" // GENERIC_ALL access. } else if (!InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION)) { // error } else if (!SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE)) { // error } else { // success RetVal = Sd; } // only free Sd if we encountered a failure if (!RetVal) LocalFree(Sd); } ErrorExit: if (AuthenticatedUsers) FreeSid(AuthenticatedUsers); if (BuiltInAdministrators) FreeSid(BuiltInAdministrators); if (PowerUsers) FreeSid(PowerUsers); return RetVal; }