⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psapi.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
STDCALL
InitializeProcessForWsWatch(HANDLE hProcess)
{
  NTSTATUS Status;

  Status = NtSetInformationProcess(hProcess,
                                   ProcessWorkingSetWatch,
                                   NULL,
                                   0);
  if(!NT_SUCCESS(Status))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  return TRUE;
}


/*
 * @implemented
 */
BOOL
STDCALL
GetWsChanges(HANDLE hProcess,
             PPSAPI_WS_WATCH_INFORMATION lpWatchInfo,
             DWORD cb)
{
  NTSTATUS Status;

  Status = NtQueryInformationProcess(hProcess,
                                     ProcessWorkingSetWatch,
                                     (PVOID)lpWatchInfo,
                                     cb,
                                     NULL);
  if(!NT_SUCCESS(Status))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  return TRUE;
}


/*
 * @implemented
 */
DWORD
STDCALL
GetProcessImageFileNameW(HANDLE hProcess,
                         LPWSTR lpImageFileName,
                         DWORD nSize)
{
  PUNICODE_STRING ImageFileName;
  SIZE_T BufferSize;
  NTSTATUS Status;
  DWORD Ret = 0;

  BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));

  ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
  if(ImageFileName != NULL)
  {
    Status = NtQueryInformationProcess(hProcess,
                                       ProcessImageFileName,
                                       ImageFileName,
                                       BufferSize,
                                       NULL);
    if(NT_SUCCESS(Status))
    {
      memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length);

      /* make sure the string is null-terminated! */
      lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = L'\0';
      Ret = ImageFileName->Length / sizeof(WCHAR);
    }
    else if(Status == STATUS_INFO_LENGTH_MISMATCH)
    {
      /* XP sets this error code for some reason if the buffer is too small */
      SetLastError(ERROR_INSUFFICIENT_BUFFER);
    }
    else
    {
      SetLastErrorByStatus(Status);
    }

    LocalFree((HLOCAL)ImageFileName);
  }

  return Ret;
}


/*
 * @implemented
 */
DWORD
STDCALL
GetProcessImageFileNameA(HANDLE hProcess,
                         LPSTR lpImageFileName,
                         DWORD nSize)
{
  PUNICODE_STRING ImageFileName;
  SIZE_T BufferSize;
  NTSTATUS Status;
  DWORD Ret = 0;

  BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));

  ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
  if(ImageFileName != NULL)
  {
    Status = NtQueryInformationProcess(hProcess,
                                       ProcessImageFileName,
                                       ImageFileName,
                                       BufferSize,
                                       NULL);
    if(NT_SUCCESS(Status))
    {
      WideCharToMultiByte(CP_ACP,
                          0,
                          ImageFileName->Buffer,
                          ImageFileName->Length / sizeof(WCHAR),
                          lpImageFileName,
                          nSize,
                          NULL,
                          NULL);

      /* make sure the string is null-terminated! */
      lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = '\0';
      Ret = ImageFileName->Length / sizeof(WCHAR);
    }
    else if(Status == STATUS_INFO_LENGTH_MISMATCH)
    {
      /* XP sets this error code for some reason if the buffer is too small */
      SetLastError(ERROR_INSUFFICIENT_BUFFER);
    }
    else
    {
      SetLastErrorByStatus(Status);
    }

    LocalFree((HLOCAL)ImageFileName);
  }

  return Ret;
}


/*
 * @implemented
 */
BOOL
STDCALL
EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine,
               LPVOID lpContext)
{
  INTERNAL_ENUM_PAGE_FILES_CONTEXT Context;
  
  Context.pCallbackRoutine = pCallbackRoutine;
  Context.lpContext = lpContext;
  
  return EnumPageFilesW(InternalAnsiPageFileCallback, &Context);
}


/*
 * @implemented
 */
