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 Rückgabewert von CreateProcessWithLogonW und GetLastError (https://www.delphipraxis.net/38439-rueckgabewert-von-createprocesswithlogonw-und-getlasterror.html)

Luckie 19. Jan 2005 14:04


Rückgabewert von CreateProcessWithLogonW und GetLastError
 
Ich habe hier ein dummes Problem. Erstmal der Code:

Delphi-Quellcode:
if not CreateProcessAsLogon(User, PW, Filename, Params)then
  begin
    MessageBox(hDlg, PChar(SysErrorMessage(GetLastError)), APPNAME, MB_ICONSTOP);
    // ExitCode: ID_CANCEL -> don't close main window
    ExitCode := ID_CANCEL;
  end
  else
    // ExitCode: ID_OK -> close main window
  ExitCode := ID_OK;
end
CreateProcessAsLogon sieht so aus:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
begin
  ZeroMemory(@si, sizeof(TStartupInfo));
  si.cb := SizeOf(TStartupInfoW);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;
  Result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, PWideChar(Application + ' ' + CmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, si, pif);
end;
Nun das Problem: Übergebe ich ein falsches Passwort, gibt die Funktion auch brav false zurück. Entsprechend geht der Code in den False-Zweig und die Messagebox erscheint. Schön, wenn da in der Messagebox nicht stünde, dass der Vorgang erfolgreich beendet wurde, was ja nun nicht stimmt. :gruebel:
Weiß jemand, was da falsch läuft? Also warum GetLastError 0 ist?

SubData 19. Jan 2005 15:06

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Ich würde mal auf Absicht tippen...

Nehmen wir an du hast ein Programm was das Passwort knacken will...
Wenn es keinen "Fehler-Wert" bei falschem Passwort bekommt, kann man an der Stelle keine "Try and Error" Methode anwenden..

Nur so als Idee, man korrigiere mich, wenn ich daneben liege :)

Luckie 19. Jan 2005 15:09

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Dann dürfte die Funktion aber auch kein False zurückliefern.

Luckie 20. Jan 2005 18:55

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Ich habe das Programm jetzt erstmal mit einer eigenen Fehlermeldung veröffentlicht: RunAsUser. Aber befriedigen tut mich das nicht. Hat sonst noch jemand eine Idee, woran das liegen könnte oder was ich falsch mache?

mirage228 20. Jan 2005 19:14

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Hi,

was sagt denn das MSDN dazu?

Steht dort, dass man den Fehler mit GetLastError bestimmen kann?

mfG
mirage228

Motzi 20. Jan 2005 19:22

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von mirage228
was sagt denn das MSDN dazu?

Steht dort, dass man den Fehler mit GetLastError bestimmen kann?

Wenn du nachgeschaut hättest wüsstest du es.. :roll: Ja, steht dort! ;)

Liefert GetLastError korrekte Fehlercodes bei anderen Fehlern (zB nicht existierender User)? Wenn ja könnte man im Fall von CreateProcessWithLogonW = False + GetLastError = 0 eine eigene Überprüfung des Passwortes per SSPI durchführen und eventuell eine entsprechende Fehlermeldung ausgeben...

Luckie 22. Jan 2005 13:17

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
So dieser Code
Code:
#define _WIN32_WINNT 0x0500 

#include <windows.h>
#include <iostream>

int main()

    STARTUPINFOW startupInfo;
    ZeroMemory(&startupInfo, sizeof(STARTUPINFOW));
    startupInfo.cb = sizeof(STARTUPINFOW);
    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
    startupInfo.wShowWindow = SW_SHOWNORMAL;
   
    PROCESS_INFORMATION processInformation;

    WCHAR commandLine[MAX_PATH];
    lstrcpyW(commandLine, L"C:\\winnt\\notepad.exe");

    BOOL ret = CreateProcessWithLogonW(L"Administrator",
                                       NULL,
                                       L"xxx",
                                       LOGON_WITH_PROFILE,
                                       NULL,
                                       commandLine,
                                       CREATE_DEFAULT_ERROR_MODE,
                                       NULL,
                                       NULL,
                                       &startupInfo,
                                       &processInformation);

    if(ret)
    { 
        std::cout << "CreateProcessWithLogonW succeed!" << std::endl;
    } 
    else
    { 
        std::cout << "CreateProcessWithLogonW failed! " << GetLastError() << std::endl;
    } 
}
(Quelle: http://www.c-plusplus.de/forum/viewtopic.php?t=98607 )

tut es unter Windows XP SP2 korrekt:
Zitat:

Anmeldung fehlgeschlagen: unbekannter Benutzername oder falsches Kennwort.
So jetzt die Preisfrage: Wo ist der Unterschied zu meinem Code?

MathiasSimmack 22. Jan 2005 13:43

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Was ist denn der Preis? Sehe ich das richtig: Wenn ein falsches Passwort angegeben wird, soll die besagte Meldung kommen? Dann geht´s bei mir. 8)

