﻿//
//    Copyright (C) Microsoft.  All rights reserved.
//
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
public struct ProcessBasicInformation
{
    // PROCESS_BASIC_INFORMATION
    //
    internal System.IntPtr Reserved1;
    internal System.IntPtr PebBaseAddress;
    internal System.IntPtr Reserved2_0;
    internal System.IntPtr Reserved2_1;
    internal System.IntPtr UniqueProcessId;
    internal System.IntPtr InheritedFromUniqueProcessId;

    [System.Runtime.InteropServices.DllImport("ntdll.dll")]
    private static extern int NtQueryInformationProcess(
        System.IntPtr processHandle,
        int processInformationClass,
        ref ProcessBasicInformation processInformation,
        int processInformationLenagth,
        out uint returnLength);

    public static System.Diagnostics.Process GetParentProcess(System.IntPtr handle)
    {
        ProcessBasicInformation pbi = new ProcessBasicInformation();
        uint cbRet;
        int status = NtQueryInformationProcess(
            handle,
            0,
            ref pbi,
            System.Runtime.InteropServices.Marshal.SizeOf(pbi),
            out cbRet);
        if ( status != 0 )
        {
            throw new System.ComponentModel.Win32Exception(status);
        }

        try
        {
            return System.Diagnostics.Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
        }
        catch (System.ArgumentException)
        {
            return null;
        }
    }

    public static System.Diagnostics.Process GetParentProcess()
    {
        return GetParentProcess(System.Diagnostics.Process.GetCurrentProcess().Handle);
    }

    public static System.Diagnostics.Process GetParentProcess(int id)
    {
        return GetParentProcess(System.Diagnostics.Process.GetProcessById(id).Handle);
    }
}
