AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Starting a Interactive Process in Vista using TService
Thema durchsuchen
Ansicht
Themen-Optionen

Starting a Interactive Process in Vista using TService

Ein Thema von FaNIX · begonnen am 9. Okt 2007 · letzter Beitrag vom 9. Okt 2007
Antwort Antwort
Seite 1 von 3  1 23      
FaNIX

Registriert seit: 8. Okt 2007
36 Beiträge
 
#1

Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 08:13
Hallo,

I hope it's not a problem if i type in English. Im have a TService application, running on windows vista. All i want to do is create a process(lets say notepad.exe) and display that on the logged in users desktop.

As most of you know, in Vista Services run on a completely different environment, which is non interactive to the user, so basically all processes started inside the service will be invisible to the user.

After reading A LOT of forums and reading alot about this, i saw a few examples using LSALogonUser and CreateProcessAsUser... But i couldnt get any of them to work... Ive downloaded some source form this forum, pasted that in a service, but it still doesnt work... It does work when i paste it in a Normal Win32 VCL Application, then the process starts correctly, so it's clear that something is wrong, here is my code, please any advice would be much appreciated.

Delphi-Quellcode:

unit uMain;

interface

uses
  JwaWindows,SvcMgr, SysUtils,
  JwaWinType, JwaWinBase, JwaWinNT, JwaNtSecApi, JwaNTStatus,
  JwaNative, JwaUserEnv, JwaWinSta, JwaWtsApi32, Dialogs, uWinStation;

const
  DNLEN = 15;
  UNLEN = 256;

type
  TAuthInfo = record
    Header: MSV1_0_INTERACTIVE_LOGON;
    Domain: array[0..DNLEN] of WideChar;
    User: array[0..UNLEN] of WideChar;
    Password: array[0..UNLEN] of WideChar;
  end;

type
  TService1 = class(TService)
    procedure ServiceStart(Sender: TService; var Started: Boolean);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  Service1: TService1;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

Procedure LsaInitUnicodeString(Var LsaString: TLsaUnicodeString; Const WS:
  WideString);
Begin
  FillChar(LsaString, SizeOf(LsaString), 0);
  If WS <> 'Then
  Begin
    LsaString.Length:=Length(WS) * SizeOf(WideChar);
    LsaString.MaximumLength:=LsaString.Length + SizeOf(WideChar);
    LsaString.Buffer:=PWideChar(WS);
  End;
End;

procedure GetLogonSID(hToken: THandle; var ppsid: PSID);
var dwLength: DWORD;
    ptg : ^TOKEN_GROUPS;
    i : integer;
begin
  dwLength := 0;
  ptg := nil;

  try
    // Get required buffer size and allocate the TOKEN_GROUPS buffer.
    if not GetTokenInformation(hToken, TokenGroups, ptg, 0, dwLength) then
    begin
      if GetLastError <> ERROR_INSUFFICIENT_BUFFER then
      begin
        ShowMessage('GetTokenInformation failed');
        Exit;
      end;

      ptg := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
      if ptg = nil then
      begin
        Exit;
      end;

      // Get the token group information from the access token.
      if not GetTokenInformation(hToken, TokenGroups, ptg, dwLength, dwLength) then
      begin
        Exit;
      end;

      // Loop through the groups to find the logon SID.
      for i := 0 to ptg.GroupCount-1 do
      begin
       if ptg.Groups[i].Attributes and SE_GROUP_LOGON_ID = SE_GROUP_LOGON_ID then
       begin
         // Found the logon SID; make a copy of it.
         dwLength := GetLengthSid(ptg.Groups[i].Sid);
         ppsid := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength);
         if ppsid = nil then
         begin
           Exit;
         end;
         if not CopySid(dwLength, ppsid, ptg.Groups[i].Sid) then
         begin
// raise exception.Create(Format('CopySid: %s', [SysErrorMessage(GetLastError)]));
           HeapFree(GetProcessHeap, 0, ppsid);
           Exit;
         end;

         Break;
        end;
      end;
    end;
  finally
    // Free the buffer for the token groups.
    if ptg <> nil then
    begin
      HeapFree(GetProcessHeap, 0, ptg);
    end;
  end;
end;
procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
var hToken: THandle;
  si: _STARTUPINFOA;
  pi: _PROCESS_INFORMATION;
  Res: NTSTATUS;
  hLSA: THandle;
  LSAString: _LSA_STRING;
  AuthenticationPackage: ULONG;
  AuthentificationInfo: TAuthInfo;
  pProfileBuffer: Pointer;
  LogonID: JwaWinType.LUID;
  hLsaToken: THandle;
  QuotaLimits: QUOTA_LIMITS;
  SubStatus: Integer;
  wsDomain: WideString;
  wsUser: WideString;
  wsPwd: WideString;
  TokenSource: TOKEN_SOURCE;
  dwReturnLength: ULONG;
  Mode: LSA_OPERATIONAL_MODE;
  pGroups: PTOKEN_GROUPS;
  AdminSid: PSid;
  dwSizeSid: Cardinal;
  dwSizeDomain: Cardinal;
  SidType: TSidNameUse;
  Domain: String;
  MaxGroups: Integer;
  bRes: Longbool;
begin
  ZeroMemory(@si, SizeOf(si));
  si.cb := SizeOf(si);
  si.lpDesktop := nil;

  if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then
  begin
    RtlInitString(@LsaString, PCSZ(PChar('Winlogon')));
    Res := LsaRegisterLogonProcess(LsaString, hLSA, @Mode);
    if Failed(Res) then
    begin
      ShowMessageFmt('LsaRegisterLogonProcess: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    RtlInitString(@LsaString,PCSZ(PChar(MSV1_0_PACKAGE_NAME)));

    Res := LsaLookupAuthenticationPackage(hLSA, LSAString, AuthenticationPackage);
    if Failed(Res) then
    begin
      ShowMessageFmt('LookupAuthPackage: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    TokenSource.SourceName := '**ANON**';
    if not AllocateLocallyUniqueId(TokenSource.SourceIdentifier) then
    begin
      ShowMessageFmt('AllocLocUniqueId: %s', [SysErrorMessage(GetLastError)]);
    end;

    // The number of TOKEN_GROUPS we're going to insert
    MaxGroups := 2;

    // Reserve memory for MaxGroups numbur of PTOKEN_GROUPS
    pGroups := PTOKEN_GROUPS(GlobalAlloc(GPTR, sizeof(_SID_AND_ATTRIBUTES) * MaxGroups));
    pGroups^.GroupCount := MaxGroups;

    // Get the Logon Sid and it to the LocalGroups parameter of LsaLogonUser
    // The Logon Sid has the form S-1-5-5-XXXXXXXX-YYYYYYYY
    // We need it to obtain access to the user's desktop
    GetLogonSid(hToken, pGroups^.Groups[0].Sid);
    pGroups^.Groups[0].Attributes := SE_GROUP_MANDATORY or
                                     SE_GROUP_ENABLED or
                                     SE_GROUP_ENABLED_BY_DEFAULT or
                                     SE_GROUP_LOGON_ID;

    // Now get the Administrator's SID
    dwSizeSid := 0;
    dwSizeDomain := 0;
    bRes := LookupAccountName(nil, 'Administrator', nil, dwSizeSid, nil, dwSizeDomain, SidType);

    if (not bRes) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
    begin
      // Reserve memory
      AdminSid := AllocMem(dwSizeSid);
      SetLength(Domain, dwSizeDomain);

      // Lookup Sid from Accountname
      // Assuming that the Admin account has not been renamed!
      bRes := LookUpAccountName(nil, 'Administrator', AdminSid, dwSizeSid, PChar(Domain), dwSizeDomain, SidType);
      if not bRes then
      begin
        // Cleanup
        FreeMem(AdminSid);
        AdminSid := nil;
      end;
    end
    else begin
      RaiseLastOSError;
    end;

    ShowMessageFmt('Administrator Sid: %s, Domain: %s', [SidToStr(AdminSid), Domain]);

    // Add the Administrator's sid to pGroups
    pGroups^.Groups[MaxGroups -1].Sid := AdminSid;
    pGroups^.Groups[MaxGroups -1].Attributes := SE_GROUP_MANDATORY or
                                                SE_GROUP_ENABLED or
                                                SE_GROUP_ENABLED_BY_DEFAULT or
                                                SE_GROUP_LOGON_ID;

    // Fill the AuthentificationInfo structure
    // First convert the EDITs to WideString
    wsDomain:= '';
    wsUser:= 'username';
    wsPwd:= 'password';

    // Fill with zeros
    RtlZeroMemory(@AuthentificationInfo, sizeof(AuthentificationInfo));
    AuthentificationInfo.Header.MessageType := MsV1_0InteractiveLogon;
    // AuthentificationInfo.Header.MessageType := MsV1_0NetworkLogon;

    // Copy the strings into a buffer.
    RtlCopyMemory(@AuthentificationInfo.Domain, @wsDomain[1], sizeof(WideChar) * Length(wsDomain));
    RtlCopyMemory(@AuthentificationInfo.User, @wsUser[1], sizeof(WideChar) * Length(wsUser));
    RtlCopyMemory(@AuthentificationInfo.Password, @wsPwd[1], sizeof(WideChar) * Length(wsPwd));

    // Now set which buffer we want to use (the arrays of WideChar from the struct)
    RtlInitUnicodeString(@AuthentificationInfo.Header.LogonDomainName, AuthentificationInfo.Domain);
    RtlInitUnicodeString(@AuthentificationInfo.Header.UserName, AuthentificationInfo.User);
    RtlInitUnicodeString(@AuthentificationInfo.Header.Password, AuthentificationInfo.Password);

    Res := JwaNtSecApi.LsaLogonUser(hLSA,
                                    LsaString,
                                    RemoteInteractive,
                                    AuthenticationPackage,
                                    @AuthentificationInfo,
                                    SizeOf(AuthentificationInfo),
                                    pGroups,
                                    @TokenSource,
                                    pProfileBuffer,
                                    dwReturnLength,
                                    LogonID,
                                    hLSAToken,
                                    QuotaLimits,
                                    SubStatus);

    if Failed(Res) then
    begin
      ShowMessageFmt('LsaLogonUser: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]);
    end;

    ZeroMemory(@si, SizeOf(si));
    si.cb := SizeOf(si);
    si.lpReserved := nil;
    si.lpDesktop := nil;
    si.dwFlags := STARTF_USESHOWWINDOW;;
    si.wShowWindow := SW_SHOWNORMAL;

    if not CreateProcessAsUser(hLsaToken, nil, PChar('notepad.exe'), nil, nil, False,
                               NORMAL_PRIORITY_CLASS or CREATE_NEW_PROCESS_GROUP,
                               nil, nil, &si, &pi) then
    begin
      ShowMessageFmt('CreateProcessAsUser: %s', [SysErrorMessage(GetLastError)]); end
    else
    begin
    end;

    // Cleanup
    CloseHandle(hToken);
    FreeMem(AdminSid);
    LsaDeregisterLogonProcess(hLSA);
    LsaFreeReturnBuffer(pProfileBuffer);
  end;
  Self.DoStop;


end;

end.
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Sal iemand my kan help?

  Alt 9. Okt 2007, 08:15
Guten Morgen,

wie wäre es mit deutsch oder englisch, so verstehe ich nicht die Bohne.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.606 Beiträge
 
#3

Re: Sal iemand my kan help?

  Alt 9. Okt 2007, 08:18
hi Fanix.

Ich bin ein klitzekleines wenig des niederländischen mächtig, aber was ein interaktiver gezüchteter (fokken?) Desktop ist weiss ich nun doch nicht?

Bitte versuche es mal auf englisch oder Deutsch. Dann können Dir sicher viel mehr Leute helfen.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.606 Beiträge
 
#4

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 08:32
Ah, english is much better.

I don't think that what you want is possible in the Vista Security System in the way you think of it.

Nevertheless, while I was looking for some samples about WCF i came across an interesting article on Codeproject:
http://www.codeproject.com/WCF/AppWatcher.asp

I know, this is a .NET article, but he author uses a out of process com+ component to start an application in the users context out of a service on a vista machine. The technology he used should be the same with a win/32 service.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
FaNIX

Registriert seit: 8. Okt 2007
36 Beiträge
 
#5

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 08:45
Zitat von Phoenix:
Ah, english is much better.

I don't think that what you want is possible in the Vista Security System in the way you think of it.

Nevertheless, while I was looking for some samples about WCF i came across an interesting article on Codeproject:
http://www.codeproject.com/WCF/AppWatcher.asp

I know, this is a .NET article, but he author uses a out of process com+ component to start an application in the users context out of a service on a vista machine. The technology he used should be the same with a win/32 service.
Thanks for your reply, but i think it would take too much time to try and convert that method to delphi/win32
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#6

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 09:18
Is SetThreadDesktop still working in Vista? you can try to set a thread to the users desktop and then create the process in that thread.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#7

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 10:22
Why does your service need to run an interactive application? In many instances, if there is the need for a service to trigger user interaction, a separate application is run on the user's desktop (mostly with a TNA icon). The service can then contact this GUI application which will perform the needed actions. You may want to have a look at Larry Osterman's article series about applets (search for applet) though.
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#8

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 11:04
You do not need LsaLogonUser at all.

You already use WTSQueryUserToken which gives you a token, that can be used for CreateProcessAsUser.
That token leads to a process that is started in the logonsession of the user.
Parameter lpStartupInfo (member lpDesktop) you can provide a windowsstation and desktop where the new application is put ("winsta0\default").
That should work.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
FaNIX

Registriert seit: 8. Okt 2007
36 Beiträge
 
#9

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 12:25
Zitat von Dezipaitor:
You do not need LsaLogonUser at all.

You already use WTSQueryUserToken which gives you a token, that can be used for CreateProcessAsUser.
That token leads to a process that is started in the logonsession of the user.
Parameter lpStartupInfo (member lpDesktop) you can provide a windowsstation and desktop where the new application is put ("winsta0\default").
That should work.
Could you perhaps give me a example?
  Mit Zitat antworten Zitat
Tyrael Y.

Registriert seit: 28. Jul 2003
Ort: Stuttgart
1.093 Beiträge
 
Delphi 2007 Professional
 
#10

Re: Starting a Interactive Process in Vista using TService

  Alt 9. Okt 2007, 12:34
You can´t start a GUI application from a service in Vista.

To display GUI from service you must start a non visible application with the service and this application have to start the GUI elements.

If you need data of interaction you have to implement communication between service and non-visible application e.g. TCP.



[Service] <------> [Non-Visible-App] <------> [GUI-App]
Levent Yildirim
Erzeugung von Icons aus Bildern:IconLev
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:32 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