implemented ProfileHandle

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1411 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2009-06-13 02:33:24 +00:00
parent a0c172e63e
commit 09bbec47bf
2 changed files with 109 additions and 4 deletions
@@ -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 &lt;= address &lt;
/// 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);
}
}
}