1
votes

I've been trying to detect whether or not the Terminal Services are running. I tried to use the MSDN Way:

OSVERSIONINFOEX osVersionInfo;
DWORDLONG dwlConditionMask = 0;

memset( &osVersionInfo, 0, sizeof( osVersionInfo ) );
osVersionInfo.dwOSVersionInfoSize = sizeof( osVersionInfo );
osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;

VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );

return VerifyVersionInfo( &osVersionInfo, VER_SUITENAME, dwlConditionMask );

It works well, but on:

OS Name: Microsoft(R) Windows(R) Server 2003, Enterprise Edition  
OS Version:                5.2.3790 Service Pack 2 Build 3790  
OS Manufacturer:           Microsoft Corporation  
OS Configuration:          Standalone Server  
OS Build Type:             Multiprocessor Free

without Terminal Services role, the call to VerifyVersionInfo returns a non-zero value which means "the currently running operating system satisfies the specified requirements" or the function fails.

GetLastError returns:

0x000000cb "The system could not find the environment option that was entered."

On Windows XP SP3, a call to VerifyVersionInfo returns a zero value, so there are no typing errors, I suppose.

How do I handle this behavior? Is it good to treat this as if there are no Terminal Services? Are there any better techniques?

Is it a bug in the OS?

Update:

On Windows Server 2008 R1 behavior is similar (fails). May be on many other systems too.

3

3 Answers

0
votes

Terminal Services is an NT-service like any other, internally named TermServices, and if you have the permission.privilege to access the service manager, you could poll there to see if it's running:

OpenSCManager OpenService QueryServiceStatus

0
votes

Well, I found almost working solution (fails only on Win2k server).

OSVERSIONINFOEX osVersionInfo;
DWORDLONG dwlConditionMask = 0;

memset( &osVersionInfo, 0, sizeof( osVersionInfo ) );
osVersionInfo.dwOSVersionInfoSize = sizeof( osVersionInfo );
osVersionInfo.wSuiteMask = VER_SUITE_SINGLEUSERTS;

VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );

return !VerifyVersionInfo( &osVersionInfo, VER_SUITENAME, dwlConditionMask );

Interesting fact - call to VerifyVersionInfo do not modify last error code. Error code 0x000000cb that GetLastError returns to me is just a garbage.

-1
votes

A late reply but better late then never, the code below is Delphi but it wouldn't need much changes for c/c++

function AreWeRunningTerminalServices: Boolean;
var VersionInfo: TOSVersionInfoEx;
  dwlConditionMask: Int64;
begin
  // Zero Memory and set structure size
  ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
  VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);

  // We are either Terminal Server or Personal Terminal Server
  VersionInfo.wSuiteMask := VER_SUITE_TERMINAL or VER_SUITE_SINGLEUSERTS;
  dwlConditionMask := VerSetConditionMask(0, VER_SUITENAME, VER_OR);

  // Test it
  Result := VerifyVersionInfo(VersionInfo, VER_SUITENAME, dwlConditionMask);
end;

or if you want to check it the Terminal Server service is really running:

function IsTerminalServiceRunning: boolean;
var hSCM: HANDLE;
  hService: HANDLE;
  ServiceStatus: SERVICE_STATUS;
begin
  Result := False;
  // Open handle to Service Control Manager
  hSCM := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, GENERIC_READ);
  if hSCM > 0 then
  begin
    // Open handle to Terminal Server Service
    hService := OpenService(hSCM, 'TermService', GENERIC_READ);
    if hService > 0 then
    begin
      // Check if the service is running
      QueryServiceStatus(hService, ServiceStatus);
      Result := ServiceStatus.dwCurrentState = SERVICE_RUNNING;
      // Close the handle
      CloseServiceHandle(hService);
    end;
    // Close the handle
    CloseServiceHandle(hSCM);
  end;
end;