Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Named Pipes zwischen Service und eingeschränktem Programm (https://www.delphipraxis.net/119717-named-pipes-zwischen-service-und-eingeschraenktem-programm.html)

CodeX 30. Aug 2008 12:06


Named Pipes zwischen Service und eingeschränktem Programm
 
Ich habe ein für mich beunruhigendes Problem.

Nachdem ich jetzt eine funktionierende Named-Pipes-Kommunikation zwischen einem Service (der hier u.a. als Pipes-Server dient) und einem normalen Programm (das sich als Client verbinden kann) implementiert habe, kommt mir der böse Verdacht auf, dass das nur funktioniert, wenn das Programm nicht unter einem eingeschränkten Benutzeraccount läuft.

Da das ganze so weit richtig funktioniert hat, poste ich mal nur die entscheidende Stelle im Code:

Delphi-Quellcode:
function TPipeClient.ProcessMsg(aMsg: RPIPEMessage): RPIPEMessage;
begin
  CalcMsgSize(aMsg);
  Result.Size := SizeOf(Result);
  if WaitNamedPipe(PChar(FPipeName), 10) then
    if not CallNamedPipe(
      PChar(FPipeName), @aMsg, aMsg.Size, @Result, Result.Size, Result.Size, 3000
    ) then
      MessageDlg('PIPE antwortet nicht.', mtError, [mbOK], 0)
    else
  else
    MessageDlg('PIPE ist nicht vorhanden.', mtError, [mbOK], 0);
end;
CallNamedPipe schlägt fehl, wenn das Programm mit eingeschränkten Rechten läuft und es kommt die Meldung 'PIPE antwortet nicht.'. (Wenn der Service/Server nicht aktiv ist, dann kommt die korrekte Meldung, dass die Pipe nicht vorhanden sei. Auch mit eingeschränkten Rechten wird also nocht erkannt, ob die Pipe vorhanden ist oder nicht.)

Kann man da irgendwas machen? Irgendwie fühle ich mich hier von Windows auf den Schlips getreten...
Es muss doch möglich sein, dass selbst ein eingeschränktes Programm noch über Pipes kommunizieren kann!?

Fridolin Walther 30. Aug 2008 13:05

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Welcher Error Code wird zurückgegeben (GetLastError)?

CodeX 30. Aug 2008 13:25

Re: Named Pipes zwischen Service und eingeschränktem Program
 
5, Access is denied

Apollonius 30. Aug 2008 13:29

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Dann hast du beim Erstellen der Pipe einen zu strengen Security Descriptor angegeben. Windows ermöglicht dir, zu entscheiden, wer mit der Pipe kommunizieren darf und wer nicht.

Fridolin Walther 30. Aug 2008 13:40

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Zeig mal bitte deinen Code der die Pipe erstellt.

CodeX 30. Aug 2008 13:45

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Hm, sind die Flags bei CreateNamedPipe jetzt zu streng?

Delphi-Quellcode:
procedure TPipeServer.StartUpServer;
begin
  try
    // Pipe bereits vorhanden?
    if WaitNamedPipe(PChar(FPipeName), 100 {ms}) then
      raise Exception.Create('PIPE bereits vorhanden.');

    // Pipe erstellen
    FHandle := CreateNamedPipe(
      PChar(FPipeName), PIPE_ACCESS_DUPLEX,
      PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_WAIT,
      PIPE_UNLIMITED_INSTANCES, SizeOf(RPIPEMessage), SizeOf(RPIPEMessage),
      NMPWAIT_USE_DEFAULT_WAIT, nil
    );

    // Pipe erstellt?
    if FHandle = INVALID_HANDLE_VALUE then
      raise Exception.Create('PIPE konnte nicht erstellt werden.');
  except
  end;
end;

Apollonius 30. Aug 2008 13:51

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Als letzten Parameter solltest du einen Zeiger auf eine gültige SECURITY_ATTRIBUTES-Struktur angeben, in der du den Security Descriptor festlegen kannst.

Fridolin Walther 30. Aug 2008 13:58

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Das sollte in diesem Falle nicht wirklich notwendig sein. Eine NULL DACL bedeutet "Zugriff für jeden".

Apollonius 30. Aug 2008 14:02

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Ja, aber du musst unterscheiden zwischen DACL nil und Security Descriptor nil. Security Descriptor nil bedeutet Standard-Descriptor, und dieser ist bei Benutzer System glücklicherweise sehr restriktiv.

CodeX 30. Aug 2008 14:05

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Kannst Du mir bitte ein Beispiel geben, wie ich das richtig machen muss?

Fridolin Walther 30. Aug 2008 14:13

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Delphi-Quellcode:
program pipeserver;

{$APPTYPE CONSOLE}

uses
  jwawinbase, jwawintype, jwawinnt, jwaaccctrl, jwaaclapi, jwawinerror, sysutils;

function InstanceThread(PipeHandle : dword) : dword; stdcall;
var
  Value : dword;
  tmp  : dword;
begin
  result := 0;

  ReadFile(PipeHandle, @Value, 4, @tmp, nil);
  WriteFile(PipeHandle, @Value, 4, @tmp, nil);

  FlushFileBuffers(PipeHandle);
  DisconnectNamedPipe(PipeHandle);
  CloseHandle(PipeHandle);
end;

function ServerThread(unused : dword) : dword; stdcall;
const
  BUFSIZE = 4;
var
  PipeHandle : dword;
  Connected : boolean;
  SA        : LPSECURITY_ATTRIBUTES;
  ACL       : PACL;
  Group     : TRUSTEE;
  EA        : PEXPLICIT_ACCESS;
  SD        : PSECURITY_DESCRIPTOR;
  ACL_SIZE  : ACL_SIZE_INFORMATION;
  tmp       : dword;
begin
  Group.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE;
  Group.pMultipleTrustee := nil;
  Group.ptstrName := 'Jeder';
  Group.TrusteeForm := TRUSTEE_IS_NAME;
  Group.TrusteeType := TRUSTEE_IS_GROUP;

  new(EA);
  EA^.grfAccessMode := GRANT_ACCESS;
  EA^.grfAccessPermissions := GENERIC_READ or GENERIC_WRITE;
  EA^.grfInheritance := NO_INHERITANCE;
  EA^.Trustee := group;

  SetEntriesInAcl(1, EA, nil, ACL);
  GetAclInformation(ACL, @ACL_SIZE, sizeof(ACL_SIZE), AclSizeInformation);
  getmem(SD, SECURITY_DESCRIPTOR_MIN_LENGTH + ACL_SIZE.AclBytesFree + ACL_SIZE.AclBytesInUse);
  InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(sd, TRUE, ACL, FALSE);

  new(SA);
  sa^.bInheritHandle := FALSE;
  sa^.lpSecurityDescriptor := sd;
  sa^.nLength := sizeof(sa);

  while true do
    begin
      PipeHandle := CreateNamedPipeW('\\.\pipe\demopipe', PIPE_ACCESS_DUPLEX,
                                     PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or
                                     PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE,
                                     BUFSIZE, INFINITE, SA);

      if PipeHandle = INVALID_HANDLE_VALUE then
        begin
          sleep(100);
          continue;
        end;

      Connected := ConnectNamedPipe(PipeHandle, nil)
                   or (GetLastError = ERROR_PIPE_CONNECTED);

      if Connected then
        begin
          tmp := CreateThread(nil, 0, @InstanceThread,
                                       Pointer(PipeHandle), 0, nil);
          if tmp = 0 then
            begin
              DisconnectNamedPipe(PipeHandle);
              CloseHandle(PipeHandle);
              continue;
            end else
              CloseHandle(tmp);
        end else
          CloseHandle(PipeHandle);
  end;

  LocalFree(cardinal(ACL));
  freemem(SD);
  dispose(EA);
end;

var
  tmp : dword;
begin
  write('Starting ServerThread: ');
  tmp := CreateThread(nil, 0, @ServerThread, nil, 0, nil);
  writeln(tmp <> 0);
  CloseHandle(tmp);
  readln;
end.
Ist ein kleiner Pipe Server, der eine Pipe mit einer DACL die Jedem im System explizit Lese und Schreibrechte erlaubt erstellt.

CodeX 30. Aug 2008 14:21

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Danke!
Sieht recht kompliziert aus. Ich habe parallel hier im Forum noch nach dem Stichwort gesucht und diesen Thread hier gefunden.
Tun es die paar Zeilen, um FSA zu bestimmen, auch? Oder gibt es irgendwelche Bedenken?

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
   FSA : SECURITY_ATTRIBUTES;
   FSD : SECURITY_DESCRIPTOR;
   pch1: shortstring;
begin
   InitializeSecurityDescriptor(@FSD, SECURITY_DESCRIPTOR_REVISION);
   SetSecurityDescriptorDacl(@FSD, True, nil, False);
   FSA.lpSecurityDescriptor := @FSD;
   FSA.nLength := sizeof(SECURITY_ATTRIBUTES);
   FSA.bInheritHandle := True;

   Pipe:= CreateNamedPipe(PChar('\\.\pipe\<test>'),
                          PIPE_ACCESS_DUPLEX or FILE_FLAG_WRITE_THROUGH,
                          PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or PIPE_NOWAIT,
                          PIPE_UNLIMITED_INSTANCES,
                          1024,
                          1024,
                          50,
                          @FSA);
end;

Fridolin Walther 30. Aug 2008 14:27

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Funktioniert genauso. Allerdings solltest Du Dir bewusst sein, das alles und jeder dann auf die Pipe zugreifen kann - auch übers Netzwerk und ohne Authentifizierung!

CodeX 30. Aug 2008 15:05

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Hm, also mein Service prüft den Sender der Nachricht auf seine Signatur und agiert nur dann, wenn es sich um meine Signatur handelt.
Dennoch wäre es wahrscheinlich nicht verkehrt, die beiden Punkte Netzwerk und Authentifizierung in den Code einzubeziehen.

Ich habe Deinen Code nun genauer angeschaut. Ich verstehe zwar nicht alles davon, aber die Zeile Group.ptstrName := 'Jeder'; macht mich stutzig. Die starre Angabe, würde dann doch nur auf deutschen Betriebssystemen funktionieren, oder? Ich nehme an, dass es nicht einfach einen Flag-Wert gibt, der nur lokal angemeldete Benutzer zulässt? :gruebel:

Apollonius 30. Aug 2008 15:09

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Mit der TRUSTEE-Struktur kann man Gruppen oder Benutzer nicht nur per Name, sondern auch per SID angeben. *klick* Die SID der eingebauten Gruppen ist unabhängig von der Sprache.

Fridolin Walther 30. Aug 2008 15:19

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Nunja, das war Code aus einem kleinen Beispiel von mir, wie man eine Pipe erstellt auf die nur Mitglieder einer bestimmten Gruppe Zugriff haben. Für Deine Zwecke wäre es wahrscheinlich besser den Zugriff an einen Well Known SID zu koppeln. Der Code würde dann so aussehen:

Delphi-Quellcode:
program pipeserver;

{$APPTYPE CONSOLE}

uses
  jwawinbase, jwawintype, jwawinnt, jwaaccctrl, jwaaclapi, jwawinerror, sysutils;

function InstanceThread(PipeHandle : dword) : dword; stdcall;
var
  Value : dword;
  tmp  : dword;
begin
  result := 0;

  ReadFile(PipeHandle, @Value, 4, @tmp, nil);
  WriteFile(PipeHandle, @Value, 4, @tmp, nil);

  FlushFileBuffers(PipeHandle);
  DisconnectNamedPipe(PipeHandle);
  CloseHandle(PipeHandle);
end;

function ServerThread(unused : dword) : dword; stdcall;
const
  BUFSIZE = 4;
var
  PipeHandle  : dword;
  Connected   : boolean;
  SA          : LPSECURITY_ATTRIBUTES;
  ACL         : PACL;
  Group       : TRUSTEE;
  EA          : PEXPLICIT_ACCESS;
  SD          : PSECURITY_DESCRIPTOR;
  ACL_SIZE    : ACL_SIZE_INFORMATION;
  WellKnownSID : PSID;
  tmp         : dword;
begin
  tmp := SECURITY_MAX_SID_SIZE;
  GetMem(WellKnownSID, tmp);
  CreateWellKnownSid(WinWorldSid, nil, WellKnownSID, tmp);

  Group.MultipleTrusteeOperation := NO_MULTIPLE_TRUSTEE;
  Group.pMultipleTrustee := nil;
  Group.ptstrName := Pointer(WellKnownSID);
  Group.TrusteeForm := TRUSTEE_IS_SID;
  Group.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP;

  new(EA);
  EA^.grfAccessMode := GRANT_ACCESS;
  EA^.grfAccessPermissions := GENERIC_READ or GENERIC_WRITE;
  EA^.grfInheritance := NO_INHERITANCE;
  EA^.Trustee := group;

  SetEntriesInAcl(1, EA, nil, ACL);
  GetAclInformation(ACL, @ACL_SIZE, sizeof(ACL_SIZE), AclSizeInformation);
  getmem(SD, SECURITY_DESCRIPTOR_MIN_LENGTH + ACL_SIZE.AclBytesFree + ACL_SIZE.AclBytesInUse);
  InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(sd, TRUE, ACL, FALSE);

  new(SA);
  sa^.bInheritHandle := FALSE;
  sa^.lpSecurityDescriptor := sd;
  sa^.nLength := sizeof(sa);

  while true do
    begin
      PipeHandle := CreateNamedPipeW('\\.\pipe\demopipe', PIPE_ACCESS_DUPLEX,
                                     PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or
                                     PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE,
                                     BUFSIZE, INFINITE, SA);

      if PipeHandle = INVALID_HANDLE_VALUE then
        begin
          sleep(100);
          continue;
        end;

      Connected := ConnectNamedPipe(PipeHandle, nil)
                   or (GetLastError = ERROR_PIPE_CONNECTED);

      if Connected then
        begin
          tmp := CreateThread(nil, 0, @InstanceThread,
                                       Pointer(PipeHandle), 0, nil);
          if tmp = 0 then
            begin
              DisconnectNamedPipe(PipeHandle);
              CloseHandle(PipeHandle);
              continue;
            end else
              CloseHandle(tmp);
        end else
          CloseHandle(PipeHandle);
  end;

  LocalFree(cardinal(ACL));
  freemem(SD);
  freemem(WellKnownSID);
  dispose(EA);
end;

var
  tmp : dword;
begin
  write('Starting ServerThread: ');
  tmp := CreateThread(nil, 0, @ServerThread, nil, 0, nil);
  writeln(tmp <> 0);
  CloseHandle(tmp);
  readln;
end.
Eine Liste der Well Known SIDs gibts hier: http://msdn.microsoft.com/en-us/library/aa379650(VS.85).aspx
In Deinem Falle wäre wohl WinLocalSid nützlich.

Man kann den Code übrigens noch stark vereinfachen indem man die JWSCL benutzt. Allerdings ist mir die JWSCL für meinen Geschmack zu viel Overhead.

Apollonius 30. Aug 2008 15:23

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Wäre es hier nicht klüger, den Speicher für WellKnownSID auf dem Stack zu reservieren?

Fridolin Walther 30. Aug 2008 15:25

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Welchen Vorteil erhoffst Du Dir dadurch?

CodeX 30. Aug 2008 15:26

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Zitat:

Zitat von 0xF30FC7
Man kann den Code übrigens noch stark vereinfachen indem man die JWSCL benutzt.

Ich bin ganz Ohr! :-D
Da ich die JWSCL so oder so bereits eingebunden habe, würd ich auch gern den vereinfachten Code nehmen.

Zitat:

Zitat von 0xF30FC7
Allerdings ist mir die JWSCL für meinen Geschmack zu viel Overhead.

Ja, stimmt leider. Hat mich auch Überwindung gekostet, mich letztlich darauf festzulegen. Aber gut, die Arbeitsersparnis wars dann doch Wert.

Apollonius 30. Aug 2008 15:40

Re: Named Pipes zwischen Service und eingeschränktem Program
 
@0xF30FC7: Ich finde einfach, dass man den Memory Manager nicht bemühen sollte, wenn der Stack es genauso tut, denn er ist in jedem Fall langsamer und hat einen nicht zu vernachlässigenden Speicher-Overhead.
Das gleiche gilt für EA. Bei SD würde ich allerdings auch den MM nehmen, da du die Größe nicht im Voraus weißt.

Dezipaitor 30. Aug 2008 15:57

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Sowas ?
http://jedi-apilib.svn.sourceforge.n...23&view=markup
Delphi-Quellcode:
program Server;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Dialogs,
  jwaWindows,
  jwsclDescriptor,
  jwsclACL,
  JwsclSID,
  jwsclKnownSid,
  jwsclMapping,
  jwsclToken,
  jwsclStrings;

type TMessage = record
       Data : array[0..1023] of Char;
     end;

var PipeHandle : THandle;
    pSecAttr : TSecurityAttributes;
    SD : TJwSecurityDescriptor;
    i : Integer;
    lpData : TMessage;
    iWritten,
    iRead : DWORD;

    PipeToken : TJwSecurityToken;
    c : Char;
begin
  Writeln('Server Pipe');
  JwInitWellKnownSIDs; //for the JwXxxxSID variables

  SD := TJwSecurityDescriptor.Create;
  SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_ALL,JwAdministratorsSID, false));
  SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_ALL,JwLocalSystemSID, false));

  Writeln('Do you want to allow the actual logged on user to connect to the pipe? (y/n)');
  Writeln('If you say yes, your user will succed to connect to the pipe. However if you are using Vista, the user will get'+
   'the string ''denied'' from the server because he is deny only for admins. Is the process started elevated or on XP it should work fine.');
  Writeln('If you say no, the user will only allowed to be connected to the pipe, if he is an administrator or system ');
  Write('[Y/N]:');

  Read(c);
  if UpCase(c) = 'Y' then
    SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil,[],GENERIC_ALL,JwLocalGroupSID, false));


  //ShowMessage(SD.GetTextMap(TJwSecurityPipeMapping));

  //remove Everyone group if available
  i := SD.DACL.FindSID(JwWorldSID);
  if i > -1 then
  begin
    {If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor
    and the handle cannot be inherited. The ACLs in the default security descriptor for
    a named pipe grant full control to the LocalSystem account, administrators, and the creator owner.
    They also grant read access to members of the Everyone group and the anonymous account.
    }
    SD.DACL.Delete(i); //remove Everyone group
  end;


  pSecAttr := SD.Create_SAEx(true);

  try
    PipeHandle := CreateNamedPipe(
      '\\.\pipe\JwsclPipeTest',//__in     LPCTSTR lpName,
      PIPE_ACCESS_DUPLEX or FILE_FLAG_FIRST_PIPE_INSTANCE,//__in     DWORD dwOpenMode,
      PIPE_TYPE_MESSAGE or      // message type pipe
        PIPE_WAIT,//__in     DWORD dwPipeMode,
      1,//__in     DWORD nMaxInstances,
      4096,//__in     DWORD nOutBufferSize,
      4096,//__in     DWORD nInBufferSize,
      0,//__in     DWORD nDefaultTimeOut,
      LPSECURITY_ATTRIBUTES(@pSecAttr)//__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes
    );
    if PipeHandle = INVALID_HANDLE_VALUE then
      RaiseLastOSError;
  finally
    SD.Free_SAEx(pSecAttr);
    FreeAndNil(SD);
  end;

  try
    if not ConnectNamedPipe(PipeHandle,nil) then
      RaiseLastOSError;

    if not ReadFile(PipeHandle,@lpData,sizeof(lpData),@iRead, nil) then
      RaiseLastOSError;

    writeln('Data from other side: ',lpData.Data);

    try
      //throws exception if fails
      TJwSecurityToken.ImpersonateNamedPipeClient(PipeHandle);
      //we are in context of user now
     
      try
        if JwCheckAdministratorAccess then
        begin
          lpData.Data := 'Success'#0#0;
          Writeln('Client is approved.');
        end
        else
        begin
          lpData.Data := 'Denied.'#0#0;
          Writeln('Client is denied.');
        end;

        WriteFile(PipeHandle, @lpData,sizeof(lpData), @iWritten, nil);
       
      finally
        TJwSecurityToken.RevertToSelf;
      end;
    finally
    end;
  finally
    Sleep(2000); //or wait for more connections as shown above
    CloseHandle(PipeHandle);
  end;
  writeln('Hit enter...');
  readln;
