2012-03-26 3 views
2

I einen kleinen Service schreiben müssen, die eine Anwendung läuft (mit gui, zB calc.exe) auf dem Anmeldebild- .Ausführen eines Prozesses (mit GUI) unter Windows XP Logon Screen (.NET/PInvoke)

Ich fand diese Frage bereits (und Antwort): Running a process at the Windows 7 Welcome Screen

bitte den Code-Kommentare lesen, wenn Sie nicht verstehen, wie das funktioniert:

 // grab the winlogon process 
     Process winLogon = null; 
     foreach (Process p in Process.GetProcesses()) 
     { 
      if (p.ProcessName.Contains("winlogon")) 
      { 
       winLogon = p; 
       break; 
      } 
     } 
     // grab the winlogon's token 
     IntPtr userToken = IntPtr.Zero; 
     if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, out userToken)) 
     { 
      log("ERROR: OpenProcessToken returned false - " + Marshal.GetLastWin32Error()); 
     } 

     // create a new token 
     IntPtr newToken = IntPtr.Zero; 
     SECURITY_ATTRIBUTES tokenAttributes = new SECURITY_ATTRIBUTES(); 
     tokenAttributes.nLength = Marshal.SizeOf(tokenAttributes); 
     SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES(); 
     threadAttributes.nLength = Marshal.SizeOf(threadAttributes); 
     // duplicate the winlogon token to the new token 
     if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 
      TOKEN_TYPE.TokenImpersonation, out newToken)) 
     { 
      log("ERROR: DuplicateTokenEx returned false - " + Marshal.GetLastWin32Error()); 
     } 
     TOKEN_PRIVILEGES tokPrivs = new TOKEN_PRIVILEGES(); 
     tokPrivs.PrivilegeCount = 1; 
     LUID seDebugNameValue = new LUID(); 
     if (!LookupPrivilegeValue(null, SE_DEBUG_NAME, out seDebugNameValue)) 
     { 
      log("ERROR: LookupPrivilegeValue returned false - " + Marshal.GetLastWin32Error()); 
     } 
     tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1]; 
     tokPrivs.Privileges[0].Luid = seDebugNameValue; 
     tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
     // escalate the new token's privileges 
     if (!AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero)) 
     { 
      log("ERROR: AdjustTokenPrivileges returned false - " + Marshal.GetLastWin32Error()); 
     } 
     PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 
     STARTUPINFO si = new STARTUPINFO(); 
     si.cb = Marshal.SizeOf(si); 
     si.lpDesktop = "Winsta0\\Winlogon"; 
     // start the process using the new token 
     if (!CreateProcessAsUser(newToken, "calc.exe", null, ref tokenAttributes, ref threadAttributes, 
      true, (uint)CreateProcessFlags.CREATE_NEW_CONSOLE | (uint)CreateProcessFlags.INHERIT_CALLER_PRIORITY, IntPtr.Zero, 
      "C:\\Windows\\System32", ref si, out pi)) 
     { 
      log("ERROR: CreateProcessAsUser returned false - " + Marshal.GetLastWin32Error()); 
     } 

     Process _p = Process.GetProcessById(pi.dwProcessId); 
     if (_p != null) 
     { 
      log("Process " + _p.Id + " Name " + _p.ProcessName); 
     } 
     else 
     { 
      log("Process not found"); 
     } 

Es ist mit Windows funktioniert 7. Mit XP Ich bekomme Fehler 1349 ERROR_BAD_TOKEN_TYPE beim Aufruf CreateProcessAsUser (MSDN: Der Typ des Token ist ungeeignet für den versuchten Einsatz.).

Wie dies in Windows XP zu realisieren? Es muss nicht der Code von oben sein, aber es sollte als Dienst funktionieren (mit System-Account?).

Vielen Dank für Ihre Unterstützung Fluxer

Antwort

3

Dies ist definitiv mit Privileg Probleme (Windows Vista und 7 haben bemerkenswerte Veränderungen in Sicherheit) zu tun hat. Anstatt zu versuchen, Token von winlogon.exe zu bekommen und es imitieren, versuchen Benutzertoken wie dies über WTSQueryUserToken bekommen:

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken); 

Ersetzen Sie die Openlinie, die verwendet wird, um das Token mit der obigen Aussage zu erhalten.

Ihr neuer Code sollte wie folgt sein:

//  if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | //TOKEN_DUPLICATE, out userToken)) 
//  { 
//   log("ERROR: OpenProcessToken returned false - " + //Marshal.GetLastWin32Error()); 
//  } 

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken); 

Sie Ihre DLL-Import wie folgt aus:

[DllImport("Kernel32.dll", SetLastError = true)] 
[return:MarshalAs(UnmanagedType.U4)] 
public static extern int WTSGetActiveConsoleSessionId (); 

Sie müssen nur den Teil ersetze ich mit diesem Code als Kommentar gekennzeichnet.

+0

Danke für Ihre Antwort! Was soll ich mit Token '& newToken' machen? benutze es einfach für 'CreateNewProcessAsUser'? – MariusK

+0

Ich werde meine Antwort bearbeiten. –

+0

danke für deine Bearbeitung. Ich ersetzte den Code, aber immer noch Fehlercode 1349 beim Aufruf von 'CreateProcessAsUser' .. – MariusK

Verwandte Themen