/// <summary>
 /// Walks the call stack for the thread.
 /// </summary>
 /// <param name="walkStackCallback">A callback to execute.</param>
 /// <param name="architecture">
 /// The type of stack walk. On 32-bit systems, this value is ignored.
 /// On 64-bit systems, this value can be set to I386 to walk the
 /// 32-bit stack.
 /// </param>
 public void WalkStack(WalkStackDelegate walkStackCallback, OSArch architecture)
 {
     // We need to duplicate the handle to get QueryInformation access.
     using (NativeHandle <ThreadAccess> dupThreadHandle = this.Duplicate(OSVersion.MinThreadQueryInfoAccess))
         using (ProcessHandle phandle = new ProcessHandle(
                    FromHandle(dupThreadHandle).GetBasicInformation().ClientId.ProcessId,
                    ProcessAccess.QueryInformation | ProcessAccess.VmRead
                    ))
         {
             this.WalkStack(phandle, walkStackCallback, architecture);
         }
 }
 /// <summary>
 /// Walks the call stack for the thread.
 /// </summary>
 /// <param name="walkStackCallback">A callback to execute.</param>
 /// <param name="architecture">
 /// The type of stack walk. On 32-bit systems, this value is ignored.
 /// On 64-bit systems, this value can be set to I386 to walk the
 /// 32-bit stack.
 /// </param>
 public void WalkStack(WalkStackDelegate walkStackCallback, OSArch architecture)
 {
     if (KProcessHacker.Instance != null)
     {
         // Use KPH to open the parent process.
         using (var phandle = this.GetProcess(ProcessAccess.QueryInformation | ProcessAccess.VmRead))
             this.WalkStack(phandle, walkStackCallback, architecture);
     }
     else
     {
         // We need to duplicate the handle to get QueryInformation access.
         using (var dupThreadHandle = this.Duplicate(OSVersion.MinThreadQueryInfoAccess))
             using (var phandle = new ProcessHandle(
                        ThreadHandle.FromHandle(dupThreadHandle).GetBasicInformation().ClientId.ProcessId,
                        ProcessAccess.QueryInformation | ProcessAccess.VmRead
                        ))
             {
                 this.WalkStack(phandle, walkStackCallback, architecture);
             }
     }
 }
        /// <summary>
        /// Walks the call stack for the thread.
        /// </summary>
        /// <param name="parentProcess">A handle to the thread's parent process.</param>
        /// <param name="walkStackCallback">A callback to execute.</param>
        /// <param name="architecture">
        /// The type of stack walk. On 32-bit systems, this value is ignored.
        /// On 64-bit systems, this value can be set to I386 to walk the
        /// 32-bit stack.
        /// </param>
        public unsafe void WalkStack(ProcessHandle parentProcess, WalkStackDelegate walkStackCallback, OSArch architecture)
        {
            bool suspended = false;

            // Suspend the thread to avoid inaccurate thread stacks.
            try
            {
                this.Suspend();
                suspended = true;
            }
            catch (WindowsException)
            {
                suspended = false;
            }

            // Use KPH for reading memory if we can.
            ReadProcessMemoryProc64 readMemoryProc = null;

            if (KProcessHacker.Instance != null)
            {
                readMemoryProc = new ReadProcessMemoryProc64(
                    delegate(IntPtr processHandle, ulong baseAddress, IntPtr buffer, int size, out int bytesRead)
                {
                    return(KProcessHacker.Instance.KphReadVirtualMemorySafe(
                               ProcessHandle.FromHandle(processHandle), (int)baseAddress, buffer, size, out bytesRead).IsSuccess());
                });
            }

            try
            {
                // x86/WOW64 stack walk.
                if (OSVersion.Architecture == OSArch.I386 || (OSVersion.Architecture == OSArch.Amd64 && architecture == OSArch.I386))
                {
                    Context context = new Context();

                    context.ContextFlags = ContextFlags.All;

                    if (OSVersion.Architecture == OSArch.I386)
                    {
                        // Get the context.
                        this.GetContext(ref context);
                    }
                    else
                    {
                        // Get the WOW64 x86 context.
                        this.GetContextWow64(ref context);
                    }

                    // Set up the initial stack frame structure.
                    var stackFrame = new StackFrame64();

                    stackFrame.AddrPC.Mode      = AddressMode.AddrModeFlat;
                    stackFrame.AddrPC.Offset    = (ulong)context.Eip;
                    stackFrame.AddrStack.Mode   = AddressMode.AddrModeFlat;
                    stackFrame.AddrStack.Offset = (ulong)context.Esp;
                    stackFrame.AddrFrame.Mode   = AddressMode.AddrModeFlat;
                    stackFrame.AddrFrame.Offset = (ulong)context.Ebp;

                    while (true)
                    {
                        using (Win32.DbgHelpLock.AcquireContext())
                        {
                            if (!Win32.StackWalk64(
                                    MachineType.I386,
                                    parentProcess,
                                    this,
                                    ref stackFrame,
                                    ref context,
                                    readMemoryProc,
                                    Win32.SymFunctionTableAccess64,
                                    Win32.SymGetModuleBase64,
                                    IntPtr.Zero
                                    ))
                            {
                                break;
                            }
                        }

                        // If we got an invalid eip, break.
                        if (stackFrame.AddrPC.Offset == 0)
                        {
                            break;
                        }

                        // Execute the callback.
                        if (!walkStackCallback(new ThreadStackFrame(ref stackFrame)))
                        {
                            break;
                        }
                    }
                }
                // x64 stack walk.
                else if (OSVersion.Architecture == OSArch.Amd64)
                {
                    ContextAmd64 context = new ContextAmd64();

                    context.ContextFlags = ContextFlagsAmd64.All;
                    // Get the context.
                    this.GetContext(ref context);

                    // Set up the initial stack frame structure.
                    var stackFrame = new StackFrame64();

                    stackFrame.AddrPC.Mode      = AddressMode.AddrModeFlat;
                    stackFrame.AddrPC.Offset    = (ulong)context.Rip;
                    stackFrame.AddrStack.Mode   = AddressMode.AddrModeFlat;
                    stackFrame.AddrStack.Offset = (ulong)context.Rsp;
                    stackFrame.AddrFrame.Mode   = AddressMode.AddrModeFlat;
                    stackFrame.AddrFrame.Offset = (ulong)context.Rbp;

                    while (true)
                    {
                        using (Win32.DbgHelpLock.AcquireContext())
                        {
                            if (!Win32.StackWalk64(
                                    MachineType.Amd64,
                                    parentProcess,
                                    this,
                                    ref stackFrame,
                                    ref context,
                                    readMemoryProc,
                                    Win32.SymFunctionTableAccess64,
                                    Win32.SymGetModuleBase64,
                                    IntPtr.Zero
                                    ))
                            {
                                break;
                            }
                        }

                        // If we got an invalid rip, break.
                        if (stackFrame.AddrPC.Offset == 0)
                        {
                            break;
                        }

                        // Execute the callback.
                        if (!walkStackCallback(new ThreadStackFrame(ref stackFrame)))
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                // If we suspended the thread before, resume it.
                if (suspended)
                {
                    try
                    {
                        this.Resume();
                    }
                    catch (WindowsException)
                    { }
                }
            }
        }
 /// <summary>
 /// Walks the call stack for the thread.
 /// </summary>
 /// <param name="parentProcess">A handle to the thread's parent process.</param>
 /// <param name="walkStackCallback">A callback to execute.</param>
 public unsafe void WalkStack(ProcessHandle parentProcess, WalkStackDelegate walkStackCallback)
 {
     this.WalkStack(parentProcess, walkStackCallback, OSVersion.Architecture);
 }
 /// <summary>
 /// Walks the call stack for the thread.
 /// </summary>
 /// <param name="walkStackCallback">A callback to execute.</param>
 public void WalkStack(WalkStackDelegate walkStackCallback)
 {
     this.WalkStack(walkStackCallback, OSVersion.Architecture);
 }