AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Rückgabewert von CreateProcessWithLogonW und GetLastError
Thema durchsuchen
Ansicht
Themen-Optionen

Rückgabewert von CreateProcessWithLogonW und GetLastError

Ein Thema von Luckie · begonnen am 19. Jan 2005 · letzter Beitrag vom 24. Jan 2005
Antwort Antwort
Seite 3 von 4     123 4      
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#21

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 22. Jan 2005, 19:05
Die Exe schon, leider habe ich es noch nicht geschafft es zu kompilieren.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#22

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 22. Jan 2005, 19:24
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#23

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 22. Jan 2005, 20:38
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öööö
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#24

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 13:20
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? 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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#25

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 13:41
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...
Manuel Pöter
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#26

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 14:27
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 von Luckie:
Aber wo liegt da der Unterschied zu meinem urspünglichem Code?
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 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 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.
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.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#27

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 15:22
Moin Thomas,

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 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.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#28

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 16:36
Hmm, habe ich tatsächlich nicht bemerkt, aber ändert nichts dran, denn:
Zitat von Christian Seehase:
Zitat von PSDK GetLastError - Remarks:
Some functions call SetLastError under conditions of success; those cases are noted in each function's reference page.
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?
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#29

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 17:19
Um die Ecke denken? Nein. Richtig übersetzen würde schon reichen.

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.
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#30

Re: Rückgabewert von CreateProcessWithLogonW und GetLastErro

  Alt 23. Jan 2005, 17:27
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;
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:11 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