Process not suspending (NtSuspendProcess) -> What is going on?

  c++, windows

I have adapted a 32-bit memory scanner in C# to 64-bit. Before scanning a program (read: live program), it is supposed to suspend the process. I am using NtSuspendProcess at this point to attempt to achieve this end. The funny thing is, I have this program (do not have access to the source) which, once a file is opened, refuses to suspend. Figuring it was a bug in my scanner, I tried suspending the program, once again when a file is opened, using Process Explorer; it flashes "Suspended" very briefly; I looked under Suspend Count for the threads associated with the process, and it increments just fine when I tell Process Explorer to suspend it…but when I tell Process Explorer to resume the process, it increments the Suspend Count (you read that right, it INCREMENTS it).

So yes, with my memory scanner and Process Explorer, when this program has no files open, it suspends and resumes normally. When the program has a file open, it fails to suspend, and increments the Suspend Count on attempts to resume.

I suspect a number of things here. Somehow, the message to suspend is being duplicated, and being released when resume is called. This explains the Suspend Count incrementing when it should be decrementing. Which might mean the original Suspend message isn’t being consumed properly.

How do I even go about debugging this problem from this point? Where do I start?

Below are some code snippets from my memory scanner:

    const uint PROCESS_SUSPEND_RESUME = 0x0800;
    const uint PROCESS_QUERY_INFORMATION = 0x0400;
    const uint MEM_COMMIT = 0x00001000;
    const uint PAGE_READWRITE = 0x04;
    const uint PROCESS_WM_READ = 0x0010;

    [DllImport("ntdll.dll", EntryPoint = "NtSuspendProcess", SetLastError = true, ExactSpelling = false)]
    private static extern UIntPtr NtSuspendProcess(UIntPtr processHandle);

    [DllImport("ntdll.dll", EntryPoint = "NtResumeProcess", SetLastError = true, ExactSpelling = false)]
    private static extern UIntPtr NtResumeProcess(UIntPtr processHandle);

    public static extern UIntPtr OpenProcess(UIntPtr dwDesiredAccess, bool bInheritHandle, UIntPtr dwProcessId);

    public static extern bool ReadProcessMemory(UIntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr dwSize, out UIntPtr lpNumberOfBytesRead);

    static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern UIntPtr VirtualQueryEx(UIntPtr hProcess, UIntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, UIntPtr dwLength);

    static extern bool CloseHandle(UIntPtr hObject);

private void Button_Extract_Click(object sender, EventArgs e)
            Process process = Process.GetProcessById(int.Parse(DataGridView_Processes.SelectedRows[0].Cells["Process ID"].Value.ToString()));
            UIntPtr processSuspendResumeHandle = OpenProcess(new UIntPtr(PROCESS_SUSPEND_RESUME), false, new UIntPtr((uint)process.Id));

            SYSTEM_INFO sys_info = new SYSTEM_INFO();
            GetSystemInfo(out sys_info);

            UIntPtr proc_min_address = sys_info.minimumApplicationAddress;
            UIntPtr proc_max_address = sys_info.maximumApplicationAddress;

            ulong proc_min_address_l = (ulong)proc_min_address;
            ulong proc_max_address_l = (ulong)proc_max_address;

            UIntPtr processHandle = OpenProcess(new UIntPtr(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ), false, new UIntPtr((uint)process.Id));

//Skip to end

            MessageBox.Show("Extraction Complete.");

Source: Windows Questions