LPC 的一個(gè)示例(Ntdll Port API test)
之前小小學(xué)了一點(diǎn)win32 LPC的知識(shí),這個(gè)sample是wine ref的一個(gè)test,感覺已經(jīng)很全面。
今天還找來了兩本關(guān)于Ntdll方面的電子書,Windows_2000_Native_API_Reference,
Undocumented Windows 2000 Secrets..都是英文書,慢慢啃。
1 /* Unit test suite for Ntdll Port API functions 2 * 3 * Copyright 2006 James Hawkins 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include <stdio.h> 21 #include <stdarg.h> 22 23 #include "24 #define WIN32_NO_STATUS 25 #include "26 #include "27 #include "28 #include "29 #include "30 #include "31 #include "32 33 #ifndef __WINE_WINTERNL_H 34 35 typedef struct _CLIENT_ID 36 { 37 HANDLE UniqueProcess; 38 HANDLE UniqueThread; 39 } CLIENT_ID, *PCLIENT_ID; 40 41 typedef struct _LPC_SECTION_WRITE 42 { 43 ULONG Length; 44 HANDLE SectionHandle; 45 ULONG SectionOffset; 46 ULONG ViewSize; 47 PVOID ViewBase; 48 PVOID TargetViewBase; 49 } LPC_SECTION_WRITE, *PLPC_SECTION_WRITE; 50 51 typedef struct _LPC_SECTION_READ 52 { 53 ULONG Length; 54 ULONG ViewSize; 55 PVOID ViewBase; 56 } LPC_SECTION_READ, *PLPC_SECTION_READ; 57 58 typedef struct _LPC_MESSAGE 59 { 60 USHORT DataSize; 61 USHORT MessageSize; 62 USHORT MessageType; 63 USHORT VirtualRangesOffset; 64 CLIENT_ID ClientId; 65 ULONG MessageId; 66 ULONG SectionSize; 67 UCHAR Data[ANYSIZE_ARRAY]; 68 } LPC_MESSAGE, *PLPC_MESSAGE; 69 70 #endif 71 72 /* Types of LPC messages */ 73 #define UNUSED_MSG_TYPE 0 74 #define LPC_REQUEST 1 75 #define LPC_REPLY 2 76 #define LPC_DATAGRAM 3 77 #define LPC_LOST_REPLY 4 78 #define LPC_PORT_CLOSED 5 79 #define LPC_CLIENT_DIED 6 80 #define LPC_EXCEPTION 7 81 #define LPC_DEBUG_EVENT 8 82 #define LPC_ERROR_EVENT 9 83 #define LPC_CONNECTION_REQUEST 10 84 85 static const WCHAR PORTNAME[] = {'\\','M','y','P','o','r','t',0}; 86 87 #define REQUEST1 "Request1" 88 #define REQUEST2 "Request2" 89 #define REPLY "Reply" 90 91 #define MAX_MESSAGE_LEN 30 92 93 UNICODE_STRING port; 94 static char selfname[MAX_PATH]; 95 static int myARGC; 96 static char** myARGV; 97 98 /* Function pointers for ntdll calls */ 99 static HMODULE hntdll = 0; 100 static NTSTATUS (WINAPI *pNtCompleteConnectPort)(HANDLE); 101 static NTSTATUS (WINAPI *pNtAcceptConnectPort)(PHANDLE,ULONG,PLPC_MESSAGE,ULONG, 102 ULONG,PLPC_SECTION_READ); 103 static NTSTATUS (WINAPI *pNtReplyPort)(HANDLE,PLPC_MESSAGE); 104 static NTSTATUS (WINAPI *pNtReplyWaitReceivePort)(PHANDLE,PULONG,PLPC_MESSAGE, 105 PLPC_MESSAGE); 106 static NTSTATUS (WINAPI *pNtCreatePort)(PHANDLE,POBJECT_ATTRIBUTES,ULONG,ULONG,ULONG); 107 static NTSTATUS (WINAPI *pNtRequestWaitReplyPort)(HANDLE,PLPC_MESSAGE,PLPC_MESSAGE); 108 static NTSTATUS (WINAPI *pNtRequestPort)(HANDLE,PLPC_MESSAGE); 109 static NTSTATUS (WINAPI *pNtRegisterThreadTerminatePort)(HANDLE); 110 static NTSTATUS (WINAPI *pNtConnectPort)(PHANDLE,PUNICODE_STRING, 111 PSECURITY_QUALITY_OF_SERVICE, 112 PLPC_SECTION_WRITE,PLPC_SECTION_READ, 113 PVOID,PVOID,PULONG); 114 static NTSTATUS (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING,LPCWSTR); 115 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE,BOOLEAN,PLARGE_INTEGER); 116 117 static BOOL init_function_ptrs(void) 118 { 119 hntdll = ); 120 121 if (hntdll) 122 { 123 pNtCompleteConnectPort = (void *)GetProcAddress(hntdll, "NtCompleteConnectPort"); 124 pNtAcceptConnectPort = (void *)GetProcAddress(hntdll, "NtAcceptConnectPort"); 125 pNtReplyPort = (void *)GetProcAddress(hntdll, "NtReplyPort"); 126 pNtReplyWaitReceivePort = (void *)GetProcAddress(hntdll, "NtReplyWaitReceivePort"); 127 pNtCreatePort = (void *)GetProcAddress(hntdll, "NtCreatePort"); 128 pNtRequestWaitReplyPort = (void *)GetProcAddress(hntdll, "NtRequestWaitReplyPort"); 129 pNtRequestPort = (void *)GetProcAddress(hntdll, "NtRequestPort"); 130 pNtRegisterThreadTerminatePort = (void *)GetProcAddress(hntdll, "NtRegisterThreadTerminatePort"); 131 pNtConnectPort = (void *)GetProcAddress(hntdll, "NtConnectPort"); 132 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString"); 133 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); 134 } 135 136 if (!pNtCompleteConnectPort || !pNtAcceptConnectPort || 137 !pNtReplyWaitReceivePort || !pNtCreatePort || !pNtRequestWaitReplyPort || 138 !pNtRequestPort || !pNtRegisterThreadTerminatePort || 139 !pNtConnectPort || !pRtlInitUnicodeString) 140 { 141 return FALSE; 142 } 143 144 return TRUE; 145 } 146 147 static void ProcessConnectionRequest(PLPC_MESSAGE LpcMessage, PHANDLE pAcceptPortHandle) 148 { 149 NTSTATUS status; 150 151 ok(LpcMessage->MessageType == LPC_CONNECTION_REQUEST, 152 "Expected LPC_CONNECTION_REQUEST, got %d\n", LpcMessage->MessageType); 153 ok(!*LpcMessage->Data, "Expected empty string!\n"); 154 155 status = pNtAcceptConnectPort(pAcceptPortHandle, 0, LpcMessage, 1, 0, NULL); 156 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 157 158 status = pNtCompleteConnectPort(*pAcceptPortHandle); 159 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 160 } 161 162 static void ProcessLpcRequest(HANDLE PortHandle, PLPC_MESSAGE LpcMessage) 163 { 164 NTSTATUS status; 165 166 ok(LpcMessage->MessageType == LPC_REQUEST, 167 "Expected LPC_REQUEST, got %d\n", LpcMessage->MessageType); 168 ok(!lstrcmp((LPSTR)LpcMessage->Data, REQUEST2), 169 "Expected %s, got %s\n", REQUEST2, LpcMessage->Data); 170 171 lstrcpy((LPSTR)LpcMessage->Data, REPLY); 172 173 status = pNtReplyPort(PortHandle, LpcMessage); 174 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 175 ok(LpcMessage->MessageType == LPC_REQUEST, 176 "Expected LPC_REQUEST, got %d\n", LpcMessage->MessageType); 177 ok(!lstrcmp((LPSTR)LpcMessage->Data, REPLY), 178 "Expected %s, got %s\n", REPLY, LpcMessage->Data); 179 } 180 181 static DWORD WINAPI test_ports_client(LPVOID arg) 182 { 183 SECURITY_QUALITY_OF_SERVICE sqos; 184 LPC_MESSAGE *LpcMessage, *out; 185 HANDLE PortHandle; 186 ULONG len, size; 187 NTSTATUS status; 188 189 sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 190 sqos.ImpersonationLevel = SecurityImpersonation; 191 sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING; 192 sqos.EffectiveOnly = TRUE; 193 194 status = pNtConnectPort(&PortHandle, &port, &sqos, 0, 0, &len, NULL, NULL); 195 todo_wine ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 196 if (status != STATUS_SUCCESS) return 1; 197 198 status = pNtRegisterThreadTerminatePort(PortHandle); 199 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 200 201 size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN; 202 LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 203 out = HeapAlloc(GetProcessHeap(), 0, size); 204 205 LpcMessage->DataSize = lstrlen(REQUEST1) + 1; 206 LpcMessage->MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data) + LpcMessage->DataSize; 207 lstrcpy((LPSTR)LpcMessage->Data, REQUEST1); 208 209 status = pNtRequestPort(PortHandle, LpcMessage); 210 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 211 ok(LpcMessage->MessageType == 0, "Expected 0, got %d\n", LpcMessage->MessageType); 212 ok(!lstrcmp((LPSTR)LpcMessage->Data, REQUEST1), 213 "Expected %s, got %s\n", REQUEST1, LpcMessage->Data); 214 215 /* Fill in the message */ 216 memset(LpcMessage, 0, size); 217 LpcMessage->DataSize = lstrlen(REQUEST2) + 1; 218 LpcMessage->MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data) + LpcMessage->DataSize; 219 lstrcpy((LPSTR)LpcMessage->Data, REQUEST2); 220 221 /* Send the message and wait for the reply */ 222 status = pNtRequestWaitReplyPort(PortHandle, LpcMessage, out); 223 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 224 ok(!lstrcmp((LPSTR)out->Data, REPLY), "Expected %s, got %s\n", REPLY, out->Data); 225 ok(out->MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->MessageType); 226 227 return 0; 228 } 229 230 static void test_ports_server(void) 231 { 232 OBJECT_ATTRIBUTES obj; 233 HANDLE PortHandle; 234 HANDLE AcceptPortHandle; 235 PLPC_MESSAGE LpcMessage; 236 ULONG size; 237 NTSTATUS status; 238 BOOL done = FALSE; 239 240 pRtlInitUnicodeString(&port, PORTNAME); 241 242 memset(&obj, 0, sizeof(OBJECT_ATTRIBUTES)); 243 obj.Length = sizeof(OBJECT_ATTRIBUTES); 244 obj.ObjectName = &port; 245 246 status = pNtCreatePort(&PortHandle, &obj, 100, 100, 0); 247 todo_wine 248 { 249 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status); 250 } 251 if (status != STATUS_SUCCESS) return; 252 253 size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN; 254 LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 255 256 while (TRUE) 257 { 258 status = pNtReplyWaitReceivePort(PortHandle, NULL, NULL, LpcMessage); 259 todo_wine 260 { 261 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d(%x)\n", status, status); 262 } 263 /* STATUS_INVALID_HANDLE: win2k without admin rights will perform an 264 * endless loop here 265 */ 266 if ((status == STATUS_NOT_IMPLEMENTED) || 267 (status == STATUS_INVALID_HANDLE)) return; 268 269 switch (LpcMessage->MessageType) 270 { 271 case LPC_CONNECTION_REQUEST: 272 ProcessConnectionRequest(LpcMessage, &AcceptPortHandle); 273 break; 274 275 case LPC_REQUEST: 276 ProcessLpcRequest(PortHandle, LpcMessage); 277 done = TRUE; 278 break; 279 280 case LPC_DATAGRAM: 281 ok(!lstrcmp((LPSTR)LpcMessage->Data, REQUEST1), 282 "Expected %s, got %s\n", REQUEST1, LpcMessage->Data); 283 break; 284 285 case LPC_CLIENT_DIED: 286 ok(done, "Expected LPC request to be completed!\n"); 287 return; 288 289 default: 290 ok(FALSE, "Unexpected message: %d\n", LpcMessage->MessageType); 291 break; 292 } 293 } 294 } 295 296 START_TEST(port) 297 { 298 HANDLE thread; 299 DWORD id; 300 301 if (!init_function_ptrs()) 302 return; 303 304 myARGC = winetest_get_mainargs(&myARGV); 305 strcpy(selfname, myARGV[0]); 306 307 thread = CreateThread(NULL, 0, test_ports_client, NULL, 0, &id); 308 ok(thread != NULL, "Expected non-NULL thread handle!\n"); 309 310 test_ports_server(); 311 CloseHandle(thread); 312 } 313
posted on 2008-02-28 00:48 Gohan 閱讀(1758) 評(píng)論(0) 編輯 收藏 引用 所屬分類: MFC/SDK