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 Benutzer einer Gruppe zu ordnen (https://www.delphipraxis.net/2527-benutzer-einer-gruppe-zu-ordnen.html)

Luckie 28. Jan 2003 02:41


Benutzer einer Gruppe zu ordnen
 
So es geht in die letzte Runde des User-Managers. Wenn das Problem gelöst ist. Kann ich ihn veröffentlichen bzw. als Alpha-Release zum Testen freigeben und dann das große Geld damit machen. :mrgreen:

Es geht jetzt darum einem Benutzer einer Gruppe zu zuordnen. Folgender Code läßt sich prima kompilieren (beide Versionen):
Delphi-Quellcode:
{ 1. Version }
      {dwEntries := 0;
      if IsDlgButtonChecked(hApp, IDC_CHKISADMIN) = BST_CHECKED then
      begin
        Inc(dwEntries);
        setlength(sGroupArray, dwEntries);
        sGroupArray[dwEntries-1] := 'Administratoren';
      end;
      if IsDlgButtonChecked(hApp, IDC_CHKISPOWERUSER) = BST_CHECKED then
      begin
        Inc(dwEntries);
        setlength(sGroupArray, dwEntries);
        sGroupArray[dwEntries-1] := 'Hauptbenutzer';
      end

      GetMem(gui0, dwEntries*sizeof(Pointer));
      for i := 0 to dwEntries-1 do
      begin
        Inc(Integer(gui0), sizeof(Pointer));
        PGroupInfo0(gui0)^.grpi0_name := PWideChar(WideString(sGroupArray[i]));
      end;

      dwError := NetUserSetGroups(nil, PWideChar(WideString(sUser)), 0, gui0, dwEntries); }
      //NetAPIBufferFree(gui0); // <- mag er nicht
      //FreeMem(gui0, dwEntries*sizeof(Pointer)); // <- mag er auch nicht :o(

      { 2. Version }
      if IsDlgButtonChecked(hApp, IDC_CHKISPOWERUSER) = BST_CHECKED then
        dwError := NetGroupAddUser(nil, PWideChar(WideString('Hauptbenutzer')), PWideChar(WideString(sUser)))
      else
        dwError := NetGroupDelUser(nil, PWideChar(WideString('Hauptbenutzer')), PWideChar(WideString(sUser)));

      case dwError of
        ERROR_ACCESS_DENIED    : s := 'Zugriff verweigert.';
        ERROR_INVALID_PARAMETER : s := 'Ungültiger Parameter.';
        NERR_InvalidComputer   : s := 'Ungültiger Computer';
        NERR_NotPrimary        : s := 'Operation darf nur auf dem Domain-Controller ausgeführt werden.';
        NERR_SpeGroupOp        : s := 'Operation darf nicht auf diese Gruppe angewandt werden.';
        NERR_LastAdmin         : s := 'Der letzte macht das Licht aus, aber nicht bei Windows. :o)'
                                    +#13#10+'Der letzte Administrator Account kann nicht gelöscht werden';
        NERR_BadPassword,
        NERR_PasswordTooShort  : s := 'Ungültiges Passwort';
        NERR_UserNotFound      : s := 'Ungültiger Benutzer.';
        NERR_GroupNotFound     : s := 'Gruppe nicht gefunden.';
        NERR_Success           : s := 'Konto erfolgreich geändert.';
      end;
Das Problem ist nur, ich bekomme jedes mal "Gruppe nicht gefunden". Obwohl das auslesen so geht:
Delphi-Quellcode:
if sUser <> '' then
  begin
    if NetUserGetLocalGroups(nil, PWideChar(WideString(sUser)), 0, 0, gui0, MAX_PREFERRED_LENGTH,
      dwEntriesRead, dwEntriesTotal) = NERR_SUCCESS then
    tmp := gui0;
    begin
      for i := 0 to dwEntriesRead-1 do
      begin
        s := String(PGroupInfo0(gui0)^.grpi0_name);
        if s = 'Administratoren' then
          CheckDlgButton(hApp, IDC_CHKISADMIN, Integer(TRUE));
        if s = 'Hauptbenutzer' then
          CheckDlgButton(hApp, IDC_CHKISPOWERUSER, Integer(TRUE));
        if s = 'Benutzer' then
          CheckDlgButton(hApp, IDC_CHKISUSER, Integer(TRUE));
        if s = 'Sicherungs-Operatoren' then
          CheckDlgButton(hApp, IDC_CHKISBACKUPOP, Integer(TRUE));
        if s = 'Replikations-Operator' then
          CheckDlgButton(hApp, IDC_CHKISREPOP, Integer(TRUE));
        if s = 'Gäste' then
          CheckDlgButton(hApp, IDC_CHKISGUEST, Integer(TRUE));
        Inc(Integer(gui0), sizeof(pointer));
      end;
        //Messagebox(0, pointer(s), '', 0);
    end;
    NetAPIBufferFree(tmp);

Luckie 28. Jan 2003 04:37

So:
Delphi-Quellcode:
GetMem(lgrmi, dwEntries*sizeof(Pointer));
      for i := 0 to dwEntries-1 do
      begin
        Inc(Integer(gui0), sizeof(Pointer));
        PLocalGroupInfo0(lgrmi)^.lgrpi0_name := PWideChar(WideString(sGroupArray[i]));
      end;

      dwError := NetLocalGroupAddMembers(nil, PWideChar(WideString(sUser)), 0, lgrmi, dwEntries);
Also mit NetLocalGroupAddMembers bekomme ich keine Fehlermeldung, aber er macht es auch nicht.

Christian Seehase 28. Jan 2003 13:15

Moin Luckie,

wie heute Früh im Chat versprochen hab' ich mir das noch einmal angesehen:

So geht's bei mir:

Delphi-Quellcode:
var
  pGroupname : PWideChar;
  pMember   : PLOCALGROUP_MEMBERS_INFO_3;
  dwResult  : NET_API_STATUS;

begin
  pGroupName := AllocMem((Length('Hauptbenutzer')+1) shl 1);
  pMember   := AllocMem(SizeOf(LOCALGROUP_MEMBERS_INFO_3));
  pMember.lgrmi3_domainandname := AllocMem((Length('<Rechnername>\testuser')+1) shl 1);
  try
    // Kein Length + 1, wegen der abschliessenden #00#00
    StringToWideChar('Hauptbenutzer',pGroupName,Length('Hauptbenutzer') shl 1);
    StringToWideChar('<Rechnername>\testuser',pMember.lgrmi3_domainandname,Length('<Rechnername>\testuser') shl 1);
    dwResult := NetLocalGroupAddMembers(nil,pGroupName,3,pMember,1);
    case dwResult of
      NERR_SUCCESS         : ShowMessage('OK');
      NERR_GROUPNOTFOUND   : ShowMessage('Group not found');
      else ShowMessage(SysErrorMessage(dwResult)+#13#10+IntToStr(dwResult));
    end;
  finally
    FreeMem(pGroupname,(Length('Hauptbenutzer')+1) shl 1);
    FreeMem(pMember.lgrmi3_domainandname,(Length('<Rechnername>\testuser')+1) shl 1);
    FreeMem(pMember,SizeOf(LOCALGROUP_MEMBERS_INFO_3));
  end;
end;
Achtung:
Eventuell musst Du noch was im Aufruf anpassen, da ich nicht die Jedi Units benutze.

<Rechnername> muss natürlich gegen den Namen des Rechners ausgetauscht werden, auf dem die Funktion aufgerufen wird, aber Du wirst ja eh' nicht drum herumkommen das was ich da als Stringliterale angegeben habe in Form von Stringvariablen zu benutzen.

Luckie 28. Jan 2003 13:55

Ich werde mir dan nachher mal ankucken(, ich muß noch etwas von der Nacht nachholen. :wink:) . Wenn es bei dir klappt, aber bei mir nicht, dann war ich zu blöd es einzubauen. :roll:

Stichwort Rechnername: Es geht mir erstmal nur um den lokalen Rechner. Und wenn man die NetUserxxx Funktionen mit nil als Rechnernamen aufruft, wird immer der lokale Rechner genommen. Sollte hier nicht anders sein.

Danke für deine Mühe.

Sharky 28. Jan 2003 14:30

Re: Benutzer einer Gruppe zu ordnen
 
Zitat:

Zitat von Luckie
...und dann das große Geld damit machen. :mrgreen:

Es geht jetzt darum einem Benutzer einer Gruppe zu zuordnen. Folgender Code läßt sich prima kompilieren (beide Versionen):

Wenn Du dann so viel Kohle hast wie Bill musst Du uns aber zum essen einladen :lol:

Aber jetzt die Frage:
Warum nur EINE Gruppe? Ich kann doch Mitglied von verschiedenen Gruppen sein. Besonders von Gruppen die ich selber angelegt habe!

Christian Seehase 28. Jan 2003 16:40

Moin Luckie,

an der Stelle, an der ich <Rechername> geschrieben habe, muss der Name des lokalen Rechners stehen, damit die Funktion weiss, von wo sie die Userinformationen ziehen soll.
Es wird an der Stelle die Angabe von Arbeitsgruppe oder Domain erwartet, aus der der User stammt. Ist es ein lokaler User muss hier also der Name des Rechners angegeben werden.
Du könntest hier ja ebensogut einen Domänenuser angeben.

Das Du für den "Server" hier nil eintragen kannst hat damit nichts zu tun. An dieser Stelle wird ja festgelegt, von welchem Rechner die Lokale Gruppe gemeint ist, der der User hinzugefügt werden soll.

Prinzipiell kann diese Funktion ja auch auf anderen Rechnern als dem eigenen, User zu lokalen Gruppen hinzufügen.

Luckie 28. Jan 2003 18:10

@Sharky: Das kann man ja auch wenn es fertig ist.

@Christian: Ja stimmt. Hast Recht.

Hansa 28. Jan 2003 18:16

Ich habe das Programm mit Novell getestet. Das stimmt soweit, aber Alter des Passworts nicht.

Gruß
Hansa

MadMason 28. Jan 2003 18:18

Re: Benutzer einer Gruppe zu ordnen
 
Zitat:

Zitat von Luckie
Kann ich ihn veröffentlichen bzw. als Alpha-Release zum Testen freigeben und dann das große Geld damit machen. :mrgreen:

ich kenn mich ja in der lizenzpolitik borlands nicht 100% aus aber ich glaube mit ner Personal darfst du deine Software nicht verkaufen sondern nur als freeware weitergeben.
korigier mich wenn ich mich irre :?:

Luckie 28. Jan 2003 18:25

Das stimmt, aber was spricht dagegen sich das von einem Freund kompilieren zu lassen, der Professional oder höher hat?

MadMason 28. Jan 2003 18:52

da spricht natürlich nichts dagegen :spin:

Luckie 28. Jan 2003 20:08

Es klappt. ich mußte nur Allocmem durch GetMem ersetzen.

:dancer: :dancer2: :bouncing4: :firejump: :bounce1: :bounce2: :P :) :D :hello: :witch: :love: :roteyes: :spin2: :corky: :stupid: :thuimb:

Christian Seehase 28. Jan 2003 21:12

Moin Luckie,

Zitat:

ich mußte nur Allocmem durch GetMem ersetzen.

:shock:

Warum das denn?

AllocMem macht doch nichts anderes, ausser dass der Speicher auf #00 initialisiert wird.

Luckie 28. Jan 2003 21:20

Ja, steckt aber in SysUtils drin. Du verstehen? :wink:

Jetzt bekomme ich aber hier einen RunTimeError:

Delphi-Quellcode:
procedure AddUserProc(sComputer: String);
var
  ui3        : PUSERINFO3; //Pointer;
  szBuffer  : array[0..255] of Char;
  s, sUser  : String;
  dwNetError : NET_API_STATUS;
begin
  Sender := VOID;
  GetMem(ui3, (sizeof(USER_INFO_3)) shl 1);
  GetDlgItemText(hApp, IDC_EDTNAME, szBuffer, sizeof(szBuffer));
  sUser := s;
  s := String(szBuffer);
  ui3.usri3_name := PWideChar(WideString(s));
  GetDlgItemText(hApp, IDC_EDTDESCRIPTION, szBuffer, sizeof(szBuffer));
  s := String(szBuffer);
  ui3.usri3_comment := PWideChar(WideString(s));
  GetDlgItemText(hApp, IDC_EDTFULLNAME, szBuffer, sizeof(szBuffer));
  s := String(szBuffer);
  ui3.usri3_full_name := PWideChar(WideString(s));
  GetDlgItemText(hApp, IDC_EDTHOMEDIR, szBuffer, sizeof(szBuffer));
  s := String(szBuffer);
  ui3.usri3_home_dir := PWideChar(WideString(s));

  ui3.usri3_flags := 0;
  if IsDlgButtonChecked(hApp, IDC_CHKCANTCHNGPW) = BST_CHECKED then
    ui3.usri3_flags := ui3.usri3_flags or UF_PASSWD_CANT_CHANGE
  else
    ui3.usri3_flags := ui3.usri3_flags and not UF_PASSWD_CANT_CHANGE;
  if IsDlgButtonChecked(hApp, IDC_CHKDISABLED) = BST_CHECKED then
    ui3.usri3_flags := ui3.usri3_flags or UF_ACCOUNTDISABLE
  else
    ui3.usri3_flags := ui3.usri3_flags and not UF_ACCOUNTDISABLE;
  if IsDlgButtonChecked(hApp, IDC_CHKDONTEXPIRE) = BST_CHECKED then
    ui3.usri3_flags := ui3.usri3_flags or UF_DONT_EXPIRE_PASSWD
  else
    ui3.usri3_flags := ui3.usri3_flags and not UF_DONT_EXPIRE_PASSWD;
  if IsDlgButtonChecked(hApp, IDC_CHKLOCKED) = BST_CHECKED then
    ui3.usri3_flags := ui3.usri3_flags or UF_LOCKOUT
  else
    ui3.usri3_flags := ui3.usri3_flags and not UF_LOCKOUT;
  if IsDlgButtonChecked(hApp, IDC_CHKMUSTCHNGPW) = BST_CHECKED then
    ui3.usri3_password_expired := 1
  else
    ui3.usri3_password_expired := 0;

  dwNetError := NetUserAdd(nil, 3, ui3, nil); // <- hier kommt der RunTimeError. Was habe ich übersehen?
  NetAPIBufferFree(ui3);

  if IsDlgButtonChecked(hApp, IDC_CHKISADMIN) = BST_CHECKED then
    dwNetError := AddToGroup('Administratoren', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISPOWERUSER) = BST_CHECKED then
    dwNetError := AddToGroup('Hauptbenutzer', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISUSER) = BST_CHECKED then
    dwNetError := AddToGroup('Benutzer', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISGUEST) = BST_CHECKED then
    dwNetError := AddToGroup('Gäste', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISBACKUPOP) = BST_CHECKED then
    dwNetError := AddToGroup('Sicherungs-Operatoren', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISREPOP) = BST_CHECKED then
    dwNetError := AddToGroup('Replikations-Operator', sUser, sComputer);

  case dwNetError of
    ERROR_ACCESS_DENIED    : s := 'Zugriff verweigert.';
    ERROR_INVALID_PARAMETER : s := 'Ungültiger Parameter.';
    NERR_InvalidComputer   : s := 'Ungültiger Computer';
    NERR_NotPrimary        : s := 'Operation darf nur auf dem Domain-Controller ausgeführt werden.';
    NERR_SpeGroupOp        : s := 'Operation darf nicht auf diese Gruppe angewandt werden.';
    NERR_LastAdmin         : s := 'Der letzte macht das Licht aus, aber nicht bei Windows. :o)'
                                +#13#10+'Der letzte Administrator Account kann nicht gelöscht werden';
    NERR_BadPassword,
    NERR_PasswordTooShort  : s := 'Ungültiges Passwort';
    NERR_UserNotFound      : s := 'Ungültiger Benutzer.';
    NERR_GroupNotFound     : s := 'Gruppe nicht gefunden.';
    NERR_Success           : s := 'Konto erfolgreich geändert.';
  end;
  if dwNetError <> NERR_Success then
    Messagebox(hApp, pointer(s), 'Konto ändern', MB_ICONSTOP);
end;
Wozu eigentlich das shl 1 bei GetMem?

Christian Seehase 28. Jan 2003 21:58

Moin Luckie,

wie shl 1 bei GetMem?

Das hab' ich nur dort gemacht, wo ich den Platz für den WideString reserviert habe, alldieweil dies ja schliesslich 2 Byte je Zeichen haben, und meine Ausgangsliterale waren ja ANSI Strings.

Also einen Runtime Error kann ich mir so auch nicht erklären.

Eine Frage bleibt mir aber noch:
Der 3. Parameter (ui3) soll ein Pointer sein. Wie sieht hier die Deklaration der Jedis aus? Wenn es Borland konform ist müsste dies ein var Parameter sein, so dass Du an dieser Stelle keinen Pointer übergeben darfst. Die Deklaration von ui3 müsste also lauten

ui3 : USER_INFO_3;

und nicht

ui3 : PUSER_INFO_3;

NetApiBufferFree(ui3) ist übrigens schlicht falsch.

Man muss diese Funktion aufrufen, nachdem man eine Funktion verwendet hat, die Speicher reserviert, was NetUserAdd ja nicht tut.
Die Funktion (NetApiBufferFree) wird gar nichts mit dem Pointer anfangen können. Ich würde glatt mal mit einem "unfreundlichen" Returncode rechen (zumindest nicht NERR_SUCCESS).

[EDIT]
Wenn Du schon nicht AllocMem verwenden willst, solltest Du aber, der Ordnung halber, ZeroMemory einbauen.
Ein try/finally wär' auch nicht schlecht ;-)
[/EDIT]

Luckie 28. Jan 2003 22:10

Gut dann hat sich das mit shl 1 geklärt.

NetAPIBufferFree ist noch aus dem Copy and paste von ModifyUser übriggeblieben.

Die Jedi Deklaration sieht so aus:

Delphi-Quellcode:
  PUserInfo3 = ^TUserInfo3;
  {$EXTERNALSYM _USER_INFO_3}
  _USER_INFO_3 = record
    usri3_name: LPWSTR;
    usri3_password: LPWSTR;
    usri3_password_age: DWORD;
    usri3_priv: DWORD;
    usri3_home_dir: LPWSTR;
    usri3_comment: LPWSTR;
    usri3_flags: DWORD;
    usri3_script_path: LPWSTR;
    usri3_auth_flags: DWORD;
    usri3_full_name: LPWSTR;
    usri3_usr_comment: LPWSTR;
    usri3_parms: LPWSTR;
    usri3_workstations: LPWSTR;
    usri3_last_logon: DWORD;
    usri3_last_logoff: DWORD;
    usri3_acct_expires: DWORD;
    usri3_max_storage: DWORD;
    usri3_units_per_week: DWORD;
    usri3_logon_hours: PBYTE;
    usri3_bad_pw_count: DWORD;
    usri3_num_logons: DWORD;
    usri3_logon_server: LPWSTR;
    usri3_country_code: DWORD;
    usri3_code_page: DWORD;
    usri3_user_id: DWORD;
    usri3_primary_group_id: DWORD;
    usri3_profile: LPWSTR;
    usri3_home_dir_drive: LPWSTR;
    usri3_password_expired: DWORD;
  end;
  TUserInfo3 = _USER_INFO_3;
  {$EXTERNALSYM USER_INFO_3}
  USER_INFO_3 = _USER_INFO_3;
Delphi-Quellcode:
{$EXTERNALSYM NetUserAdd}
function NetUserAdd(servername: LPCWSTR; level: DWORD; buf: Pointer;
  parm_err: PDWORD): NET_API_STATUS; stdcall;
Ich bin da jetzt noch nicht viel weitergekommen.

Christian Seehase 28. Jan 2003 23:44

Moin Luckie,

ein Runtime Error als solcher ist ja eh' schon recht unschön. Das ist ja nichts Halbes und nichts Ganzes ;-)

Hast Du schon mal bei Borland nachgesehen, was es mit diesem Fehler auf sich hat? (oder gibt's noch nicht mal 'ne Fehlernummer?)

Das Einzige was mir so auf Anhieb noch einfiele:
Breakpoint auf NetUserAdd, und dann in's CPU Debug Fenster wechseln. Vielleicht gibt's da mehr zu sehen.

Luckie 28. Jan 2003 23:51

Den habe ich ganz übersehen:
216: The image file %1 is valid, but is for a machine type other than the current machine.

Sehr viel weiter hilft mir das aber auch nicht. Eher im Gegenteil.

Und CPU-Fenster. OK, ich weiß, wie es man es auf macht und wie es aussieht, aber meine Assembler-Kenntnisse sind mehr als beschränkt.

Der Benutzer wird auch richtig angelegt. Bis auf die Tatsache, dass die Benutzergruppen nicht übernommen wird.

Hansa 29. Jan 2003 00:25

Zitat:

Zitat von Luckie
216:

Der Fehler ist mir noch gut in Erinnerung. Hat der mich Zeit gekostet. Im Protected Mode bei BP7 war das mehr oder weniger ein Hardware - Fehler. Geh der Spur mal nach.

Gruß
Hansa

Luckie 29. Jan 2003 00:29

Hardwarefehler? :shock:

Mein Programm hat nichts mit der Hardware am Hut. Wie soll ich da was nachgehen?

Hansa 29. Jan 2003 00:36

Zitat:

Zitat von Hansa
Geh der Spur mal nach.

Damit meinte ich MICH ! Ich geh der Spur nach. Das ist ein dubioser Fehler. Irgendwo in meinen Quelltexten ist darauf ein Hinweis drin. Den suche ich, aber erst morgen :angle:

Gruß
Hansa

Luckie 29. Jan 2003 00:42

Achso. Na dan mal los. Aber ich denke nicht, dass die Fehler die gleiche Ursache haben.

Hansa 29. Jan 2003 00:57

Zitat:

Zitat von Luckie
...Aber ich denke nicht, dass die Fehler die gleiche Ursache haben.

Ja, glaube ich auch. Aber das ist ein ätzender Fehler. Lese hier:

http://www.nl.freepascal.org/lists/f...ry/002758.html

Wenn ich mein Gedächtnis bemühe : ab 500 MHz gabs Ärger. Dann kam dieser Fehler. Irgendwo mußte integer (16Bit) auf 32 Bit umgestellt werden. Dann gings.

Gruß
Hansa

Luckie 29. Jan 2003 01:00

Nein, daran liegt es wohl nicht. ich vermute eher, dass ich mit dem Speicher Mist baue.

Hansa 29. Jan 2003 01:07

Ja,

irgend so eine Scheiße ist das da. Absolut unsinniger und unnötiger Mist !

Gruß
Hansa

P.S.: wie gesagt, gucke morge mal nach.

Luckie 29. Jan 2003 04:16

Irgendwie glaube ich, dass ich mich im Kreise drehe. Ich bin, glaube ich, wieder bei der Ursprungsversion angekommen:
Delphi-Quellcode:
procedure AddUserProc(sComputer: String);
var
  ui3        : Pointer; // USER_INFO_3; //
  szBuffer  : array[0..255] of Char;
  s, sUser  : String;
  dwNetError : NET_API_STATUS;
begin
  Sender := VOID;
  GetMem(ui3, sizeof(USER_INFO_3));
  try
    GetDlgItemText(hApp, IDC_EDTNAME, szBuffer, sizeof(szBuffer));
    sUser := s;
    s := String(szBuffer);
    PUSERINFO3(ui3)^.usri3_name := PWideChar(WideString(s));
    GetDlgItemText(hApp, IDC_EDTDESCRIPTION, szBuffer, sizeof(szBuffer));
    s := String(szBuffer);
    PUSERINFO3(ui3)^.usri3_comment := PWideChar(WideString(s));
    GetDlgItemText(hApp, IDC_EDTFULLNAME, szBuffer, sizeof(szBuffer));
    s := String(szBuffer);
    PUSERINFO3(ui3)^.usri3_full_name := PWideChar(WideString(s));
    GetDlgItemText(hApp, IDC_EDTHOMEDIR, szBuffer, sizeof(szBuffer));
    s := String(szBuffer);
    PUSERINFO3(ui3)^.usri3_home_dir := PWideChar(WideString(s));

    PUSERINFO3(ui3)^.usri3_flags := 0;
    if IsDlgButtonChecked(hApp, IDC_CHKCANTCHNGPW) = BST_CHECKED then
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags or UF_PASSWD_CANT_CHANGE
    else
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags and not UF_PASSWD_CANT_CHANGE;
    if IsDlgButtonChecked(hApp, IDC_CHKDISABLED) = BST_CHECKED then
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags or UF_ACCOUNTDISABLE
    else
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags and not UF_ACCOUNTDISABLE;
    if IsDlgButtonChecked(hApp, IDC_CHKDONTEXPIRE) = BST_CHECKED then
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags or UF_DONT_EXPIRE_PASSWD
    else
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags and not UF_DONT_EXPIRE_PASSWD;
    if IsDlgButtonChecked(hApp, IDC_CHKLOCKED) = BST_CHECKED then
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags or UF_LOCKOUT
    else
      PUSERINFO3(ui3)^.usri3_flags := PUSERINFO3(ui3)^.usri3_flags and not UF_LOCKOUT;
    if IsDlgButtonChecked(hApp, IDC_CHKMUSTCHNGPW) = BST_CHECKED then
      PUSERINFO3(ui3)^.usri3_password_expired := 1
    else
      PUSERINFO3(ui3)^.usri3_password_expired := 0;

    dwNetError := NetUserAdd(nil, 3, ui3, nil); //  hier steigt er mit dem RuntimeError 216 aus
  finally
    FreeMem(ui3, sizeof(USER_INFO_3));
  end;

  if IsDlgButtonChecked(hApp, IDC_CHKISADMIN) = BST_CHECKED then
    dwNetError := AddToGroup('Administratoren', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISPOWERUSER) = BST_CHECKED then
    dwNetError := AddToGroup('Hauptbenutzer', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISUSER) = BST_CHECKED then
    dwNetError := AddToGroup('Benutzer', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISGUEST) = BST_CHECKED then
    dwNetError := AddToGroup('Gäste', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISBACKUPOP) = BST_CHECKED then
    dwNetError := AddToGroup('Sicherungs-Operatoren', sUser, sComputer);
  if IsDlgButtonChecked(hApp, IDC_CHKISREPOP) = BST_CHECKED then
    dwNetError := AddToGroup('Replikations-Operator', sUser, sComputer);

  if dwNetError <> NERR_Success then
    DisplayNetError(dwNetError);
end;
Mit dem Erfolg, dass der RuntimeError immer noch nicht weg ist. :cry:

Irgendwelche Vorschläge, Ideen? :?

Christian Seehase 29. Jan 2003 13:07

Moin Luckie,

ich hab' das mal versucht auch zu machen. Bei mir sieht's dann so aus:

Delphi-Quellcode:
const // aus Winnt.h
  DOMAIN_GROUP_RID_USERS = $00000201;

var
  rUI     : USER_INFO_3;
  dwResult : NET_API_STATUS;

begin
  FillChar(rUI,SizeOf(USER_INFO_3),0);
  rUI.usri3_name            := 'testuser2';
  rUI.usri3_password        := '';
  rUI.usri3_comment         := 'Neuer Testuser';
  rUI.usri3_flags           := UF_NORMAL_ACCOUNT;
  rUI.usri3_max_storage     := USER_MAXSTORAGE_UNLIMITED;
  rUI.usri3_primary_group_id := DOMAIN_GROUP_RID_USERS;
  dwResult := NetUserAdd(nil,3,@rUI,nil);
  if dwResult <> NERR_SUCCESS then
  begin
    ShowMessage(SysErrorMessage(dwResult));
  end;
end;
So geht's, auch kein Runtime Error.

Was mir allerdings auffällt:

Du weist ganz zu Anfang der lokalen Variablen sUser die lokale Variable s zu. Beide sind zu diesem Zeitpunkt allerdings noch nicht initialisiert. Das könnte nach NetUserAdd doch zu Problemen führen.

Luckie 29. Jan 2003 13:58

*luckie der vor freude aus dem schreibtsichstuhl springt und vor glückseeligkeit im zimmer rumhüpft*

:bouncing4: :firejump: :bounce1: :bounce2: :hello:

*luckie der außeratem zum schreibtischstuhl zurückkehrt und christian um den hals fällt*

:P :hello: :witch: :stupid:

Christian Seehase 29. Jan 2003 15:19

Moin Luckie,

freut mich ja, wenn ich Dir helfen konnte, aber was war's denn nun.

BTW:
Und pass auf meinen Arm auf ;-)

Luckie 29. Jan 2003 15:23

Gute Frage. Auf alle Fälle ging es dann ohne Runtime Error. was auch wichtig war ist das: DOMAIN_GROUP_RID_USERS = $00000201; ohne das legt er den Benutzer nicht an.

Deinen Arm? Was ist mit dem?


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:36 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