-
//necessary units
-
uses JwaWindows, …, JwsclToken, JwsclUtils, JwsclComUtils, JwsclLogging, SvcMgr;
-
…
-
{checks ReadFile and WriteFile result but ignores overlapped error result}
-
function CheckPipe(const Value : Boolean) : Boolean;
-
begin
-
result := (Value )
-
or (not Value and (GetLastError() = ERROR_IO_PENDING));
-
end;
-
-
var
-
ServiceStopEvent : THandle; //define a stop event for the service
-
Stopped : Boolean = false;
-
-
procedure …ServiceExecute
-
var
-
Log : IJwLogClient;
-
-
ProtocolVersion,
-
WaitResult : DWORD;
-
Msg : TMsg;
-
OvLapped : OVERLAPPED;
-
PipeToken : TJwSecurityToken;
-
begin
-
//JWSCL logging
-
Log := uLogging.LogServer.Connect(etMethod,ClassName,
-
‘ServiceExecute’,‘MainUnit.pas’,”);
-
-
hPipe := CreateNamedPipe(‘\\.\pipe\PipeName’,
-
PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED,
-
PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, nil);
-
-
//check hPipe here…TODO for the reader
-
-
ZeroMemory(@OvLapped, sizeof(OvLapped));
-
OvLapped.hEvent := CreateEvent(nil, false, false, nil);
-
//auto CloseHandle
-
TJwAutoPointer.Wrap(OvLapped.hEvent);
-
-
Stopped := false;
-
//for services we use this msg friendly approach
-
repeat //1.
-
ConnectNamedPipe(Pipe, @OvLapped);
-
-
repeat //2.
-
ServiceThread.ProcessRequests(False);
-
WaitResult := JwMsgWaitForMultipleObjects([ServiceStopEvent, OvLapped.hEvent], false, INFINITE, QS_ALLINPUT);
-
-
case WaitResult of
-
WAIT_OBJECT_0 + 1 : ResetEvent(OvLapped.hEvent);
-
WAIT_OBJECT_0 + 2 : PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE); //tag message as read, so waitfor does not return next time
-
else
-
//another problem
-
end;
-
until WaitResult <> WAIT_OBJECT_0 + 2; //2.
-
-
if WaitResult = WAIT_OBJECT_0 +1 then //connected
-
begin
-
//read dummy data or e.g. Protocol version of client
-
if not CheckPipe(ReadFile(Pipe, @ProtocolVersion, sizeof(ProtocolVersion) ,nil, @OvLapped)) then
-
//uhh error
-
else
-
begin
-
//JWSCL JwsclUtils.pas implements this more convenient wait function
-
if JwWaitForMultipleObjects([ServiceStopEvent, OvLapped.hEvent], false,
-
TIMEOUT) = WAIT_OBJECT_0 +1 then
-
begin
-
try
-
//now we can get the client’s token - may throw exception if it fails!
-
TJwSecurityToken.ImpersonateNamedPipeClient(Pipe);
-
-
try
-
PipeToken := TJwSecurityToken.CreateTokenByThread(0, MAXIMUM_ALLOWED, true);
-
finally
-
TJwSecurityToken.RevertToSelf;
-
end;
-
//……. go on with what you want
-
on E : Exception do
-
begin
-
Log.Exception(E);
-
end;
-
end
-
else
-
Log.Log(‘Read for protocol version failed.’);
-
end;
-
end;
-
-
DisconnectNamedPipe(Pipe);
-
until Stopped; //1. - the one who signales ServiceStopEvent, must also set this boolean value to true
-
-
CloseHandle(Pipe);
-
end;
Leave a reply