Einzelnen Beitrag anzeigen

Benutzerbild von Memnarch
Memnarch

Registriert seit: 24. Sep 2010
737 Beiträge
 
#7

AW: CreateProcessWithTokenW ERROR_DEVICE_NO_RESOURCES

  Alt 2. Sep 2013, 14:08
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
Da man Trunc nicht auf einen Integer anwenden kann, muss dieser zuerst in eine Float kopiert werden

Geändert von Memnarch ( 2. Sep 2013 um 16:28 Uhr)
  Mit Zitat antworten Zitat