Página 2 de 2

Alternativa a BlockInput

Enviado: 07 Jan 2016 15:31
por asimoes
Acho que a solução seria bloquear a estação enquanto a aplicação faz alguma coisa.

Tem uma função neste código que eu estou postando que funciona independente de permissão.

BloqueiaEstacao()

rotinas.c

Código: Selecionar todos

#include "windows.h"
#include "time.h"
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapifs.h"
#include <shellapi.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <lmcons.h>
#include <commctrl.h>

HB_FUNC( PEGAINATIVIDADE ) 
{
   LASTINPUTINFO lpi;
   lpi.cbSize = sizeof (LASTINPUTINFO);
   GetLastInputInfo (&lpi);
   hb_retnd( ( DOUBLE ) ( GetTickCount() - lpi.dwTime ) / CLOCKS_PER_SEC ); 
}

HB_FUNC( SHELLEXECUTE )
{
   hb_retnl
   (
      ( LONG ) ShellExecute
      (
         ( HWND ) hb_parnl( 1 ),
         HB_ISNIL( 2 ) ? NULL : ( LPCTSTR ) hb_parc( 2 ),
         ( LPCSTR ) hb_parc( 3 ),
         HB_ISNIL( 4 ) ? NULL : ( LPCTSTR ) hb_parc( 4 ),
         HB_ISNIL( 5 ) ? NULL : ( LPCTSTR ) hb_parc( 5 ),
         hb_parni( 6 )
      )
   );
}

HB_FUNC( RUNDLL32SHELL )
{
  SHELLEXECUTEINFO ShExecInfo = {0};     
  
  LPCTSTR lpCommand = (LPTSTR) hb_parc( 1 );
  
  BOOL bRetorno = FALSE;
  
  int lenlpCommand = hb_parclen( 1 ) + 4;
  
  char * cfinalCommand = ( char * ) hb_xgrab( hb_parclen( 1 ) + 4 );
  
  hb_snprintf(cfinalCommand, lenlpCommand, "%s%s", "/C ", lpCommand);
 
  //MessageBox( NULL, cfinalCommand, TEXT( HB_I_("TESTE final") ), MB_ICONASTERISK );
  
  ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  ShExecInfo.hwnd = NULL;
  ShExecInfo.lpVerb = NULL;
  ShExecInfo.lpFile = "rundll32.exe";
  ShExecInfo.lpParameters = cfinalCommand;   
  ShExecInfo.lpDirectory = NULL;
  ShExecInfo.nShow = SW_HIDE;
  ShExecInfo.hInstApp = NULL; 
  ShellExecuteEx(&ShExecInfo);
  if(ShExecInfo.hProcess !=NULL)
  {
     if (hb_parl(2))
     {
        //Aguarda até que a execução tenha sido concluída.
        WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
        CloseHandle(ShExecInfo.hProcess);
     }
     bRetorno = TRUE;
  }
  else
  {
     //Retorna .F.
     bRetorno = FALSE;
  }
  hb_xfree( cfinalCommand );
  hb_retl(bRetorno);
}

HB_FUNC( ENABLEPERMISSIONS )
{
   LUID tmpLuid;
   TOKEN_PRIVILEGES tkp, tkpNewButIgnored;
   DWORD lBufferNeeded;
   HANDLE hdlTokenHandle;
   HANDLE hdlProcessHandle = GetCurrentProcess();

   OpenProcessToken(hdlProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hdlTokenHandle);

   LookupPrivilegeValue(NULL, "SeShutdownPrivilege", &tmpLuid);

   tkp.PrivilegeCount            = 1;
   tkp.Privileges[0].Luid        = tmpLuid;
   tkp.Privileges[0].Attributes  = SE_PRIVILEGE_ENABLED;

   AdjustTokenPrivileges(hdlTokenHandle, FALSE, &tkp, sizeof(tkpNewButIgnored), &tkpNewButIgnored, &lBufferNeeded);
}

HB_FUNC( EXITWINDOWSEX )
{
   hb_retl( ExitWindowsEx( (UINT) hb_parni( 1 ), (DWORD) hb_parnl( 2 ) ) );
}

HB_FUNC( BLOQUEIAESTACAO )
{
    WINUSERAPI
    BOOL
    WINAPI LockWorkStation(VOID);
    //SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0); // Inicia a proteção de tela.
    LockWorkStation();
}

HB_FUNC( PROTECAODETELA )
{
    SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0); // Inicia a proteção de tela.
}

HB_FUNC( DESLIGARMONITOR )
{
    //Monitor Off - Desligar o monitor.
    //Sleep(100);
    //SendMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
    //Sleep(300);
    //SendMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
    //Sleep(1000);
    SendMessage(GetForegroundWindow(), WM_SYSCOMMAND, SC_MONITORPOWER, 2);
 }

Alternativa a BlockInput

Enviado: 07 Jan 2016 15:36
por asimoes
O código para testar o bloqueio:
Tem que linkar com rotinas.c

Código: Selecionar todos

#include "inkey.ch"
#include "setcurs.ch"
#include "error.ch"
#include "achoice.ch"
#include "fileio.ch"
#include "common.ch"
#include "dbinfo.ch"
#include "hbver.ch"
#include "hbdyn.ch"
#include "wvtwin.ch"
#include "hbgtinfo.ch"
#include "hbgtwvg.ch"
#include "wvgparts.ch"
#include "hbcompat.ch"
#include "hbhrb.ch"
#include "directry.ch"
#include "hbwin.ch"
#include "hbthread.ch"

STATIC nSeconds
STATIC nTempoUltimaVerificacao
STATIC nIdleTime
STATIC nInatividade

#define EWX_LOGOFF   0
#define EWX_SHUTDOWN 1
#define EWX_REBOOT   2
#define EWX_FORCE    4
#define EWX_POWEROFF 8

//#translate CBNew()    => { , <(b)> }
//#translate CBEval()   => eval( \[1\] )
//#translate CBString() => \[2\]


#Translate CBNew(<b>)    => { <b>, <(b)> }
#Translate CBEval(<b>)   => eval( <b>\[1\] )
#Translate CBString(<b>) => <b>\[2\]

FUNCTION MAIN()
LOCAL cTeste:=Space(5)

local bCod1 := CBNew( { || MINHA_FUNC("Teste") } )
local bCod2 := CBNew( { || MINHA_FUNC(12) } )
local bCod3 := CBNew( { || MINHA_FUNC("Teste") } )
local bCod4 := CBNew( { || nCtd += 1, npar2 -=1, npar3 +=10 } )

private nCtd := 0, npar2 := 0, npar3 := 0

PUBLIC __nTeclaDigitada:=Inkey()

? "-CBEval-"
? CBEval( bCod1 )
? "---"
? CBEval( bCod2 )
? "---"
? CBEval( bCod3 )
? "---"
? CBEval( bCod4 )
? "---"

? "-CBString-"
? CBString(  bCod1 )
? "---"
? CBString(  bCod2 )
? "---"
? CBString(  bCod3 )
? "---"
? CBString(  bCod4 )
? "---"
INKEY(0)
   
   IniciaTempo()
   
   @ 01,00 SAY PADC("TESTE DE BLOQUEIO DE ESTAۂO",80) COLOR "W+/B*"
  
  nKey:=0
  
  //DO WHILE nKey = 0 
  //   nKey:=Marquee("0123456789",.3,10,0)
  //ENDDO
      
   SET CURSOR ON
   @ 05,00 SAY "TESTE : " GET cTeste COLOR "W/N"
   READ

RETURN NIL

function MINHA_FUNC( uDesc )
*******************

? valtype(uDesc), uDesc

return uDesc

FUNCTION Marquee(cString,nDelay,nRow,nCol)
LOCAL x:=0,;
      nLeft:=0,;
      cStr,;
      n,;
      cMarquee,;
      nKey:=0

   DEFAULT cString TO "TESTE",;
           nDelay TO .5,;
           nRow TO 0,;
           nCol TO 0
   
   SetCursor(0)

   nLeft:=(MaxCol())+2
   
   x:=nCol
   cStr:=""   
   n:=0
   cMarquee:=""
   lLinha:=.t.

   DO WHILE X < nLeft .AND. nKey = 0
      nKey:=Inkey()
      IF Len(cStr) < Len(cString)
         cStr+=IF(Len(cStr)<Len(cString),SubStr(cString,Len(cString)-N,1),"")
         cMarquee:=CharMirr(cStr) 
         lLinha:=.T.
         N++
      ELSE
         IF lLinha
            X:=nCol+1
         ENDIF
         cMarquee:=cString
         lLinha:=.F.
      ENDIF
      @ nRow,x-1 CLEAR TO nRow,x-1
      IF lLinha
         @ nRow,nCol SAY cMarquee 
      ELSE
         @ nRow,x SAY cMarquee 
      ENDIF
      hb_IdleSleep(nDelay)
      x++
   ENDDO
   IF nKey <> 0
      @ nRow,nCol CLEAR TO nRow,MaxCol()+1
   ENDIF
RETURN nKey

FUNCTION MensTime(nTime)
   DO WHILE .T.
      IF nSeconds = Nil
         nSeconds:=Seconds()
      ENDIF
      IF __nTeclaDigitada <> 0
         nSeconds:=Seconds()
      ENDIF
      
      nInatividade:=PegaInatividade()
      
      IF Seconds() - nSeconds >= nTime .OR. nInatividade >= 30
         nInatividade:=0
         /*
         0 - LOGOFF
         1 - SHUTDOWN
         2 - REBOOT
         4 - FORCE
         8 - POWEROFF
         (can be combined -> 6 = 2+4 FORCE REBOOT)
         */
         //ExitWindowsEx(0,0) //logoff
         //ExitWindowsEx(1,0) //shutdown
         //ExitWindowsEx(2,0) //reboot (reinicilializar)
         //ExitWindowsEx(6,0) //force reboot (reinicialização forçada)
         //ExitWindowsEx(8,0) //poweroff (desligar)
        
         //IF hb_osIsWinNT()
         //   EnablePermissions()
         //ENDIF
         //ExitWindowsEx(1,0) //poweroff
         
         //BloquearEstacao("%windir%\System32\rundll32.exe user32.dll,LockWorkStation",.F.)
         //ShellExecute(0, "open", "rundll32.exe", "user32.dll,LockWorkStation", , 1)
         //ExecuteShell("%windir%\System32\rundll32.exe user32.dll,ExitWindowsEx 0",.F.)
         //LockTeste()
         //altd()
         BloqueiaEstacao()
         //ProtecaodeTela()
         //rundll32Shell("user32.dll,LockWorkStation",.F.)

         nSeconds:=Seconds()
      ENDIF
      HB_IdleSleep( 0 )
   ENDDO
RETURN Nil

FUNCTION IniciaTempo
   IF nIdleTime != Nil
      HB_IdleDel( nIdleTime )
   ENDIF
   hb_threadStart(HB_THREAD_INHERIT_PUBLIC,@MensTime(),60)
   nIdleTime:=HB_IdleAdd( {|| ViewTime(60) } )
RETURN .T.  

FUNCTION ViewTime(nTempo)
LOCAL nRow, nCol 

   __nTeclaDigitada:=Inkey()
   nRow:=Row()
   nCol:=Col()
   IF nTempoUltimaVerificacao = Nil
      nTempoUltimaVerificacao:=Seconds()
   ENDIF
   IF Round(PegaInatividade(),0) = 0
      nTempoUltimaVerificacao:=Seconds()
   ENDIF
   IF Seconds() - nTempoUltimaVerificacao >= nTempo .OR. __nTeclaDigitada <> 0
      KEYBOARD Chr(__nTeclaDigitada)
      nTempoUltimaVerificacao:=Seconds()
   ELSE
      HB_gtInfo(HB_GTI_WINTITLE, SecToTime(PegaInatividade()))
      @ 23,00 SAY SecToTime(PegaInatividade())
      @ 24,00 SAY PADC("Bloqueando a esta‡Æo em "+StrZero(nTempo,2)+" segundo(s) - "+SecToTime(Seconds()-nTempoUltimaVerificacao),80) COLOR "W+/B"
      SetPos(nRow,nCol)
   ENDIF
   HB_IdleSleep( 0 )
RETURN Nil

FUNCTION BloquearEstacao(cComando,lEspera)
LOCAL oShell, lOk:=.T.
DEFAULT lEspera TO .T.
   TRY
      oShell:=WIN_OleCreateObject( "WScript.Shell" )
   CATCH
      TRY
         oShell:=WIN_OleCreateObject( "WScript.Shell" )
      CATCH
         lOk:=.F.
      END
   END
   IF lOk
      TRY
        oShell:Run( "%comspec% /c " + cComando, 0, lEspera )
      CATCH
         lOk:=.F.
      END
      oShell:=Nil
   ENDIF
RETURN lOk

INIT FUNCTION AppSetup()
  
  REQUEST HB_LANG_PT
  REQUEST HB_CODEPAGE_PT850
  HB_LANGSELECT("PT")
  HB_CDPSELECT( "PT850" ) //pt850

  SETMODE(25,80)

  SET TYPEAHEAD TO 0
  SET INTENSITY ON
  SET SCOREBOARD OFF
  SET DELETED ON
  SET SAFETY OFF
  SET DATE ANSI
  SET ESCAPE ON
  SET DELIMITERS TO
  SET EXCLUSIVE OFF
  SET WRAP ON
  SET EPOCH TO 1920
  SET MESSAGE TO 24 CENTER

  SetColor("W+/B")
  
  CLS

  SetColor("W+/B")
  
  IniciaJanela()


RETURN Nil 


FUNCTION IniciaJanela(nLi,nCi,nLf,nCf)

LOCAL oCrt
   HB_Default(@nLi,0)
   HB_Default(@nCi,0)
   HB_Default(@nLf,MaxRow())
   HB_Default(@nCf,MaxCol())
  
  cTituloJanela:="Teste de Bloqueio de Esta‡Æo"

  #ifndef HARBOUR_MSVC
     oCrt:=WvgCrt():New( , , { nLi, nCi }, { nLf, nCf }, , .T. )
     oCrt:create()
     oCrt:resizable:=.F.
  #endif

   HB_gtInfo(HB_GTI_FONTNAME, "Lucida Console")
   HB_gtInfo(HB_GTI_WINTITLE, cTituloJanela)
   HB_gtInfo(HB_GTI_CLOSABLE, .F. )
   HB_gtInfo(HB_GTI_ISGRAPHIC, .T. )
   HB_gtInfo(HB_GTI_STDERRCON, .T. )
   HB_gtInfo(HB_GTI_COMPATBUFFER, .T. ) 
   HB_gtInfo(HB_GTI_SPEC, HB_GTS_WNDSTATE, HB_GTS_WS_MAXIMIZED )
   HB_gtInfo(HB_GTI_SPEC, HB_GTS_SHOWWINDOW, SW_NORMAL )
   
RETURN Nil

FUNCTION HB_GTSYS()
   REQUEST HB_GT_WVG_DEFAULT
   REQUEST HB_GT_WVT
   REQUEST HB_GT_WGU
   REQUEST HB_GT_WVG
RETURN Nil 

Alternativa a BlockInput

Enviado: 07 Jan 2016 16:19
por asimoes
Uma alternativa seria criar a rotina para ser executada externamente modal e invisivel. um .exe e ser executado dentro da aplicação principal.

Alternativa a BlockInput

Enviado: 07 Jan 2016 16:26
por André Corrêa
asimoes,

Obrigado pelas dicas.
Essa função Lockworkstation() pode funcionar, vou testar aqui.

Alternativa a BlockInput

Enviado: 08 Jan 2016 14:59
por André Corrêa
asimoes,

Fiz alguns testes com a LockWorkstations(), mas ela bloqueia a estação como a combinação de teclas [WIN] + [L].
Não seria viável para uso em rotinas comuns no sistema. Continuamos na busca.

Obrigado.

Alternativa a BlockInput

Enviado: 22 Jan 2016 11:16
por André Corrêa
Bom dia colegas!

Estou quase chegando a um resultado e gostaria de compartilhar.
Precisava de uma forma de bloquear o teclado, mas sem utilizar a função BLOCKINPUT() da API do Windows, pois
ela precisa ser executada como administrador, ou com a UAC desativada. No meu caso, nenhuma das alternativas
seria viável.
Decidi tentar encontrar uma forma de ler as entradas do teclado e fazer com que fossem anuladas antes de chegarem a
qualquer aplicação.
Consegui isso utilizando um Hook de teclado e anulando qualquer tecla pressionada. Segue o código:

Código: Selecionar todos

#pragma begindump

//#define WINVER 0x0500 //Win 2000
//#define WINVER 0x0501 //Win XP
#define WINVER 0x0601 //Win 7

#include    <windows.h>
#include    <stdlib.h>
#include    <hbapi.h>

#define WH_KEYBOARD_LL 13

  HINSTANCE hInst ; // Instance handle                                            

  HHOOK hhk = NULL;  //Handler para o hook


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) //Trata o retorno do Hook
{
    PKBDLLHOOKSTRUCT p;

    if (nCode == HC_ACTION) 
    {
        p = (PKBDLLHOOKSTRUCT) lParam;
        
		return 1; //Retoro maior que 0 = anula entrada do teclado.
   }
                    
   return CallNextHookEx(hhk, nCode, wParam, lParam);
}

//------------------------------------------------------------------------------

HB_FUNC (INSTALL_READ_KEYBOARD)
{

  hhk = SetWindowsHookEx (WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0 ); //Faz o Hook
  
}

//------------------------------------------------------------------------------

HB_FUNC (UNINSTALL_READ_KEYBOARD) //Desfaz o hook
{

 UnhookWindowsHookEx (hhk)
}

#pragma enddump
Vale lembrar que estou utilizando o Xailer e que esse código é um wrapper em C utilizando HB_FUNC para criar
as funções.
Já consigo travar e destravar o teclado, porém, se for utilizado um Sleep(), perde-se o Hook, devido a forma que o
Windows trata esta chamada.
Estou estudando uma forma de trocar o Sleep por um WaitableTimer, também da API do Windows, mas estou apanhando
um pouco.
Bom, fica aí o código, pois acredito que pode ser útil para quem queira anular qualquer entrada de teclado e não precise
utilizar o Sleep() para aguardar retornar.

Abraços.

Alternativa a BlockInput

Enviado: 22 Jan 2016 11:26
por asimoes
André,

Obrigado por compartilhar!

No seu código não vi a chamada do sleep, seria em alguma outra função em c ? e que neste caso anula a função.

Alternativa a BlockInput

Enviado: 22 Jan 2016 11:52
por André Corrêa
asimoes,

Eu removi a chamada do Sleep() devido a anular o Hook.
Na verdade, o Sleep() ficava no meu código, eu utilizo este hook diretamente no código, mas se for usado em uma DLL separada, também ocorre o erro.

Alternativa a BlockInput

Enviado: 22 Jan 2016 12:02
por asimoes
André,

Se alguma aplicação externa fizer uso do sleep, anula também a função de bloqueio?

Alternativa a BlockInput

Enviado: 22 Jan 2016 12:55
por André Corrêa
Nos testes que fiz, anulou.
Só para ficar claro, o Sleep() pode ser utilizado em outras partes do código,
só anula o Hook se for chamado enquanto ele estiver ativo.