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 CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES (https://www.delphipraxis.net/176365-createprocesswithtokenw-error_device_no_resources.html)

Memnarch 30. Aug 2013 15:51

CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Hallo,
Ich habe nen verzwicktes Problem und bisher hat nichts geholfen.

Was ich erreichen möchte(oder besser gesagt MUSS, ist so vorgegeben ;) )

Ich möchte ein programm mithilfe von zuvor angegebenen Logindaten unter einem anderen Benutzer ausführen. Dabei kann dies entweder aus einem Nutzerkontext oder Servicekontext pasieren.

Ich bearbeite gerade den Usecase das ich versuche von NutzerA mit NutzerB ein Programm auszuführen.
Bei ausführen mit CreateProcessWithTokenW wird das Programm gestartet(CreateProcessWithTokenW meldet erfolg), windows wirft aber sofort die im Titel erwähnte Fehlermeldung(Code 0.x142)

das wäre der Rohbau der aktuell den Fehler wirft:
(Dummycode)
Delphi-Quellcode:
  ZeroMemory(@Startup, SizeOf(Startup));
  Startup.cb := SizeOf(Startup);
  ZeroMemory(@Process, SizeOf(Process));
  LogonUserW(Name, Domäne,
    Passwort, LOGON32_LOGON_INTERACTIVE,
    LOGON32_PROVIDER_DEFAULT, Token);
  CreateEnvironmentBlock(@Umgebungsblock, Token, False);
  CreateProcessWithTokenW(Token, LOGON_WITH_PROFILE,
            nil, @PfadZurExe[1],
            CREATE_NEW_CONSOLE or CREATE_UNICODE_ENVIRONMENT or CREATE_DEFAULT_ERROR_MODE,
            Umgebungsblock, nil, @Startup, @Process);
Jemand eine Idee?

MFG
Memnarch

Zacherl 30. Aug 2013 18:11

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Habe ich das richtig verstanden: Der Prozess wird erzeugt und CreateProcessWithToken meldet TRUE, aber GetLastError ist ERROR_DEVICE_NO_RESOURCES? Bei Erfolg eines API Aufrufs ist GetLastError nicht eindeutig definiert, von daher würde ich mir keine Gedanken machen, sofern die Process Creation ansich funktioniert.

Ansonsten musst du beachten, dass dein Prozess diverse Privilegien benötigt. Hier der Auszug aus dem MSDN:
Zitat:

The process that calls CreateProcessWithTokenW must have the SE_IMPERSONATE_NAME privilege. If this function fails with ERROR_PRIVILEGE_NOT_HELD (1314), use the CreateProcessAsUser or CreateProcessWithLogonW function instead. Typically, the process that calls CreateProcessAsUser must have the SE_INCREASE_QUOTA_NAME privilege and may require the SE_ASSIGNPRIMARYTOKEN_NAME privilege if the token is not assignable. CreateProcessWithLogonW requires no special privileges, but the specified user account must be allowed to log on interactively. Generally, it is best to use CreateProcessWithLogonW to create a process with alternate credentials.
Dort wird auch empfohlen, eher CreateProcessWithLogon zu verwenden.

Memnarch 31. Aug 2013 02:16

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Der Fehlercode wird von Windows in einem Error Dialog angezeigt. Ist also kein GetLastError.