end.

Fridolin Walther 30. Aug 2008 16:19

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Zitat:

Zitat von Apollonius
@0xF30FC7: Ich finde einfach, dass man den Memory Manager nicht bemühen sollte, wenn der Stack es genauso tut, denn er ist in jedem Fall langsamer und hat einen nicht zu vernachlässigenden Speicher-Overhead.
Das gleiche gilt für EA. Bei SD würde ich allerdings auch den MM nehmen, da du die Größe nicht im Voraus weißt.

Nunja, würde das ganze tausendfach in einer Schleife ablaufen, würd ich Dir recht geben. Aber der Performanceunterschied ist wahrscheinlich nicht mal ohne weiteres Messbar und geht in der Messungenauigkeit unter.

@CodeX:
Dezipaitor hat ja bereits den Beispiel Quelltext aus der JWSCL gepostet. Mein Beispiel würde so aussehen:

Delphi-Quellcode:
program pipeserver;

{$APPTYPE CONSOLE}

uses
  SysUtils, jwaWindows, jwsclDescriptor, jwsclACL, JwsclSID, jwsclKnownSid;

function InstanceThread(PipeHandle : dword) : dword; stdcall;
var
  Value : dword;
  tmp  : dword;
begin
  result := 0;

  ReadFile(PipeHandle, @Value, 4, @tmp, nil);
  WriteFile(PipeHandle, @Value, 4, @tmp, nil);

  FlushFileBuffers(PipeHandle);
  DisconnectNamedPipe(PipeHandle);
  CloseHandle(PipeHandle);
