2012-09-26 25 views
1

我想號召下另一個用戶從其他Windows應用程序中執行應用程式帳戶使用此代碼:CreateProcessAsUser如何添加特權?

procedure TForm1.Button3Click(Sender: TObject); 
var 
    userName: string; 
    password: string; 
    domain: string; 
    path: string; 
    logonok: boolean; 
    impok: boolean; 
    hUserToken: THandle; 
    ProcessCreatedOK: Boolean; 
    startupInfo: TStartupInfo; 
    processInfo: TProcessInformation; 
    err: DWORD; 
begin 
    username := 'theusername'; 
    password := 'thepassword'; 
    domain := ''; 
    Path := 'myapp.exe'; 

    LogonOK := LogonUser(PWideChar(username), PWideChar(domain), PWideChar(password), 
     LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hUserToken); 

    if LogonOK then 
    begin 
     impOK := ImpersonateLoggedOnUser(hUserToken); 

     if impok then 
     begin 
     FillChar(startupInfo, SizeOf(startupInfo), 0); 
     startupInfo.CB := SizeOf(startupinfo); 
     startupInfo.dwFlags := STARTF_USESHOWWINDOW; 
     startupinfo.wShowWindow := SW_SHOWNORMAL; 

     NewState.PrivilegeCount := 1; 
     res := LookupPrivilegeValue(
      nil, 
      SE_ASSIGNPRIMARYTOKEN_NAME, 
      NewState.Privileges[0].Luid); 
      Win32Check(res); 

     NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; 
     res := AdjustTokenPrivileges(
      hUserToken, 
      False, 
      NewState, 
      SizeOf(NewState), 
      nil, 
      returnLength); 
     Win32Check(res); 

     NewState.PrivilegeCount := 1; 
     res := LookupPrivilegeValue(
      nil, 
      SE_INCREASE_QUOTA_NAME, 
      NewState.Privileges[0].Luid); 
      Win32Check(res); 

     NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; 
     res := AdjustTokenPrivileges(
      hUserToken, 
      False, 
      NewState, 
      SizeOf(NewState), 
      nil, 
      returnLength); 
     Win32Check(res); 

     ProcessCreatedOK := CreateProcessAsUser(
      hUserToken, 
      nil, 
      PChar(path), 
      nil, nil, 
      false, 
      CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, 
      startupInfo, processInfo); 

     if GetLastError <> 0 then 
     begin 
      err := GetlastError; 
      ShowMessage(inttostr(err) + ' ' + SysErrorMessage(err)); 
     end; 
     end; 
    end; 

我得到一個1314錯誤「A所需的特權不保留由客戶端」。

現在從一些挖掘我可以看到,我需要應用一些特權模擬帳戶:SE_ASSIGNPRIMARYTOKEN_NAME和SE_INCREASE_QUOTA_NAME?

有沒有人有如何做到這一點的建議?

我已經看到了這個Stackoverflow answer中給出的JCL示例,但是我遇到了與帳戶權限有關的類似問題。

我不想使用CreateProcessWithLogonW - 我可以解釋爲什麼要求。

回答

5

使用AdjustTokenPrivileges。首先,撥打LookupPrivilegeValue以獲取所需特權的ID,然後設置它們。下面是一個適合我使用的C代碼示例:

var 
    NewState: TTokenPrivileges; 

NewState.PrivilegeCount := 1; 
res := LookupPrivilegeValue(nil, Se_AssignPrimaryToken_Name, 
    @NewState.Privileges[0].Luid); 
Win32Check(res); 

NewState.Privileges[0].Attributes := Se_Privilege_Enabled; 
res := AdjustTokenPrivileges(hUserToken, False, @NewState, 
    SizeOf(NewState), nil, nil); 
Win32Check(res); 
+0

謝謝你。我已經用你的例子編輯了上面的代碼,但不幸的是我仍然得到了同樣的錯誤 - 1314「所需的特權不是由客戶端持有的」。也許還有其他特權要求? – Mattl

+0

也許吧。聽起來像是值得調查的事情,但我想我已經回答了你問的問題,即如何授予新的權限。在問題得到解答後,請不要改變問題的性質。我想你需要提出一個新的問題:「當操作系統表示不需要特權時,我如何知道哪一個?」 –

+0

在這種情況下,實際上並不需要AdjustTokenPrivileges,如下所示:「如果必要的權限尚未啓用,則CreateProcessAsUser會在調用期間啓用它們。」 OP的問題可能是他根本沒有這些特權,而不是他們沒有啓用。 –