Edit: Mit Delphi natürlich!

Luckie 22. Jan 2005 13:46

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Reicht ein feuchter Händedruck? ;)

MathiasSimmack 22. Jan 2005 13:49

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Feucht auch noch. :shock: Tja, keine Ahnung. Ich habe nur Delphi 5 und musste den ganzen Plunder daher selbst deklarieren, aber ich sehe die gewünschte Fehlermeldung, weil "xxx" natürlich nicht mein Admin-Kennwort ist. Hier der Code (die "DisplayErrorMsg"-Prozedur müsstest du kennen)
Delphi-Quellcode:
type
  _STARTUPINFOW = record
    cb: DWORD;
    lpReserved: Pointer;
    lpDesktop: Pointer;
    lpTitle: Pointer;
    dwX: DWORD;
    dwY: DWORD;
    dwXSize: DWORD;
    dwYSize: DWORD;
    dwXCountChars: DWORD;
    dwYCountChars: DWORD;
    dwFillAttribute: DWORD;
    dwFlags: DWORD;
    wShowWindow: Word;
    cbReserved2: Word;
    lpReserved2: PByte;
    hStdInput: THandle;
    hStdOutput: THandle;
    hStdError: THandle;
  end;
  TStartUpInfoW = _STARTUPINFOW;
  PStartUpInfoW = ^_STARTUPINFOW;
const
  LOGON_WITH_PROFILE = $00000001;

function CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword: PWideChar;
  dwLogonFlags: dword; lpApplicationName, lpCommandLine: PWideChar;
  dwCreationFlags: dword; lpEnvironment: pointer;
  lpCurrentDirectory: PWideChar; lpStartupInfo: PStartUpInfoW;
  lpProcessInfo: PProcessInformation): boolean; stdcall;
  external 'advapi32.dll';

procedure DisplayErrorMsg(wnd: HWND);
var
  buf : array[0..MAX_PATH]of char;
begin
  ZeroMemory  (@buf,sizeof(buf));
  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,nil,GetLastError,0,buf,
    sizeof(buf),nil);
  MessageBox  (wnd,buf,nil,MB_OK or MB_ICONSTOP);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  si : TStartupInfoW;
  pif : TProcessInformation;
  res : boolean;
begin
  ZeroMemory(@si,sizeof(si));
  si.cb         := sizeof(si);
  si.dwFlags    := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  res           := CreateProcessWithLogonW('Administrator',nil,
    'xxx',LOGON_WITH_PROFILE,nil,
    'rollup.exe',
    CREATE_DEFAULT_ERROR_MODE,nil,nil,@si,@pif);

  if(not res) then DisplayErrorMsg(self.Handle);
end;
Das Test-OS war XP SP2.

Luckie 22. Jan 2005 14:12

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Hmpf. Mit einem leeren Projekt geht es. Füge ich den Code bei mir ein, bekomme ich nach der Passwort Eingabe einen RunTime Error 216 (AccessViolation). Die Deklaraition von _STARTUPINFOW = record habe ich so auch übernommen.
TProcessInformation sieht bei mir so aus:
Delphi-Quellcode:
  TProcessInformation = record
    hProcess: THandle;
    hThread: THandle;
    dwProcessId: DWORD;
    dwThreadId: DWORD;
  end;
  PProcessInformation = ^TProcessInformation;
Das sollte aber passen.

Motzi 22. Jan 2005 14:16

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Wenn du willst kann ichs mir morgen nochmal genauer anschaun.. jetzt muss ich erstmal zur Geburtstagsfeier meiner "Schwiegermama".. ;)

Luckie 22. Jan 2005 14:19

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Liste der Anhänge anzeigen (Anzahl: 1)
So der 216'er ist weg. Aber jetzt bekomme ich wieder "Vorgang wurde erfolgreich abgeschlossen" bei falschen Passwort. Ich werde noch mal wahnsinnig. :wall:

Wenn da mal bitte jemand draufgucken könnte? Ich sehe es einfach nicht. Sourcen im Anhang. Die Deklarationen sind in MpuWinNT.pas und der Code, um den es geht in RunDlg.pas.

MathiasSimmack 22. Jan 2005 14:48

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Also, halte mir bitte zugute, dass ich heute das erste Mal mit dieser Funktion gearbeitet habe. Darum fiel mir ein Problem vorher gar nicht auf. :oops: Aber egal, jetzt will ich mich erst mal im Glanz meines Wissens sonnen 8).

Also, ein Problem liegt daran, dass du Programm und Parameter mit Leerzeichen verbindest. An sich kein Problem, und wenn ich die Dateinamen und Parameter direkt als String vorgebe (s. wie oben in meinem Beispiel), dann klappt das sogar. Ich hätte es also erst mal auf ein Problem beim Typecast von Widestring -> PWideChar geschoben.

Nach näherer Betrachtung der Deklaration im PSDK schlage ich aber vor, du machst es einfach so:
Delphi-Quellcode:
  result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, { --> } PWideChar(Application), PWideChar(CmdLine), { <-- }
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
Ich meine, die werden sich schon was dabei gedacht haben, die Parameter als "lpApplicationName" und "lpCommandLine" zu bezeichnen. :mrgreen:


Edit: Könnte sein, dass ich das Wort "Problem" zu oft benutzt habe :zwinker:

Luckie 22. Jan 2005 14:50

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
:angel: :hello: :love: :firejump: :drunken: :duck:

Edit: Zu früh gefreut, jetzt beachtet er den Parameter nicht mehr. :cry:

MathiasSimmack 22. Jan 2005 14:57

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Erst will ich meinen feuchten Händedruck, dann schaue ich´s mir vielleicht noch mal an ...

Luckie 22. Jan 2005 15:02

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
hände ableck und drückt

Ich habe eine Managment Konsole (mmc.exe) der über gebe ich eine Konsole (D:\Einstellungen\Konsole.msc), nur öffnet er mir die mmc.exe jetzt immer leer. Ich glaube deswegen habe ich auch Programm und Parameter zusammen beo lpApplication angegeben.

MathiasSimmack 22. Jan 2005 15:05

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Ich habe zwar keine Ahnung, was ich hier eigentlich mache :oops:, aber du hast Recht. Ich habe gerade mal ein Programm mit Parameter gestartet, und es funktionierte nicht. Normalerweise hätte der ungültige Parameter eine entsprechende Syntaxmeldung zum Vorschein bringen müssen.
Nun kann das aber in meinem Fall auch daran gelegen haben, dass ich einen langen Dateinamen hatte. Und da steht im PSDK: Anführungszeichen
Delphi-Quellcode:
  result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, pwidechar('"' + Application + '" ' + CmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
Jetzt entspricht es wieder dem Muster vom Anfang, und es funktionierte bei mir sogar. Nein, jetzt kommt wieder die Meldung "Vorgang wurde erfolgreich ausgeführt", trotz falschem Passwort. Hm ... :?

Luckie 22. Jan 2005 15:09

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Wir sind wieder am Anfang. Jetzt startet er die Anwnednug wieder korrekt, aber bei falschen Passwort habe ich wieder:
Zitat:

---------------------------
RunAsUser
---------------------------
Der Vorgang wurde erfolgreich beendet
---------------------------
OK
---------------------------
:wall:

MathiasSimmack 22. Jan 2005 18:37

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Tja, warum auch immer, aber es hat was mit dem Typecast zu tun:
Delphi-Quellcode:
pwidecar(Application + ' ' + CmdLine)
Wenn ich nämlich das Programm und den falschen Parameter fest eintrage, dann funktioniert es wie es soll: Mit richtigem Passwort kommt die Fehlermeldung wg. Syntax (der Parameter wird also berücksichtigt), und mit falschem Passwort kommt die Meldung "Unbekannter Benutzer oder Passwort".

In der Richtung solltest du also mal weiter forschen.
Reagiert das C-Programm eigentlich immer richtig? Mit und ohne Parameter, meine ich.

Luckie 22. Jan 2005 19:05

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Die Exe schon, leider habe ich es noch nicht geschafft es zu kompilieren.

Luckie 22. Jan 2005 19:24

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Hm meine Versuche sehen jetzt so aus:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: PWideChar):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  AppCmdLine  : PWideChar;
begin
  GetMem(AppCmdLine, length(Application) + length(CmdLine) + 3);
  try
    lstrcpyW(AppCmdLine, Application);
    lstrcatW(AppCmdLine, ' "');
    lstrcatW(AppCmdLine, CmdLine);
    lstrcatW(AppCmdLine, '"');
    ZeroMemory(@si, sizeof(si));
    si.cb := sizeof(si);
    si.dwFlags := STARTF_USESHOWWINDOW;
    si.wShowWindow := 1;

    result := CreateProcessWithLogonW(User, nil, PW,
      LOGON_WITH_PROFILE, nil, AppCmdLine,
      CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
  finally
    FreeMem(AppCmdLine);
  end;
end;
Anwendungen lassen sich mit und ohne Parameter starten, aber es kommt eine AV. Die Parameter werden als PWideChar(WideString(User)) übergeben.

Dann noch das:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  //AppCmdLine  : PWideChar;
begin
//  GetMem(AppCmdLine, length(Application) + length(CmdLine) + 3);
  try
//    lstrcpyW(AppCmdLine, Application);
//    lstrcatW(AppCmdLine, ' "');
//    lstrcatW(AppCmdLine, CmdLine);
//    lstrcatW(AppCmdLine, '"');
    ZeroMemory(@si, sizeof(si));
    si.cb := sizeof(si);
    si.dwFlags := STARTF_USESHOWWINDOW;
    si.wShowWindow := 1;

    result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
      LOGON_WITH_PROFILE, nil, PWideChar(Application+' "'+CmdLine+'"'),
      CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
  finally
//    FreeMem(AppCmdLine);
  end;
end;
Die Parameter werden ungecastet als Stringsübergeben. Da bekomme ich auch Anwendungen mit und ohne Parameter gestartet, aber bei falschen Passwort habe ich wieder GetLastError = 0:

Noch ein Versuch:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  WUser       : WideString;
  WPW         : WideString;
  WApp        : WideString;
  WCmdLine    : WideString;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  WUser := User;
  WPW := PW;
  WApp := Application;
  WCmdLine := CmdLine;

  result := CreateProcessWithLogonW(PWideChar(WUser), nil, PWideChar(WPW),
    LOGON_WITH_PROFILE, nil, PWideChar(WApp + ' "' + WCmdLine + '"'),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
end;
False und GetLastError = 0.

Nächster Versuch:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: PWideChar):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  WUser       : LPWSTR;
  WPW         : LPWSTR;
  WApp        : LPWSTR;
  WCmdLine    : LPWSTR;
  AppCmd: LPWSTR;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  WUser := SysAllocString(User);
  WPW := SysAllocString(PW);
  WApp := SysAllocString(Application);
  WCmdLine := SysAllocString(CmdLine);
  GetMem(AppCmd, length(Application)+length(CmdLine)+3);
  lstrcpyW(AppCmd, WApp);
  lstrcatW(AppCmd, ' "');
  lstrcatW(AppCmd, CmdLine);
  lstrcatW(AppCmd, '"');

  result := CreateProcessWithLogonW(PWideChar(WUser), nil, PWideChar(WPW),
    LOGON_WITH_PROFILE, nil, AppCmd,
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
end;
False und GetLastError = 0. Bei Anwendungen mit Paramtern komt eine AV nach dem Start.

tommie-lie 22. Jan 2005 20:38

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Also folgendes funktioniert bei mir:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  WUser       : WideString;
  WPW         : WideString;
  WApp        : WideString;
  WCmdLine    : WideString;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  WUser := User;
  WPW := PW;
  WApp := Application;
  WCmdLine := CmdLine;

  result := CreateProcessWithLogonW(PWideChar(WUser), nil, PWideChar(WPW),
    LOGON_WITH_PROFILE, PWideChar(WApp), PWideChar(WCmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);

  if not result then
    MessageBox(0, PChar(SysErrorMessage(GetLastError)), 'Testanwendung', MB_ICONSTOP);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  User, PW, Filename, Params: WideString;
begin
  User := Edit1.Text;
  PW := Edit2.Text;
  Filename := Edit3.Text;
  Params := Edit4.Text;

  CreateProcessAsLogon(User, PW, Filename, Params)
end;
Mit Parameter, mit ohne Parameter, mit falschen Passwrt, mit richtigem Passwort, Username, immer das erwartete Ergebnis.

Das geniale ist aber, folgender Code:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  WUser       : WideString;
  WPW         : WideString;
  WApp        : WideString;
  WCmdLine    : WideString;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  WUser := User;
  WPW := PW;
  WApp := Application;
  WCmdLine := CmdLine;

  result := CreateProcessWithLogonW(PWideChar(WUser), nil, PWideChar(WPW),
    LOGON_WITH_PROFILE, PWideChar(WApp), PWideChar(WCmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  User, PW, Filename, Params: WideString;
begin

User := Edit1.Text;
PW := Edit2.Text;
Filename := Edit3.Text;
Params := Edit4.Text;

SetLastError(0);

if not CreateProcessAsLogon(User, PW, Filename, Params)then
    MessageBox(0, PChar(SysErrorMessage(GetLastError)), '', MB_ICONSTOP);
end;
führt zu GetLastError = 0.

Dem bin ich mal nachgegangen, und das ganze scheint sich tief in der Laufzeitumgebung abzuspielen und - oh wunder - alles andere als dokumentiert zu sein.
Vor dem Austritt aus der Funktion ruft der Compiler WStrArrayClr() aus der Borland-RTL auf. Die wiederum ruft SysFreeString aus Microsofts OleAuto32.dll auf (deren Funktioenen in D6 übrigens nur unvollständig implementiert sind, und in der Personal anscheinend noch unvollständiger). Diese ist eigentlich dazu da, einen String wieder freizugeben. Das erstaunliche aber ist, daß sie gleichzeitig den Wert von GetLastError() ändert, und zwar ohne daß das mit nur einem Wort im SDK erwähnt wird. Wenn du GetLastError() vor dem Funktionsaustritt aufrufst, hat der Compiler noch nicht versucht die Widestrings wieder freizugeben, folglich wurde SysFreeString() noch nicht aufgerufen und der Wert von GetLastError stimmt noch. So wie es aussieht musst du also entweder einen variablen Parameter für den Fehlerwert einführen, oder anstatt eines Boolean-Ergebnisses einen Integer mit dem Wert von GetLastError() nehmen.

Ich denke, daß folgender Code es auch tun würde:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, PWideChar(App), PWideChar(CmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);

  if not result then
    MessageBox(0, PChar(SysErrorMessage(GetLastError)), 'Testanwendung', MB_ICONSTOP);
end;
Macht den Code kürzer und spart immerhin das Rumreferenziere der Strings ;-)




Kriege ich jetzt auch einen feuchten Händedruck? Biddöööö :mrgreen:

Luckie 23. Jan 2005 13:20

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von tommie-lie
Also folgendes funktioniert bei mir:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
  WUser       : WideString;
  WPW         : WideString;
  WApp        : WideString;
  WCmdLine    : WideString;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  WUser := User;
  WPW := PW;
  WApp := Application;
  WCmdLine := CmdLine;

  result := CreateProcessWithLogonW(PWideChar(WUser), nil, PWideChar(WPW),
    LOGON_WITH_PROFILE, PWideChar(WApp), PWideChar(WCmdLine),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);

  if not result then
    MessageBox(0, PChar(SysErrorMessage(GetLastError)), 'Testanwendung', MB_ICONSTOP);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  User, PW, Filename, Params: WideString;
begin
  User := Edit1.Text;
  PW := Edit2.Text;
  Filename := Edit3.Text;
  Params := Edit4.Text;

  CreateProcessAsLogon(User, PW, Filename, Params)
end;
Mit Parameter, mit ohne Parameter, mit falschen Passwrt, mit richtigem Passwort, Username, immer das erwartete Ergebnis.

Also GetLastError ist nicht null? Aber wo liegt da der Unterschied zu meinem urspünglichem Code? :gruebel: Du hast übrigens Windows XP oder? Leider bin ich gerade bei meiner Freundin und kann das wohl erst heute Abend ausprobieren. :? Als ich es getrennt ausprobiert habe, also Anwnedung und CommandLine separate angegeben habe, hat er die Coomadline nicht verarbeitet, denn ich meinen, deinen Code hatte icfh auch schon mal ausprobiert. :roll:

Motzi 23. Jan 2005 13:41

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Joa, also mit dem Problem der WideStrings bzw den Typecasts hab ich mich auch schonmal ausführlich beschäftigt. Das Problem ist, wie schon von Thomas erkannt, das interne String-Handling und die damit verbundenen transparenten API-Aufrufe. Werd mir das sobald ich dazu komm nochmal genauer anschaun...

tommie-lie 23. Jan 2005 14:27

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von Luckie
Also GetLastError ist nicht null?

Ich hab' den Zahlwert nicht überprüft, aber er sagt mir schon richtig, daß Passwort oder Username falsch sind und nicht, daß der Vorgang korrekt abgeschlossen wurde. ;-)

Zitat:

Zitat von Luckie
Aber wo liegt da der Unterschied zu meinem urspünglichem Code? :gruebel:

Inhaltlich könnte man meinen, es gebe keinen, aber ich werte GetLastError() in der Funktion aus, in der auch der CreateProcessWithLogonW() aufgerufen wird, das ist der einzige Unterschied. Das Problem tritt wie gesagt dadurch auf, daß intern SysFreeString() aufgerufen wird, was den Wert von GetLastError() beeinflusst (ich habe es getestet, es ist definitiv so), auch wenn dieses Verhalten mit keinem Wort irgendwo erwähnt wird.

Zitat:

Zitat von Luckie
Du hast übrigens Windows XP oder?

Ja, das sollte aber egal sein, da ich bei den anderen Methoden die gleichen Ergebnisse wie du erhalte.

Zitat:

Zitat von Luckie
Als ich es getrennt ausprobiert habe, also Anwnedung und CommandLine separate angegeben habe, hat er die Coomadline nicht verarbeitet, denn ich meinen, deinen Code hatte icfh auch schon mal ausprobiert. :roll:

Dann bastelst du halt die Commandline aus der Anwendung und den Parameter zusammen, dürfte nichts ändern. Das Problem liegt im String-Handling von Delphi (deswegen geht auch der C-Code, denn C macht so einen Blödsinn nicht) und nicht in der grundsätzlichen Verwendung von CreateProcessWithLogonW(). Was du aber probieren könntest ist, komplett mit PWideChars zu arbeiten, schließlich kriegst du aus den Controls über die API auch nur Pointer und keine delphi-like WideStrings. Mit anderen Worten: Wenn du das String-Handling von Delphi umgehst, brauchst du vielleicht nicht GetLastError() in der CreateProcessAsLogon()-Funktion aufrufen und zurückgeben, sondern es nach dem Aufruf auswerten.

Christian Seehase 23. Jan 2005 15:22

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Moin Thomas,

Zitat:

Zitat von tommie-lie
Das Problem tritt wie gesagt dadurch auf, daß intern SysFreeString() aufgerufen wird, was den Wert von GetLastError() beeinflusst (ich habe es getestet, es ist definitiv so), auch wenn dieses Verhalten mit keinem Wort irgendwo erwähnt wird.

Muss auch nicht.
Man sollte nur die Doku zu GetLastError berücksichtigen, bezüglich SysFreeString ist hier der letzte markierte Satz entscheidend.

Zitat:

Zitat von PSDK GetLastError - Remarks
You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.

Most functions that set the thread's last error code value set it when they fail; a few functions set it when they succeed. Function failure is typically indicated by a return value error code such as zero, NULL, or –1. Some functions call SetLastError under conditions of success; those cases are noted in each function's reference page.


tommie-lie 23. Jan 2005 16:36

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Hmm, habe ich tatsächlich nicht bemerkt, aber ändert nichts dran, denn:
Zitat:

Zitat von Christian Seehase
Zitat:

Zitat von PSDK GetLastError - Remarks
Some functions call SetLastError under conditions of success; those cases are noted in each function's reference page.


Zitat:

Zitat von PSDK SysFreeString - Komplett
SysFreeString
Deallocates a string allocated previously by SysAllocString, SysAllocStringByteLen, SysReAllocString, SysAllocStringLen, or SysReAllocStringLen.
Code:
VOID SysFreeString( 
  BSTR bstr
);
Parameter
bstr
Previously allocated BSTR. If bstr is NULL, the function simply returns.

Example
Code:
CStatBar::~CStatBar()
{
   SysFreeString(m_bstrMsg);
}
Requirements
Windows NT/2000: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Header: Declared in oleauto.h.
Library: Use oleaut32.lib.

Nix mit noted, soweit ich das sehe, oder soll man um die Ecke denken und das "not" in "note" finden? :gruebel: :mrgreen:

MathiasSimmack 23. Jan 2005 17:19

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Um die Ecke denken? Nein. Richtig übersetzen würde schon reichen. :mrgreen:

Zitat:

those cases are noted in each function's reference page.
bedeutet wohl, dass du (wenn überhaupt) was in der Funktion findest, die den Wert ändert. Also per Zufall, wenn du eine jener Funktionen brauchst und im SDK nachschlägst. ;)

tommie-lie 23. Jan 2005 17:27

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von MathiasSimmack
Zitat:

those cases are noted in each function's reference page.
bedeutet wohl, dass du (wenn überhaupt) was in der Funktion findest, die den Wert ändert. Also per Zufall, wenn du eine jener Funktionen brauchst und im SDK nachschlägst. ;)

Witzbold, ich weiß, was es übersetzt heißt, deswegen habe ich ja die Doku zu SysFreeString() gepostet, wie sie bei mir im PSDK Februar/2003 zu finden ist. Diese ändert den Wert von GetLastError(), sagt aber nichts davon, wie folgendes kleines Experiment beweist:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  c: PWideChar;
begin
  SysAllocStringLen(c, 10);
  SetLastError(123);
  ShowMessage(IntToStr(GetLastError)); // <-- '123'
  SysFreeString(c);
  ShowMessage(IntToStr(GetLastError)); // <-- '0'
end;

Luckie 24. Jan 2005 00:05

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
So ein Mist. So geht es jetzt:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString; var LastError: DWORD):
  LongBool;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, PWideChar(Application+' "'+CmdLine+'"'),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);

  if not result then
    MessageBox(hApp, PChar(SysErrorMessage(GetLastError)), APPNAME, MB_ICONSTOP);
end;
Auch mit Parametern. Aber das ist Mist, weil dann die aufrufende Routine die Fehlerbehandlung nicht machen kann. Und so was gefällt mir nicht. Wollte ich jetzt keine Fehlermeldung haben, müsste ich im Code rumfuschen. :roll:

Hier übrigens dein feuchter Händedruck:
Delphi-Quellcode:
{************************************************************}
{                                                            }
{                   RunAsUser - Version 1.1                  }
{                                                            }
{               Copyright (c) 2005 Michael Puff             }
{                                                            }
{  When I die I want 'Hello, world' carved on my headstone. }
{                                                            }
{************************************************************}

{*************************************************************

  History:

    - 2005-01-24 - 1.1
      GetLastError-Bug in CreateProcessAsLogon von tommie-lie
      gefunden:
      [url]http://www.delphipraxis.net/post306577.html#306577[/url]

*************************************************************}
;)

tommie-lie 24. Jan 2005 12:34

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von Luckie
So ein Mist. So geht es jetzt:
Delphi-Quellcode:
  result := CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, PWideChar(Application+' "'+CmdLine+'"'),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);

  if not result then
    MessageBox(hApp, PChar(SysErrorMessage(GetLastError)), APPNAME, MB_ICONSTOP);

Ja, so hatte ich es ja auch ausprobiert.

Zitat:

Zitat von Luckie
Aber das ist Mist, weil dann die aufrufende Routine die Fehlerbehandlung nicht machen kann.

Du könntest als Rückgabewert den Wert von GetLastError zurückgeben:
Delphi-Quellcode:
CreateProcessBlubb(...);
  result := GetLastError;
So würde zumindest ich es machen ;-)
Wenn CreateProcessWithLogonW() True zurückgegeben hat, müsste GetLastError() ja 0 sein. Und andernfalls hat es halt einen bestimmten Fehlerwert. In der Aufruffunktion überprüfst du dann das Ergebnis auf 0 und gibst entsprechend die Fehlermeldung passend zum Fehlercode aus, sofern die Funktion nicht 0 zurückliefert. Erfordert zwar eine weitere Variable, aber der Compiler sollte sie in ein Register packen können (wäre glaub' ich sogar schneller, weil nur ein Wert geladen wird :gruebel: Schwachsinn, stattdessen wird er vorher geladen, macht absolut keinen Unterschied, wenn der Compiler die Variable in ein Register packt).

Zitat:

Zitat von Luckie
Hier übrigens dein feuchter Händedruck:

Der trieft ja schon fast ;-)

Luckie 24. Jan 2005 14:51

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von tommie-lie
Zitat:

Zitat von Luckie
Aber das ist Mist, weil dann die aufrufende Routine die Fehlerbehandlung nicht machen kann.

Du könntest als Rückgabewert den Wert von GetLastError zurückgeben:
Delphi-Quellcode:
CreateProcessBlubb(...);
  result := GetLastError;
So würde zumindest ich es machen ;-)
Wenn CreateProcessWithLogonW() True zurückgegeben hat, müsste GetLastError() ja 0 sein. Und andernfalls hat es halt einen bestimmten Fehlerwert. In der Aufruffunktion überprüfst du dann

Habe ich auch probiert, wird auch 0 zurückgegeben, wenn der Aufruf fehlschlägt. Aber danke für die ausführliche Erläuterung wie man GetLastError auswertet. ;)

tommie-lie 24. Jan 2005 15:00

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von Luckie
Habe ich auch probiert, wird auch 0 zurückgegeben, wenn der Aufruf fehlschlägt.

Hmm? Ich denke das Problem haben wir gerade gelöst? :gruebel:
Naja, ich glaube du hast mich nur wie immer falsch verstanden ;-)

Zitat:

Zitat von Luckie
Aber danke für die ausführliche Erläuterung wie man GetLastError auswertet. ;)

Gern geschehen :mrgreen:

Luckie 24. Jan 2005 15:03

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Es funktioniert, wenn GetLastWrror direkt in der Routine ausgewertet wird, nicht aber wenn ich GetLastError zurückgeben lasse.

tommie-lie 24. Jan 2005 15:15

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Zitat:

Zitat von Luckie
Es funktioniert, wenn GetLastWrror direkt in der Routine ausgewertet wird, nicht aber wenn ich GetLastError zurückgeben lasse.

:gruebel:
Also bei mir geht das, auch wenn ich GetLastError() zurückgebe:
Delphi-Quellcode:
function CreateProcessAsLogon(const User, PW, Application, CmdLine: WideString):
  LongWord;
var
  si          : TStartupInfoW;
  pif         : TProcessInformation;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb := sizeof(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := 1;

  SetLastError(0);
  CreateProcessWithLogonW(PWideChar(User), nil, PWideChar(PW),
    LOGON_WITH_PROFILE, nil, PWideChar(Application+' "'+CmdLine+'"'),
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif);
  Result := GetLastError;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  lasterror: LongWord;
begin
  lasterror := CreateProcessAsLogon(Edit1.Text, Edit2.Text, Edit3.Text, Edit4.Text);
  if LastError <> 0 then
    MessageBox(Application.Handle, PChar(SysErrorMessage(LastError)), '', MB_ICONSTOP);
end;

Luckie 24. Jan 2005 15:31

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro
 
Verdammt, jetzt geht es bei mir auch. :roll:


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