1 /*
2 * RPC endpoint mapper
3 *
4 * Copyright 2002 Greg Turner
5 * Copyright 2001 Ove Kåven, TransGaming Technologies
6 * Copyright 2008 Robert Shearman (for CodeWeavers)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "winsvc.h"
29
30 #include "rpc.h"
31
32 #include "wine/debug.h"
33 #include "wine/exception.h"
34
35 #include "rpc_binding.h"
36 #include "epm_c.h"
37 #include "epm_towers.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40
41 /* The "real" RPC portmapper endpoints that I know of are:
42 *
43 * ncadg_ip_udp: 135
44 * ncacn_ip_tcp: 135
45 * ncacn_np: \\pipe\epmapper
46 * ncalrpc: epmapper
47 * ncacn_http: 593
48 *
49 * If the user's machine ran a DCE RPC daemon, it would
50 * probably be possible to connect to it, but there are many
51 * reasons not to, like:
52 * - the user probably does *not* run one, and probably
53 * shouldn't be forced to run one just for local COM
54 * - very few Unix systems use DCE RPC... if they run a RPC
55 * daemon at all, it's usually Sun RPC
56 * - DCE RPC registrations are persistent and saved on disk,
57 * while MS-RPC registrations are documented as non-persistent
58 * and stored only in RAM, and auto-destroyed when the process
59 * dies (something DCE RPC can't do)
60 *
61 * Of course, if the user *did* want to run a DCE RPC daemon anyway,
62 * there would be interoperability advantages, like the possibility
63 * of running a fully functional DCOM server using Wine...
64 */
65
66 static const struct epm_endpoints
67 {
68 const char *protseq;
69 const char *endpoint;
70 } epm_endpoints[] =
71 {
72 { "ncacn_np", "\\pipe\\epmapper" },
73 { "ncacn_ip_tcp", "135" },
74 { "ncacn_ip_udp", "135" },
75 { "ncalrpc", "epmapper" },
76 { "ncacn_http", "593" },
77 };
78
start_rpcss(void)79 static BOOL start_rpcss(void)
80 {
81 static const WCHAR rpcssW[] = {'R','p','c','S','s',0};
82 SC_HANDLE scm, service;
83 SERVICE_STATUS_PROCESS status;
84 BOOL ret = FALSE;
85
86 TRACE("\n");
87
88 if (!(scm = OpenSCManagerW( NULL, NULL, 0 )))
89 {
90 ERR( "failed to open service manager\n" );
91 return FALSE;
92 }
93 if (!(service = OpenServiceW( scm, rpcssW, SERVICE_START | SERVICE_QUERY_STATUS )))
94 {
95 ERR( "failed to open RpcSs service\n" );
96 CloseServiceHandle( scm );
97 return FALSE;
98 }
99 if (StartServiceW( service, 0, NULL ) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
100 {
101 ULONGLONG start_time = GetTickCount64();
102 do
103 {
104 DWORD dummy;
105
106 if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
107 (BYTE *)&status, sizeof(status), &dummy ))
108 break;
109 if (status.dwCurrentState == SERVICE_RUNNING)
110 {
111 ret = TRUE;
112 break;
113 }
114 if (GetTickCount64() - start_time > 30000) break;
115 Sleep( 100 );
116
117 } while (status.dwCurrentState == SERVICE_START_PENDING);
118
119 if (status.dwCurrentState != SERVICE_RUNNING)
120 WARN( "RpcSs failed to start %u\n", status.dwCurrentState );
121 }
122 else ERR( "failed to start RpcSs service\n" );
123
124 CloseServiceHandle( service );
125 CloseServiceHandle( scm );
126 return ret;
127 }
128
is_epm_destination_local(RPC_BINDING_HANDLE handle)129 static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
130 {
131 RpcBinding *bind = handle;
132 const char *protseq = bind->Protseq;
133 const char *network_addr = bind->NetworkAddr;
134
135 return (!strcmp(protseq, "ncalrpc") ||
136 (!strcmp(protseq, "ncacn_np") &&
137 (!network_addr || !strcmp(network_addr, "."))));
138 }
139
get_epm_handle_client(RPC_BINDING_HANDLE handle,RPC_BINDING_HANDLE * epm_handle)140 static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle)
141 {
142 RpcBinding *bind = handle;
143 const char * pszEndpoint = NULL;
144 RPC_STATUS status;
145 RpcBinding* epm_bind;
146 unsigned int i;
147
148 if (bind->server)
149 return RPC_S_INVALID_BINDING;
150
151 for (i = 0; i < ARRAY_SIZE(epm_endpoints); i++)
152 if (!strcmp(bind->Protseq, epm_endpoints[i].protseq))
153 pszEndpoint = epm_endpoints[i].endpoint;
154
155 if (!pszEndpoint)
156 {
157 FIXME("no endpoint for the endpoint-mapper found for protseq %s\n", debugstr_a(bind->Protseq));
158 return RPC_S_PROTSEQ_NOT_SUPPORTED;
159 }
160
161 status = RpcBindingCopy(handle, epm_handle);
162 if (status != RPC_S_OK) return status;
163
164 epm_bind = *epm_handle;
165 if (epm_bind->AuthInfo)
166 {
167 /* don't bother with authenticating against the EPM by default
168 * (see EnableAuthEpResolution registry value) */
169 RpcAuthInfo_Release(epm_bind->AuthInfo);
170 epm_bind->AuthInfo = NULL;
171 }
172 RPCRT4_ResolveBinding(epm_bind, pszEndpoint);
173 TRACE("RPC_S_OK\n");
174 return RPC_S_OK;
175 }
176
get_epm_handle_server(RPC_BINDING_HANDLE * epm_handle)177 static RPC_STATUS get_epm_handle_server(RPC_BINDING_HANDLE *epm_handle)
178 {
179 unsigned char string_binding[] = "ncacn_np:.[\\\\pipe\\\\epmapper]";
180
181 return RpcBindingFromStringBindingA(string_binding, epm_handle);
182 }
183
rpc_filter(EXCEPTION_POINTERS * __eptr)184 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
185 {
186 switch (__eptr->ExceptionRecord->ExceptionCode)
187 {
188 case EXCEPTION_ACCESS_VIOLATION:
189 case EXCEPTION_ILLEGAL_INSTRUCTION:
190 return EXCEPTION_CONTINUE_SEARCH;
191 default:
192 return EXCEPTION_EXECUTE_HANDLER;
193 }
194 }
195
epm_register(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector,RPC_CSTR Annotation,BOOL replace)196 static RPC_STATUS epm_register( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
197 UUID_VECTOR *UuidVector, RPC_CSTR Annotation, BOOL replace )
198 {
199 PRPC_SERVER_INTERFACE If = IfSpec;
200 ULONG i;
201 RPC_STATUS status = RPC_S_OK;
202 error_status_t status2;
203 ept_entry_t *entries;
204 handle_t handle;
205
206 TRACE("(%p,%p,%p,%s) replace=%d\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation), replace);
207 TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
208 for (i=0; i<BindingVector->Count; i++) {
209 RpcBinding* bind = BindingVector->BindingH[i];
210 TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
211 TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
212 }
213 if (UuidVector) {
214 for (i=0; i<UuidVector->Count; i++)
215 TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
216 }
217
218 if (!BindingVector->Count) return RPC_S_OK;
219
220 entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1));
221 if (!entries)
222 return RPC_S_OUT_OF_MEMORY;
223
224 status = get_epm_handle_server(&handle);
225 if (status != RPC_S_OK)
226 {
227 HeapFree(GetProcessHeap(), 0, entries);
228 return status;
229 }
230
231 for (i = 0; i < BindingVector->Count; i++)
232 {
233 unsigned j;
234 RpcBinding* bind = BindingVector->BindingH[i];
235 for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
236 {
237 status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
238 bind->Protseq, bind->Endpoint,
239 bind->NetworkAddr,
240 &entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower);
241 if (status != RPC_S_OK) break;
242
243 if (UuidVector)
244 memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID));
245 else
246 memset(&entries[i].object, 0, sizeof(entries[i].object));
247 if (Annotation)
248 memcpy(entries[i].annotation, Annotation,
249 min(strlen((char *)Annotation) + 1, ept_max_annotation_size));
250 }
251 }
252
253 if (status == RPC_S_OK)
254 {
255 while (TRUE)
256 {
257 __TRY
258 {
259 ept_insert(handle, BindingVector->Count * (UuidVector ? UuidVector->Count : 1),
260 entries, replace, &status2);
261 }
262 __EXCEPT(rpc_filter)
263 {
264 status2 = GetExceptionCode();
265 }
266 __ENDTRY
267 if (status2 == RPC_S_SERVER_UNAVAILABLE &&
268 is_epm_destination_local(handle))
269 {
270 if (start_rpcss())
271 continue;
272 }
273 if (status2 != RPC_S_OK)
274 ERR("ept_insert failed with error %d\n", status2);
275 status = status2; /* FIXME: convert status? */
276 break;
277 }
278 }
279 RpcBindingFree(&handle);
280
281 for (i = 0; i < BindingVector->Count; i++)
282 {
283 unsigned j;
284 for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
285 I_RpcFree(entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower);
286 }
287
288 HeapFree(GetProcessHeap(), 0, entries);
289
290 return status;
291 }
292
293 /***********************************************************************
294 * RpcEpRegisterA (RPCRT4.@)
295 */
RpcEpRegisterA(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector,RPC_CSTR Annotation)296 RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
297 UUID_VECTOR *UuidVector, RPC_CSTR Annotation )
298 {
299 return epm_register(IfSpec, BindingVector, UuidVector, Annotation, TRUE);
300 }
301
302 /***********************************************************************
303 * RpcEpRegisterNoReplaceA (RPCRT4.@)
304 */
RpcEpRegisterNoReplaceA(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector,RPC_CSTR Annotation)305 RPC_STATUS WINAPI RpcEpRegisterNoReplaceA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
306 UUID_VECTOR *UuidVector, RPC_CSTR Annotation )
307 {
308 return epm_register(IfSpec, BindingVector, UuidVector, Annotation, FALSE);
309 }
310
311 /***********************************************************************
312 * RpcEpRegisterW (RPCRT4.@)
313 */
RpcEpRegisterW(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector,RPC_WSTR Annotation)314 RPC_STATUS WINAPI RpcEpRegisterW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
315 UUID_VECTOR *UuidVector, RPC_WSTR Annotation )
316 {
317 LPSTR annA = RPCRT4_strdupWtoA(Annotation);
318 RPC_STATUS status;
319
320 status = epm_register(IfSpec, BindingVector, UuidVector, (RPC_CSTR)annA, TRUE);
321
322 HeapFree(GetProcessHeap(), 0, annA);
323 return status;
324 }
325
326 /***********************************************************************
327 * RpcEpRegisterNoReplaceW (RPCRT4.@)
328 */
RpcEpRegisterNoReplaceW(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector,RPC_WSTR Annotation)329 RPC_STATUS WINAPI RpcEpRegisterNoReplaceW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
330 UUID_VECTOR *UuidVector, RPC_WSTR Annotation )
331 {
332 LPSTR annA = RPCRT4_strdupWtoA(Annotation);
333 RPC_STATUS status;
334
335 status = epm_register(IfSpec, BindingVector, UuidVector, (RPC_CSTR)annA, FALSE);
336
337 HeapFree(GetProcessHeap(), 0, annA);
338 return status;
339 }
340
341 /***********************************************************************
342 * RpcEpUnregister (RPCRT4.@)
343 */
RpcEpUnregister(RPC_IF_HANDLE IfSpec,RPC_BINDING_VECTOR * BindingVector,UUID_VECTOR * UuidVector)344 RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
345 UUID_VECTOR *UuidVector )
346 {
347 PRPC_SERVER_INTERFACE If = IfSpec;
348 ULONG i;
349 RPC_STATUS status = RPC_S_OK;
350 error_status_t status2;
351 ept_entry_t *entries;
352 handle_t handle;
353
354 TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);
355 TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
356 for (i=0; i<BindingVector->Count; i++) {
357 RpcBinding* bind = BindingVector->BindingH[i];
358 TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
359 TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
360 }
361 if (UuidVector) {
362 for (i=0; i<UuidVector->Count; i++)
363 TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
364 }
365
366 entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1));
367 if (!entries)
368 return RPC_S_OUT_OF_MEMORY;
369
370 status = get_epm_handle_server(&handle);
371 if (status != RPC_S_OK)
372 {
373 HeapFree(GetProcessHeap(), 0, entries);
374 return status;
375 }
376
377 for (i = 0; i < BindingVector->Count; i++)
378 {
379 unsigned j;
380 RpcBinding* bind = BindingVector->BindingH[i];
381 for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
382 {
383 status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
384 bind->Protseq, bind->Endpoint,
385 bind->NetworkAddr,
386 &entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower);
387 if (status != RPC_S_OK) break;
388
389 if (UuidVector)
390 memcpy(&entries[i * UuidVector->Count + j].object, &UuidVector->Uuid[j], sizeof(GUID));
391 else
392 memset(&entries[i].object, 0, sizeof(entries[i].object));
393 }
394 }
395
396 if (status == RPC_S_OK)
397 {
398 __TRY
399 {
400 ept_insert(handle, BindingVector->Count * (UuidVector ? UuidVector->Count : 1),
401 entries, TRUE, &status2);
402 }
403 __EXCEPT(rpc_filter)
404 {
405 status2 = GetExceptionCode();
406 }
407 __ENDTRY
408 if (status2 == RPC_S_SERVER_UNAVAILABLE)
409 status2 = EPT_S_NOT_REGISTERED;
410 if (status2 != RPC_S_OK)
411 ERR("ept_insert failed with error %d\n", status2);
412 status = status2; /* FIXME: convert status? */
413 }
414 RpcBindingFree(&handle);
415
416 for (i = 0; i < BindingVector->Count; i++)
417 {
418 unsigned j;
419 for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
420 I_RpcFree(entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower);
421 }
422
423 HeapFree(GetProcessHeap(), 0, entries);
424
425 return status;
426 }
427
428 /***********************************************************************
429 * RpcEpResolveBinding (RPCRT4.@)
430 */
RpcEpResolveBinding(RPC_BINDING_HANDLE Binding,RPC_IF_HANDLE IfSpec)431 RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
432 {
433 PRPC_CLIENT_INTERFACE If = IfSpec;
434 RpcBinding* bind = Binding;
435 RPC_STATUS status;
436 error_status_t status2;
437 handle_t handle;
438 ept_lookup_handle_t entry_handle = NULL;
439 twr_t *tower;
440 twr_t *towers[4] = { NULL };
441 unsigned32 num_towers, i;
442 GUID uuid = GUID_NULL;
443 char *resolved_endpoint = NULL;
444
445 TRACE("(%p,%p)\n", Binding, IfSpec);
446 TRACE(" protseq=%s\n", debugstr_a(bind->Protseq));
447 TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid));
448 TRACE(" networkaddr=%s\n", debugstr_a(bind->NetworkAddr));
449 TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
450
451 /* just return for fully bound handles */
452 if (bind->Endpoint && (bind->Endpoint[0] != '\0'))
453 return RPC_S_OK;
454
455 status = get_epm_handle_client(Binding, &handle);
456 if (status != RPC_S_OK) return status;
457
458 status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, bind->Protseq,
459 ((RpcBinding *)handle)->Endpoint,
460 bind->NetworkAddr, &tower);
461 if (status != RPC_S_OK)
462 {
463 WARN("couldn't get tower\n");
464 RpcBindingFree(&handle);
465 return status;
466 }
467
468 while (TRUE)
469 {
470 __TRY
471 {
472 ept_map(handle, &uuid, tower, &entry_handle, ARRAY_SIZE(towers), &num_towers, towers, &status2);
473 /* FIXME: translate status2? */
474 }
475 __EXCEPT(rpc_filter)
476 {
477 status2 = GetExceptionCode();
478 }
479 __ENDTRY
480 if (status2 == RPC_S_SERVER_UNAVAILABLE &&
481 is_epm_destination_local(handle))
482 {
483 if (start_rpcss())
484 continue;
485 }
486 break;
487 };
488
489 RpcBindingFree(&handle);
490 I_RpcFree(tower);
491
492 if (status2 != RPC_S_OK)
493 {
494 ERR("ept_map failed for ifid %s, protseq %s, networkaddr %s\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID), bind->Protseq, bind->NetworkAddr);
495 return status2;
496 }
497
498 for (i = 0; i < num_towers; i++)
499 {
500 /* only parse the tower if we haven't already found a suitable
501 * endpoint, otherwise just free the tower */
502 if (!resolved_endpoint)
503 {
504 status = TowerExplode(towers[i], NULL, NULL, NULL, &resolved_endpoint, NULL);
505 TRACE("status = %d\n", status);
506 }
507 I_RpcFree(towers[i]);
508 }
509
510 if (resolved_endpoint)
511 {
512 RPCRT4_ResolveBinding(Binding, resolved_endpoint);
513 I_RpcFree(resolved_endpoint);
514 return RPC_S_OK;
515 }
516
517 WARN("couldn't find an endpoint\n");
518 return EPT_S_NOT_REGISTERED;
519 }
520
521 /*****************************************************************************
522 * TowerExplode (RPCRT4.@)
523 */
TowerExplode(const twr_t * tower,PRPC_SYNTAX_IDENTIFIER object,PRPC_SYNTAX_IDENTIFIER syntax,char ** protseq,char ** endpoint,char ** address)524 RPC_STATUS WINAPI TowerExplode(
525 const twr_t *tower, PRPC_SYNTAX_IDENTIFIER object, PRPC_SYNTAX_IDENTIFIER syntax,
526 char **protseq, char **endpoint, char **address)
527 {
528 size_t tower_size;
529 RPC_STATUS status;
530 const unsigned char *p;
531 u_int16 floor_count;
532 const twr_uuid_floor_t *object_floor;
533 const twr_uuid_floor_t *syntax_floor;
534
535 TRACE("(%p, %p, %p, %p, %p, %p)\n", tower, object, syntax, protseq,
536 endpoint, address);
537
538 if (protseq)
539 *protseq = NULL;
540 if (endpoint)
541 *endpoint = NULL;
542 if (address)
543 *address = NULL;
544
545 tower_size = tower->tower_length;
546
547 if (tower_size < sizeof(u_int16))
548 return EPT_S_NOT_REGISTERED;
549
550 p = &tower->tower_octet_string[0];
551
552 floor_count = *(const u_int16 *)p;
553 p += sizeof(u_int16);
554 tower_size -= sizeof(u_int16);
555 TRACE("floor_count: %d\n", floor_count);
556 /* FIXME: should we do something with the floor count? at the moment we don't */
557
558 if (tower_size < sizeof(*object_floor) + sizeof(*syntax_floor))
559 return EPT_S_NOT_REGISTERED;
560
561 object_floor = (const twr_uuid_floor_t *)p;
562 p += sizeof(*object_floor);
563 tower_size -= sizeof(*object_floor);
564 syntax_floor = (const twr_uuid_floor_t *)p;
565 p += sizeof(*syntax_floor);
566 tower_size -= sizeof(*syntax_floor);
567
568 if ((object_floor->count_lhs != sizeof(object_floor->protid) +
569 sizeof(object_floor->uuid) + sizeof(object_floor->major_version)) ||
570 (object_floor->protid != EPM_PROTOCOL_UUID) ||
571 (object_floor->count_rhs != sizeof(object_floor->minor_version)))
572 return EPT_S_NOT_REGISTERED;
573
574 if ((syntax_floor->count_lhs != sizeof(syntax_floor->protid) +
575 sizeof(syntax_floor->uuid) + sizeof(syntax_floor->major_version)) ||
576 (syntax_floor->protid != EPM_PROTOCOL_UUID) ||
577 (syntax_floor->count_rhs != sizeof(syntax_floor->minor_version)))
578 return EPT_S_NOT_REGISTERED;
579
580 status = RpcTransport_ParseTopOfTower(p, tower_size, protseq, address, endpoint);
581 if ((status == RPC_S_OK) && syntax && object)
582 {
583 syntax->SyntaxGUID = syntax_floor->uuid;
584 syntax->SyntaxVersion.MajorVersion = syntax_floor->major_version;
585 syntax->SyntaxVersion.MinorVersion = syntax_floor->minor_version;
586 object->SyntaxGUID = object_floor->uuid;
587 object->SyntaxVersion.MajorVersion = object_floor->major_version;
588 object->SyntaxVersion.MinorVersion = object_floor->minor_version;
589 }
590 return status;
591 }
592
593 /***********************************************************************
594 * TowerConstruct (RPCRT4.@)
595 */
TowerConstruct(const RPC_SYNTAX_IDENTIFIER * object,const RPC_SYNTAX_IDENTIFIER * syntax,const char * protseq,const char * endpoint,const char * address,twr_t ** tower)596 RPC_STATUS WINAPI TowerConstruct(
597 const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax,
598 const char *protseq, const char *endpoint, const char *address,
599 twr_t **tower)
600 {
601 size_t tower_size;
602 RPC_STATUS status;
603 unsigned char *p;
604 twr_uuid_floor_t *object_floor;
605 twr_uuid_floor_t *syntax_floor;
606
607 TRACE("(%p, %p, %s, %s, %s, %p)\n", object, syntax, debugstr_a(protseq),
608 debugstr_a(endpoint), debugstr_a(address), tower);
609
610 *tower = NULL;
611
612 status = RpcTransport_GetTopOfTower(NULL, &tower_size, protseq, address, endpoint);
613
614 if (status != RPC_S_OK)
615 return status;
616
617 tower_size += sizeof(u_int16) + sizeof(*object_floor) + sizeof(*syntax_floor);
618 *tower = I_RpcAllocate(FIELD_OFFSET(twr_t, tower_octet_string[tower_size]));
619 if (!*tower)
620 return RPC_S_OUT_OF_RESOURCES;
621
622 (*tower)->tower_length = tower_size;
623 p = &(*tower)->tower_octet_string[0];
624 *(u_int16 *)p = 5; /* number of floors */
625 p += sizeof(u_int16);
626 object_floor = (twr_uuid_floor_t *)p;
627 p += sizeof(*object_floor);
628 syntax_floor = (twr_uuid_floor_t *)p;
629 p += sizeof(*syntax_floor);
630
631 object_floor->count_lhs = sizeof(object_floor->protid) + sizeof(object_floor->uuid) +
632 sizeof(object_floor->major_version);
633 object_floor->protid = EPM_PROTOCOL_UUID;
634 object_floor->count_rhs = sizeof(object_floor->minor_version);
635 object_floor->uuid = object->SyntaxGUID;
636 object_floor->major_version = object->SyntaxVersion.MajorVersion;
637 object_floor->minor_version = object->SyntaxVersion.MinorVersion;
638
639 syntax_floor->count_lhs = sizeof(syntax_floor->protid) + sizeof(syntax_floor->uuid) +
640 sizeof(syntax_floor->major_version);
641 syntax_floor->protid = EPM_PROTOCOL_UUID;
642 syntax_floor->count_rhs = sizeof(syntax_floor->minor_version);
643 syntax_floor->uuid = syntax->SyntaxGUID;
644 syntax_floor->major_version = syntax->SyntaxVersion.MajorVersion;
645 syntax_floor->minor_version = syntax->SyntaxVersion.MinorVersion;
646
647 status = RpcTransport_GetTopOfTower(p, &tower_size, protseq, address, endpoint);
648 if (status != RPC_S_OK)
649 {
650 I_RpcFree(*tower);
651 *tower = NULL;
652 return status;
653 }
654 return RPC_S_OK;
655 }
656
MIDL_user_allocate(SIZE_T len)657 void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
658 {
659 return HeapAlloc(GetProcessHeap(), 0, len);
660 }
661
MIDL_user_free(void __RPC_FAR * ptr)662 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
663 {
664 HeapFree(GetProcessHeap(), 0, ptr);
665 }
666