├── README.md
├── Client.c
├── Server.c
└── ntalpcapi.h
/README.md:
--------------------------------------------------------------------------------
1 | # ALPC-Example
2 | An example of a client and server using Windows' ALPC functions to send and receive data.
3 | ###
4 | ## Purpose
5 | This example will hopefully help devlopers who want to use ALPC for communication get a basic understanding of the process. There are only a few code samples around that show how to use ALPC and for some reason many of them are high level language implementations. This example uses [Process Hacker's](https://github.com/processhacker/processhacker) (ntlpcapi.h) ALPC header file for function and structs definitions.
6 | ## Further Information
7 | Some other resources that are useful for ALPC programming:
8 | [Alex Ionescu's SyScan talk](http://alex-ionescu.com/Publications/SyScan/syscan2014.pdf)
9 | [Thomas Garnier's ALPC LPE paper](https://recon.cx/2008/a/thomas_garnier/LPC-ALPC-paper.pdf)
10 |
--------------------------------------------------------------------------------
/Client.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "ntalpcapi.h"
5 | #pragma comment(lib, "ntdll.lib")
6 |
7 | #define MSG_LEN 0x100
8 |
9 | LPVOID CreateMsgMem(PPORT_MESSAGE PortMessage, SIZE_T MessageSize, LPVOID Message)
10 | {
11 | /*
12 | It's important to understand that after the PORT_MESSAGE struct is the message data
13 | */
14 | LPVOID lpMem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MessageSize + sizeof(PORT_MESSAGE));
15 | memmove(lpMem, PortMessage, sizeof(PORT_MESSAGE));
16 | memmove((BYTE*)lpMem + sizeof(PORT_MESSAGE), Message, MessageSize);
17 | return(lpMem);
18 | }
19 |
20 | void main()
21 | {
22 | UNICODE_STRING usPort;
23 | PORT_MESSAGE pmSend;
24 | PORT_MESSAGE pmReceive;
25 | NTSTATUS ntRet;
26 | BOOLEAN bBreak;
27 | SIZE_T nLen;
28 | HANDLE hPort;
29 | LPVOID lpMem;
30 | CHAR szInput[MSG_LEN];
31 |
32 | printf("ALPC-Example Client\n");
33 | RtlInitUnicodeString(&usPort, L"\\RPC Control\\NameOfPort");
34 | RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
35 | pmSend.u1.s1.DataLength = MSG_LEN;
36 | pmSend.u1.s1.TotalLength = pmSend.u1.s1.DataLength + sizeof(pmSend);
37 | lpMem = CreateMsgMem(&pmSend, MSG_LEN, L"Hello World!");
38 | ntRet = NtAlpcConnectPort(&hPort, &usPort, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
39 |
40 | printf("[i] NtAlpcConnectPort: 0x%X\n", ntRet);
41 | if (!ntRet)
42 | {
43 | printf("[i] type 'exit' to disconnect from the server\n");
44 | bBreak = TRUE;
45 | while (bBreak)
46 | {
47 | RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
48 | RtlSecureZeroMemory(&szInput, sizeof(szInput));
49 | printf("[.] Enter Message > ");
50 | fgets(&szInput, MSG_LEN, stdin);
51 | pmSend.u1.s1.DataLength = strlen(szInput);
52 | pmSend.u1.s1.TotalLength = pmSend.u1.s1.DataLength + sizeof(PORT_MESSAGE);
53 | lpMem = CreateMsgMem(&pmSend, pmSend.u1.s1.DataLength, &szInput);
54 | ntRet = NtAlpcSendWaitReceivePort(hPort, 0, (PPORT_MESSAGE)lpMem, NULL, NULL, NULL, NULL, NULL);
55 | printf("[i] NtAlpcSendWaitReceivePort: 0x%X\n", ntRet);
56 | HeapFree(GetProcessHeap(), 0, lpMem);
57 | }
58 | }
59 | getchar();
60 | return;
61 | }
62 |
--------------------------------------------------------------------------------
/Server.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "ntalpcapi.h"
5 | #pragma comment(lib, "ntdll.lib")
6 |
7 | #define MAX_MSG_LEN 0x500
8 |
9 | LPVOID AllocMsgMem(SIZE_T Size)
10 | {
11 | /*
12 | It's important to understand that after the PORT_MESSAGE struct is the message data
13 | */
14 | return(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size + sizeof(PORT_MESSAGE)));
15 | }
16 |
17 | void CreatePortAndListen(LPCWSTR PortName)
18 | {
19 | ALPC_PORT_ATTRIBUTES serverPortAttr;
20 | OBJECT_ATTRIBUTES objPort;
21 | UNICODE_STRING usPortName;
22 | PORT_MESSAGE pmRequest;
23 | PORT_MESSAGE pmReceive;
24 | NTSTATUS ntRet;
25 | BOOLEAN bBreak;
26 | HANDLE hConnectedPort;
27 | HANDLE hPort;
28 | SIZE_T nLen;
29 | LPVOID lpMem;
30 | BYTE bTemp;
31 |
32 | RtlInitUnicodeString(&usPortName, PortName);
33 | InitializeObjectAttributes(&objPort, &usPortName, 0, 0, 0);
34 | RtlSecureZeroMemory(&serverPortAttr, sizeof(serverPortAttr));
35 | serverPortAttr.MaxMessageLength = MAX_MSG_LEN; // For ALPC this can be max of 64KB
36 |
37 | ntRet = NtAlpcCreatePort(&hPort, &objPort, &serverPortAttr);
38 | printf("[i] NtAlpcCreatePort: 0x%X\n", ntRet);
39 | if (!ntRet)
40 | {
41 | nLen = sizeof(pmReceive);
42 | ntRet = NtAlpcSendWaitReceivePort(hPort, 0, NULL, NULL, &pmReceive, &nLen, NULL, NULL);
43 | if (!ntRet)
44 | {
45 | RtlSecureZeroMemory(&pmRequest, sizeof(pmRequest));
46 | pmRequest.MessageId = pmReceive.MessageId;
47 | pmRequest.u1.s1.DataLength = 0x0;
48 | pmRequest.u1.s1.TotalLength = pmRequest.u1.s1.DataLength + sizeof(PORT_MESSAGE);
49 | ntRet = NtAlpcAcceptConnectPort(&hConnectedPort, hPort, 0, NULL, NULL, NULL, &pmRequest, NULL, TRUE); // 0
50 | printf("[i] NtAlpcAcceptConnectPort: 0x%X\n", ntRet);
51 | if (!ntRet)
52 | {
53 | bBreak = TRUE;
54 | while (bBreak)
55 | {
56 | nLen = MAX_MSG_LEN;
57 | lpMem = AllocMsgMem(nLen);
58 | NtAlpcSendWaitReceivePort(hPort, 0, NULL, NULL, (PPORT_MESSAGE)lpMem, &nLen, NULL, NULL);
59 | pmReceive = *(PORT_MESSAGE*)lpMem;
60 | if (!strcmp((BYTE*)lpMem + sizeof(PORT_MESSAGE), "exit\n"))
61 | {
62 | printf("[i] Received 'exit' command\n");
63 | HeapFree(GetProcessHeap(), 0, lpMem);
64 | ntRet = NtAlpcDisconnectPort(hPort, 0);
65 | printf("[i] NtAlpcDisconnectPort: %X\n", ntRet);
66 | CloseHandle(hConnectedPort);
67 | CloseHandle(hPort);
68 | ExitThread(0);
69 | }
70 | else
71 | {
72 | printf("[i] Received Data: ");
73 | for (int i = 0; i <= pmReceive.u1.s1.DataLength; i++)
74 | {
75 | bTemp = *(BYTE*)((BYTE*)lpMem + i + sizeof(PORT_MESSAGE));
76 | printf("0x%X ", bTemp);
77 | }
78 | printf("\n");
79 | HeapFree(GetProcessHeap(), 0, lpMem);
80 | }
81 | }
82 | }
83 | }
84 | }
85 | ExitThread(0);
86 | }
87 |
88 | void main()
89 | {
90 | HANDLE hThread;
91 |
92 | printf("[i] ALPC-Example Server\n");
93 | hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&CreatePortAndListen, L"\\RPC Control\\NameOfPort", 0, NULL);
94 | WaitForSingleObject(hThread, INFINITE);
95 | printf("[!] Shuting down server\n");
96 | getchar();
97 | return;
98 | }
99 |
--------------------------------------------------------------------------------
/ntalpcapi.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef _NTLPCAPI_H
3 | #define _NTLPCAPI_H
4 | #include
5 |
6 | // Local Inter-process Communication
7 |
8 | #define PORT_CONNECT 0x0001
9 | #define PORT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1)
10 |
11 | typedef short CSHORT;
12 |
13 | typedef struct _CLIENT_ID64
14 | {
15 | ULONGLONG UniqueProcess;
16 | ULONGLONG UniqueThread;
17 | } CLIENT_ID64, *PCLIENT_ID64;
18 |
19 | typedef struct _PORT_MESSAGE
20 | {
21 | union
22 | {
23 | struct
24 | {
25 | CSHORT DataLength;
26 | CSHORT TotalLength;
27 | } s1;
28 | ULONG Length;
29 | } u1;
30 | union
31 | {
32 | struct
33 | {
34 | CSHORT Type;
35 | CSHORT DataInfoOffset;
36 | } s2;
37 | ULONG ZeroInit;
38 | } u2;
39 | union
40 | {
41 | CLIENT_ID ClientId;
42 | double DoNotUseThisField;
43 | };
44 | ULONG MessageId;
45 | union
46 | {
47 | SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages
48 | ULONG CallbackId; // only valid for LPC_REQUEST messages
49 | };
50 | } PORT_MESSAGE, *PPORT_MESSAGE;
51 |
52 | typedef struct _PORT_DATA_ENTRY
53 | {
54 | PVOID Base;
55 | ULONG Size;
56 | } PORT_DATA_ENTRY, *PPORT_DATA_ENTRY;
57 |
58 | typedef struct _PORT_DATA_INFORMATION
59 | {
60 | ULONG CountDataEntries;
61 | PORT_DATA_ENTRY DataEntries[1];
62 | } PORT_DATA_INFORMATION, *PPORT_DATA_INFORMATION;
63 |
64 | #define LPC_REQUEST 1
65 | #define LPC_REPLY 2
66 | #define LPC_DATAGRAM 3
67 | #define LPC_LOST_REPLY 4
68 | #define LPC_PORT_CLOSED 5
69 | #define LPC_CLIENT_DIED 6
70 | #define LPC_EXCEPTION 7
71 | #define LPC_DEBUG_EVENT 8
72 | #define LPC_ERROR_EVENT 9
73 | #define LPC_CONNECTION_REQUEST 10
74 |
75 | #define LPC_KERNELMODE_MESSAGE (CSHORT)0x8000
76 | #define LPC_NO_IMPERSONATE (CSHORT)0x4000
77 |
78 | #define PORT_VALID_OBJECT_ATTRIBUTES OBJ_CASE_INSENSITIVE
79 |
80 | #ifdef _WIN64
81 | #define PORT_MAXIMUM_MESSAGE_LENGTH 512
82 | #else
83 | #define PORT_MAXIMUM_MESSAGE_LENGTH 256
84 | #endif
85 |
86 | #define LPC_MAX_CONNECTION_INFO_SIZE (16 * sizeof(ULONG_PTR))
87 |
88 | #define PORT_TOTAL_MAXIMUM_MESSAGE_LENGTH \
89 | ((PORT_MAXIMUM_MESSAGE_LENGTH + sizeof(PORT_MESSAGE) + LPC_MAX_CONNECTION_INFO_SIZE + 0xf) & ~0xf)
90 |
91 | typedef struct _LPC_CLIENT_DIED_MSG
92 | {
93 | PORT_MESSAGE PortMsg;
94 | LARGE_INTEGER CreateTime;
95 | } LPC_CLIENT_DIED_MSG, *PLPC_CLIENT_DIED_MSG;
96 |
97 | typedef struct _PORT_VIEW
98 | {
99 | ULONG Length;
100 | HANDLE SectionHandle;
101 | ULONG SectionOffset;
102 | SIZE_T ViewSize;
103 | PVOID ViewBase;
104 | PVOID ViewRemoteBase;
105 | } PORT_VIEW, *PPORT_VIEW;
106 |
107 | typedef struct _REMOTE_PORT_VIEW
108 | {
109 | ULONG Length;
110 | SIZE_T ViewSize;
111 | PVOID ViewBase;
112 | } REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW;
113 |
114 | // WOW64 definitions
115 |
116 | // Except in a small number of special cases, WOW64 programs using the LPC APIs must use the 64-bit versions of the
117 | // PORT_MESSAGE, PORT_VIEW and REMOTE_PORT_VIEW data structures. Note that we take a different approach than the
118 | // official NT headers, which produce 64-bit versions in a 32-bit environment when USE_LPC6432 is defined.
119 |
120 | typedef struct _PORT_MESSAGE64
121 | {
122 | union
123 | {
124 | struct
125 | {
126 | CSHORT DataLength;
127 | CSHORT TotalLength;
128 | } s1;
129 | ULONG Length;
130 | } u1;
131 | union
132 | {
133 | struct
134 | {
135 | CSHORT Type;
136 | CSHORT DataInfoOffset;
137 | } s2;
138 | ULONG ZeroInit;
139 | } u2;
140 | union
141 | {
142 | CLIENT_ID64 ClientId;
143 | double DoNotUseThisField;
144 | };
145 | ULONG MessageId;
146 | union
147 | {
148 | ULONGLONG ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages
149 | ULONG CallbackId; // only valid for LPC_REQUEST messages
150 | };
151 | } PORT_MESSAGE64, *PPORT_MESSAGE64;
152 |
153 | typedef struct _LPC_CLIENT_DIED_MSG64
154 | {
155 | PORT_MESSAGE64 PortMsg;
156 | LARGE_INTEGER CreateTime;
157 | } LPC_CLIENT_DIED_MSG64, *PLPC_CLIENT_DIED_MSG64;
158 |
159 | typedef struct _PORT_VIEW64
160 | {
161 | ULONG Length;
162 | ULONGLONG SectionHandle;
163 | ULONG SectionOffset;
164 | ULONGLONG ViewSize;
165 | ULONGLONG ViewBase;
166 | ULONGLONG ViewRemoteBase;
167 | } PORT_VIEW64, *PPORT_VIEW64;
168 |
169 | typedef struct _REMOTE_PORT_VIEW64
170 | {
171 | ULONG Length;
172 | ULONGLONG ViewSize;
173 | ULONGLONG ViewBase;
174 | } REMOTE_PORT_VIEW64, *PREMOTE_PORT_VIEW64;
175 |
176 | // Port creation
177 |
178 | NTSYSCALLAPI
179 | NTSTATUS
180 | NTAPI
181 | NtCreatePort(
182 | _Out_ PHANDLE PortHandle,
183 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
184 | _In_ ULONG MaxConnectionInfoLength,
185 | _In_ ULONG MaxMessageLength,
186 | _In_opt_ ULONG MaxPoolUsage
187 | );
188 |
189 | NTSYSCALLAPI
190 | NTSTATUS
191 | NTAPI
192 | NtCreateWaitablePort(
193 | _Out_ PHANDLE PortHandle,
194 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
195 | _In_ ULONG MaxConnectionInfoLength,
196 | _In_ ULONG MaxMessageLength,
197 | _In_opt_ ULONG MaxPoolUsage
198 | );
199 |
200 | // Port connection (client)
201 |
202 | NTSYSCALLAPI
203 | NTSTATUS
204 | NTAPI
205 | NtConnectPort(
206 | _Out_ PHANDLE PortHandle,
207 | _In_ PUNICODE_STRING PortName,
208 | _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos,
209 | _Inout_opt_ PPORT_VIEW ClientView,
210 | _Inout_opt_ PREMOTE_PORT_VIEW ServerView,
211 | _Out_opt_ PULONG MaxMessageLength,
212 | _Inout_updates_bytes_to_opt_(*ConnectionInformationLength, *ConnectionInformationLength) PVOID ConnectionInformation,
213 | _Inout_opt_ PULONG ConnectionInformationLength
214 | );
215 |
216 | NTSYSCALLAPI
217 | NTSTATUS
218 | NTAPI
219 | NtSecureConnectPort(
220 | _Out_ PHANDLE PortHandle,
221 | _In_ PUNICODE_STRING PortName,
222 | _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos,
223 | _Inout_opt_ PPORT_VIEW ClientView,
224 | _In_opt_ PSID RequiredServerSid,
225 | _Inout_opt_ PREMOTE_PORT_VIEW ServerView,
226 | _Out_opt_ PULONG MaxMessageLength,
227 | _Inout_updates_bytes_to_opt_(*ConnectionInformationLength, *ConnectionInformationLength) PVOID ConnectionInformation,
228 | _Inout_opt_ PULONG ConnectionInformationLength
229 | );
230 |
231 | // Port connection (server)
232 |
233 | NTSYSCALLAPI
234 | NTSTATUS
235 | NTAPI
236 | NtListenPort(
237 | _In_ HANDLE PortHandle,
238 | _Out_ PPORT_MESSAGE ConnectionRequest
239 | );
240 |
241 | NTSYSCALLAPI
242 | NTSTATUS
243 | NTAPI
244 | NtAcceptConnectPort(
245 | _Out_ PHANDLE PortHandle,
246 | _In_opt_ PVOID PortContext,
247 | _In_ PPORT_MESSAGE ConnectionRequest,
248 | _In_ BOOLEAN AcceptConnection,
249 | _Inout_opt_ PPORT_VIEW ServerView,
250 | _Out_opt_ PREMOTE_PORT_VIEW ClientView
251 | );
252 |
253 | NTSYSCALLAPI
254 | NTSTATUS
255 | NTAPI
256 | NtCompleteConnectPort(
257 | _In_ HANDLE PortHandle
258 | );
259 |
260 | // General
261 |
262 | NTSYSCALLAPI
263 | NTSTATUS
264 | NTAPI
265 | NtRequestPort(
266 | _In_ HANDLE PortHandle,
267 | _In_ PPORT_MESSAGE RequestMessage
268 | );
269 |
270 | NTSYSCALLAPI
271 | NTSTATUS
272 | NTAPI
273 | NtRequestWaitReplyPort(
274 | _In_ HANDLE PortHandle,
275 | _In_ PPORT_MESSAGE RequestMessage,
276 | _Out_ PPORT_MESSAGE ReplyMessage
277 | );
278 |
279 | NTSYSCALLAPI
280 | NTSTATUS
281 | NTAPI
282 | NtReplyPort(
283 | _In_ HANDLE PortHandle,
284 | _In_ PPORT_MESSAGE ReplyMessage
285 | );
286 |
287 | NTSYSCALLAPI
288 | NTSTATUS
289 | NTAPI
290 | NtReplyWaitReplyPort(
291 | _In_ HANDLE PortHandle,
292 | _Inout_ PPORT_MESSAGE ReplyMessage
293 | );
294 |
295 | NTSYSCALLAPI
296 | NTSTATUS
297 | NTAPI
298 | NtReplyWaitReceivePort(
299 | _In_ HANDLE PortHandle,
300 | _Out_opt_ PVOID *PortContext,
301 | _In_opt_ PPORT_MESSAGE ReplyMessage,
302 | _Out_ PPORT_MESSAGE ReceiveMessage
303 | );
304 |
305 | NTSYSCALLAPI
306 | NTSTATUS
307 | NTAPI
308 | NtReplyWaitReceivePortEx(
309 | _In_ HANDLE PortHandle,
310 | _Out_opt_ PVOID *PortContext,
311 | _In_opt_ PPORT_MESSAGE ReplyMessage,
312 | _Out_ PPORT_MESSAGE ReceiveMessage,
313 | _In_opt_ PLARGE_INTEGER Timeout
314 | );
315 |
316 | NTSYSCALLAPI
317 | NTSTATUS
318 | NTAPI
319 | NtImpersonateClientOfPort(
320 | _In_ HANDLE PortHandle,
321 | _In_ PPORT_MESSAGE Message
322 | );
323 |
324 | NTSYSCALLAPI
325 | NTSTATUS
326 | NTAPI
327 | NtReadRequestData(
328 | _In_ HANDLE PortHandle,
329 | _In_ PPORT_MESSAGE Message,
330 | _In_ ULONG DataEntryIndex,
331 | _Out_writes_bytes_to_(BufferSize, *NumberOfBytesRead) PVOID Buffer,
332 | _In_ SIZE_T BufferSize,
333 | _Out_opt_ PSIZE_T NumberOfBytesRead
334 | );
335 |
336 | NTSYSCALLAPI
337 | NTSTATUS
338 | NTAPI
339 | NtWriteRequestData(
340 | _In_ HANDLE PortHandle,
341 | _In_ PPORT_MESSAGE Message,
342 | _In_ ULONG DataEntryIndex,
343 | _In_reads_bytes_(BufferSize) PVOID Buffer,
344 | _In_ SIZE_T BufferSize,
345 | _Out_opt_ PSIZE_T NumberOfBytesWritten
346 | );
347 |
348 | typedef enum _PORT_INFORMATION_CLASS
349 | {
350 | PortBasicInformation,
351 | PortDumpInformation
352 | } PORT_INFORMATION_CLASS;
353 |
354 | NTSYSCALLAPI
355 | NTSTATUS
356 | NTAPI
357 | NtQueryInformationPort(
358 | _In_ HANDLE PortHandle,
359 | _In_ PORT_INFORMATION_CLASS PortInformationClass,
360 | _Out_writes_bytes_to_(Length, *ReturnLength) PVOID PortInformation,
361 | _In_ ULONG Length,
362 | _Out_opt_ PULONG ReturnLength
363 | );
364 |
365 | // Asynchronous Local Inter-process Communication
366 |
367 | // rev
368 | typedef HANDLE ALPC_HANDLE, *PALPC_HANDLE;
369 |
370 | #define ALPC_PORFLG_ALLOW_LPC_REQUESTS 0x20000 // rev
371 | #define ALPC_PORFLG_WAITABLE_PORT 0x40000 // dbg
372 | #define ALPC_PORFLG_SYSTEM_PROCESS 0x100000 // dbg
373 |
374 | // symbols
375 | typedef struct _ALPC_PORT_ATTRIBUTES
376 | {
377 | ULONG Flags;
378 | SECURITY_QUALITY_OF_SERVICE SecurityQos;
379 | SIZE_T MaxMessageLength;
380 | SIZE_T MemoryBandwidth;
381 | SIZE_T MaxPoolUsage;
382 | SIZE_T MaxSectionSize;
383 | SIZE_T MaxViewSize;
384 | SIZE_T MaxTotalSectionSize;
385 | ULONG DupObjectTypes;
386 | #ifdef _WIN64
387 | ULONG Reserved;
388 | #endif
389 | } ALPC_PORT_ATTRIBUTES, *PALPC_PORT_ATTRIBUTES;
390 |
391 | // begin_rev
392 | #define ALPC_MESSAGE_SECURITY_ATTRIBUTE 0x80000000
393 | #define ALPC_MESSAGE_VIEW_ATTRIBUTE 0x40000000
394 | #define ALPC_MESSAGE_CONTEXT_ATTRIBUTE 0x20000000
395 | #define ALPC_MESSAGE_HANDLE_ATTRIBUTE 0x10000000
396 | // end_rev
397 |
398 | // symbols
399 | typedef struct _ALPC_MESSAGE_ATTRIBUTES
400 | {
401 | ULONG AllocatedAttributes;
402 | ULONG ValidAttributes;
403 | } ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;
404 |
405 | // symbols
406 | typedef struct _ALPC_COMPLETION_LIST_STATE
407 | {
408 | union
409 | {
410 | struct
411 | {
412 | ULONG64 Head : 24;
413 | ULONG64 Tail : 24;
414 | ULONG64 ActiveThreadCount : 16;
415 | } s1;
416 | ULONG64 Value;
417 | } u1;
418 | } ALPC_COMPLETION_LIST_STATE, *PALPC_COMPLETION_LIST_STATE;
419 |
420 | #define ALPC_COMPLETION_LIST_BUFFER_GRANULARITY_MASK 0x3f // dbg
421 |
422 | // symbols
423 | typedef struct DECLSPEC_ALIGN(128) _ALPC_COMPLETION_LIST_HEADER
424 | {
425 | ULONG64 StartMagic;
426 |
427 | ULONG TotalSize;
428 | ULONG ListOffset;
429 | ULONG ListSize;
430 | ULONG BitmapOffset;
431 | ULONG BitmapSize;
432 | ULONG DataOffset;
433 | ULONG DataSize;
434 | ULONG AttributeFlags;
435 | ULONG AttributeSize;
436 |
437 | DECLSPEC_ALIGN(128) ALPC_COMPLETION_LIST_STATE State;
438 | ULONG LastMessageId;
439 | ULONG LastCallbackId;
440 | DECLSPEC_ALIGN(128) ULONG PostCount;
441 | DECLSPEC_ALIGN(128) ULONG ReturnCount;
442 | DECLSPEC_ALIGN(128) ULONG LogSequenceNumber;
443 | DECLSPEC_ALIGN(128) RTL_SRWLOCK UserLock;
444 |
445 | ULONG64 EndMagic;
446 | } ALPC_COMPLETION_LIST_HEADER, *PALPC_COMPLETION_LIST_HEADER;
447 |
448 | // private
449 | typedef struct _ALPC_CONTEXT_ATTR
450 | {
451 | PVOID PortContext;
452 | PVOID MessageContext;
453 | ULONG Sequence;
454 | ULONG MessageId;
455 | ULONG CallbackId;
456 | } ALPC_CONTEXT_ATTR, *PALPC_CONTEXT_ATTR;
457 |
458 | // begin_rev
459 | #define ALPC_HANDLEFLG_DUPLICATE_SAME_ACCESS 0x10000
460 | #define ALPC_HANDLEFLG_DUPLICATE_SAME_ATTRIBUTES 0x20000
461 | #define ALPC_HANDLEFLG_DUPLICATE_INHERIT 0x80000
462 | // end_rev
463 |
464 | // private
465 | typedef struct _ALPC_HANDLE_ATTR32
466 | {
467 | ULONG Flags;
468 | ULONG Reserved0;
469 | ULONG SameAccess;
470 | ULONG SameAttributes;
471 | ULONG Indirect;
472 | ULONG Inherit;
473 | ULONG Reserved1;
474 | ULONG Handle;
475 | ULONG ObjectType; // ObjectTypeCode, not ObjectTypeIndex
476 | ULONG DesiredAccess;
477 | ULONG GrantedAccess;
478 | } ALPC_HANDLE_ATTR32, *PALPC_HANDLE_ATTR32;
479 |
480 | // private
481 | typedef struct _ALPC_HANDLE_ATTR
482 | {
483 | ULONG Flags;
484 | ULONG Reserved0;
485 | ULONG SameAccess;
486 | ULONG SameAttributes;
487 | ULONG Indirect;
488 | ULONG Inherit;
489 | ULONG Reserved1;
490 | HANDLE Handle;
491 | PALPC_HANDLE_ATTR32 HandleAttrArray;
492 | ULONG ObjectType; // ObjectTypeCode, not ObjectTypeIndex
493 | ULONG HandleCount;
494 | ACCESS_MASK DesiredAccess;
495 | ACCESS_MASK GrantedAccess;
496 | } ALPC_HANDLE_ATTR, *PALPC_HANDLE_ATTR;
497 |
498 | #define ALPC_SECFLG_CREATE_HANDLE 0x20000 // dbg
499 | #define ALPC_SECFLG_NOSECTIONHANDLE 0x40000
500 | // private
501 | typedef struct _ALPC_SECURITY_ATTR
502 | {
503 | ULONG Flags;
504 | PSECURITY_QUALITY_OF_SERVICE QoS;
505 | ALPC_HANDLE ContextHandle; // dbg
506 | } ALPC_SECURITY_ATTR, *PALPC_SECURITY_ATTR;
507 |
508 | // begin_rev
509 | #define ALPC_VIEWFLG_NOT_SECURE 0x40000
510 | // end_rev
511 |
512 | // private
513 | typedef struct _ALPC_DATA_VIEW_ATTR
514 | {
515 | ULONG Flags;
516 | ALPC_HANDLE SectionHandle;
517 | PVOID ViewBase; // must be zero on input
518 | SIZE_T ViewSize;
519 | } ALPC_DATA_VIEW_ATTR, *PALPC_DATA_VIEW_ATTR;
520 |
521 | // private
522 | typedef enum _ALPC_PORT_INFORMATION_CLASS
523 | {
524 | AlpcBasicInformation, // q: out ALPC_BASIC_INFORMATION
525 | AlpcPortInformation, // s: in ALPC_PORT_ATTRIBUTES
526 | AlpcAssociateCompletionPortInformation, // s: in ALPC_PORT_ASSOCIATE_COMPLETION_PORT
527 | AlpcConnectedSIDInformation, // q: in SID
528 | AlpcServerInformation, // q: inout ALPC_SERVER_INFORMATION
529 | AlpcMessageZoneInformation, // s: in ALPC_PORT_MESSAGE_ZONE_INFORMATION
530 | AlpcRegisterCompletionListInformation, // s: in ALPC_PORT_COMPLETION_LIST_INFORMATION
531 | AlpcUnregisterCompletionListInformation, // s: VOID
532 | AlpcAdjustCompletionListConcurrencyCountInformation, // s: in ULONG
533 | AlpcRegisterCallbackInformation, // kernel-mode only
534 | AlpcCompletionListRundownInformation, // s: VOID
535 | AlpcWaitForPortReferences
536 | } ALPC_PORT_INFORMATION_CLASS;
537 |
538 | // private
539 | typedef struct _ALPC_BASIC_INFORMATION
540 | {
541 | ULONG Flags;
542 | ULONG SequenceNo;
543 | PVOID PortContext;
544 | } ALPC_BASIC_INFORMATION, *PALPC_BASIC_INFORMATION;
545 |
546 | // private
547 | typedef struct _ALPC_PORT_ASSOCIATE_COMPLETION_PORT
548 | {
549 | PVOID CompletionKey;
550 | HANDLE CompletionPort;
551 | } ALPC_PORT_ASSOCIATE_COMPLETION_PORT, *PALPC_PORT_ASSOCIATE_COMPLETION_PORT;
552 |
553 | // private
554 | typedef struct _ALPC_SERVER_INFORMATION
555 | {
556 | union
557 | {
558 | struct
559 | {
560 | HANDLE ThreadHandle;
561 | } In;
562 | struct
563 | {
564 | BOOLEAN ThreadBlocked;
565 | HANDLE ConnectedProcessId;
566 | UNICODE_STRING ConnectionPortName;
567 | } Out;
568 | };
569 | } ALPC_SERVER_INFORMATION, *PALPC_SERVER_INFORMATION;
570 |
571 | // private
572 | typedef struct _ALPC_PORT_MESSAGE_ZONE_INFORMATION
573 | {
574 | PVOID Buffer;
575 | ULONG Size;
576 | } ALPC_PORT_MESSAGE_ZONE_INFORMATION, *PALPC_PORT_MESSAGE_ZONE_INFORMATION;
577 |
578 | // private
579 | typedef struct _ALPC_PORT_COMPLETION_LIST_INFORMATION
580 | {
581 | PVOID Buffer; // PALPC_COMPLETION_LIST_HEADER
582 | ULONG Size;
583 | ULONG ConcurrencyCount;
584 | ULONG AttributeFlags;
585 | } ALPC_PORT_COMPLETION_LIST_INFORMATION, *PALPC_PORT_COMPLETION_LIST_INFORMATION;
586 |
587 | // private
588 | typedef enum _ALPC_MESSAGE_INFORMATION_CLASS
589 | {
590 | AlpcMessageSidInformation, // q: out SID
591 | AlpcMessageTokenModifiedIdInformation, // q: out LUID
592 | AlpcMessageDirectStatusInformation,
593 | AlpcMessageHandleInformation, // ALPC_MESSAGE_HANDLE_INFORMATION
594 | MaxAlpcMessageInfoClass
595 | } ALPC_MESSAGE_INFORMATION_CLASS, *PALPC_MESSAGE_INFORMATION_CLASS;
596 |
597 | typedef struct _ALPC_MESSAGE_HANDLE_INFORMATION
598 | {
599 | ULONG Index;
600 | ULONG Flags;
601 | ULONG Handle;
602 | ULONG ObjectType;
603 | ACCESS_MASK GrantedAccess;
604 | } ALPC_MESSAGE_HANDLE_INFORMATION, *PALPC_MESSAGE_HANDLE_INFORMATION;
605 |
606 | // begin_private
607 |
608 | #if (PHNT_VERSION >= PHNT_VISTA)
609 |
610 | // System calls
611 |
612 | NTSYSCALLAPI
613 | NTSTATUS
614 | NTAPI
615 | NtAlpcCreatePort(
616 | _Out_ PHANDLE PortHandle,
617 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
618 | _In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes
619 | );
620 |
621 | NTSYSCALLAPI
622 | NTSTATUS
623 | NTAPI
624 | NtAlpcDisconnectPort(
625 | _In_ HANDLE PortHandle,
626 | _In_ ULONG Flags
627 | );
628 |
629 | NTSYSCALLAPI
630 | NTSTATUS
631 | NTAPI
632 | NtAlpcQueryInformation(
633 | _In_opt_ HANDLE PortHandle,
634 | _In_ ALPC_PORT_INFORMATION_CLASS PortInformationClass,
635 | _Inout_updates_bytes_to_(Length, *ReturnLength) PVOID PortInformation,
636 | _In_ ULONG Length,
637 | _Out_opt_ PULONG ReturnLength
638 | );
639 |
640 | NTSYSCALLAPI
641 | NTSTATUS
642 | NTAPI
643 | NtAlpcSetInformation(
644 | _In_ HANDLE PortHandle,
645 | _In_ ALPC_PORT_INFORMATION_CLASS PortInformationClass,
646 | _In_reads_bytes_opt_(Length) PVOID PortInformation,
647 | _In_ ULONG Length
648 | );
649 |
650 | NTSYSCALLAPI
651 | NTSTATUS
652 | NTAPI
653 | NtAlpcCreatePortSection(
654 | _In_ HANDLE PortHandle,
655 | _In_ ULONG Flags,
656 | _In_opt_ HANDLE SectionHandle,
657 | _In_ SIZE_T SectionSize,
658 | _Out_ PALPC_HANDLE AlpcSectionHandle,
659 | _Out_ PSIZE_T ActualSectionSize
660 | );
661 |
662 | NTSYSCALLAPI
663 | NTSTATUS
664 | NTAPI
665 | NtAlpcDeletePortSection(
666 | _In_ HANDLE PortHandle,
667 | _Reserved_ ULONG Flags,
668 | _In_ ALPC_HANDLE SectionHandle
669 | );
670 |
671 | NTSYSCALLAPI
672 | NTSTATUS
673 | NTAPI
674 | NtAlpcCreateResourceReserve(
675 | _In_ HANDLE PortHandle,
676 | _Reserved_ ULONG Flags,
677 | _In_ SIZE_T MessageSize,
678 | _Out_ PALPC_HANDLE ResourceId
679 | );
680 |
681 | NTSYSCALLAPI
682 | NTSTATUS
683 | NTAPI
684 | NtAlpcDeleteResourceReserve(
685 | _In_ HANDLE PortHandle,
686 | _Reserved_ ULONG Flags,
687 | _In_ ALPC_HANDLE ResourceId
688 | );
689 |
690 | NTSYSCALLAPI
691 | NTSTATUS
692 | NTAPI
693 | NtAlpcCreateSectionView(
694 | _In_ HANDLE PortHandle,
695 | _Reserved_ ULONG Flags,
696 | _Inout_ PALPC_DATA_VIEW_ATTR ViewAttributes
697 | );
698 |
699 | NTSYSCALLAPI
700 | NTSTATUS
701 | NTAPI
702 | NtAlpcDeleteSectionView(
703 | _In_ HANDLE PortHandle,
704 | _Reserved_ ULONG Flags,
705 | _In_ PVOID ViewBase
706 | );
707 |
708 | NTSYSCALLAPI
709 | NTSTATUS
710 | NTAPI
711 | NtAlpcCreateSecurityContext(
712 | _In_ HANDLE PortHandle,
713 | _Reserved_ ULONG Flags,
714 | _Inout_ PALPC_SECURITY_ATTR SecurityAttribute
715 | );
716 |
717 | NTSYSCALLAPI
718 | NTSTATUS
719 | NTAPI
720 | NtAlpcDeleteSecurityContext(
721 | _In_ HANDLE PortHandle,
722 | _Reserved_ ULONG Flags,
723 | _In_ ALPC_HANDLE ContextHandle
724 | );
725 |
726 | NTSYSCALLAPI
727 | NTSTATUS
728 | NTAPI
729 | NtAlpcRevokeSecurityContext(
730 | _In_ HANDLE PortHandle,
731 | _Reserved_ ULONG Flags,
732 | _In_ ALPC_HANDLE ContextHandle
733 | );
734 |
735 | NTSYSCALLAPI
736 | NTSTATUS
737 | NTAPI
738 | NtAlpcQueryInformationMessage(
739 | _In_ HANDLE PortHandle,
740 | _In_ PPORT_MESSAGE PortMessage,
741 | _In_ ALPC_MESSAGE_INFORMATION_CLASS MessageInformationClass,
742 | _Out_writes_bytes_to_opt_(Length, *ReturnLength) PVOID MessageInformation,
743 | _In_ ULONG Length,
744 | _Out_opt_ PULONG ReturnLength
745 | );
746 |
747 | #define ALPC_MSGFLG_REPLY_MESSAGE 0x1
748 | #define ALPC_MSGFLG_LPC_MODE 0x2 // ?
749 | #define ALPC_MSGFLG_RELEASE_MESSAGE 0x10000 // dbg
750 | #define ALPC_MSGFLG_SYNC_REQUEST 0x20000 // dbg
751 | #define ALPC_MSGFLG_WAIT_USER_MODE 0x100000
752 | #define ALPC_MSGFLG_WAIT_ALERTABLE 0x200000
753 | #define ALPC_MSGFLG_WOW64_CALL 0x80000000 // dbg
754 |
755 | NTSYSCALLAPI
756 | NTSTATUS
757 | NTAPI
758 | NtAlpcConnectPort(
759 | _Out_ PHANDLE PortHandle,
760 | _In_ PUNICODE_STRING PortName,
761 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
762 | _In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
763 | _In_ ULONG Flags,
764 | _In_opt_ PSID RequiredServerSid,
765 | _Inout_updates_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ConnectionMessage,
766 | _Inout_opt_ PULONG BufferLength,
767 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes,
768 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES InMessageAttributes,
769 | _In_opt_ PLARGE_INTEGER Timeout
770 | );
771 |
772 | #if (PHNT_VERSION >= PHNT_WIN8)
773 | NTSYSCALLAPI
774 | NTSTATUS
775 | NTAPI
776 | NtAlpcConnectPortEx(
777 | _Out_ PHANDLE PortHandle,
778 | _In_ POBJECT_ATTRIBUTES ConnectionPortObjectAttributes,
779 | _In_opt_ POBJECT_ATTRIBUTES ClientPortObjectAttributes,
780 | _In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
781 | _In_ ULONG Flags,
782 | _In_opt_ PSECURITY_DESCRIPTOR ServerSecurityRequirements,
783 | _Inout_updates_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ConnectionMessage,
784 | _Inout_opt_ PSIZE_T BufferLength,
785 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes,
786 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES InMessageAttributes,
787 | _In_opt_ PLARGE_INTEGER Timeout
788 | );
789 | #endif
790 |
791 | NTSYSCALLAPI
792 | NTSTATUS
793 | NTAPI
794 | NtAlpcAcceptConnectPort(
795 | _Out_ PHANDLE PortHandle,
796 | _In_ HANDLE ConnectionPortHandle,
797 | _In_ ULONG Flags,
798 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
799 | _In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
800 | _In_opt_ PVOID PortContext,
801 | _In_reads_bytes_(ConnectionRequest->u1.s1.TotalLength) PPORT_MESSAGE ConnectionRequest,
802 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ConnectionMessageAttributes,
803 | _In_ BOOLEAN AcceptConnection
804 | );
805 |
806 | NTSYSCALLAPI
807 | NTSTATUS
808 | NTAPI
809 | NtAlpcSendWaitReceivePort(
810 | _In_ HANDLE PortHandle,
811 | _In_ ULONG Flags,
812 | _In_reads_bytes_opt_(SendMessage->u1.s1.TotalLength) PPORT_MESSAGE SendMessage,
813 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes,
814 | _Out_writes_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ReceiveMessage,
815 | _Inout_opt_ PSIZE_T BufferLength,
816 | _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,
817 | _In_opt_ PLARGE_INTEGER Timeout
818 | );
819 |
820 | #define ALPC_CANCELFLG_TRY_CANCEL 0x1 // dbg
821 | #define ALPC_CANCELFLG_NO_CONTEXT_CHECK 0x8
822 | #define ALPC_CANCELFLGP_FLUSH 0x10000 // dbg
823 |
824 | NTSYSCALLAPI
825 | NTSTATUS
826 | NTAPI
827 | NtAlpcCancelMessage(
828 | _In_ HANDLE PortHandle,
829 | _In_ ULONG Flags,
830 | _In_ PALPC_CONTEXT_ATTR MessageContext
831 | );
832 |
833 | NTSYSCALLAPI
834 | NTSTATUS
835 | NTAPI
836 | NtAlpcImpersonateClientOfPort(
837 | _In_ HANDLE PortHandle,
838 | _In_ PPORT_MESSAGE Message,
839 | _In_ PVOID Flags
840 | );
841 |
842 | #if (PHNT_VERSION >= PHNT_THRESHOLD)
843 | NTSYSCALLAPI
844 | NTSTATUS
845 | NTAPI
846 | NtAlpcImpersonateClientContainerOfPort(
847 | _In_ HANDLE PortHandle,
848 | _In_ PPORT_MESSAGE Message,
849 | _In_ ULONG Flags
850 | );
851 | #endif
852 |
853 | NTSYSCALLAPI
854 | NTSTATUS
855 | NTAPI
856 | NtAlpcOpenSenderProcess(
857 | _Out_ PHANDLE ProcessHandle,
858 | _In_ HANDLE PortHandle,
859 | _In_ PPORT_MESSAGE PortMessage,
860 | _In_ ULONG Flags,
861 | _In_ ACCESS_MASK DesiredAccess,
862 | _In_ POBJECT_ATTRIBUTES ObjectAttributes
863 | );
864 |
865 | NTSYSCALLAPI
866 | NTSTATUS
867 | NTAPI
868 | NtAlpcOpenSenderThread(
869 | _Out_ PHANDLE ThreadHandle,
870 | _In_ HANDLE PortHandle,
871 | _In_ PPORT_MESSAGE PortMessage,
872 | _In_ ULONG Flags,
873 | _In_ ACCESS_MASK DesiredAccess,
874 | _In_ POBJECT_ATTRIBUTES ObjectAttributes
875 | );
876 |
877 | // Support functions
878 |
879 | NTSYSAPI
880 | ULONG
881 | NTAPI
882 | AlpcMaxAllowedMessageLength(
883 | VOID
884 | );
885 |
886 | NTSYSAPI
887 | ULONG
888 | NTAPI
889 | AlpcGetHeaderSize(
890 | _In_ ULONG Flags
891 | );
892 |
893 | #define ALPC_ATTRFLG_ALLOCATEDATTR 0x20000000
894 | #define ALPC_ATTRFLG_VALIDATTR 0x40000000
895 | #define ALPC_ATTRFLG_KEEPRUNNINGATTR 0x60000000
896 |
897 | NTSYSAPI
898 | NTSTATUS
899 | NTAPI
900 | AlpcInitializeMessageAttribute(
901 | _In_ ULONG AttributeFlags,
902 | _Out_opt_ PALPC_MESSAGE_ATTRIBUTES Buffer,
903 | _In_ ULONG BufferSize,
904 | _Out_ PULONG RequiredBufferSize
905 | );
906 |
907 | NTSYSAPI
908 | PVOID
909 | NTAPI
910 | AlpcGetMessageAttribute(
911 | _In_ PALPC_MESSAGE_ATTRIBUTES Buffer,
912 | _In_ ULONG AttributeFlag
913 | );
914 |
915 | NTSYSAPI
916 | NTSTATUS
917 | NTAPI
918 | AlpcRegisterCompletionList(
919 | _In_ HANDLE PortHandle,
920 | _Out_ PALPC_COMPLETION_LIST_HEADER Buffer,
921 | _In_ ULONG Size,
922 | _In_ ULONG ConcurrencyCount,
923 | _In_ ULONG AttributeFlags
924 | );
925 |
926 | NTSYSAPI
927 | NTSTATUS
928 | NTAPI
929 | AlpcUnregisterCompletionList(
930 | _In_ HANDLE PortHandle
931 | );
932 |
933 | #if (PHNT_VERSION >= PHNT_WIN7)
934 | // rev
935 | NTSYSAPI
936 | NTSTATUS
937 | NTAPI
938 | AlpcRundownCompletionList(
939 | _In_ HANDLE PortHandle
940 | );
941 | #endif
942 |
943 | NTSYSAPI
944 | NTSTATUS
945 | NTAPI
946 | AlpcAdjustCompletionListConcurrencyCount(
947 | _In_ HANDLE PortHandle,
948 | _In_ ULONG ConcurrencyCount
949 | );
950 |
951 | NTSYSAPI
952 | BOOLEAN
953 | NTAPI
954 | AlpcRegisterCompletionListWorkerThread(
955 | _Inout_ PVOID CompletionList
956 | );
957 |
958 | NTSYSAPI
959 | BOOLEAN
960 | NTAPI
961 | AlpcUnregisterCompletionListWorkerThread(
962 | _Inout_ PVOID CompletionList
963 | );
964 |
965 | NTSYSAPI
966 | VOID
967 | NTAPI
968 | AlpcGetCompletionListLastMessageInformation(
969 | _In_ PVOID CompletionList,
970 | _Out_ PULONG LastMessageId,
971 | _Out_ PULONG LastCallbackId
972 | );
973 |
974 | NTSYSAPI
975 | ULONG
976 | NTAPI
977 | AlpcGetOutstandingCompletionListMessageCount(
978 | _In_ PVOID CompletionList
979 | );
980 |
981 | NTSYSAPI
982 | PPORT_MESSAGE
983 | NTAPI
984 | AlpcGetMessageFromCompletionList(
985 | _In_ PVOID CompletionList,
986 | _Out_opt_ PALPC_MESSAGE_ATTRIBUTES *MessageAttributes
987 | );
988 |
989 | NTSYSAPI
990 | VOID
991 | NTAPI
992 | AlpcFreeCompletionListMessage(
993 | _Inout_ PVOID CompletionList,
994 | _In_ PPORT_MESSAGE Message
995 | );
996 |
997 | NTSYSAPI
998 | PALPC_MESSAGE_ATTRIBUTES
999 | NTAPI
1000 | AlpcGetCompletionListMessageAttributes(
1001 | _In_ PVOID CompletionList,
1002 | _In_ PPORT_MESSAGE Message
1003 | );
1004 |
1005 | #endif
1006 |
1007 | // end_private
1008 |
1009 | #endif
1010 |
--------------------------------------------------------------------------------