Конференция "WinAPI" » владелец процесса, ошибка при определении [D7]
 
  • Danger © (25.04.10 15:53) [0]
    Здравствуйте,
    Мне нужно определить владельцев всех процессов, имеющихся в системе. Получаю список процессов системы при помощи EnumProcesses() (из PsAPI), затем пробую получить информацию о каждом конкретном процессе  при помощи такой функции:


    function GetProcessParams( dwProcessID: DWord; var strOwner: string; var timeCreate: PFileTime ): Boolean;
    var
     hProcess, hToken: THandle;
     ptiUser: PTOKEN_USER; peUse: SID_NAME_USE;
     dwLength: DWord; dwLen1, dwLen2: DWord;
     timeExit, timeKernel, timeUser: FILETIME;
    begin
     Result:= false;
     hProcess:= OpenProcess( PROCESS_QUERY_INFORMATION + PROCESS_VM_READ, false, dwProcessId );
     if ( hProcess > 0 ) then
     begin
       // retrieving process owner
       if ( OpenProcessToken( hProcess, TOKEN_QUERY, hToken ) ) then
       begin
         GetTokenInformation( hToken, TokenUser, nil, 0, dwLength );
         if ( ( GetLastError = ERROR_INSUFFICIENT_BUFFER ) and ( dwLength > 0 ) ) then
         begin
           GetMem( ptiUser, dwLength );
           try
            if ( GetTokenInformation( hToken, TokenUser, ptiUser, dwLength, dwLength ) ) then
             if IsValidSid( ptiUser^.User.Sid ) then
             begin
               ZeroMemory( @strUsername, MAX_PATH );
               ZeroMemory( @strDomain, MAX_PATH );
               dwLen1:= MAX_PATH - 1;
               dwLen2:= MAX_PATH - 1;
               if ( LookupAccountSid( nil, ptiUser^.User.Sid, strUsername, dwLen1, strDomain, dwLen2, peUse ) ) then
               begin;
                 strOwner:= Copy( strDomain, 0, lstrlen( strDomain ) ) + '\' + Copy( strUsername, 0, lstrlen( strUsername ) );
                 Result:= true;
               end;
             end; // 'if IsValidSid( ptiUser^.User.Sid ) then'
           finally
             FreeMem( ptiUser );
           end;
         end; // 'if ( ( GetLastError = ERROR_INSUFFICIENT_BUFFER ) and ( dwLength > 0 ) ) then'
         CloseHandle( hToken );
       end // 'if ( OpenProcessToken( hProcess, TOKEN_READ, hToken ) ) then'
       else Writeln('OpenProcessToken() failed - ', GetLastError); // TODO
      // retrieving process times
       if ( not GetProcessTimes( hProcess, timeCreate^, timeExit, timeKernel, timeUser ) ) then
        // if fails, always set result to false
       begin
       Result:= false;
       Writeln('GetProcessTimes() failed');
       end; // TODO
       CloseHandle( hProcess );
     end // 'if ( hProcess > 0 ) then'
     else Writeln('OpenProcess() failed'); // TODO
      if not ( Result ) then Writeln('FAILED'); // TODO
    end;  



    Проблема в том, что при вызове OpenProcessToken() выдает ошибку "0x05 (Access Denied)" для процессов, владельцем которых не является запускающий программу пользователь. Подскажите, как побороть?

    Хотя программу запускаю из-под администратора. Привилегии SE_DEBUG_NAME даны (без них отваливается на OpenProcess() ).
    Системы Windows 2003 и WIndows 7 Home.
  • Игорь © (25.04.10 19:05) [1]
    Не помню есть ли WinStationGetProcessSid в Windows 2003

    function WinStationGetProcessSid(hServer: Cardinal; ProcessId: Cardinal; ProcessStartTime: _FILETIME; pProcessUserSid: PByte; var dwSidSize: Cardinal): Boolean; stdcall; external 'winsta.dll';

    function GetProcessUserAndDomainName(PID: DWORD; var UserName: string; var DomainName: string): Boolean;
    var
     hProcess: THandle;
     CreationTime, ExitTime, KernelTime, UserTime: _FILETIME;
     UserSid: Pointer;
     _UserName, _DomainName: PAnsiChar;
     cbUser, cbDomain: Cardinal;
     ReturnLength: Cardinal;
     CreateTime: TSystemTime;
    begin
     UserName:= '';
     DomainName:= '';
     Result:= False;
     hProcess:= 0;
       hProcess:= OpenProcess(MAXIMUM_ALLOWED($1000 Vista, 7), False, PID);
     if hProcess > 0 then
     begin
       try
         GetProcessTimes(hProcess, CreationTime, ExitTime, KernelTime, UserTime);
         FileTimeToSystemTime(CreationTime, CreateTime);
         ReturnLength:= 1024;
         GetMem(UserSid, ReturnLength);
         try
           if WinStationGetProcessSid(0, PID, CreationTime, UserSid, ReturnLength) then
           begin
             cbUser:= 1024;
             cbDomain:= 1024;
             GetMem(_UserName, cbUser);
             GetMem(_DomainName, cbDomain);
             try
               if LookupAccountSid(nil, UserSid, _UserName, cbUser, _DomainName, cbDomain, ReturnLength) then
               begin
                 SetLength(UserName, cbUser);
                 SetLength(DomainName, cbDomain);
                 lstrcpy(PAnsiChar(UserName), _UserName);
                 lstrcpy(PAnsiChar(DomainName), _DomainName);
                 Result:= True;
               end;
             finally
               FreeMem(_UserName);
               FreeMem(_DomainName);
             end;
           end;
         finally
           FreeMem(UserSid);
         end;
       finally
         CloseHandle(hProcess);
       end;
     end;
    end;

  • Danger © (25.04.10 21:42) [2]
    > Не помню есть ли WinStationGetProcessSid в Windows 2003

    Вроде, в ХР есть, значит, и в 2003 должно быть. Кстати, там рядом есть еще одна функция, наводящая на раздумье - WinStationGetAllProcesses().
    Попробую Ваше решение; завтра отпишусь.

    Жаль только, что приходится использовать низкоуровневые функции (рискованное это дело в продакшене, да документации по ним мало).
  • Игорь © (25.04.10 22:25) [3]

    > Danger ©   (25.04.10 21:42) [2]
    >
    > Жаль только, что приходится использовать низкоуровневые
    > функции (рискованное это дело в продакшене, да документации
    > по ним мало).


    Низкоуровневая функция?

    Ниже какого она уровня? че за бред?

    Обычная функция импортируемая из winsta.dll
  • Danger © (25.04.10 23:47) [4]
    Имел в виду, недокументированная в MSDN и, соответственно, отсутствующая в заголовочных файлах. Ниже API, предоставленного пользователю, ведь экспорт нигде официально не описан.

    Спасибо за подсказку, будем смотреть. Надеюсь, что получится.
  • Eraser © (26.04.10 00:21) [5]
    до кучи WTSEnumerateProcesses.
 
Конференция "WinAPI" » владелец процесса, ошибка при определении [D7]
Есть новые Нет новых   [134431   +15][b:0][p:0.003]