end;

function ServerThread(unused : dword) : dword; stdcall;
const
  BUFSIZE = 4;
var
  PipeHandle : dword;
  Connected : boolean;
  tmp       : dword;
  SD        : TJwSecurityDescriptor;
  SA        : TSecurityAttributes;
begin
  JwInitWellKnownSIDs;

  SD := TJwSecurityDescriptor.Create;
  SD.DACL.Add(TJwDiscretionaryAccessControlEntryAllow.Create(nil, [], GENERIC_ALL, JwLocalGroupSID, false));
  SA := SD.Create_SAEx(true, false);

  while true do
    begin
      PipeHandle := CreateNamedPipeW('\\.\pipe\demopipe', PIPE_ACCESS_DUPLEX,
                                     PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE or
                                     PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE,
                                     BUFSIZE, INFINITE, @SA);

      if PipeHandle = INVALID_HANDLE_VALUE then
        begin
          sleep(100);
          continue;
        end;

      Connected := ConnectNamedPipe(PipeHandle, nil)
                   or (GetLastError = ERROR_PIPE_CONNECTED);

      if Connected then
        begin
          tmp := CreateThread(nil, 0, @InstanceThread,
                                       Pointer(PipeHandle), 0, nil);
          if tmp = 0 then
            begin
              DisconnectNamedPipe(PipeHandle);
              CloseHandle(PipeHandle);
              continue;
            end else
              CloseHandle(tmp);
        end else
          CloseHandle(PipeHandle);
  end;

  SD.Free_SAEx(SA);
  SD.Free;
end;

var
  tmp : dword;
begin
  write('Starting ServerThread: ');
  tmp := CreateThread(nil, 0, @ServerThread, nil, 0, nil);
  writeln(tmp <> 0);
  CloseHandle(tmp);
  readln;
end.
Das PipeServer Executable ist übrigens dadurch von 58kb auf 610kb angewachsen ;).

Dezipaitor 30. Aug 2008 16:27

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Ich arbeite dran die Units bisschen kleiner zu machen. Besonders da JwaWindows und SysUtils drin sind, ist das alles etwas groß.
Dummerweise gibt es nur wenig Zeit und wenig Hilfe für die Aufgaben :wall:

Dezipaitor 30. Aug 2008 17:24

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Ich habe auch grad erlebt,dass es garnicht möglich ist SysUtils zu ersetzen.
Zudem, wenn man die einzelnen Units JwaXXX der JwaWindows vorzieht, dann muss man damit leben, dass je nach Reihenfolge dieser Units in der Uses Klausel, man verschiedene Typen verwendet. Diese Typen können nämlich doppelt in verschiedenen JwaUnits definiert worden sein. Dann muss man explizit casten.

CodeX 30. Aug 2008 18:34

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Ich denke, mein Problem ist so weit gelöst. Danke schön Euch allen!! :cheers:

quendolineDD 6. Nov 2008 09:54

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Ich verfolge ja das ganze Thema und bin selber am Schreiben eines Dienstes, der eine NamedPipe zur Verfügung stellt und für eine definierte Benutzergruppe diese zur Verfügung stellen soll.
Jedoch möchte ich keine JEDI-Komponenten verwenden .... Probleme bekomme ich bei dem Code u.a. bei

[Fehler] uService.pas(89): Undefinierter Bezeichner: 'LPSECURITY_ATTRIBUTES'
[Fehler] uService.pas(90): Undefinierter Bezeichner: 'PSECURITY_ATTRIBUTES'
[Fehler] uService.pas(93): Undefinierter Bezeichner: 'ACL_SIZE_INFORMATION'
[Fehler] uService.pas(98): Undefinierter Bezeichner: 'MultipleTrusteeOperations'
[Fehler] uService.pas(100): Undefinierter Bezeichner: 'pstrName'
[...]
[Fehler] uService.pas(111): Inkompatible Typen: '_ACL' und 'PACL'

Derzeitiges uses

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, accctrl, aclapi;

Dezipaitor 6. Nov 2008 10:09

Re: Named Pipes zwischen Service und eingeschränktem Program
 
Die musst du alle selbst übersetzen aus C nach Delphi.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz