(*
/*

CLASS {NATIVE_process|_Pascal},
UNTESTED, NATIVE:

IMPORT, ANYWAY: {System_functions} .

NATIVE: "///copy NATIVE_process.pas" .

*/
*)

unit NATIVE_process;

interface

uses{$IFDEF LINUX} Classes, SysUtils, Process
	 {$ELSE } Windows, ShellAPI
	 {$ENDIF} ;

function Do_start_program(
	X_App, X_Param: String; X_Visible, X_Run_As: Boolean): Integer;
	
{$IFDEF LINUX}
	var All_processes: TList;
	function Allocate_process(p: TProcess): Integer;
	procedure Free_process(i: Integer);
{$ENDIF}

implementation

{$IFDEF LINUX}
	
	function Allocate_process(p: TProcess): Integer;
	begin
	    if All_processes = nil then begin
	    	All_processes := TList.Create;
	    	All_processes.Add(TProcess.Create(nil));
	    end;
		Result := All_processes.IndexOf(nil);
		
		if Result > 0 then All_processes[Result] := p
		else begin
			Result := All_processes.Count;
			All_processes.Add(p);
		end;
	end;
	
	procedure Free_process(i: Integer);
	begin
		TObject(All_processes[i]).Free;
		All_processes[i] := nil;
	end;

{$ELSE}
	{$IFDEF SMALLER_CODE}
	{$ELSE}
	function GetProcessId(hProcess: THandle): Integer; stdcall;
	external 'kernel32.dll' name 'GetProcessId';
	{$ENDIF}
{$ENDIF}

function Do_start_program(
	X_App, X_Param: String; X_Visible, X_Run_as: Boolean): Integer;
{$IFDEF LINUX}
var AProcess: TProcess;
{$ELSE WINDOWS}
	var v: DWORD;
		verb: {$IFDEF SMALLER_CODE} PChar {$ELSE} PWideChar {$ENDIF};
		verbw: {$IFDEF SMALLER_CODE} String {$ELSE} WideString {$ENDIF};
	{$IFDEF SMALLER_CODE}
	{$ELSE}
	var SEI: TShellExecuteInfoW;
		W, P: WideString;
	{$ENDIF}
{$ENDIF}
var i: Integer;
begin
	if (X_Param = '') and (Pos(' ', X_App) > 0) then begin
		i := Pos(' ', X_App);
		X_Param := Copy(X_App, i+1, Length(X_App) - i);
		X_App := Copy(X_App, 1, i-1);
	end;
{$IFDEF LINUX}
    AProcess := TProcess.Create(nil);
    AProcess.Executable := X_App;
    AProcess.Parameters.Add(X_Param);
    if not X_Visible then AProcess.ShowWindow := swoHide;
    //if X_Run_as then AProcess.Verb := '"runas"'
    AProcess.Execute;
    RESULT := Allocate_process(AProcess);
{$ELSE WINDOWS}
	if X_Visible then v := SW_SHOW else v := SW_HIDE;
	verb := nil;
	if X_Run_as then begin
		verbw := 'runas';
		verb := @verbw[1];
	end;
  {$IFDEF SMALLER_CODE}
  	RESULT := ShellExecute(0, verb, PChar(X_App), PChar(X_Param), nil, v); // > 32;
  {$ELSE}
    W := X_App;
    P := X_Param;
  	FillChar(SEI, Sizeof(SEI), 0);
  	SEI.cbSize := Sizeof(SEI);
  	SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  	SEI.lpVerb := verb;
  	SEI.lpFile := PWideChar(W);
  	SEI.lpParameters := PWideChar(P);
  	SEI.nShow := v;
  	//writeln('Program=' + W);
    if ShellExecuteExW(@SEI) then 
  		 RESULT := GetProcessId(SEI.hProcess)
    else RESULT := 0;
  {$ENDIF}
{$ENDIF}
end;


end .
(*
/*

CONST STR :
	NATIVE_process_import = @
	"uses NATIVE_process"
	"{$IFDEF LINUX}, Process"
	"	  {$ELSE}, Windows"
	"	  {$ENDIF}"
	";"	

	NATIVE_process_create = @
	"	 try"
    "    C_Process(RESULT.Obj).F_pid := Do_start_program(X_App, X_Param, "
    "		X_Visible, false);"
	"	 except"
	"	 end;"
	
	NATIVE_process_run_as = @
	"	 try"
    "    C_Process(RESULT.Obj).F_pid := Do_start_program(X_App, X_Param,"
    "		X_Visible, true);"
	"	 except"
	"	 end;"
	
	NATIVE_process_ended = @
    "var h_p: THandle;"
    "var ret: DWORD;"     
	"	{$IFDEF LINUX}"
	"	RESULT := not TProcess(All_processes[C_Process(X_P.Obj).F_pid])"
	"			  .Running;"
	"	{$ELSE}"
	"	h_p := OpenProcess(SYNCHRONIZE, FALSE, C_Process(X_P.Obj).F_pid);"
	"	ret := WaitForSingleObject(h_p, 0);"
	"	CloseHandle(h_p);"
	"	RESULT := ret <> WAIT_TIMEOUT;"     
	"	{$ENDIF}"
	
	NATIVE_process_terminate = @
	"var pH: THandle;"
	"	{$IFDEF LINUX}"
	"		TProcess(All_processes[C_Process(X_P.Obj).F_pid]).Terminate(0);"
	"	{$ELSE}"
	"	try"
	"		pH := OpenProcess(PROCESS_TERMINATE,"
	"			FALSE, C_Process(X_P.Obj).F_pid);"
	"		if pH <> 0 then begin"
	"			if not TerminateProcess(pH, 0) then begin"
	"				//writeln('bbbbbbbbbbbbbbbbad: ' + IntToStr(GetLastError));"
	"			    readln;"
	"			end;"     
	"		end;"
	"		CloseHandle(pH);"
	"	except"
	"	end;"
	"	{$ENDIF}"
	
	NATIVE_process_release = @
	"{$IFDEF LINUX}"
	"	Free_process(C_Process(X_P.Obj).F_pid)"
	"{$ENDIF}"

	.


END

*/
*)

