![]() |
da spricht natürlich nichts dagegen :spin:
|
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: |
Moin Luckie,
Zitat:
:shock: Warum das denn? AllocMem macht doch nichts anderes, ausser dass der Speicher auf #00 initialisiert wird. |
Ja, steckt aber in SysUtils drin. Du verstehen? :wink:
Jetzt bekomme ich aber hier einen RunTimeError:
Delphi-Quellcode:
Wozu eigentlich das shl 1 bei GetMem?
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; |
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] |
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:
Ich bin da jetzt noch nicht viel weitergekommen.
{$EXTERNALSYM NetUserAdd}
function NetUserAdd(servername: LPCWSTR; level: DWORD; buf: Pointer; parm_err: PDWORD): NET_API_STATUS; stdcall; |
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. |
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. |
Zitat:
Gruß Hansa |
Hardwarefehler? :shock:
Mein Programm hat nichts mit der Hardware am Hut. Wie soll ich da was nachgehen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:41 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