public TerminalServicesSession(ITerminalServer server, int sessionId, string windowStationName,
                                       ConnectionState connectionState)
        {
            _server = server;
            _sessionId = sessionId;
            _windowStationName = windowStationName;
            _connectionState = connectionState;
            _clientBuildNumber = new LazyLoadedProperty<int>(GetClientBuildNumber);
            _clientIPAddress = new LazyLoadedProperty<IPAddress>(GetClientIPAddress);
            _clientDisplay = new LazyLoadedProperty<IClientDisplay>(GetClientDisplay);
            _clientName =
                NativeMethodsHelper.QuerySessionInformationForString(_server.Handle, _sessionId,
                                                                     WTS_INFO_CLASS.WTSClientName);

            // TODO: MSDN says most of these properties should be null for the console session.
            // I haven't observed this in practice on Windows Server 2000, 2003, or 2008, but perhaps this
            // should be considered.
            if (Environment.OSVersion.Version >= new Version(6, 0))
            {
                // We can actually use documented APIs in Vista / Windows Server 2008+.
                WTSINFO info =
                    NativeMethodsHelper.QuerySessionInformationForStruct<WTSINFO>(server.Handle, _sessionId,
                                                                                  WTS_INFO_CLASS.WTSSessionInfo);
                _connectTime = NativeMethodsHelper.FileTimeToDateTime(info.ConnectTime);
                _currentTime = NativeMethodsHelper.FileTimeToDateTime(info.CurrentTime);
                _disconnectTime = NativeMethodsHelper.FileTimeToDateTime(info.DisconnectTime);
                _lastInputTime = NativeMethodsHelper.FileTimeToDateTime(info.LastInputTime);
                _loginTime = NativeMethodsHelper.FileTimeToDateTime(info.LogonTime);
                _userName = info.UserName;
                _domainName = info.Domain;
            }
            else
            {
                WINSTATIONINFORMATIONW wsInfo = NativeMethodsHelper.GetWinStationInformation(server.Handle, _sessionId);
                _connectTime = NativeMethodsHelper.FileTimeToDateTime(wsInfo.ConnectTime);
                _currentTime = NativeMethodsHelper.FileTimeToDateTime(wsInfo.CurrentTime);
                _disconnectTime = NativeMethodsHelper.FileTimeToDateTime(wsInfo.DisconnectTime);
                _lastInputTime = NativeMethodsHelper.FileTimeToDateTime(wsInfo.LastInputTime);
                _loginTime = NativeMethodsHelper.FileTimeToDateTime(wsInfo.LoginTime);
                _userName =
                    NativeMethodsHelper.QuerySessionInformationForString(server.Handle, _sessionId,
                                                                         WTS_INFO_CLASS.WTSUserName);
                _domainName =
                    NativeMethodsHelper.QuerySessionInformationForString(server.Handle, _sessionId,
                                                                         WTS_INFO_CLASS.WTSDomainName);
            }
        }
        public TerminalServicesSession(ITerminalServer server, int sessionId)
        {
            _server = server;
            _sessionId = sessionId;

            // TODO: on Windows Server 2008, most of these values can be fetched in one shot from WTSCLIENT.
            // Do this with GroupLazyLoadedProperty.
            _clientBuildNumber = new LazyLoadedProperty<int>(GetClientBuildNumber);
            _clientIPAddress = new LazyLoadedProperty<IPAddress>(GetClientIPAddress);
            _sessionIPAddress = new LazyLoadedProperty<IPAddress>(GetSessionIPAddress);
            _remoteEndPoint = new LazyLoadedProperty<EndPoint>(GetRemoteEndPoint);
            _clientDisplay = new LazyLoadedProperty<IClientDisplay>(GetClientDisplay);
            _clientDirectory = new LazyLoadedProperty<string>(GetClientDirectory);
            _workingDirectory = new LazyLoadedProperty<string>(GetWorkingDirectory);
            _initialProgram = new LazyLoadedProperty<string>(GetInitialProgram);
            _applicationName = new LazyLoadedProperty<string>(GetApplicationName);
            _clientHardwareId = new LazyLoadedProperty<int>(GetClientHardwareId);
            _clientProductId = new LazyLoadedProperty<short>(GetClientProductId);
            _clientProtocolType = new LazyLoadedProperty<ClientProtocolType>(GetClientProtocolType);
            _clientName = new LazyLoadedProperty<string>(GetClientName);

            // TODO: MSDN says most of these properties should be null for the console session.
            // I haven't observed this in practice on Windows Server 2000, 2003, or 2008, but perhaps this
            // should be considered.
            var loader = IsVistaSp1OrHigher
                ? (GroupPropertyLoader) LoadWtsInfoProperties
                : LoadWinStationInformationProperties;
            _windowStationName = new GroupLazyLoadedProperty<string>(loader);
            _connectionState = new GroupLazyLoadedProperty<ConnectionState>(loader);
            _connectTime = new GroupLazyLoadedProperty<DateTime?>(loader);
            _currentTime = new GroupLazyLoadedProperty<DateTime?>(loader);
            _disconnectTime = new GroupLazyLoadedProperty<DateTime?>(loader);
            _lastInputTime = new GroupLazyLoadedProperty<DateTime?>(loader);
            _loginTime = new GroupLazyLoadedProperty<DateTime?>(loader);
            _userName = new GroupLazyLoadedProperty<string>(loader);
            _domainName = new GroupLazyLoadedProperty<string>(loader);
            _incomingStatistics = new GroupLazyLoadedProperty<IProtocolStatistics>(loader);
            _outgoingStatistics = new GroupLazyLoadedProperty<IProtocolStatistics>(loader);
        }