Einzelnen Beitrag anzeigen

madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#8

AW: Programmstart nach Update

  Alt 18. Mär 2013, 15:33
Die Quelltexte von Innosetup habe ich durch forstet, konnte jedoch nichts sinnvolles finden, was zu meiner Lösung beitragen wollte.
Nach weiterer Recherche im WWW bin ich auf folgenden Artikel gestoßen:

http://blogs.msdn.com/b/aaron_margos...vated-app.aspx

Ich habe dann versucht das Ganze mal nach Delphi zu portieren und es scheint auf den ersten Blick zu funzen. Die Funktion macht nur Sinn bzw. ist nur ausführbar, wenn das Programm in dem sie aufrufen wird mit Admin-Rechten läuft. Hier der Delphi Quelltext:

Delphi-Quellcode:
interface

  function RunsAsDesktopUser(appFileName, appParams, currDir: WideString): Boolean;

uses
  ..., JwaWindows, JwsclToken, JwsclPrivileges, ...;

implementation

function RunsAsDesktopUser(appFileName, appParams, currDir: WideString): Boolean;
const
  dwTokenRights: DWORD = TOKEN_QUERY or TOKEN_ASSIGN_PRIMARY or TOKEN_DUPLICATE or TOKEN_ADJUST_DEFAULT or TOKEN_ADJUST_SESSIONID;
var
  hProcessToken, hShellProcess, hShellProcessToken, hPrimaryToken: THandle;
  hHWND: HWND;
  dwPID: DWORD;
  tkp: TOKEN_PRIVILEGES;
  startupInfo: TSTARTUPINFOW;
  processInfo: TPROCESSINFORMATION;
  lastError: String;
  pAppParams: PWideChar;
begin
  Result := False;
  hProcessToken := THandle(nil); hShellProcess := THandle(nil); hShellProcessToken := THandle(nil); hPrimaryToken := THandle(nil);
  dwPID := 0; lastError := EmptyStr;
  ZeroMemory(@startupInfo, sizeof(startupInfo));
  startupInfo.cb := sizeof(startupInfo);
  startupInfo.lpDesktop := 'winsta0\default';
  startupInfo.dwFlags := STARTF_USESHOWWINDOW;
  startupInfo.wShowWindow := SW_SHOWDEFAULT;
  try
    if (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hProcessToken)) then
    begin
      try
        tkp.PrivilegeCount := 1;
        if (LookupPrivilegeValue(nil, SE_INCREASE_QUOTA_NAME, tkp.Privileges[0].Luid)) then
        begin
          tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
          AdjustTokenPrivileges(hProcessToken, false, @tkp, SizeOf(TOKEN_PRIVILEGES), nil, nil);
          if (GetLastError <> ERROR_SUCCESS) then
          begin
            lastError := 'AdjustTokenPrivileges: ' + SysErrorMessage(GetLastError);
            Result := False;
            Exit;
          end;
        end;
      finally
        CloseHandle(hProcessToken);
      end;
    end else
    begin
      lastError := 'OpenProcessToken: ' + SysErrorMessage(GetLastError);
      Result := false;
      Exit;
    end;

    hHWND := GetShellWindow;
    if (hHWND = 0) then
    begin
      lastError := 'GetShellWindow: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    GetWindowThreadProcessId(hHWND, @dwPID);
    if (hHWND = 0) then
    begin
      lastError := 'GetWindowThreadProcessId: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    hShellProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, dwPID);
    if (hHWND = 0) then
    begin
      lastError := 'OpenProcess: ' + SysErrorMessage(GetLastError);
      Result := False;
      Exit;
    end;

    Result := OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, hShellProcessToken);
    if (not Result) then
    begin
      lastError := 'OpenProcessToken: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    Result := DuplicateTokenEx(hShellProcessToken, dwTokenRights, nil, SecurityImpersonation, TokenPrimary, hPrimaryToken);
    if (not Result) then
    begin
      lastError := 'DuplicateTokenEx: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    if (appParams = EmptyWideStr) then
      pAppParams := nil
    else
      pAppParams := PWideChar(appFileName + ' ' + appParams);
    Result := CreateProcessWithTokenW(hPrimaryToken, 0, PWideChar(appFileName), pAppParams, 0, nil, PWideChar(currDir),   @startupInfo, @processInfo);
    if (not Result) then
    begin
      lastError := 'CreateProcessWithTokenW: ' + SysErrorMessage(GetLastError);
      Exit;
    end;

    Result := True;
  finally
    CloseHandle(hShellProcessToken);
    CloseHandle(hPrimaryToken);
    CloseHandle(hShellProcess);
    if (not Result) then
      ShowMessage(lastError);
  end;
end;
Grüße.

madas

PS: Falls es Verbesserungsvorschläge gibt nur raus damit.

Geändert von madas (18. Mär 2013 um 15:35 Uhr)
  Mit Zitat antworten Zitat