BOOL
STDCALL
EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine,
               LPVOID lpContext)
{
  NTSTATUS Status;
  PVOID Buffer;
  ULONG BufferSize = 0;
  BOOL Ret = FALSE;

  for(;;)
  {
    BufferSize += 0x1000;
    Buffer = LocalAlloc(LMEM_FIXED, BufferSize);
    if(Buffer == NULL)
    {
      return FALSE;
    }

    Status = NtQuerySystemInformation(SystemPageFileInformation,
                                      Buffer,
                                      BufferSize,
                                      NULL);
    if(Status == STATUS_INFO_LENGTH_MISMATCH)
    {
      LocalFree((HLOCAL)Buffer);
    }
    else
    {
      break;
    }
  }

  if(NT_SUCCESS(Status))
  {
    ENUM_PAGE_FILE_INFORMATION Information;
    PSYSTEM_PAGEFILE_INFORMATION pfi = (PSYSTEM_PAGEFILE_INFORMATION)Buffer;
    ULONG Offset = 0;

    do
    {
      PWCHAR Colon;

      pfi = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)pfi + Offset);

      Information.cb = sizeof(Information);
      Information.Reserved = 0;
      Information.TotalSize = pfi->TotalSize;
      Information.TotalInUse = pfi->TotalInUse;
      Information.PeakUsage = pfi->PeakUsage;

      /* strip the \??\ prefix from the file name. We do this by searching for the first
         : character and then just change Buffer to point to the previous character. */

      Colon = wcschr(pfi->PageFileName.Buffer, L':');
      if(Colon != NULL)
      {
        pfi->PageFileName.Buffer = --Colon;
      }

      /* FIXME - looks like the PageFileName string is always NULL-terminated on win.
                 At least I haven't encountered a different case so far, we should
                 propably manually NULL-terminate the string here... */

      if(!pCallbackRoutine(lpContext, &Information, pfi->PageFileName.Buffer))
      {
        break;
      }

      Offset = pfi->NextEntryOffset;
    } while(Offset != 0);

    Ret = TRUE;
  }
  else
  {
    SetLastErrorByStatus(Status);
  }

  LocalFree((HLOCAL)Buffer);

  return Ret;
}


/*
 * @implemented
 */
BOOL
STDCALL
GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation,
                   DWORD cb)
{
  SYSTEM_PERFORMANCE_INFORMATION spi;
  SYSTEM_BASIC_INFORMATION sbi;
  SYSTEM_HANDLE_INFORMATION shi;
  PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  ULONG BufferSize, ProcOffset, ProcessCount, ThreadCount;
  PVOID Buffer;
  NTSTATUS Status;

  Status = NtQuerySystemInformation(SystemPerformanceInformation,
                                    &spi,
                                    sizeof(spi),
                                    NULL);
  if(!NT_SUCCESS(Status))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  Status = NtQuerySystemInformation(SystemBasicInformation,
                                    &sbi,
                                    sizeof(sbi),
                                    NULL);
  if(!NT_SUCCESS(Status))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  /*
   * allocate enough memory to get a dump of all processes and threads
   */
  BufferSize = 0;
  for(;;)
  {
    BufferSize += 0x10000;
    Buffer = (PVOID)LocalAlloc(LMEM_FIXED, BufferSize);
    if(Buffer == NULL)
    {
      return FALSE;
    }

    Status = NtQuerySystemInformation(SystemProcessInformation,
                                      Buffer,
                                      BufferSize,
                                      NULL);
    if(Status == STATUS_INFO_LENGTH_MISMATCH)
    {
      LocalFree((HLOCAL)Buffer);
    }
    else
    {
      break;
    }
  }

  if(!NT_SUCCESS(Status))
  {
    LocalFree((HLOCAL)Buffer);
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  /*
   * determine the process and thread count
   */
  ProcessCount = ThreadCount = ProcOffset = 0;
  ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
  do
  {
    ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
    ProcessCount++;
    ThreadCount += ProcessInfo->NumberOfThreads;

    ProcOffset = ProcessInfo->NextEntryOffset;
  } while(ProcOffset != 0);

  LocalFree((HLOCAL)Buffer);

  /*
   * it's enough to supply a SYSTEM_HANDLE_INFORMATION structure as buffer. Even
   * though it returns STATUS_INFO_LENGTH_MISMATCH, it already sets the NumberOfHandles
   * field which is all we're looking for anyway.
   */
  Status = NtQuerySystemInformation(SystemHandleInformation,
                                    &shi,
                                    sizeof(shi),
                                    NULL);
  if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  /*
   * all required information collected, fill the structure
   */

  pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION);
  pPerformanceInformation->CommitTotal = spi.CommittedPages;
  pPerformanceInformation->CommitLimit = spi.CommitLimit;
  pPerformanceInformation->CommitPeak = spi.PeakCommitment;
  pPerformanceInformation->PhysicalTotal = sbi.NumberOfPhysicalPages;
  pPerformanceInformation->PhysicalAvailable = spi.AvailablePages;
  pPerformanceInformation->SystemCache = 0; /* FIXME - where to get this information from? */
  pPerformanceInformation->KernelTotal = spi.PagedPoolPages + spi.NonPagedPoolPages;
  pPerformanceInformation->KernelPaged = spi.PagedPoolPages;
  pPerformanceInformation->KernelNonpaged = spi.NonPagedPoolPages;
  pPerformanceInformation->PageSize = sbi.PageSize;
  pPerformanceInformation->HandleCount = shi.NumberOfHandles;
  pPerformanceInformation->ProcessCount = ProcessCount;
  pPerformanceInformation->ThreadCount = ThreadCount;

  return TRUE;
}


