mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
238 lines
4.9 KiB
ObjectPascal
238 lines
4.9 KiB
ObjectPascal
unit lua_server;
|
|
{
|
|
This unit will setup a communication to the lua engine
|
|
It will be responsible for receiving and dispatching messages
|
|
|
|
lua server waits for pipe connections and when made spawns a new thread(TLuaServerHandler) which
|
|
handles the communication while it itself is going back to listen to new connections.
|
|
|
|
}
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
jwawindows, windows, Classes, SysUtils, lua, lauxlib, lualib, LuaHandler;
|
|
|
|
type
|
|
TLuaServerHandler=class(TThread)
|
|
private
|
|
pipe: THandle;
|
|
exec: tstringlist;
|
|
result: qword;
|
|
procedure ExecuteLuaScript;
|
|
procedure ExecuteScript;
|
|
protected
|
|
procedure execute; override;
|
|
|
|
public
|
|
constructor create(pipe: THandle);
|
|
destructor destroy; override;
|
|
end;
|
|
|
|
TLuaServer=class(TThread)
|
|
private
|
|
fname: string;
|
|
protected
|
|
procedure execute; override;
|
|
public
|
|
constructor create(name: string);
|
|
destructor destroy; override;
|
|
property name: string read fname;
|
|
end;
|
|
|
|
// TLuaServers = TFPGList<TLuaServer>;
|
|
|
|
var luaservers: TList;
|
|
|
|
function luaserverExists(name: string): boolean;
|
|
|
|
implementation
|
|
|
|
resourcestring
|
|
rsALuaserverWithTheName = 'A luaserver with the name ';
|
|
rsAlreadyExists = ' already exists';
|
|
|
|
function luaserverExists(name: string): boolean;
|
|
var i: integer;
|
|
begin
|
|
result:=true;
|
|
for i:=0 to luaservers.count-1 do
|
|
if TLuaServer(luaservers[i]).name=name then exit;
|
|
|
|
result:=false;
|
|
end;
|
|
|
|
|
|
|
|
//--------TLuaServerHandler--------
|
|
|
|
constructor TLuaServerHandler.create(pipe: THandle);
|
|
begin
|
|
FreeOnTerminate:=true;
|
|
self.pipe:=pipe;
|
|
exec:=TStringlist.create;
|
|
inherited create(false);
|
|
end;
|
|
|
|
destructor TLuaServerHandler.destroy;
|
|
begin
|
|
exec.free;
|
|
inherited destroy;
|
|
end;
|
|
|
|
procedure TLuaServerHandler.ExecuteScript;
|
|
var
|
|
i: integer;
|
|
top: integer;
|
|
|
|
begin
|
|
LuaCS.Enter;
|
|
try
|
|
top:=lua_gettop(Luavm);
|
|
i:=luahandler.lua_dostring(luavm, pchar(exec.text));
|
|
if i=0 then
|
|
result:=lua_tointeger(Luavm, -1)
|
|
else
|
|
result:=0;
|
|
|
|
lua_settop(Luavm, top);
|
|
|
|
finally
|
|
luacs.leave;
|
|
end;
|
|
end;
|
|
|
|
procedure TLuaServerHandler.ExecuteLuaScript;
|
|
procedure error;
|
|
begin
|
|
OutputDebugString('Read error');
|
|
terminate;
|
|
end;
|
|
|
|
var
|
|
scriptsize: integer;
|
|
br: dword;
|
|
script: pchar;
|
|
|
|
parameter: qword;
|
|
begin
|
|
if readfile(pipe, scriptsize, sizeof(scriptsize), br, nil) then
|
|
begin
|
|
getmem(script, scriptsize+1);
|
|
|
|
try
|
|
if readfile(pipe, script^, scriptsize, br, nil) then
|
|
begin
|
|
script[scriptsize]:=#0;
|
|
|
|
if readfile(pipe, parameter, 8, br, nil) then
|
|
begin
|
|
exec.clear;
|
|
exec.Text:=script;
|
|
|
|
exec.Insert(0, 'function _luaservercall'+inttostr(GetCurrentThreadId)+'(parameter)');
|
|
exec.add('end');
|
|
exec.add('return _luaservercall'+inttostr(GetCurrentThreadId)+'('+inttostr(parameter)+')');
|
|
|
|
synchronize(executescript);
|
|
|
|
if writefile(pipe, result, 8, br, nil)=false then
|
|
error;
|
|
end
|
|
else
|
|
error;
|
|
end
|
|
else
|
|
error;
|
|
|
|
finally
|
|
freemem(script);
|
|
end;
|
|
end
|
|
else
|
|
error;
|
|
|
|
end;
|
|
|
|
procedure TLuaServerHandler.execute;
|
|
var
|
|
command: byte;
|
|
br: dword;
|
|
begin
|
|
try
|
|
while not terminated do
|
|
begin
|
|
ReadFile(pipe, command, sizeof(command), br, nil);
|
|
case command of
|
|
1: ExecuteLuaScript;
|
|
else terminate;
|
|
end;
|
|
end;
|
|
|
|
finally
|
|
CloseHandle(pipe);
|
|
end;
|
|
end;
|
|
|
|
|
|
//--------TLuaServer--------
|
|
|
|
procedure TLuaServer.execute;
|
|
var
|
|
pipe: THandle;
|
|
a: SECURITY_ATTRIBUTES;
|
|
begin
|
|
while not terminated do
|
|
begin
|
|
ZeroMemory(@a, sizeof(a));
|
|
a.nLength:=sizeof(a);
|
|
a.bInheritHandle:=TRUE;
|
|
|
|
//got this string from https://www.osronline.com/showThread.CFM?link=204207
|
|
ConvertStringSecurityDescriptorToSecurityDescriptor('D:(D;;FA;;;NU)(A;;0x12019f;;;WD)(A;;0x12019f;;;CO)', SDDL_REVISION_1, a.lpSecurityDescriptor, nil);
|
|
|
|
pipe:=CreateNamedPipe(pchar('\\.\pipe\'+name), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or PIPE_WAIT, 255, 16, 8192, 0, @a );
|
|
LocalFree(HLOCAL(a.lpSecurityDescriptor));
|
|
|
|
|
|
if ConnectNamedPipe(pipe, nil) or (GetLastError = ERROR_PIPE_CONNECTED) then
|
|
begin
|
|
//connected
|
|
//send this pipe of to the handler and create a new pipe
|
|
TLuaServerHandler.create(pipe);
|
|
end
|
|
else
|
|
begin
|
|
OutputDebugString('Lua server connect error');
|
|
CloseHandle(pipe); //failure, try again
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor TLuaServer.create(name: string);
|
|
var i: integer;
|
|
begin
|
|
fname:=name;
|
|
|
|
if luaserverExists(name) then
|
|
raise exception.create(rsALuaserverWithTheName+name+rsAlreadyExists);
|
|
|
|
luaservers.Add(self);
|
|
|
|
|
|
inherited create(false);
|
|
end;
|
|
|
|
destructor TLuaServer.destroy;
|
|
begin
|
|
inherited destroy;
|
|
end;
|
|
|
|
initialization
|
|
luaservers:=TList.create;
|
|
|
|
|
|
end.
|
|
|