Last active
June 16, 2018 01:56
-
-
Save yuru4c/3720701323878f88be909b458b4f2f85 to your computer and use it in GitHub Desktop.
艦これ Flash 一時停止プログラムの断片
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Windows.Forms; | |
using Suspender.Utility; | |
namespace Suspender | |
{ | |
internal partial class FormSuspender : Form | |
{ | |
private const int PseudoId = -1; | |
private readonly FormBrowser _browser; | |
private int _video = PseudoId; | |
private int _sound = PseudoId; | |
internal FormSuspender(FormBrowser browser) | |
{ | |
_browser = browser; | |
InitializeComponent(); | |
} | |
private void Suspend() | |
{ | |
_video = PseudoId; | |
_sound = PseudoId; | |
try | |
{ | |
using (var snapshot = new Api.Snapshot( | |
Process.GetProcessById(_browser.BrowserProcess.Id))) | |
{ | |
const string moduleName = "Flash.ocx"; | |
var video = snapshot.GetLastThreadId(moduleName, 8); | |
Api.SuspendThread(video); | |
_video = video; | |
try | |
{ | |
var sound = snapshot.GetLastThreadId(moduleName, 21); | |
Api.SuspendThread(sound); | |
_sound = sound; | |
} | |
catch | |
{ | |
} | |
} | |
} | |
catch | |
{ | |
return; | |
} | |
} | |
private void Resume() | |
{ | |
if (_video != PseudoId) | |
{ | |
try | |
{ | |
Api.ResumeThread(_video); | |
} | |
catch | |
{ | |
} | |
} | |
if (_sound != PseudoId) | |
{ | |
try | |
{ | |
Api.ResumeThread(_sound); | |
} | |
catch | |
{ | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ComponentModel; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
namespace Suspender.Utility | |
{ | |
internal static partial class Api | |
{ | |
#region Private | |
private static IntPtr OpenThread(int threadId, NativeMethods.ThreadAccess threadAccess) | |
{ | |
var hThread = NativeMethods.OpenThread(threadAccess, false, (uint)threadId); | |
if (hThread == IntPtr.Zero) | |
{ | |
throw new Win32Exception(); | |
} | |
return hThread; | |
} | |
private static uint SuspendThread(IntPtr hThread) | |
{ | |
var result = NativeMethods.SuspendThread(hThread); | |
if ((int)result == -1) | |
{ | |
throw new Win32Exception(); | |
} | |
return result; | |
} | |
private static uint ResumeThread(IntPtr hThread) | |
{ | |
var result = NativeMethods.ResumeThread(hThread); | |
if ((int)result == -1) | |
{ | |
throw new Win32Exception(); | |
} | |
return result; | |
} | |
private static IntPtr CreateModuleSnapshot(int processId) | |
{ | |
var snapshot = NativeMethods.CreateToolhelp32Snapshot( | |
NativeMethods.Th32Cs.SnapModule | NativeMethods.Th32Cs.SnapModule32, | |
(uint)processId); | |
if ((int)snapshot == -1) | |
{ | |
throw new Win32Exception(); | |
} | |
return snapshot; | |
} | |
private static string GetThreadModuleName(IntPtr snapshot, int threadId) | |
{ | |
var mod = new NativeMethods.ModuleEntry32 | |
{ | |
dwSize = (uint)Marshal.SizeOf(typeof(NativeMethods.ModuleEntry32)) | |
}; | |
if (!NativeMethods.Module32First(snapshot, ref mod)) | |
{ | |
return null; | |
} | |
var startAddress = GetThreadStartAddress(threadId); | |
do | |
{ | |
var modBaseAddr = (ulong)mod.modBaseAddr; | |
if (startAddress >= modBaseAddr) | |
{ | |
if (startAddress < modBaseAddr + mod.modBaseSize) | |
{ | |
return mod.szModule; | |
} | |
} | |
} while (NativeMethods.Module32Next(snapshot, ref mod)); | |
return null; | |
} | |
private static ulong GetThreadStartAddress(int threadId) | |
{ | |
var threadHandle = OpenThread(threadId, NativeMethods.ThreadAccess.QueryInformation); | |
try | |
{ | |
var threadInformation = Marshal.AllocHGlobal(IntPtr.Size); | |
try | |
{ | |
var ntstatus = NativeMethods.NtQueryInformationThread(threadHandle, | |
NativeMethods.ThreadInfoClass.ThreadQuerySetWin32StartAddress, | |
threadInformation, (uint)IntPtr.Size, IntPtr.Zero); | |
if (ntstatus != 0U) | |
{ | |
throw new Exception(); | |
} | |
return (ulong)Marshal.ReadIntPtr(threadInformation); | |
} | |
finally | |
{ | |
Marshal.FreeHGlobal(threadInformation); | |
} | |
} | |
finally | |
{ | |
NativeMethods.CloseHandle(threadHandle); | |
} | |
} | |
#endregion | |
internal static void SuspendThread(int threadId) | |
{ | |
var hThread = OpenThread(threadId, NativeMethods.ThreadAccess.SuspendResume); | |
try | |
{ | |
SuspendThread(hThread); | |
} | |
finally | |
{ | |
NativeMethods.CloseHandle(hThread); | |
} | |
} | |
internal static void ResumeThread(int threadId) | |
{ | |
var hThread = OpenThread(threadId, NativeMethods.ThreadAccess.SuspendResume); | |
try | |
{ | |
uint suspendCount; | |
do | |
{ | |
suspendCount = ResumeThread(hThread); | |
} while (suspendCount > 1U); | |
} | |
finally | |
{ | |
NativeMethods.CloseHandle(hThread); | |
} | |
} | |
internal class Snapshot : IDisposable | |
{ | |
private readonly IntPtr _snapshot; | |
private readonly ProcessThreadCollection _threads; | |
internal Snapshot(Process process) | |
{ | |
_snapshot = CreateModuleSnapshot(process.Id); | |
_threads = process.Threads; | |
} | |
internal int GetLastThreadId(string module, int priority) | |
{ | |
for (var i = _threads.Count - 1; i >= 0; i--) | |
{ | |
var thread = _threads[i]; | |
if (thread.BasePriority == priority) | |
{ | |
if (GetThreadModuleName(_snapshot, thread.Id) == module) | |
{ | |
return thread.Id; | |
} | |
} | |
} | |
throw new Exception(); | |
} | |
public void Dispose() | |
{ | |
NativeMethods.CloseHandle(_snapshot); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
namespace Suspender.Utility | |
{ | |
partial class Api | |
{ | |
private static class NativeMethods | |
{ | |
private const string Kernel32 = "kernel32.dll"; | |
private const string Ntdll = "ntdll.dll"; | |
#region Thread | |
[Flags] | |
internal enum ThreadAccess : uint | |
{ | |
// Terminate = 0x0001U, | |
SuspendResume = 0x0002U, | |
// GetContext = 0x0008U, | |
// SetContext = 0x0010U, | |
// SetInformation = 0x0020U, | |
QueryInformation = 0x0040U, | |
// SetThreadToken = 0x0080U, | |
// Impersonate = 0x0100U, | |
// DirectImpersonation = 0x0200U | |
} | |
[DllImport(Kernel32, SetLastError = true)] | |
internal static extern IntPtr OpenThread( | |
ThreadAccess dwDesiredAccess, | |
bool bInheritHandle, uint dwThreadId); | |
[DllImport(Kernel32, SetLastError = true)] | |
internal static extern uint SuspendThread(IntPtr hThread); | |
[DllImport(Kernel32, SetLastError = true)] | |
internal static extern uint ResumeThread(IntPtr hThread); | |
#endregion | |
#region Snapshot | |
[Flags] | |
internal enum Th32Cs : uint | |
{ | |
// SnapHeapList = 0x00000001U, | |
// SnapProcess = 0x00000002U, | |
// SnapThread = 0x00000004U, | |
SnapModule = 0x00000008U, | |
SnapModule32 = 0x00000010U, | |
// SnapAll = (SnapHeapList | SnapProcess | SnapThread | SnapModule), | |
// NoHeaps = 0x40000000U, | |
// Inherit = 0x80000000U | |
} | |
[DllImport(Kernel32, SetLastError = true)] | |
internal static extern IntPtr CreateToolhelp32Snapshot(Th32Cs dwFlags, uint th32ProcessId); | |
#endregion | |
#region Module | |
private const int MaxModuleName32 = 255; | |
private const int MaxPath = 260; | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] | |
internal struct ModuleEntry32 | |
{ | |
internal uint dwSize; | |
private readonly uint th32ModuleID; | |
private readonly uint th32ProcessID; | |
private readonly uint GlblcntUsage; | |
private readonly uint ProccntUsage; | |
internal readonly IntPtr modBaseAddr; | |
internal readonly uint modBaseSize; | |
private readonly IntPtr hModule; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxModuleName32 + 1)] | |
internal readonly string szModule; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPath)] | |
private readonly string szExePath; | |
} | |
[DllImport(Kernel32)] | |
internal static extern bool Module32First(IntPtr hSnapshot, ref ModuleEntry32 lpme); | |
[DllImport(Kernel32)] | |
internal static extern bool Module32Next(IntPtr hSnapshot, ref ModuleEntry32 lpme); | |
#endregion | |
#region ThreadInformation | |
internal enum ThreadInfoClass : uint | |
{ | |
ThreadQuerySetWin32StartAddress = 9U | |
} | |
[DllImport(Ntdll)] | |
internal static extern uint NtQueryInformationThread(IntPtr threadHandle, | |
ThreadInfoClass threadInformationClass, | |
IntPtr threadInformation, uint threadInformationLength, IntPtr returnLengthPtr); | |
#endregion | |
[DllImport(Kernel32)] | |
internal static extern bool CloseHandle(IntPtr hObject); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment