|
|
#include <shlwapi.h>
#include <regstr.h>
#if (_WIN32_WINNT >= 0x0500)
#include <lm.h> // for NetGetJoinInformation
#endif
// stolen from winuser
#ifndef SM_REMOTESESSION
#define SM_REMOTESESSION 0x1000
#endif
BOOL IsWinlogonRegValueSet(HKEY hKey, LPSTR pszKeyName, LPSTR pszPolicyKeyName, LPSTR pszValueName) { BOOL bRet = FALSE; DWORD dwType; DWORD dwSize; HKEY hkey;
// first check the per-machine location.
if (RegOpenKeyExA(hKey, pszKeyName, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { dwSize = sizeof(bRet); if (RegQueryValueExA(hkey, pszValueName, NULL, &dwType, (LPBYTE)&bRet, &dwSize) == ERROR_SUCCESS) { if (dwType != REG_DWORD) { bRet = FALSE; } } RegCloseKey(hkey); } // then let the policy value override
if (RegOpenKeyExA(hKey, pszPolicyKeyName, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { dwSize = sizeof(bRet); if (RegQueryValueExA(hkey, pszValueName, NULL, &dwType, (LPBYTE)&bRet, &dwSize) == ERROR_SUCCESS) { if (dwType != REG_DWORD) { bRet = FALSE; } } RegCloseKey(hkey); }
return bRet; }
BOOL IsWinlogonRegValuePresent(HKEY hKey, LPSTR pszKeyName, LPSTR pszValueName) { BOOL bRet = FALSE; DWORD dwType; DWORD dwSize; HKEY hkey;
// first check the per-machine location.
if (RegOpenKeyExA(hKey, pszKeyName, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { char szValueData[MAX_PATH];
dwSize = sizeof(szValueData); bRet = (RegQueryValueExA(hkey, pszValueName, NULL, &dwType, (LPBYTE)szValueData, &dwSize) == ERROR_SUCCESS); RegCloseKey(hkey); } return bRet; }
/*
BOOL IsTermsrvRunning() { BOOL fResult = TRUE; // assume the service is running
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager) { SC_HANDLE hSCService = OpenService(hSCManager, TEXT("TermService"), SERVICE_QUERY_CONFIG);
if (hSCService) { SERVICE_STATUS ServiceStatus;
if (QueryServiceStatus(hSCService, &ServiceStatus)) { if ((ServiceStatus.dwCurrentState == SERVICE_START_PENDING) || (ServiceStatus.dwCurrentState == SERVICE_RUNNING) || (ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING)) { fResult = FALSE; } } }
CloseServiceHandle(hSCManager); }
return fResult; } */
#if (_WIN32_WINNT >= 0x0500)
// Have to use a LoadLibrary/GetProcAddress thunk since we are part of stock4.lib/stock.lib,
// and we can't require users of stocklib to delayload netapi32.dll
typedef NET_API_STATUS (* NETGETJOININFORMATION) (LPCWSTR, LPWSTR*, PNETSETUP_JOIN_STATUS); NET_API_STATUS NT5_NetGetJoinInformation(LPCWSTR pszServer, LPWSTR* ppszNameBuffer, PNETSETUP_JOIN_STATUS BufferType) { static NETGETJOININFORMATION s_pfn = (NETGETJOININFORMATION)-1;
if (s_pfn == (NETGETJOININFORMATION)-1) { if (IsOS(OS_WIN2000ORGREATER)) { s_pfn = (NETGETJOININFORMATION)GetProcAddress(LoadLibrary(TEXT("netapi32")), "NetGetJoinInformation"); } else { s_pfn = NULL; } }
if (s_pfn) { return s_pfn(pszServer, ppszNameBuffer, BufferType); } else { return ERROR_PROC_NOT_FOUND; } }
typedef NET_API_STATUS (* NETAPIBUFFERFREE) (void*); NET_API_STATUS NT5_NetApiBufferFree(LPVOID pv) { static NETAPIBUFFERFREE s_pfn = (NETAPIBUFFERFREE)-1;
if (s_pfn == (NETAPIBUFFERFREE)-1) { if (IsOS(OS_WIN2000ORGREATER)) { s_pfn = (NETAPIBUFFERFREE)GetProcAddress(GetModuleHandle(TEXT("netapi32")), "NetApiBufferFree"); } else { s_pfn = NULL; } }
if (s_pfn) { return s_pfn(pv); } else { return ERROR_PROC_NOT_FOUND; } } #endif // (_WIN32_WINNT >= 0x0500)
// checks to see if this machine is a member of a domain or not
// NOTE: this will always return FALSE on downlevel platforms (older than win2k)
BOOL IsMachineDomainMember() { // don't call NetGetJoinInformation if we are part of stock4.lib
#if (_WIN32_WINNT >= 0x0500)
static BOOL s_bIsDomainMember = FALSE; static BOOL s_bDomainCached = FALSE;
if (IsOS(OS_WIN2000ORGREATER) && !s_bDomainCached) { LPWSTR pwszDomain; NETSETUP_JOIN_STATUS njs; NET_API_STATUS nas;
nas = NT5_NetGetJoinInformation(NULL, &pwszDomain, &njs); if (nas == NERR_Success) { if (pwszDomain) { NT5_NetApiBufferFree(pwszDomain); }
if (njs == NetSetupDomainName) { // we are joined to a domain!
s_bIsDomainMember = TRUE; } } s_bDomainCached = TRUE; } return s_bIsDomainMember; #else
return FALSE; #endif
}
typedef LONG (WINAPI *PFNTQUERYINFORMATIONPROCESS) (HANDLE ProcessHandle, int ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
// this function checks to see if we are a 32-bit process running on a 64-bit platform
BOOL RunningOnWow64() { static BOOL bRunningOnWow64 = (BOOL)-1;
if (bRunningOnWow64 == (BOOL)-1) { PFNTQUERYINFORMATIONPROCESS pfn = (PFNTQUERYINFORMATIONPROCESS)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQueryInformationProcess");
if (pfn) { LONG lStatus; ULONG_PTR Wow64Info;
#define ProcessWow64Information 26 // stolen from ntpsapi.h
lStatus = pfn(GetCurrentProcess(), ProcessWow64Information, &Wow64Info, sizeof(Wow64Info), NULL); if ((lStatus >= 0) && Wow64Info) { bRunningOnWow64 = TRUE; } else { bRunningOnWow64 = FALSE; } } else { bRunningOnWow64 = FALSE; } }
return bRunningOnWow64; }
BOOL ShouldShowServerAdminUI() { DWORD dw = FALSE; HKEY hk; if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\Advanced"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS) { DWORD cb = sizeof(dw); RegQueryValueEx(hk, TEXT("ServerAdminUI"), NULL, NULL, (LPBYTE)&dw, &cb); // preinitialized dw for failure
RegCloseKey(hk); } return dw; }
BOOL IsApplianceServer() { static BOOL s_bRet = (BOOL)-1;
// Cache the value since it should not change normally. If any of the
// following code fails, just assume it is not an appliance server.
if (s_bRet == (BOOL)-1) { HKEY hkey;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\WPA\\ApplianceServer", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { DWORD dwType; DWORD dwValue; DWORD dwSize = sizeof(dwValue);
if (RegQueryValueExA(hkey, "Installed", NULL, &dwType, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS) { if ((dwType == REG_DWORD) && (dwValue != 0)) { s_bRet = TRUE; } } RegCloseKey(hkey); } }
if (s_bRet == (BOOL)-1) { s_bRet = FALSE; }
return s_bRet; }
/*----------------------------------------------------------
Purpose: Returns TRUE/FALSE if the platform is the given OS_ value.
*/ STDAPI_(BOOL) IsOS(DWORD dwOS) { BOOL bRet; static OSVERSIONINFOEXA s_osvi = {0}; static BOOL s_bVersionCached = FALSE;
if (!s_bVersionCached) { s_bVersionCached = TRUE; s_osvi.dwOSVersionInfoSize = sizeof(s_osvi); if (!GetVersionExA((OSVERSIONINFOA*)&s_osvi)) { // If it failed, it must be a down level platform
s_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); GetVersionExA((OSVERSIONINFOA*)&s_osvi); } }
switch (dwOS) { case OS_TERMINALCLIENT: // WARNING: this will only return TRUE for REMOTE TS sessions (eg you are comming in via tsclient).
// If you want to see if TS is enabled or if the user is on the TS console, the use one of the other flags.
bRet = GetSystemMetrics(SM_REMOTESESSION); break;
case OS_WIN2000TERMINAL: // WARNING: this flag is VERY ambiguous... you probably want to use one of
// OS_TERMINALSERVER, OS_TERMINALREMOTEADMIN, or OS_PERSONALTERMINALSERVER instead.
RIPMSG(!IsOS(OS_WHISTLERORGREATER), "IsOS: use one of OS_TERMINALSERVER, OS_TERMINALREMOTEADMIN, or OS_PERSONALTERMINALSERVER instead !"); bRet = ((VER_SUITE_TERMINAL & s_osvi.wSuiteMask) && s_osvi.dwMajorVersion >= 5); break;
case OS_TERMINALSERVER: // NOTE: be careful about using OS_TERMINALSERVER. It will only return true for nt server boxes
// configured in what used to be called "Applications Server" mode in the win2k days. It is now simply called
// "Terminal Server" (hence the name of this flag).
bRet = ((VER_SUITE_TERMINAL & s_osvi.wSuiteMask) && !(VER_SUITE_SINGLEUSERTS & s_osvi.wSuiteMask)); #ifdef DEBUG
if (bRet) { // all "Terminal Server" machines have to be server (cannot be per/pro)
ASSERT(VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType); } #endif
break;
case OS_TERMINALREMOTEADMIN: // this checks to see if TS has been installed in the "Remote Administration" mode. This is
// the default for server installs on win2k and whistler
bRet = ((VER_SUITE_TERMINAL & s_osvi.wSuiteMask) && (VER_SUITE_SINGLEUSERTS & s_osvi.wSuiteMask)); break;
case OS_PERSONALTERMINALSERVER: bRet = ((VER_SUITE_SINGLEUSERTS & s_osvi.wSuiteMask) && !(VER_SUITE_TERMINAL & s_osvi.wSuiteMask)); break;
case OS_FASTUSERSWITCHING: bRet = (((VER_SUITE_TERMINAL | VER_SUITE_SINGLEUSERTS) & s_osvi.wSuiteMask) && IsWinlogonRegValueSet(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\system", "AllowMultipleTSSessions")); break;
case OS_FRIENDLYLOGONUI: bRet = ((VER_NT_WORKSTATION == s_osvi.wProductType) && !IsMachineDomainMember() && !IsWinlogonRegValuePresent(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "GinaDLL") && IsWinlogonRegValueSet(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\system", "LogonType")); break;
case OS_DOMAINMEMBER: bRet = IsMachineDomainMember(); ASSERT(VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId); // has to be a NT machine to be on a domain!
break;
case 4: // used to be OS_NT5, is the same as OS_WIN2000ORGREATER so use that instead
case OS_WIN2000ORGREATER: bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId && s_osvi.dwMajorVersion >= 5); break;
// NOTE: The flags in this section are bogus and SHOULD NOT BE USED
// (but the ie4 shell32 uses them, so don't RIP on downlevel platforms)
case OS_WIN2000PRO: RIPMSG(!IsOS(OS_WHISTLERORGREATER), "IsOS: use OS_PROFESSIONAL instead of OS_WIN2000PRO !"); bRet = (VER_NT_WORKSTATION == s_osvi.wProductType && s_osvi.dwMajorVersion == 5); break; case OS_WIN2000ADVSERVER: RIPMSG(!IsOS(OS_WHISTLERORGREATER), "IsOS: use OS_ADVSERVER instead of OS_WIN2000ADVSERVER !"); bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && s_osvi.dwMajorVersion == 5 && (VER_SUITE_ENTERPRISE & s_osvi.wSuiteMask) && !(VER_SUITE_DATACENTER & s_osvi.wSuiteMask)); break; case OS_WIN2000DATACENTER: RIPMSG(!IsOS(OS_WHISTLERORGREATER), "IsOS: use OS_DATACENTER instead of OS_WIN2000DATACENTER !"); bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && s_osvi.dwMajorVersion == 5 && (VER_SUITE_DATACENTER & s_osvi.wSuiteMask)); break; case OS_WIN2000SERVER: RIPMSG(!IsOS(OS_WHISTLERORGREATER), "IsOS: use OS_SERVER instead of OS_WIN2000SERVER !"); bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && !(VER_SUITE_DATACENTER & s_osvi.wSuiteMask) && !(VER_SUITE_ENTERPRISE & s_osvi.wSuiteMask) && s_osvi.dwMajorVersion == 5); break; // END bogus Flags
case OS_EMBEDDED: bRet = (VER_SUITE_EMBEDDEDNT & s_osvi.wSuiteMask); break;
case OS_WINDOWS: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId); break;
case OS_NT: bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId); break;
case OS_WIN95: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId && s_osvi.dwMajorVersion >= 4); break;
case OS_WIN95GOLD: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId && s_osvi.dwMajorVersion == 4 && s_osvi.dwMinorVersion == 0 && LOWORD(s_osvi.dwBuildNumber) == 950); break;
case OS_WIN98ORGREATER: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId && (s_osvi.dwMajorVersion > 4 || s_osvi.dwMajorVersion == 4 && s_osvi.dwMinorVersion >= 10)); break;
case OS_WIN98_GOLD: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId && s_osvi.dwMajorVersion == 4 && s_osvi.dwMinorVersion == 10 && LOWORD(s_osvi.dwBuildNumber) == 1998); break;
case OS_MILLENNIUMORGREATER: bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId && ((s_osvi.dwMajorVersion == 4 && s_osvi.dwMinorVersion >= 90) || s_osvi.dwMajorVersion > 4)); break;
case OS_NT4: bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId && s_osvi.dwMajorVersion >= 4); break;
case OS_WHISTLERORGREATER: bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId && ((s_osvi.dwMajorVersion > 5) || (s_osvi.dwMajorVersion == 5 && (s_osvi.dwMinorVersion > 0 || (s_osvi.dwMinorVersion == 0 && LOWORD(s_osvi.dwBuildNumber) > 2195))))); break;
case OS_PERSONAL: bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId && (VER_SUITE_PERSONAL & s_osvi.wSuiteMask)); break;
case OS_PROFESSIONAL: bRet = ((VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId) && (VER_NT_WORKSTATION == s_osvi.wProductType)); break;
case OS_DATACENTER: bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && (VER_SUITE_DATACENTER & s_osvi.wSuiteMask)); break;
case OS_ADVSERVER: bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && (VER_SUITE_ENTERPRISE & s_osvi.wSuiteMask) && !(VER_SUITE_DATACENTER & s_osvi.wSuiteMask)); break;
case OS_SERVER: // NOTE: be careful! this specifically means Server -- will return false for Avanced Server and Datacenter machines
bRet = ((VER_NT_SERVER == s_osvi.wProductType || VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType) && !(VER_SUITE_DATACENTER & s_osvi.wSuiteMask) && !(VER_SUITE_ENTERPRISE & s_osvi.wSuiteMask) && !(VER_SUITE_BLADE & s_osvi.wSuiteMask) && !(VER_SUITE_SMALLBUSINESS & s_osvi.wSuiteMask) && !(VER_SUITE_SMALLBUSINESS_RESTRICTED & s_osvi.wSuiteMask)); break;
case OS_BLADE: // Blade has a direct suite mask
bRet = (VER_SUITE_BLADE & s_osvi.wSuiteMask); break;
case OS_SMALLBUSINESSSERVER: // SBS also has a direct suite mask
bRet = (VER_SUITE_SMALLBUSINESS_RESTRICTED & s_osvi.wSuiteMask); break;
case OS_ANYSERVER: // this is for people who want to know if this is ANY type of NT server machine (eg dtc, ads, or srv)
bRet = ((VER_NT_SERVER == s_osvi.wProductType) || (VER_NT_DOMAIN_CONTROLLER == s_osvi.wProductType)); break;
case OS_WOW6432: bRet = RunningOnWow64(); break;
#if (_WIN32_WINNT >= 0x0501)
case OS_TABLETPC: bRet = GetSystemMetrics(SM_TABLETPC); break; case OS_MEDIACENTER: bRet = GetSystemMetrics(SM_MEDIACENTER); break;
case OS_APPLIANCE: bRet = IsApplianceServer(); break; #endif
case OS_SERVERADMINUI: // Note that it is possible to have server admin UI on a non-server machine.
// This is to prevent "surprises" when an admin's profile roams to a non-server.
// Otherwise the user gets a mix of admin settings (Start Menu, full path in
// title bar, etc.) and nonadmin settings (hide taskbar icons, folder sniffing).
//
bRet = ShouldShowServerAdminUI(); break;
default: bRet = FALSE; break; }
return bRet; }
|