mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
implemented ProfileHandle
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1411 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -295,10 +295,32 @@ namespace ProcessHacker.Native.Api
|
||||
[In] [Optional] IntPtr ExceptionPort
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a profile object.
|
||||
/// </summary>
|
||||
/// <param name="ProfileHandle">A handle to the profile object.</param>
|
||||
/// <param name="ProcessHandle">
|
||||
/// A handle to the process to profile. If NULL, all address spaces are profiled.
|
||||
/// </param>
|
||||
/// <param name="ProfileBase">
|
||||
/// The first address at which to collect profiling information.
|
||||
/// </param>
|
||||
/// <param name="ProfileSize">
|
||||
/// The size of the range to profile. ProfileBase <= address <
|
||||
/// ProfileBase + ProfileSize will generate a hit.
|
||||
/// </param>
|
||||
/// <param name="BucketSize">
|
||||
/// A log2 value of each address bucket. Acceptable values are from 2 to 30.
|
||||
/// </param>
|
||||
/// <param name="Buffer">An array of int hit counters.</param>
|
||||
/// <param name="BufferSize">The size of the buffer, in bytes.</param>
|
||||
/// <param name="ProfileSource">The profiling source.</param>
|
||||
/// <param name="Affinity">The processors to profile.</param>
|
||||
/// <returns>A NTSTATUS value.</returns>
|
||||
[DllImport("ntdll.dll")]
|
||||
public static extern NtStatus NtCreateProfile(
|
||||
[Out] out IntPtr ProfileHandle,
|
||||
[In] IntPtr ProcessHandle,
|
||||
[In] [Optional] IntPtr ProcessHandle,
|
||||
[In] IntPtr ProfileBase,
|
||||
[In] IntPtr ProfileSize,
|
||||
[In] int BucketSize,
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using ProcessHacker.Native.Api;
|
||||
using ProcessHacker.Native.Security;
|
||||
|
||||
@@ -30,6 +29,90 @@ namespace ProcessHacker.Native.Objects
|
||||
{
|
||||
public class ProfileHandle : NativeHandle<ProfileAccess>
|
||||
{
|
||||
// TODO: Implement basics
|
||||
public static ProfileHandle Create(
|
||||
ProcessHandle processHandle,
|
||||
IntPtr rangeBase,
|
||||
int rangeSize,
|
||||
int bucketSize,
|
||||
KProfileSource profileSource,
|
||||
IntPtr affinity
|
||||
)
|
||||
{
|
||||
NtStatus status;
|
||||
IntPtr handle;
|
||||
|
||||
if (bucketSize < 2 || bucketSize > 30)
|
||||
throw new ArgumentException("Bucket size must be between 2 and 30, inclusive.");
|
||||
|
||||
int realBucketSize = 2 << bucketSize;
|
||||
MemoryAlloc buffer = new MemoryAlloc(((rangeSize - 1) / realBucketSize + 1) * sizeof(int)); // divide, round up
|
||||
|
||||
if ((status = Win32.NtCreateProfile(
|
||||
out handle,
|
||||
processHandle,
|
||||
rangeBase,
|
||||
new IntPtr(rangeSize),
|
||||
bucketSize,
|
||||
buffer,
|
||||
buffer.Size,
|
||||
profileSource,
|
||||
affinity
|
||||
)) >= NtStatus.Error)
|
||||
Win32.ThrowLastError(status);
|
||||
|
||||
return new ProfileHandle(handle, true, rangeBase, rangeSize, realBucketSize, buffer);
|
||||
}
|
||||
|
||||
private IntPtr _rangeBase;
|
||||
private int _rangeSize;
|
||||
private int _bucketSize; // not logarithmic
|
||||
private MemoryAlloc _buffer;
|
||||
|
||||
private ProfileHandle(
|
||||
IntPtr handle,
|
||||
bool owned,
|
||||
IntPtr rangeBase,
|
||||
int rangeSize,
|
||||
int bucketSize,
|
||||
MemoryAlloc buffer
|
||||
)
|
||||
{
|
||||
_rangeBase = rangeBase;
|
||||
_rangeSize = rangeSize;
|
||||
_bucketSize = bucketSize;
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
protected override void Close()
|
||||
{
|
||||
_buffer.Dispose();
|
||||
|
||||
base.Close();
|
||||
}
|
||||
|
||||
public int[] Collect()
|
||||
{
|
||||
int[] counters = new int[_buffer.Size / sizeof(int)];
|
||||
|
||||
Marshal.Copy(_buffer, counters, 0, counters.Length);
|
||||
|
||||
return counters;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
NtStatus status;
|
||||
|
||||
if ((status = Win32.NtStartProfile(this)) >= NtStatus.Error)
|
||||
Win32.ThrowLastError(status);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
NtStatus status;
|
||||
|
||||
if ((status = Win32.NtStopProfile(this)) >= NtStatus.Error)
|
||||
Win32.ThrowLastError(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user