CreateProcessWithLogon ist keine Option, in einem Service ist es nicht verfügbar :( (es wäre schöner eine Lösung anstatt mehrere zu haben).
AH bei dir steht das SE_IMPERSONATE_NAME für CreateProcessWithToken benötigt wird. Das bekomm ich sicherlich noch hin(wie ich die Privilegien setzen kann habe ich schon raus).

Was immer funktioniert hat war LOGON32_LOGON_BATCH bei LogoinUser. Dann liefen die Programme, aber halt ohne Fenster^^

Zacherl 31. Aug 2013 11:20

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Mit dem SE_IMPERSONATE_NAME musst du aufpassen. Das Privileg steht dir standardmäßig nur auf Administratorkonten zur Verfügung.

Da tatsächlich eine Fehlermeldung erscheint, CreateProcessWithToken aber erfolgreich ist, vermute ich, dass die Meldung im Prozess geschmissen wird, den du versuchst zu starten. Hast du mal versucht einfach nur notepad.exe oder etwas Vergleichbares zu starten?

Memnarch 31. Aug 2013 12:21

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Genau die tun das ;) (Notepad, MSPaint, ALLE, auch selbst geschriebene kleine programme)

Die Meldung die ich bekomme heißt soviel wie, dass benötigte Dateien nicht gefunden wurden. Das macht aber keinen Sinn. Hat der irgendwie keine Umgebungsvariablen zum suchen der DLLs oder sontigen sachen o.O?

Zacherl 1. Sep 2013 17:32

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Du könntest es mal mit CreateProcessAsUser probieren. Das funktioniert auf jeden Fall auch aus einem Service heraus. Hatte folgenden Code verwenden, um einen Prozess im Kontext des aktuell eingeloggten Benutzers zu erstellen (mit UAC Elevation):
http://www.delphipraxis.net/160355-s...t-starten.html

Memnarch 2. Sep 2013 14:08

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES
 
Inzwischen habe ich es mit CreateProcessWithTokenW hinbekommen(und dann festgestellt das es ja nur auf Vista und aufwärts geht(XP sollte noch gehen -.-) UND die StdOut/In/Error handle nicht korrekt unterstützt wen der Prozess 32bit ist und auf einem 64bit OS ausgeführt wird).

Komischerweise, kann ich den token den ich in CreateProcessWithTokenW genutzt habe nicht in CreateProcessAsUser verwenden. Und das versteh ich nicht. wenn ich zum einloggen meinen eigenen account verwende, hat er angeblich nicht die korrekten rechte. wenn ich mir einfach den Token meines laufenden Prozesses hole(der ich auch bin) dan gehts? Was ist dann der Unterschied zwischen Mir(per LogonUser) und Mir(bestehender Prozesstoken)?

Habe mir deinen Source durchgelesen. Es für mich selbst auszuführen klappt in meinem kleinen Usecase auch so, aber wie soll es in bezug auf Logonuser gehen? Die Tokens die mir das ausspuckt scheinen(auch nach DublicateTokenEx mit entsprechenden Flags) nicht brauchbar.

Das hier ist die CreateProcasUserEx aus JclMiscel. Die habe ich mir kopiert und nutze am ende CreateProcessWithTokenW anstatt CreateProcessAsUser(Letzteres geht auch hier wegen den Rechten nicht, allerdings brauch ich es ja nun doch so, weil es erst ab Vista geht -.-)

hier der Auszug aus der JCLMiscl.pas damit nicht alles gegooglet werden muss ;)

Delphi-Quellcode:
{ TODO -cTest : Check for Win9x }
procedure CreateProcAsUserEx(const UserDomain, UserName, Password, CommandLine: string;
  const Environment: PChar);
const
  // default values for window stations and desktops
  CreateProcDEFWINSTATION = 'WinSta0';
  CreateProcDEFDESKTOP   = 'Default';
  // CreateProcDOMUSERSEP   = '\';
var
  ConsoleTitle: string;
  Help: string;
  WinStaName: string;
  DesktopName: string;
  hUserToken: THandle;
  hWindowStation: HWINSTA;
  hDesktop: HDESK;
  StartUpInfo: TStartUpInfo;
  ProcInfo: TProcessInformation;