/*
 * @implemented
 */
BOOL
STDCALL
GetProcessMemoryInfo(HANDLE Process,
                     PPROCESS_MEMORY_COUNTERS ppsmemCounters,
                     DWORD cb)
{
  NTSTATUS Status;
  VM_COUNTERS vmc;
  BOOL Ret = FALSE;

  /* XP's implementation secures access to ppsmemCounters in SEH, we should behave
     similar so we can return the proper error codes when bad pointers are passed
     to this function! */

  _SEH_TRY
  {
    if(cb < sizeof(PROCESS_MEMORY_COUNTERS))
    {
      SetLastError(ERROR_INSUFFICIENT_BUFFER);
      _SEH_LEAVE;
    }

    /* ppsmemCounters->cb isn't checked at all! */

    Status = NtQueryInformationProcess(Process,
                                       ProcessVmCounters,
                                       &vmc,
                                       sizeof(vmc),
                                       NULL);
    if(!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      _SEH_LEAVE;
    }

    /* fill the structure with the collected information, in case of bad pointers
       SEH will catch the exception and set the appropriate error code */
    ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
    ppsmemCounters->PageFaultCount = vmc.PageFaultCount;
    ppsmemCounters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
    ppsmemCounters->WorkingSetSize = vmc.WorkingSetSize;
    ppsmemCounters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
    ppsmemCounters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
    ppsmemCounters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
    ppsmemCounters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
    ppsmemCounters->PagefileUsage = vmc.PagefileUsage;
    ppsmemCounters->PeakPagefileUsage = vmc.PeakPagefileUsage;

    Ret = TRUE;
  }
  _SEH_HANDLE
  {
    SetLastErrorByStatus(_SEH_GetExceptionCode());
  }
  _SEH_END;

  return Ret;
}


/*
 * @implemented
 */
BOOL
STDCALL
QueryWorkingSet(HANDLE hProcess,
                PVOID pv,
                DWORD cb)
{
  NTSTATUS Status;

  Status = NtQueryVirtualMemory(hProcess,
                                NULL,
                                MemoryWorkingSetList,
                                pv,
                                cb,
                                NULL);
  if(!NT_SUCCESS(Status))
  {
    SetLastErrorByStatus(Status);
    return FALSE;
  }

  return TRUE;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -