1 | /*
|
---|
2 | MIDLTESTS client.
|
---|
3 |
|
---|
4 | Copyright (C) Stefan Metzmacher 2008
|
---|
5 |
|
---|
6 | This program is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 3 of the License, or
|
---|
9 | (at your option) any later version.
|
---|
10 |
|
---|
11 | This program is distributed in the hope that it will be useful,
|
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | GNU General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #include <stdio.h>
|
---|
21 | #include <stdlib.h>
|
---|
22 | #include <ctype.h>
|
---|
23 | #include <winsock.h>
|
---|
24 | #include "midltests.h"
|
---|
25 |
|
---|
26 | #ifndef _M_AMD64
|
---|
27 | #error "please run 'vcvarsall.bat amd64' -midltests_tcp needs 64-bit support!"
|
---|
28 | #endif
|
---|
29 |
|
---|
30 | #define MIDLTESTS_C_CODE 1
|
---|
31 | #include "midltests.idl"
|
---|
32 |
|
---|
33 | #ifndef LISTEN_IP
|
---|
34 | #define LISTEN_IP "127.0.0.1"
|
---|
35 | #endif
|
---|
36 |
|
---|
37 | #ifndef FORWARD_IP
|
---|
38 | #define FORWARD_IP "127.0.0.1"
|
---|
39 | #endif
|
---|
40 |
|
---|
41 | #ifndef CONNECT_IP
|
---|
42 | #define CONNECT_IP "127.0.0.1"
|
---|
43 | #endif
|
---|
44 |
|
---|
45 | struct NDRTcpThreadCtx;
|
---|
46 |
|
---|
47 | struct NDRProxyThreadCtx {
|
---|
48 | const struct NDRTcpThreadCtx *ctx;
|
---|
49 | SOCKET InSocket;
|
---|
50 | SOCKET OutSocket;
|
---|
51 | DWORD dwThreadId;
|
---|
52 | HANDLE hThread;
|
---|
53 | };
|
---|
54 |
|
---|
55 | struct NDRTcpThreadCtx {
|
---|
56 | const char *name;
|
---|
57 | short listen_port;
|
---|
58 | short client_port;
|
---|
59 | BOOL ndr64;
|
---|
60 | BOOL stop;
|
---|
61 | };
|
---|
62 |
|
---|
63 | struct dcerpc_header {
|
---|
64 | BYTE rpc_vers; /* RPC version */
|
---|
65 | BYTE rpc_vers_minor; /* Minor version */
|
---|
66 | BYTE ptype; /* Packet type */
|
---|
67 | BYTE pfc_flags; /* Fragmentation flags */
|
---|
68 | BYTE drep[4]; /* NDR data representation */
|
---|
69 | short frag_length; /* Total length of fragment */
|
---|
70 | short auth_length; /* authenticator length */
|
---|
71 | DWORD call_id; /* Call identifier */
|
---|
72 | };
|
---|
73 |
|
---|
74 | static void dump_packet(const char *ctx, const char *direction,
|
---|
75 | const unsigned char *buf, int len)
|
---|
76 | {
|
---|
77 | struct dcerpc_header *hdr = (struct dcerpc_header *)buf;
|
---|
78 |
|
---|
79 | if (len < sizeof(struct dcerpc_header)) {
|
---|
80 | printf("%s:%s: invalid dcerpc pdu len(%d)\n",
|
---|
81 | ctx, direction, len);
|
---|
82 | fflush(stdout);
|
---|
83 | return;
|
---|
84 | }
|
---|
85 |
|
---|
86 | if (hdr->rpc_vers != 5 || hdr->rpc_vers_minor != 0) {
|
---|
87 | printf("%s:%s: invalid dcerpc pdu len(%d) ver:%d min:%d\n",
|
---|
88 | ctx, direction, len,
|
---|
89 | hdr->rpc_vers, hdr->rpc_vers_minor);
|
---|
90 | fflush(stdout);
|
---|
91 | return;
|
---|
92 | }
|
---|
93 |
|
---|
94 | if (hdr->frag_length != len) {
|
---|
95 | printf("%s:%s: invalid dcerpc pdu len(%d) should be (%d)\n",
|
---|
96 | ctx, direction, len, hdr->frag_length);
|
---|
97 | fflush(stdout);
|
---|
98 | return;
|
---|
99 | }
|
---|
100 |
|
---|
101 |
|
---|
102 | switch (hdr->ptype) {
|
---|
103 | case 0: /* request */
|
---|
104 | printf("%s:%s: ptype[request] flen[%d] plen[%d] ahint[%d]\n\n",
|
---|
105 | ctx, direction, hdr->frag_length,
|
---|
106 | len - 24, *(DWORD *)(&buf[0x10]));
|
---|
107 | dump_data(buf + 24, len - 24);
|
---|
108 | printf("\n");
|
---|
109 | fflush(stdout);
|
---|
110 | break;
|
---|
111 |
|
---|
112 | case 2: /* response */
|
---|
113 | printf("\n%s:%s: ptype[response] flen[%d] plen[%d] ahint[%d]\n\n",
|
---|
114 | ctx, direction, hdr->frag_length,
|
---|
115 | len - 24, *(DWORD *)(&buf[0x10]));
|
---|
116 | dump_data(buf + 24, len - 24);
|
---|
117 | printf("\n");
|
---|
118 | fflush(stdout);
|
---|
119 | break;
|
---|
120 |
|
---|
121 | case 11: /* bind */
|
---|
122 | #if 0
|
---|
123 | printf("%s:%s: ptype[bind] flen[%d] call[%d] contexts[%d]\n\n"
|
---|
124 | ctx, direction, hdr->frag_length, hdr->call_id,
|
---|
125 | buf[24]);
|
---|
126 | dump_data(buf + 24, len - 24);
|
---|
127 | printf("\n");
|
---|
128 | fflush(stdout);
|
---|
129 | #endif
|
---|
130 | break;
|
---|
131 |
|
---|
132 | case 12: /* bind ack */
|
---|
133 | #if 0
|
---|
134 | printf("%s:%s: ptype[bind_ack] flen[%d] call[%d]\n\n",
|
---|
135 | ctx, direction, hdr->frag_length, hdr->call_id);
|
---|
136 | fflush(stdout);
|
---|
137 | #endif
|
---|
138 | break;
|
---|
139 |
|
---|
140 | case 14: /* alter_req */
|
---|
141 | #if 1
|
---|
142 | printf("%s:%s: ptype[alter_req] flen[%d] call[%d] contexts[%d]\n\n",
|
---|
143 | ctx, direction, hdr->frag_length, hdr->call_id,
|
---|
144 | buf[24]);
|
---|
145 | //dump_data(buf + 24, len - 24);
|
---|
146 | printf("\n");
|
---|
147 | fflush(stdout);
|
---|
148 | #endif
|
---|
149 | break;
|
---|
150 |
|
---|
151 | case 15: /* alter_ack */
|
---|
152 | #if 1
|
---|
153 | printf("%s:%s: ptype[alter_ack] flen[%d] call[%d]\n\n",
|
---|
154 | ctx, direction, hdr->frag_length, hdr->call_id);
|
---|
155 | fflush(stdout);
|
---|
156 | #endif
|
---|
157 | break;
|
---|
158 |
|
---|
159 | default:
|
---|
160 | printf("%s:%s: ptype[%d] flen[%d] call[%d]\n\n",
|
---|
161 | ctx, direction, hdr->ptype, hdr->frag_length, hdr->call_id);
|
---|
162 | fflush(stdout);
|
---|
163 | break;
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 | static void change_packet(const char *ctx, BOOL ndr64,
|
---|
168 | unsigned char *buf, int len)
|
---|
169 | {
|
---|
170 | struct dcerpc_header *hdr = (struct dcerpc_header *)buf;
|
---|
171 | BOOL is_ndr64 = FALSE;
|
---|
172 | const unsigned char ndr64_buf[] = {
|
---|
173 | 0x33, 0x05, 0x71, 0x71, 0xBA, 0xBE, 0x37, 0x49,
|
---|
174 | 0x83, 0x19, 0xB5, 0xDB, 0xEF, 0x9C, 0xCC, 0x36
|
---|
175 | };
|
---|
176 |
|
---|
177 | if (len < sizeof(struct dcerpc_header)) {
|
---|
178 | printf("%s: invalid dcerpc pdu len(%d)\n",
|
---|
179 | ctx, len);
|
---|
180 | fflush(stdout);
|
---|
181 | return;
|
---|
182 | }
|
---|
183 |
|
---|
184 | if (hdr->rpc_vers != 5 || hdr->rpc_vers_minor != 0) {
|
---|
185 | printf("%s: invalid dcerpc pdu len(%d) ver:%d min:%d\n",
|
---|
186 | ctx, len,
|
---|
187 | hdr->rpc_vers, hdr->rpc_vers_minor);
|
---|
188 | fflush(stdout);
|
---|
189 | return;
|
---|
190 | }
|
---|
191 |
|
---|
192 | if (hdr->frag_length != len) {
|
---|
193 | printf("%s: invalid dcerpc pdu len(%d) should be (%d)\n",
|
---|
194 | ctx, len, hdr->frag_length);
|
---|
195 | fflush(stdout);
|
---|
196 | return;
|
---|
197 | }
|
---|
198 |
|
---|
199 | switch (hdr->ptype) {
|
---|
200 | case 11: /* bind */
|
---|
201 | case 14: /* alter_req */
|
---|
202 |
|
---|
203 | if (buf[24] >= 2) {
|
---|
204 | int ret;
|
---|
205 |
|
---|
206 | ret = memcmp(&buf[0x60], ndr64_buf, 16);
|
---|
207 | if (ret == 0) {
|
---|
208 | is_ndr64 = TRUE;
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | if (is_ndr64 && !ndr64) {
|
---|
213 | buf[24+0x48] = 0xFF;
|
---|
214 | memset(&buf[0x60], 0xFF, 16);
|
---|
215 | printf("%s: disable NDR64\n\n", ctx);
|
---|
216 | } else if (!is_ndr64 && ndr64) {
|
---|
217 | printf("\n%s: got NDR32 downgrade\n\n", ctx);
|
---|
218 | #ifndef DONOT_FORCE_NDR64
|
---|
219 | printf("\n\tERROR!!!\n\n");
|
---|
220 | memset(&buf[0x34], 0xFF, 16);
|
---|
221 | printf("You may need to run 'vcvarsall.bat amd64' before 'nmake tcp'\n");
|
---|
222 | #endif
|
---|
223 | printf("\n");
|
---|
224 | } else if (is_ndr64) {
|
---|
225 | printf("%s: got NDR64\n\n", ctx);
|
---|
226 | } else {
|
---|
227 | printf("%s: got NDR32\n\n", ctx);
|
---|
228 | }
|
---|
229 | //printf("%s: bind with %u pres\n", ctx, buf[24]);
|
---|
230 | fflush(stdout);
|
---|
231 | break;
|
---|
232 | }
|
---|
233 | }
|
---|
234 |
|
---|
235 | static int sock_pending(SOCKET s)
|
---|
236 | {
|
---|
237 | int ret, error;
|
---|
238 | int value = 0;
|
---|
239 | int len;
|
---|
240 |
|
---|
241 | ret = ioctlsocket(s, FIONREAD, &value);
|
---|
242 | if (ret == -1) {
|
---|
243 | return ret;
|
---|
244 | }
|
---|
245 |
|
---|
246 | if (ret != 0) {
|
---|
247 | /* this should not be reached */
|
---|
248 | return -1;
|
---|
249 | }
|
---|
250 |
|
---|
251 | if (value != 0) {
|
---|
252 | return value;
|
---|
253 | }
|
---|
254 |
|
---|
255 | error = 0;
|
---|
256 | len = sizeof(error);
|
---|
257 |
|
---|
258 | /*
|
---|
259 | * if no data is available check if the socket is in error state. For
|
---|
260 | * dgram sockets it's the way to return ICMP error messages of
|
---|
261 | * connected sockets to the caller.
|
---|
262 | */
|
---|
263 | ret = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&error, &len);
|
---|
264 | if (ret == -1) {
|
---|
265 | return ret;
|
---|
266 | }
|
---|
267 | if (error != 0) {
|
---|
268 | return -1;
|
---|
269 | }
|
---|
270 | return 0;
|
---|
271 | }
|
---|
272 |
|
---|
273 | DWORD WINAPI NDRProxyThread(LPVOID lpParameter)
|
---|
274 | {
|
---|
275 | struct NDRProxyThreadCtx *p = (struct NDRProxyThreadCtx *)lpParameter;
|
---|
276 |
|
---|
277 | while (!p->ctx->stop) {
|
---|
278 | int r, s;
|
---|
279 | int ret = -1;
|
---|
280 | BYTE buf[5840];
|
---|
281 |
|
---|
282 | Sleep(250);
|
---|
283 |
|
---|
284 | ret = sock_pending(p->InSocket);
|
---|
285 | if (ret == 0) {
|
---|
286 | goto out;
|
---|
287 | }
|
---|
288 |
|
---|
289 | r = recv(p->InSocket, buf, sizeof(buf), 0);
|
---|
290 | if (r <= 0) {
|
---|
291 | ret = WSAGetLastError();
|
---|
292 | printf("%s: recv(in) failed[%d][%d]\n", p->ctx->name, r, ret);
|
---|
293 | fflush(stdout);
|
---|
294 | goto stop;
|
---|
295 | }
|
---|
296 |
|
---|
297 | change_packet(p->ctx->name, p->ctx->ndr64, buf, r);
|
---|
298 | fflush(stdout);
|
---|
299 |
|
---|
300 | dump_packet(p->ctx->name, "in => out", buf, r);
|
---|
301 | fflush(stdout);
|
---|
302 |
|
---|
303 | out:
|
---|
304 | s = send(p->OutSocket, buf, r, 0);
|
---|
305 | if (s <= 0) {
|
---|
306 | ret = WSAGetLastError();
|
---|
307 | printf("%s: send(out) failed[%d][%d]\n", p->ctx->name, s, ret);
|
---|
308 | fflush(stdout);
|
---|
309 | goto stop;
|
---|
310 | }
|
---|
311 |
|
---|
312 | ret = sock_pending(p->OutSocket);
|
---|
313 | if (ret == 0) {
|
---|
314 | goto next;
|
---|
315 | }
|
---|
316 |
|
---|
317 | r = recv(p->OutSocket, buf, sizeof(buf), 0);
|
---|
318 | if (r <= 0) {
|
---|
319 | ret = WSAGetLastError();
|
---|
320 | printf("%s: recv(out) failed[%d][%d]\n", p->ctx->name, r, ret);
|
---|
321 | fflush(stdout);
|
---|
322 | goto stop;
|
---|
323 | }
|
---|
324 |
|
---|
325 | dump_packet(p->ctx->name, "out => in", buf, r);
|
---|
326 | fflush(stdout);
|
---|
327 |
|
---|
328 | s = send(p->InSocket, buf, r, 0);
|
---|
329 | if (s <= 0) {
|
---|
330 | ret = WSAGetLastError();
|
---|
331 | printf("%s: send(in) failed[%d][%d]\n", p->ctx->name, s, ret);
|
---|
332 | fflush(stdout);
|
---|
333 | goto stop;
|
---|
334 | }
|
---|
335 | next:
|
---|
336 | continue;
|
---|
337 | }
|
---|
338 | stop:
|
---|
339 | closesocket(p->InSocket);
|
---|
340 | closesocket(p->OutSocket);
|
---|
341 |
|
---|
342 | printf("NDRTcpThread[%s] stop\n", p->ctx->name);
|
---|
343 | fflush(stdout);
|
---|
344 | return 0;
|
---|
345 | }
|
---|
346 |
|
---|
347 | DWORD WINAPI NDRTcpThread(LPVOID lpParameter)
|
---|
348 | {
|
---|
349 | struct NDRTcpThreadCtx *ctx = (struct NDRTcpThreadCtx *)lpParameter;
|
---|
350 | int ret = -1;
|
---|
351 | SOCKET ListenSocket;
|
---|
352 | struct sockaddr_in saServer;
|
---|
353 | struct sockaddr_in saClient;
|
---|
354 |
|
---|
355 | //printf("NDRTcpThread[%s] start\n", ctx->name);
|
---|
356 | fflush(stdout);
|
---|
357 |
|
---|
358 | ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
---|
359 | if (ListenSocket == INVALID_SOCKET) {
|
---|
360 | ret = WSAGetLastError();
|
---|
361 | printf("socket() failed[%d][%d]\n", ListenSocket, ret);
|
---|
362 | fflush(stdout);
|
---|
363 | goto failed;
|
---|
364 | }
|
---|
365 |
|
---|
366 | saServer.sin_family = AF_INET;
|
---|
367 | saServer.sin_addr.s_addr = inet_addr(LISTEN_IP);
|
---|
368 | saServer.sin_port = htons(ctx->listen_port);
|
---|
369 |
|
---|
370 | saClient.sin_family = AF_INET;
|
---|
371 | saClient.sin_addr.s_addr = inet_addr(FORWARD_IP);
|
---|
372 | saClient.sin_port = htons(ctx->client_port);
|
---|
373 |
|
---|
374 | ret = bind(ListenSocket, (SOCKADDR*)&saServer, sizeof(saServer));
|
---|
375 | if (ret == SOCKET_ERROR) {
|
---|
376 | ret = WSAGetLastError();
|
---|
377 | printf("bind() failed[%d]\n", ret);
|
---|
378 | fflush(stdout);
|
---|
379 | goto failed;
|
---|
380 | }
|
---|
381 |
|
---|
382 | ret = listen(ListenSocket, 10);
|
---|
383 | if (ret == SOCKET_ERROR) {
|
---|
384 | ret = WSAGetLastError();
|
---|
385 | printf("listen() failed[%d]\n", ret);
|
---|
386 | fflush(stdout);
|
---|
387 | goto failed;
|
---|
388 | }
|
---|
389 |
|
---|
390 | while (!ctx->stop) {
|
---|
391 | struct sockaddr_in sa;
|
---|
392 | int sa_len = sizeof(sa);
|
---|
393 | struct NDRProxyThreadCtx *p = malloc(sizeof(*p));
|
---|
394 | p->ctx = ctx;
|
---|
395 |
|
---|
396 | p->InSocket = accept(ListenSocket, (SOCKADDR *)&sa, &sa_len);
|
---|
397 | if (p->InSocket == INVALID_SOCKET) {
|
---|
398 | ret = WSAGetLastError();
|
---|
399 | printf("%s: accept() failed[%d][%d]\n", p->ctx->name, p->InSocket, ret);
|
---|
400 | fflush(stdout);
|
---|
401 | continue;
|
---|
402 | }
|
---|
403 |
|
---|
404 | p->OutSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
---|
405 | if (p->OutSocket == INVALID_SOCKET) {
|
---|
406 | ret = WSAGetLastError();
|
---|
407 | printf("%s: socket(out) failed[%d][%d]\n", p->ctx->name, p->OutSocket, ret);
|
---|
408 | fflush(stdout);
|
---|
409 | closesocket(p->InSocket);
|
---|
410 | continue;
|
---|
411 | }
|
---|
412 |
|
---|
413 | ret = connect(p->OutSocket, (SOCKADDR*)&saClient, sizeof(saClient));
|
---|
414 | if (ret == SOCKET_ERROR) {
|
---|
415 | ret = WSAGetLastError();
|
---|
416 | printf("%s: connect() failed[%d]\n", p->ctx->name, ret);
|
---|
417 | fflush(stdout);
|
---|
418 | closesocket(p->InSocket);
|
---|
419 | closesocket(p->OutSocket);
|
---|
420 | continue;
|
---|
421 | }
|
---|
422 |
|
---|
423 | p->hThread = CreateThread(
|
---|
424 | NULL, // default security attributes
|
---|
425 | 0, // use default stack size
|
---|
426 | NDRProxyThread, // thread function name
|
---|
427 | p, // argument to thread function
|
---|
428 | 0, // use default creation flags
|
---|
429 | &p->dwThreadId);// returns the thread identifier
|
---|
430 | if (p->hThread == NULL) {
|
---|
431 | printf("failed to create thread ndr32\n");
|
---|
432 | fflush(stdout);
|
---|
433 | return -1;
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 | //printf("NDRTcpThread[%s] stop\n", ctx->name);
|
---|
438 | fflush(stdout);
|
---|
439 | return 0;
|
---|
440 | failed:
|
---|
441 | printf("NDRTcpThread[%s] failed[%d]\n", ctx->name, ret);
|
---|
442 | fflush(stdout);
|
---|
443 | return ret;
|
---|
444 | }
|
---|
445 |
|
---|
446 | struct NDRRpcThreadCtx {
|
---|
447 | const char *name;
|
---|
448 | short listen_port;
|
---|
449 | };
|
---|
450 |
|
---|
451 | DWORD WINAPI NDRRpcThread(LPVOID lpParameter)
|
---|
452 | {
|
---|
453 | struct NDRRpcThreadCtx *ctx = (struct NDRRpcThreadCtx *)lpParameter;
|
---|
454 | int ret = -1;
|
---|
455 | RPC_STATUS status;
|
---|
456 | RPC_BINDING_VECTOR *pBindingVector;
|
---|
457 |
|
---|
458 | #define RPC_MIN_CALLS 1
|
---|
459 | #define RPC_MAX_CALLS 20
|
---|
460 |
|
---|
461 | //printf("NDRRpcThread[%s] start\n", ctx->name);
|
---|
462 | fflush(stdout);
|
---|
463 | status = RpcServerUseProtseqEp("ncacn_ip_tcp", RPC_MAX_CALLS, "5055", NULL);
|
---|
464 | if (status) {
|
---|
465 | printf("Failed to register ncacn_ip_tcp endpoint\n");
|
---|
466 | fflush(stdout);
|
---|
467 | return status;
|
---|
468 | }
|
---|
469 |
|
---|
470 | status = RpcServerInqBindings(&pBindingVector);
|
---|
471 | if (status) {
|
---|
472 | printf("Failed RpcServerInqBindings\n");
|
---|
473 | fflush(stdout);
|
---|
474 | return status;
|
---|
475 | }
|
---|
476 |
|
---|
477 | #if 0
|
---|
478 | status = RpcEpRegister(srv_midltests_v0_0_s_ifspec, pBindingVector, NULL, "midltests server");
|
---|
479 | if (status) {
|
---|
480 | printf("Failed RpcEpRegister\n");
|
---|
481 | fflush(stdout);
|
---|
482 | return status;
|
---|
483 | }
|
---|
484 | #endif
|
---|
485 | status = RpcServerRegisterIf(srv_midltests_v0_0_s_ifspec, NULL, NULL);
|
---|
486 | if (status) {
|
---|
487 | printf("Failed to register interface\n");
|
---|
488 | fflush(stdout);
|
---|
489 | return status;
|
---|
490 | }
|
---|
491 |
|
---|
492 | status = RpcServerListen(RPC_MIN_CALLS, RPC_MAX_CALLS, FALSE);
|
---|
493 | if (status) {
|
---|
494 | printf("RpcServerListen returned error %d\n", status);
|
---|
495 | fflush(stdout);
|
---|
496 | return status;
|
---|
497 | }
|
---|
498 |
|
---|
499 | printf("NDRRpcThread[%s] stop\n", ctx->name);
|
---|
500 | fflush(stdout);
|
---|
501 | return 0;
|
---|
502 | failed:
|
---|
503 | printf("NDRRpcThread[%s] failed[%d]\n", ctx->name, ret);
|
---|
504 | fflush(stdout);
|
---|
505 | return ret;
|
---|
506 | }
|
---|
507 |
|
---|
508 | int main(int argc, char **argv)
|
---|
509 | {
|
---|
510 | int ret;
|
---|
511 | struct NDRTcpThreadCtx ctx_ndr32;
|
---|
512 | struct NDRTcpThreadCtx ctx_ndr64;
|
---|
513 | struct NDRRpcThreadCtx ctx_rpc;
|
---|
514 | DWORD dwThreadIdArray[3];
|
---|
515 | HANDLE hThreadArray[3];
|
---|
516 | WORD wVersionRequested = MAKEWORD(2, 2);
|
---|
517 | WSADATA wsaData;
|
---|
518 | char *binding;
|
---|
519 | RPC_STATUS status;
|
---|
520 |
|
---|
521 | ret = WSAStartup(wVersionRequested, &wsaData);
|
---|
522 | if (ret != 0) {
|
---|
523 | printf("WSAStartup failed with error: %d\n", ret);
|
---|
524 | fflush(stdout);
|
---|
525 | return -1;
|
---|
526 | }
|
---|
527 |
|
---|
528 | ctx_ndr32.name = "ndr32";
|
---|
529 | ctx_ndr32.listen_port = 5032;
|
---|
530 | ctx_ndr32.client_port = 5055;
|
---|
531 | ctx_ndr32.ndr64 = FALSE;
|
---|
532 | ctx_ndr32.stop = FALSE;
|
---|
533 | hThreadArray[0] = CreateThread(
|
---|
534 | NULL, // default security attributes
|
---|
535 | 0, // use default stack size
|
---|
536 | NDRTcpThread, // thread function name
|
---|
537 | &ctx_ndr32, // argument to thread function
|
---|
538 | 0, // use default creation flags
|
---|
539 | &dwThreadIdArray[0]); // returns the thread identifier
|
---|
540 | if (hThreadArray[0] == NULL) {
|
---|
541 | printf("failed to create thread ndr32\n");
|
---|
542 | fflush(stdout);
|
---|
543 | return -1;
|
---|
544 | }
|
---|
545 |
|
---|
546 | ctx_ndr64.name = "ndr64";
|
---|
547 | ctx_ndr64.listen_port = 5064;
|
---|
548 | ctx_ndr64.client_port = 5055;
|
---|
549 | ctx_ndr64.ndr64 = TRUE;
|
---|
550 | ctx_ndr64.stop = FALSE;
|
---|
551 | hThreadArray[1] = CreateThread(
|
---|
552 | NULL, // default security attributes
|
---|
553 | 0, // use default stack size
|
---|
554 | NDRTcpThread, // thread function name
|
---|
555 | &ctx_ndr64, // argument to thread function
|
---|
556 | 0, // use default creation flags
|
---|
557 | &dwThreadIdArray[1]); // returns the thread identifier
|
---|
558 | if (hThreadArray[1] == NULL) {
|
---|
559 | printf("failed to create thread ndr64\n");
|
---|
560 | fflush(stdout);
|
---|
561 | return -1;
|
---|
562 | }
|
---|
563 |
|
---|
564 | ctx_rpc.name = "rpc";
|
---|
565 | ctx_rpc.listen_port = 5050;
|
---|
566 | hThreadArray[2] = CreateThread(
|
---|
567 | NULL, // default security attributes
|
---|
568 | 0, // use default stack size
|
---|
569 | NDRRpcThread, // thread function name
|
---|
570 | &ctx_rpc, // argument to thread function
|
---|
571 | 0, // use default creation flags
|
---|
572 | &dwThreadIdArray[2]); // returns the thread identifier
|
---|
573 | if (hThreadArray[2] == NULL) {
|
---|
574 | printf("failed to create thread rpc\n");
|
---|
575 | fflush(stdout);
|
---|
576 | return -1;
|
---|
577 | }
|
---|
578 |
|
---|
579 | printf("Wait for setup of server threads\n");
|
---|
580 | fflush(stdout);
|
---|
581 | ret = WaitForMultipleObjects(3, hThreadArray, TRUE, 3000);
|
---|
582 | if (ret == WAIT_TIMEOUT) {
|
---|
583 | /* OK */
|
---|
584 | } else {
|
---|
585 | printf("Failed to setup of server threads %d:%d\n",
|
---|
586 | ret, GetLastError());
|
---|
587 | fflush(stdout);
|
---|
588 | return -1;
|
---|
589 | }
|
---|
590 | ret = 0;
|
---|
591 |
|
---|
592 | printf("\nTest NDR32\n\n");
|
---|
593 | fflush(stdout);
|
---|
594 | binding = "ncacn_ip_tcp:" CONNECT_IP "[5032]";
|
---|
595 | status = RpcBindingFromStringBinding(
|
---|
596 | binding,
|
---|
597 | &midltests_IfHandle);
|
---|
598 | if (status) {
|
---|
599 | printf("RpcBindingFromStringBinding returned %d\n", status);
|
---|
600 | fflush(stdout);
|
---|
601 | return status;
|
---|
602 | }
|
---|
603 |
|
---|
604 | RpcTryExcept {
|
---|
605 | midltests();
|
---|
606 | } RpcExcept(1) {
|
---|
607 | ret = RpcExceptionCode();
|
---|
608 | printf("NDR32 Runtime error 0x%x\n", ret);
|
---|
609 | fflush(stdout);
|
---|
610 | } RpcEndExcept
|
---|
611 | ctx_ndr32.stop = TRUE;
|
---|
612 |
|
---|
613 | Sleep(250);
|
---|
614 |
|
---|
615 | printf("\nTest NDR64\n\n");
|
---|
616 | binding = "ncacn_ip_tcp:" CONNECT_IP "[5064]";
|
---|
617 | status = RpcBindingFromStringBinding(
|
---|
618 | binding,
|
---|
619 | &midltests_IfHandle);
|
---|
620 | if (status) {
|
---|
621 | printf("RpcBindingFromStringBinding returned %d\n", status);
|
---|
622 | fflush(stdout);
|
---|
623 | return status;
|
---|
624 | }
|
---|
625 |
|
---|
626 | RpcTryExcept {
|
---|
627 | midltests();
|
---|
628 | } RpcExcept(1) {
|
---|
629 | ret = RpcExceptionCode();
|
---|
630 | printf("Runtime error 0x%x\n", ret);
|
---|
631 | fflush(stdout);
|
---|
632 | } RpcEndExcept
|
---|
633 | ctx_ndr64.stop = TRUE;
|
---|
634 |
|
---|
635 | WaitForMultipleObjects(3, hThreadArray, TRUE, 2000);
|
---|
636 |
|
---|
637 | if (ret == 0) {
|
---|
638 | printf("\nTest OK\n");
|
---|
639 | fflush(stdout);
|
---|
640 | } else {
|
---|
641 | printf("\nTest FAILED[%d]\n", ret);
|
---|
642 | fflush(stdout);
|
---|
643 | }
|
---|
644 |
|
---|
645 | return ret;
|
---|
646 | }
|
---|