4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 #include "rpc_binding.h"
42 #include "rpc_assoc.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(rpc
);
46 LPSTR
RPCRT4_strndupA(LPCSTR src
, INT slen
)
50 if (!src
) return NULL
;
51 if (slen
== -1) slen
= strlen(src
);
53 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
59 LPSTR
RPCRT4_strdupWtoA(LPCWSTR src
)
63 if (!src
) return NULL
;
64 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
65 s
= HeapAlloc(GetProcessHeap(), 0, len
);
66 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
70 LPWSTR
RPCRT4_strdupAtoW(LPCSTR src
)
74 if (!src
) return NULL
;
75 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
76 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
77 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
81 static LPWSTR
RPCRT4_strndupAtoW(LPCSTR src
, INT slen
)
85 if (!src
) return NULL
;
86 len
= MultiByteToWideChar(CP_ACP
, 0, src
, slen
, NULL
, 0);
87 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
88 MultiByteToWideChar(CP_ACP
, 0, src
, slen
, s
, len
);
92 LPWSTR
RPCRT4_strndupW(LPCWSTR src
, INT slen
)
96 if (!src
) return NULL
;
97 if (slen
== -1) slen
= strlenW(src
);
99 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
100 memcpy(s
, src
, len
*sizeof(WCHAR
));
105 void RPCRT4_strfree(LPSTR src
)
107 HeapFree(GetProcessHeap(), 0, src
);
110 static RPC_STATUS
RPCRT4_AllocBinding(RpcBinding
** Binding
, BOOL server
)
112 RpcBinding
* NewBinding
;
114 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
115 NewBinding
->refs
= 1;
116 NewBinding
->server
= server
;
118 *Binding
= NewBinding
;
123 static RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPCSTR Protseq
)
125 RpcBinding
* NewBinding
;
127 RPCRT4_AllocBinding(&NewBinding
, server
);
128 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
130 TRACE("binding: %p\n", NewBinding
);
131 *Binding
= NewBinding
;
136 static RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPCWSTR Protseq
)
138 RpcBinding
* NewBinding
;
140 RPCRT4_AllocBinding(&NewBinding
, server
);
141 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
143 TRACE("binding: %p\n", NewBinding
);
144 *Binding
= NewBinding
;
149 static RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPCSTR NetworkAddr
,
150 LPCSTR Endpoint
, LPCSTR NetworkOptions
)
154 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding
,
155 debugstr_a(NetworkAddr
), debugstr_a(Endpoint
), debugstr_a(NetworkOptions
));
157 RPCRT4_strfree(Binding
->NetworkAddr
);
158 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
159 RPCRT4_strfree(Binding
->Endpoint
);
161 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
163 Binding
->Endpoint
= RPCRT4_strdupA("");
165 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
166 Binding
->NetworkOptions
= RPCRT4_strdupAtoW(NetworkOptions
);
167 if (!Binding
->Endpoint
) ERR("out of memory?\n");
169 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
170 Binding
->Endpoint
, Binding
->NetworkOptions
,
172 if (status
!= RPC_S_OK
)
178 static RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPCWSTR NetworkAddr
,
179 LPCWSTR Endpoint
, LPCWSTR NetworkOptions
)
183 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding
,
184 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
186 RPCRT4_strfree(Binding
->NetworkAddr
);
187 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
188 RPCRT4_strfree(Binding
->Endpoint
);
190 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
192 Binding
->Endpoint
= RPCRT4_strdupA("");
194 if (!Binding
->Endpoint
) ERR("out of memory?\n");
195 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
196 Binding
->NetworkOptions
= RPCRT4_strdupW(NetworkOptions
);
198 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
199 Binding
->Endpoint
, Binding
->NetworkOptions
,
201 if (status
!= RPC_S_OK
)
207 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPCSTR Endpoint
)
211 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
213 RPCRT4_strfree(Binding
->Endpoint
);
214 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
216 RpcAssoc_Release(Binding
->Assoc
);
217 Binding
->Assoc
= NULL
;
218 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
219 Binding
->Endpoint
, Binding
->NetworkOptions
,
221 if (status
!= RPC_S_OK
)
227 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, const UUID
* ObjectUuid
)
229 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
230 if (ObjectUuid
) Binding
->ObjectUuid
= *ObjectUuid
;
231 else UuidCreateNil(&Binding
->ObjectUuid
);
235 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
237 RpcBinding
* NewBinding
;
238 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding
, Connection
);
240 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
241 NewBinding
->Protseq
= RPCRT4_strdupA(rpcrt4_conn_get_name(Connection
));
242 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
243 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
244 NewBinding
->FromConn
= Connection
;
246 TRACE("binding: %p\n", NewBinding
);
247 *Binding
= NewBinding
;
252 void RPCRT4_AddRefBinding(RpcBinding
* Binding
)
254 InterlockedIncrement(&Binding
->refs
);
257 RPC_STATUS
RPCRT4_ReleaseBinding(RpcBinding
* Binding
)
259 if (InterlockedDecrement(&Binding
->refs
))
262 TRACE("binding: %p\n", Binding
);
263 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
264 RPCRT4_strfree(Binding
->Endpoint
);
265 RPCRT4_strfree(Binding
->NetworkAddr
);
266 RPCRT4_strfree(Binding
->Protseq
);
267 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
268 if (Binding
->AuthInfo
) RpcAuthInfo_Release(Binding
->AuthInfo
);
269 if (Binding
->QOS
) RpcQualityOfService_Release(Binding
->QOS
);
270 HeapFree(GetProcessHeap(), 0, Binding
);
274 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
,
275 const RPC_SYNTAX_IDENTIFIER
*TransferSyntax
,
276 const RPC_SYNTAX_IDENTIFIER
*InterfaceId
)
278 TRACE("(Binding == ^%p)\n", Binding
);
280 if (!Binding
->server
) {
281 return RpcAssoc_GetClientConnection(Binding
->Assoc
, InterfaceId
,
282 TransferSyntax
, Binding
->AuthInfo
, Binding
->QOS
, Connection
);
284 /* we already have a connection with acceptable binding, so use it */
285 if (Binding
->FromConn
) {
286 *Connection
= Binding
->FromConn
;
289 ERR("no connection in binding\n");
290 return RPC_S_INTERNAL_ERROR
;
295 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
297 TRACE("(Binding == ^%p)\n", Binding
);
298 if (!Connection
) return RPC_S_OK
;
299 if (Binding
->server
) {
300 /* don't destroy a connection that is cached in the binding */
301 if (Binding
->FromConn
== Connection
)
303 return RPCRT4_DestroyConnection(Connection
);
306 RpcAssoc_ReleaseIdleConnection(Binding
->Assoc
, Connection
);
311 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
313 DWORD len
= strlen(dst
), slen
= strlen(src
);
314 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
317 HeapFree(GetProcessHeap(), 0, dst
);
321 memcpy(ndst
+len
+1, src
, slen
+1);
325 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
327 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
328 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
331 HeapFree(GetProcessHeap(), 0, dst
);
335 memcpy(ndst
+len
+1, src
, (slen
+1)*sizeof(WCHAR
));
339 /* Copies the escaped version of a component into a string binding.
340 * Note: doesn't nul-terminate the string */
341 static RPC_CSTR
escape_string_binding_component(RPC_CSTR string_binding
,
342 const unsigned char *component
)
344 for (; *component
; component
++) {
345 switch (*component
) {
351 *string_binding
++ = '\\';
352 *string_binding
++ = *component
;
355 *string_binding
++ = *component
;
359 return string_binding
;
362 static RPC_WSTR
escape_string_binding_componentW(RPC_WSTR string_binding
,
363 const WCHAR
*component
)
365 for (; *component
; component
++) {
366 switch (*component
) {
372 *string_binding
++ = '\\';
373 *string_binding
++ = *component
;
376 *string_binding
++ = *component
;
380 return string_binding
;
383 static const unsigned char *string_binding_find_delimiter(
384 const unsigned char *string_binding
, unsigned char delim
)
386 const unsigned char *next
;
387 for (next
= string_binding
; *next
; next
++) {
398 static const WCHAR
*string_binding_find_delimiterW(
399 const WCHAR
*string_binding
, WCHAR delim
)
402 for (next
= string_binding
; *next
; next
++) {
413 static RPC_CSTR
unescape_string_binding_component(
414 const unsigned char *string_binding
, int len
)
416 RPC_CSTR component
, p
;
418 if (len
== -1) len
= strlen((const char *)string_binding
);
420 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
421 if (!component
) return NULL
;
422 for (p
= component
; len
> 0; string_binding
++, len
--) {
423 if (*string_binding
== '\\') {
426 *p
++ = *string_binding
;
428 *p
++ = *string_binding
;
435 static RPC_WSTR
unescape_string_binding_componentW(
436 const WCHAR
*string_binding
, int len
)
438 RPC_WSTR component
, p
;
440 if (len
== -1) len
= strlen((const char *)string_binding
);
442 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
443 if (!component
) return NULL
;
444 for (p
= component
; len
> 0; string_binding
++, len
--) {
445 if (*string_binding
== '\\') {
448 *p
++ = *string_binding
;
450 *p
++ = *string_binding
;
457 /***********************************************************************
458 * RpcStringBindingComposeA (RPCRT4.@)
460 RPC_STATUS WINAPI
RpcStringBindingComposeA(RPC_CSTR ObjUuid
, RPC_CSTR Protseq
,
461 RPC_CSTR NetworkAddr
, RPC_CSTR Endpoint
,
462 RPC_CSTR Options
, RPC_CSTR
*StringBinding
)
467 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
468 debugstr_a( (char*)ObjUuid
), debugstr_a( (char*)Protseq
),
469 debugstr_a( (char*)NetworkAddr
), debugstr_a( (char*)Endpoint
),
470 debugstr_a( (char*)Options
), StringBinding
);
472 /* overestimate for each component for escaping of delimiters */
473 if (ObjUuid
&& *ObjUuid
) len
+= strlen((char*)ObjUuid
) * 2 + 1;
474 if (Protseq
&& *Protseq
) len
+= strlen((char*)Protseq
) * 2 + 1;
475 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen((char*)NetworkAddr
) * 2;
476 if (Endpoint
&& *Endpoint
) len
+= strlen((char*)Endpoint
) * 2 + 2;
477 if (Options
&& *Options
) len
+= strlen((char*)Options
) * 2 + 2;
479 data
= HeapAlloc(GetProcessHeap(), 0, len
);
480 *StringBinding
= data
;
482 if (ObjUuid
&& *ObjUuid
) {
483 data
= escape_string_binding_component(data
, ObjUuid
);
486 if (Protseq
&& *Protseq
) {
487 data
= escape_string_binding_component(data
, Protseq
);
490 if (NetworkAddr
&& *NetworkAddr
)
491 data
= escape_string_binding_component(data
, NetworkAddr
);
493 if ((Endpoint
&& *Endpoint
) ||
494 (Options
&& *Options
)) {
496 if (Endpoint
&& *Endpoint
) {
497 data
= escape_string_binding_component(data
, Endpoint
);
498 if (Options
&& *Options
) *data
++ = ',';
500 if (Options
&& *Options
) {
501 data
= escape_string_binding_component(data
, Options
);
510 /***********************************************************************
511 * RpcStringBindingComposeW (RPCRT4.@)
513 RPC_STATUS WINAPI
RpcStringBindingComposeW( RPC_WSTR ObjUuid
, RPC_WSTR Protseq
,
514 RPC_WSTR NetworkAddr
, RPC_WSTR Endpoint
,
515 RPC_WSTR Options
, RPC_WSTR
* StringBinding
)
520 TRACE("(%s,%s,%s,%s,%s,%p)\n",
521 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
522 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
523 debugstr_w( Options
), StringBinding
);
525 /* overestimate for each component for escaping of delimiters */
526 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) * 2 + 1;
527 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) * 2 + 1;
528 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
) * 2;
529 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) * 2 + 2;
530 if (Options
&& *Options
) len
+= strlenW(Options
) * 2 + 2;
532 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
533 *StringBinding
= data
;
535 if (ObjUuid
&& *ObjUuid
) {
536 data
= escape_string_binding_componentW(data
, ObjUuid
);
539 if (Protseq
&& *Protseq
) {
540 data
= escape_string_binding_componentW(data
, Protseq
);
543 if (NetworkAddr
&& *NetworkAddr
) {
544 data
= escape_string_binding_componentW(data
, NetworkAddr
);
546 if ((Endpoint
&& *Endpoint
) ||
547 (Options
&& *Options
)) {
549 if (Endpoint
&& *Endpoint
) {
550 data
= escape_string_binding_componentW(data
, Endpoint
);
551 if (Options
&& *Options
) *data
++ = ',';
553 if (Options
&& *Options
) {
554 data
= escape_string_binding_componentW(data
, Options
);
564 /***********************************************************************
565 * RpcStringBindingParseA (RPCRT4.@)
567 RPC_STATUS WINAPI
RpcStringBindingParseA( RPC_CSTR StringBinding
, RPC_CSTR
*ObjUuid
,
568 RPC_CSTR
*Protseq
, RPC_CSTR
*NetworkAddr
,
569 RPC_CSTR
*Endpoint
, RPC_CSTR
*Options
)
571 const unsigned char *data
, *next
;
572 static const char ep_opt
[] = "endpoint=";
573 BOOL endpoint_already_found
= FALSE
;
575 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding
),
576 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
578 if (ObjUuid
) *ObjUuid
= NULL
;
579 if (Protseq
) *Protseq
= NULL
;
580 if (NetworkAddr
) *NetworkAddr
= NULL
;
581 if (Endpoint
) *Endpoint
= NULL
;
582 if (Options
) *Options
= NULL
;
584 data
= StringBinding
;
586 next
= string_binding_find_delimiter(data
, '@');
590 RPC_CSTR str_uuid
= unescape_string_binding_component(data
, next
- data
);
591 status
= UuidFromStringA(str_uuid
, &uuid
);
592 if (status
!= RPC_S_OK
) {
593 HeapFree(GetProcessHeap(), 0, str_uuid
);
599 HeapFree(GetProcessHeap(), 0, str_uuid
);
603 next
= string_binding_find_delimiter(data
, ':');
605 if (Protseq
) *Protseq
= unescape_string_binding_component(data
, next
- data
);
609 next
= string_binding_find_delimiter(data
, '[');
611 const unsigned char *close
;
614 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_component(data
, next
- data
);
616 close
= string_binding_find_delimiter(data
, ']');
617 if (!close
) goto fail
;
619 /* tokenize options */
620 while (data
< close
) {
621 next
= string_binding_find_delimiter(data
, ',');
622 if (!next
|| next
> close
) next
= close
;
623 /* FIXME: this is kind of inefficient */
624 opt
= unescape_string_binding_component(data
, next
- data
);
628 next
= string_binding_find_delimiter(opt
, '=');
630 /* not an option, must be an endpoint */
631 if (endpoint_already_found
) goto fail
;
632 if (Endpoint
) *Endpoint
= opt
;
633 else HeapFree(GetProcessHeap(), 0, opt
);
634 endpoint_already_found
= TRUE
;
636 if (strncmp((const char *)opt
, ep_opt
, strlen(ep_opt
)) == 0) {
637 /* endpoint option */
638 if (endpoint_already_found
) goto fail
;
639 if (Endpoint
) *Endpoint
= unescape_string_binding_component(next
+1, -1);
640 HeapFree(GetProcessHeap(), 0, opt
);
641 endpoint_already_found
= TRUE
;
646 /* FIXME: this is kind of inefficient */
647 *Options
= (unsigned char*) RPCRT4_strconcatA( (char*)*Options
, (char *)opt
);
648 HeapFree(GetProcessHeap(), 0, opt
);
652 HeapFree(GetProcessHeap(), 0, opt
);
658 if (*data
) goto fail
;
660 else if (NetworkAddr
)
661 *NetworkAddr
= unescape_string_binding_component(data
, -1);
666 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
667 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
668 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
669 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
670 if (Options
) RpcStringFreeA((unsigned char**)Options
);
671 return RPC_S_INVALID_STRING_BINDING
;
674 /***********************************************************************
675 * RpcStringBindingParseW (RPCRT4.@)
677 RPC_STATUS WINAPI
RpcStringBindingParseW( RPC_WSTR StringBinding
, RPC_WSTR
*ObjUuid
,
678 RPC_WSTR
*Protseq
, RPC_WSTR
*NetworkAddr
,
679 RPC_WSTR
*Endpoint
, RPC_WSTR
*Options
)
681 const WCHAR
*data
, *next
;
682 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
683 BOOL endpoint_already_found
= FALSE
;
685 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
686 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
688 if (ObjUuid
) *ObjUuid
= NULL
;
689 if (Protseq
) *Protseq
= NULL
;
690 if (NetworkAddr
) *NetworkAddr
= NULL
;
691 if (Endpoint
) *Endpoint
= NULL
;
692 if (Options
) *Options
= NULL
;
694 data
= StringBinding
;
696 next
= string_binding_find_delimiterW(data
, '@');
700 RPC_WSTR str_uuid
= unescape_string_binding_componentW(data
, next
- data
);
701 status
= UuidFromStringW(str_uuid
, &uuid
);
702 if (status
!= RPC_S_OK
) {
703 HeapFree(GetProcessHeap(), 0, str_uuid
);
709 HeapFree(GetProcessHeap(), 0, str_uuid
);
713 next
= string_binding_find_delimiterW(data
, ':');
715 if (Protseq
) *Protseq
= unescape_string_binding_componentW(data
, next
- data
);
719 next
= string_binding_find_delimiterW(data
, '[');
724 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_componentW(data
, next
- data
);
726 close
= string_binding_find_delimiterW(data
, ']');
727 if (!close
) goto fail
;
729 /* tokenize options */
730 while (data
< close
) {
731 next
= string_binding_find_delimiterW(data
, ',');
732 if (!next
|| next
> close
) next
= close
;
733 /* FIXME: this is kind of inefficient */
734 opt
= unescape_string_binding_componentW(data
, next
- data
);
738 next
= string_binding_find_delimiterW(opt
, '=');
740 /* not an option, must be an endpoint */
741 if (endpoint_already_found
) goto fail
;
742 if (Endpoint
) *Endpoint
= opt
;
743 else HeapFree(GetProcessHeap(), 0, opt
);
744 endpoint_already_found
= TRUE
;
746 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
747 /* endpoint option */
748 if (endpoint_already_found
) goto fail
;
749 if (Endpoint
) *Endpoint
= unescape_string_binding_componentW(next
+1, -1);
750 HeapFree(GetProcessHeap(), 0, opt
);
751 endpoint_already_found
= TRUE
;
756 /* FIXME: this is kind of inefficient */
757 *Options
= RPCRT4_strconcatW(*Options
, opt
);
758 HeapFree(GetProcessHeap(), 0, opt
);
762 HeapFree(GetProcessHeap(), 0, opt
);
768 if (*data
) goto fail
;
769 } else if (NetworkAddr
)
770 *NetworkAddr
= unescape_string_binding_componentW(data
, -1);
775 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
776 if (Protseq
) RpcStringFreeW(Protseq
);
777 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
778 if (Endpoint
) RpcStringFreeW(Endpoint
);
779 if (Options
) RpcStringFreeW(Options
);
780 return RPC_S_INVALID_STRING_BINDING
;
783 /***********************************************************************
784 * RpcBindingFree (RPCRT4.@)
786 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
789 TRACE("(%p) = %p\n", Binding
, *Binding
);
790 status
= RPCRT4_ReleaseBinding(*Binding
);
791 if (status
== RPC_S_OK
) *Binding
= 0;
795 /***********************************************************************
796 * RpcBindingVectorFree (RPCRT4.@)
798 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
803 TRACE("(%p)\n", BindingVector
);
804 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
805 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
807 HeapFree(GetProcessHeap(), 0, *BindingVector
);
808 *BindingVector
= NULL
;
812 /***********************************************************************
813 * RpcBindingInqObject (RPCRT4.@)
815 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
817 RpcBinding
* bind
= (RpcBinding
*)Binding
;
819 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
820 *ObjectUuid
= bind
->ObjectUuid
;
824 /***********************************************************************
825 * RpcBindingSetObject (RPCRT4.@)
827 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
829 RpcBinding
* bind
= (RpcBinding
*)Binding
;
831 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
832 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
833 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
836 /***********************************************************************
837 * RpcBindingFromStringBindingA (RPCRT4.@)
839 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( RPC_CSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
842 RpcBinding
* bind
= NULL
;
843 RPC_CSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
846 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
848 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
849 &NetworkAddr
, &Endpoint
, &Options
);
850 if (ret
!= RPC_S_OK
) return ret
;
852 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
855 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
856 if (ret
!= RPC_S_OK
) return ret
;
857 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
859 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
861 RpcStringFreeA((unsigned char**)&Options
);
862 RpcStringFreeA((unsigned char**)&Endpoint
);
863 RpcStringFreeA((unsigned char**)&NetworkAddr
);
864 RpcStringFreeA((unsigned char**)&Protseq
);
865 RpcStringFreeA((unsigned char**)&ObjectUuid
);
868 *Binding
= (RPC_BINDING_HANDLE
)bind
;
870 RPCRT4_ReleaseBinding(bind
);
875 /***********************************************************************
876 * RpcBindingFromStringBindingW (RPCRT4.@)
878 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( RPC_WSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
881 RpcBinding
* bind
= NULL
;
882 RPC_WSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
885 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
887 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
888 &NetworkAddr
, &Endpoint
, &Options
);
889 if (ret
!= RPC_S_OK
) return ret
;
891 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
894 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
895 if (ret
!= RPC_S_OK
) return ret
;
896 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
898 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
900 RpcStringFreeW(&Options
);
901 RpcStringFreeW(&Endpoint
);
902 RpcStringFreeW(&NetworkAddr
);
903 RpcStringFreeW(&Protseq
);
904 RpcStringFreeW(&ObjectUuid
);
907 *Binding
= (RPC_BINDING_HANDLE
)bind
;
909 RPCRT4_ReleaseBinding(bind
);
914 /***********************************************************************
915 * RpcBindingToStringBindingA (RPCRT4.@)
917 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*StringBinding
)
920 RpcBinding
* bind
= (RpcBinding
*)Binding
;
923 TRACE("(%p,%p)\n", Binding
, StringBinding
);
925 if (UuidIsNil(&bind
->ObjectUuid
, &ret
))
929 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
930 if (ret
!= RPC_S_OK
) return ret
;
933 ret
= RpcStringBindingComposeA(ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
934 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
936 RpcStringFreeA(&ObjectUuid
);
941 /***********************************************************************
942 * RpcBindingToStringBindingW (RPCRT4.@)
944 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*StringBinding
)
947 unsigned char *str
= NULL
;
948 TRACE("(%p,%p)\n", Binding
, StringBinding
);
949 ret
= RpcBindingToStringBindingA(Binding
, &str
);
950 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
951 RpcStringFreeA((unsigned char**)&str
);
955 /***********************************************************************
956 * I_RpcBindingInqTransportType (RPCRT4.@)
958 RPC_STATUS WINAPI
I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding
, unsigned int * Type
)
961 FIXME( "(%p,%p): stub\n", Binding
, Type
);
962 *Type
= TRANSPORT_TYPE_LPC
;
966 /***********************************************************************
967 * I_RpcBindingSetAsync (RPCRT4.@)
969 * Exists in win9x and winNT, but with different number of arguments
970 * (9x version has 3 arguments, NT has 2).
972 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
974 RpcBinding
* bind
= (RpcBinding
*)Binding
;
976 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
978 bind
->BlockingFn
= BlockingFn
;
983 /***********************************************************************
984 * RpcBindingCopy (RPCRT4.@)
986 RPC_STATUS RPC_ENTRY
RpcBindingCopy(
987 RPC_BINDING_HANDLE SourceBinding
,
988 RPC_BINDING_HANDLE
* DestinationBinding
)
990 RpcBinding
*DestBinding
;
991 RpcBinding
*SrcBinding
= (RpcBinding
*)SourceBinding
;
994 TRACE("(%p, %p)\n", SourceBinding
, DestinationBinding
);
996 status
= RPCRT4_AllocBinding(&DestBinding
, SrcBinding
->server
);
997 if (status
!= RPC_S_OK
) return status
;
999 DestBinding
->ObjectUuid
= SrcBinding
->ObjectUuid
;
1000 DestBinding
->BlockingFn
= SrcBinding
->BlockingFn
;
1001 DestBinding
->Protseq
= RPCRT4_strndupA(SrcBinding
->Protseq
, -1);
1002 DestBinding
->NetworkAddr
= RPCRT4_strndupA(SrcBinding
->NetworkAddr
, -1);
1003 DestBinding
->Endpoint
= RPCRT4_strndupA(SrcBinding
->Endpoint
, -1);
1004 DestBinding
->NetworkOptions
= RPCRT4_strdupW(SrcBinding
->NetworkOptions
);
1005 if (SrcBinding
->Assoc
) SrcBinding
->Assoc
->refs
++;
1006 DestBinding
->Assoc
= SrcBinding
->Assoc
;
1008 if (SrcBinding
->AuthInfo
) RpcAuthInfo_AddRef(SrcBinding
->AuthInfo
);
1009 DestBinding
->AuthInfo
= SrcBinding
->AuthInfo
;
1010 if (SrcBinding
->QOS
) RpcQualityOfService_AddRef(SrcBinding
->QOS
);
1011 DestBinding
->QOS
= SrcBinding
->QOS
;
1013 *DestinationBinding
= DestBinding
;
1017 /***********************************************************************
1018 * RpcImpersonateClient (RPCRT4.@)
1020 * Impersonates the client connected via a binding handle so that security
1021 * checks are done in the context of the client.
1024 * BindingHandle [I] Handle to the binding to the client.
1027 * Success: RPS_S_OK.
1028 * Failure: RPC_STATUS value.
1032 * If BindingHandle is NULL then the function impersonates the client
1033 * connected to the binding handle of the current thread.
1035 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
1037 FIXME("(%p): stub\n", BindingHandle
);
1038 ImpersonateSelf(SecurityImpersonation
);
1042 /***********************************************************************
1043 * RpcRevertToSelfEx (RPCRT4.@)
1045 * Stops impersonating the client connected to the binding handle so that security
1046 * checks are no longer done in the context of the client.
1049 * BindingHandle [I] Handle to the binding to the client.
1052 * Success: RPS_S_OK.
1053 * Failure: RPC_STATUS value.
1057 * If BindingHandle is NULL then the function stops impersonating the client
1058 * connected to the binding handle of the current thread.
1060 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
1062 FIXME("(%p): stub\n", BindingHandle
);
1066 static inline BOOL
has_nt_auth_identity(ULONG AuthnLevel
)
1070 case RPC_C_AUTHN_GSS_NEGOTIATE
:
1071 case RPC_C_AUTHN_WINNT
:
1072 case RPC_C_AUTHN_GSS_KERBEROS
:
1079 static RPC_STATUS
RpcAuthInfo_Create(ULONG AuthnLevel
, ULONG AuthnSvc
,
1080 CredHandle cred
, TimeStamp exp
,
1082 RPC_AUTH_IDENTITY_HANDLE identity
,
1085 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
1087 return ERROR_OUTOFMEMORY
;
1090 AuthInfo
->AuthnLevel
= AuthnLevel
;
1091 AuthInfo
->AuthnSvc
= AuthnSvc
;
1092 AuthInfo
->cred
= cred
;
1093 AuthInfo
->exp
= exp
;
1094 AuthInfo
->cbMaxToken
= cbMaxToken
;
1095 AuthInfo
->identity
= identity
;
1096 AuthInfo
->server_principal_name
= NULL
;
1098 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1099 * enable better matching in RpcAuthInfo_IsEqual */
1100 if (identity
&& has_nt_auth_identity(AuthnSvc
))
1102 const SEC_WINNT_AUTH_IDENTITY_W
*nt_identity
= identity
;
1103 AuthInfo
->nt_identity
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
->nt_identity
));
1104 if (!AuthInfo
->nt_identity
)
1106 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1107 return ERROR_OUTOFMEMORY
;
1110 AuthInfo
->nt_identity
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1111 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1112 AuthInfo
->nt_identity
->User
= RPCRT4_strndupW(nt_identity
->User
, nt_identity
->UserLength
);
1114 AuthInfo
->nt_identity
->User
= RPCRT4_strndupAtoW((const char *)nt_identity
->User
, nt_identity
->UserLength
);
1115 AuthInfo
->nt_identity
->UserLength
= nt_identity
->UserLength
;
1116 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1117 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupW(nt_identity
->Domain
, nt_identity
->DomainLength
);
1119 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupAtoW((const char *)nt_identity
->Domain
, nt_identity
->DomainLength
);
1120 AuthInfo
->nt_identity
->DomainLength
= nt_identity
->DomainLength
;
1121 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1122 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupW(nt_identity
->Password
, nt_identity
->PasswordLength
);
1124 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupAtoW((const char *)nt_identity
->Password
, nt_identity
->PasswordLength
);
1125 AuthInfo
->nt_identity
->PasswordLength
= nt_identity
->PasswordLength
;
1127 if ((nt_identity
->User
&& !AuthInfo
->nt_identity
->User
) ||
1128 (nt_identity
->Domain
&& !AuthInfo
->nt_identity
->Domain
) ||
1129 (nt_identity
->Password
&& !AuthInfo
->nt_identity
->Password
))
1131 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1132 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1133 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1134 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1135 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1136 return ERROR_OUTOFMEMORY
;
1140 AuthInfo
->nt_identity
= NULL
;
1145 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
1147 return InterlockedIncrement(&AuthInfo
->refs
);
1150 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
1152 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
1156 FreeCredentialsHandle(&AuthInfo
->cred
);
1157 if (AuthInfo
->nt_identity
)
1159 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1160 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1161 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1162 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1164 HeapFree(GetProcessHeap(), 0, AuthInfo
->server_principal_name
);
1165 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1171 BOOL
RpcAuthInfo_IsEqual(const RpcAuthInfo
*AuthInfo1
, const RpcAuthInfo
*AuthInfo2
)
1173 if (AuthInfo1
== AuthInfo2
)
1176 if (!AuthInfo1
|| !AuthInfo2
)
1179 if ((AuthInfo1
->AuthnLevel
!= AuthInfo2
->AuthnLevel
) ||
1180 (AuthInfo1
->AuthnSvc
!= AuthInfo2
->AuthnSvc
))
1183 if (AuthInfo1
->identity
== AuthInfo2
->identity
)
1186 if (!AuthInfo1
->identity
|| !AuthInfo2
->identity
)
1189 if (has_nt_auth_identity(AuthInfo1
->AuthnSvc
))
1191 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= AuthInfo1
->nt_identity
;
1192 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= AuthInfo2
->nt_identity
;
1193 /* compare user names */
1194 if (identity1
->UserLength
!= identity2
->UserLength
||
1195 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1197 /* compare domain names */
1198 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1199 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1201 /* compare passwords */
1202 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1203 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1212 static RPC_STATUS
RpcQualityOfService_Create(const RPC_SECURITY_QOS
*qos_src
, BOOL unicode
, RpcQualityOfService
**qos_dst
)
1214 RpcQualityOfService
*qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
));
1217 return RPC_S_OUT_OF_RESOURCES
;
1220 qos
->qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
->qos
));
1221 if (!qos
->qos
) goto error
;
1222 qos
->qos
->Version
= qos_src
->Version
;
1223 qos
->qos
->Capabilities
= qos_src
->Capabilities
;
1224 qos
->qos
->IdentityTracking
= qos_src
->IdentityTracking
;
1225 qos
->qos
->ImpersonationType
= qos_src
->ImpersonationType
;
1226 qos
->qos
->AdditionalSecurityInfoType
= 0;
1228 if (qos_src
->Version
>= 2)
1230 const RPC_SECURITY_QOS_V2_W
*qos_src2
= (const RPC_SECURITY_QOS_V2_W
*)qos_src
;
1231 qos
->qos
->AdditionalSecurityInfoType
= qos_src2
->AdditionalSecurityInfoType
;
1232 if (qos_src2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1234 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_src
= qos_src2
->u
.HttpCredentials
;
1235 RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_dst
;
1237 http_credentials_dst
= HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst
));
1238 qos
->qos
->u
.HttpCredentials
= http_credentials_dst
;
1239 if (!http_credentials_dst
) goto error
;
1240 http_credentials_dst
->TransportCredentials
= NULL
;
1241 http_credentials_dst
->Flags
= http_credentials_src
->Flags
;
1242 http_credentials_dst
->AuthenticationTarget
= http_credentials_src
->AuthenticationTarget
;
1243 http_credentials_dst
->NumberOfAuthnSchemes
= http_credentials_src
->NumberOfAuthnSchemes
;
1244 http_credentials_dst
->AuthnSchemes
= NULL
;
1245 http_credentials_dst
->ServerCertificateSubject
= NULL
;
1246 if (http_credentials_src
->TransportCredentials
)
1248 SEC_WINNT_AUTH_IDENTITY_W
*cred_dst
;
1249 cred_dst
= http_credentials_dst
->TransportCredentials
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cred_dst
));
1250 if (!cred_dst
) goto error
;
1251 cred_dst
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1254 const SEC_WINNT_AUTH_IDENTITY_W
*cred_src
= http_credentials_src
->TransportCredentials
;
1255 cred_dst
->UserLength
= cred_src
->UserLength
;
1256 cred_dst
->PasswordLength
= cred_src
->PasswordLength
;
1257 cred_dst
->DomainLength
= cred_src
->DomainLength
;
1258 cred_dst
->User
= RPCRT4_strndupW(cred_src
->User
, cred_src
->UserLength
);
1259 cred_dst
->Password
= RPCRT4_strndupW(cred_src
->Password
, cred_src
->PasswordLength
);
1260 cred_dst
->Domain
= RPCRT4_strndupW(cred_src
->Domain
, cred_src
->DomainLength
);
1264 const SEC_WINNT_AUTH_IDENTITY_A
*cred_src
= (const SEC_WINNT_AUTH_IDENTITY_A
*)http_credentials_src
->TransportCredentials
;
1265 cred_dst
->UserLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, NULL
, 0);
1266 cred_dst
->DomainLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, NULL
, 0);
1267 cred_dst
->PasswordLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, NULL
, 0);
1268 cred_dst
->User
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->UserLength
* sizeof(WCHAR
));
1269 cred_dst
->Password
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->PasswordLength
* sizeof(WCHAR
));
1270 cred_dst
->Domain
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->DomainLength
* sizeof(WCHAR
));
1271 if (!cred_dst
|| !cred_dst
->Password
|| !cred_dst
->Domain
) goto error
;
1272 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, cred_dst
->User
, cred_dst
->UserLength
);
1273 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, cred_dst
->Domain
, cred_dst
->DomainLength
);
1274 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, cred_dst
->Password
, cred_dst
->PasswordLength
);
1277 if (http_credentials_src
->NumberOfAuthnSchemes
)
1279 http_credentials_dst
->AuthnSchemes
= HeapAlloc(GetProcessHeap(), 0, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1280 if (!http_credentials_dst
->AuthnSchemes
) goto error
;
1281 memcpy(http_credentials_dst
->AuthnSchemes
, http_credentials_src
->AuthnSchemes
, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1283 if (http_credentials_src
->ServerCertificateSubject
)
1286 http_credentials_dst
->ServerCertificateSubject
=
1287 RPCRT4_strndupW(http_credentials_src
->ServerCertificateSubject
,
1288 strlenW(http_credentials_src
->ServerCertificateSubject
));
1290 http_credentials_dst
->ServerCertificateSubject
=
1291 RPCRT4_strdupAtoW((char *)http_credentials_src
->ServerCertificateSubject
);
1292 if (!http_credentials_dst
->ServerCertificateSubject
) goto error
;
1302 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
&&
1303 qos
->qos
->u
.HttpCredentials
)
1305 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1307 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1308 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1309 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1310 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1312 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1313 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1314 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1316 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1318 HeapFree(GetProcessHeap(), 0, qos
);
1319 return RPC_S_OUT_OF_RESOURCES
;
1322 ULONG
RpcQualityOfService_AddRef(RpcQualityOfService
*qos
)
1324 return InterlockedIncrement(&qos
->refs
);
1327 ULONG
RpcQualityOfService_Release(RpcQualityOfService
*qos
)
1329 ULONG refs
= InterlockedDecrement(&qos
->refs
);
1333 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1335 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1337 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1338 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1339 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1340 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1342 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1343 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1344 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1346 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1347 HeapFree(GetProcessHeap(), 0, qos
);
1352 BOOL
RpcQualityOfService_IsEqual(const RpcQualityOfService
*qos1
, const RpcQualityOfService
*qos2
)
1360 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1361 qos1
->qos
->Capabilities
, qos1
->qos
->IdentityTracking
,
1362 qos1
->qos
->ImpersonationType
, qos1
->qos
->AdditionalSecurityInfoType
,
1363 qos2
->qos
->Capabilities
, qos2
->qos
->IdentityTracking
,
1364 qos2
->qos
->ImpersonationType
, qos2
->qos
->AdditionalSecurityInfoType
);
1366 if ((qos1
->qos
->Capabilities
!= qos2
->qos
->Capabilities
) ||
1367 (qos1
->qos
->IdentityTracking
!= qos2
->qos
->IdentityTracking
) ||
1368 (qos1
->qos
->ImpersonationType
!= qos2
->qos
->ImpersonationType
) ||
1369 (qos1
->qos
->AdditionalSecurityInfoType
!= qos2
->qos
->AdditionalSecurityInfoType
))
1372 if (qos1
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1374 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials1
= qos1
->qos
->u
.HttpCredentials
;
1375 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials2
= qos2
->qos
->u
.HttpCredentials
;
1377 if (http_credentials1
->Flags
!= http_credentials2
->Flags
)
1380 if (http_credentials1
->AuthenticationTarget
!= http_credentials2
->AuthenticationTarget
)
1383 /* authentication schemes and server certificate subject not currently used */
1385 if (http_credentials1
->TransportCredentials
!= http_credentials2
->TransportCredentials
)
1387 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= http_credentials1
->TransportCredentials
;
1388 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= http_credentials2
->TransportCredentials
;
1390 if (!identity1
|| !identity2
)
1393 /* compare user names */
1394 if (identity1
->UserLength
!= identity2
->UserLength
||
1395 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1397 /* compare domain names */
1398 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1399 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1401 /* compare passwords */
1402 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1403 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1411 /***********************************************************************
1412 * RpcRevertToSelf (RPCRT4.@)
1414 RPC_STATUS WINAPI
RpcRevertToSelf(void)
1421 /***********************************************************************
1422 * RpcMgmtSetComTimeout (RPCRT4.@)
1424 RPC_STATUS WINAPI
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle
, unsigned int Timeout
)
1426 FIXME("(%p, %d): stub\n", BindingHandle
, Timeout
);
1430 /***********************************************************************
1431 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1433 RPCRTAPI RPC_STATUS RPC_ENTRY
1434 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1435 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1436 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1438 FIXME("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1439 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1440 return RPC_S_INVALID_BINDING
;
1443 /***********************************************************************
1444 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1446 RPCRTAPI RPC_STATUS RPC_ENTRY
1447 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1448 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1449 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1451 FIXME("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1452 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1453 return RPC_S_INVALID_BINDING
;
1456 /***********************************************************************
1457 * RpcBindingInqAuthInfoA (RPCRT4.@)
1459 RPCRTAPI RPC_STATUS RPC_ENTRY
1460 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1461 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1463 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1464 AuthnSvc
, AuthIdentity
, AuthzSvc
);
1465 return RPC_S_INVALID_BINDING
;
1468 /***********************************************************************
1469 * RpcBindingInqAuthInfoW (RPCRT4.@)
1471 RPCRTAPI RPC_STATUS RPC_ENTRY
1472 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1473 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1475 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1476 AuthnSvc
, AuthIdentity
, AuthzSvc
);
1477 return RPC_S_INVALID_BINDING
;
1480 /***********************************************************************
1481 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1483 RPCRTAPI RPC_STATUS RPC_ENTRY
1484 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
,
1485 ULONG AuthnLevel
, ULONG AuthnSvc
,
1486 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1487 RPC_SECURITY_QOS
*SecurityQos
)
1489 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1493 ULONG package_count
;
1495 PSecPkgInfoA packages
;
1498 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1499 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1505 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1506 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1507 if (SecurityQos
->Version
>= 2)
1509 const RPC_SECURITY_QOS_V2_A
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_A
*)SecurityQos
;
1510 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2
->AdditionalSecurityInfoType
);
1511 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1512 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1513 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1514 SecurityQos2
->u
.HttpCredentials
->Flags
,
1515 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1516 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1517 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1518 SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
);
1521 status
= RpcQualityOfService_Create(SecurityQos
, FALSE
, &bind
->QOS
);
1522 if (status
!= RPC_S_OK
)
1527 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1531 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1532 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1534 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1535 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1536 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1538 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1540 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1541 bind
->AuthInfo
= NULL
;
1545 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1547 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1548 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1551 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1552 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1554 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1555 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1558 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1561 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1562 return RPC_S_SEC_PKG_ERROR
;
1565 for (i
= 0; i
< package_count
; i
++)
1566 if (packages
[i
].wRPCID
== AuthnSvc
)
1569 if (i
== package_count
)
1571 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1572 FreeContextBuffer(packages
);
1573 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1576 TRACE("found package %s for service %u\n", packages
[i
].Name
, AuthnSvc
);
1577 r
= AcquireCredentialsHandleA(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1578 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1579 cbMaxToken
= packages
[i
].cbMaxToken
;
1580 FreeContextBuffer(packages
);
1581 if (r
== ERROR_SUCCESS
)
1583 RpcAuthInfo
*new_auth_info
;
1584 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1585 AuthIdentity
, &new_auth_info
);
1588 new_auth_info
->server_principal_name
= RPCRT4_strdupAtoW((char *)ServerPrincName
);
1589 if (new_auth_info
->server_principal_name
)
1591 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1592 bind
->AuthInfo
= new_auth_info
;
1596 RpcAuthInfo_Release(new_auth_info
);
1597 r
= ERROR_OUTOFMEMORY
;
1601 FreeCredentialsHandle(&cred
);
1606 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1607 return RPC_S_SEC_PKG_ERROR
;
1611 /***********************************************************************
1612 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1614 RPCRTAPI RPC_STATUS RPC_ENTRY
1615 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1616 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1617 RPC_SECURITY_QOS
*SecurityQos
)
1619 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1623 ULONG package_count
;
1625 PSecPkgInfoW packages
;
1628 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1629 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1635 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1636 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1637 if (SecurityQos
->Version
>= 2)
1639 const RPC_SECURITY_QOS_V2_W
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_W
*)SecurityQos
;
1640 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2
->AdditionalSecurityInfoType
);
1641 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1642 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1643 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1644 SecurityQos2
->u
.HttpCredentials
->Flags
,
1645 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1646 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1647 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1648 debugstr_w(SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
));
1651 status
= RpcQualityOfService_Create(SecurityQos
, TRUE
, &bind
->QOS
);
1652 if (status
!= RPC_S_OK
)
1657 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1661 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1662 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1664 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1665 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1666 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1668 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1670 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1671 bind
->AuthInfo
= NULL
;
1675 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1677 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1678 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1681 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1682 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1684 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1685 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1688 r
= EnumerateSecurityPackagesW(&package_count
, &packages
);
1691 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r
);
1692 return RPC_S_SEC_PKG_ERROR
;
1695 for (i
= 0; i
< package_count
; i
++)
1696 if (packages
[i
].wRPCID
== AuthnSvc
)
1699 if (i
== package_count
)
1701 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1702 FreeContextBuffer(packages
);
1703 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1706 TRACE("found package %s for service %u\n", debugstr_w(packages
[i
].Name
), AuthnSvc
);
1707 r
= AcquireCredentialsHandleW(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1708 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1709 cbMaxToken
= packages
[i
].cbMaxToken
;
1710 FreeContextBuffer(packages
);
1711 if (r
== ERROR_SUCCESS
)
1713 RpcAuthInfo
*new_auth_info
;
1714 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1715 AuthIdentity
, &new_auth_info
);
1718 new_auth_info
->server_principal_name
= RPCRT4_strdupW(ServerPrincName
);
1719 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1721 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1722 bind
->AuthInfo
= new_auth_info
;
1726 RpcAuthInfo_Release(new_auth_info
);
1727 r
= ERROR_OUTOFMEMORY
;
1731 FreeCredentialsHandle(&cred
);
1736 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r
);
1737 return RPC_S_SEC_PKG_ERROR
;
1741 /***********************************************************************
1742 * RpcBindingSetAuthInfoA (RPCRT4.@)
1744 RPCRTAPI RPC_STATUS RPC_ENTRY
1745 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
, ULONG AuthnLevel
,
1746 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1748 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1749 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1750 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1753 /***********************************************************************
1754 * RpcBindingSetAuthInfoW (RPCRT4.@)
1756 RPCRTAPI RPC_STATUS RPC_ENTRY
1757 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1758 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1760 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1761 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1762 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1765 /***********************************************************************
1766 * RpcBindingSetOption (RPCRT4.@)
1768 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG_PTR OptionValue
)
1770 FIXME("(%p, %d, %ld): stub\n", BindingHandle
, Option
, OptionValue
);