Board index » delphi » Threads and Named pipes under NT 4.0

Threads and Named pipes under NT 4.0

Hi

I'm making a service for windows NT where the shell for the service needs
to communicate via named pipes. I have there for made a thread in the
service that handles all namedpipe activity, but since it's in blocking
mode I can't just terminate the thread because it want's data on the pipe
before continuing. To solve this I have created a small piece of code
i the main thread that sends a termination string to the named pipe
thread, but it never sends the termination string :-(

Any ideas to solve this?

Regards
 Anders Gregersen

-------------------==== Posted via Deja News ====-----------------------
      http://www.dejanews.com/     Search, Read, Post to Usenet

 

Re:Threads and Named pipes under NT 4.0


The last parm in the ReadFile function is for using the overlapping
feature.  I could never get it to work.

Instead I used TerminateThread( Thread.Handle,  dwExitCode ).  It seems to
be ok, and I have had no problems with it.

Edwin

a...@twinsoft.dk wrote in article <869750300.15...@dejanews.com>...

Quote
> Hi

> I'm making a service for windows NT where the shell for the service needs
> to communicate via named pipes. I have there for made a thread in the
> service that handles all namedpipe activity, but since it's in blocking
> mode I can't just terminate the thread because it want's data on the pipe
> before continuing. To solve this I have created a small piece of code
> i the main thread that sends a termination string to the named pipe
> thread, but it never sends the termination string :-(

> Any ideas to solve this?

> Regards
>  Anders Gregersen

> -------------------==== Posted via Deja News ====-----------------------
>       http://www.dejanews.com/     Search, Read, Post to Usenet

Re:Threads and Named pipes under NT 4.0


On 24 Jul 1997 17:06:26 GMT, "Edwin Walker" <ewal...@mcs.net> wrote:

Quote

>The last parm in the ReadFile function is for using the overlapping
>feature.  I could never get it to work.

I've just started looking a using Named Pipes, I recall seeing
something in the API help (Delphi 2) entry for ReadFile that states
the overlapped mode is no longer supported & therefore require
a Nil pointer to be passed instead.

kjb.
kbl...@cix.compulink.co.uk

Re:Threads and Named pipes under NT 4.0


Quote
>Hi
>I'm making a service for windows NT where the shell for the service needs
>to communicate via named pipes. I have there for made a thread in the
>service that handles all namedpipe activity, but since it's in blocking
>mode I can't just terminate the thread because it want's data on the pipe
>before continuing. To solve this I have created a small piece of code
>i the main thread that sends a termination string to the named pipe
>thread, but it never sends the termination string :-(

>Any ideas to solve this?

>Regards
> Anders Gregersen

>-------------------==== Posted via Deja News ====-----------------------
>      http://www.dejanews.com/     Search, Read, Post to Usenet

Hello!

You can either create you named pipe in overlapped mode (in this case you'll
never be able to connect to it from Windows 95 client, getting
OPERATION_NOT_SUPPORTED errror) or make a 'fake'connection inside your server
to awake the pipe. Look at the example below.
Create a simple project with two buttons on main form ('Connect' and
'Disconnect'). Use breakpoints in the listening loop and 'View\Threads'
IDE menu command. Comment {$DEFINE OVERLAPPED_MODE} to test blocking mode.

Theodore V. Kapustin
Project manager
INEC (Information & Economics)

Moscow, Russia

{****************************** Cut here *************************}

unit PipeServ;

interface

procedure ListenToConnections;
function Listening : Boolean;
procedure StopListening;

implementation

uses Windows, Classes, Dialogs;

type

    { TClientThread }

    TClientThread = class(TThread)
    private
           FPipe : THandle;
    protected
             procedure Execute; override;
             procedure DoTerminate; override;
    public
          constructor Create(hPipe : THandle);
    end;

    { TListenThread }

    TListenThread = class(TThread)
    protected
             procedure Execute; override;
    end;

const
     pipeName : PChar = '\\.\pipe\mynamedpipe';
     BUFSIZE = 1024;
var
   pipeList : TList;
   listenThread : TListenThread;

{$DEFINE OVERLAPPED_MODE}

procedure ListenToConnections;
begin
     if Listening then
     begin
          ShowMessage('Already connected');
          Exit;
     end;
     listenThread := TListenThread.Create(False);
     listenThread.FreeOnTerminate := True;
end;

function Listening : Boolean;
begin
     result := listenThread <> nil;
end;

procedure StopListening;
var
   hFakePipe : THandle;
begin
     if not Listening then Exit;
     listenThread.Terminate;
{$IFNDEF OVERLAPED_MODE}
     hFakePipe := CreateFile(pipeName, GENERIC_READ or GENERIC_WRITE,
           FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
     CloseHandle(hFakePipe);
{$ENDIF}
     listenThread := nil;
end;

{ TListenThread }

procedure TListenThread.Execute;
var
   ovl : TOverlapped;
   sa : TSecurityAttributes;
   sd : TSecurityDescriptor;
   hPipe : THandle;
   fConnected : Boolean;
const
     SECURITY_DESCRIPTOR_REVISION : DWORD = 1;
begin
     InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
     sa.nLength := SizeOf(TSecurityAttributes);
     sa.lpSecurityDescriptor := @sd;
     sa.bInheritHandle := False;
     SetSecurityDescriptorDacl(@sd, True, nil, False);
     ovl.hEvent := CreateEvent(nil, True, False, 'PipeConnected');

     while not Terminated do
     begin
          hPipe := CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX or
{$IFDEF OVERLAPED_MODE}
                   FILE_FLAG_OVERLAPPED or
{$ENDIF}
                   FILE_FLAG_WRITE_THROUGH,
                   PIPE_TYPE_BYTE or PIPE_WAIT,
                   PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, PIPE_WAIT, @sa);

          if hPipe = INVALID_HANDLE_VALUE then
          begin
               ShowMessage('CreatePipe failed');
               StopListening;
               break;
          end;

          fConnected := ConnectNamedPipe(hPipe, @ovl) or
                     (GetLastError = ERROR_PIPE_CONNECTED);

{$IFDEF OVERLAPED_MODE}
          while not (fConnected or Terminated) do fConnected :=
                WaitForSingleObject(ovl.hEvent, 1000) <> WAIT_TIMEOUT;
{$ENDIF}

          if not Terminated then
          begin
               ResetEvent(ovl.hEvent);
               if fConnected then pipeList.Add(TClientThread.Create(hPipe))
               else CloseHandle(hPipe);
          end;
     end;
     CloseHandle(ovl.hEvent);
end;

{ TClientThread }

constructor TClientThread.Create(hPipe : THandle);
begin
     inherited Create(False);
     FPipe := hPipe;
     FreeOnTerminate := True;
end;

procedure TClientThread.Execute;
begin
        // Serve a client here
end;

procedure TClientThread.DoTerminate;
begin
     FlushFileBuffers(FPipe);
     DisconnectNamedPipe(FPipe);
     CloseHandle(FPipe);
     pipeList.Remove(self);
     inherited DoTerminate;
end;

initialization
    pipeList := TList.Create;
finalization
    pipeList.Free;
end.

Other Threads