www.pudn.com > ServerClient-tcp.rar > ServerDlg.pas
unit ServerDlg;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, WinSock, ScktComp, Menus, TrayIcon, FormSettings,
RemConMessages, ZLib, MsgSimulator, ComCtrls, ShellAPI;
type
TServerForm = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
LogList: TListBox;
ServerPanel: TPanel;
Label5: TLabel;
StartLab: TLabel;
Label9: TLabel;
ConLab: TLabel;
Label11: TLabel;
NumRecLab: TLabel;
Label13: TLabel;
NumSendLab: TLabel;
Label3: TLabel;
LastRecLab: TLabel;
Label4: TLabel;
NumErrLab: TLabel;
Panel1: TPanel;
Label1: TLabel;
NameLabel: TLabel;
Label2: TLabel;
PortEdit: TEdit;
Panel2: TPanel;
StartBut: TButton;
DisconBut: TButton;
MinimizeBut: TButton;
ClientBut: TButton;
ServerSocket1: TServerSocket;
TrayIcon1: TTrayIcon;
TrayMenu: TPopupMenu;
RemoteControl1: TMenuItem;
N1: TMenuItem;
Client1: TMenuItem;
N2: TMenuItem;
Shutdown1: TMenuItem;
FormSettings1: TFormSettings;
MsgSimulator1: TMsgSimulator;
Label6: TLabel;
PassEdit: TEdit;
procedure StartButClick(Sender: TObject);
procedure DisconButClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure MinimizeButClick(Sender: TObject);
procedure RemoteControl1Click(Sender: TObject);
procedure Shutdown1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Client1Click(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure ClientButClick(Sender: TObject);
protected
NumRec : double;
NumSend : double;
NumError : integer;
CurMsg : string;
LoggedOn : boolean;
CurBmp : TBitmap;
CurSocket : TCustomWinSocket;
CurHandle : THandle;
SleepTime : integer;
ViewMode : TViewMode;
CompMode : TCompressionLevel;
procedure UpdateStats;
procedure Log(const s: string);
procedure ProcessClick(const Data: string);
procedure ProcessDrag(const Data: string);
procedure Send_Screen_Update(Socket: TCustomWinSocket);
procedure SleepDone(Sender: TObject);
procedure ProcessKeys(const Data: string);
procedure CreateSleepThread;
procedure GetHostNameAddr;
procedure ParseComLine;
function Get_Process_List: string;
procedure CloseWindow(const Data: string);
procedure KillWindow(const Data: string);
function Get_Drive_List: string;
function GetDirectory(const PathName: string): string;
function GetFile(const PathName: string): string;
public
procedure EnableButs;
procedure ProcessMessage(const Msg: string; Socket: TCustomWinSocket);
procedure SendMsg(MsgNum: integer; const MsgData: string; Socket: TCustomWinSocket);
end;
var
ServerForm: TServerForm;
implementation
uses ClientFrm;
{$R *.DFM}
procedure TServerForm.StartButClick(Sender: TObject);
begin
with ServerSocket1 do begin
Port := StrToInt(PortEdit.Text);
Active := True;
end;
EnableButs;
end;
procedure TServerForm.DisconButClick(Sender: TObject);
begin
ServerSocket1.Active := False;
EnableButs;
end;
procedure TServerForm.EnableButs;
var
b : boolean;
begin
b := ServerSocket1.Active;
StartBut.Enabled := not b;
PortEdit.Enabled := not b;
DisconBut.Enabled := b;
// MinimizeBut.Enabled := b;
end;
procedure TServerForm.GetHostNameAddr;
var
buf : array[0..MAX_PATH] of char;
he : PHostEnt;
buf2 : PChar;
rc : integer;
begin
rc := GetHostName(buf, sizeof(buf));
if rc<>SOCKET_ERROR then begin
he := GetHostByName(buf);
if he = nil then begin
rc := WSAGetLastError;
NameLabel.Caption := Format('Socket Error %d = %s', [rc, SysErrorMessage(rc)]);
end else begin
buf2 := inet_ntoa(PInAddr(he.h_addr^)^);
NameLabel.Caption := Format('%s (%s)', [buf, buf2]);
end;
end else begin
NameLabel.Caption := 'Unknown Host';
end;
end;
procedure TServerForm.FormShow(Sender: TObject);
begin
EnableButs;
GetHostNameAddr;
end;
procedure TServerForm.MinimizeButClick(Sender: TObject);
begin
if ServerSocket1.Active then begin
TrayIcon1.ToolTip := Application.Title + ' - Port: ' + PortEdit.Text;
end else begin
TrayIcon1.ToolTip := Application.Title + ' - Inactive';
end;
TrayIcon1.Active := True;
ShowWindow(Application.Handle, SW_HIDE);
Hide;
end;
procedure TServerForm.RemoteControl1Click(Sender: TObject);
begin
TrayIcon1.Active := False;
ShowWindow(Application.Handle, SW_SHOW);
Application.Restore;
Show;
SetForegroundWindow(Handle);
end;
procedure TServerForm.Shutdown1Click(Sender: TObject);
begin
RemoteControl1Click(nil);
Close;
end;
procedure TServerForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FormSettings1.SaveSettings;
end;
procedure TServerForm.ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
begin
StartLab.Caption := CurTime;
NumRec := 0;
NumSend := 0;
CurMsg := '';
LoggedOn := False;
UpdateStats;
Log('Startup at ' + CurTime);
end;
procedure TServerForm.UpdateStats;
begin
ConLab.Caption := IntToStr(ServerSocket1.Socket.ActiveConnections);
NumRecLab.Caption := Format('%1.0n', [NumRec]);
NumSendLab.Caption := Format('%1.0n', [NumSend]);
NumErrLab.Caption := IntToStr(NumError);
end;
procedure TServerForm.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
s : string;
begin
Log(Format('%-20s %s', ['Recv Data', Socket.RemoteAddress]));
LastRecLab.Caption := CurTime;
s := Socket.ReceiveText;
NumRec := NumRec + Length(s);
UpdateStats;
CurMsg := CurMsg + s;
while IsValidMessage(CurMsg) do begin
s := TrimFirstMsg(CurMsg);
ProcessMessage(s, Socket);
end;
end;
procedure TServerForm.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Log(Format('%-20s %s', ['Connect', Socket.RemoteAddress]));
ViewMode := vmColor4;
CompMode := clDefault;
SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);
UpdateStats;
end;
procedure TServerForm.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Log(Format('%-20s %s', ['Disconnect', Socket.RemoteAddress]));
UpdateStats;
end;
procedure TServerForm.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Log(Format('%-20s %d', ['Error', ErrorCode]));
ErrorCode := 0;
Inc(NumError);
UpdateStats;
end;
procedure TServerForm.Log(const s: string);
begin
LogList.ItemIndex := LogList.Items.Add(s);
end;
procedure TServerForm.ProcessMessage(const Msg: string; Socket: TCustomWinSocket);
var
MsgNum, x: integer;
rc : integer;
Data : string;
bmp : TBitmap;
tmp : string;
begin
CurSocket := Socket;
Move(Msg[1], MsgNum, sizeof(integer));
Data := Copy(Msg, 9, Length(Msg));
Log(Format('%-20s %d', ['Message', MsgNum]));
if MsgNum = MSG_LOGON then begin
LoggedOn := (AnsiCompareText(Data, PassEdit.Text) = 0);
if LoggedOn then begin
SendMsg(MSG_LOGON, '1', Socket)
end else begin
SendMsg(MSG_LOGON, '0', Socket);
end;
exit;
end;
if not LoggedOn then begin
Log('Denied Access!');
SendMsg(MSG_STAT_MSG, 'Invalid Password', Socket);
Socket.Close;
exit;
end;
if MsgNum = MSG_REFRESH then begin
Log('Screen Capture');
SendMsg(MSG_STAT_MSG, 'Screen Capture', Socket);
GetScreen(bmp, ViewMode);
Log('Compressing Bitmap');
SendMsg(MSG_STAT_MSG, 'Screen Compression', Socket);
CompressBitmap(bmp, tmp);
SaveString(tmp, 'Temp1.txt');
SendMsg(MSG_REFRESH, tmp, Socket);
CurBmp.Assign(bmp);
bmp.Free;
end;
if MsgNum = MSG_SCREEN_UPDATE then begin
Send_Screen_Update(Socket);
end;
if MsgNum = MSG_CLICK then begin
SendMsg(MSG_STAT_MSG, 'Simulating Input', Socket);
ProcessClick(Data);
// SleepDone will be called when it is finished
end;
if MsgNum = MSG_DRAG then begin
SendMsg(MSG_STAT_MSG, 'Simulating Input', Socket);
ProcessDrag(Data);
// SleepDone will be called when it is finished
end;
if MsgNum = MSG_KEYS then begin
SendMsg(MSG_STAT_MSG, 'Simulating Input', Socket);
ProcessKeys(Data);
// SleepDone will be called when it is finished
end;
if MsgNum = MSG_SEVER_DELAY then begin
Move(Data[1], SleepTime, sizeof(integer));
SendMsg(MSG_SEVER_DELAY, '', Socket);
end;
if MsgNum = MSG_VIEW_MODE then begin
Move(Data[1], x, sizeof(integer));
ViewMode := TViewMode(x);
SendMsg(MSG_VIEW_MODE, '', Socket);
end;
if MsgNum = MSG_FOCUS_SERVER then begin
if TrayIcon1.Active then RemoteControl1Click(nil);
SetFocus;
CreateSleepThread;
// SleepDone will be called when it is finished
end;
if MsgNum = MSG_COMP_MODE then begin
Move(Data[1], x, sizeof(integer));
CompMode := TCompressionLevel(x);
SendMsg(MSG_COMP_MODE, '', Socket);
end;
if MsgNum = MSG_PRIORITY_MODE then begin
Move(Data[1], x, sizeof(integer));
SetThreadPriority(GetCurrentThread, x);
SendMsg(MSG_PRIORITY_MODE, '', Socket);
end;
if MsgNum = MSG_PROCESS_LIST then begin
SendMsg(MSG_PROCESS_LIST, Get_Process_List, Socket);
end;
if MsgNum = MSG_CLOSE_WIN then begin
CloseWindow(Data);
end;
if MsgNum = MSG_KILL_WIN then begin
KillWindow(Data);
end;
if MsgNum = MSG_DRIVE_LIST then begin
SendMsg(MSG_DRIVE_LIST, Get_Drive_List, Socket);
end;
if MsgNum = MSG_DIRECTORY then begin
SendMsg(MSG_DIRECTORY, GetDirectory(Data), Socket);
end;
if MsgNum = MSG_FILE then begin
SendMsg(MSG_FILE, GetFile(Data), Socket);
end;
if MsgNum = MSG_REMOTE_LAUNCH then begin
SendMsg(MSG_STAT_MSG, 'Launching File: ' + Data, Socket);
rc := ShellExecute(Handle, 'open', PChar(Data), nil, nil, SW_SHOWNORMAL);
if rc <= 32 then begin
Data := Format('ShellExecute Error #%d Launching %s', [rc, Data]);
SendMsg(MSG_REMOTE_LAUNCH, Data, Socket);
end else begin
SendMsg(MSG_REMOTE_LAUNCH, Data, Socket);
end;
end;
end;
function EnumWinProc(hw: THandle; lp: LParam): boolean; stdcall;
var
sl : TStringList;
buf : array[0..MAX_PATH] of char;
s, iv : string;
begin
sl := TStringList(lp);
GetWindowText(hw, buf, sizeof(buf));
if buf<>'' then begin
if IsWindowVisible(hw) then iv := '' else iv := '(Invisible)';
s := Format('%8.8x - %-32s %s', [hw, buf, iv]);
sl.AddObject(s, TObject(hw));
end;
Result := True;
end;
function TServerForm.Get_Process_List: string;
var
sl : TStringList;
begin
sl := TStringList.Create;
EnumWindows(@EnumWinProc, integer(sl));
Result := sl.Text;
sl.Free;
end;
function TServerForm.Get_Drive_List: string;
var
DriveBits : integer;
i : integer;
begin
Result := '';
DriveBits := GetLogicalDrives;
for i := 0 to 25 do begin
if (DriveBits and (1 shl i)) <> 0 then
Result := Result + Chr(Ord('A') + i) + ':\' + #13#10;
end;
end;
function TServerForm.GetDirectory(const PathName: string): string;
var
DirList : TStringList;
CommaList : TStringList;
sr : TSearchRec;
s : string;
dt : TDateTime;
begin
DirList := TStringList.Create;
CommaList := TStringList.Create;
if FindFirst(PathName, faAnyFile, sr) = 0 then repeat
CommaList.Clear;
s := sr.Name;
if (s = '.') or (s = '..') then continue;
if (sr.Attr and faDirectory) <> 0 then s := s + '\';
CommaList.Add(s);
s := Format('%1.0n', [sr.Size+0.0]);
CommaList.Add(s);
dt := FileDateToDateTime(sr.Time);
s := FormatDateTime('yyyy-mm-dd hh:nn ampm', dt);
CommaList.Add(s);
DirList.Add(CommaList.CommaText);
until FindNext(sr) <> 0;
FindClose(sr);
Result := DirList.Text;
CommaList.Free;
DirList.Free;
end;
function TServerForm.GetFile(const PathName: string): string;
var
fs : TFileStream;
begin
fs := TFileStream.Create(PathName, fmOpenRead or fmShareDenyWrite);
SetLength(Result, fs.Size);
fs.Read(Result[1], fs.Size);
fs.Free;
end;
procedure TServerForm.CloseWindow(const Data: string);
var
sl : TStringList;
i : integer;
hw : THandle;
begin
sl := TStringList.Create;
EnumWindows(@EnumWinProc, integer(sl));
i := sl.IndexOf(Data);
if i<>-1 then begin
hw := THandle(sl.Objects[i]);
SendMessage(hw, WM_CLOSE, 0, 0);
Sleep(SleepTime);
SendMsg(MSG_PROCESS_LIST, Get_Process_List, CurSocket);
end;
sl.Free;
end;
procedure TServerForm.KillWindow(const Data: string);
var
sl : TStringList;
i : integer;
hw : THandle;
ProcID : integer;
hProc : THandle;
begin
sl := TStringList.Create;
EnumWindows(@EnumWinProc, integer(sl));
i := sl.IndexOf(Data);
if i<>-1 then begin
hw := THandle(sl.Objects[i]);
GetWindowThreadProcessId(hw, @ProcID);
hProc := OpenProcess(PROCESS_ALL_ACCESS, False, ProcID);
TerminateProcess(hProc, DWORD(-1));
CloseHandle(hProc);
Sleep(SleepTime);
SendMsg(MSG_PROCESS_LIST, Get_Process_List, CurSocket);
end;
sl.Free;
end;
procedure TServerForm.SleepDone(Sender: TObject);
begin
Send_Screen_Update(CurSocket);
end;
procedure TServerForm.Send_Screen_Update(Socket: TCustomWinSocket);
var
bmp, dif : TBitmap;
R : TRect;
tmp : string;
begin
Log('Screen Capture');
SendMsg(MSG_STAT_MSG, 'Screen Capture', Socket);
GetScreen(bmp, ViewMode);
Log('Creating Diff Image');
dif := TBitmap.Create;
dif.Assign(bmp);
R := Rect(0, 0, dif.Width, dif.Height);
SendMsg(MSG_STAT_MSG, 'Screen Difference', Socket);
dif.Canvas.CopyMode := cmSrcInvert;
dif.Canvas.CopyRect(R, CurBmp.Canvas, R);
Log('Compressing Bitmap');
SendMsg(MSG_STAT_MSG, 'Screen Compression', Socket);
CompressBitmap(dif, tmp);
SendMsg(MSG_SCREEN_UPDATE, tmp, Socket);
CurBmp.Assign(bmp);
dif.Free;
bmp.Free;
end;
function GetMB(but: integer): TMouseButton;
begin
case but of
1 : Result := mbLeft;
2 : Result := mbRight;
else Result := mbLeft;
end;
end;
procedure TServerForm.ProcessClick(const Data: string);
var
x, y, i : integer;
num, but : integer;
p : TPoint;
begin
Move(Data[1], x, sizeof(integer));
Move(Data[1+4], y, sizeof(integer));
Move(Data[1+8], num, sizeof(integer));
Move(Data[1+12], but, sizeof(integer));
// Find the Window Handle
p := Point(x, y);
CurHandle := WindowFromPoint(p);
Assert(CurHandle<>0);
SetCursorPos(x, y);
// Create the Messages to send in the Hook procedure
with MsgSimulator1 do begin
Messages.Clear;
for i := 1 to num do
Add_ClickEx(0, GetMB(but), [], x, y, 1);
Play;
end;
CreateSleepThread;
end;
procedure TServerForm.ProcessDrag(const Data: string);
var
x, y : integer;
time : integer;
num, but : integer;
p : TPoint;
StartPt : TPoint;
StopPt : TPoint;
begin
Move(Data[1], but, sizeof(integer));
Move(Data[1+4], num, sizeof(integer));
Assert(num > 2);
// Create the Messages to send in the Hook procedure
// Mouse Down
Move(Data[(1-1)*12 + 9], x, sizeof(integer));
Move(Data[(1-1)*12 + 13], y, sizeof(integer));
Move(Data[(1-1)*12 + 17], time, sizeof(integer));
SetCursorPos(x, y);
// Find the Window Handle
p := Point(x, y);
CurHandle := WindowFromPoint(p);
Assert(CurHandle<>0);
with MsgSimulator1 do begin
Messages.Clear;
StartPt.X := x;
StartPt.Y := y;
Windows.ScreenToClient(CurHandle, StartPt);
Move(Data[(num-1)*12 + 9], x, sizeof(integer));
Move(Data[(num-1)*12 + 13], y, sizeof(integer));
StopPt.X := x;
StopPt.Y := y;
Windows.ScreenToClient(CurHandle, StopPt);
Add_Window_Drag(CurHandle, StartPt.X, StartPt.Y, StopPt.X, StopPt.Y);
Play;
end;
CreateSleepThread;
end;
procedure TServerForm.ProcessKeys(const Data: string);
begin
with MsgSimulator1 do begin
Messages.Clear;
Add_ASCII_Keys(Data);
Play;
end;
CreateSleepThread;
end;
procedure TServerForm.SendMsg(MsgNum: integer; const MsgData: string; Socket: TCustomWinSocket);
var
s : string;
begin
s := IntToByteStr(MsgNum) + IntToByteStr(Length(MsgData)) + MsgData;
Log(Format('%-20s %-4d %1.0n', ['Send', MsgNum, Length(s)+0.0]));
Socket.SendText(s);
NumSend := NumSend + Length(s);
UpdateStats;
end;
procedure TServerForm.FormCreate(Sender: TObject);
begin
CurBmp := TBitmap.Create;
SleepTime := 50;
ParseComLine;
end;
procedure TServerForm.FormDestroy(Sender: TObject);
begin
CurBmp.Free;
end;
type
TSleepThread = class(TThread)
public
SleepTime : integer;
procedure Execute; override;
end;
procedure TSleepThread.Execute;
begin
Sleep(SleepTime);
end;
procedure TServerForm.CreateSleepThread;
var
st : TSleepThread;
begin
st := TSleepThread.Create(True);
st.SleepTime := SleepTime;
st.OnTerminate := SleepDone;
st.Resume;
end;
procedure TServerForm.Client1Click(Sender: TObject);
begin
ClientForm.Show;
end;
procedure TServerForm.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
var
rc : integer;
begin
if ServerSocket1.Socket.ActiveConnections > 0 then begin
rc := MessageDlg('Clients are still connected, do you want to close?',
mtWarning, mbYesNoCancel, 0);
CanClose := (rc = mrYes);
end;
end;
procedure TServerForm.ParseComLine;
var
i : integer;
s : string;
AutoStart : boolean;
begin
AutoStart := False;
for i := 1 to ParamCount do begin
s := UpperCase(ParamStr(i));
if Copy(s, 1, 6) = '/PORT:' then begin
PortEdit.Text := Copy(s, 7, Length(s));
AutoStart := True;
StartButClick(nil);
MinimizeButClick(nil);
end;
if s = '/CLIENT' then begin
MinimizeButClick(nil);
AutoStart := True;
end;
end;
if not AutoStart then
Visible := True;
end;
procedure TServerForm.ClientButClick(Sender: TObject);
begin
ClientForm.Show;
end;
end.