Delphi-PRAXiS
Seite 3 von 4     123 4      

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 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;


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:47 Uhr.
Seite 3 von 4     123 4      

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