Конференция "WinAPI" » Вопрос по ZwQuerySystemInformation
 
  • pushkin42 © (22.06.13 21:00) [0]
    Итак, сразу прошу прощения за грязь в коде. Вариант черновой.
    Есть код ( в принципе, спер из инета и ничего не переделывал особо, признаюсь честно ):

    function FillProcessesList(var slProcesses: TStringList;
     aProcessName: String = '1cv7s.exe'): Boolean;
    var
     ret: NTSTATUS;
     pBuffer, pCur: PSYSTEM_PROCESSES;
     ReturnLength: DWORD;
     i: Integer;
     c: String;
     ProcessName, PN: String;
    begin
     Result := False;
     ReturnLength := 0;
     // Запрашиваем размер требуемого буфера
     ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, nil, 0,
       ReturnLength);
     // Резервируем буфер
     pBuffer := AllocMem(ReturnLength);
     // Получаем информацию о процессах в буфер
     ret := ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pBuffer,
       ReturnLength, ReturnLength);
     if ret = STATUS_SUCCESS then // Проверяем успешность выполнения запроса
     begin
       pCur := pBuffer; // Инициируем указатель на текущую структуру
       i := 0; // Инициируем счетчик процессов. Его можно и не использовать.
       // Проходим в цикле по всей цепочке структур
       slProcesses.Clear;

       repeat
       begin

         // Смотрим длину имени процесса и если оно не равно 0,
         // то читаем строку из буфера, иначе – имя = <неизвестно>
         if pCur.ProcessName.Length = 0 then
           ProcessName := '<неизвестно>'
         else
           ProcessName := WideCharToString(pCur.ProcessName.Buffer);
         // Добавляем инфу о процессе в TStringList
         if ProcessName = aProcessName then
         begin

           inc(i); // Увеличиваем счетчик процессов.
           {
             Format('%s|%d|%s|%s', [pe.szExeFile, pe.th32ProcessID, c,
             GetProcessUser(pe.th32ProcessID)])); }


           c := GetWindowCaption(pCur.ProcessId);
           PN := pCur.ProcessName.Buffer;
           slProcesses.Add(

             Format('%s|%d|%s|%s', [PN, pCur.ProcessId, c,
             GetProcessAccount(pCur.ProcessId)]));

         end;

         // Вычисляем указатель на следующую структуру SYSTEM_PROCESSES
         // Для этого к адресу этой структуру прибавляем смещение следующей
         // из поля NextEntryDelta
         pCur := Ptr(DWORD(pCur) + pCur.NextEntryDelta);
         // Крутим цикл, пока есть следующая структура
       end;
       Result := True;
       until pCur.NextEntryDelta = 0;
     end;
     FreeMem(pBuffer);
     // form1.btnNotify.Caption := IntToStr(slProcesses.Count);



    Вопрос вот в чем.
    Почему когда ПЕРВЫЙ РАЗ вызываешь эту функцию, она отрабатывает корректно, и все процессы показывает, а все последующие вызовы теряет ровно 1 процесс (причем похоже тот, что был запущен последним)? Причем иногда таки при вызове функции процесс в списке появляется. Но с дикой задержкой (около минуты) - как это победить? Форум уже курил, но именно такой проблемы не нашел...
  • Rouse_ © (22.06.13 21:33) [1]
    просто не выводится последняя запись, поправь алгоритм
  • p © (22.06.13 21:34) [2]
    type
     PUNICODE_STRING = ^UNICODE_STRING;

     UNICODE_STRING = record
       Length: USHORT;
       MaximumLength: USHORT;
       Buffer: PWideChar;
     end;
     
     CLIENT_ID = record
       UniqueProcess: THandle;
       UniqueThread: THandle;
     end;

     PCLIENT_ID = ^CLIENT_ID;

     KPRIORITY = Integer;

     _KWAIT_REASON = (
       Executive,
       FreePage,
       PageIn,
       PoolAllocation,
       DelayExecution,
       Suspended,
       UserRequest,
       WrExecutive,
       WrFreePage,
       WrPageIn,
       WrPoolAllocation,
       WrDelayExecution,
       WrSuspended,
       WrUserRequest,
       WrEventPair,
       WrQueue,
       WrLpcReceive,
       WrLpcReply,
       WrVirtualMemory,
       WrPageOut,
       WrRendezvous,
       WrKeyedEvent,
       WrTerminated,
       WrProcessInSwap,
       WrCpuRateControl,
       WrCalloutStack,
       WrKernel,
       WrResource,
       WrPushLock,
       WrMutex,
       WrQuantumEnd,
       WrDispatchInt,
       WrPreempted,
       WrYieldExecution,
       WrFastMutex,
       WrGuardedMutex,
       WrRundown,
       MaximumWaitReason);
     KWAIT_REASON = _KWAIT_REASON;

     SYSTEM_THREADS = record
       KernelTime: FILETIME;
       UserTime: FILETIME;
       CreateTime: FILETIME;
       WaitTime: ULONG;
       StartAddress: PVOID;
       ClientId: CLIENT_ID;
       Priority: KPRIORITY;
       BasePriority: LONG;
       ContextSwitches: ULONG;
       ThreadState: ULONG;
       WaitReason: KWAIT_REASON;
     end;

     SYSTEM_PROCESS_INFORMATION = record
       NextEntryOffset: ULONG;
       NumberOfThreads: ULONG;
       WorkingSetPrivateSize: Int64;
       HardFaultCount: ULONG;
       NumberOfThreadsHighWatermark: ULONG;
       CycleTime: ULONGLONG;
       CreateTime: FILETIME;
       UserTime: FILETIME;
       KernelTime: FILETIME;
       ImageName: UNICODE_STRING;
       BasePriority: KPRIORITY;
       UniqueProcessId: THandle;
       InheritedFromUniqueProcessId: THandle;
       HandleCount: ULONG;
       SessionId: ULONG;
       UniqueProcessKey: ULONG_PTR;
       PeakVirtualSize: SIZE_T;
       VirtualSize: SIZE_T;
       PageFaultCount: ULONG;
       PeakWorkingSetSize: SIZE_T;
       WorkingSetSize: SIZE_T;
       QuotaPeakPagedPoolUsage: SIZE_T;
       QuotaPagedPoolUsage: SIZE_T;
       QuotaPeakNonPagedPoolUsage: SIZE_T;
       QuotaNonPagedPoolUsage: SIZE_T;
       PagefileUsage: SIZE_T;
       PeakPagefileUsage: SIZE_T;
       PrivatePageCountp: SIZE_T;
       ReadOperationCount: Int64;
       WriteOperationCount: Int64;
       OtherOperationCount: Int64;
       ReadTransferCount: Int64;
       WriteTransferCount: Int64;
       OtherTransferCount: Int64;
       Threads: array [0 .. 0] of SYSTEM_THREADS;
     end;

     PSYSTEM_PROCESS_INFORMATION = ^SYSTEM_PROCESS_INFORMATION;

    type
     NTSTATUS = System.LongInt;
     
    const
     STATUS_SUCCESS = NTSTATUS($00000000);
     STATUS_INFO_LENGTH_MISMATCH = NTSTATUS($C0000004);  


    var
     SystemInformation: PVOID;
     SystemInformationLength: ULONG;
     ReturnLength: ULONG;
     PSPI: PSYSTEM_PROCESS_INFORMATION;
    begin
       SystemInformationLength := $400;
       GetMem(SystemInformation, SystemInformationLength);
       Result := NtQuerySystemInformation(SystemProcessesAndThreadsInformation, SystemInformation, SystemInformationLength, @ReturnLength);
       if (Result = STATUS_INFO_LENGTH_MISMATCH) then
       begin
         while (Result = STATUS_INFO_LENGTH_MISMATCH) do
         begin
           FreeMem(SystemInformation);
           SystemInformationLength := SystemInformationLength * 2;
           GetMem(SystemInformation, SystemInformationLength);
           Result := NtQuerySystemInformation(SystemProcessesAndThreadsInformation, SystemInformation, SystemInformationLength, @ReturnLength);
         end;
       end;
       try
         if Result = STATUS_SUCCESS then
         begin
           PSPI := PSYSTEM_PROCESS_INFORMATION(SystemInformation);
           repeat
               if PSPI^.UniqueProcessId = 0 then
                 ProcessName := 'System Idle Process';
               else
                 ProcessName := PSPI^.ImageName.Buffer;

             if PSPI^.NextEntryOffset = 0 then
               Break;
             PSPI := PSYSTEM_PROCESS_INFORMATION(DWORD(PSPI) + PSPI^.NextEntryOffset);
           until
             False;

         end;
       finally
         if SystemInformation <> nil then
           FreeMem(SystemInformation);
         SystemInformation := nil;
       end;
    end;

  • p © (22.06.13 21:36) [3]
    NtQuerySystemInformation(SystemInformationClass: ULONG; SystemInformation: PVOID; SystemInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS;

 
Конференция "WinAPI" » Вопрос по ZwQuerySystemInformation
Есть новые Нет новых   [119101   +92][b:0][p:0.004]