4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 #include "rpc_binding.h"
45 #include "rpc_message.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(rpc
);
49 LPSTR
RPCRT4_strndupA(LPCSTR src
, INT slen
)
53 if (!src
) return NULL
;
54 if (slen
== -1) slen
= strlen(src
);
56 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
62 LPSTR
RPCRT4_strdupWtoA(LPWSTR src
)
66 if (!src
) return NULL
;
67 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
68 s
= HeapAlloc(GetProcessHeap(), 0, len
);
69 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
73 LPWSTR
RPCRT4_strdupAtoW(LPSTR src
)
77 if (!src
) return NULL
;
78 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
79 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
80 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
84 LPWSTR
RPCRT4_strndupW(LPWSTR src
, INT slen
)
88 if (!src
) return NULL
;
89 if (slen
== -1) slen
= strlenW(src
);
91 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
92 memcpy(s
, src
, len
*sizeof(WCHAR
));
97 void RPCRT4_strfree(LPSTR src
)
99 HeapFree(GetProcessHeap(), 0, src
);
102 static RPC_STATUS
RPCRT4_AllocBinding(RpcBinding
** Binding
, BOOL server
)
104 RpcBinding
* NewBinding
;
106 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
107 NewBinding
->refs
= 1;
108 NewBinding
->server
= server
;
110 *Binding
= NewBinding
;
115 RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPSTR Protseq
)
117 RpcBinding
* NewBinding
;
119 RPCRT4_AllocBinding(&NewBinding
, server
);
120 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
122 TRACE("binding: %p\n", NewBinding
);
123 *Binding
= NewBinding
;
128 RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPWSTR Protseq
)
130 RpcBinding
* NewBinding
;
132 RPCRT4_AllocBinding(&NewBinding
, server
);
133 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
135 TRACE("binding: %p\n", NewBinding
);
136 *Binding
= NewBinding
;
141 RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
143 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
144 debugstr_a(NetworkAddr
), debugstr_a(Endpoint
), debugstr_a(NetworkOptions
));
146 RPCRT4_strfree(Binding
->NetworkAddr
);
147 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
148 RPCRT4_strfree(Binding
->Endpoint
);
150 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
152 Binding
->Endpoint
= RPCRT4_strdupA("");
154 if (!Binding
->Endpoint
) ERR("out of memory?\n");
159 RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPWSTR NetworkAddr
, LPWSTR Endpoint
, LPWSTR NetworkOptions
)
161 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
162 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
164 RPCRT4_strfree(Binding
->NetworkAddr
);
165 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
166 RPCRT4_strfree(Binding
->Endpoint
);
168 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
170 Binding
->Endpoint
= RPCRT4_strdupA("");
172 if (!Binding
->Endpoint
) ERR("out of memory?\n");
177 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPSTR Endpoint
)
179 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
181 RPCRT4_strfree(Binding
->Endpoint
);
182 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
187 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, UUID
* ObjectUuid
)
189 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
190 if (ObjectUuid
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
191 else UuidCreateNil(&Binding
->ObjectUuid
);
195 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
197 RpcBinding
* NewBinding
;
198 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding
, Connection
);
200 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
201 NewBinding
->Protseq
= RPCRT4_strdupA(rpcrt4_conn_get_name(Connection
));
202 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
203 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
204 NewBinding
->FromConn
= Connection
;
206 TRACE("binding: %p\n", NewBinding
);
207 *Binding
= NewBinding
;
212 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
214 InterlockedIncrement(&OldBinding
->refs
);
215 *Binding
= OldBinding
;
219 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
221 if (InterlockedDecrement(&Binding
->refs
))
224 TRACE("binding: %p\n", Binding
);
225 /* FIXME: release connections */
226 RPCRT4_strfree(Binding
->Endpoint
);
227 RPCRT4_strfree(Binding
->NetworkAddr
);
228 RPCRT4_strfree(Binding
->Protseq
);
229 HeapFree(GetProcessHeap(), 0, Binding
);
233 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
,
234 PRPC_SYNTAX_IDENTIFIER TransferSyntax
,
235 PRPC_SYNTAX_IDENTIFIER InterfaceId
)
237 RpcConnection
* NewConnection
;
240 TRACE("(Binding == ^%p)\n", Binding
);
242 /* if we try to bind a new interface and the connection is already opened,
243 * close the current connection and create a new with the new binding. */
244 if (!Binding
->server
&& Binding
->FromConn
&&
245 (Binding
->AuthInfo
== Binding
->FromConn
->AuthInfo
) &&
246 memcmp(&Binding
->FromConn
->ActiveInterface
, InterfaceId
,
247 sizeof(RPC_SYNTAX_IDENTIFIER
))) {
249 TRACE("releasing pre-existing connection\n");
250 RPCRT4_DestroyConnection(Binding
->FromConn
);
251 Binding
->FromConn
= NULL
;
253 /* we already have a connection with acceptable binding, so use it */
254 if (Binding
->FromConn
) {
255 *Connection
= Binding
->FromConn
;
260 /* create a new connection */
261 RPCRT4_CreateConnection(&NewConnection
, Binding
->server
, Binding
->Protseq
,
262 Binding
->NetworkAddr
, Binding
->Endpoint
, NULL
,
263 Binding
->AuthInfo
, Binding
);
264 *Connection
= NewConnection
;
265 status
= RPCRT4_OpenConnection(NewConnection
);
266 if (status
!= RPC_S_OK
) {
270 /* we need to send a binding packet if we are client. */
271 if (!(*Connection
)->server
) {
273 RpcPktHdr
*response_hdr
;
276 TRACE("sending bind request to server\n");
278 hdr
= RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION
,
279 RPC_MAX_PACKET_SIZE
, RPC_MAX_PACKET_SIZE
,
280 InterfaceId
, TransferSyntax
);
282 status
= RPCRT4_Send(*Connection
, hdr
, NULL
, 0);
283 RPCRT4_FreeHeader(hdr
);
284 if (status
!= RPC_S_OK
) {
285 RPCRT4_DestroyConnection(*Connection
);
289 status
= RPCRT4_Receive(NewConnection
, &response_hdr
, &msg
);
290 if (status
!= RPC_S_OK
) {
291 ERR("receive failed\n");
292 RPCRT4_DestroyConnection(*Connection
);
296 if (response_hdr
->common
.ptype
!= PKT_BIND_ACK
||
297 response_hdr
->bind_ack
.max_tsize
< RPC_MIN_PACKET_SIZE
) {
298 ERR("failed to bind\n");
299 RPCRT4_FreeHeader(response_hdr
);
300 RPCRT4_DestroyConnection(*Connection
);
301 return RPC_S_PROTOCOL_ERROR
;
304 /* FIXME: do more checks? */
306 (*Connection
)->MaxTransmissionSize
= response_hdr
->bind_ack
.max_tsize
;
307 (*Connection
)->ActiveInterface
= *InterfaceId
;
308 RPCRT4_FreeHeader(response_hdr
);
310 Binding
->FromConn
= *Connection
;
315 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
317 TRACE("(Binding == ^%p)\n", Binding
);
318 if (!Connection
) return RPC_S_OK
;
319 if (Binding
->FromConn
== Connection
) return RPC_S_OK
;
320 return RPCRT4_DestroyConnection(Connection
);
323 /* utility functions for string composing and parsing */
324 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
326 unsigned len
= strlen(src
);
327 memcpy(data
, src
, len
*sizeof(CHAR
));
331 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
333 unsigned len
= strlenW(src
);
334 memcpy(data
, src
, len
*sizeof(WCHAR
));
338 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
340 DWORD len
= strlen(dst
), slen
= strlen(src
);
341 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
344 HeapFree(GetProcessHeap(), 0, dst
);
348 memcpy(ndst
+len
+1, src
, slen
+1);
352 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
354 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
355 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
358 HeapFree(GetProcessHeap(), 0, dst
);
362 memcpy(ndst
+len
+1, src
, (slen
+1)*sizeof(WCHAR
));
367 /***********************************************************************
368 * RpcStringBindingComposeA (RPCRT4.@)
370 RPC_STATUS WINAPI
RpcStringBindingComposeA(unsigned char *ObjUuid
, unsigned char *Protseq
,
371 unsigned char *NetworkAddr
, unsigned char *Endpoint
,
372 unsigned char *Options
, unsigned char** StringBinding
)
377 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
378 debugstr_a( (char*)ObjUuid
), debugstr_a( (char*)Protseq
),
379 debugstr_a( (char*)NetworkAddr
), debugstr_a( (char*)Endpoint
),
380 debugstr_a( (char*)Options
), StringBinding
);
382 if (ObjUuid
&& *ObjUuid
) len
+= strlen((char*)ObjUuid
) + 1;
383 if (Protseq
&& *Protseq
) len
+= strlen((char*)Protseq
) + 1;
384 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen((char*)NetworkAddr
);
385 if (Endpoint
&& *Endpoint
) len
+= strlen((char*)Endpoint
) + 2;
386 if (Options
&& *Options
) len
+= strlen((char*)Options
) + 2;
388 data
= HeapAlloc(GetProcessHeap(), 0, len
);
389 *StringBinding
= (unsigned char*)data
;
391 if (ObjUuid
&& *ObjUuid
) {
392 data
+= RPCRT4_strcopyA(data
, (char*)ObjUuid
);
395 if (Protseq
&& *Protseq
) {
396 data
+= RPCRT4_strcopyA(data
, (char*)Protseq
);
399 if (NetworkAddr
&& *NetworkAddr
)
400 data
+= RPCRT4_strcopyA(data
, (char*)NetworkAddr
);
402 if ((Endpoint
&& *Endpoint
) ||
403 (Options
&& *Options
)) {
405 if (Endpoint
&& *Endpoint
) {
406 data
+= RPCRT4_strcopyA(data
, (char*)Endpoint
);
407 if (Options
&& *Options
) *data
++ = ',';
409 if (Options
&& *Options
) {
410 data
+= RPCRT4_strcopyA(data
, (char*)Options
);
419 /***********************************************************************
420 * RpcStringBindingComposeW (RPCRT4.@)
422 RPC_STATUS WINAPI
RpcStringBindingComposeW( LPWSTR ObjUuid
, LPWSTR Protseq
,
423 LPWSTR NetworkAddr
, LPWSTR Endpoint
,
424 LPWSTR Options
, LPWSTR
* StringBinding
)
429 TRACE("(%s,%s,%s,%s,%s,%p)\n",
430 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
431 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
432 debugstr_w( Options
), StringBinding
);
434 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
435 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
436 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
437 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
438 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
440 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
441 *StringBinding
= data
;
443 if (ObjUuid
&& *ObjUuid
) {
444 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
447 if (Protseq
&& *Protseq
) {
448 data
+= RPCRT4_strcopyW(data
, Protseq
);
451 if (NetworkAddr
&& *NetworkAddr
) {
452 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
454 if ((Endpoint
&& *Endpoint
) ||
455 (Options
&& *Options
)) {
457 if (Endpoint
&& *Endpoint
) {
458 data
+= RPCRT4_strcopyW(data
, Endpoint
);
459 if (Options
&& *Options
) *data
++ = ',';
461 if (Options
&& *Options
) {
462 data
+= RPCRT4_strcopyW(data
, Options
);
472 /***********************************************************************
473 * RpcStringBindingParseA (RPCRT4.@)
475 RPC_STATUS WINAPI
RpcStringBindingParseA( unsigned char *StringBinding
, unsigned char **ObjUuid
,
476 unsigned char **Protseq
, unsigned char **NetworkAddr
,
477 unsigned char **Endpoint
, unsigned char **Options
)
480 static const char ep_opt
[] = "endpoint=";
482 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding
),
483 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
485 if (ObjUuid
) *ObjUuid
= NULL
;
486 if (Protseq
) *Protseq
= NULL
;
487 if (NetworkAddr
) *NetworkAddr
= NULL
;
488 if (Endpoint
) *Endpoint
= NULL
;
489 if (Options
) *Options
= NULL
;
491 data
= (char*) StringBinding
;
493 next
= strchr(data
, '@');
495 if (ObjUuid
) *ObjUuid
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
499 next
= strchr(data
, ':');
501 if (Protseq
) *Protseq
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
505 next
= strchr(data
, '[');
509 if (NetworkAddr
) *NetworkAddr
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
511 close
= strchr(data
, ']');
512 if (!close
) goto fail
;
514 /* tokenize options */
515 while (data
< close
) {
516 next
= strchr(data
, ',');
517 if (!next
|| next
> close
) next
= close
;
518 /* FIXME: this is kind of inefficient */
519 opt
= RPCRT4_strndupA(data
, next
- data
);
523 next
= strchr(opt
, '=');
525 /* not an option, must be an endpoint */
526 if (*Endpoint
) goto fail
;
527 *Endpoint
= (unsigned char*) opt
;
529 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
530 /* endpoint option */
531 if (*Endpoint
) goto fail
;
532 *Endpoint
= (unsigned char*) RPCRT4_strdupA(next
+1);
533 HeapFree(GetProcessHeap(), 0, opt
);
537 /* FIXME: this is kind of inefficient */
538 *Options
= (unsigned char*) RPCRT4_strconcatA( (char*)*Options
, opt
);
539 HeapFree(GetProcessHeap(), 0, opt
);
541 *Options
= (unsigned char*) opt
;
547 if (*data
) goto fail
;
549 else if (NetworkAddr
)
550 *NetworkAddr
= (unsigned char*)RPCRT4_strdupA(data
);
555 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
556 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
557 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
558 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
559 if (Options
) RpcStringFreeA((unsigned char**)Options
);
560 return RPC_S_INVALID_STRING_BINDING
;
563 /***********************************************************************
564 * RpcStringBindingParseW (RPCRT4.@)
566 RPC_STATUS WINAPI
RpcStringBindingParseW( LPWSTR StringBinding
, LPWSTR
*ObjUuid
,
567 LPWSTR
*Protseq
, LPWSTR
*NetworkAddr
,
568 LPWSTR
*Endpoint
, LPWSTR
*Options
)
571 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
573 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
574 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
576 if (ObjUuid
) *ObjUuid
= NULL
;
577 if (Protseq
) *Protseq
= NULL
;
578 if (NetworkAddr
) *NetworkAddr
= NULL
;
579 if (Endpoint
) *Endpoint
= NULL
;
580 if (Options
) *Options
= NULL
;
582 data
= StringBinding
;
584 next
= strchrW(data
, '@');
586 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
590 next
= strchrW(data
, ':');
592 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
596 next
= strchrW(data
, '[');
600 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
602 close
= strchrW(data
, ']');
603 if (!close
) goto fail
;
605 /* tokenize options */
606 while (data
< close
) {
607 next
= strchrW(data
, ',');
608 if (!next
|| next
> close
) next
= close
;
609 /* FIXME: this is kind of inefficient */
610 opt
= RPCRT4_strndupW(data
, next
- data
);
614 next
= strchrW(opt
, '=');
616 /* not an option, must be an endpoint */
617 if (*Endpoint
) goto fail
;
620 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
621 /* endpoint option */
622 if (*Endpoint
) goto fail
;
623 *Endpoint
= RPCRT4_strdupW(next
+1);
624 HeapFree(GetProcessHeap(), 0, opt
);
628 /* FIXME: this is kind of inefficient */
629 *Options
= RPCRT4_strconcatW(*Options
, opt
);
630 HeapFree(GetProcessHeap(), 0, opt
);
638 if (*data
) goto fail
;
639 } else if (NetworkAddr
)
640 *NetworkAddr
= RPCRT4_strdupW(data
);
645 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
646 if (Protseq
) RpcStringFreeW(Protseq
);
647 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
648 if (Endpoint
) RpcStringFreeW(Endpoint
);
649 if (Options
) RpcStringFreeW(Options
);
650 return RPC_S_INVALID_STRING_BINDING
;
653 /***********************************************************************
654 * RpcBindingFree (RPCRT4.@)
656 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
659 TRACE("(%p) = %p\n", Binding
, *Binding
);
660 status
= RPCRT4_DestroyBinding(*Binding
);
661 if (status
== RPC_S_OK
) *Binding
= 0;
665 /***********************************************************************
666 * RpcBindingVectorFree (RPCRT4.@)
668 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
673 TRACE("(%p)\n", BindingVector
);
674 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
675 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
677 HeapFree(GetProcessHeap(), 0, *BindingVector
);
678 *BindingVector
= NULL
;
682 /***********************************************************************
683 * RpcBindingInqObject (RPCRT4.@)
685 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
687 RpcBinding
* bind
= (RpcBinding
*)Binding
;
689 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
690 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
694 /***********************************************************************
695 * RpcBindingSetObject (RPCRT4.@)
697 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
699 RpcBinding
* bind
= (RpcBinding
*)Binding
;
701 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
702 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
703 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
706 /***********************************************************************
707 * RpcBindingFromStringBindingA (RPCRT4.@)
709 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( unsigned char *StringBinding
, RPC_BINDING_HANDLE
* Binding
)
712 RpcBinding
* bind
= NULL
;
713 unsigned char *ObjectUuid
, *Protseq
, *NetworkAddr
, *Endpoint
, *Options
;
716 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
718 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
719 &NetworkAddr
, &Endpoint
, &Options
);
720 if (ret
!= RPC_S_OK
) return ret
;
722 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
725 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
727 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
729 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
731 RpcStringFreeA((unsigned char**)&Options
);
732 RpcStringFreeA((unsigned char**)&Endpoint
);
733 RpcStringFreeA((unsigned char**)&NetworkAddr
);
734 RpcStringFreeA((unsigned char**)&Protseq
);
735 RpcStringFreeA((unsigned char**)&ObjectUuid
);
738 *Binding
= (RPC_BINDING_HANDLE
)bind
;
740 RPCRT4_DestroyBinding(bind
);
745 /***********************************************************************
746 * RpcBindingFromStringBindingW (RPCRT4.@)
748 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( LPWSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
751 RpcBinding
* bind
= NULL
;
752 LPWSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
755 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
757 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
758 &NetworkAddr
, &Endpoint
, &Options
);
759 if (ret
!= RPC_S_OK
) return ret
;
761 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
764 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
766 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
768 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
770 RpcStringFreeW(&Options
);
771 RpcStringFreeW(&Endpoint
);
772 RpcStringFreeW(&NetworkAddr
);
773 RpcStringFreeW(&Protseq
);
774 RpcStringFreeW(&ObjectUuid
);
777 *Binding
= (RPC_BINDING_HANDLE
)bind
;
779 RPCRT4_DestroyBinding(bind
);
784 /***********************************************************************
785 * RpcBindingToStringBindingA (RPCRT4.@)
787 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, unsigned char** StringBinding
)
790 RpcBinding
* bind
= (RpcBinding
*)Binding
;
793 TRACE("(%p,%p)\n", Binding
, StringBinding
);
795 ret
= UuidToStringA(&bind
->ObjectUuid
, (unsigned char**)&ObjectUuid
);
796 if (ret
!= RPC_S_OK
) return ret
;
798 ret
= RpcStringBindingComposeA((unsigned char*) ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
799 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
801 RpcStringFreeA((unsigned char**)&ObjectUuid
);
806 /***********************************************************************
807 * RpcBindingToStringBindingW (RPCRT4.@)
809 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, unsigned short** StringBinding
)
812 unsigned char *str
= NULL
;
813 TRACE("(%p,%p)\n", Binding
, StringBinding
);
814 ret
= RpcBindingToStringBindingA(Binding
, &str
);
815 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
816 RpcStringFreeA((unsigned char**)&str
);
820 /***********************************************************************
821 * I_RpcBindingSetAsync (RPCRT4.@)
823 * Exists in win9x and winNT, but with different number of arguments
824 * (9x version has 3 arguments, NT has 2).
826 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
828 RpcBinding
* bind
= (RpcBinding
*)Binding
;
830 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
832 bind
->BlockingFn
= BlockingFn
;
837 /***********************************************************************
838 * RpcNetworkIsProtseqValidA (RPCRT4.@)
840 RPC_STATUS WINAPI
RpcNetworkIsProtseqValidA(unsigned char *protseq
) {
841 UNICODE_STRING protseqW
;
843 if (!protseq
) return RPC_S_INVALID_RPC_PROTSEQ
; /* ? */
845 if (RtlCreateUnicodeStringFromAsciiz(&protseqW
, (char*)protseq
)) {
846 RPC_STATUS ret
= RpcNetworkIsProtseqValidW(protseqW
.Buffer
);
847 RtlFreeUnicodeString(&protseqW
);
849 } else return RPC_S_OUT_OF_MEMORY
;
852 /***********************************************************************
853 * RpcNetworkIsProtseqValidW (RPCRT4.@)
855 * Checks if the given protocol sequence is known by the RPC system.
856 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
858 * We currently support:
859 * ncalrpc local-only rpc over LPC (LPC is not really used)
860 * ncacn_np rpc over named pipes
862 RPC_STATUS WINAPI
RpcNetworkIsProtseqValidW(LPWSTR protseq
) {
863 static const WCHAR protseqsW
[][15] = {
864 {'n','c','a','l','r','p','c',0},
865 {'n','c','a','c','n','_','n','p',0}
867 static const int count
= sizeof(protseqsW
) / sizeof(protseqsW
[0]);
870 if (!protseq
) return RPC_S_INVALID_RPC_PROTSEQ
; /* ? */
872 for (i
= 0; i
< count
; i
++) {
873 if (!strcmpW(protseq
, protseqsW
[i
])) return RPC_S_OK
;
876 FIXME("Unknown protseq %s - we probably need to implement it one day\n", debugstr_w(protseq
));
877 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
880 /***********************************************************************
881 * RpcImpersonateClient (RPCRT4.@)
883 * Impersonates the client connected via a binding handle so that security
884 * checks are done in the context of the client.
887 * BindingHandle [I] Handle to the binding to the client.
891 * Failure: RPC_STATUS value.
895 * If BindingHandle is NULL then the function impersonates the client
896 * connected to the binding handle of the current thread.
898 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
900 FIXME("(%p): stub\n", BindingHandle
);
904 /***********************************************************************
905 * RpcRevertToSelfEx (RPCRT4.@)
907 * Stops impersonating the client connected to the binding handle so that security
908 * checks are no longer done in the context of the client.
911 * BindingHandle [I] Handle to the binding to the client.
915 * Failure: RPC_STATUS value.
919 * If BindingHandle is NULL then the function stops impersonating the client
920 * connected to the binding handle of the current thread.
922 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
924 FIXME("(%p): stub\n", BindingHandle
);
928 static RPC_STATUS
RpcAuthInfo_Create(unsigned long AuthnLevel
, unsigned long AuthnSvc
, CredHandle cred
, TimeStamp exp
, RpcAuthInfo
**ret
)
930 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
932 return ERROR_OUTOFMEMORY
;
934 AuthInfo
->AuthnLevel
= AuthnLevel
;
935 AuthInfo
->AuthnSvc
= AuthnSvc
;
936 AuthInfo
->cred
= cred
;
942 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
944 return InterlockedIncrement(&AuthInfo
->refs
);
947 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
949 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
953 FreeCredentialsHandle(&AuthInfo
->cred
);
954 HeapFree(GetProcessHeap(), 0, AuthInfo
);
960 /***********************************************************************
961 * RpcBindingInqAuthInfoExA (RPCRT4.@)
963 RPCRTAPI RPC_STATUS RPC_ENTRY
964 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, unsigned char ** ServerPrincName
, unsigned long *AuthnLevel
,
965 unsigned long *AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, unsigned long *AuthzSvc
,
966 unsigned long RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
968 FIXME("%p %p %p %p %p %p %lu %p\n", Binding
, ServerPrincName
, AuthnLevel
,
969 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
970 return RPC_S_INVALID_BINDING
;
973 /***********************************************************************
974 * RpcBindingInqAuthInfoExW (RPCRT4.@)
976 RPCRTAPI RPC_STATUS RPC_ENTRY
977 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, unsigned short ** ServerPrincName
, unsigned long *AuthnLevel
,
978 unsigned long *AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, unsigned long *AuthzSvc
,
979 unsigned long RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
981 FIXME("%p %p %p %p %p %p %lu %p\n", Binding
, ServerPrincName
, AuthnLevel
,
982 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
983 return RPC_S_INVALID_BINDING
;
986 /***********************************************************************
987 * RpcBindingInqAuthInfoA (RPCRT4.@)
989 RPCRTAPI RPC_STATUS RPC_ENTRY
990 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, unsigned char ** ServerPrincName
, unsigned long *AuthnLevel
,
991 unsigned long *AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, unsigned long *AuthzSvc
)
993 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
994 AuthnSvc
, AuthIdentity
, AuthzSvc
);
995 return RPC_S_INVALID_BINDING
;
998 /***********************************************************************
999 * RpcBindingInqAuthInfoW (RPCRT4.@)
1001 RPCRTAPI RPC_STATUS RPC_ENTRY
1002 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, unsigned short ** ServerPrincName
, unsigned long *AuthnLevel
,
1003 unsigned long *AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, unsigned long *AuthzSvc
)
1005 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1006 AuthnSvc
, AuthIdentity
, AuthzSvc
);
1007 return RPC_S_INVALID_BINDING
;
1010 /***********************************************************************
1011 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1013 RPCRTAPI RPC_STATUS RPC_ENTRY
1014 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, unsigned char *ServerPrincName
,
1015 unsigned long AuthnLevel
, unsigned long AuthnSvc
,
1016 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, unsigned long AuthzSvr
,
1017 RPC_SECURITY_QOS
*SecurityQos
)
1019 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1023 ULONG package_count
;
1025 PSecPkgInfoA packages
;
1027 TRACE("%p %s %lu %lu %p %lu %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1028 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1031 return RPC_S_INVALID_AUTH_IDENTITY
;
1033 if (AuthnLevel
!= RPC_C_AUTHN_LEVEL_CONNECT
)
1035 FIXME("unsupported AuthnLevel %lu\n", AuthnLevel
);
1036 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1041 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr
);
1042 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1046 FIXME("SecurityQos ignored\n");
1048 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1051 ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r
);
1052 return RPC_S_SEC_PKG_ERROR
;
1055 for (i
= 0; i
< package_count
; i
++)
1056 if (packages
[i
].wRPCID
== AuthnSvc
)
1059 if (i
== package_count
)
1061 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc
);
1062 FreeContextBuffer(packages
);
1063 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1066 TRACE("found package %s for service %ld\n", packages
[i
].Name
, AuthnSvc
);
1067 r
= AcquireCredentialsHandleA(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1068 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1069 FreeContextBuffer(packages
);
1070 if (r
== ERROR_SUCCESS
)
1072 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1073 bind
->AuthInfo
= NULL
;
1074 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, &bind
->AuthInfo
);
1076 FreeCredentialsHandle(&cred
);
1081 ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r
);
1082 return RPC_S_SEC_PKG_ERROR
;
1086 /***********************************************************************
1087 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1089 RPCRTAPI RPC_STATUS RPC_ENTRY
1090 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, unsigned short *ServerPrincName
, unsigned long AuthnLevel
,
1091 unsigned long AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, unsigned long AuthzSvr
,
1092 RPC_SECURITY_QOS
*SecurityQos
)
1094 FIXME("%p %s %lu %lu %p %lu %p\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1095 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1099 /***********************************************************************
1100 * RpcBindingSetAuthInfoA (RPCRT4.@)
1102 RPCRTAPI RPC_STATUS RPC_ENTRY
1103 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, unsigned char *ServerPrincName
, unsigned long AuthnLevel
,
1104 unsigned long AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, unsigned long AuthzSvr
)
1106 TRACE("%p %s %lu %lu %p %lu\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1107 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1108 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1111 /***********************************************************************
1112 * RpcBindingSetAuthInfoW (RPCRT4.@)
1114 RPCRTAPI RPC_STATUS RPC_ENTRY
1115 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, unsigned short *ServerPrincName
, unsigned long AuthnLevel
,
1116 unsigned long AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, unsigned long AuthzSvr
)
1118 TRACE("%p %s %lu %lu %p %lu\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1119 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1120 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1123 /***********************************************************************
1124 * RpcBindingSetOption (RPCRT4.@)
1126 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG OptionValue
)
1128 FIXME("(%p, %ld, %ld): stub\n", BindingHandle
, Option
, OptionValue
);