// -------------------------------------------------------------------------- // Module Name: SpecialAccounts.cpp // // Copyright (c) 1999-2000, Microsoft Corporation // // Class that implements handling special account names for exclusion or // inclusion. // // History: 1999-10-30 vtan created // 1999-11-26 vtan moved from logonocx // 2000-01-31 vtan moved from Neptune to Whistler // -------------------------------------------------------------------------- #include "StandardHeader.h" #include "SpecialAccounts.h" #include "RegistryResources.h" // -------------------------------------------------------------------------- // CSpecialAccounts::s_szUserListKeyName // // Purpose: Static const member variable that holds the location of the // special accounts in the registry. // // History: 2000-01-31 vtan created // -------------------------------------------------------------------------- const TCHAR CSpecialAccounts::s_szUserListKeyName[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList"); // -------------------------------------------------------------------------- // CSpecialAccounts::CSpecialAccounts // // Arguments: // // Returns: // // Purpose: Reads the registry to determine which accounts should be // filtered out and which should not be filtered out based on an // action code. The list is built up in memory so that each time // the class is invoked it adjusts live. // // History: 1999-10-30 vtan created // -------------------------------------------------------------------------- CSpecialAccounts::CSpecialAccounts (void) : _dwSpecialAccountsCount(0), _pSpecialAccounts(NULL) { CRegKey regKeyUserList; // Open the key to where the information is stored. if (ERROR_SUCCESS == regKeyUserList.Open(HKEY_LOCAL_MACHINE, s_szUserListKeyName, KEY_READ)) { DWORD dwValueCount; // Find out how many entries there are so an array of the correct // size can be allocated. if (ERROR_SUCCESS == regKeyUserList.QueryInfoKey(NULL, NULL, NULL, NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL)) { _pSpecialAccounts = static_cast(LocalAlloc(LPTR, dwValueCount * sizeof(SPECIAL_ACCOUNTS))); if (_pSpecialAccounts != NULL) { DWORD dwIndex, dwType, dwValueNameSize, dwDataSize; PSPECIAL_ACCOUNTS pSCA; // If the memory was allocated then fill the array in. regKeyUserList.Reset(); _dwSpecialAccountsCount = dwValueCount; pSCA = _pSpecialAccounts; for (dwIndex = 0; dwIndex < dwValueCount; ++dwIndex) { dwValueNameSize = ARRAYSIZE(pSCA->wszUsername); dwDataSize = sizeof(pSCA->dwAction); // Ensure that the entries are of type REG_DWORD. Ignore // any that are not. if ((ERROR_SUCCESS == regKeyUserList.Next(pSCA->wszUsername, &dwValueNameSize, &dwType, &pSCA->dwAction, &dwDataSize)) && (REG_DWORD == dwType)) { ++pSCA; } } } } } } // -------------------------------------------------------------------------- // CSpecialAccounts::~CSpecialAccounts // // Arguments: // // Returns: // // Purpose: Releases the memory allocated in the constructor. // // History: 1999-10-30 vtan created // -------------------------------------------------------------------------- CSpecialAccounts::~CSpecialAccounts (void) { if (_pSpecialAccounts != NULL) { (HLOCAL)LocalFree(_pSpecialAccounts); _pSpecialAccounts = NULL; _dwSpecialAccountsCount = 0; } } // -------------------------------------------------------------------------- // CSpecialAccounts::AlwaysExclude // // Arguments: pwszAccountName = Account name to match. // // Returns: bool // // Purpose: Uses the iterate loop to find a match for exclusion accounts. // // History: 1999-10-30 vtan created // -------------------------------------------------------------------------- bool CSpecialAccounts::AlwaysExclude (const WCHAR *pwszAccountName) const { return(IterateAccounts(pwszAccountName, RESULT_EXCLUDE)); } // -------------------------------------------------------------------------- // CSpecialAccounts::AlwaysInclude // // Arguments: pwszAccountName = Account name to match. // // Returns: bool // // Purpose: Uses the iterate loop to find a match for inclusion accounts. // // History: 1999-10-30 vtan created // -------------------------------------------------------------------------- bool CSpecialAccounts::AlwaysInclude (const WCHAR *pwszAccountName) const { return(IterateAccounts(pwszAccountName, RESULT_INCLUDE)); } // -------------------------------------------------------------------------- // CSpecialAccounts::StaticInitialize // // Arguments: // // Returns: NTSTATUS // // Purpose: Installs default user list for CSpecialAccounts to use. // CSpecialAccounts lives in specialaccounts.cpp and handles // exclusion or inclusion of special account names. // // History: 1999-11-01 vtan created // 1999-11-26 vtan moved from logonocx // -------------------------------------------------------------------------- void CSpecialAccounts::Install (void) { // Some of these names can be localized. IWAM_ and IUSR_ are stored in // resources in IIS. VUSR_ and SQLAgentCmdExec are of unknown origin. // TsInternetUser is hard coded in TS component bits. static const TCHAR szTsInternetUserName[] = TEXT("TsInternetUser"); static const TCHAR szSQLAgentUserName[] = TEXT("SQLAgentCmdExec"); static const TCHAR szWebAccessUserName[] = TEXT("IWAM_"); static const TCHAR szInternetUserName[] = TEXT("IUSR_"); static const TCHAR szVisualStudioUserName[] = TEXT("VUSR_"); static const TCHAR szNetShowServicesUserName[] = TEXT("NetShowServices"); static const TCHAR szHelpAssistantUserName[] = TEXT("HelpAssistant"); typedef struct { bool fInstall; const TCHAR *pszAccountName; DWORD dwActionType; } tSpecialAccount, *pSpecialAccount; DWORD dwDisposition; CRegKey regKeyUserList; // Open key to the user list. if (ERROR_SUCCESS == regKeyUserList.Create(HKEY_LOCAL_MACHINE, s_szUserListKeyName, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, &dwDisposition)) { tSpecialAccount *pSA; static tSpecialAccount sSpecialAccount[] = { { true, szTsInternetUserName, COMPARISON_EQUALS | RESULT_EXCLUDE }, { true, szSQLAgentUserName, COMPARISON_EQUALS | RESULT_EXCLUDE }, { true, szNetShowServicesUserName, COMPARISON_EQUALS | RESULT_EXCLUDE }, { true, szHelpAssistantUserName, COMPARISON_EQUALS | RESULT_EXCLUDE }, { true, szWebAccessUserName, COMPARISON_STARTSWITH | RESULT_EXCLUDE }, { true, szInternetUserName, COMPARISON_STARTSWITH | RESULT_EXCLUDE }, { true, szVisualStudioUserName, COMPARISON_STARTSWITH | RESULT_EXCLUDE }, { true, NULL, 0 }, }; pSA = sSpecialAccount; while (pSA->pszAccountName != NULL) { if (pSA->fInstall) { TW32(regKeyUserList.SetDWORD(pSA->pszAccountName, pSA->dwActionType)); } else { TW32(regKeyUserList.DeleteValue(pSA->pszAccountName)); } ++pSA; } } } // -------------------------------------------------------------------------- // CSpecialAccounts::IterateAccounts // // Arguments: pwszAccountName = Account name to match. // dwResultType = Result type to match. // // Returns: bool // // Purpose: Iterates thru the special case account name list from the // registry built in the constructor. Matches the given account // name based on the type of match specified for the special case // entry. If the account names match then match the result type. // // History: 1999-10-30 vtan created // -------------------------------------------------------------------------- bool CSpecialAccounts::IterateAccounts (const WCHAR *pwszAccountName, DWORD dwResultType) const { bool fResult; PSPECIAL_ACCOUNTS pSCA; fResult = false; pSCA = _pSpecialAccounts; if (pSCA != NULL) { DWORD dwIndex; for (dwIndex = 0; !fResult && (dwIndex < _dwSpecialAccountsCount); ++pSCA, ++dwIndex) { bool fMatch; // Perform the account name match based on the required type. // Currently only "equals" and "starts with" are supported. switch (pSCA->dwAction & COMPARISON_MASK) { case COMPARISON_EQUALS: { fMatch = (lstrcmpiW(pwszAccountName, pSCA->wszUsername) == 0); break; } case COMPARISON_STARTSWITH: { int iLength; iLength = lstrlenW(pSCA->wszUsername); fMatch = (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pwszAccountName, iLength, pSCA->wszUsername, iLength) == CSTR_EQUAL); break; } default: { fMatch = false; break; } } if (fMatch) { // If the name matches make sure the result type does as well. fResult = ((pSCA->dwAction & RESULT_MASK) == dwResultType); } } } return(fResult); }