{
	"id": "8d31c908-bd14-4498-a024-c87768af792a",
	"created_at": "2026-04-06T00:08:00.173119Z",
	"updated_at": "2026-04-10T03:21:55.063291Z",
	"deleted_at": null,
	"sha1_hash": "c93c4609bcf70756be469013fbdf291fc4109e77",
	"title": "Asynchronous Procedure Calls - Win32 apps",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 50957,
	"plain_text": "Asynchronous Procedure Calls - Win32 apps\r\nBy stevewhims\r\nArchived: 2026-04-05 21:56:58 UTC\r\nAn asynchronous procedure call (APC) is a function that executes asynchronously in the context of a particular\r\nthread. When an APC is queued to a thread, the system issues a software interrupt. The next time the thread is\r\nscheduled, it will run the APC function. An APC generated by the system is called a kernel-mode APC. An APC\r\ngenerated by an application is called a user-mode APC. A thread must be in an alertable state to run a user-mode\r\nAPC.\r\nEach thread has its own APC queue. An application queues an APC to a thread by calling the QueueUserAPC\r\nfunction. The calling thread specifies the address of an APC function in the call to QueueUserAPC. The queuing\r\nof an APC is a request for the thread to call the APC function.\r\nWhen a user-mode APC is queued, the thread to which it is queued is not directed to call the APC function unless\r\nit is in an alertable state. A thread enters an alertable state when it calls the SleepEx, SignalObjectAndWait,\r\nMsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx, or WaitForSingleObjectEx function. If the wait\r\nis satisfied before the APC is queued, the thread is no longer in an alertable wait state so the APC function will not\r\nbe executed. However, the APC is still queued, so the APC function will be executed when the thread calls another\r\nalertable wait function.\r\nThe ReadFileEx, SetWaitableTimer, SetWaitableTimerEx, and WriteFileEx functions are implemented using\r\nan APC as the completion notification callback mechanism.\r\nIf you are using a thread pool, note that APCs do not work as well as other signaling mechanisms because the\r\nsystem controls the lifetime of thread pool threads, so it is possible for a thread to be terminated before the\r\nnotification is delivered. Instead of using an APC-based signaling mechanism such as the pfnCompletionRoutine\r\nparameter of SetWaitableTimer or SetWaitableTimerEx, use a waitable object such as a timer created with\r\nCreateThreadpoolTimer. For I/O, use an I/O completion object created with CreateThreadpoolIo or an hEvent-based OVERLAPPED structure where the event can be passed to the SetThreadpoolWait function.\r\nWhen an I/O request is issued, a structure is allocated to represent the request. This structure is called an I/O\r\nrequest packet (IRP). With synchronous I/O, the thread builds the IRP, sends it to the device stack, and waits in the\r\nkernel for the IRP to complete. With asynchronous I/O, the thread builds the IRP and sends it to the device stack.\r\nThe stack might complete the IRP immediately, or it might return a pending status indicating that the request is in\r\nprogress. When this happens, the IRP is still associated with the thread, so it will be canceled if the thread\r\nterminates or calls a function such as CancelIo. In the meantime, the thread can continue to perform other tasks\r\nwhile the device stack continues to process the IRP.\r\nThere are several ways that the system can indicate that the IRP has completed:\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms681951.aspx\r\nPage 1 of 2\n\nUpdate the overlapped structure with the result of the operation so the thread can poll to determine whether\r\nthe operation has completed.\r\nSignal the event in the overlapped structure so a thread can synchronize on the event and be woken when\r\nthe operation completes.\r\nQueue the IRP to the thread's pending APC so that the thread will execute the APC routine when it enters\r\nan alertable wait state and return from the wait operation with a status indicating that it executed one or\r\nmore APC routines.\r\nQueue the IRP to an I/O completion port, where it will be executed by the next thread that waits on the\r\ncompletion port.\r\nThreads that wait on an I/O completion port do not wait in an alertable state. Therefore, if those threads issue IRPs\r\nthat are set to complete as APCs to the thread, those IPC completions will not occur in a timely manner; they will\r\noccur only if the thread picks up a request from the I/O completion port and then happens to enter an alertable\r\nwait.\r\nUsing a Waitable Timer with an Asynchronous Procedure Call\r\nSource: https://msdn.microsoft.com/library/windows/desktop/ms681951.aspx\r\nhttps://msdn.microsoft.com/library/windows/desktop/ms681951.aspx\r\nPage 2 of 2",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://msdn.microsoft.com/library/windows/desktop/ms681951.aspx"
	],
	"report_names": [
		"ms681951.aspx"
	],
	"threat_actors": [],
	"ts_created_at": 1775434080,
	"ts_updated_at": 1775791315,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/c93c4609bcf70756be469013fbdf291fc4109e77.pdf",
		"text": "https://archive.orkl.eu/c93c4609bcf70756be469013fbdf291fc4109e77.txt",
		"img": "https://archive.orkl.eu/c93c4609bcf70756be469013fbdf291fc4109e77.jpg"
	}
}