Re[2]: Отладка сервисов!!!
От: Danchik Украина  
Дата: 11.08.06 14:31
Оценка:
Здравствуйте, glh, Вы писали:

glh>Самый простой вариант


glh>Напиши так, что бы работало в 2 режимах, как приложение и как сервис.


[Skip]

Плохо что в коде SC_MANAGER_ALL_ACCESS и SERVICE_ALL_ACCESS. Не все же юзера администраторы

Мне не нравится SvcCanStart. Зачем сие? Тут нужно узнать запустил ли процес Service Manager или мы просто тыкнули в в иконку
Простенький пример я писал вот здесь
Автор: Danchik
Дата: 24.07.06

Но со временем у меня появился более навороченный вариант .

Код портирован мною с С++. Источник: http://win32.mvps.org/security/is_svc.html.

This code fragment determines whether the current process is running interactively or as a service (services running in a real user account have a SID with SECURITY_SERVICE_RID in their token; console processes have a SID with SECURITY_INTERACTIVE_RID; services running as BUILTIN\SYSTEM [LocalSystem] have neither). If the process is a LocalSystem service, the fragment checks for interactive access to the desktop, too.

Kudos to Rohan Philips for sharing this!


type
  TDServiceUtils = class
  protected
    class function InternalIsService(out IsService, IsInteractive : Boolean): Integer;
  public
    ....
    class function IsService: Boolean;
  end;

implementation

class function TDServiceUtils.IsService: Boolean;
var
  aIsService : Boolean;
  aIsInteractive : Boolean;
begin
  aIsService := False;
  Result := (InternalIsService (aIsService, aIsInteractive) <> 0) or aIsService;
end;

class function TDServiceUtils.InternalIsService(out IsService, IsInteractive : Boolean): Integer;
var
  hProcessToken: THandle;
  groupLength: Cardinal;
  groupInfo: PTokenGroups;
  siaNt: SID_IDENTIFIER_AUTHORITY;
  pInteractiveSid: PSID;
  pServiceSid: PSID;
  ndx: Cardinal;
  sanda: SID_AND_ATTRIBUTES;
  aSid: PSID;
  aKey: HKEY;
  aStrKey: string;
  aServiceName: string;
  dwType: Cardinal;
  dwSize: Cardinal;
begin
  hProcessToken := 0;
  groupLength   := 50;
  groupInfo     := nil;

  siaNt := SECURITY_NT_AUTHORITY;
  pInteractiveSid := nil;
  pServiceSid := nil;

  Result := NO_ERROR;

  try
    // open the token
    if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hProcessToken) then
    begin
      Result := GetLastError;
      Exit;
    end;

    // allocate a buffer of default size
    groupInfo := AllocMem (groupLength);

    // try to get the info
    if not GetTokenInformation(hProcessToken, TokenGroups,
      groupInfo, groupLength, groupLength) then
    begin
      // if buffer was too small, allocate to proper size, otherwise error
      if GetLastError <> ERROR_INSUFFICIENT_BUFFER then
      begin
        Result := GetLastError;
        Exit;
      end;

      FreeMem(groupInfo);

      groupInfo := AllocMem(groupLength);

      if not GetTokenInformation(hProcessToken, TokenGroups,
        groupInfo, groupLength, groupLength) then
      begin
        Result := GetLastError;
        Exit;
      end;
    end;

    //
    //  We now know the groups associated with this token.  We want
    //  to look to see if the interactive group is active in the
    //  token, and if so, we know that this is an interactive process.
    //
    //  We also look for the "service" SID, and if it's present,
    //  we know we're a service.
    //
    //  The service SID will be present iff the service is running in a
    //  user account (and was invoked by the service controller).
    //

    // create comparison sids
    if not AllocateAndInitializeSid(siaNt, 1, SECURITY_INTERACTIVE_RID,
      0, 0, 0, 0, 0, 0, 0, pInteractiveSid) then
    begin
      Result := GetLastError;
      Exit;
    end;

    if not AllocateAndInitializeSid(siaNt, 1, SECURITY_SERVICE_RID,
      0, 0, 0, 0, 0, 0, 0, pServiceSid) then 
    begin
      Result := GetLastError;
      Exit;
    end;


    // reset flags
    IsInteractive := False;
    IsService := False;

    // try to match sids
    ndx := 0;
    while ndx < groupInfo.GroupCount do
    begin
      sanda := groupInfo.Groups[ndx];
      aSid  := sanda.Sid;

      //
      //  Check to see if the group we're looking at is one of
      //  the two groups we're interested in.
      //

      if EqualSid(aSid, pInteractiveSid) then
      begin
        //
        //  This process has the Interactive SID in its
        //  token.  This means that the process is running as
        //  a console process
        //
        IsInteractive := True;
        IsService := False;
        Break;
      end else
        if EqualSid(aSid, pServiceSid) then
        begin
          //
          //  This process has the Service SID in its
          //  token.  This means that the process is running as
          //  a service running in a user account ( not local system ).
          //
          IsService := True;
          IsInteractive := False;
          Break;
        end;

      Inc (ndx);
    end;

    if not (IsService or IsInteractive) then
    begin
      //
      //  Neither Interactive or Service was present in the current
      //  users token, This implies that the process is running as
      //  a service, most likely running as LocalSystem.
      //
      IsService := True;

      // determine if the local system service is interactive.  We
      // do this y looking in the service's registry and checking
      // the Type value for the SERVICE_INTERACTIVE_PROCESS bit

      aKey := 0;

      aStrKey := Format ('SYSTEM\CurrentControlSet\Services\%s', [aServiceName]);
      if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                 PChar (aStrKey),
                 0,
                 KEY_READ,
                 aKey) = ERROR_SUCCESS then
      begin
        dwType := 0;
        dwSize := sizeof(DWORD);
        if RegQueryValueEx(aKey,
                   PChar ('Type'),
                   nil,
                   nil,
                   @dwType,
                   @dwSize) = ERROR_SUCCESS then
        begin
          if (dwType and SERVICE_INTERACTIVE_PROCESS) <> 0 then
            IsInteractive := True;
        end;

        RegCloseKey(aKey);
      end;


    end;
  finally
    if pServiceSid <> nil then
      FreeSid (pServiceSid);

    if pInteractiveSid <> nil then
      FreeSid (pInteractiveSid);

    if groupInfo <> nil then
      FreeMem (groupInfo);

    if hProcessToken <> 0 then
      CloseHandle (hProcessToken);
  end;

end;

Надеюсь комуто это будет полезно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.