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 NetLocalGroupAdd funktioniert nicht (https://www.delphipraxis.net/100552-netlocalgroupadd-funktioniert-nicht.html)

RWarnecke 30. Sep 2007 10:45


NetLocalGroupAdd funktioniert nicht
 
Hallo zusammen,

ich möchte mir ein paar Befehle aus dem MSDN Library in einer Unit zusammenschreiben. Nur irgendwie komme ich nicht ganz damit zurecht das in Delphi zuschreiben.
Hier meine Übersetzung :
Delphi-Quellcode:
type
  LOCALGROUP_INFO_0 = record                   // Gruppenname
    lgrpi0_name : LPWSTR;
  end;
  PLOCALGROUP_INFO_0 = ^LOCALGROUP_INFO_0;

  LOCALGROUP_INFO_1 = record                   // Gruppenname + Kommentar
    lgrpi1_name   : LPWSTR;
    lgrpi1_comment : LPWSTR;
  end;
  PLOCALGROUP_INFO_1 = ^LOCALGROUP_INFO_1;

function NetLocalGroupAdd(servername : PWideChar; level : Integer; buf: PChar;
         parm_err : Integer) : DWORD; stdcall; external 'netapi32.dll';

function AddGroups(wServer, wGroupName, wComment : WideString):DWORD;
var
  info : PLOCALGROUP_INFO_1;
  parmerr : Integer;
begin
  parmerr := 0;
  info.lgrpi1_comment := PWideChar(wComment);
  info.lgrpi1_name := PWideChar(wGroupName);
  result := NetLocalGroupAdd (PWideChar (wServer), 1, PChar(@info), parmerr);
end;
Wenn ich jetzt die Funktion "AddGroups" so aufrufe :
Delphi-Quellcode:
AddGroups('.', 'Testgruppe', 'Erstellen einer Gruppe Testen');
Bekomme ich eine EAccessViolation in Zeile 22. Warum passiert das ? Ich sehe mal wieder den Wald vor lauter Bäumen nicht.

Dezipaitor 30. Sep 2007 20:03

Re: NetLocalGroupAdd funktioniert nicht
 
Die Befehle gibts doch schon alle in Windows.pas ?

Zitat:

Zitat von RWarnecke
Hallo zusammen,

ich möchte mir ein paar Befehle aus dem MSDN Library in einer Unit zusammenschreiben. Nur irgendwie komme ich nicht ganz damit zurecht das in Delphi zuschreiben.
Hier meine Übersetzung :

Das hat schon jemand getan. Dabei kam das hier raus: http://jedi-apilib.sourceforge.net/

Wenn du Unicodeparameter verwendest, dann musst du NetLocalGroupAddW verwenden.

Apollonius 30. Sep 2007 20:12

Re: NetLocalGroupAdd funktioniert nicht
 
Ich denke, dass für info vielleicht vor dem Zugriff Speicher alloziert werden sollte. :wink:

RWarnecke 30. Sep 2007 20:54

Re: NetLocalGroupAdd funktioniert nicht
 
Zitat:

Zitat von Dezipaitor
Die Befehle gibts doch schon alle in Windows.pas ?

Zitat:

Zitat von RWarnecke
Hallo zusammen,

ich möchte mir ein paar Befehle aus dem MSDN Library in einer Unit zusammenschreiben. Nur irgendwie komme ich nicht ganz damit zurecht das in Delphi zuschreiben.
Hier meine Übersetzung :

Das hat schon jemand getan. Dabei kam das hier raus: http://jedi-apilib.sourceforge.net/

Wenn du Unicodeparameter verwendest, dann musst du NetLocalGroupAddW verwenden.

Das ist ja auch richtig so, nur ich mache irgendwo noch einen Fehler in der Anwendung. Um es vielleicht besser zu verstehen, wollte ich das ganze selber machen. Denn das hier erworbene Wissen kann ich ja auch auf andere API's anwenden.

Zitat:

Zitat von Apollonius
Ich denke, dass für info vielleicht vor dem Zugriff Speicher alloziert werden sollte. :wink:

Ich habe das ganze jetzt mal so umgeschrieben :
Delphi-Quellcode:
function AddGroups(wServer, wGroupName, wComment : String;):DWORD;
var
  info          : ^PLOCALGROUP_INFO_1;
  wTempComment  : WideString;
  wTempGroupName : WideString;
  wTempServer   : WideString;
  parmerr: DWORD;
begin
  wTempComment := wComment;
  wTempGroupName := wGroupName;
  wTempServer := wServer;
  parmerr := 0;
  GetMem(info,sizeOf(info));
  info^.lgrpi1_comment := PWideChar(wTempComment);
  info^.lgrpi1_name := PWideChar(wTempGroupName);
  result := NetLocalGroupAdd (PWideChar(wTempServer), 1, @info, parmerr);
end;
Nur leider bekomme ich immer noch die EAccessViolation in der Zeile 14. Das heißt also wenn ich Speicher alloziere mit GetMem hilft mir auch nicht weiter.

Dezipaitor 30. Sep 2007 21:42

Re: NetLocalGroupAdd funktioniert nicht
 
Zitat:

Zitat von RWarnecke
Das ist ja auch richtig so, nur ich mache irgendwo noch einen Fehler in der Anwendung. Um es vielleicht besser zu verstehen, wollte ich das ganze selber machen. Denn das hier erworbene Wissen kann ich ja auch auf andere API's anwenden.

Dadurch hast du doppelte Anzahl von Fehlerquellen.
1. Deine Deklaration ist falsch
2. Deine Verwendung ist falsch.
Verwendest du vordefinierte Header, dann hast du nur noch den Fall 2.

Setze mal const in die Parameterliste für die Parameter deiner Funktion.

Außerdem hast du für die Info Variable einen Pointer auf einen Pointer. Mit GetMem allokierst du Speicher für den Pointer. Und dann übergibst du den Pointer nocht mit dem Addressoperator. Entweder du deklarierst die Info-variable auf dem Stack (ohne Pointer!!! also LOCALGROUP_INFO_1) und übergibst sie mit dem Addressoperator (@) --- oder du erstellst die Variable auf dem Heap mit GetMem (PLOCALGROUP_INFO_1) und verwendest dafür kein Addressoperator bei der Funktion. Aber nicht mischen.
Du verwendest eine Ansicode Deklaration der Funktion. Definierst sie aber als Unicode. Dann solltest du sie auch als Unicode laden! Setze ein W ans Ende der Funktion!!!!!
Delphi-Quellcode:
function NetLocalGroupAdd(servername: LPCWSTR; level: DWORD; buf: LPBYTE; parm_err: LPDWORD): NET_API_STATUS; external netapi32 name 'NetLocalGroupAddW';

Deine Deklaration ist falsch.
Delphi-Quellcode:
function NetLocalGroupAdd(servername : PWideChar; level : Integer; buf: PChar;
         parm_err : Integer) : DWORD; stdcall; external 'netapi32.dll';
Laut MSDN für NetLocalGroupAdd ist die Deklaration die folgende:
Code:
NET_API_STATUS NetLocalGroupAdd(
  __in         LPCWSTR servername,
  __in         DWORD level,
  __in         LPBYTE buf,
  __out        LPDWORD parm_err
);
Der Parameter parm_err kann durch den out Typ auch so deklariert werden: "out parm_err : DWORD". Wenn es in/out ist, dann verwenden wir in Delphi "var".


Pass auf welche Datentype du verwendest. Deine Deklaration verwendet für den zweiten und vierten Parameter ein Integer. Jedoch wird ein DWORD (Cardinal) erwartet. Das sind ganz andere Datentypen.


Mein Rat ist, dass du erstmal die vordefinierten WindowsAPI Funktionen verwenden solltest. Wenn das klappt, kannst du immernoch Headerkonvertierung machen. Aber wie du gesehen hast, kann man viel falsch machen. Im schlimmsten Fall funktioniert es in 80% aller Fälle.

Luckie 30. Sep 2007 21:43

Re: NetLocalGroupAdd funktioniert nicht
 
Deklarier die Übergabeparameter auch mal als WideString.

RWarnecke 1. Okt 2007 13:33

Re: NetLocalGroupAdd funktioniert nicht
 
Also, ich habe mir jetzt den Rat von Dezipaitor zu Herzen genommen und es mit der Unit JclWin32 probiert. Ich habe ein Beispielprojekt gemacht. Hier der Code dazu :
Delphi-Quellcode:
procedure TForm10.Button1Click(Sender: TObject);
var
  info   : Pointer;
  parmerr : LPDWORD;
  wComment: WideString;
  wGroupName: WideString;
  nerr: Cardinal;
begin
  wComment := Edit2.Text;
  wGroupName := Edit1.Text;
  parmerr := nil;
  GetMem(info,sizeOf(PLOCALGROUP_INFO_1));
  PLOCALGROUP_INFO_1(info)^.lgrpi1_comment := PWideChar(wComment);
  PLOCALGROUP_INFO_1(info)^.lgrpi1_name := PWideChar(wGroupName);
  nerr := NetLocalGroupAdd(PWideChar('.'), 1, @info, parmerr);
  if nerr = 0 then
    ShowMessage('Gruppe erfolgreich erstellt')
  else
    ShowMessage('Fehlermeldung : ' + IntToStr(nerr));
end;
Nur leider erhalte ich folgende Fehlermeldung in Zeile 15:
---------------------------
Project12
---------------------------
Zugriffsverletzung bei Adresse 7C9112F1 in Modul 'ntdll.dll'. Lesen von Adresse 0000002E.
---------------------------
OK
---------------------------

Was habe ich denn jetzt nun wieder falsch gemacht ? Bin ich wieder mit der Adressierung drucheinander gekommen ?

Dezipaitor 1. Okt 2007 13:58

Re: NetLocalGroupAdd funktioniert nicht
 
hehe, jedesmal wenn du Änderungen machst, hast du etwas geändert, was niemand gewollt hat.
Ich sehe, dass du keine Ahnung von Pointern hast und eigentlich nur ausprobierst. Such dir mal (oder frage im Forum) Tutorials
über Pointerarithmetik.

Delphi-Quellcode:
var
  info   : Pointer;
Hier verwendest du plötzlich einen untypisierten Pointer. KA warum.

Delphi-Quellcode:
  parmerr : LPDWORD;
  wComment: WideString;
  wGroupName: WideString;
  nerr: Cardinal;
begin
  wComment := Edit2.Text;
  wGroupName := Edit1.Text;
  parmerr := nil;
  GetMem(info,sizeOf(PLOCALGROUP_INFO_1));
Das GetMem ist falsch. Mit "sizeOf(PLOCALGROUP_INFO_1)" bekommst du die Größe des Zeigers und nicht die der Struktur. Auf 32Bit Systemen kommt immer 4 raus.
Es sollte also LOCALGROUP_INFO_1 sein, für das 8 rauskommt.
Zudem erstellst du Speicher für Info, jedoch nicht "parmerr" was ja auch ein Pointer ist (LP... -> Long Pointer).

Delphi-Quellcode:
  PLOCALGROUP_INFO_1(info)^.lgrpi1_comment := PWideChar(wComment);
  PLOCALGROUP_INFO_1(info)^.lgrpi1_name := PWideChar(wGroupName);
  nerr := NetLocalGroupAdd(PWideChar('.'), 1, @info, parmerr);
Hier übergibst du per @-Operator einen Zeiger an die Funktion. Das bedeutet du übergibst die Speicheraddresse des Zeigers an die Funktion.Sozusagen ein Zeiger auf einen Zeiger.
Resultat: Buffer Overflow (Zugriffsverletzung im besten Fall).
Ich hab dir schon geschrieben (was du nicht gelesen oder nicht verstanden hast), dass man einfach LOCALGROUP_INFO_1 als Variablentyp nimmt und kein GetMem verwendet,
dafür die Variable mit @ der API-Funktion übergibt.
Oder, dass man PLOCALGROUP_INFO_1 mit GetMem verwendet und dafür @ nicht verwendet.
Dasselbe gilt für "parmerr".
Hättest du keinen untypisierten Zeiger für "info" verwendet, dann müsstest du kein Type-Cast machen.


Ich lege dir dringend nahe, dass du dich mit Zeigern beschäftigen solltest, bevor du weitermachst.

RWarnecke 1. Okt 2007 15:52

Re: NetLocalGroupAdd funktioniert nicht
 
Zitat:

Zitat von Dezipaitor
Ich lege dir dringend nahe, dass du dich mit Zeigern beschäftigen solltest, bevor du weitermachst.

Ok, ich sehe ein das da noch viel nachholbedarf besteht. Ich werde mal die Suche quälen und mir Tutorials raussuchen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr.

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