begin

  // Step 1: check for the correct OS version
  CheckOSVersion;

  // Step 2: logon as the specified user
  hUserToken := 0;
  if not LogonUser(PChar(UserName), PChar(UserDomain), PChar(Password),
    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hUserToken) then
  begin
    case GetLastError of
      ERROR_PRIVILEGE_NOT_HELD:
        raise EJclCreateProcessError.CreateResFmt(@RsCreateProcPrivilegeMissing,
          [GetPrivilegeDisplayName(SE_TCB_NAME), SE_TCB_NAME]);
      ERROR_LOGON_FAILURE:
        raise EJclCreateProcessError.CreateRes(@RsCreateProcLogonUserError);
      ERROR_ACCESS_DENIED:
        raise EJclCreateProcessError.CreateRes(@RsCreateProcAccessDenied);
    else
      raise EJclCreateProcessError.CreateRes(@RsCreateProcLogonFailed);
    end;
  end;

  // Step 3: give the new user access to the current WindowStation and Desktop
  hWindowStation:= GetProcessWindowStation;
  WinStaName := GetUserObjectName(hWindowStation);
  if WinStaName = '' then
    WinStaName := CreateProcDEFWINSTATION;

  if not SetUserObjectFullAccess(hWindowStation) then
  begin
    CloseHandle(hUserToken);
    raise EJclCreateProcessError.CreateResFmt(@RsCreateProcSetStationSecurityError, [WinStaName]);
  end;

  hDesktop := GetThreadDesktop(GetCurrentThreadId);
  DesktopName := GetUserObjectName(hDesktop);
  if DesktopName = '' then
    DesktopName := CreateProcDEFDESKTOP;

  if not SetUserObjectFullAccess(hDesktop) then
  begin
    CloseHandle(hUserToken);
    raise EJclCreateProcessError.CreateResFmt(@RsCreateProcSetDesktopSecurityError, [DesktopName]);
  end;

  // Step 4: set the startup info for the new process
  ConsoleTitle := UserDomain + UserName;
  ResetMemory(StartUpInfo, SizeOf(StartUpInfo));
  with StartUpInfo do
  begin
    cb:= SizeOf(StartUpInfo);
    lpTitle:= PChar(ConsoleTitle);
    Help := WinStaName + '\' + DeskTopName;
    lpDesktop:= PChar(Help);
  end;

  // Step 5: create the child process
  if not CreateProcessAsUser(hUserToken, nil, PChar(CommandLine), nil, nil,
    False, CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP, Environment, nil,
    {$IFDEF FPC}
    @StartUpInfo, @ProcInfo) then
    {$ELSE ~FPC}
    StartUpInfo, ProcInfo) then
    {$ENDIF ~FPC}
  begin
    case GetLastError of
      ERROR_PRIVILEGE_NOT_HELD:
        raise EJclCreateProcessError.CreateResFmt(@RsCreateProcPrivilegesMissing,
          [GetPrivilegeDisplayName(SE_ASSIGNPRIMARYTOKEN_NAME), SE_ASSIGNPRIMARYTOKEN_NAME,
           GetPrivilegeDisplayName(SE_INCREASE_QUOTA_NAME), SE_INCREASE_QUOTA_NAME]);
      ERROR_FILE_NOT_FOUND:
        raise EJclCreateProcessError.CreateResFmt(@RsCreateProcCommandNotFound, [CommandLine]);
      else
        raise EJclCreateProcessError.CreateRes(@RsCreateProcFailed);
    end;
  end;

  // clean up
  CloseWindowStation(hWindowStation);
  CloseDesktop(hDesktop);
  CloseHandle(hUserToken);

  // if this code should be called although there has
  // been an exception during invocation of CreateProcessAsUser,
  // it will quite surely fail. you should make sure this doesn't happen.
  // (it shouldn't happen due to the use of exceptions in the above lines)
  CloseHandle(ProcInfo.hThread);
  CloseHandle(ProcInfo.hProcess);
end;
EDIT: also ich werde jetzt wohl doch 2 gleisig fahren müssen. CreateProcessAsUser vom Service und CreateProcessWithLogonW vom Benutzer


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