Jan 16 2007

Delphi: Como detectar se a sua aplicação está rodando sobre WTS e saber qual é a ID da sessão

Autor: Marcos Dell Antonio - Categorias: Delphi

Parece ridículo, mas quem poderia imaginar que o controle de licenças de um software furaria quando os clientes fizessem o acesso via WTS (Windows Terminal Server)?

Imagine a seguinte situação: um controlador de licenças baseado no IP dos clientes e que bloqueia a execução da mesma aplicação duas vezes simultaneamente na mesma máquina. Se o acesso ao controlador for via TCP/IP “diretamente”, da forma mais comum possível (um servidor + um cliente), essa validação funcionará perfeitamente.

Agora pense no mesmo cenário acima, porém com o acesso de dois clientes usando WTS. O que acontece? O primeiro cliente acessa, o controlador faz o registro do IP. Quando o segundo cliente for acessar (lembre-se, é WTS), adivinha? O controlador bloqueia! Por que? Pois o segundo cliente possui o mesmo IP do primeiro, que por sua vez possui o mesmo IP do servidor, pois está tudo sobre WTS.

Solução? Eu vejo duas:

  1. Controlar o acesso pelo IP do cliente. Para isso, é preciso identificar qual a sessão que está acessando o WTS e através do seu ID buscar as informações (IP e outras) de quem a originou;
  2. Fazer com que o controlador de licenças conheça se o cliente está sobre WTS e considerar o ID da sessão no controle de acesso.

Para ambas as soluções duas rotinas são fundamentais:

  1. Identificar se a aplicação está sendo executada via WTS:

    function IsRemoteSession: boolean; const SM_REMOTESESSION = $1000; begin Result := GetSystemMetrics(SM_REMOTESESSION) <> 0; end;

    Adicione o uses Windows à unit.

  2. Pegar o ID da sessão que vai executar o aplicativo:

    1 function GetCurrentSessionID: Integer; 2 type 3 TProcessIdToSessionId = 4 function(dwProcessId: DWORD; 5 pSessionId: DWORD): 6 BOOL; stdcall; 7 var 8 ProcessIdToSessionId: TProcessIdToSessionId; 9 hWTSapi32dll: THandle; 10 Lib : THandle; 11 pSessionId : DWord; 12 begin 13 Result := 0; 14 Lib := GetModuleHandle('kernel32'); 15 if Lib <> 0 then 16 begin 17 ProcessIdToSessionId := 18 GetProcAddress(Lib, 'ProcessIdToSessionId'); 19 20 if Assigned(ProcessIdToSessionId) then 21 begin 22 ProcessIdToSessionId(GetCurrentProcessId(), 23 DWORD(@pSessionId)); 24 Result:= pSessionId; 25 end; 26 end; 27 end;

    As units Windows e Winsock são necessárias.

Com essas duas rotinas é possível controlar se aplicação cliente está sobre WTS ou não. O resto fica por conta da sua imaginação. ;)

Fonte: Torry’s Delphi Pages (cuidado com a rotina que está lá, ela tem um errinho no parâmetro da GetProcAddress - o número 1 está sobrando)

Até +!

Adicione ao del.icio.us del.icio.us | Adicione ao Rec6 Rec6

Faça um comentário