Hooking Project

Functions for  process manipulation

License
Boost License 1.0.
Authors
Denis Shelomovskij

struct  Process;

This struct encapsulates process hooking functionality.


static @property Process  currentLocal();

Returns a Process with pseudo handle of current processes retrieved by GetCurrentProcess that is valid only in the context of current processes.


static Process  getCurrentGlobal();

Returns a Process with "real" handle of current processes that is valid in the context of other processes.


static @property uint[]  getRunningIds();

Returns process identifiers of all running processes.

Example:
	import std.algorithm;

	bool isProcessRunning(int processId)
	{
		return Process.getRunningIds().canFind(processId);
	}

this(DWORD processId, DWORD desiredAccess, bool tryUsePseudoHandle);

Construct a Process from a processId. If tryUsePseudoHandle is true and processId is current process id then pseudo handle with PROCESS_ALL_ACCESS access will be used. Otherwise if desiredAccess is non-zero then a process handle will be opened with requested access. Otherwise no handle is opened. In the latter case for each member function with "Required handle access" paragraph in documentation call a temporary handle with required access is opened.


this(HANDLE processHandle, DWORD handleAccess, bool remainPseudoHandle);

Construct a Process from a processHandle. processHandle access obtained when it was opened should be passed as handleAccess parameter. If remainPseudoHandle is false and processHandle is pseudo handle of current process then "real" handle with access from handleAccess will be opened instead. If remainPseudoHandle is true and processHandle is pseudo handle then handleAccess will be set to PROCESS_ALL_ACCESS.

processId will not be set iff resulting handleAccess doesn't include PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION. In this case calling closeHandle will result in unassociation of this struct.


this(in ProcessStartInfo startInfo, out Thread primaryThread);
this(in ProcessStartInfo startInfo);

Launch a new process.

handleAccess will be set to PROCESS_ALL_ACCESS. primaryThread will be set.

Preconditions:
startInfo is associated.
Example:
	// With executable file searching:
	{ Process(ProcessStartInfo("notepad", true)); }

	// Without executable file searching:
	import std.process;
	immutable path = environment["windir"] ~ `\system32\notepad.exe`;
	{ Process(ProcessStartInfo(path, null)); } // using file & arguments
	{ Process(ProcessStartInfo('"' ~ path ~ '"')); } // using command line

const pure nothrow @property @safe bool  associated();

Returns whether process is associated with a process. It is asserted that no member functions are called for an unassociated Process struct.

Example:
	assert(Process.currentLocal.associated);
	assert(!Process.init.associated);
	auto h = Process.init.handle; // assert violation

@property HANDLE  handle();

Gets the native handle.


const @property DWORD  handleAccess();

Gets access to the handle.


const @property DWORD  processId();

Gets the process identifier.


@property ProcessMemory  memory();

Gets associated ProcessMemory instance.


@property bool  isWOW64();

Determines whether this process is running under WOW64.

Required handle access: PROCESS_QUERY_INFORMATION


void  initializeWindowsStuff(ref Thread primaryThread);
void  initializeWindowsStuff();

Initializes internal Windows stuff required for WinAPI functions like EnumProcessModules.

When a process is created such stuff isn't initialized unless some process code is executed.

Preconditions:
The process is created suspended and not started yet or its primary thread is paused before initialization is finished (before module entry point is reached in current implementation). Preconditions violation results in undefined behavior.

Required handle access: PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION
Example:
	import std.process;
	auto p = Process(environment["windir"] ~ `\system32\notepad.exe`, null, true);
	scope(exit) p.terminate();

	HMODULE[256] buff;
	DWORD needed;

	// The call will fail because internal Windows stuff isn't initialized yet:
	assert(!EnumProcessModules(p.handle, buff.ptr, buff.sizeof, &needed));

	p.initializeWindowsStuff();

	assert(EnumProcessModules(p.handle, buff.ptr, buff.sizeof, &needed));

void*[]  getModules();

Gets loaded modules.

Preconditions:
Initialized internal Windows stuff. No DLL are loaded/unloaded during function call. Preconditions violation results in undefined behavior.

Required handle access: PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
Example:
	import std.process: environment;
	auto p = Process(environment["windir"] ~ `\system32\notepad.exe`, null, true);
	scope(exit) p.terminate();

	p.initializeWindowsStuff();
	auto modules = p.getModules();

uint[]  getThreadIds();

Returns thread identifiers of all running threads in the process.

Required handle access: PROCESS_QUERY_INFORMATION | PROCESS_VM_READ


void  loadDll(ref Thread thread, string dllName);

Loads module into the process.

Preconditions:
Initialized internal Windows stuff. Preconditions violation results in undefined behavior.

Required handle access: PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION

void  terminate(uint exitCode = -1);

Terminates the process and set its exit code with exitCode.

Calls TerminateProcess.

Required handle access: PROCESS_TERMINATE


int  waitForExit();

Waits for the process to exit and returns exit code.

Required handle access: SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION


bool  waitForExit(Duration duration, out uint exitCode);
bool  waitForExit(Duration duration);

Waits the specified duration for the process to exit and returns wheter it exited. If it does exited, set exitCode with the process exit code.

Required handle access: SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION

Known Bugs
If total milliseconds in duration >= uint.max (more than 49 days) it will wait infinite time (i.e. equals to  waitForExit()).

void  closeHandle();

Closes native handle if any.