program HideRDPxButtoN;
{$R HideRDPxButtoN.res}
uses Windows, Messages;

var
  m: TMsg;
  wndClass:TWndClass;
  MyWnd:HWND;
  strMsg: PChar;

//==============================================================================
function EnumProc(wnd:HWND; lPar:LPARAM):BOOL; stdcall;
var
  ClassName:PChar;
begin
  Result:= True;
  GetMem(ClassName,255);
  GetClassName(wnd,ClassName,254);
  if lstrcmpi(ClassName,PChar('#32770')) = 0 then begin
    Result:=False;
    //забавно, но с WM_CLOSE касперский определяет нас как
    //Trojan-Downloader.Win32.Agent.xi
    //SendMessage(Wnd, WM_CLOSE, 0, 0);
    SendMessage(Wnd, WM_COMMAND, MAKEWPARAM(2, BN_CLICKED), 0);
  end;
  FreeMem(ClassName);
end;

//==============================================================================
//через определенное время 
//(значения ключей реестра HungAppTimeout (5sec) и WaitToKillAppTimeout(20sec))
//если не нажать на MessageBox то программа считается зависшей и всёравно
//закрывается, и выключение компьютера, соответственно, продолжается
//поэтому покажем сообщение только на 3 секунды
procedure CloseMsgBox();
begin
  EnumThreadWindows(GetCurrentThreadId,@EnumProc,0);
end;

//==============================================================================
procedure FindTSWindow();
var
  rcBtn,rcPanel: TRect;
  wnd, wnd2: HWND;
begin
  wnd := FindWindow('TSSHELLWND',nil);
  if wnd > 0 then begin
    DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
    wnd:= FindWindowEx(Wnd,0,'TSCAXHOST',nil);
    if wnd > 0 then begin
      wnd:= FindWindowEx(Wnd,0,nil,nil);
      if wnd > 0 then begin
        wnd:= FindWindowEx(wnd,0,'UIMainClass',nil);
        if wnd > 0 then begin
          wnd:= FindWindowEx(wnd,0,'BBARCLASS',nil);
          if wnd > 0 then begin
            GetWindowRect(wnd,rcPanel);
            wnd:= FindWindowEx(wnd,0,'ToolbarWindow32',nil);
            if wnd > 0 then begin
              GetWindowRect(wnd,rcBtn);
              MoveWindow(wnd,rcBtn.Left-rcPanel.Left,rcBtn.Top-rcPanel.Top,40,rcBtn.Bottom - rcBtn.Top {22},true);
            end;
          end;
        end;
      end;
    end;
  end;

  //ищем панель RDP клиента от XP_SP3, Vista и Windows7

  //уберем пункт меню "Закрыть". Панель теперь не является child'ом главного окна RDP, его надо найти отдельно.
  wnd2 := FindWindow('TscShellContainerClass',nil);
  if wnd2 > 0 then DeleteMenu(GetSystemMenu(wnd2, FALSE), SC_CLOSE, MF_BYCOMMAND);

  wnd := FindWindow('BBarWindowClass','BBar');
  if wnd > 0 then begin
    GetWindowRect(wnd,rcPanel);
    //на панели два окна ToolbarWindow32, ищем то, что справа
    wnd2:= FindWindowEx(wnd,0,'ToolbarWindow32',nil);
    GetWindowRect(wnd2,rcBtn);
    if not (rcBtn.Left > (((rcPanel.Right - rcPanel.Left) div 2) + rcPanel.Left)) then begin
      wnd2:= FindWindowEx(Wnd,wnd2,'ToolbarWindow32',nil);
      GetWindowRect(wnd2,rcBtn);
      if not (rcBtn.Left > (((rcPanel.Right - rcPanel.Left) div 2) + rcPanel.Left)) then wnd2 := 0;
    end;
    if wnd2 > 0 then begin
      MoveWindow(wnd2,rcBtn.Left-rcPanel.Left,rcBtn.Top-rcPanel.Top,40,rcBtn.Bottom - rcBtn.Top,true);
    end;
  end;
end;

//==============================================================================
function WndProc(wnd:HWND;msg:UInt;wPar:WPARAM;lPar:LPARAM):longint;stdcall;
var
  w: HWND;
begin
  Result:=DefWindowProc(Wnd,msg,wPar,lPar);
  case msg of
    WM_QUERYENDSESSION: begin
      w := FindWindow('TSSHELLWND',nil);
      if w = 0 then w := FindWindow('BBarWindowClass','BBar');
      if w > 0 then begin
        Result := 0;
        SetTimer(MyWnd, 10002, 3000, nil);
        MessageBox(0,strMsg,'Внимание',MB_OK or MB_ICONWARNING);
        ShowWindow(w,SW_SHOWNORMAL);
      end;
    end;

    WM_TIMER: begin
      if wPar = 10001 then FindTSWindow();
      if wPar = 10002 then begin
        KillTimer(MyWnd, 10002);
        CloseMsgBox();
      end;
    end;
  end;
end;

begin
  //проверка на повторный запуск
  if FindWindow(PChar('3969EA09_9580_4F37_81CA_7527E9D78080'),nil) > 0 then exit;

  FillChar(wndClass,SizeOf(wndClass),0);
  with wndClass do begin
    lpfnWndProc:=@WndProc;
    lpszClassName:=PChar('3969EA09_9580_4F37_81CA_7527E9D78080');
    hInstance:=SysInit.hInstance;
  end;
  RegisterClass(wndClass);
  MyWnd:=CreateWindow(wndClass.lpszClassName,nil,0,0,0,0,0,0,0,wndClass.hInstance,nil);
  if MyWnd = 0 then Exit;

  GetMem(strMsg,255);
  LoadString(SysInit.HInstance,1,strMsg,254);
  //FindTSWindow();
  SetTimer(MyWnd, 10001, 10000, nil);

  while GetMessage(m,0,0,0) do DispatchMessage(m);
  KillTimer(MyWnd, 10001);
end.

