├── 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 | --------------------------------------------------------------------------------