summaryrefslogtreecommitdiff
path: root/packages/fcl-process/src
diff options
context:
space:
mode:
authorpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-10-28 21:26:51 +0000
committerpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-10-28 21:26:51 +0000
commit9a1c84e2531f3f115297d745fa9f03b322e5e881 (patch)
treeb6e0165c05e881ee4bc595ed417dd9a315e0d15c /packages/fcl-process/src
parent77722a04c495e3d5b8200c8641f56d364009f1f1 (diff)
downloadfpc-9a1c84e2531f3f115297d745fa9f03b322e5e881.tar.gz
* created fcl-async and fcl-process packages
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@8979 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-process/src')
-rw-r--r--packages/fcl-process/src/amiga/pipes.inc30
-rw-r--r--packages/fcl-process/src/amiga/process.inc42
-rw-r--r--packages/fcl-process/src/beos/pipes.inc30
-rw-r--r--packages/fcl-process/src/dbugintf.pp285
-rw-r--r--packages/fcl-process/src/dbugmsg.pp102
-rw-r--r--packages/fcl-process/src/go32v2/pipes.inc30
-rw-r--r--packages/fcl-process/src/go32v2/process.inc42
-rw-r--r--packages/fcl-process/src/morphos/pipes.inc30
-rw-r--r--packages/fcl-process/src/morphos/process.inc42
-rw-r--r--packages/fcl-process/src/netware/pipes.inc30
-rw-r--r--packages/fcl-process/src/netware/process.inc42
-rw-r--r--packages/fcl-process/src/netwlibc/pipes.inc30
-rw-r--r--packages/fcl-process/src/netwlibc/process.inc42
-rw-r--r--packages/fcl-process/src/os2/pipes.inc34
-rw-r--r--packages/fcl-process/src/os2/process.inc42
-rw-r--r--packages/fcl-process/src/pipes.pp127
-rw-r--r--packages/fcl-process/src/process.pp325
-rw-r--r--packages/fcl-process/src/process.txt281
-rw-r--r--packages/fcl-process/src/simpleipc.pp457
-rw-r--r--packages/fcl-process/src/unix/pipes.inc32
-rw-r--r--packages/fcl-process/src/unix/process.inc399
-rw-r--r--packages/fcl-process/src/unix/simpleipc.inc194
-rw-r--r--packages/fcl-process/src/win/pipes.inc43
-rw-r--r--packages/fcl-process/src/win/process.inc257
-rw-r--r--packages/fcl-process/src/win/simpleipc.inc293
-rw-r--r--packages/fcl-process/src/wince/pipes.inc30
-rw-r--r--packages/fcl-process/src/wince/process.inc257
-rw-r--r--packages/fcl-process/src/wince/simpleipc.inc291
28 files changed, 3839 insertions, 0 deletions
diff --git a/packages/fcl-process/src/amiga/pipes.inc b/packages/fcl-process/src/amiga/pipes.inc
new file mode 100644
index 0000000000..dc35fb365c
--- /dev/null
+++ b/packages/fcl-process/src/amiga/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ AmigaOS specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// Unsupported for the moment...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+
+begin
+ Result := False;
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/amiga/process.inc b/packages/fcl-process/src/amiga/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/amiga/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/beos/pipes.inc b/packages/fcl-process/src/beos/pipes.inc
new file mode 100644
index 0000000000..9e0a292569
--- /dev/null
+++ b/packages/fcl-process/src/beos/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ DOS/go32v2 specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// No pipes under beos, sorry...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+
+begin
+ Result := False;
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/dbugintf.pp b/packages/fcl-process/src/dbugintf.pp
new file mode 100644
index 0000000000..b86f74d96a
--- /dev/null
+++ b/packages/fcl-process/src/dbugintf.pp
@@ -0,0 +1,285 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Debugserver client interface, based on SimpleIPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit dbugintf;
+
+interface
+
+Type
+ TDebugLevel = (dlInformation,dlWarning,dlError);
+
+procedure SendBoolean(const Identifier: string; const Value: Boolean);
+procedure SendDateTime(const Identifier: string; const Value: TDateTime);
+procedure SendInteger(const Identifier: string; const Value: Integer; HexNotation: Boolean = False);
+procedure SendPointer(const Identifier: string; const Value: Pointer);
+procedure SendDebugEx(const Msg: string; MType: TDebugLevel);
+procedure SendDebug(const Msg: string);
+procedure SendMethodEnter(const MethodName: string);
+procedure SendMethodExit(const MethodName: string);
+procedure SendSeparator;
+procedure SendDebugFmt(const Msg: string; const Args: array of const);
+procedure SendDebugFmtEx(const Msg: string; const Args: array of const; MType: TDebugLevel);
+
+procedure SetDebuggingEnabled(const AValue : boolean);
+function GetDebuggingEnabled : Boolean;
+
+{ low-level routines }
+
+Function StartDebugServer : integer;
+Function InitDebugClient : Boolean;
+
+Const
+ SendError : String = '';
+
+ResourceString
+ SProcessID = 'Process %s';
+ SEntering = '> Entering ';
+ SExiting = '< Exiting ';
+ SSeparator = '>-=-=-=-=-=-=-=-=-=-=-=-=-=-=-<';
+
+implementation
+
+Uses
+ SysUtils, classes,dbugmsg, process, simpleipc;
+
+Const
+ DmtInformation = lctInformation;
+ DmtWarning = lctWarning;
+ DmtError = lctError;
+ ErrorLevel : Array[TDebugLevel] of integer
+ = (dmtInformation,dmtWarning,dmtError);
+ IndentChars = 2;
+
+var
+ DebugClient : TSimpleIPCClient = nil;
+ MsgBuffer : TMemoryStream = Nil;
+ ServerID : Integer;
+ DebugDisabled : Boolean;
+ Indent : Integer = 0;
+
+Procedure WriteMessage(Const Msg : TDebugMessage);
+
+begin
+ MsgBuffer.Seek(0,soFrombeginning);
+ WriteDebugMessageToStream(MsgBuffer,Msg);
+ DebugClient.SendMessage(mtUnknown,MsgBuffer);
+end;
+
+
+procedure SendDebugMessage(Var Msg : TDebugMessage);
+
+begin
+ if DebugDisabled then exit;
+ try
+ If (DebugClient=Nil) then
+ InitDebugClient;
+ if (Indent>0) then
+ Msg.Msg:=StringOfChar(' ',Indent)+Msg.Msg;
+ WriteMessage(Msg);
+ except
+ On E : Exception do
+ SendError:=E.Message;
+ end;
+end;
+
+procedure SendBoolean(const Identifier: string; const Value: Boolean);
+
+Const
+ Booleans : Array[Boolean] of string = ('False','True');
+
+begin
+ SendDebugFmt('%s = %s',[Identifier,Booleans[value]]);
+end;
+
+procedure SendDateTime(const Identifier: string; const Value: TDateTime);
+
+begin
+ SendDebugFmt('%s = %s',[Identifier,DateTimeToStr(Value)]);
+end;
+
+procedure SendInteger(const Identifier: string; const Value: Integer; HexNotation: Boolean = False);
+
+Const
+ Msgs : Array[Boolean] of string = ('%s = %d','%s = %x');
+
+begin
+ SendDebugFmt(Msgs[HexNotation],[Identifier,Value]);
+end;
+
+procedure SendPointer(const Identifier: string; const Value: Pointer);
+
+begin
+ SendDebugFmt('%s = %p',[Identifier,Value]);
+end;
+
+procedure SendDebugEx(const Msg: string; MType: TDebugLevel);
+
+Var
+ Mesg : TDebugMessage;
+
+begin
+ Mesg.MsgTimeStamp:=Now;
+ Mesg.MsgType:=ErrorLevel[MTYpe];
+ Mesg.Msg:=Msg;
+ SendDebugMessage(Mesg);
+end;
+
+procedure SendDebug(const Msg: string);
+
+Var
+ Mesg : TDebugMessage;
+begin
+ Mesg.MsgTimeStamp:=Now;
+ Mesg.MsgType:=dmtInformation;
+ Mesg.Msg:=Msg;
+ SendDebugMessage(Mesg);
+end;
+
+procedure SendMethodEnter(const MethodName: string);
+
+begin
+ SendDebug(SEntering+MethodName);
+ inc(Indent,IndentChars);
+end;
+
+procedure SendMethodExit(const MethodName: string);
+
+begin
+ Dec(Indent,IndentChars);
+ If (Indent<0) then
+ Indent:=0;
+ SendDebug(SExiting+MethodName);
+end;
+
+procedure SendSeparator;
+
+begin
+ SendDebug(SSeparator);
+end;
+
+procedure SendDebugFmt(const Msg: string; const Args: array of const);
+
+Var
+ Mesg : TDebugMessage;
+
+begin
+ Mesg.MsgTimeStamp:=Now;
+ Mesg.MsgType:=dmtInformation;
+ Mesg.Msg:=Format(Msg,Args);
+ SendDebugMessage(Mesg);
+end;
+
+procedure SendDebugFmtEx(const Msg: string; const Args: array of const; MType: TDebugLevel);
+
+Var
+ Mesg : TDebugMessage;
+
+begin
+ Mesg.MsgTimeStamp:=Now;
+ Mesg.MsgType:=ErrorLevel[mType];
+ Mesg.Msg:=Format(Msg,Args);
+ SendDebugMessage(Mesg);
+end;
+
+procedure SetDebuggingEnabled(const AValue: boolean);
+begin
+ DebugDisabled := not AValue;
+end;
+
+function GetDebuggingEnabled: Boolean;
+begin
+ Result := not DebugDisabled;
+end;
+
+function StartDebugServer : Integer;
+
+begin
+ With TProcess.Create(Nil) do
+ begin
+ Try
+ CommandLine:='debugserver';
+ Execute;
+ Result:=ProcessID;
+ Except
+ Result := 0;
+ end;
+ Free;
+ end;
+end;
+
+procedure FreeDebugClient;
+
+Var
+ msg : TDebugMessage;
+
+begin
+ try
+ If (DebugClient<>Nil) and
+ (DebugClient.ServerRunning) then
+ begin
+ Msg.MsgType:=lctStop;
+ Msg.MsgTimeStamp:=Now;
+ Msg.Msg:=Format(SProcessID,[ApplicationName]);
+ WriteMessage(Msg);
+ end;
+ FreeAndNil(MsgBuffer);
+ FreeAndNil(DebugClient);
+ except
+ end;
+end;
+
+Function InitDebugClient : Boolean;
+
+Var
+ msg : TDebugMessage;
+ I : Integer;
+
+begin
+ Result := False;
+ DebugClient:=TSimpleIPCClient.Create(Nil);
+ DebugClient.ServerID:=DebugServerID;
+ If not DebugClient.ServerRunning then
+ begin
+ ServerID:=StartDebugServer;
+ if ServerID = 0 then
+ begin
+ DebugDisabled := True;
+ Exit;
+ end
+ else
+ DebugDisabled := False;
+ I:=0;
+ While (I<10) and not DebugClient.ServerRunning do
+ begin
+ Inc(I);
+ Sleep(100);
+ end;
+ end;
+ DebugClient.Connect;
+ MsgBuffer:=TMemoryStream.Create;
+ Msg.MsgType:=lctIdentify;
+ Msg.MsgTimeStamp:=Now;
+ Msg.Msg:=Format(SProcessID,[ApplicationName]);
+ WriteMessage(Msg);
+ Result := True;
+end;
+
+Initialization
+ DebugDisabled := False;
+Finalization
+ FreeDebugClient;
+end.
diff --git a/packages/fcl-process/src/dbugmsg.pp b/packages/fcl-process/src/dbugmsg.pp
new file mode 100644
index 0000000000..2cb575824a
--- /dev/null
+++ b/packages/fcl-process/src/dbugmsg.pp
@@ -0,0 +1,102 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Debugserver Client/Server common code.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit dbugmsg;
+
+interface
+
+uses Classes;
+
+Const
+ DebugServerID : String = 'fpcdebugserver';
+
+ lctStop = -1;
+ lctInformation = 0;
+ lctWarning = 1;
+ lctError = 2;
+ lctIdentify = 3;
+
+Type
+ TDebugMessage = Record
+ MsgType : Integer;
+ MsgTimeStamp : TDateTime;
+ Msg : String;
+ end;
+
+Procedure ReadDebugMessageFromStream(AStream : TStream; Var Msg : TDebugMessage);
+Procedure WriteDebugMessageToStream(AStream : TStream; Const Msg : TDebugMessage);
+Function DebugMessageName(msgType : Integer) : String;
+
+
+implementation
+
+resourcestring
+ SStop = 'Stop';
+ SInformation = 'Information';
+ SWarning = 'Warning';
+ SError = 'Error';
+ SIdentify = 'Identify';
+ SUnknown = 'Unknown';
+
+procedure ReadDebugMessageFromStream(AStream : TStream; Var Msg : TDebugMessage);
+
+Var
+ MsgSize : Integer;
+
+begin
+ With AStream do
+ begin
+ ReadBuffer(Msg.MsgType,SizeOf(Integer));
+ ReadBuffer(Msg.MsgTimeStamp,SizeOf(TDateTime));
+ ReadBuffer(MsgSize,SizeOf(Integer));
+ SetLength(Msg.Msg,MsgSize);
+ If (MsgSize<>0) then
+ ReadBuffer(Msg.msg[1],MsgSize);
+ end;
+end;
+
+procedure WriteDebugMessageToStream(AStream : TStream; Const Msg : TDebugMessage);
+
+Var
+ MsgSize : Integer;
+
+begin
+ With AStream do
+ begin
+ WriteBuffer(Msg.MsgType,SizeOf(Integer));
+ WriteBuffer(Msg.MsgTimeStamp,SizeOf(TDateTime));
+ MsgSize:=Length(Msg.Msg);
+ WriteBuffer(MsgSize,SizeOf(Integer));
+ WriteBuffer(Msg.msg[1],MsgSize);
+ end;
+end;
+
+Function DebugMessageName(msgType : Integer) : String;
+
+begin
+ Case MsgType of
+ lctStop : Result:=SStop;
+ lctInformation : Result:=SInformation;
+ lctWarning : Result:=SWarning;
+ lctError : Result:=SError;
+ lctIdentify : Result:=SIdentify;
+ else
+ Result:=SUnknown;
+ end;
+end;
+
+end.
diff --git a/packages/fcl-process/src/go32v2/pipes.inc b/packages/fcl-process/src/go32v2/pipes.inc
new file mode 100644
index 0000000000..2734d39a03
--- /dev/null
+++ b/packages/fcl-process/src/go32v2/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ DOS/go32v2 specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// No pipes under dos, sorry...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+
+begin
+ Result := False;
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/go32v2/process.inc b/packages/fcl-process/src/go32v2/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/go32v2/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/morphos/pipes.inc b/packages/fcl-process/src/morphos/pipes.inc
new file mode 100644
index 0000000000..dc35fb365c
--- /dev/null
+++ b/packages/fcl-process/src/morphos/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ AmigaOS specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// Unsupported for the moment...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+
+begin
+ Result := False;
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/morphos/process.inc b/packages/fcl-process/src/morphos/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/morphos/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/netware/pipes.inc b/packages/fcl-process/src/netware/pipes.inc
new file mode 100644
index 0000000000..4a031d52a5
--- /dev/null
+++ b/packages/fcl-process/src/netware/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ Netware specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// Unsupported for the moment...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+
+begin
+ Result := false; {dont know how to do that with netware clib}
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/netware/process.inc b/packages/fcl-process/src/netware/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/netware/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/netwlibc/pipes.inc b/packages/fcl-process/src/netwlibc/pipes.inc
new file mode 100644
index 0000000000..fd8b9b6115
--- /dev/null
+++ b/packages/fcl-process/src/netwlibc/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2004 by Michael Van Canneyt
+
+ Netware specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// Unsupported for the moment...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+
+begin
+ Result := false; {todo}
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/netwlibc/process.inc b/packages/fcl-process/src/netwlibc/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/netwlibc/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/os2/pipes.inc b/packages/fcl-process/src/os2/pipes.inc
new file mode 100644
index 0000000000..f47ba06588
--- /dev/null
+++ b/packages/fcl-process/src/os2/pipes.inc
@@ -0,0 +1,34 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ OS/2 specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+uses
+ DosCalls;
+
+const
+ PipeBufSize = 1024;
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+
+begin
+ CreatePipeHandles := DosCreatePipe (InHandle, OutHandle, PipeBufSize) = 0;
+end;
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ // TODO: find out if this is possible in OS/2
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/os2/process.inc b/packages/fcl-process/src/os2/process.inc
new file mode 100644
index 0000000000..74f9c2fe50
--- /dev/null
+++ b/packages/fcl-process/src/os2/process.inc
@@ -0,0 +1,42 @@
+{
+ Dummy process.inc
+}
+
+procedure TProcess.CloseProcessHandles;
+begin
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+begin
+end;
+
+Procedure TProcess.Execute;
+begin
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+begin
+ Result:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+begin
+ Result:=0;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+begin
+ Result:=False;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+begin
+end;
+
+
diff --git a/packages/fcl-process/src/pipes.pp b/packages/fcl-process/src/pipes.pp
new file mode 100644
index 0000000000..f3604c562a
--- /dev/null
+++ b/packages/fcl-process/src/pipes.pp
@@ -0,0 +1,127 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ Implementation of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+{$mode objfpc}
+
+Unit Pipes;
+
+Interface
+
+Uses sysutils,Classes;
+
+Type
+ EPipeError = Class(EStreamError);
+ ENoReadPipe = Class(EPipeError);
+ ENoWritePipe = Class (EPipeError);
+ EPipeSeek = Class (EPipeError);
+ EPipeCreation = Class (EPipeError);
+
+ { TInputPipeStream }
+
+ TInputPipeStream = Class(THandleStream)
+ Private
+ FPos : Int64;
+ function GetNumBytesAvailable: DWord;
+ public
+ Function Write (Const Buffer; Count : Longint) :Longint; Override;
+ Function Seek (Offset : Longint;Origin : Word) : longint;override;
+ Function Read (Var Buffer; Count : Longint) : longint; Override;
+ property NumBytesAvailable: DWord read GetNumBytesAvailable;
+ end;
+
+ TOutputPipeStream = Class(THandleStream)
+ Public
+ Function Seek (Offset : Longint;Origin : Word) : longint;override;
+ Function Read (Var Buffer; Count : Longint) : longint; Override;
+ end;
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+Procedure CreatePipeStreams (Var InPipe : TInputPipeStream;
+ Var OutPipe : TOutputPipeStream);
+
+Const EPipeMsg = 'Failed to create pipe.';
+ ENoReadMSg = 'Cannot read from OuputPipeStream.';
+ ENoWriteMsg = 'Cannot write to InputPipeStream.';
+ ENoSeekMsg = 'Cannot seek on pipes';
+
+
+Implementation
+
+{$i pipes.inc}
+
+Procedure CreatePipeStreams (Var InPipe : TInputPipeStream;
+ Var OutPipe : TOutputPipeStream);
+
+Var InHandle,OutHandle : THandle;
+
+begin
+ if CreatePipeHandles (InHandle, OutHandle) then
+ begin
+ InPipe:=TInputPipeStream.Create (InHandle);
+ OutPipe:=TOutputPipeStream.Create (OutHandle);
+ end
+ Else
+ Raise EPipeCreation.Create (EPipeMsg)
+end;
+
+Function TInputPipeStream.Write (Const Buffer; Count : Longint) : longint;
+
+begin
+ Raise ENoWritePipe.Create (ENoWriteMsg);
+end;
+
+Function TInputPipeStream.Read (Var Buffer; Count : Longint) : longint;
+
+begin
+ Result:=Inherited Read(Buffer,Count);
+ Inc(FPos,Result);
+end;
+
+Function TInputPipeStream.Seek (Offset : Longint;Origin : Word) : longint;
+
+Const BufSize = 100;
+
+Var Buf : array[1..BufSize] of Byte;
+
+begin
+ If (Origin=soFromCurrent) and (Offset=0) then
+ result:=FPos;
+ { Try to fake seek by reading and discarding }
+ if Not((Origin=soFromCurrent) and (Offset>=0) or
+ ((Origin=soFrombeginning) and (OffSet>=FPos))) then
+ Raise EPipeSeek.Create(ENoSeekMSg);
+ if Origin=soFromBeginning then
+ Dec(Offset,FPos);
+ While ((Offset Div BufSize)>0)
+ and (Read(Buf,SizeOf(Buf))=BufSize) do
+ Dec(Offset,BufSize);
+ If (Offset>0) then
+ Read(Buf,BufSize);
+ Result:=FPos;
+end;
+
+Function TOutputPipeStream.Read(Var Buffer; Count : Longint) : longint;
+
+begin
+ Raise ENoReadPipe.Create (ENoReadMsg);
+end;
+
+Function TOutputPipeStream.Seek (Offset : Longint;Origin : Word) : longint;
+
+begin
+ Raise EPipeSeek.Create (ENoSeekMsg);
+end;
+
+end.
diff --git a/packages/fcl-process/src/process.pp b/packages/fcl-process/src/process.pp
new file mode 100644
index 0000000000..6c732c9c85
--- /dev/null
+++ b/packages/fcl-process/src/process.pp
@@ -0,0 +1,325 @@
+{
+ This file is part of the Free Component Library (FCL)
+ Copyright (c) 1999-2000 by the Free Pascal development team
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit process;
+
+interface
+
+Uses Classes,
+ pipes,
+ SysUtils;
+
+Type
+ TProcessOption = (poRunSuspended,poWaitOnExit,
+ poUsePipes,poStderrToOutPut,
+ poNoConsole,poNewConsole,
+ poDefaultErrorMode,poNewProcessGroup,
+ poDebugProcess,poDebugOnlyThisProcess);
+
+ TShowWindowOptions = (swoNone,swoHIDE,swoMaximize,swoMinimize,swoRestore,swoShow,
+ swoShowDefault,swoShowMaximized,swoShowMinimized,
+ swoshowMinNOActive,swoShowNA,swoShowNoActivate,swoShowNormal);
+
+ TStartupOption = (suoUseShowWindow,suoUseSize,suoUsePosition,
+ suoUseCountChars,suoUseFillAttribute);
+
+ TProcessPriority = (ppHigh,ppIdle,ppNormal,ppRealTime);
+
+ TProcessOptions = set of TProcessOption;
+ TStartupOptions = set of TStartupOption;
+
+
+Type
+ TProcess = Class (TComponent)
+ Private
+ FProcessOptions : TProcessOptions;
+ FStartupOptions : TStartupOptions;
+ FProcessID : Integer;
+ FThreadID : Integer;
+ FProcessHandle : Thandle;
+ FThreadHandle : Thandle;
+ FFillAttribute : Cardinal;
+ FApplicationName : string;
+ FConsoleTitle : String;
+ FCommandLine : String;
+ FCurrentDirectory : String;
+ FDesktop : String;
+ FEnvironment : Tstrings;
+ FShowWindow : TShowWindowOptions;
+ FInherithandles : Boolean;
+ FProcessPriority : TProcessPriority;
+ dwXCountchars,
+ dwXSize,
+ dwYsize,
+ dwx,
+ dwYcountChars,
+ dwy : Cardinal;
+ Procedure FreeStreams;
+ Function GetExitStatus : Integer;
+ Function GetRunning : Boolean;
+ Function GetWindowRect : TRect;
+ Procedure SetWindowRect (Value : TRect);
+ Procedure SetShowWindow (Value : TShowWindowOptions);
+ Procedure SetWindowColumns (Value : Cardinal);
+ Procedure SetWindowHeight (Value : Cardinal);
+ Procedure SetWindowLeft (Value : Cardinal);
+ Procedure SetWindowRows (Value : Cardinal);
+ Procedure SetWindowTop (Value : Cardinal);
+ Procedure SetWindowWidth (Value : Cardinal);
+ procedure SetApplicationName(const Value: String);
+ procedure SetProcessOptions(const Value: TProcessOptions);
+ procedure SetActive(const Value: Boolean);
+ procedure SetEnvironment(const Value: TStrings);
+ function PeekExitStatus: Boolean;
+ Protected
+ FRunning : Boolean;
+ FExitCode : Cardinal;
+ FInputStream : TOutputPipeStream;
+ FOutputStream : TInputPipeStream;
+ FStderrStream : TInputPipeStream;
+ procedure CloseProcessHandles; virtual;
+ Procedure CreateStreams(InHandle,OutHandle,ErrHandle : Longint);virtual;
+ procedure FreeStream(var AStream: THandleStream);
+ Public
+ Constructor Create (AOwner : TComponent);override;
+ Destructor Destroy; override;
+ Procedure Execute; virtual;
+ procedure CloseInput; virtual;
+ procedure CloseOutput; virtual;
+ procedure CloseStderr; virtual;
+ Function Resume : Integer; virtual;
+ Function Suspend : Integer; virtual;
+ Function Terminate (AExitCode : Integer): Boolean; virtual;
+ Function WaitOnExit : Boolean;
+ Property WindowRect : Trect Read GetWindowRect Write SetWindowRect;
+ Property Handle : THandle Read FProcessHandle;
+ Property ProcessHandle : THandle Read FProcessHandle;
+ Property ThreadHandle : THandle Read FThreadHandle;
+ Property ProcessID : Integer Read FProcessID;
+ Property ThreadID : Integer Read FThreadID;
+ Property Input : TOutputPipeStream Read FInputStream;
+ Property Output : TInputPipeStream Read FOutputStream;
+ Property Stderr : TinputPipeStream Read FStderrStream;
+ Property ExitStatus : Integer Read GetExitStatus;
+ Property InheritHandles : Boolean Read FInheritHandles Write FInheritHandles;
+ Published
+ Property Active : Boolean Read GetRunning Write SetActive;
+ Property ApplicationName : String Read FApplicationName Write SetApplicationName;
+ Property CommandLine : String Read FCommandLine Write FCommandLine;
+ Property ConsoleTitle : String Read FConsoleTitle Write FConsoleTitle;
+ Property CurrentDirectory : String Read FCurrentDirectory Write FCurrentDirectory;
+ Property Desktop : String Read FDesktop Write FDesktop;
+ Property Environment : TStrings Read FEnvironment Write SetEnvironment;
+ Property Options : TProcessOptions Read FProcessOptions Write SetProcessOptions;
+ Property Priority : TProcessPriority Read FProcessPriority Write FProcessPriority;
+ Property StartupOptions : TStartupOptions Read FStartupOptions Write FStartupOptions;
+ Property Running : Boolean Read GetRunning;
+ Property ShowWindow : TShowWindowOptions Read FShowWindow Write SetShowWindow;
+ Property WindowColumns : Cardinal Read dwXCountChars Write SetWindowColumns;
+ Property WindowHeight : Cardinal Read dwYSize Write SetWindowHeight;
+ Property WindowLeft : Cardinal Read dwX Write SetWindowLeft;
+ Property WindowRows : Cardinal Read dwYCountChars Write SetWindowRows;
+ Property WindowTop : Cardinal Read dwY Write SetWindowTop ;
+ Property WindowWidth : Cardinal Read dwXSize Write SetWindowWidth;
+ Property FillAttribute : Cardinal read FFillAttribute Write FFillAttribute;
+ end;
+
+ EProcess = Class(Exception);
+
+implementation
+
+{$i process.inc}
+
+Constructor TProcess.Create (AOwner : TComponent);
+begin
+ Inherited;
+ FProcessPriority:=ppNormal;
+ FShowWindow:=swoNone;
+ FInheritHandles:=True;
+ FEnvironment:=TStringList.Create;
+end;
+
+Destructor TProcess.Destroy;
+
+begin
+ FEnvironment.Free;
+ FreeStreams;
+ CloseProcessHandles;
+ Inherited Destroy;
+end;
+
+Procedure TProcess.FreeStreams;
+begin
+ If FStderrStream<>FOutputStream then
+ FreeStream(FStderrStream);
+ FreeStream(FOutputStream);
+ FreeStream(FInputStream);
+end;
+
+
+Function TProcess.GetExitStatus : Integer;
+
+begin
+ If FRunning then
+ PeekExitStatus;
+ Result:=FExitCode;
+end;
+
+
+Function TProcess.GetRunning : Boolean;
+
+begin
+ IF FRunning then
+ FRunning:=Not PeekExitStatus;
+ Result:=FRunning;
+end;
+
+
+Procedure TProcess.CreateStreams(InHandle,OutHandle,ErrHandle : Longint);
+
+begin
+ FreeStreams;
+ FInputStream:=TOutputPipeStream.Create (InHandle);
+ FOutputStream:=TInputPipeStream.Create (OutHandle);
+ if Not (poStderrToOutput in FProcessOptions) then
+ FStderrStream:=TInputPipeStream.Create(ErrHandle);
+end;
+
+procedure TProcess.FreeStream(var AStream: THandleStream);
+begin
+ if AStream = nil then exit;
+ FileClose(AStream.Handle);
+ FreeAndNil(AStream);
+end;
+
+procedure TProcess.CloseInput;
+begin
+ FreeStream(FInputStream);
+end;
+
+procedure TProcess.CloseOutput;
+begin
+ FreeStream(FOutputStream);
+end;
+
+procedure TProcess.CloseStderr;
+begin
+ FreeStream(FStderrStream);
+end;
+
+Procedure TProcess.SetWindowColumns (Value : Cardinal);
+
+begin
+ if Value<>0 then
+ Include(FStartupOptions,suoUseCountChars);
+ dwXCountChars:=Value;
+end;
+
+
+Procedure TProcess.SetWindowHeight (Value : Cardinal);
+
+begin
+ if Value<>0 then
+ include(FStartupOptions,suoUsePosition);
+ dwYSize:=Value;
+end;
+
+Procedure TProcess.SetWindowLeft (Value : Cardinal);
+
+begin
+ if Value<>0 then
+ Include(FStartupOptions,suoUseSize);
+ dwx:=Value;
+end;
+
+Procedure TProcess.SetWindowTop (Value : Cardinal);
+
+begin
+ if Value<>0 then
+ Include(FStartupOptions,suoUsePosition);
+ dwy:=Value;
+end;
+
+Procedure TProcess.SetWindowWidth (Value : Cardinal);
+begin
+ If (Value<>0) then
+ Include(FStartupOptions,suoUseSize);
+ dwXSize:=Value;
+end;
+
+Function TProcess.GetWindowRect : TRect;
+begin
+ With Result do
+ begin
+ Left:=dwx;
+ Right:=dwx+dwxSize;
+ Top:=dwy;
+ Bottom:=dwy+dwysize;
+ end;
+end;
+
+Procedure TProcess.SetWindowRect (Value : Trect);
+begin
+ Include(FStartupOptions,suoUseSize);
+ Include(FStartupOptions,suoUsePosition);
+ With Value do
+ begin
+ dwx:=Left;
+ dwxSize:=Right-Left;
+ dwy:=Top;
+ dwySize:=Bottom-top;
+ end;
+end;
+
+
+Procedure TProcess.SetWindowRows (Value : Cardinal);
+
+begin
+ if Value<>0 then
+ Include(FStartupOptions,suoUseCountChars);
+ dwYCountChars:=Value;
+end;
+
+procedure TProcess.SetApplicationName(const Value: String);
+begin
+ FApplicationName := Value;
+ If (csDesigning in ComponentState) and
+ (FCommandLine='') then
+ FCommandLine:=Value;
+end;
+
+procedure TProcess.SetProcessOptions(const Value: TProcessOptions);
+begin
+ FProcessOptions := Value;
+ If poNewConsole in FProcessOptions then
+ Exclude(FProcessOptions,poNoConsole);
+ if poRunSuspended in FProcessOptions then
+ Exclude(FProcessOptions,poWaitOnExit);
+end;
+
+procedure TProcess.SetActive(const Value: Boolean);
+begin
+ if (Value<>GetRunning) then
+ If Value then
+ Execute
+ else
+ Terminate(0);
+end;
+
+procedure TProcess.SetEnvironment(const Value: TStrings);
+begin
+ FEnvironment.Assign(Value);
+end;
+
+end.
diff --git a/packages/fcl-process/src/process.txt b/packages/fcl-process/src/process.txt
new file mode 100644
index 0000000000..1d9aeb36c5
--- /dev/null
+++ b/packages/fcl-process/src/process.txt
@@ -0,0 +1,281 @@
+This file describes the TProcess object.
+
+The TProcess object provides an easy way to start and manipulate
+the running of other programs (processes) by your application.
+On top of that, it allows you to redirect the program's input, output
+and standard error to streams that are readable/writeable by your
+program.
+
+It is a descendent class of TObject, but this is easily changeable to
+TComponent, should you desire to do so. None of the properties will
+conflict with the existing properties of TComponent.
+
+Furthermore it is written in such a way that it is easily extensible,
+although most of the properties that a Process has, are accessible and
+can be controlled with this object.
+
+In what follows, is a description of the object's methods and properties.
+
+The following two types control the creation of the TProcess Object.
+See The constructor description for a description on what they do.
+
+TProcessOptions = (poExecuteOnCreate,poRunSuspended,poUsePipes,
+ poNoConsole,poStderrToOutPut,poWaitOnExit);
+TCreateOptions = Set of TPRocessOptions;
+
+
+
+Constructor Create (Const ACommandline : String;
+ Options : TCreateOptions);
+
+This creates an TPRocess object.
+
+ACommandline is the commandline to execute, including any options
+you wish to pass to the program. If you don't specify an explicit path
+Windows will look for your program in the Windows directory and in the
+path.
+
+Options control the behaviour of the object. It can be a set of the
+following constants:
+
+poExecuteOnCreate
+ If you include this option, the constructor will immediatly
+ call the Execute method, using default settings for all parameters.
+ This has the effect that the program is run at once.
+
+poRunSuspended
+ If you include this option, the Execute method will start the
+ program in a suspended state, and the program will start running
+ only after you have called the Resume method.
+
+poUsePipes
+ If you include this option, the Execute method will redirect the
+ standard input,output and error descriptors to 3 pipes, which you
+ can read from or write to.
+ (see Input,OutPut and Error properties)
+ It makes little sense to use ths for GUI applications (i.e. non-
+ console applications)
+
+poNoConsole
+ If you include this option, the application will not display a
+ console, untill it explicitly needs one or requests one using the
+ AllocConsole method. This is very convenient in combination with the
+ poUsePipes option, allowing you to run an application without getting
+ the Console window, and being able to read it's output at once.
+
+poStderrToOutPut
+ If This option is included, then the error desciptor is redirected to
+ the standard output director, i.e. all output goes to the standard
+ output.
+
+poWaitOnExit
+ If you specify this option, then the Execute method will wait for the
+ executed program to finish, before returning.
+ This option will be ignored if you also specified ExecuteOnCreate and
+ CreateSuspended.
+
+
+Destructor Destroy; virtual;
+
+ Destroys the TProcess Object. Be careful NOT to close a TProcess
+ object when you use pipes, and the application is still running.
+ you may kill it.
+
+Procedure Execute; virtual;
+ This actually runs the application. It will return immediatly, unless
+ you specified the poWaitOnExit option when creating the object.
+
+Function Resume : Integer; virtual;
+ Resume lowers the suspend count of the application.
+ it returns the new suspend count of the application. As long as the
+ suspend count is larger than 0, the application will not run.
+ If the suspend count reaches 0, the application will continue
+ running.
+
+Function Suspend : Integer; virtual;
+ Increases the suspend count of the application, and returns the
+ new suspend count of the application.
+
+Function Terminate (AExitCode : Integer): Boolean; virtual;
+ Terminate terminates the main thread of the application, giving it
+ exitcode 'AExitCode'
+ It returns True on succes, False on failure.
+
+Function WaitOnExit : Boolean;
+ This function returns true if the wait for the process exit was succesful,
+ false if some error occurded. It returns immediatly if the application is
+ not running, and waits for the application to finish if it was still running.
+
+Property ApplicationName : String;
+ Sets the name of the application.
+
+Property CommandLine : String;
+ Read-Only
+ contains the commandline of the application, as set by the create
+ method of TProcess.
+
+Property ConsoleTitle : String;
+ For console applications only :
+ Sets the title that appears in the title bar of the Console window.
+
+Property CreateOptions : TCreateOptions;
+ Read-Only
+ Contains the options as set by the Create method of TProcess.
+
+Property CreationFlags : Cardinal;
+ This contains the creation flags that are passed to the CreateProcess
+ call. These flags are modified by the Execute call to reflect any
+ settings tat you may have made.
+
+Property CurrentDirectory : String;
+ When set, the process wil start in the directory that you have set
+ for it.
+
+Property DeskTop : String;
+ NT only:
+ Contains the name of the desktop or window station that the process
+ will be run on. See STARTUPINFO in the win32 programmers manual.
+
+Property Environment : Pointer;
+ A pointer to a null-terminated list of environment variable pointers.
+ Each pair is of the form 'Name=Value'.
+ If this is nil, the environment of your application is used.
+
+Property ExitStatus : Integer;
+ Read-Only
+ This returns the exit status of the application, or STILL_ACTIVE
+ (defined in Windows.pas) if the application is still running.
+
+Property FillAttribute : Integer;
+ For console processes only.
+ Sets the fill color for the console window.
+
+Property Handle : THandle;
+ Read-Only;
+ Returns the handle of the process, which can be used to pass on to
+ calls that require a handle of a process.
+ Onl valid if the process is running.
+
+
+Property Input : TOutPutPipeStream;
+ Read-Only
+ Returns the Input handle of the process.
+ Anything you write to this stream, will appear on the applications
+ input file descriptor.
+ Only valid if you used poUsePipes when you created the TProcess
+ object.
+
+Property InheritHandles : LongBool;
+ If you set this to true, each inheritable handle of your application
+ is inherited by the new application.
+
+Property OutPut : TInputPipeStream;
+ Read-Only
+ Returns the Output handle of the process. Anything the process writes
+ to its standard output can be read from this stream.
+ Only valid if you used poUsePipes when you created the TProcess
+ object.
+
+Property ProcessAttributes : TSecurityAttributes;
+
+Property ProcessInformation : TProcessInformation;
+ Read-Only
+ Gives access to the ProcessInformation returned by Windows
+ upon executing the program. This contains
+ hProcess : Process Handle (See Handle property)
+ hThread : Process' main thread handle (See ThreadHandle property)
+ dwProcessId : Process ID. (as seen in the task manager)
+ dwThreadId : Process' main thread ID
+
+Property Running : Boolean;
+ Read-Only
+ Retruns True if the application is still running, False otherwise.
+ If the application is suspended or not doesn't affect the result.
+
+Property ShowWindow : Word;
+ You can set the applications ShowWindow attribute here.
+
+Property StartupInfo : TStartupInfo;
+ Read-Only
+ Gives access to the TStartupInfo that will be passed to the
+ application in the CreateProcess Call. You can manipulate its various
+ members through the properties of the TProcess object.
+
+Property StdErr : TinputPipeStream;
+ Read-Only
+ Returns the Output handle of the process. Anything the process writes
+ to its error output can be read from this stream.
+ Only valid if you used poUsePipes when you created the TProcess
+ object.
+ If you specified poStderrToOutput then this is the same as the
+ 'Output' stream.
+
+Property ThreadAttributes : TSecurityAttributes;
+ Contains the security attributes that will be passed to the process'
+ main thread. By default, no security attributes are passed.
+
+Property ThreadHandle : THandle;
+ Read-Only
+ Returns the Handle of the process' main thread.
+
+Property WindowColumns : Integer;
+ For console applications:
+ This will set the number of screen columns that the console window
+ will have.
+ If you don't set this property nor the WindowRows property, Windows will
+ choose default values.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowHeight : Integer;
+ Set the height of the application's main window.
+ If you don't specify this, nor WindowWidth, Windows will choose
+ the height and Width of the applications window.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowLeft : Integer;
+ Set the applications main window position, in pixels from the left
+ side of the screen.
+ If you don't specify this, nor WindowTop, Windows will choose
+ the Left and Top of the applications window.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowRows : Integer;
+ For console applications:
+ This will set the number of screen rows (lines) that the console window
+ will have.
+ If you don't set this property nor the WindowColumns property, Windows will
+ choose default values.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowTop : Integer;
+ Set the applications main window position, in pixels from the Top
+ side of the screen.
+ If you don't specify this, nor WindowLeft, Windows will choose
+ the Left and Top of the applications window.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowWidth : Integer;
+ Set the Width of the application's main window.
+ If you don't specify this, nor WindowWidth, Windows will choose
+ the height and Width of the applications window.
+ You can only set this PRIOR to calling the execute method, after
+ the application was executed, or while it is running, the setting
+ will be ignored until you run it again.
+
+Property WindowRect : Trect;
+ This sets the bounding rectangle of the application's main window.
+ It allows to set the WindowTop, WindowLeft, WindowHeight, WindowWidth
+ properties in 1 call.
+
+
+
diff --git a/packages/fcl-process/src/simpleipc.pp b/packages/fcl-process/src/simpleipc.pp
new file mode 100644
index 0000000000..c595e2090b
--- /dev/null
+++ b/packages/fcl-process/src/simpleipc.pp
@@ -0,0 +1,457 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Unit implementing one-way IPC between 2 processes
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+unit simpleipc;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils;
+
+Const
+ MsgVersion = 1;
+
+ //Message types
+ mtUnknown = 0;
+ mtString = 1;
+
+Type
+
+ TMessageType = LongInt;
+ TMsgHeader = Packed record
+ Version : Byte;
+ MsgType : TMessageType;
+ MsgLen : Integer;
+ end;
+
+ TSimpleIPCServer = class;
+ TSimpleIPCClient = class;
+
+ { TIPCServerComm }
+
+ TIPCServerComm = Class(TObject)
+ Private
+ FOwner : TSimpleIPCServer;
+ Protected
+ Function GetInstanceID : String; virtual; abstract;
+ Public
+ Constructor Create(AOwner : TSimpleIPCServer); virtual;
+ Property Owner : TSimpleIPCServer read FOwner;
+ Procedure StartServer; virtual; Abstract;
+ Procedure StopServer;virtual; Abstract;
+ Function PeekMessage(TimeOut : Integer) : Boolean;virtual; Abstract;
+ Procedure ReadMessage ;virtual; Abstract;
+ Property InstanceID : String read GetInstanceID;
+ end;
+ TIPCServerCommClass = Class of TIPCServerComm;
+
+ { TSimpleIPC }
+ TSimpleIPC = Class(TComponent)
+ Private
+ procedure SetActive(const AValue: Boolean);
+ procedure SetServerID(const AValue: String);
+ Protected
+ FBusy: Boolean;
+ FActive : Boolean;
+ FServerID : String;
+ Procedure DoError(Msg : String; Args : Array of const);
+ Procedure CheckInactive;
+ Procedure CheckActive;
+ Procedure Activate; virtual; abstract;
+ Procedure Deactivate; virtual; abstract;
+ Property Busy : Boolean Read FBusy;
+ Published
+ Property Active : Boolean Read FActive Write SetActive;
+ Property ServerID : String Read FServerID Write SetServerID;
+ end;
+
+ { TSimpleIPCServer }
+
+ TSimpleIPCServer = Class(TSimpleIPC)
+ private
+ FGlobal: Boolean;
+ FOnMessage: TNotifyEvent;
+ FMsgType: TMessageType;
+ FMsgData : TStream;
+ function GetInstanceID: String;
+ function GetStringMessage: String;
+ procedure SetGlobal(const AValue: Boolean);
+ Protected
+ FIPCComm: TIPCServerComm;
+ Function CommClass : TIPCServerCommClass; virtual;
+ Procedure Activate; override;
+ Procedure Deactivate; override;
+ Procedure ReadMessage;
+ Public
+ Constructor Create(AOwner : TComponent); override;
+ Destructor Destroy; override;
+ Procedure StartServer;
+ Procedure StopServer;
+ Function PeekMessage(TimeOut : Integer; DoReadMessage : Boolean): Boolean;
+ Property StringMessage : String Read GetStringMessage;
+ Procedure GetMessageData(Stream : TStream);
+ Property MsgType: TMessageType Read FMsgType;
+ Property MsgData : TStream Read FMsgData;
+ Property InstanceID : String Read GetInstanceID;
+ Published
+ Property Global : Boolean Read FGlobal Write SetGlobal;
+ Property OnMessage : TNotifyEvent Read FOnMessage Write FOnMessage;
+ end;
+
+
+ { TIPCClientComm}
+ TIPCClientComm = Class(TObject)
+ private
+ FOwner: TSimpleIPCClient;
+ Public
+ Constructor Create(AOwner : TSimpleIPCClient); virtual;
+ Property Owner : TSimpleIPCClient read FOwner;
+ Procedure Connect; virtual; abstract;
+ Procedure Disconnect; virtual; abstract;
+ Function ServerRunning : Boolean; virtual; abstract;
+ Procedure SendMessage(MsgType : TMessageType; Stream : TStream);virtual;Abstract;
+ end;
+ TIPCClientCommClass = Class of TIPCClientComm;
+
+ { TSimpleIPCClient }
+ TSimpleIPCClient = Class(TSimpleIPC)
+ Private
+ FServerInstance: String;
+ procedure SetServerInstance(const AValue: String);
+ Protected
+ FIPCComm : TIPCClientComm;
+ Procedure Activate; override;
+ Procedure Deactivate; override;
+ Function CommClass : TIPCClientCommClass; virtual;
+ Public
+ Constructor Create(AOwner : TComponent); override;
+ Destructor Destroy; override;
+ Procedure Connect;
+ Procedure Disconnect;
+ Function ServerRunning : Boolean;
+ Procedure SendMessage(MsgType : TMessageType; Stream: TStream);
+ Procedure SendStringMessage(const Msg : String);
+ Procedure SendStringMessage(MsgType : TMessageType; const Msg : String);
+ Procedure SendStringMessageFmt(const Msg : String; Args : Array of const);
+ Procedure SendStringMessageFmt(MsgType : TMessageType; const Msg : String; Args : Array of const);
+ Property ServerInstance : String Read FServerInstance Write SetServerInstance;
+ end;
+
+
+ EIPCError = Class(Exception);
+
+Var
+ DefaultIPCServerClass : TIPCServerCommClass = Nil;
+ DefaultIPCClientClass : TIPCClientCommClass = Nil;
+
+resourcestring
+ SErrServerNotActive = 'Server with ID %s is not active.';
+ SErrActive = 'This operation is illegal when the server is active.';
+ SErrInActive = 'This operation is illegal when the server is inactive.';
+
+
+implementation
+
+{ ---------------------------------------------------------------------
+ Include platform specific implementation.
+ Should implement the CommClass method of both server and client component,
+ as well as the communication class itself.
+
+ This comes first, to allow the uses clause to be set.
+ --------------------------------------------------------------------- }
+
+{$i simpleipc.inc}
+
+{ ---------------------------------------------------------------------
+ TIPCServerComm
+ ---------------------------------------------------------------------}
+
+constructor TIPCServerComm.Create(AOwner: TSimpleIPCServer);
+begin
+ FOwner:=AOWner;
+end;
+
+{ ---------------------------------------------------------------------
+ TIPCClientComm
+ ---------------------------------------------------------------------}
+
+constructor TIPCClientComm.Create(AOwner: TSimpleIPCClient);
+begin
+ FOwner:=AOwner;
+end;
+
+{ ---------------------------------------------------------------------
+ TSimpleIPC
+ ---------------------------------------------------------------------}
+
+procedure TSimpleIPC.DoError(Msg: String; Args: array of const);
+begin
+ Raise EIPCError.Create(Name+': '+Format(Msg,Args));
+end;
+
+procedure TSimpleIPC.CheckInactive;
+begin
+ If Active then
+ DoError(SErrActive,[]);
+end;
+
+procedure TSimpleIPC.CheckActive;
+begin
+ If Not Active then
+ DoError(SErrInActive,[]);
+end;
+
+procedure TSimpleIPC.SetActive(const AValue: Boolean);
+begin
+ if (FActive<>AValue) then
+ begin
+ If AValue then
+ Activate
+ else
+ Deactivate;
+ end;
+end;
+
+procedure TSimpleIPC.SetServerID(const AValue: String);
+begin
+ if (FServerID<>AValue) then
+ begin
+ CheckInactive;
+ FServerID:=AValue
+ end;
+end;
+
+{ ---------------------------------------------------------------------
+ TSimpleIPCServer
+ ---------------------------------------------------------------------}
+
+constructor TSimpleIPCServer.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FGlobal:=False;
+ FActive:=False;
+ FBusy:=False;
+ FMsgData:=TStringStream.Create('');
+end;
+
+destructor TSimpleIPCServer.Destroy;
+begin
+ Active:=False;
+ FreeAndNil(FMsgData);
+ inherited Destroy;
+end;
+
+procedure TSimpleIPCServer.SetGlobal(const AValue: Boolean);
+begin
+ if (FGlobal<>AValue) then
+ begin
+ CheckInactive;
+ FGlobal:=AValue;
+ end;
+end;
+
+function TSimpleIPCServer.GetInstanceID: String;
+begin
+ Result:=FIPCComm.InstanceID;
+end;
+
+
+function TSimpleIPCServer.GetStringMessage: String;
+begin
+ Result:=TStringStream(FMsgData).DataString;
+end;
+
+
+procedure TSimpleIPCServer.StartServer;
+begin
+ if Not Assigned(FIPCComm) then
+ begin
+ If (FServerID='') then
+ FServerID:=ApplicationName;
+ FIPCComm:=CommClass.Create(Self);
+ FIPCComm.StartServer;
+ end;
+ FActive:=True;
+end;
+
+procedure TSimpleIPCServer.StopServer;
+begin
+ If Assigned(FIPCComm) then
+ begin
+ FIPCComm.StopServer;
+ FreeAndNil(FIPCComm);
+ end;
+ FActive:=False;
+end;
+
+function TSimpleIPCServer.PeekMessage(TimeOut: Integer; DoReadMessage: Boolean
+ ): Boolean;
+begin
+ CheckActive;
+ FBusy:=True;
+ Try
+ Result:=FIPCComm.PeekMessage(Timeout);
+ Finally
+ FBusy:=False;
+ end;
+ If Result then
+ If DoReadMessage then
+ Readmessage;
+end;
+
+procedure TSimpleIPCServer.ReadMessage;
+begin
+ CheckActive;
+ FBusy:=True;
+ Try
+ FIPCComm.ReadMessage;
+ If Assigned(FOnMessage) then
+ FOnMessage(Self);
+ Finally
+ FBusy:=False;
+ end;
+end;
+
+procedure TSimpleIPCServer.GetMessageData(Stream: TStream);
+begin
+ Stream.CopyFrom(FMsgData,0);
+end;
+
+procedure TSimpleIPCServer.Activate;
+begin
+ StartServer;
+end;
+
+procedure TSimpleIPCServer.Deactivate;
+begin
+ StopServer;
+end;
+
+{ ---------------------------------------------------------------------
+ TSimpleIPCClient
+ ---------------------------------------------------------------------}
+
+procedure TSimpleIPCClient.SetServerInstance(const AValue: String);
+begin
+ CheckInactive;
+ FServerInstance:=AVAlue;
+end;
+
+procedure TSimpleIPCClient.Activate;
+begin
+ Connect;
+end;
+
+procedure TSimpleIPCClient.Deactivate;
+begin
+ DisConnect;
+end;
+constructor TSimpleIPCClient.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+end;
+
+destructor TSimpleIPCClient.destroy;
+begin
+ Active:=False;
+ Inherited;
+end;
+
+procedure TSimpleIPCClient.Connect;
+begin
+ If Not assigned(FIPCComm) then
+ begin
+ FIPCComm:=CommClass.Create(Self);
+ Try
+ FIPCComm.Connect;
+ Except
+ FreeAndNil(FIPCComm);
+ Raise;
+ end;
+ FActive:=True;
+ end;
+end;
+
+procedure TSimpleIPCClient.Disconnect;
+begin
+ If Assigned(FIPCComm) then
+ Try
+ FIPCComm.DisConnect;
+ Finally
+ FActive:=False;
+ FreeAndNil(FIPCComm);
+ end;
+end;
+
+function TSimpleIPCClient.ServerRunning: Boolean;
+
+begin
+ If Assigned(FIPCComm) then
+ Result:=FIPCComm.ServerRunning
+ else
+ With CommClass.Create(Self) do
+ Try
+ Result:=ServerRunning;
+ finally
+ Free;
+ end;
+end;
+
+procedure TSimpleIPCClient.SendMessage(MsgType : TMessageType; Stream: TStream);
+
+begin
+ CheckActive;
+ FBusy:=True;
+ Try
+ FIPCComm.SendMessage(MsgType,Stream);
+ Finally
+ FBusy:=False;
+ end;
+end;
+
+procedure TSimpleIPCClient.SendStringMessage(const Msg: String);
+begin
+ SendStringMessage(mtString,Msg);
+end;
+
+procedure TSimpleIPCClient.SendStringMessage(MsgType: TMessageType; const Msg: String
+ );
+Var
+ S : TStringStream;
+begin
+ S:=TStringStream.Create(Msg);
+ try
+ SendMessage(MsgType,S);
+ finally
+ S.free;
+ end;
+end;
+
+procedure TSimpleIPCClient.SendStringMessageFmt(const Msg: String;
+ Args: array of const);
+begin
+ SendStringMessageFmt(mtString,Msg,Args);
+end;
+
+procedure TSimpleIPCClient.SendStringMessageFmt(MsgType: TMessageType;
+ const Msg: String; Args: array of const);
+begin
+ SendStringMessage(MsgType, Format(Msg,Args));
+end;
+
+end.
+
diff --git a/packages/fcl-process/src/unix/pipes.inc b/packages/fcl-process/src/unix/pipes.inc
new file mode 100644
index 0000000000..e26bfbce0c
--- /dev/null
+++ b/packages/fcl-process/src/unix/pipes.inc
@@ -0,0 +1,32 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1999-2000 by Michael Van Canneyt
+
+ Linux specific part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+Uses
+ BaseUnix, Unix, TermIO;
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : Longint) : Boolean;
+
+begin
+ Result := (AssignPipe (Inhandle,OutHandle)<>-1);
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ if fpioctl(Handle, FIONREAD, @Result)<0 then
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/unix/process.inc b/packages/fcl-process/src/unix/process.inc
new file mode 100644
index 0000000000..f88623c959
--- /dev/null
+++ b/packages/fcl-process/src/unix/process.inc
@@ -0,0 +1,399 @@
+{
+ Unix Process .inc.
+}
+
+uses
+ Unix,
+ Baseunix;
+
+resourcestring
+ SErrNoSuchProgram = 'Executable not found: "%s"';
+
+Const
+ PriorityConstants : Array [TProcessPriority] of Integer =
+ (20,20,0,-20);
+
+Const
+ GeometryOption : String = '-geometry';
+ TitleOption : String ='-title';
+
+
+
+procedure TProcess.CloseProcessHandles;
+
+begin
+ // Do nothing. Win32 call.
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+
+begin
+ Result:=fpWaitPid(Handle,pcint(@FExitCode),WNOHANG)=Handle;
+ If Result then
+ FExitCode:=wexitstatus(FExitCode)
+ else
+ FexitCode:=0;
+end;
+
+Type
+ TPCharArray = Array[Word] of pchar;
+ PPCharArray = ^TPcharArray;
+
+Function StringsToPCharList(List : TStrings) : PPChar;
+
+Var
+ I : Integer;
+ S : String;
+
+begin
+ I:=(List.Count)+1;
+ GetMem(Result,I*sizeOf(PChar));
+ PPCharArray(Result)^[List.Count]:=Nil;
+ For I:=0 to List.Count-1 do
+ begin
+ S:=List[i];
+ Result[i]:=StrNew(PChar(S));
+ end;
+end;
+
+Procedure FreePCharList(List : PPChar);
+
+Var
+ I : integer;
+
+begin
+ I:=0;
+ While List[i]<>Nil do
+ begin
+ StrDispose(List[i]);
+ Inc(I);
+ end;
+ FreeMem(List);
+end;
+
+
+Procedure CommandToList(S : String; List : TStrings);
+
+ Function GetNextWord : String;
+
+ Const
+ WhiteSpace = [' ',#8,#10];
+ Literals = ['"',''''];
+
+ Var
+ Wstart,wend : Integer;
+ InLiteral : Boolean;
+ LastLiteral : char;
+
+ begin
+ WStart:=1;
+ While (WStart<=Length(S)) and (S[WStart] in WhiteSpace) do
+ Inc(WStart);
+ WEnd:=WStart;
+ InLiteral:=False;
+ LastLiteral:=#0;
+ While (Wend<=Length(S)) and (Not (S[Wend] in WhiteSpace) or InLiteral) do
+ begin
+ if S[Wend] in Literals then
+ If InLiteral then
+ InLiteral:=Not (S[Wend]=LastLiteral)
+ else
+ begin
+ InLiteral:=True;
+ LastLiteral:=S[Wend];
+ end;
+ inc(wend);
+ end;
+
+ Result:=Copy(S,WStart,WEnd-WStart);
+
+ if (Length(Result) > 0)
+ and (Result[1] = Result[Length(Result)]) // if 1st char = last char and..
+ and (Result[1] in Literals) then // it's one of the literals, then
+ Result:=Copy(Result, 2, Length(Result) - 2); //delete the 2 (but not others in it)
+
+ While (WEnd<=Length(S)) and (S[Wend] in WhiteSpace) do
+ inc(Wend);
+ Delete(S,1,WEnd-1);
+
+ end;
+
+Var
+ W : String;
+
+begin
+ While Length(S)>0 do
+ begin
+ W:=GetNextWord;
+ If (W<>'') then
+ List.Add(W);
+ end;
+end;
+
+
+Function MakeCommand(P : TProcess) : PPchar;
+
+Const
+ SNoCommandLine = 'Cannot execute empty command-line';
+
+Var
+ Cmd : String;
+ S : TStringList;
+ G : String;
+
+begin
+ if (P.ApplicationName='') then
+ begin
+ If (P.CommandLine='') then
+ Raise EProcess.Create(SNoCommandline);
+ Cmd:=P.CommandLine;
+ end
+ else
+ begin
+ If (P.CommandLine='') then
+ Cmd:=P.ApplicationName
+ else
+ Cmd:=P.CommandLine;
+ end;
+ S:=TStringList.Create;
+ try
+ CommandToList(Cmd,S);
+ if poNewConsole in P.Options then
+ begin
+ S.Insert(0,'-e');
+ If (P.ApplicationName<>'') then
+ begin
+ S.Insert(0,P.ApplicationName);
+ S.Insert(0,'-title');
+ end;
+ if suoUseCountChars in P.StartupOptions then
+ begin
+ S.Insert(0,Format('%dx%d',[P.dwXCountChars,P.dwYCountChars]));
+ S.Insert(0,'-geometry');
+ end;
+ S.Insert(0,'xterm');
+ end;
+ if (P.ApplicationName<>'') then
+ begin
+ S.Add(TitleOption);
+ S.Add(P.ApplicationName);
+ end;
+ G:='';
+ if (suoUseSize in P.StartupOptions) then
+ g:=format('%dx%d',[P.dwXSize,P.dwYsize]);
+ if (suoUsePosition in P.StartupOptions) then
+ g:=g+Format('+%d+%d',[P.dwX,P.dwY]);
+ if G<>'' then
+ begin
+ S.Add(GeometryOption);
+ S.Add(g);
+ end;
+ Result:=StringsToPcharList(S);
+ Finally
+ S.free;
+ end;
+end;
+
+Function GetLastError : Integer;
+
+begin
+ Result:=-1;
+end;
+
+Type
+ TPipeEnd = (peRead,peWrite);
+ TPipePair = Array[TPipeEnd] of cint;
+
+Procedure CreatePipes(Var HI,HO,HE : TPipePair; CE : Boolean);
+
+ Procedure CreatePair(Var P : TPipePair);
+
+ begin
+ If not CreatePipeHandles(P[peRead],P[peWrite]) then
+ Raise EProcess.Create('Failed to create pipes');
+ end;
+
+ Procedure ClosePair(Var P : TPipePair);
+
+ begin
+ if (P[peRead]<>-1) then
+ FileClose(P[peRead]);
+ if (P[peWrite]<>-1) then
+ FileClose(P[peWrite]);
+ end;
+
+begin
+ HO[peRead]:=-1;HO[peWrite]:=-1;
+ HI[peRead]:=-1;HI[peWrite]:=-1;
+ HE[peRead]:=-1;HE[peWrite]:=-1;
+ Try
+ CreatePair(HO);
+ CreatePair(HI);
+ If CE then
+ CreatePair(HE);
+ except
+ ClosePair(HO);
+ ClosePair(HI);
+ If CE then
+ ClosePair(HE);
+ Raise;
+ end;
+end;
+
+Procedure TProcess.Execute;
+
+Var
+ HI,HO,HE : TPipePair;
+ PID : Longint;
+ FEnv : PPChar;
+ Argv : PPChar;
+ fd : Integer;
+ PName : String;
+
+begin
+ If (poUsePipes in FProcessOptions) then
+ CreatePipes(HI,HO,HE,Not (poStdErrToOutPut in FProcessOptions));
+ Try
+ if FEnvironment.Count<>0 then
+ FEnv:=StringsToPcharList(FEnvironment)
+ else
+ FEnv:=Nil;
+ Try
+ Argv:=MakeCommand(Self);
+ Try
+ If (Argv<>Nil) and (ArgV[0]<>Nil) then
+ PName:=StrPas(Argv[0])
+ else
+ begin
+ // This should never happen, actually.
+ PName:=ApplicationName;
+ If (PName='') then
+ PName:=CommandLine;
+ end;
+
+ if not FileExists(PName) then begin
+ PName := FileSearch(Pname,fpgetenv('PATH'));
+
+ if Length(PName) = 0 then
+ raise EProcess.CreateFmt(SErrNoSuchProgram,[PName]);
+ end;
+
+ Pid:=fpfork;
+ if Pid<0 then
+ Raise EProcess.Create('Failed to Fork process');
+ if (PID>0) then
+ begin
+ // Parent process. Copy process information.
+ FProcessHandle:=PID;
+ FThreadHandle:=PID;
+ FProcessId:=PID;
+ //FThreadId:=PID;
+ end
+ else
+ begin
+ { We're in the child }
+ if (FCurrentDirectory<>'') then
+ ChDir(FCurrentDirectory);
+ if PoUsePipes in Options then
+ begin
+ fpclose(HI[peWrite]);
+ fpdup2(HI[peRead],0);
+ fpclose(HO[peRead]);
+ fpdup2(HO[peWrite],1);
+ if (poStdErrToOutPut in Options) then
+ fpdup2(HO[peWrite],2)
+ else
+ begin
+ fpclose(HE[peRead]);
+ fpdup2(HE[peWrite],2);
+ end
+ end
+ else if poNoConsole in Options then
+ begin
+ fd:=FileOpen('/dev/null',fmOpenReadWrite);
+ fpdup2(fd,0);
+ fpdup2(fd,1);
+ fpdup2(fd,2);
+ end;
+ if (poRunSuspended in Options) then
+ sigraise(SIGSTOP);
+ if FEnv<>Nil then
+ fpexecve(PName,Argv,Fenv)
+ else
+ fpexecv(PName,argv);
+ Halt(127);
+ end
+ Finally
+ FreePcharList(Argv);
+ end;
+ Finally
+ If (FEnv<>Nil) then
+ FreePCharList(FEnv);
+ end;
+ Finally
+ if POUsePipes in FProcessOptions then
+ begin
+ FileClose(HO[peWrite]);
+ FileClose(HI[peRead]);
+ if Not (poStdErrToOutPut in FProcessOptions) then
+ FileClose(HE[peWrite]);
+ CreateStreams(HI[peWrite],HO[peRead],HE[peRead]);
+ end;
+ end;
+ FRunning:=True;
+ if not (csDesigning in ComponentState) and // This would hang the IDE !
+ (poWaitOnExit in FProcessOptions) and
+ not (poRunSuspended in FProcessOptions) then
+ WaitOnExit;
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+
+Var
+ R : Dword;
+
+begin
+ R:=fpWaitPid(Handle,pcint(@FExitCode),0);
+ Result:=(R=Handle);
+ If Result then
+ FExitCode:=WExitStatus(FExitCode);
+ FRunning:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+
+begin
+ If fpkill(Handle,SIGSTOP)<>0 then
+ Result:=-1
+ else
+ Result:=1;
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ If fpKill(Handle,SIGCONT)<>0 then
+ Result:=-1
+ else
+ Result:=0;
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+
+begin
+ Result:=False;
+ Result:=fpkill(Handle,SIGTERM)=0;
+ If Result then
+ begin
+ If Running then
+ Result:=fpkill(Handle,SIGKILL)=0;
+ end;
+ GetExitStatus;
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+
+begin
+ FShowWindow:=Value;
+end;
+
diff --git a/packages/fcl-process/src/unix/simpleipc.inc b/packages/fcl-process/src/unix/simpleipc.inc
new file mode 100644
index 0000000000..143ab2471c
--- /dev/null
+++ b/packages/fcl-process/src/unix/simpleipc.inc
@@ -0,0 +1,194 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Unix implementation of one-way IPC between 2 processes
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+uses baseunix;
+
+ResourceString
+ SErrFailedToCreatePipe = 'Failed to create named pipe: %s';
+ SErrFailedToRemovePipe = 'Failed to remove named pipe: %s';
+
+{ ---------------------------------------------------------------------
+ TPipeClientComm
+ ---------------------------------------------------------------------}
+
+Type
+ TPipeClientComm = Class(TIPCClientComm)
+ Private
+ FFileName: String;
+ FStream: TFileStream;
+ Public
+ Constructor Create(AOWner : TSimpleIPCClient); override;
+ Procedure Connect; override;
+ Procedure Disconnect; override;
+ Procedure SendMessage(MsgType : TMessageType; AStream : TStream); override;
+ Function ServerRunning : Boolean; override;
+ Property FileName : String Read FFileName;
+ Property Stream : TFileStream Read FStream;
+ end;
+
+
+constructor TPipeClientComm.Create(AOWner: TSimpleIPCClient);
+
+Var
+ D : String;
+
+begin
+ inherited Create(AOWner);
+ FFileName:=Owner.ServerID;
+ If (Owner.ServerInstance<>'') then
+ FFileName:=FFileName+'-'+Owner.ServerInstance;
+ D:='/tmp/'; // Change to something better later
+ FFileName:=D+FFileName;
+end;
+
+
+procedure TPipeClientComm.Connect;
+begin
+ If Not ServerRunning then
+ Owner.DoError(SErrServerNotActive,[Owner.ServerID]);
+ FStream:=TFileStream.Create(FFileName,fmOpenReadWrite);
+end;
+
+procedure TPipeClientComm.Disconnect;
+begin
+ FreeAndNil(FStream);
+end;
+
+procedure TPipeClientComm.SendMessage(MsgType : TMessagetype; AStream: TStream);
+
+Var
+ Hdr : TMsgHeader;
+ P,L,Count : Integer;
+
+begin
+ Hdr.Version:=MsgVersion;
+ Hdr.msgType:=MsgType;
+ Hdr.MsgLen:=AStream.Size;
+ FStream.WriteBuffer(hdr,SizeOf(hdr));
+ FStream.CopyFrom(AStream,0);
+end;
+
+function TPipeClientComm.ServerRunning: Boolean;
+begin
+ Result:=FileExists(FFileName);
+end;
+
+
+{ ---------------------------------------------------------------------
+ TPipeServerComm
+ ---------------------------------------------------------------------}
+
+Type
+ TPipeServerComm = Class(TIPCServerComm)
+ Private
+ FFileName: String;
+ FStream: TFileStream;
+ Public
+ Constructor Create(AOWner : TSimpleIPCServer); override;
+ Procedure StartServer; override;
+ Procedure StopServer; override;
+ Function PeekMessage(TimeOut : Integer) : Boolean; override;
+ Procedure ReadMessage ; override;
+ Function GetInstanceID : String;override;
+ Property FileName : String Read FFileName;
+ Property Stream : TFileStream Read FStream;
+ end;
+
+constructor TPipeServerComm.Create(AOWner: TSimpleIPCServer);
+
+Var
+ D : String;
+
+begin
+ inherited Create(AOWner);
+ FFileName:=Owner.ServerID;
+ If Not Owner.Global then
+ FFileName:=FFileName+'-'+IntToStr(fpGetPID);
+ D:='/tmp/'; // Change to something better later
+ FFileName:=D+FFileName;
+end;
+
+
+procedure TPipeServerComm.StartServer;
+begin
+ If not FileExists(FFileName) then
+ If (fpmkFifo(FFileName,438)<>0) then
+ Owner.DoError(SErrFailedToCreatePipe,[FFileName]);
+ FStream:=TFileStream.Create(FFileName,fmOpenReadWrite);
+end;
+
+procedure TPipeServerComm.StopServer;
+begin
+ FreeAndNil(FStream);
+ if Not DeleteFile(FFileName) then
+ Owner.DoError(SErrFailedtoRemovePipe,[FFileName]);
+end;
+
+function TPipeServerComm.PeekMessage(TimeOut: Integer): Boolean;
+
+Var
+ FDS : TFDSet;
+
+begin
+ fpfd_zero(FDS);
+ fpfd_set(FStream.Handle,FDS);
+ Result:=fpSelect(FStream.Handle+1,@FDS,Nil,Nil,TimeOut)>0;
+end;
+
+procedure TPipeServerComm.ReadMessage;
+
+Var
+ L,P,Count : Integer;
+ Hdr : TMsgHeader;
+
+begin
+ FStream.ReadBuffer(Hdr,SizeOf(Hdr));
+ Owner.FMsgType:=Hdr.MsgType;
+ Count:=Hdr.MsgLen;
+ if count > 0 then
+ begin
+ Owner.FMsgData.Seek(0,soFrombeginning);
+ Owner.FMsgData.CopyFrom(FStream,Count);
+ end
+ else
+ Owner.FMsgData.Size := 0;
+end;
+
+function TPipeServerComm.GetInstanceID: String;
+begin
+ Result:=IntToStr(fpGetPID);
+end;
+
+{ ---------------------------------------------------------------------
+ Set TSimpleIPCClient / TSimpleIPCServer defaults.
+ ---------------------------------------------------------------------}
+
+Function TSimpleIPCServer.CommClass : TIPCServerCommClass;
+
+begin
+ if (DefaultIPCServerClass<>Nil) then
+ Result:=DefaultIPCServerClass
+ else
+ Result:=TPipeServerComm;
+end;
+
+function TSimpleIPCClient.CommClass: TIPCClientCommClass;
+begin
+ if (DefaultIPCClientClass<>Nil) then
+ Result:=DefaultIPCClientClass
+ else
+ Result:=TPipeClientComm;
+end;
diff --git a/packages/fcl-process/src/win/pipes.inc b/packages/fcl-process/src/win/pipes.inc
new file mode 100644
index 0000000000..3f39493d0e
--- /dev/null
+++ b/packages/fcl-process/src/win/pipes.inc
@@ -0,0 +1,43 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1998 by Michael Van Canneyt
+
+ Win part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+uses windows;
+
+Const piInheritablePipe : TSecurityAttributes = (
+ nlength:SizeOF(TSecurityAttributes);
+ lpSecurityDescriptor:Nil;
+ Binherithandle:True);
+ piNonInheritablePipe : TSecurityAttributes = (
+ nlength:SizeOF(TSecurityAttributes);
+ lpSecurityDescriptor:Nil;
+ Binherithandle:False);
+
+
+ PipeBufSize = 1024;
+
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+
+begin
+ Result := CreatePipe (@Inhandle,@OutHandle,@piInheritablePipe,PipeBufSize);
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+begin
+ if not PeekNamedPipe(Handle, nil, 0, nil, @Result, nil) then
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/win/process.inc b/packages/fcl-process/src/win/process.inc
new file mode 100644
index 0000000000..0661175958
--- /dev/null
+++ b/packages/fcl-process/src/win/process.inc
@@ -0,0 +1,257 @@
+{
+ Win32 Process .inc.
+}
+
+uses Windows;
+
+Const
+ PriorityConstants : Array [TProcessPriority] of Cardinal =
+ (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
+ NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
+
+procedure TProcess.CloseProcessHandles;
+begin
+ if (FProcessHandle<>0) then
+ CloseHandle(FProcessHandle);
+ if (FThreadHandle<>0) then
+ CloseHandle(FThreadHandle);
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+
+begin
+ GetExitCodeProcess(ProcessHandle,FExitCode);
+ Result:=(FExitCode<>Still_Active);
+end;
+
+Function GetStartupFlags (P : TProcess): Cardinal;
+
+begin
+ With P do
+ begin
+ Result:=0;
+ if poUsePipes in FProcessOptions then
+ Result:=Result or Startf_UseStdHandles;
+ if suoUseShowWindow in FStartupOptions then
+ Result:=Result or startf_USESHOWWINDOW;
+ if suoUSESIZE in FStartupOptions then
+ Result:=Result or startf_usesize;
+ if suoUsePosition in FStartupOptions then
+ Result:=Result or startf_USEPOSITION;
+ if suoUSECOUNTCHARS in FStartupoptions then
+ Result:=Result or startf_usecountchars;
+ if suoUsefIllAttribute in FStartupOptions then
+ Result:=Result or startf_USEFILLATTRIBUTE;
+ end;
+end;
+
+Function GetCreationFlags(P : TProcess) : Cardinal;
+
+begin
+ With P do
+ begin
+ Result:=0;
+ if poNoConsole in FProcessOptions then
+ Result:=Result or Detached_Process;
+ if poNewConsole in FProcessOptions then
+ Result:=Result or Create_new_console;
+ if poNewProcessGroup in FProcessOptions then
+ Result:=Result or CREATE_NEW_PROCESS_GROUP;
+ If poRunSuspended in FProcessOptions Then
+ Result:=Result or Create_Suspended;
+ if poDebugProcess in FProcessOptions Then
+ Result:=Result or DEBUG_PROCESS;
+ if poDebugOnlyThisProcess in FProcessOptions Then
+ Result:=Result or DEBUG_ONLY_THIS_PROCESS;
+ if poDefaultErrorMode in FProcessOptions Then
+ Result:=Result or CREATE_DEFAULT_ERROR_MODE;
+ result:=result or PriorityConstants[FProcessPriority];
+ end;
+end;
+
+Function StringsToPChars(List : TStrings): pointer;
+
+var
+ EnvBlock: string;
+ I: Integer;
+
+begin
+ EnvBlock := '';
+ For I:=0 to List.Count-1 do
+ EnvBlock := EnvBlock + List[i] + #0;
+ EnvBlock := EnvBlock + #0;
+ GetMem(Result, Length(EnvBlock));
+ CopyMemory(Result, @EnvBlock[1], Length(EnvBlock));
+end;
+
+Procedure InitProcessAttributes(P : TProcess; Var PA : TSecurityAttributes);
+
+begin
+ FillChar(PA,SizeOf(PA),0);
+ PA.nLength := SizeOf(PA);
+end;
+
+Procedure InitThreadAttributes(P : TProcess; Var TA : TSecurityAttributes);
+
+begin
+ FillChar(TA,SizeOf(TA),0);
+ TA.nLength := SizeOf(TA);
+end;
+
+Procedure InitStartupInfo(P : TProcess; Var SI : STARTUPINFO);
+
+Const
+ SWC : Array [TShowWindowOptions] of Cardinal =
+ (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
+ SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
+ SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
+
+begin
+ FillChar(SI,SizeOf(SI),0);
+ With SI do
+ begin
+ dwFlags:=GetStartupFlags(P);
+ if P.FShowWindow<>swoNone then
+ dwFlags:=dwFlags or Startf_UseShowWindow
+ else
+ dwFlags:=dwFlags and not Startf_UseShowWindow;
+ wShowWindow:=SWC[P.FShowWindow];
+ if (poUsePipes in P.Options) then
+ begin
+ dwFlags:=dwFlags or Startf_UseStdHandles;
+ end;
+ if P.FillAttribute<>0 then
+ begin
+ dwFlags:=dwFlags or Startf_UseFillAttribute;
+ dwFillAttribute:=P.FillAttribute;
+ end;
+ dwXCountChars:=P.WindowColumns;
+ dwYCountChars:=P.WindowRows;
+ dwYsize:=P.WindowHeight;
+ dwXsize:=P.WindowWidth;
+ dwy:=P.WindowTop;
+ dwX:=P.WindowLeft;
+ end;
+end;
+
+Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean);
+
+begin
+ CreatePipeHandles(SI.hStdInput,HI);
+ CreatePipeHandles(HO,Si.hStdOutput);
+ if CE then
+ CreatePipeHandles(HE,SI.hStdError)
+ else
+ begin
+ SI.hStdError:=SI.hStdOutput;
+ HE:=HO;
+ end;
+end;
+
+
+Procedure TProcess.Execute;
+
+
+Var
+ PName,PDir,PCommandLine : PChar;
+ FEnv: pointer;
+ FCreationFlags : Cardinal;
+ FProcessAttributes : TSecurityAttributes;
+ FThreadAttributes : TSecurityAttributes;
+ FProcessInformation : TProcessInformation;
+ FStartupInfo : STARTUPINFO;
+ HI,HO,HE : THandle;
+
+begin
+ FInheritHandles:=True;
+ PName:=Nil;
+ PCommandLine:=Nil;
+ PDir:=Nil;
+ If FApplicationName<>'' then
+ PName:=Pchar(FApplicationName);
+ If FCommandLine<>'' then
+ PCommandLine:=Pchar(FCommandLine);
+ If FCurrentDirectory<>'' then
+ PDir:=Pchar(FCurrentDirectory);
+ if FEnvironment.Count<>0 then
+ FEnv:=StringsToPChars(FEnvironment)
+ else
+ FEnv:=Nil;
+ Try
+ FCreationFlags:=GetCreationFlags(Self);
+ InitProcessAttributes(Self,FProcessAttributes);
+ InitThreadAttributes(Self,FThreadAttributes);
+ InitStartupInfo(Self,FStartUpInfo);
+ If poUsePipes in FProcessOptions then
+ CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions));
+ Try
+ If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
+ FInheritHandles,FCreationFlags,FEnv,PDir,FStartupInfo,
+ fProcessInformation) then
+ Raise EProcess.CreateFmt('Failed to execute %s : %d',[FCommandLine,GetLastError]);
+ FProcessHandle:=FProcessInformation.hProcess;
+ FThreadHandle:=FProcessInformation.hThread;
+ FProcessID:=FProcessINformation.dwProcessID;
+ Finally
+ if POUsePipes in FProcessOptions then
+ begin
+ FileClose(FStartupInfo.hStdInput);
+ FileClose(FStartupInfo.hStdOutput);
+ if Not (poStdErrToOutPut in FProcessOptions) then
+ FileClose(FStartupInfo.hStdError);
+ CreateStreams(HI,HO,HE);
+ end;
+ end;
+ FRunning:=True;
+ Finally
+ If FEnv<>Nil then
+ FreeMem(FEnv);
+ end;
+ if not (csDesigning in ComponentState) and // This would hang the IDE !
+ (poWaitOnExit in FProcessOptions) and
+ not (poRunSuspended in FProcessOptions) then
+ WaitOnExit;
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+
+Var
+ R : DWord;
+
+begin
+ R:=WaitForSingleObject (FProcessHandle,Infinite);
+ Result:=(R<>Wait_Failed);
+ If Result then
+ GetExitStatus;
+ FRunning:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+
+begin
+ Result:=SuspendThread(ThreadHandle);
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=ResumeThread(ThreadHandle);
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+
+begin
+ Result:=False;
+ If ExitStatus=Still_active then
+ Result:=TerminateProcess(Handle,AexitCode);
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+
+
+begin
+ FShowWindow:=Value;
+end;
+
+
+
diff --git a/packages/fcl-process/src/win/simpleipc.inc b/packages/fcl-process/src/win/simpleipc.inc
new file mode 100644
index 0000000000..1bd2758119
--- /dev/null
+++ b/packages/fcl-process/src/win/simpleipc.inc
@@ -0,0 +1,293 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Windows implementation of one-way IPC between 2 processes
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+uses Windows,messages;
+
+Const
+ MsgWndClassName : pchar = 'FPCMsgWindowCls';
+
+Resourcestring
+ SErrFailedToRegisterWindowClass = 'Failed to register message window class';
+ SErrFailedToCreateWindow = 'Failed to create message window %s';
+
+var
+ MsgWindowClass: TWndClass = (
+ style: 0;
+ lpfnWndProc: Nil;
+ cbClsExtra: 0;
+ cbWndExtra: 0;
+ hInstance: 0;
+ hIcon: 0;
+ hCursor: 0;
+ hbrBackground: 0;
+ lpszMenuName: nil;
+ lpszClassName: Nil);
+
+{ ---------------------------------------------------------------------
+ TWinMsgServerComm
+ ---------------------------------------------------------------------}
+
+Type
+ TWinMsgServerComm = Class(TIPCServerComm)
+ Private
+ FHWND : HWND;
+ FWindowName : String;
+ FDataPushed : Boolean;
+ FUnction AllocateHWnd(Const aWindowName : String) : HWND;
+ Public
+ Constructor Create(AOWner : TSimpleIPCServer); override;
+ procedure ReadMsgData(var Msg: TMsg);
+ Procedure StartServer; override;
+ Procedure StopServer; override;
+ Function PeekMessage(TimeOut : Integer) : Boolean; override;
+ Procedure ReadMessage ; override;
+ Function GetInstanceID : String;override;
+ Property WindowName : String Read FWindowName;
+ end;
+
+
+function MsgWndProc(HWindow: HWnd; Message, WParam, LParam: Longint): Longint;stdcall;
+
+Var
+ I : TWinMsgServerComm;
+ Msg : TMsg;
+
+begin
+ Result:=0;
+ If (Message=WM_COPYDATA) then
+ begin
+ I:=TWinMsgServerComm(GetWindowLongPtr(HWindow,GWL_USERDATA));
+ If (I<>NIl) then
+ begin
+ Msg.Message:=Message;
+ Msg.WParam:=WParam;
+ Msg.LParam:=LParam;
+ I.ReadMsgData(Msg);
+ I.FDataPushed:=True;
+ If Assigned(I.Owner.OnMessage) then
+ I.Owner.ReadMessage;
+ Result:=1;
+ end
+ end
+ else
+ Result:=DefWindowProc(HWindow,Message,WParam,LParam);
+end;
+
+
+function TWinMsgServerComm.AllocateHWnd(const aWindowName: String): HWND;
+
+var
+ cls: TWndClass;
+ isreg : Boolean;
+
+begin
+ Pointer(MsgWindowClass.lpfnWndProc):=@MsgWndProc;
+ MsgWindowClass.hInstance := HInstance;
+ MsgWindowClass.lpszClassName:=MsgWndClassName;
+ isreg:=GetClassInfo(HInstance,MsgWndClassName,cls);
+ if not isreg then
+ if (Windows.RegisterClass(MsgWindowClass)=0) then
+ Owner.DoError(SErrFailedToRegisterWindowClass,[]);
+ Result:=CreateWindowEx(WS_EX_TOOLWINDOW, MsgWndClassName,
+ PChar(aWindowName), WS_POPUP {!0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
+ if (Result=0) then
+ Owner.DoError(SErrFailedToCreateWindow,[aWindowName]);
+ SetWindowLongPtr(Result,GWL_USERDATA,PtrInt(Self));
+end;
+
+constructor TWinMsgServerComm.Create(AOWner: TSimpleIPCServer);
+begin
+ inherited Create(AOWner);
+ FWindowName:=Owner.ServerID;
+ If not Owner.Global then
+ FWindowName:=FWindowName+'_'+InstanceID;
+end;
+
+procedure TWinMsgServerComm.StartServer;
+
+begin
+ FHWND:=AllocateHWND(FWindowName);
+end;
+
+procedure TWinMsgServerComm.StopServer;
+begin
+ DestroyWindow(FHWND);
+ FHWND:=0;
+end;
+
+function TWinMsgServerComm.PeekMessage(TimeOut: Integer): Boolean;
+
+Var
+ Msg : Tmsg;
+ B : Boolean;
+ R : DWORD;
+
+begin
+ Result:=FDataPushed;
+ If Result then
+ Exit;
+ B:=Windows.PeekMessage(Msg, FHWND, 0, 0, PM_NOREMOVE);
+ If not B then
+ // No message yet. Wait for a message to arrive available within specified time.
+ begin
+ if (TimeOut=0) then
+ TimeOut:=Integer(INFINITE);
+ R:=MsgWaitForMultipleObjects(1,FHWND,False,TimeOut,QS_SENDMESSAGE);
+ B:=(R<>WAIT_TIMEOUT);
+ end;
+ If B then
+ Repeat
+ B:=Windows.PeekMessage(Msg, FHWND, 0, 0, PM_NOREMOVE);
+ if B then
+ begin
+ Result:=(Msg.Message=WM_COPYDATA);
+ // Remove non WM_COPY messages from Queue
+ if not Result then
+ GetMessage(Msg,FHWND,0,0);
+ end;
+ Until Result or (not B);
+end;
+
+procedure TWinMsgServerComm.ReadMsgData(var Msg: TMsg);
+
+Var
+ CDS : PCopyDataStruct;
+
+begin
+ CDS:=PCopyDataStruct(Msg.Lparam);
+ Owner.FMsgType:=CDS^.dwData;
+ Owner.FMsgData.Seek(0,soFrombeginning);
+ Owner.FMsgData.WriteBuffer(CDS^.lpData^,CDS^.cbData);
+end;
+
+procedure TWinMsgServerComm.ReadMessage;
+
+Var
+ Msg : TMsg;
+
+begin
+ If FDataPushed then
+ FDataPushed:=False
+ else
+ If Windows.PeekMessage(Msg, FHWND, 0, 0, PM_REMOVE) then
+ if (Msg.Message=WM_COPYDATA) then
+ ReadMsgData(Msg);
+end;
+
+function TWinMsgServerComm.GetInstanceID: String;
+begin
+ Result:=IntToStr(HInstance);
+end;
+
+{ ---------------------------------------------------------------------
+ TWinMsgClientComm
+ ---------------------------------------------------------------------}
+
+Type
+ TWinMsgClientComm = Class(TIPCClientComm)
+ Private
+ FWindowName: String;
+ FHWND : HWnd;
+ Public
+ Constructor Create(AOWner : TSimpleIPCClient); override;
+ Procedure Connect; override;
+ Procedure Disconnect; override;
+ Procedure SendMessage(MsgType : TMessageType; Stream : TStream); override;
+ Function ServerRunning : Boolean; override;
+ Property WindowName : String Read FWindowName;
+ end;
+
+
+constructor TWinMsgClientComm.Create(AOWner: TSimpleIPCClient);
+begin
+ inherited Create(AOWner);
+ FWindowName:=Owner.ServerID;
+ If (Owner.ServerInstance<>'') then
+ FWindowName:=FWindowName+'_'+Owner.ServerInstance;
+end;
+
+procedure TWinMsgClientComm.Connect;
+begin
+ FHWND:=FindWindow(MsgWndClassName,PChar(FWindowName));
+ If (FHWND=0) then
+ Owner.DoError(SErrServerNotActive,[Owner.ServerID]);
+end;
+
+procedure TWinMsgClientComm.Disconnect;
+begin
+ FHWND:=0;
+end;
+
+procedure TWinMsgClientComm.SendMessage(MsgType: TMessageType; Stream: TStream
+ );
+Var
+ CDS : TCopyDataStruct;
+ Data,FMemstr : TMemorySTream;
+
+begin
+ If Stream is TMemoryStream then
+ begin
+ Data:=TMemoryStream(Stream);
+ FMemStr:=Nil
+ end
+ else
+ begin
+ FMemStr:=TMemoryStream.Create;
+ Data:=FMemstr;
+ end;
+ Try
+ If Assigned(FMemStr) then
+ begin
+ FMemStr.CopyFrom(Stream,0);
+ FMemStr.Seek(0,soFromBeginning);
+ end;
+ CDS.dwData:=MsgType;
+ CDS.lpData:=Data.Memory;
+ CDS.cbData:=Data.Size;
+ Windows.SendMessage(FHWnd,WM_COPYDATA,0,Integer(@CDS));
+ Finally
+ FreeAndNil(FMemStr);
+ end;
+end;
+
+function TWinMsgClientComm.ServerRunning: Boolean;
+begin
+ Result:=FindWindow(MsgWndClassName,PChar(FWindowName))<>0;
+end;
+
+{ ---------------------------------------------------------------------
+ Set TSimpleIPCClient / TSimpleIPCServer defaults.
+ ---------------------------------------------------------------------}
+
+
+Function TSimpleIPCServer.CommClass : TIPCServerCommClass;
+
+begin
+ if (DefaultIPCServerClass<>Nil) then
+ Result:=DefaultIPCServerClass
+ else
+ Result:=TWinMsgServerComm;
+end;
+
+Function TSimpleIPCClient.CommClass : TIPCClientCommClass;
+
+begin
+ if (DefaultIPCClientClass<>Nil) then
+ Result:=DefaultIPCClientClass
+ else
+ Result:=TWinMsgClientComm;
+end;
+
diff --git a/packages/fcl-process/src/wince/pipes.inc b/packages/fcl-process/src/wince/pipes.inc
new file mode 100644
index 0000000000..af26fb8b63
--- /dev/null
+++ b/packages/fcl-process/src/wince/pipes.inc
@@ -0,0 +1,30 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1998 by Michael Van Canneyt
+
+ Win32 part of pipe stream.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+// Unsupported for the moment...
+
+Function CreatePipeHandles (Var Inhandle,OutHandle : THandle) : Boolean;
+begin
+ Result := False;
+end;
+
+
+Function TInputPipeStream.GetNumBytesAvailable: DWord;
+
+begin
+ // Windows CE doesn´t have the API function PeekNamedPipe
+ Result := 0;
+end;
+
diff --git a/packages/fcl-process/src/wince/process.inc b/packages/fcl-process/src/wince/process.inc
new file mode 100644
index 0000000000..a3f358dcc2
--- /dev/null
+++ b/packages/fcl-process/src/wince/process.inc
@@ -0,0 +1,257 @@
+{
+ Wince Process .inc.
+}
+
+uses Windows;
+
+Const
+ PriorityConstants : Array [TProcessPriority] of Cardinal =
+ (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
+ NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
+
+procedure TProcess.CloseProcessHandles;
+begin
+ if (FProcessHandle<>0) then
+ CloseHandle(FProcessHandle);
+ if (FThreadHandle<>0) then
+ CloseHandle(FThreadHandle);
+end;
+
+Function TProcess.PeekExitStatus : Boolean;
+
+begin
+ GetExitCodeProcess(ProcessHandle,FExitCode);
+ Result:=(FExitCode<>Still_Active);
+end;
+
+Function GetStartupFlags (P : TProcess): Cardinal;
+
+begin
+ With P do
+ begin
+ Result:=0;
+ if poUsePipes in FProcessOptions then
+ Result:=Result or Startf_UseStdHandles;
+ if suoUseShowWindow in FStartupOptions then
+ Result:=Result or startf_USESHOWWINDOW;
+ if suoUSESIZE in FStartupOptions then
+ Result:=Result or startf_usesize;
+ if suoUsePosition in FStartupOptions then
+ Result:=Result or startf_USEPOSITION;
+ if suoUSECOUNTCHARS in FStartupoptions then
+ Result:=Result or startf_usecountchars;
+ if suoUsefIllAttribute in FStartupOptions then
+ Result:=Result or startf_USEFILLATTRIBUTE;
+ end;
+end;
+
+Function GetCreationFlags(P : TProcess) : Cardinal;
+
+begin
+ With P do
+ begin
+ Result:=0;
+ if poNoConsole in FProcessOptions then
+ Result:=Result or Detached_Process;
+ if poNewConsole in FProcessOptions then
+ Result:=Result or Create_new_console;
+ if poNewProcessGroup in FProcessOptions then
+ Result:=Result or CREATE_NEW_PROCESS_GROUP;
+ If poRunSuspended in FProcessOptions Then
+ Result:=Result or Create_Suspended;
+ if poDebugProcess in FProcessOptions Then
+ Result:=Result or DEBUG_PROCESS;
+ if poDebugOnlyThisProcess in FProcessOptions Then
+ Result:=Result or DEBUG_ONLY_THIS_PROCESS;
+ if poDefaultErrorMode in FProcessOptions Then
+ Result:=Result or CREATE_DEFAULT_ERROR_MODE;
+ result:=result or PriorityConstants[FProcessPriority];
+ end;
+end;
+
+Function StringsToPWidechars(List : TStrings): pointer;
+
+var
+ EnvBlock: Widestring;
+ I: Integer;
+
+begin
+ EnvBlock := '';
+ For I:=0 to List.Count-1 do
+ EnvBlock := EnvBlock + List[i] + #0;
+ EnvBlock := EnvBlock + #0;
+ GetMem(Result, Length(EnvBlock));
+ CopyMemory(Result, @EnvBlock[1], Length(EnvBlock));
+end;
+
+Procedure InitProcessAttributes(P : TProcess; Var PA : TSecurityAttributes);
+
+begin
+ FillChar(PA,SizeOf(PA),0);
+ PA.nLength := SizeOf(PA);
+end;
+
+Procedure InitThreadAttributes(P : TProcess; Var TA : TSecurityAttributes);
+
+begin
+ FillChar(TA,SizeOf(TA),0);
+ TA.nLength := SizeOf(TA);
+end;
+
+Procedure InitStartupInfo(P : TProcess; Var SI : STARTUPINFO);
+
+Const
+ SWC : Array [TShowWindowOptions] of Cardinal =
+ (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
+ SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
+ SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
+
+begin
+ FillChar(SI,SizeOf(SI),0);
+ With SI do
+ begin
+ dwFlags:=GetStartupFlags(P);
+ if P.FShowWindow<>swoNone then
+ dwFlags:=dwFlags or Startf_UseShowWindow
+ else
+ dwFlags:=dwFlags and not Startf_UseShowWindow;
+ wShowWindow:=SWC[P.FShowWindow];
+ if (poUsePipes in P.Options) then
+ begin
+ dwFlags:=dwFlags or Startf_UseStdHandles;
+ end;
+ if P.FillAttribute<>0 then
+ begin
+ dwFlags:=dwFlags or Startf_UseFillAttribute;
+ dwFillAttribute:=P.FillAttribute;
+ end;
+ dwXCountChars:=P.WindowColumns;
+ dwYCountChars:=P.WindowRows;
+ dwYsize:=P.WindowHeight;
+ dwXsize:=P.WindowWidth;
+ dwy:=P.WindowTop;
+ dwX:=P.WindowLeft;
+ end;
+end;
+
+Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean);
+
+begin
+ CreatePipeHandles(SI.hStdInput,HI);
+ CreatePipeHandles(HO,Si.hStdOutput);
+ if CE then
+ CreatePipeHandles(HE,SI.hStdError)
+ else
+ begin
+ SI.hStdError:=SI.hStdOutput;
+ HE:=HO;
+ end;
+end;
+
+
+Procedure TProcess.Execute;
+
+
+Var
+ PName,PDir,PCommandLine : PWidechar;
+ FEnv: pointer;
+ FCreationFlags : Cardinal;
+ FProcessAttributes : TSecurityAttributes;
+ FThreadAttributes : TSecurityAttributes;
+ FProcessInformation : TProcessInformation;
+ FStartupInfo : STARTUPINFO;
+ HI,HO,HE : THandle;
+
+begin
+ FInheritHandles:=True;
+ PName:=Nil;
+ PCommandLine:=Nil;
+ PDir:=Nil;
+ If FApplicationName<>'' then
+ PName:=PWidechar(FApplicationName);
+ If FCommandLine<>'' then
+ PCommandLine:=PWidechar(FCommandLine);
+ If FCurrentDirectory<>'' then
+ PDir:=PWidechar(FCurrentDirectory);
+ if FEnvironment.Count<>0 then
+ FEnv:=StringsToPWideChars(FEnvironment)
+ else
+ FEnv:=Nil;
+ Try
+ FCreationFlags:=GetCreationFlags(Self);
+ InitProcessAttributes(Self,FProcessAttributes);
+ InitThreadAttributes(Self,FThreadAttributes);
+ InitStartupInfo(Self,FStartUpInfo);
+ If poUsePipes in FProcessOptions then
+ CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions));
+ Try
+ If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
+ FInheritHandles,FCreationFlags,FEnv,PDir,@FStartupInfo,
+ fProcessInformation) then
+ Raise EProcess.CreateFmt('Failed to execute %s : %d',[FCommandLine,GetLastError]);
+ FProcessHandle:=FProcessInformation.hProcess;
+ FThreadHandle:=FProcessInformation.hThread;
+ FProcessID:=FProcessINformation.dwProcessID;
+ Finally
+ if POUsePipes in FProcessOptions then
+ begin
+ FileClose(FStartupInfo.hStdInput);
+ FileClose(FStartupInfo.hStdOutput);
+ if Not (poStdErrToOutPut in FProcessOptions) then
+ FileClose(FStartupInfo.hStdError);
+ CreateStreams(HI,HO,HE);
+ end;
+ end;
+ FRunning:=True;
+ Finally
+ If FEnv<>Nil then
+ FreeMem(FEnv);
+ end;
+ if not (csDesigning in ComponentState) and // This would hang the IDE !
+ (poWaitOnExit in FProcessOptions) and
+ not (poRunSuspended in FProcessOptions) then
+ WaitOnExit;
+end;
+
+Function TProcess.WaitOnExit : Boolean;
+
+Var
+ R : DWord;
+
+begin
+ R:=WaitForSingleObject (FProcessHandle,Infinite);
+ Result:=(R<>Wait_Failed);
+ If Result then
+ GetExitStatus;
+ FRunning:=False;
+end;
+
+Function TProcess.Suspend : Longint;
+
+begin
+ Result:=SuspendThread(ThreadHandle);
+end;
+
+Function TProcess.Resume : LongInt;
+
+begin
+ Result:=ResumeThread(ThreadHandle);
+end;
+
+Function TProcess.Terminate(AExitCode : Integer) : Boolean;
+
+begin
+ Result:=False;
+ If ExitStatus=Still_active then
+ Result:=TerminateProcess(Handle,AexitCode);
+end;
+
+Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
+
+
+begin
+ FShowWindow:=Value;
+end;
+
+
+
diff --git a/packages/fcl-process/src/wince/simpleipc.inc b/packages/fcl-process/src/wince/simpleipc.inc
new file mode 100644
index 0000000000..a323f876ac
--- /dev/null
+++ b/packages/fcl-process/src/wince/simpleipc.inc
@@ -0,0 +1,291 @@
+{
+ This file is part of the Free Component library.
+ Copyright (c) 2005 by Michael Van Canneyt, member of
+ the Free Pascal development team
+
+ Windows implementation of one-way IPC between 2 processes
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ 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.
+
+ **********************************************************************}
+
+uses Windows,messages;
+
+Const
+ MsgWndClassName : pwidechar = 'FPCMsgWindowCls';
+
+Resourcestring
+ SErrFailedToRegisterWindowClass = 'Failed to register message window class';
+ SErrFailedToCreateWindow = 'Failed to create message window %s';
+
+var
+ MsgWindowClass: TWndClass = (
+ style: 0;
+ lpfnWndProc: Nil;
+ cbClsExtra: 0;
+ cbWndExtra: 0;
+ hInstance: 0;
+ hIcon: 0;
+ hCursor: 0;
+ hbrBackground: 0;
+ lpszMenuName: nil;
+ lpszClassName: Nil);
+
+{ ---------------------------------------------------------------------
+ TWinMsgServerComm
+ ---------------------------------------------------------------------}
+
+Type
+ TWinMsgServerComm = Class(TIPCServerComm)
+ Private
+ FHWND : HWND;
+ FWindowName : Widestring;
+ FDataPushed : Boolean;
+ Function AllocateHWnd(const cwsWindowName : widestring) : HWND;
+ Public
+ Constructor Create(AOwner : TSimpleIPCServer); override;
+ procedure ReadMsgData(var Msg: TMsg);
+ Procedure StartServer; override;
+ Procedure StopServer; override;
+ Function PeekMessage(TimeOut : Integer) : Boolean; override;
+ Procedure ReadMessage ; override;
+ Function GetInstanceID : String;override;
+ Property WindowName : WideString Read FWindowName;
+ end;
+
+
+function MsgWndProc(HWindow: HWnd; Message, WParam, LParam: Longint): Longint;stdcall;
+
+Var
+ I : TWinMsgServerComm;
+ Msg : TMsg;
+
+begin
+ Result:=0;
+ If (Message=WM_COPYDATA) then
+ begin
+ I:=TWinMsgServerComm(GetWindowLong(HWindow,GWL_USERDATA));
+ If (I<>NIl) then
+ begin
+ Msg.Message:=Message;
+ Msg.WParam:=WParam;
+ Msg.LParam:=LParam;
+ I.ReadMsgData(Msg);
+ I.FDataPushed:=True;
+ If Assigned(I.Owner.OnMessage) then
+ I.Owner.ReadMessage;
+ Result:=1;
+ end
+ end
+ else
+ Result:=DefWindowProc(HWindow,Message,WParam,LParam);
+end;
+
+
+function TWinMsgServerComm.AllocateHWnd(const cwsWindowName: Widestring): HWND;
+
+var
+ cls: LPWNDCLASS;
+ isreg : Boolean;
+
+begin
+ Pointer(MsgWindowClass.lpfnWndProc):=@MsgWndProc;
+ MsgWindowClass.hInstance := HInstance;
+ MsgWindowClass.lpszClassName:=MsgWndClassName;
+ isreg:=GetClassInfo(HInstance,MsgWndClassName,cls);
+ if not isreg then
+ if (Windows.RegisterClass(MsgWindowClass)=0) then
+ Owner.DoError(SErrFailedToRegisterWindowClass,[]);
+ Result:=CreateWindowEx(WS_EX_TOOLWINDOW, MsgWndClassName,
+ PWidechar(cwsWindowName), WS_POPUP {!0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
+ if (Result=0) then
+ Owner.DoError(SErrFailedToCreateWindow,[cwsWindowName]);
+ SetWindowLong(Result,GWL_USERDATA,Longint(Self));
+end;
+
+constructor TWinMsgServerComm.Create(AOWner: TSimpleIPCServer);
+begin
+ inherited Create(AOWner);
+ FWindowName:=Owner.ServerID;
+ If not Owner.Global then
+ FWindowName:=FWindowName+'_'+InstanceID;
+end;
+
+procedure TWinMsgServerComm.StartServer;
+
+begin
+ FHWND:=AllocateHWND(FWindowName);
+end;
+
+procedure TWinMsgServerComm.StopServer;
+begin
+ DestroyWindow(FHWND);
+ FHWND:=0;
+end;
+
+function TWinMsgServerComm.PeekMessage(TimeOut: Integer): Boolean;
+
+Var
+ Msg : Tmsg;
+ B : Boolean;
+ R : DWORD;
+
+begin
+ Result:=FDataPushed;
+ If Result then
+ Exit;
+ B:=Windows.PeekMessage(Msg, FHWND, 0, 0, PM_NOREMOVE);
+ If not B then
+ // No message yet. Wait for a message to arrive available within specified time.
+ begin
+ if (TimeOut=0) then
+ TimeOut:=Integer(INFINITE);
+ R:=MsgWaitForMultipleObjects(1,FHWND,False,TimeOut,QS_SENDMESSAGE);
+ B:=(R<>WAIT_TIMEOUT);
+ end;
+ If B then
+ Repeat
+ B:=Windows.PeekMessage(Msg, FHWND, 0, 0, PM_NOREMOVE);
+ if B then
+ begin
+ Result:=(Msg.Message=WM_COPYDATA);
+ // Remove non WM_COPY messages from Queue
+ if not Result then
+ GetMessage(@Msg,FHWND,0,0);
+ end;
+ Until Result or (not B);
+end;
+
+procedure TWinMsgServerComm.ReadMsgData(var Msg: TMsg);
+
+Var
+ CDS : PCopyDataStruct;
+
+begin
+ CDS:=PCopyDataStruct(Msg.Lparam);
+ Owner.FMsgData.Seek(0,soFrombeginning);
+ Owner.FMsgData.WriteBuffer(CDS^.lpData^,CDS^.cbData);
+end;
+
+procedure TWinMsgServerComm.ReadMessage;
+
+Var
+ Msg : TMsg;
+
+begin
+ If FDataPushed then
+ FDataPushed:=False
+ else
+ If Windows.PeekMessage(Msg, FHWND, 0, 0, PM_REMOVE) then
+ if (Msg.Message=WM_COPYDATA) then
+ ReadMsgData(Msg);
+end;
+
+function TWinMsgServerComm.GetInstanceID: String;
+begin
+ Result:=IntToStr(HInstance);
+end;
+
+{ ---------------------------------------------------------------------
+ TWinMsgClientComm
+ ---------------------------------------------------------------------}
+
+Type
+ TWinMsgClientComm = Class(TIPCClientComm)
+ Private
+ FWindowName: String;
+ FHWND : HWnd;
+ Public
+ Constructor Create(AOWner : TSimpleIPCClient); override;
+ Procedure Connect; override;
+ Procedure Disconnect; override;
+ Procedure SendMessage(MsgType : TMessageType; Stream : TStream); override;
+ Function ServerRunning : Boolean; override;
+ Property WindowName : String Read FWindowName;
+ end;
+
+
+constructor TWinMsgClientComm.Create(AOWner: TSimpleIPCClient);
+begin
+ inherited Create(AOWner);
+ FWindowName:=Owner.ServerID;
+ If (Owner.ServerInstance<>'') then
+ FWindowName:=FWindowName+'_'+Owner.ServerInstance;
+end;
+
+procedure TWinMsgClientComm.Connect;
+begin
+ FHWND:=FindWindow(MsgWndClassName,Pwidechar(FWindowName));
+ If (FHWND=0) then
+ Owner.DoError(SErrServerNotActive,[Owner.ServerID]);
+end;
+
+procedure TWinMsgClientComm.Disconnect;
+begin
+ FHWND:=0;
+end;
+
+procedure TWinMsgClientComm.SendMessage(MsgType: TMessageType; Stream: TStream
+ );
+Var
+ CDS : TCopyDataStruct;
+ Data,FMemstr : TMemorySTream;
+
+begin
+ If Stream is TMemoryStream then
+ begin
+ Data:=TMemoryStream(Stream);
+ FMemStr:=Nil
+ end
+ else
+ begin
+ FMemStr:=TMemoryStream.Create;
+ Data:=FMemstr;
+ end;
+ Try
+ If Assigned(FMemStr) then
+ begin
+ FMemStr.CopyFrom(Stream,0);
+ FMemStr.Seek(0,soFromBeginning);
+ end;
+ CDS.lpData:=Data.Memory;
+ CDS.cbData:=Data.Size;
+ Windows.SendMessage(FHWnd,WM_COPYDATA,0,Integer(@CDS));
+ Finally
+ FreeAndNil(FMemStr);
+ end;
+end;
+
+function TWinMsgClientComm.ServerRunning: Boolean;
+begin
+ Result:=FindWindow(MsgWndClassName,PWidechar(FWindowName))<>0;
+end;
+
+{ ---------------------------------------------------------------------
+ Set TSimpleIPCClient / TSimpleIPCServer defaults.
+ ---------------------------------------------------------------------}
+
+
+Function TSimpleIPCServer.CommClass : TIPCServerCommClass;
+
+begin
+ if (DefaultIPCServerClass<>Nil) then
+ Result:=DefaultIPCServerClass
+ else
+ Result:=TWinMsgServerComm;
+end;
+
+Function TSimpleIPCClient.CommClass : TIPCClientCommClass;
+
+begin
+ if (DefaultIPCClientClass<>Nil) then
+ Result:=DefaultIPCClientClass
+ else
+ Result:=TWinMsgClientComm;
+end;
+