mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
b586dfe33b
commit
a25aed2dba
12
fpPS4.lpi
12
fpPS4.lpi
|
@ -598,6 +598,18 @@
|
|||
<Filename Value="sys\host_ipc.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="sys\md\md_pipe.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="sys\md\md_host_ipc.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="rtl\evbuffer.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -8,13 +8,17 @@ uses
|
|||
windows,
|
||||
Classes,
|
||||
SysUtils,
|
||||
md_pipe,
|
||||
host_ipc,
|
||||
md_host_ipc,
|
||||
game_info;
|
||||
|
||||
var
|
||||
//FLogUpdate:Integer=0;
|
||||
|
||||
t_wr_handle:THandle;
|
||||
|
||||
mgui_ipc:THostIpcConnect=nil;
|
||||
kern_ipc:THostIpcConnect=nil;
|
||||
|
||||
procedure run_item(Item:TGameItem);
|
||||
|
||||
implementation
|
||||
|
@ -31,7 +35,6 @@ uses
|
|||
md_exception, //<- install custom
|
||||
|
||||
kern_proc,
|
||||
host_ipc,
|
||||
md_systm,
|
||||
|
||||
//internal libs
|
||||
|
@ -47,16 +50,6 @@ uses
|
|||
var
|
||||
runing:Boolean=False;
|
||||
|
||||
procedure WakeMainThread;
|
||||
begin
|
||||
//System.InterlockedIncrement(FLogUpdate);
|
||||
|
||||
if Assigned(Classes.WakeMainThread) then
|
||||
begin
|
||||
Classes.WakeMainThread(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure re_init_tty; register;
|
||||
var
|
||||
i:Integer;
|
||||
|
@ -65,18 +58,18 @@ begin
|
|||
begin
|
||||
//std_tty[i].t_rd_handle:=GetStdHandle(STD_INPUT_HANDLE);
|
||||
//std_tty[i].t_wr_handle:=t_wr_handle;
|
||||
std_tty[i].t_update :=@WakeMainThread;
|
||||
//std_tty[i].t_update :=@WakeMainThread;
|
||||
end;
|
||||
|
||||
For i:=0 to High(deci_tty) do
|
||||
begin
|
||||
//deci_tty[i].t_rd_handle:=GetStdHandle(STD_INPUT_HANDLE);
|
||||
//deci_tty[i].t_wr_handle:=t_wr_handle;
|
||||
deci_tty[i].t_update :=@WakeMainThread;
|
||||
//deci_tty[i].t_update :=@WakeMainThread;
|
||||
end;
|
||||
|
||||
//debug_tty.t_wr_handle:=t_wr_handle;
|
||||
debug_tty.t_update :=@WakeMainThread;
|
||||
//debug_tty.t_update :=@WakeMainThread;
|
||||
end;
|
||||
|
||||
procedure prepare(Item:TGameItem); SysV_ABI_CDecl;
|
||||
|
@ -86,8 +79,6 @@ var
|
|||
len:Integer;
|
||||
exec:array[0..PATH_MAX] of Char;
|
||||
argv:array[0..1] of PChar;
|
||||
|
||||
host_ipc:THostIpcConnect;
|
||||
begin
|
||||
//re_init_tty;
|
||||
//init_tty:=@re_init_tty;
|
||||
|
@ -95,17 +86,15 @@ begin
|
|||
//init all
|
||||
sys_init;
|
||||
|
||||
Writeln('Hollo World!');
|
||||
PROC_INIT_HOST_IPC(kern_ipc);
|
||||
|
||||
Writeln(Item.FGameInfo.Exec);
|
||||
|
||||
//host_ipc:=THostIpcConnect(THostIpcSimpleKERN.Create);
|
||||
//PROC_INIT_HOST_IPC(host_ipc);
|
||||
|
||||
Writeln(Item.FMountList.app0);
|
||||
Writeln(Item.FMountList.system);
|
||||
Writeln(Item.FMountList.data);
|
||||
|
||||
|
||||
|
||||
//fs guest host
|
||||
err:=vfs_mount_mkdir('ufs','/app0' ,pchar(Item.FMountList.app0 ),nil,0);
|
||||
Assert(err=0);
|
||||
|
@ -162,11 +151,16 @@ var
|
|||
td:p_kthread;
|
||||
r:Integer;
|
||||
|
||||
pipefd:THandle;
|
||||
parent:THandle;
|
||||
|
||||
mem:TPCharStream;
|
||||
Item:TGameItem;
|
||||
begin
|
||||
mem:=TPCharStream.Create(data,size);
|
||||
|
||||
mem.Read(pipefd,SizeOf(THandle));
|
||||
|
||||
Item:=TGameItem.Create;
|
||||
Item.Deserialize(mem);
|
||||
|
||||
|
@ -175,9 +169,12 @@ begin
|
|||
//free shared
|
||||
md_fork_unshare;
|
||||
|
||||
//sys_init;
|
||||
parent:=md_pidfd_open(md_getppid);
|
||||
|
||||
//sleep(-1);
|
||||
pipefd:=md_pidfd_getfd(parent,pipefd);
|
||||
|
||||
kern_ipc:=THostIpcConnect(THostIpcPipeKERN.Create);
|
||||
THostIpcPipeKERN(kern_ipc).set_pipe(pipefd);
|
||||
|
||||
td:=nil;
|
||||
r:=kthread_add(@prepare,Item,@td,'[main]');
|
||||
|
@ -186,11 +183,16 @@ begin
|
|||
sleep(-1);
|
||||
end;
|
||||
|
||||
const
|
||||
fork_proc:Boolean=True;
|
||||
|
||||
procedure run_item(Item:TGameItem);
|
||||
var
|
||||
td:p_kthread;
|
||||
r:Integer;
|
||||
|
||||
kern2mgui:array[0..1] of THandle;
|
||||
|
||||
mem:TMemoryStream;
|
||||
begin
|
||||
if Item.FLock then Exit;
|
||||
|
@ -200,21 +202,36 @@ begin
|
|||
SetStdHandle(STD_ERROR_HANDLE ,t_wr_handle);
|
||||
SetStdHandle(STD_OUTPUT_HANDLE,t_wr_handle);
|
||||
|
||||
mem:=TMemoryStream.Create;
|
||||
if fork_proc then
|
||||
begin
|
||||
md_pipe2(@kern2mgui,MD_PIPE_ASYNC0 or MD_PIPE_ASYNC1);
|
||||
|
||||
Item.Serialize(mem);
|
||||
mgui_ipc:=THostIpcConnect(THostIpcPipeMGUI.Create);
|
||||
THostIpcPipeMGUI(mgui_ipc).set_pipe(kern2mgui[0]);
|
||||
|
||||
//mem.Position:=0;
|
||||
//
|
||||
|
||||
md_fork_process(@fork_process,mem.Memory,mem.Size);
|
||||
mem:=TMemoryStream.Create;
|
||||
|
||||
mem.Free;
|
||||
mem.Write(kern2mgui[1],SizeOf(THandle));
|
||||
|
||||
{
|
||||
td:=nil;
|
||||
r:=kthread_add(@prepare,Item,@td,'[main]');
|
||||
Assert(r=0);
|
||||
}
|
||||
Item.Serialize(mem);
|
||||
|
||||
md_fork_process(@fork_process,mem.Memory,mem.Size);
|
||||
|
||||
mem.Free;
|
||||
end else
|
||||
begin
|
||||
kern_ipc:=THostIpcConnect(THostIpcSimpleKERN.Create);
|
||||
mgui_ipc:=THostIpcConnect(THostIpcSimpleMGUI.Create);
|
||||
|
||||
THostIpcSimpleKERN(kern_ipc).FDest:=THostIpcSimpleMGUI(mgui_ipc);
|
||||
THostIpcSimpleMGUI(mgui_ipc).FDest:=THostIpcSimpleKERN(kern_ipc);
|
||||
|
||||
td:=nil;
|
||||
r:=kthread_add(@prepare,Item,@td,'[main]');
|
||||
Assert(r=0);
|
||||
end;
|
||||
|
||||
runing:=True;
|
||||
end;
|
||||
|
|
34
gui/main.pas
34
gui/main.pas
|
@ -8,7 +8,9 @@ uses
|
|||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, Grids, Menus,
|
||||
|
||||
game_info,
|
||||
game_edit;
|
||||
game_edit,
|
||||
|
||||
host_ipc;
|
||||
|
||||
type
|
||||
|
||||
|
@ -73,6 +75,9 @@ uses
|
|||
TypInfo,
|
||||
Rtti,
|
||||
|
||||
evbuffer,
|
||||
evpoll,
|
||||
|
||||
game_run;
|
||||
|
||||
//
|
||||
|
@ -113,6 +118,20 @@ var
|
|||
const
|
||||
section_prefix='game-';
|
||||
|
||||
type
|
||||
TGuiIpcHandler=class(THostIpcHandler)
|
||||
Form:TfrmMain;
|
||||
Procedure OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer); override;
|
||||
end;
|
||||
|
||||
Procedure TGuiIpcHandler.OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
begin
|
||||
ShowMessage(GetEnumName(TypeInfo(mtype),ord(mtype)));
|
||||
end;
|
||||
|
||||
var
|
||||
IpcHandler:TGuiIpcHandler;
|
||||
|
||||
procedure TfrmMain.ReadIniFile;
|
||||
var
|
||||
i,c:Integer;
|
||||
|
@ -121,6 +140,9 @@ var
|
|||
List:TStringList;
|
||||
Item:TGameItem;
|
||||
begin
|
||||
IpcHandler:=TGuiIpcHandler.Create;
|
||||
IpcHandler.Form:=Self;
|
||||
|
||||
//main
|
||||
FMainInfo.ReadIni(FIniFile,'main');
|
||||
//main
|
||||
|
@ -262,18 +284,20 @@ procedure TfrmMain.OnIdleUpdate(Sender:TObject;var Done:Boolean);
|
|||
begin
|
||||
Done:=True;
|
||||
|
||||
if (GetTickCount64-FLogUpdateTime)>500 then
|
||||
if (GetTickCount64-FLogUpdateTime)>100 then
|
||||
begin
|
||||
|
||||
//if (System.InterlockedExchange(FLogUpdate,0)<>0) then
|
||||
if (FList<>nil) then
|
||||
begin
|
||||
FList.Update;
|
||||
end;
|
||||
|
||||
FLogUpdateTime:=GetTickCount64;
|
||||
end;
|
||||
|
||||
if (mgui_ipc<>nil) then
|
||||
begin
|
||||
mgui_ipc.Update(IpcHandler);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TfrmMain.MIAddClick(Sender: TObject);
|
||||
|
|
|
@ -238,34 +238,13 @@ end;
|
|||
|
||||
procedure TSynEditLineStream.Reset;
|
||||
var
|
||||
i,c,ffcnt,delta:Integer;
|
||||
tend:Boolean;
|
||||
ffcnt,delta:Integer;
|
||||
begin
|
||||
BeginUpdate;
|
||||
//
|
||||
i:=FSynLog.TopLine+FSynLog.LinesInWindow+3;
|
||||
//
|
||||
FStream.Reset;
|
||||
ffcnt:=FStream.GetCount;
|
||||
delta:=FStream.Update;
|
||||
//
|
||||
tend:=(i>=ffcnt);
|
||||
//
|
||||
if tend then
|
||||
begin
|
||||
i:=FSynLog.LinesInWindow;
|
||||
c:=FStream.GetCount;
|
||||
//
|
||||
if (c>i) then
|
||||
begin
|
||||
i:=c-i+1;
|
||||
end else
|
||||
begin
|
||||
i:=1;
|
||||
end;
|
||||
//
|
||||
FSynLog.TopLine:=i;
|
||||
end;
|
||||
FStream.Reset;
|
||||
delta:=-ffcnt;
|
||||
//
|
||||
IncreaseTextChangeStamp;
|
||||
//
|
||||
|
|
|
@ -0,0 +1,571 @@
|
|||
{ IO event buffer
|
||||
|
||||
Copyright (C) 2018-2023 Red_prig
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version with the following modification:
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,and
|
||||
to copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the terms
|
||||
and conditions of the license of that module. An independent module is a
|
||||
module which is not derived from or based on this library. If you modify
|
||||
this library, you may extend this exception to your version of the library,
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
||||
for more details.
|
||||
}
|
||||
|
||||
unit evbuffer;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
atomic;
|
||||
|
||||
type
|
||||
TfuncFree=Function(p:pointer):SizeUInt; register;
|
||||
|
||||
Peviovec=^Teviovec;
|
||||
Teviovec=object
|
||||
private
|
||||
next_:Peviovec;
|
||||
public
|
||||
base:Pointer;
|
||||
len :SizeUInt;
|
||||
pos :SizeUInt;
|
||||
buf_free:TfuncFree;
|
||||
vec_free:TfuncFree;
|
||||
end;
|
||||
|
||||
Pevbuffer=^Tevbuffer;
|
||||
Tevbuffer=object
|
||||
private
|
||||
Var
|
||||
len :SizeUInt;
|
||||
tail_,head_:Peviovec;
|
||||
stub_:Pointer;
|
||||
public
|
||||
end;
|
||||
|
||||
Procedure eviovec_free(P:Peviovec);
|
||||
function eviovec_next(buf:Pevbuffer;vec:Peviovec):Peviovec;
|
||||
function eviovec_getdata(vec:Peviovec):Pointer;
|
||||
function eviovec_getlen(vec:Peviovec):SizeUInt;
|
||||
|
||||
procedure evbuffer_init(buf:Pevbuffer);
|
||||
function evbuffer_new:Pevbuffer;
|
||||
procedure evbuffer_free(buf:Pevbuffer);
|
||||
procedure evbuffer_clear(buf:Pevbuffer);
|
||||
Function evbuffer_isempty(buf:Pevbuffer):Boolean;
|
||||
|
||||
function evbuffer_push(buf:Pevbuffer;Node:Peviovec):Boolean;
|
||||
function evbuffer_pop(buf:Pevbuffer):Peviovec;
|
||||
function evbuffer_peek(buf:Pevbuffer):Peviovec;
|
||||
function evbuffer_add_ref(buf:Pevbuffer;data:pointer;datapos,datalen:SizeUInt;ff:TfuncFree):Boolean;
|
||||
function evbuffer_remove_ref(buf:Pevbuffer;var data:pointer;var datapos,datalen:SizeUInt;var ff:TfuncFree):Boolean;
|
||||
function evbuffer_add(buf:Pevbuffer;data:pointer;datalen:SizeUInt):Boolean;
|
||||
function evbuffer_remove(buf:Pevbuffer;data:pointer;datalen:SizeUInt):SizeUInt;
|
||||
function evbuffer_copy(buf:Pevbuffer;data:pointer;datalen:SizeUInt):SizeUInt;
|
||||
function evbuffer_drain(buf:Pevbuffer;datalen:SizeUInt):SizeUInt;
|
||||
function evbuffer_get_length(buf:Pevbuffer):SizeUInt;
|
||||
function evbuffer_get_contiguous_space(buf:Pevbuffer):SizeUInt;
|
||||
function evbuffer_get_atmost_size(buf:Pevbuffer;size:SizeUint):SizeUInt;
|
||||
function evbuffer_get_atless_size(buf:Pevbuffer;size:SizeUint):SizeUInt;
|
||||
function evbuffer_move(Src,Dst:Pevbuffer):SizeUInt;
|
||||
function evbuffer_move_length(Src,Dst:Pevbuffer;length:SizeUInt):SizeUInt;
|
||||
|
||||
function Freemem_ptr:TfuncFree;
|
||||
|
||||
implementation
|
||||
|
||||
function Freemem_ptr:TfuncFree;
|
||||
Var
|
||||
MemMgr:TMemoryManager;
|
||||
begin
|
||||
MemMgr:=Default(TMemoryManager);
|
||||
GetMemoryManager(MemMgr);
|
||||
Result:=MemMgr.Freemem;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure eviovec_free(P:Peviovec);
|
||||
begin
|
||||
if not Assigned(P) then Exit;
|
||||
if Assigned(P^.buf_free) then
|
||||
begin
|
||||
P^.buf_free(P^.base);
|
||||
end;
|
||||
if Assigned(P^.vec_free) then
|
||||
begin
|
||||
P^.vec_free(P);
|
||||
end;
|
||||
end;
|
||||
|
||||
function eviovec_next(buf:Pevbuffer;vec:Peviovec):Peviovec;
|
||||
Var
|
||||
tail,n:Peviovec;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (not Assigned(buf)) or
|
||||
(not Assigned(vec)) then Exit;
|
||||
With vec^ do
|
||||
begin
|
||||
tail:=vec^.next_;
|
||||
if not Assigned(tail) then Exit;
|
||||
n:=load_consume(tail^.next_);
|
||||
if tail=@buf^.stub_ then
|
||||
begin
|
||||
if n=nil then Exit;
|
||||
tail:=n;
|
||||
end;
|
||||
Result:=tail;
|
||||
end;
|
||||
end;
|
||||
|
||||
function eviovec_getdata(vec:Peviovec):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if not Assigned(vec) then Exit;
|
||||
Result:=@PByte(vec^.base)[vec^.pos];
|
||||
end;
|
||||
|
||||
function eviovec_getlen(vec:Peviovec):SizeUInt;
|
||||
begin
|
||||
Result:=0;
|
||||
if not Assigned(vec) then Exit;
|
||||
Result:=vec^.len;
|
||||
end;
|
||||
|
||||
//--evbuffer--
|
||||
|
||||
procedure evbuffer_init(buf:Pevbuffer);
|
||||
begin
|
||||
if not Assigned(buf) then Exit;
|
||||
buf^:=Default(Tevbuffer);
|
||||
With buf^ do
|
||||
begin
|
||||
head_:=Peviovec(@stub_);
|
||||
tail_:=Peviovec(@stub_);
|
||||
end;
|
||||
ReadWriteBarrier;
|
||||
end;
|
||||
|
||||
function evbuffer_new:Pevbuffer;
|
||||
begin
|
||||
Result:=GetMem(SizeOf(Tevbuffer));
|
||||
evbuffer_init(Result);
|
||||
end;
|
||||
|
||||
procedure evbuffer_free(buf:Pevbuffer);
|
||||
begin
|
||||
if not Assigned(buf) then Exit;
|
||||
evbuffer_clear(buf);
|
||||
FreeMem(buf);
|
||||
end;
|
||||
|
||||
procedure evbuffer_clear(buf:Pevbuffer);
|
||||
Var
|
||||
Node:Peviovec;
|
||||
begin
|
||||
if not Assigned(buf) then Exit;
|
||||
repeat
|
||||
Node:=evbuffer_pop(buf);
|
||||
eviovec_free(Node);
|
||||
until (Node=nil);
|
||||
end;
|
||||
|
||||
Function evbuffer_isempty(buf:Pevbuffer):Boolean;
|
||||
begin
|
||||
if not Assigned(buf) then Exit(true);
|
||||
Result:=(load_acquire(buf^.head_)=@buf^.stub_);
|
||||
end;
|
||||
|
||||
function evbuffer_push(buf:Pevbuffer;Node:Peviovec):Boolean;
|
||||
Var
|
||||
prev:Peviovec;
|
||||
begin
|
||||
if (not Assigned(buf)) or (not Assigned(Node)) then Exit(False);
|
||||
With buf^ do
|
||||
begin
|
||||
store_release(Node^.next_,nil);
|
||||
prev:=XCHG(head_,Node);
|
||||
store_release(prev^.next_,Node);
|
||||
fetch_add(len,Node^.len);
|
||||
end;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
function evbuffer_pop(buf:Pevbuffer):Peviovec;
|
||||
Var
|
||||
tail,n,head:Peviovec;
|
||||
begin
|
||||
Result:=nil;
|
||||
if not Assigned(buf) then Exit;
|
||||
With buf^ do
|
||||
begin
|
||||
tail:=tail_;
|
||||
n:=load_consume(tail^.next_);
|
||||
|
||||
if tail=@stub_ then
|
||||
begin
|
||||
if n=nil then Exit;
|
||||
store_release(tail_,n);
|
||||
tail:=n;
|
||||
n:=load_consume(n^.next_);
|
||||
end;
|
||||
|
||||
if n<>nil then
|
||||
begin
|
||||
store_release(tail_,n);
|
||||
Result:=tail;
|
||||
store_release(tail^.next_,nil);
|
||||
fetch_sub(len,Result^.len);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
head:=head_;
|
||||
if tail<>head then Exit;
|
||||
|
||||
stub_:=nil;
|
||||
n:=XCHG(head_,@stub_);
|
||||
store_release(n^.next_,@stub_);
|
||||
|
||||
n:=load_consume(tail^.next_);
|
||||
|
||||
if n<>nil then
|
||||
begin
|
||||
store_release(tail_,n);
|
||||
Result:=tail;
|
||||
store_release(tail^.next_,nil);
|
||||
fetch_sub(len,Result^.len);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_peek(buf:Pevbuffer):Peviovec;
|
||||
Var
|
||||
tail,n:Peviovec;
|
||||
begin
|
||||
Result:=nil;
|
||||
if not Assigned(buf) then Exit;
|
||||
With buf^ do
|
||||
begin
|
||||
tail:=tail_;
|
||||
if not Assigned(tail) then Exit;
|
||||
n:=load_consume(tail^.next_);
|
||||
if tail=@stub_ then
|
||||
begin
|
||||
if not Assigned(n) then Exit;
|
||||
tail:=n;
|
||||
end;
|
||||
Result:=tail;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_get_atmost_size(buf:Pevbuffer;size:SizeUint):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if size=0 then Exit;
|
||||
vec:=evbuffer_peek(buf);
|
||||
if not Assigned(vec) then Exit;
|
||||
Result:=vec^.len;
|
||||
if Result>=size then
|
||||
begin
|
||||
Result:=size;
|
||||
end else
|
||||
begin
|
||||
repeat
|
||||
vec:=eviovec_next(buf,vec);
|
||||
if not Assigned(vec) then Break;
|
||||
if Result+vec^.len>size then Break;
|
||||
Result:=Result+vec^.len;
|
||||
until false;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_get_atless_size(buf:Pevbuffer;size:SizeUint):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if size=0 then Exit;
|
||||
vec:=evbuffer_peek(buf);
|
||||
if not Assigned(vec) then Exit;
|
||||
Result:=vec^.len;
|
||||
if Result<size then
|
||||
begin
|
||||
repeat
|
||||
vec:=eviovec_next(buf,vec);
|
||||
if not Assigned(vec) then Break;
|
||||
Result:=Result+vec^.len;
|
||||
if Result>=size then Break;
|
||||
until false;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_move(Src,Dst:Pevbuffer):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if Assigned(Dst) then
|
||||
repeat
|
||||
vec:=evbuffer_pop(Src);
|
||||
if vec=nil then Exit;
|
||||
Result:=Result+vec^.len;
|
||||
evbuffer_push(Dst,vec);
|
||||
until false;
|
||||
end;
|
||||
|
||||
function evbuffer_move_length(Src,Dst:Pevbuffer;length:SizeUInt):SizeUInt;
|
||||
var
|
||||
i:SizeUInt;
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if Assigned(Dst) then
|
||||
repeat
|
||||
vec:=evbuffer_peek(Src);
|
||||
if vec=nil then Exit;
|
||||
i:=Result+vec^.len;
|
||||
if i>length then
|
||||
begin
|
||||
i:=length-Result;
|
||||
evbuffer_add(Dst,eviovec_getdata(vec),i);
|
||||
evbuffer_drain(Src,i);
|
||||
Result:=length;
|
||||
Exit;
|
||||
end else
|
||||
begin
|
||||
evbuffer_push(Dst,evbuffer_pop(Src));
|
||||
Result:=i;
|
||||
if length=Result then Exit;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
Var
|
||||
cache_peviovec:Peviovec=nil;
|
||||
|
||||
Function get_peviovec:peviovec;
|
||||
begin
|
||||
Result:=XCHG(cache_peviovec,nil);
|
||||
if Result=nil then
|
||||
begin
|
||||
Result:=GetMem(SizeOf(Teviovec));
|
||||
end;
|
||||
end;
|
||||
|
||||
Function free_peviovec(p:pointer):SizeUInt;
|
||||
begin
|
||||
Result:=FreeMem(XCHG(cache_peviovec,p));
|
||||
end;
|
||||
|
||||
function evbuffer_add_ref(buf:Pevbuffer;data:pointer;datapos,datalen:SizeUInt;ff:TfuncFree):Boolean;
|
||||
Var
|
||||
Node:Peviovec;
|
||||
begin
|
||||
Result:=False;
|
||||
if (not Assigned(buf)) or
|
||||
(not Assigned(data)) or
|
||||
(datalen=0) then Exit;
|
||||
//Node:=GetMem(SizeOf(Teviovec));
|
||||
Node:=get_peviovec;
|
||||
if Node=nil then Exit;
|
||||
With Node^ do
|
||||
begin
|
||||
base:=data;
|
||||
len:=datalen;
|
||||
pos:=datapos;
|
||||
buf_free:=ff;
|
||||
//vec_free:=Freemem_ptr;
|
||||
vec_free:=@free_peviovec;
|
||||
end;
|
||||
Result:=evbuffer_push(buf,Node);
|
||||
end;
|
||||
|
||||
function evbuffer_remove_ref(buf:Pevbuffer;var data:pointer;var datapos,datalen:SizeUInt;var ff:TfuncFree):Boolean;
|
||||
Var
|
||||
Node:Peviovec;
|
||||
begin
|
||||
Node:=evbuffer_pop(buf);
|
||||
Result:=Assigned(Node);
|
||||
if Result then
|
||||
begin
|
||||
data :=Node^.base;
|
||||
datapos:=Node^.pos;
|
||||
datalen:=Node^.len;
|
||||
ff :=Node^.buf_free;
|
||||
if Assigned(Node^.vec_free) then
|
||||
begin
|
||||
Node^.vec_free(Node);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _evbuffer_add_opt(buf:Pevbuffer;data:pointer;datalen:SizeUInt):Boolean;
|
||||
Var
|
||||
Node:Peviovec;
|
||||
begin
|
||||
Result:=False;
|
||||
Node:=GetMem(datalen+SizeOf(Teviovec));
|
||||
if Node=nil then Exit;
|
||||
With Node^ do
|
||||
begin
|
||||
base:=@PByte(Node)[SizeOf(Teviovec)];
|
||||
len:=datalen;
|
||||
pos:=0;
|
||||
buf_free:=nil;
|
||||
vec_free:=Freemem_ptr;
|
||||
end;
|
||||
Move(data^,Node^.base^,datalen);
|
||||
Result:=evbuffer_push(buf,Node);
|
||||
end;
|
||||
|
||||
function evbuffer_add(buf:Pevbuffer;data:pointer;datalen:SizeUInt):Boolean;
|
||||
Const
|
||||
optimal_size=4*1024-SizeOf(Teviovec)-2*SizeOf(Pointer);
|
||||
Var
|
||||
base:Pointer;
|
||||
begin
|
||||
Result:=False;
|
||||
if (not Assigned(buf)) or
|
||||
(not Assigned(data)) or
|
||||
(datalen=0) then Exit;
|
||||
|
||||
if (datalen<=optimal_size) then
|
||||
begin
|
||||
Result:=_evbuffer_add_opt(buf,data,datalen);
|
||||
end else
|
||||
begin
|
||||
base:=GetMem(datalen);
|
||||
Move(data^,base^,datalen);
|
||||
Result:=evbuffer_add_ref(buf,base,0,datalen,Freemem_ptr);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function evbuffer_remove(buf:Pevbuffer;data:pointer;datalen:SizeUInt):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if not Assigned(data) then Exit;
|
||||
While (datalen<>0) do
|
||||
begin
|
||||
vec:=evbuffer_peek(buf);
|
||||
if not Assigned(vec) then Break;
|
||||
With vec^ do
|
||||
begin
|
||||
if (len>datalen) then
|
||||
begin
|
||||
Move(PByte(base)[pos],data^,datalen);
|
||||
pos:=pos+datalen;
|
||||
len:=len-datalen;
|
||||
Result:=Result+datalen;
|
||||
fetch_sub(buf^.len,datalen);
|
||||
Break;
|
||||
end else
|
||||
begin
|
||||
Move(PByte(base)[pos],data^,len);
|
||||
datalen:=datalen-len;
|
||||
Result:=Result+len;
|
||||
data:=@PByte(data)[len];
|
||||
eviovec_free(evbuffer_pop(buf));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_copy(buf:Pevbuffer;data:pointer;datalen:SizeUInt):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
if not Assigned(data) then Exit;
|
||||
vec:=evbuffer_peek(buf);
|
||||
While (datalen<>0) and Assigned(vec) do
|
||||
begin
|
||||
With vec^ do
|
||||
begin
|
||||
if (len>datalen) then
|
||||
begin
|
||||
Move(PByte(base)[pos],data^,datalen);
|
||||
Result:=Result+datalen;
|
||||
Break;
|
||||
end else
|
||||
begin
|
||||
Move(PByte(base)[pos],data^,len);
|
||||
datalen:=datalen-len;
|
||||
Result:=Result+len;
|
||||
data:=@PByte(data)[len];
|
||||
vec:=eviovec_next(buf,vec);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_drain(buf:Pevbuffer;datalen:SizeUInt):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
While (datalen<>0) do
|
||||
begin
|
||||
vec:=evbuffer_peek(buf);
|
||||
if not Assigned(vec) then Break;
|
||||
With vec^ do
|
||||
begin
|
||||
if (len>datalen) then
|
||||
begin
|
||||
pos:=pos+datalen;
|
||||
len:=len-datalen;
|
||||
Result:=Result+datalen;
|
||||
fetch_sub(buf^.len,datalen);
|
||||
Break;
|
||||
end else
|
||||
begin
|
||||
datalen:=datalen-len;
|
||||
Result:=Result+len;
|
||||
eviovec_free(evbuffer_pop(buf));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function evbuffer_get_length(buf:Pevbuffer):SizeUInt;
|
||||
begin
|
||||
Result:=0;
|
||||
if not Assigned(buf) then Exit;
|
||||
Result:=buf^.len;
|
||||
end;
|
||||
|
||||
function evbuffer_get_contiguous_space(buf:Pevbuffer):SizeUInt;
|
||||
Var
|
||||
vec:Peviovec;
|
||||
begin
|
||||
Result:=0;
|
||||
vec:=evbuffer_peek(buf);
|
||||
if Assigned(vec) then
|
||||
begin
|
||||
Result:=vec^.len;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
File diff suppressed because it is too large
Load Diff
115
rtl/ntapi.pas
115
rtl/ntapi.pas
|
@ -45,9 +45,15 @@ const
|
|||
STATUS_FILE_CORRUPT_ERROR =$C0000102; //EIO
|
||||
STATUS_NOT_A_DIRECTORY =$C0000103; //ENOTDIR
|
||||
STATUS_NAME_TOO_LONG =$C0000106; //ENAMETOOLONG
|
||||
STATUS_CANCELLED =$C0000120;
|
||||
STATUS_PAGEFILE_QUOTA_EXCEEDED=$C000012C; //ENOMEM
|
||||
STATUS_COMMITMENT_LIMIT =$C000012D; //ENOMEM
|
||||
STATUS_LOCAL_DISCONNECT =$C000013B;
|
||||
STATUS_IO_DEVICE_ERROR =$C0000185; //EIO
|
||||
STATUS_CONNECTION_RESET =$C000020D;
|
||||
STATUS_CONNECTION_REFUSED =$C0000236;
|
||||
STATUS_GRACEFUL_DISCONNECT =$C0000237;
|
||||
STATUS_CONNECTION_ABORTED =$C0000241;
|
||||
STATUS_TOO_MANY_LINKS =$C0000265; //EMLINK
|
||||
STATUS_COMMITMENT_MINIMUM =$C00002C8; //ENOMEM
|
||||
STATUS_CANT_CROSS_RM_BOUNDARY =$C0190038; //EXDEV
|
||||
|
@ -100,22 +106,25 @@ const
|
|||
PROCESS_PRIORITY_CLASS_ABOVE_NORMAL=6;
|
||||
|
||||
//FileInformationClass
|
||||
FileBasicInformation = 4;
|
||||
FileStandardInformation = 5;
|
||||
FileInternalInformation = 6;
|
||||
FileEaInformation = 7;
|
||||
FileAccessInformation = 8;
|
||||
FileRenameInformation =10;
|
||||
FileLinkInformation =11;
|
||||
FileNamesInformation =12;
|
||||
FileDispositionInformation =13;
|
||||
FilePositionInformation =14;
|
||||
FileModeInformation =16;
|
||||
FileAlignmentInformation =17;
|
||||
FileAllInformation =18;
|
||||
FileAllocationInformation =19;
|
||||
FileEndOfFileInformation =20;
|
||||
FileIdFullDirectoryInformation=38;
|
||||
FileBasicInformation = 4;
|
||||
FileStandardInformation = 5;
|
||||
FileInternalInformation = 6;
|
||||
FileEaInformation = 7;
|
||||
FileAccessInformation = 8;
|
||||
FileRenameInformation =10;
|
||||
FileLinkInformation =11;
|
||||
FileNamesInformation =12;
|
||||
FileDispositionInformation =13;
|
||||
FilePositionInformation =14;
|
||||
FileModeInformation =16;
|
||||
FileAlignmentInformation =17;
|
||||
FileAllInformation =18;
|
||||
FileAllocationInformation =19;
|
||||
FileEndOfFileInformation =20;
|
||||
FilePipeInformation =23;
|
||||
FileCompletionInformation =30;
|
||||
FileIdFullDirectoryInformation =38;
|
||||
FileReplaceCompletionInformation=61;
|
||||
|
||||
FileFsFullSizeInformation=7;
|
||||
|
||||
|
@ -227,6 +236,8 @@ const
|
|||
FSCTL_SET_REPARSE_POINT=$000900A4;
|
||||
FSCTL_GET_REPARSE_POINT=$000900A8;
|
||||
|
||||
FSCTL_PIPE_PEEK=$11400c;
|
||||
|
||||
// ReparseTag
|
||||
IO_REPARSE_TAG_SYMLINK =$A000000C;
|
||||
|
||||
|
@ -236,6 +247,18 @@ const
|
|||
// Privileges
|
||||
SE_CREATE_SYMBOLIC_LINK_PRIVILEGE=35;
|
||||
|
||||
//NamedPipeType
|
||||
FILE_PIPE_BYTE_STREAM_TYPE=$00000000;
|
||||
FILE_PIPE_MESSAGE_TYPE =$00000001;
|
||||
|
||||
//ReadMode
|
||||
FILE_PIPE_BYTE_STREAM_MODE=$00000000;
|
||||
FILE_PIPE_MESSAGE_MODE =$00000001;
|
||||
|
||||
//CompletionMode
|
||||
FILE_PIPE_QUEUE_OPERATION =$00000000;
|
||||
FILE_PIPE_COMPLETE_OPERATION=$00000001;
|
||||
|
||||
type
|
||||
PIO_STATUS_BLOCK=^IO_STATUS_BLOCK;
|
||||
IO_STATUS_BLOCK=packed record
|
||||
|
@ -319,6 +342,19 @@ type
|
|||
FileName :record end; //WCHAR
|
||||
end;
|
||||
|
||||
PFILE_COMPLETION_INFORMATION=^FILE_COMPLETION_INFORMATION;
|
||||
FILE_COMPLETION_INFORMATION=packed record
|
||||
Port:THandle;
|
||||
Key :Pointer;
|
||||
end;
|
||||
|
||||
PFILE_IO_COMPLETION_INFORMATION=^FILE_IO_COMPLETION_INFORMATION;
|
||||
FILE_IO_COMPLETION_INFORMATION=packed record
|
||||
KeyContext :Pointer;
|
||||
ApcContext :Pointer;
|
||||
IoStatusBlock:IO_STATUS_BLOCK;
|
||||
end;
|
||||
|
||||
PFILE_ALL_INFORMATION=^FILE_ALL_INFORMATION;
|
||||
FILE_ALL_INFORMATION=packed record
|
||||
BasicInformation :FILE_BASIC_INFORMATION;
|
||||
|
@ -495,6 +531,14 @@ type
|
|||
Enable :ULONG;
|
||||
end;
|
||||
|
||||
T_PIPE_PEEK=packed record
|
||||
NamedPipeState :DWORD;
|
||||
ReadDataAvailable:DWORD;
|
||||
NumberOfMessages :DWORD;
|
||||
MessageLength :DWORD;
|
||||
data :record end;
|
||||
end;
|
||||
|
||||
function NtClose(Handle:THandle):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtDuplicateObject(
|
||||
|
@ -600,6 +644,13 @@ function NtSuspendThread(
|
|||
SuspendCount:PULONG
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtOpenProcess(
|
||||
ProcessHandle :PHandle;
|
||||
DesiredAccess :DWORD;
|
||||
ObjectAttributes:POBJECT_ATTRIBUTES;
|
||||
ClientId :PCLIENT_ID
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtSuspendProcess(
|
||||
ProcessHandle:THandle
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
@ -694,6 +745,23 @@ function NtQuerySystemInformation(
|
|||
ReturnLength :PULONG
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtCreateNamedPipeFile(
|
||||
FileHandle :PHandle;
|
||||
DesiredAccess :ACCESS_MASK;
|
||||
ObjectAttributes :POBJECT_ATTRIBUTES;
|
||||
IoStatusBlock :PIO_STATUS_BLOCK;
|
||||
ShareAccess :ULONG;
|
||||
CreateDisposition:ULONG;
|
||||
CreateOptions :ULONG;
|
||||
NamedPipeType :ULONG;
|
||||
ReadMode :ULONG;
|
||||
CompletionMode :ULONG;
|
||||
MaximumInstances :ULONG;
|
||||
InboundQuota :ULONG;
|
||||
OutboundQuota :ULONG;
|
||||
DefaultTimeout :PLARGE_INTEGER
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtCreateFile(
|
||||
FileHandle :PHandle;
|
||||
DesiredAccess :ACCESS_MASK;
|
||||
|
@ -849,6 +917,21 @@ function NtQueryVolumeInformationFile(
|
|||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
|
||||
function NtCreateIoCompletion(
|
||||
IoCompletionHandle:PHandle;
|
||||
DesiredAccess :ACCESS_MASK;
|
||||
ObjectAttributes :POBJECT_ATTRIBUTES;
|
||||
Count :ULONG
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtRemoveIoCompletionEx(
|
||||
IoCompletionHandle :THandle;
|
||||
IoCompletionInformation:PFILE_IO_COMPLETION_INFORMATION;
|
||||
Count :ULONG;
|
||||
NumEntriesRemoved :PULONG;
|
||||
Timeout :PLARGE_INTEGER;
|
||||
Alertable :Boolean
|
||||
):DWORD; stdcall; external 'ntdll';
|
||||
|
||||
function NtCreateEvent(
|
||||
EventHandle :PHandle;
|
||||
|
|
|
@ -15,6 +15,20 @@ type
|
|||
iKNOTE
|
||||
);
|
||||
|
||||
PNodeHeader=^TNodeHeader;
|
||||
TNodeHeader=packed record
|
||||
mtype:DWORD;
|
||||
mlen :DWORD;
|
||||
buf :record end;
|
||||
end;
|
||||
|
||||
PQNode=^TQNode;
|
||||
TQNode=packed record
|
||||
next_ :PQNode;
|
||||
header:TNodeHeader;
|
||||
buf :record end;
|
||||
end;
|
||||
|
||||
PHostIpcKnote=^THostIpcKnote;
|
||||
THostIpcKnote=packed record
|
||||
pid :Integer;
|
||||
|
@ -22,53 +36,46 @@ type
|
|||
hint :QWORD
|
||||
end;
|
||||
|
||||
PQNode=^TQNode;
|
||||
TQNode=packed record
|
||||
next_:PQNode;
|
||||
mtype:DWORD;
|
||||
mlen :DWORD;
|
||||
buf :record end;
|
||||
end;
|
||||
|
||||
THostIpcCb=procedure(node,data:Pointer); register;
|
||||
|
||||
THostIpcCbRec=record
|
||||
cbs :THostIpcCb;
|
||||
data:Pointer;
|
||||
THostIpcHandler=class
|
||||
Procedure OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer); virtual;
|
||||
end;
|
||||
|
||||
THostIpcConnect=class
|
||||
FQueue:TIntrusiveMPSCQueue;
|
||||
FCbReg:array[t_mtype] of THostIpcCbRec;
|
||||
//
|
||||
procedure knote(pid,filter:Integer;hint:QWORD);
|
||||
//
|
||||
procedure Send(mtype:t_mtype;mlen:DWORD;buf:Pointer); virtual;
|
||||
procedure Pack(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
function Recv:PQNode;
|
||||
procedure Update; virtual;
|
||||
procedure Update(Handler:THostIpcHandler); virtual;
|
||||
//
|
||||
Constructor Create;
|
||||
end;
|
||||
|
||||
THostIpcSimpleKERN=class;
|
||||
|
||||
THostIpcSimpleGUI=class(THostIpcConnect)
|
||||
THostIpcSimpleMGUI=class(THostIpcConnect)
|
||||
FDest:THostIpcSimpleKERN;
|
||||
procedure Send(mtype:t_mtype;mlen:DWORD;buf:Pointer); override;
|
||||
end;
|
||||
|
||||
THostIpcSimpleKERN=class(THostIpcConnect)
|
||||
FDest:THostIpcSimpleGUI;
|
||||
FDest:THostIpcSimpleMGUI;
|
||||
FEvent:PRTLEvent;
|
||||
Constructor Create;
|
||||
Destructor Destroy; override;
|
||||
procedure Send(mtype:t_mtype;mlen:DWORD;buf:Pointer); override;
|
||||
procedure Update; override;
|
||||
procedure Update(Handler:THostIpcHandler); override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Procedure THostIpcHandler.OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
begin
|
||||
//
|
||||
end;
|
||||
|
||||
Constructor THostIpcConnect.Create;
|
||||
begin
|
||||
FQueue.Create;
|
||||
|
@ -79,9 +86,11 @@ var
|
|||
node:PQNode;
|
||||
begin
|
||||
node:=AllocMem(SizeOf(TQNode)+mlen);
|
||||
node^.mtype:=DWORD(mtype);
|
||||
node^.mlen :=mlen;
|
||||
node^.header.mtype:=DWORD(mtype);
|
||||
node^.header.mlen :=mlen;
|
||||
Move(buf^,node^.buf,mlen);
|
||||
//
|
||||
FQueue.Push(node);
|
||||
end;
|
||||
|
||||
function THostIpcConnect.Recv:PQNode;
|
||||
|
@ -90,18 +99,17 @@ begin
|
|||
FQueue.Pop(Result);
|
||||
end;
|
||||
|
||||
procedure THostIpcConnect.Update;
|
||||
procedure THostIpcConnect.Update(Handler:THostIpcHandler);
|
||||
var
|
||||
node:PQNode;
|
||||
rec:THostIpcCbRec;
|
||||
begin
|
||||
node:=Recv;
|
||||
while (node<>nil) do
|
||||
begin
|
||||
rec:=FCbReg[t_mtype(node^.mtype)];
|
||||
if (rec.cbs<>nil) then
|
||||
//
|
||||
if (Handler<>nil) then
|
||||
begin
|
||||
rec.cbs(@node^.buf,rec.data);
|
||||
Handler.OnMessage(t_mtype(node^.header.mtype),node^.header.mlen,@node^.buf);
|
||||
end;
|
||||
//
|
||||
FreeMem(node);
|
||||
|
@ -130,7 +138,7 @@ begin
|
|||
//
|
||||
end;
|
||||
|
||||
procedure THostIpcSimpleGUI.Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
procedure THostIpcSimpleMGUI.Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
begin
|
||||
if (FDest<>nil) then
|
||||
begin
|
||||
|
@ -153,10 +161,13 @@ begin
|
|||
inherited;
|
||||
end;
|
||||
|
||||
procedure THostIpcSimpleKERN.Update;
|
||||
procedure THostIpcSimpleKERN.Update(Handler:THostIpcHandler);
|
||||
begin
|
||||
RTLEventWaitFor(FEvent);
|
||||
inherited;
|
||||
if FQueue.IsEmpty then
|
||||
begin
|
||||
RTLEventWaitFor(FEvent);
|
||||
end;
|
||||
inherited Update(Handler);
|
||||
end;
|
||||
|
||||
procedure THostIpcSimpleKERN.Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
unit md_host_ipc;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,
|
||||
kern_thr,
|
||||
kern_thread,
|
||||
evbuffer,
|
||||
evpoll,
|
||||
host_ipc;
|
||||
|
||||
type
|
||||
t_push_cb=Function(Node:Pointer):Boolean of object;
|
||||
|
||||
t_ipc_proto=object
|
||||
Fbev :Pbufferevent;
|
||||
Finput :Pevbuffer;
|
||||
Foutput:Pevbuffer;
|
||||
|
||||
FHeader:TNodeHeader;
|
||||
FState :Integer;
|
||||
|
||||
FPush :t_push_cb;
|
||||
|
||||
procedure Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
procedure Recv;
|
||||
end;
|
||||
|
||||
THostIpcPipe=class(THostIpcConnect)
|
||||
evpoll:Tevpoll;
|
||||
proto:t_ipc_proto;
|
||||
procedure set_pipe(fd:THandle);
|
||||
procedure Recv; virtual;
|
||||
Function Push(Node:Pointer):Boolean; virtual;
|
||||
procedure thread_new; virtual;
|
||||
procedure thread_free; virtual;
|
||||
procedure Send(mtype:t_mtype;mlen:DWORD;buf:Pointer); override;
|
||||
Constructor Create;
|
||||
Destructor Destroy; override;
|
||||
end;
|
||||
|
||||
THostIpcPipeMGUI=class(THostIpcPipe)
|
||||
Ftd:TThreadID;
|
||||
procedure Recv; override;
|
||||
procedure thread_new; override;
|
||||
procedure thread_free; override;
|
||||
end;
|
||||
|
||||
THostIpcPipeKERN=class(THostIpcPipe)
|
||||
Ftd:p_kthread;
|
||||
Handler:THostIpcHandler;
|
||||
procedure Recv; override;
|
||||
procedure thread_new; override;
|
||||
procedure thread_free; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure t_ipc_proto.Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
var
|
||||
node:PNodeHeader;
|
||||
begin
|
||||
node:=AllocMem(SizeOf(TNodeHeader)+mlen);
|
||||
node^.mtype:=DWORD(mtype);
|
||||
node^.mlen :=mlen;
|
||||
Move(buf^,node^.buf,mlen);
|
||||
|
||||
evbuffer_add_ref(Foutput,node,0,SizeOf(TNodeHeader)+mlen,Freemem_ptr);
|
||||
|
||||
bufferevent_write(Fbev);
|
||||
end;
|
||||
|
||||
procedure t_ipc_proto.Recv;
|
||||
var
|
||||
node:PQNode;
|
||||
begin
|
||||
|
||||
repeat
|
||||
|
||||
case FState of
|
||||
0:
|
||||
begin
|
||||
if (evbuffer_get_length(Finput)<SizeOf(TNodeHeader)) then Exit;
|
||||
|
||||
evbuffer_remove(Finput,@FHeader,SizeOf(TNodeHeader));
|
||||
|
||||
FState:=1;
|
||||
end;
|
||||
1:
|
||||
begin
|
||||
if (evbuffer_get_length(Finput)<FHeader.mlen) then Exit;
|
||||
|
||||
node:=AllocMem(SizeOf(TQNode)+FHeader.mlen);
|
||||
|
||||
node^.header:=FHeader;
|
||||
|
||||
evbuffer_remove(Finput,@node^.buf,FHeader.mlen);
|
||||
|
||||
FPush(node);
|
||||
|
||||
FState:=0;
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
until (evbuffer_get_length(Finput)=0);
|
||||
|
||||
end;
|
||||
|
||||
function pipe_gui_thread(parameter:pointer):ptrint;
|
||||
begin
|
||||
Result:=0;
|
||||
evpoll_loop(parameter);
|
||||
end;
|
||||
|
||||
procedure pipe_kern_thread(parameter:pointer); SysV_ABI_CDecl;
|
||||
begin
|
||||
evpoll_loop(parameter);
|
||||
end;
|
||||
|
||||
Procedure eventcb(bev:Pbufferevent;events:SizeUInt;ctx:pointer);
|
||||
begin
|
||||
|
||||
if ((events and (BEV_EVENT_ERROR or BEV_EVENT_EOF))<>0) then
|
||||
begin
|
||||
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (events and BEV_EVENT_READING)<>0 then
|
||||
begin
|
||||
THostIpcPipe(ctx).Recv;
|
||||
bufferevent_read(bev);
|
||||
end;
|
||||
|
||||
if (events and BEV_EVENT_WRITING)<>0 then
|
||||
begin
|
||||
bufferevent_write(bev);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure THostIpcPipe.set_pipe(fd:THandle);
|
||||
begin
|
||||
proto.Fbev :=bufferevent_pipe_new (@evpoll,fd);
|
||||
proto.Finput :=bufferevent_get_input (proto.Fbev);
|
||||
proto.Foutput:=bufferevent_get_output(proto.Fbev);
|
||||
|
||||
proto.FPush :=@Self.Push;
|
||||
|
||||
bufferevent_setcb(proto.Fbev,@eventcb,Pointer(Self));
|
||||
bufferevent_enable(proto.Fbev);
|
||||
end;
|
||||
|
||||
procedure THostIpcPipe.Recv;
|
||||
begin
|
||||
proto.Recv;
|
||||
end;
|
||||
|
||||
Function THostIpcPipe.Push(Node:Pointer):Boolean;
|
||||
begin
|
||||
Result:=FQueue.Push(node);
|
||||
end;
|
||||
|
||||
procedure THostIpcPipe.thread_new;
|
||||
begin
|
||||
//
|
||||
end;
|
||||
|
||||
procedure THostIpcPipe.thread_free;
|
||||
begin
|
||||
//
|
||||
end;
|
||||
|
||||
procedure THostIpcPipe.Send(mtype:t_mtype;mlen:DWORD;buf:Pointer);
|
||||
begin
|
||||
proto.Send(mtype,mlen,buf);
|
||||
end;
|
||||
|
||||
Constructor THostIpcPipe.Create;
|
||||
begin
|
||||
inherited;
|
||||
evpoll_init(@evpoll,nil);
|
||||
thread_new;
|
||||
end;
|
||||
|
||||
Destructor THostIpcPipe.Destroy;
|
||||
begin
|
||||
evpoll_break(@evpoll);
|
||||
thread_free;
|
||||
bufferevent_free(proto.Fbev);
|
||||
evpoll_free(@evpoll);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure THostIpcPipeMGUI.Recv;
|
||||
begin
|
||||
inherited;
|
||||
//
|
||||
if Assigned(Classes.WakeMainThread) then
|
||||
begin
|
||||
Classes.WakeMainThread(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure THostIpcPipeMGUI.thread_new;
|
||||
begin
|
||||
Ftd:=BeginThread(@pipe_gui_thread,@evpoll);
|
||||
end;
|
||||
|
||||
procedure THostIpcPipeMGUI.thread_free;
|
||||
begin
|
||||
WaitForThreadTerminate(Ftd,0);
|
||||
CloseThread(Ftd);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure THostIpcPipeKERN.Recv;
|
||||
begin
|
||||
inherited;
|
||||
|
||||
Update(Handler);
|
||||
end;
|
||||
|
||||
procedure THostIpcPipeKERN.thread_new;
|
||||
begin
|
||||
Ftd:=nil;
|
||||
kthread_add(@pipe_kern_thread,@evpoll,@Ftd,'[ipc_pipe]');
|
||||
end;
|
||||
|
||||
procedure THostIpcPipeKERN.thread_free;
|
||||
begin
|
||||
thread_dec_ref(Ftd);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
unit md_pipe;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
windows,
|
||||
ntapi;
|
||||
|
||||
Const
|
||||
MD_PIPE_ASYNC0=1;
|
||||
MD_PIPE_ASYNC1=2;
|
||||
|
||||
function md_pipe2(pipefd:PHandle;flags:Integer):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
FILE_SHARE_VALID_FLAGS=FILE_SHARE_READ or
|
||||
FILE_SHARE_WRITE or
|
||||
FILE_SHARE_DELETE;
|
||||
|
||||
Const
|
||||
NamedPipe:PWideChar='\Device\NamedPipe\';
|
||||
|
||||
function md_pipe2(pipefd:PHandle;flags:Integer):Integer;
|
||||
var
|
||||
BLK:IO_STATUS_BLOCK;
|
||||
UNAME:UNICODE_STRING;
|
||||
OATTR:OBJECT_ATTRIBUTES;
|
||||
timeout:LARGE_INTEGER;
|
||||
|
||||
hDirectory:THandle;
|
||||
hFd:array[0..1] of THandle;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
BLK:=Default(IO_STATUS_BLOCK);
|
||||
|
||||
UNAME:=Default(UNICODE_STRING);
|
||||
UNAME.Length :=Length(NamedPipe)*SizeOf(WideChar);
|
||||
UNAME.MaximumLength:=(Length(NamedPipe)+1)*SizeOf(WideChar);
|
||||
UNAME.Buffer :=NamedPipe;
|
||||
|
||||
OATTR:=Default(OBJECT_ATTRIBUTES);
|
||||
OATTR.Length :=SizeOf(OBJECT_ATTRIBUTES);
|
||||
OATTR.ObjectName:=@UNAME;
|
||||
OATTR.Attributes:=OBJ_CASE_INSENSITIVE;
|
||||
|
||||
hDirectory:=0;
|
||||
Result:=NtOpenFile(@hDirectory,
|
||||
SYNCHRONIZE,
|
||||
@OATTR,
|
||||
@BLK,
|
||||
FILE_SHARE_VALID_FLAGS,
|
||||
0);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
timeout.QuadPart:=-500000;
|
||||
|
||||
BLK:=Default(IO_STATUS_BLOCK);
|
||||
|
||||
UNAME:=Default(UNICODE_STRING);
|
||||
|
||||
OATTR.RootDirectory:=hDirectory;
|
||||
|
||||
hFd[0]:=0;
|
||||
Result:=NtCreateNamedPipeFile(@hFd[0],
|
||||
SYNCHRONIZE or
|
||||
FILE_READ_ATTRIBUTES or FILE_READ_DATA or
|
||||
FILE_WRITE_ATTRIBUTES or FILE_WRITE_DATA or
|
||||
FILE_CREATE_PIPE_INSTANCE,
|
||||
@OATTR,
|
||||
@BLK,
|
||||
FILE_SHARE_READ or FILE_SHARE_WRITE,
|
||||
FILE_CREATE,
|
||||
(ord((flags and MD_PIPE_ASYNC0)=0)*FILE_SYNCHRONOUS_IO_NONALERT),
|
||||
FILE_PIPE_BYTE_STREAM_TYPE,
|
||||
FILE_PIPE_BYTE_STREAM_MODE,
|
||||
FILE_PIPE_QUEUE_OPERATION,
|
||||
$ffffffff,
|
||||
0,
|
||||
0,
|
||||
@timeout);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
NtClose(hDirectory);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
BLK:=Default(IO_STATUS_BLOCK);
|
||||
|
||||
OATTR.RootDirectory:=hFd[0];
|
||||
OATTR.Attributes:=OBJ_CASE_INSENSITIVE or OBJ_INHERIT;
|
||||
|
||||
hFd[1]:=0;
|
||||
Result:=NtOpenFile(@hFd[1],
|
||||
SYNCHRONIZE or
|
||||
FILE_READ_ATTRIBUTES or FILE_READ_DATA or
|
||||
FILE_WRITE_ATTRIBUTES or FILE_WRITE_DATA,
|
||||
@OATTR,
|
||||
@BLK,
|
||||
FILE_SHARE_VALID_FLAGS,
|
||||
(ord((flags and MD_PIPE_ASYNC1)=0)*FILE_SYNCHRONOUS_IO_NONALERT)
|
||||
);
|
||||
|
||||
if (Result<>0) then
|
||||
begin
|
||||
NtClose(hFd[0]);
|
||||
NtClose(hDirectory);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
NtClose(hDirectory);
|
||||
|
||||
pipefd[0]:=hFd[0];
|
||||
pipefd[1]:=hFd[1];
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -19,6 +19,10 @@ function md_copyout(hProcess:THandle;kaddr,udaddr:Pointer;len:ptruint;lencopied
|
|||
function md_copyin (udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
|
||||
function md_copyout(kaddr,udaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
|
||||
|
||||
function md_getppid:DWORD;
|
||||
function md_pidfd_getfd(pidfd,targetfd:THandle):THandle;
|
||||
function md_pidfd_open (pid:DWORD):THandle;
|
||||
|
||||
procedure md_run_forked;
|
||||
procedure md_fork_unshare;
|
||||
function md_fork_process(proc:Pointer;data:Pointer;size:QWORD):THandle;
|
||||
|
@ -32,6 +36,9 @@ uses
|
|||
errno,
|
||||
md_map;
|
||||
|
||||
var
|
||||
ppid:DWORD=0;
|
||||
|
||||
function md_copyin(hProcess:THandle;udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
|
||||
var
|
||||
num:DWORD;
|
||||
|
@ -78,6 +85,56 @@ begin
|
|||
Result:=md_copyout(NtCurrentProcess,kaddr,udaddr,len,lencopied);
|
||||
end;
|
||||
|
||||
function md_getppid:DWORD;
|
||||
begin
|
||||
Result:=ppid;
|
||||
end;
|
||||
|
||||
function md_pidfd_getfd(pidfd,targetfd:THandle):THandle;
|
||||
begin
|
||||
Result:=0;
|
||||
NtDuplicateObject(
|
||||
pidfd,
|
||||
targetfd,
|
||||
NtCurrentProcess,
|
||||
@Result,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
);
|
||||
end;
|
||||
|
||||
function md_dup_to_pidfd(pidfd,targetfd:THandle):THandle;
|
||||
begin
|
||||
Result:=0;
|
||||
NtDuplicateObject(
|
||||
NtCurrentProcess,
|
||||
targetfd,
|
||||
pidfd,
|
||||
@Result,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
);
|
||||
end;
|
||||
|
||||
function md_pidfd_open(pid:DWORD):THandle;
|
||||
var
|
||||
ClientId:TCLIENT_ID;
|
||||
OATTR:OBJECT_ATTRIBUTES;
|
||||
R:DWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
ClientId.UniqueProcess:=pid;
|
||||
ClientId.UniqueThread :=0;
|
||||
|
||||
OATTR:=Default(OBJECT_ATTRIBUTES);
|
||||
OATTR.Length:=SizeOf(OBJECT_ATTRIBUTES);
|
||||
|
||||
R:=NtOpenProcess(@Result,PROCESS_DUP_HANDLE,@OATTR,@ClientId);
|
||||
end;
|
||||
|
||||
const
|
||||
JobObjectExtendedLimitInformation=9;
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE=$00002000;
|
||||
|
@ -293,38 +350,10 @@ begin
|
|||
until (prev>=addr);
|
||||
end;
|
||||
|
||||
function md_pidfd_getfd(pidfd,targetfd:THandle):THandle;
|
||||
begin
|
||||
Result:=0;
|
||||
NtDuplicateObject(
|
||||
pidfd,
|
||||
targetfd,
|
||||
NtCurrentProcess,
|
||||
@Result,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
);
|
||||
end;
|
||||
|
||||
function md_dup_to_pidfd(pidfd,targetfd:THandle):THandle;
|
||||
begin
|
||||
Result:=0;
|
||||
NtDuplicateObject(
|
||||
NtCurrentProcess,
|
||||
targetfd,
|
||||
pidfd,
|
||||
@Result,
|
||||
0,
|
||||
0,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
);
|
||||
end;
|
||||
|
||||
type
|
||||
p_shared_info=^t_shared_info;
|
||||
t_shared_info=record
|
||||
hParent :THandle;
|
||||
ppid :QWORD;
|
||||
hStdInput :THandle;
|
||||
hStdOutput:THandle;
|
||||
hStdError :THandle;
|
||||
|
@ -340,15 +369,6 @@ var
|
|||
len:ULONG_PTR;
|
||||
|
||||
proc:Pointer;
|
||||
|
||||
{
|
||||
F:THandle;
|
||||
F2:THandle;
|
||||
S:RAwByteString;
|
||||
BLK:IO_STATUS_BLOCK;
|
||||
OFFSET:Int64;
|
||||
R:DWORD;
|
||||
}
|
||||
begin
|
||||
base:=Pointer(WIN_SHARED_ADDR);
|
||||
|
||||
|
@ -364,7 +384,7 @@ begin
|
|||
|
||||
if (info.State=MEM_FREE) then Exit;
|
||||
|
||||
//sleep(-1);
|
||||
ppid:=base^.ppid;
|
||||
|
||||
SetStdHandle(STD_INPUT_HANDLE ,base^.hStdInput );
|
||||
SetStdHandle(STD_ERROR_HANDLE ,base^.hStdOutput);
|
||||
|
@ -374,36 +394,6 @@ begin
|
|||
|
||||
if (proc=nil) then Exit;
|
||||
|
||||
{
|
||||
F:=FileCreate('log2.txt');
|
||||
|
||||
S:='0x'+HexStr(Pointer(proc))+#13#10;
|
||||
FileWrite(F,PChar(S)^,Length(S));
|
||||
|
||||
S:='hParent:'+IntToStr(base^.hParent)+':'+#13#10;
|
||||
FileWrite(F,PChar(S)^,Length(S));
|
||||
|
||||
F2:=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
//F2:=md_pidfd_getfd(base^.hParent,F2);
|
||||
|
||||
S:='[NtWriteFile] hParent:'+IntToStr(base^.hParent)+'-'+#13#10;
|
||||
//FileWrite(F2,PChar(S)^,Length(S));
|
||||
|
||||
BLK:=Default(IO_STATUS_BLOCK);
|
||||
OFFSET:=Int64(FILE_WRITE_TO_END_OF_FILE_L);
|
||||
R:=NtWriteFile(F2,0,nil,nil,@BLK,PChar(S),Length(S),@OFFSET,nil);
|
||||
|
||||
S:='F2:'+IntToStr(F2)+':'+#13#10;
|
||||
FileWrite(F,PChar(S)^,Length(S));
|
||||
|
||||
S:='R:0x'+HexStr(R,8)+#13#10;
|
||||
FileWrite(F,PChar(S)^,Length(S));
|
||||
}
|
||||
|
||||
//writeln('test!');
|
||||
|
||||
//sleep(-1);
|
||||
|
||||
t_fork_cb(proc)(@base^.data,base^.size);
|
||||
|
||||
NtTerminateProcess(NtCurrentProcess, 0);
|
||||
|
@ -453,7 +443,7 @@ begin
|
|||
|
||||
shared_info:=Default(t_shared_info);
|
||||
|
||||
shared_info.hParent :=md_dup_to_pidfd(hProcess,NtCurrentProcess);
|
||||
shared_info.ppid :=GetCurrentProcessId;
|
||||
|
||||
shared_info.hStdInput :=md_dup_to_pidfd(hProcess,GetStdHandle(STD_INPUT_HANDLE));
|
||||
shared_info.hStdOutput:=md_dup_to_pidfd(hProcess,GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
|
|
|
@ -168,6 +168,7 @@ var
|
|||
BUF:TWRITE_BUF;
|
||||
i:QWORD;
|
||||
td:p_kthread;
|
||||
R:DWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
//init
|
||||
|
@ -195,7 +196,16 @@ begin
|
|||
Inc(iov_base,i);
|
||||
Dec(iov_len ,i);
|
||||
//
|
||||
NtWriteFile(tp^.t_wr_handle,0,nil,nil,@BLK,@BUF.BUF,BUF.LEN,@OFFSET,nil);
|
||||
R:=NtWriteFile(tp^.t_wr_handle,0,nil,nil,@BLK,@BUF.BUF,BUF.LEN,@OFFSET,nil);
|
||||
//
|
||||
if (R=STATUS_PENDING) then
|
||||
begin
|
||||
R:=NtWaitForSingleObject(tp^.t_wr_handle,False,nil);
|
||||
if (R=0) then
|
||||
begin
|
||||
R:=BLK.Status;
|
||||
end;
|
||||
end;
|
||||
//
|
||||
BUF.INIT();
|
||||
end;
|
||||
|
|
|
@ -2383,6 +2383,10 @@ begin
|
|||
if (R=STATUS_PENDING) then
|
||||
begin
|
||||
R:=NtWaitForSingleObject(F,False,nil);
|
||||
if (R=0) then
|
||||
begin
|
||||
R:=BLK.Status;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=ntf2px(R);
|
||||
|
|
Loading…
Reference in New Issue