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
);
160 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
161 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
162 Binding
->NetworkOptions
= RPCRT4_strdupAtoW(NetworkOptions
);
164 /* only attempt to get an association if the binding is complete */
165 if (Endpoint
&& Endpoint
[0] != '\0')
167 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
168 Binding
->Endpoint
, Binding
->NetworkOptions
,
170 if (status
!= RPC_S_OK
)
177 static RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPCWSTR NetworkAddr
,
178 LPCWSTR Endpoint
, LPCWSTR NetworkOptions
)
182 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding
,
183 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
185 RPCRT4_strfree(Binding
->NetworkAddr
);
186 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
187 RPCRT4_strfree(Binding
->Endpoint
);
188 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
189 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
190 Binding
->NetworkOptions
= RPCRT4_strdupW(NetworkOptions
);
192 /* only attempt to get an association if the binding is complete */
193 if (Endpoint
&& Endpoint
[0] != '\0')
195 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
196 Binding
->Endpoint
, Binding
->NetworkOptions
,
198 if (status
!= RPC_S_OK
)
205 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPCSTR Endpoint
)
209 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
211 RPCRT4_strfree(Binding
->Endpoint
);
212 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
214 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
215 Binding
->Assoc
= NULL
;
216 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
217 Binding
->Endpoint
, Binding
->NetworkOptions
,
219 if (status
!= RPC_S_OK
)
225 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, const UUID
* ObjectUuid
)
227 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
228 if (ObjectUuid
) Binding
->ObjectUuid
= *ObjectUuid
;
229 else UuidCreateNil(&Binding
->ObjectUuid
);
233 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
235 RpcBinding
* NewBinding
;
236 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding
, Connection
);
238 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
239 NewBinding
->Protseq
= RPCRT4_strdupA(rpcrt4_conn_get_name(Connection
));
240 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
241 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
242 NewBinding
->FromConn
= Connection
;
244 TRACE("binding: %p\n", NewBinding
);
245 *Binding
= NewBinding
;
250 void RPCRT4_AddRefBinding(RpcBinding
* Binding
)
252 InterlockedIncrement(&Binding
->refs
);
255 RPC_STATUS
RPCRT4_ReleaseBinding(RpcBinding
* Binding
)
257 if (InterlockedDecrement(&Binding
->refs
))
260 TRACE("binding: %p\n", Binding
);
261 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
262 RPCRT4_strfree(Binding
->Endpoint
);
263 RPCRT4_strfree(Binding
->NetworkAddr
);
264 RPCRT4_strfree(Binding
->Protseq
);
265 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
266 HeapFree(GetProcessHeap(), 0, Binding
->CookieAuth
);
267 if (Binding
->AuthInfo
) RpcAuthInfo_Release(Binding
->AuthInfo
);
268 if (Binding
->QOS
) RpcQualityOfService_Release(Binding
->QOS
);
269 HeapFree(GetProcessHeap(), 0, Binding
);
273 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
,
274 const RPC_SYNTAX_IDENTIFIER
*TransferSyntax
,
275 const RPC_SYNTAX_IDENTIFIER
*InterfaceId
)
277 TRACE("(Binding == ^%p)\n", Binding
);
279 if (!Binding
->server
) {
280 return RpcAssoc_GetClientConnection(Binding
->Assoc
, InterfaceId
,
281 TransferSyntax
, Binding
->AuthInfo
, Binding
->QOS
, Binding
->CookieAuth
, Connection
);
283 /* we already have a connection with acceptable binding, so use it */
284 if (Binding
->FromConn
) {
285 *Connection
= Binding
->FromConn
;
288 ERR("no connection in binding\n");
289 return RPC_S_INTERNAL_ERROR
;
294 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
296 TRACE("(Binding == ^%p)\n", Binding
);
297 if (!Connection
) return RPC_S_OK
;
298 if (Binding
->server
) {
299 /* don't destroy a connection that is cached in the binding */
300 if (Binding
->FromConn
== Connection
)
302 return RPCRT4_ReleaseConnection(Connection
);
305 RpcAssoc_ReleaseIdleConnection(Binding
->Assoc
, Connection
);
310 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
312 DWORD len
= strlen(dst
), slen
= strlen(src
);
313 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
316 HeapFree(GetProcessHeap(), 0, dst
);
320 memcpy(ndst
+len
+1, src
, slen
+1);
324 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
326 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
327 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
330 HeapFree(GetProcessHeap(), 0, dst
);
334 memcpy(ndst
+len
+1, src
, (slen
+1)*sizeof(WCHAR
));
338 /* Copies the escaped version of a component into a string binding.
339 * Note: doesn't nul-terminate the string */
340 static RPC_CSTR
escape_string_binding_component(RPC_CSTR string_binding
,
341 const unsigned char *component
)
343 for (; *component
; component
++) {
344 switch (*component
) {
350 *string_binding
++ = '\\';
351 *string_binding
++ = *component
;
354 *string_binding
++ = *component
;
358 return string_binding
;
361 static RPC_WSTR
escape_string_binding_componentW(RPC_WSTR string_binding
,
362 const WCHAR
*component
)
364 for (; *component
; component
++) {
365 switch (*component
) {
371 *string_binding
++ = '\\';
372 *string_binding
++ = *component
;
375 *string_binding
++ = *component
;
379 return string_binding
;
382 static const unsigned char *string_binding_find_delimiter(
383 const unsigned char *string_binding
, unsigned char delim
)
385 const unsigned char *next
;
386 for (next
= string_binding
; *next
; next
++) {
397 static const WCHAR
*string_binding_find_delimiterW(
398 const WCHAR
*string_binding
, WCHAR delim
)
401 for (next
= string_binding
; *next
; next
++) {
412 static RPC_CSTR
unescape_string_binding_component(
413 const unsigned char *string_binding
, int len
)
415 RPC_CSTR component
, p
;
417 if (len
== -1) len
= strlen((const char *)string_binding
);
419 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
420 if (!component
) return NULL
;
421 for (p
= component
; len
> 0; string_binding
++, len
--) {
422 if (*string_binding
== '\\') {
425 *p
++ = *string_binding
;
427 *p
++ = *string_binding
;
434 static RPC_WSTR
unescape_string_binding_componentW(
435 const WCHAR
*string_binding
, int len
)
437 RPC_WSTR component
, p
;
439 if (len
== -1) len
= strlenW(string_binding
);
441 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
442 if (!component
) return NULL
;
443 for (p
= component
; len
> 0; string_binding
++, len
--) {
444 if (*string_binding
== '\\') {
447 *p
++ = *string_binding
;
449 *p
++ = *string_binding
;
456 /***********************************************************************
457 * RpcStringBindingComposeA (RPCRT4.@)
459 RPC_STATUS WINAPI
RpcStringBindingComposeA(RPC_CSTR ObjUuid
, RPC_CSTR Protseq
,
460 RPC_CSTR NetworkAddr
, RPC_CSTR Endpoint
,
461 RPC_CSTR Options
, RPC_CSTR
*StringBinding
)
466 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
467 debugstr_a( (char*)ObjUuid
), debugstr_a( (char*)Protseq
),
468 debugstr_a( (char*)NetworkAddr
), debugstr_a( (char*)Endpoint
),
469 debugstr_a( (char*)Options
), StringBinding
);
471 /* overestimate for each component for escaping of delimiters */
472 if (ObjUuid
&& *ObjUuid
) len
+= strlen((char*)ObjUuid
) * 2 + 1;
473 if (Protseq
&& *Protseq
) len
+= strlen((char*)Protseq
) * 2 + 1;
474 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen((char*)NetworkAddr
) * 2;
475 if (Endpoint
&& *Endpoint
) len
+= strlen((char*)Endpoint
) * 2 + 2;
476 if (Options
&& *Options
) len
+= strlen((char*)Options
) * 2 + 2;
478 data
= HeapAlloc(GetProcessHeap(), 0, len
);
479 *StringBinding
= data
;
481 if (ObjUuid
&& *ObjUuid
) {
482 data
= escape_string_binding_component(data
, ObjUuid
);
485 if (Protseq
&& *Protseq
) {
486 data
= escape_string_binding_component(data
, Protseq
);
489 if (NetworkAddr
&& *NetworkAddr
)
490 data
= escape_string_binding_component(data
, NetworkAddr
);
492 if ((Endpoint
&& *Endpoint
) ||
493 (Options
&& *Options
)) {
495 if (Endpoint
&& *Endpoint
) {
496 data
= escape_string_binding_component(data
, Endpoint
);
497 if (Options
&& *Options
) *data
++ = ',';
499 if (Options
&& *Options
) {
500 data
= escape_string_binding_component(data
, Options
);
509 /***********************************************************************
510 * RpcStringBindingComposeW (RPCRT4.@)
512 RPC_STATUS WINAPI
RpcStringBindingComposeW( RPC_WSTR ObjUuid
, RPC_WSTR Protseq
,
513 RPC_WSTR NetworkAddr
, RPC_WSTR Endpoint
,
514 RPC_WSTR Options
, RPC_WSTR
* StringBinding
)
519 TRACE("(%s,%s,%s,%s,%s,%p)\n",
520 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
521 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
522 debugstr_w( Options
), StringBinding
);
524 /* overestimate for each component for escaping of delimiters */
525 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) * 2 + 1;
526 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) * 2 + 1;
527 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
) * 2;
528 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) * 2 + 2;
529 if (Options
&& *Options
) len
+= strlenW(Options
) * 2 + 2;
531 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
532 *StringBinding
= data
;
534 if (ObjUuid
&& *ObjUuid
) {
535 data
= escape_string_binding_componentW(data
, ObjUuid
);
538 if (Protseq
&& *Protseq
) {
539 data
= escape_string_binding_componentW(data
, Protseq
);
542 if (NetworkAddr
&& *NetworkAddr
) {
543 data
= escape_string_binding_componentW(data
, NetworkAddr
);
545 if ((Endpoint
&& *Endpoint
) ||
546 (Options
&& *Options
)) {
548 if (Endpoint
&& *Endpoint
) {
549 data
= escape_string_binding_componentW(data
, Endpoint
);
550 if (Options
&& *Options
) *data
++ = ',';
552 if (Options
&& *Options
) {
553 data
= escape_string_binding_componentW(data
, Options
);
563 /***********************************************************************
564 * RpcStringBindingParseA (RPCRT4.@)
566 RPC_STATUS WINAPI
RpcStringBindingParseA( RPC_CSTR StringBinding
, RPC_CSTR
*ObjUuid
,
567 RPC_CSTR
*Protseq
, RPC_CSTR
*NetworkAddr
,
568 RPC_CSTR
*Endpoint
, RPC_CSTR
*Options
)
570 const unsigned char *data
, *next
;
571 static const char ep_opt
[] = "endpoint=";
572 BOOL endpoint_already_found
= FALSE
;
574 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding
),
575 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
577 if (ObjUuid
) *ObjUuid
= NULL
;
578 if (Protseq
) *Protseq
= NULL
;
579 if (NetworkAddr
) *NetworkAddr
= NULL
;
580 if (Endpoint
) *Endpoint
= NULL
;
581 if (Options
) *Options
= NULL
;
583 data
= StringBinding
;
585 next
= string_binding_find_delimiter(data
, '@');
589 RPC_CSTR str_uuid
= unescape_string_binding_component(data
, next
- data
);
590 status
= UuidFromStringA(str_uuid
, &uuid
);
591 if (status
!= RPC_S_OK
) {
592 HeapFree(GetProcessHeap(), 0, str_uuid
);
598 HeapFree(GetProcessHeap(), 0, str_uuid
);
602 next
= string_binding_find_delimiter(data
, ':');
604 if (Protseq
) *Protseq
= unescape_string_binding_component(data
, next
- data
);
608 next
= string_binding_find_delimiter(data
, '[');
610 const unsigned char *close
;
613 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_component(data
, next
- data
);
615 close
= string_binding_find_delimiter(data
, ']');
616 if (!close
) goto fail
;
618 /* tokenize options */
619 while (data
< close
) {
620 next
= string_binding_find_delimiter(data
, ',');
621 if (!next
|| next
> close
) next
= close
;
622 /* FIXME: this is kind of inefficient */
623 opt
= unescape_string_binding_component(data
, next
- data
);
627 next
= string_binding_find_delimiter(opt
, '=');
629 /* not an option, must be an endpoint */
630 if (endpoint_already_found
) goto fail
;
631 if (Endpoint
) *Endpoint
= opt
;
632 else HeapFree(GetProcessHeap(), 0, opt
);
633 endpoint_already_found
= TRUE
;
635 if (strncmp((const char *)opt
, ep_opt
, strlen(ep_opt
)) == 0) {
636 /* endpoint option */
637 if (endpoint_already_found
) goto fail
;
638 if (Endpoint
) *Endpoint
= unescape_string_binding_component(next
+1, -1);
639 HeapFree(GetProcessHeap(), 0, opt
);
640 endpoint_already_found
= TRUE
;
645 /* FIXME: this is kind of inefficient */
646 *Options
= (unsigned char*) RPCRT4_strconcatA( (char*)*Options
, (char *)opt
);
647 HeapFree(GetProcessHeap(), 0, opt
);
651 HeapFree(GetProcessHeap(), 0, opt
);
657 if (*data
) goto fail
;
659 else if (NetworkAddr
)
660 *NetworkAddr
= unescape_string_binding_component(data
, -1);
665 if (ObjUuid
) RpcStringFreeA(ObjUuid
);
666 if (Protseq
) RpcStringFreeA(Protseq
);
667 if (NetworkAddr
) RpcStringFreeA(NetworkAddr
);
668 if (Endpoint
) RpcStringFreeA(Endpoint
);
669 if (Options
) RpcStringFreeA(Options
);
670 return RPC_S_INVALID_STRING_BINDING
;
673 /***********************************************************************
674 * RpcStringBindingParseW (RPCRT4.@)
676 RPC_STATUS WINAPI
RpcStringBindingParseW( RPC_WSTR StringBinding
, RPC_WSTR
*ObjUuid
,
677 RPC_WSTR
*Protseq
, RPC_WSTR
*NetworkAddr
,
678 RPC_WSTR
*Endpoint
, RPC_WSTR
*Options
)
680 const WCHAR
*data
, *next
;
681 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
682 BOOL endpoint_already_found
= FALSE
;
684 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
685 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
687 if (ObjUuid
) *ObjUuid
= NULL
;
688 if (Protseq
) *Protseq
= NULL
;
689 if (NetworkAddr
) *NetworkAddr
= NULL
;
690 if (Endpoint
) *Endpoint
= NULL
;
691 if (Options
) *Options
= NULL
;
693 data
= StringBinding
;
695 next
= string_binding_find_delimiterW(data
, '@');
699 RPC_WSTR str_uuid
= unescape_string_binding_componentW(data
, next
- data
);
700 status
= UuidFromStringW(str_uuid
, &uuid
);
701 if (status
!= RPC_S_OK
) {
702 HeapFree(GetProcessHeap(), 0, str_uuid
);
708 HeapFree(GetProcessHeap(), 0, str_uuid
);
712 next
= string_binding_find_delimiterW(data
, ':');
714 if (Protseq
) *Protseq
= unescape_string_binding_componentW(data
, next
- data
);
718 next
= string_binding_find_delimiterW(data
, '[');
723 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_componentW(data
, next
- data
);
725 close
= string_binding_find_delimiterW(data
, ']');
726 if (!close
) goto fail
;
728 /* tokenize options */
729 while (data
< close
) {
730 next
= string_binding_find_delimiterW(data
, ',');
731 if (!next
|| next
> close
) next
= close
;
732 /* FIXME: this is kind of inefficient */
733 opt
= unescape_string_binding_componentW(data
, next
- data
);
737 next
= string_binding_find_delimiterW(opt
, '=');
739 /* not an option, must be an endpoint */
740 if (endpoint_already_found
) goto fail
;
741 if (Endpoint
) *Endpoint
= opt
;
742 else HeapFree(GetProcessHeap(), 0, opt
);
743 endpoint_already_found
= TRUE
;
745 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
746 /* endpoint option */
747 if (endpoint_already_found
) goto fail
;
748 if (Endpoint
) *Endpoint
= unescape_string_binding_componentW(next
+1, -1);
749 HeapFree(GetProcessHeap(), 0, opt
);
750 endpoint_already_found
= TRUE
;
755 /* FIXME: this is kind of inefficient */
756 *Options
= RPCRT4_strconcatW(*Options
, opt
);
757 HeapFree(GetProcessHeap(), 0, opt
);
761 HeapFree(GetProcessHeap(), 0, opt
);
767 if (*data
) goto fail
;
768 } else if (NetworkAddr
)
769 *NetworkAddr
= unescape_string_binding_componentW(data
, -1);
774 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
775 if (Protseq
) RpcStringFreeW(Protseq
);
776 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
777 if (Endpoint
) RpcStringFreeW(Endpoint
);
778 if (Options
) RpcStringFreeW(Options
);
779 return RPC_S_INVALID_STRING_BINDING
;
782 /***********************************************************************
783 * RpcBindingFree (RPCRT4.@)
785 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
788 TRACE("(%p) = %p\n", Binding
, *Binding
);
790 status
= RPCRT4_ReleaseBinding(*Binding
);
792 status
= RPC_S_INVALID_BINDING
;
793 if (status
== RPC_S_OK
) *Binding
= NULL
;
797 /***********************************************************************
798 * RpcBindingVectorFree (RPCRT4.@)
800 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
804 TRACE("(%p)\n", BindingVector
);
805 for (c
=0; c
<(*BindingVector
)->Count
; c
++) RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
806 HeapFree(GetProcessHeap(), 0, *BindingVector
);
807 *BindingVector
= NULL
;
811 /***********************************************************************
812 * RpcBindingInqObject (RPCRT4.@)
814 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
816 RpcBinding
* bind
= Binding
;
818 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
819 *ObjectUuid
= bind
->ObjectUuid
;
823 /***********************************************************************
824 * RpcBindingSetObject (RPCRT4.@)
826 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
828 RpcBinding
* bind
= Binding
;
830 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
831 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
832 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
835 /***********************************************************************
836 * RpcBindingFromStringBindingA (RPCRT4.@)
838 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( RPC_CSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
841 RpcBinding
* bind
= NULL
;
842 RPC_CSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
845 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
847 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
848 &NetworkAddr
, &Endpoint
, &Options
);
849 if (ret
!= RPC_S_OK
) return ret
;
851 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
854 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
855 if (ret
== RPC_S_OK
) {
856 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
858 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
861 *Binding
= (RPC_BINDING_HANDLE
)bind
;
863 RPCRT4_ReleaseBinding(bind
);
866 RpcStringFreeA(&Options
);
867 RpcStringFreeA(&Endpoint
);
868 RpcStringFreeA(&NetworkAddr
);
869 RpcStringFreeA(&Protseq
);
870 RpcStringFreeA(&ObjectUuid
);
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
) {
896 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
898 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
901 *Binding
= (RPC_BINDING_HANDLE
)bind
;
903 RPCRT4_ReleaseBinding(bind
);
906 RpcStringFreeW(&Options
);
907 RpcStringFreeW(&Endpoint
);
908 RpcStringFreeW(&NetworkAddr
);
909 RpcStringFreeW(&Protseq
);
910 RpcStringFreeW(&ObjectUuid
);
915 /***********************************************************************
916 * RpcBindingToStringBindingA (RPCRT4.@)
918 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*StringBinding
)
921 RpcBinding
* bind
= Binding
;
924 TRACE("(%p,%p)\n", Binding
, StringBinding
);
926 if (UuidIsNil(&bind
->ObjectUuid
, &ret
))
930 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
931 if (ret
!= RPC_S_OK
) return ret
;
934 ret
= RpcStringBindingComposeA(ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
935 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
937 RpcStringFreeA(&ObjectUuid
);
942 /***********************************************************************
943 * RpcBindingToStringBindingW (RPCRT4.@)
945 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*StringBinding
)
948 unsigned char *str
= NULL
;
949 TRACE("(%p,%p)\n", Binding
, StringBinding
);
950 ret
= RpcBindingToStringBindingA(Binding
, &str
);
951 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
952 RpcStringFreeA(&str
);
956 /***********************************************************************
957 * I_RpcBindingInqTransportType (RPCRT4.@)
959 RPC_STATUS WINAPI
I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding
, unsigned int * Type
)
962 FIXME( "(%p,%p): stub\n", Binding
, Type
);
963 *Type
= TRANSPORT_TYPE_LPC
;
967 /***********************************************************************
968 * I_RpcBindingSetAsync (RPCRT4.@)
970 * Exists in win9x and winNT, but with different number of arguments
971 * (9x version has 3 arguments, NT has 2).
973 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
975 RpcBinding
* bind
= Binding
;
977 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
979 bind
->BlockingFn
= BlockingFn
;
984 /***********************************************************************
985 * RpcBindingCopy (RPCRT4.@)
987 RPC_STATUS RPC_ENTRY
RpcBindingCopy(
988 RPC_BINDING_HANDLE SourceBinding
,
989 RPC_BINDING_HANDLE
* DestinationBinding
)
991 RpcBinding
*DestBinding
;
992 RpcBinding
*SrcBinding
= SourceBinding
;
995 TRACE("(%p, %p)\n", SourceBinding
, DestinationBinding
);
997 status
= RPCRT4_AllocBinding(&DestBinding
, SrcBinding
->server
);
998 if (status
!= RPC_S_OK
) return status
;
1000 DestBinding
->ObjectUuid
= SrcBinding
->ObjectUuid
;
1001 DestBinding
->BlockingFn
= SrcBinding
->BlockingFn
;
1002 DestBinding
->Protseq
= RPCRT4_strndupA(SrcBinding
->Protseq
, -1);
1003 DestBinding
->NetworkAddr
= RPCRT4_strndupA(SrcBinding
->NetworkAddr
, -1);
1004 DestBinding
->Endpoint
= RPCRT4_strndupA(SrcBinding
->Endpoint
, -1);
1005 DestBinding
->NetworkOptions
= RPCRT4_strdupW(SrcBinding
->NetworkOptions
);
1006 DestBinding
->CookieAuth
= RPCRT4_strdupW(SrcBinding
->CookieAuth
);
1007 if (SrcBinding
->Assoc
) SrcBinding
->Assoc
->refs
++;
1008 DestBinding
->Assoc
= SrcBinding
->Assoc
;
1010 if (SrcBinding
->AuthInfo
) RpcAuthInfo_AddRef(SrcBinding
->AuthInfo
);
1011 DestBinding
->AuthInfo
= SrcBinding
->AuthInfo
;
1012 if (SrcBinding
->QOS
) RpcQualityOfService_AddRef(SrcBinding
->QOS
);
1013 DestBinding
->QOS
= SrcBinding
->QOS
;
1015 *DestinationBinding
= DestBinding
;
1019 /***********************************************************************
1020 * RpcBindingReset (RPCRT4.@)
1022 RPC_STATUS RPC_ENTRY
RpcBindingReset(RPC_BINDING_HANDLE Binding
)
1024 RpcBinding
*bind
= Binding
;
1026 TRACE("(%p)\n", Binding
);
1028 RPCRT4_strfree(bind
->Endpoint
);
1029 bind
->Endpoint
= NULL
;
1030 if (bind
->Assoc
) RpcAssoc_Release(bind
->Assoc
);
1036 /***********************************************************************
1037 * RpcImpersonateClient (RPCRT4.@)
1039 * Impersonates the client connected via a binding handle so that security
1040 * checks are done in the context of the client.
1043 * BindingHandle [I] Handle to the binding to the client.
1046 * Success: RPS_S_OK.
1047 * Failure: RPC_STATUS value.
1051 * If BindingHandle is NULL then the function impersonates the client
1052 * connected to the binding handle of the current thread.
1054 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
1058 TRACE("(%p)\n", BindingHandle
);
1060 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1061 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1063 bind
= BindingHandle
;
1065 return rpcrt4_conn_impersonate_client(bind
->FromConn
);
1066 return RPC_S_WRONG_KIND_OF_BINDING
;
1069 /***********************************************************************
1070 * RpcRevertToSelfEx (RPCRT4.@)
1072 * Stops impersonating the client connected to the binding handle so that security
1073 * checks are no longer done in the context of the client.
1076 * BindingHandle [I] Handle to the binding to the client.
1079 * Success: RPS_S_OK.
1080 * Failure: RPC_STATUS value.
1084 * If BindingHandle is NULL then the function stops impersonating the client
1085 * connected to the binding handle of the current thread.
1087 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
1091 TRACE("(%p)\n", BindingHandle
);
1093 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1094 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1096 bind
= BindingHandle
;
1098 return rpcrt4_conn_revert_to_self(bind
->FromConn
);
1099 return RPC_S_WRONG_KIND_OF_BINDING
;
1102 static inline BOOL
has_nt_auth_identity(ULONG AuthnLevel
)
1106 case RPC_C_AUTHN_GSS_NEGOTIATE
:
1107 case RPC_C_AUTHN_WINNT
:
1108 case RPC_C_AUTHN_GSS_KERBEROS
:
1115 RPC_STATUS
RpcAuthInfo_Create(ULONG AuthnLevel
, ULONG AuthnSvc
,
1116 CredHandle cred
, TimeStamp exp
,
1118 RPC_AUTH_IDENTITY_HANDLE identity
,
1121 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
1123 return ERROR_OUTOFMEMORY
;
1126 AuthInfo
->AuthnLevel
= AuthnLevel
;
1127 AuthInfo
->AuthnSvc
= AuthnSvc
;
1128 AuthInfo
->cred
= cred
;
1129 AuthInfo
->exp
= exp
;
1130 AuthInfo
->cbMaxToken
= cbMaxToken
;
1131 AuthInfo
->identity
= identity
;
1132 AuthInfo
->server_principal_name
= NULL
;
1134 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1135 * enable better matching in RpcAuthInfo_IsEqual */
1136 if (identity
&& has_nt_auth_identity(AuthnSvc
))
1138 const SEC_WINNT_AUTH_IDENTITY_W
*nt_identity
= identity
;
1139 AuthInfo
->nt_identity
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
->nt_identity
));
1140 if (!AuthInfo
->nt_identity
)
1142 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1143 return ERROR_OUTOFMEMORY
;
1146 AuthInfo
->nt_identity
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1147 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1148 AuthInfo
->nt_identity
->User
= RPCRT4_strndupW(nt_identity
->User
, nt_identity
->UserLength
);
1150 AuthInfo
->nt_identity
->User
= RPCRT4_strndupAtoW((const char *)nt_identity
->User
, nt_identity
->UserLength
);
1151 AuthInfo
->nt_identity
->UserLength
= nt_identity
->UserLength
;
1152 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1153 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupW(nt_identity
->Domain
, nt_identity
->DomainLength
);
1155 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupAtoW((const char *)nt_identity
->Domain
, nt_identity
->DomainLength
);
1156 AuthInfo
->nt_identity
->DomainLength
= nt_identity
->DomainLength
;
1157 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1158 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupW(nt_identity
->Password
, nt_identity
->PasswordLength
);
1160 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupAtoW((const char *)nt_identity
->Password
, nt_identity
->PasswordLength
);
1161 AuthInfo
->nt_identity
->PasswordLength
= nt_identity
->PasswordLength
;
1163 if ((nt_identity
->User
&& !AuthInfo
->nt_identity
->User
) ||
1164 (nt_identity
->Domain
&& !AuthInfo
->nt_identity
->Domain
) ||
1165 (nt_identity
->Password
&& !AuthInfo
->nt_identity
->Password
))
1167 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1168 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1169 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1170 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1171 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1172 return ERROR_OUTOFMEMORY
;
1176 AuthInfo
->nt_identity
= NULL
;
1181 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
1183 return InterlockedIncrement(&AuthInfo
->refs
);
1186 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
1188 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
1192 FreeCredentialsHandle(&AuthInfo
->cred
);
1193 if (AuthInfo
->nt_identity
)
1195 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1196 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1197 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1198 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1200 HeapFree(GetProcessHeap(), 0, AuthInfo
->server_principal_name
);
1201 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1207 BOOL
RpcAuthInfo_IsEqual(const RpcAuthInfo
*AuthInfo1
, const RpcAuthInfo
*AuthInfo2
)
1209 if (AuthInfo1
== AuthInfo2
)
1212 if (!AuthInfo1
|| !AuthInfo2
)
1215 if ((AuthInfo1
->AuthnLevel
!= AuthInfo2
->AuthnLevel
) ||
1216 (AuthInfo1
->AuthnSvc
!= AuthInfo2
->AuthnSvc
))
1219 if (AuthInfo1
->identity
== AuthInfo2
->identity
)
1222 if (!AuthInfo1
->identity
|| !AuthInfo2
->identity
)
1225 if (has_nt_auth_identity(AuthInfo1
->AuthnSvc
))
1227 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= AuthInfo1
->nt_identity
;
1228 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= AuthInfo2
->nt_identity
;
1229 /* compare user names */
1230 if (identity1
->UserLength
!= identity2
->UserLength
||
1231 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1233 /* compare domain names */
1234 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1235 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1237 /* compare passwords */
1238 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1239 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1248 static RPC_STATUS
RpcQualityOfService_Create(const RPC_SECURITY_QOS
*qos_src
, BOOL unicode
, RpcQualityOfService
**qos_dst
)
1250 RpcQualityOfService
*qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
));
1253 return RPC_S_OUT_OF_RESOURCES
;
1256 qos
->qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
->qos
));
1257 if (!qos
->qos
) goto error
;
1258 qos
->qos
->Version
= qos_src
->Version
;
1259 qos
->qos
->Capabilities
= qos_src
->Capabilities
;
1260 qos
->qos
->IdentityTracking
= qos_src
->IdentityTracking
;
1261 qos
->qos
->ImpersonationType
= qos_src
->ImpersonationType
;
1262 qos
->qos
->AdditionalSecurityInfoType
= 0;
1264 if (qos_src
->Version
>= 2)
1266 const RPC_SECURITY_QOS_V2_W
*qos_src2
= (const RPC_SECURITY_QOS_V2_W
*)qos_src
;
1267 qos
->qos
->AdditionalSecurityInfoType
= qos_src2
->AdditionalSecurityInfoType
;
1268 if (qos_src2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1270 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_src
= qos_src2
->u
.HttpCredentials
;
1271 RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_dst
;
1273 http_credentials_dst
= HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst
));
1274 qos
->qos
->u
.HttpCredentials
= http_credentials_dst
;
1275 if (!http_credentials_dst
) goto error
;
1276 http_credentials_dst
->TransportCredentials
= NULL
;
1277 http_credentials_dst
->Flags
= http_credentials_src
->Flags
;
1278 http_credentials_dst
->AuthenticationTarget
= http_credentials_src
->AuthenticationTarget
;
1279 http_credentials_dst
->NumberOfAuthnSchemes
= http_credentials_src
->NumberOfAuthnSchemes
;
1280 http_credentials_dst
->AuthnSchemes
= NULL
;
1281 http_credentials_dst
->ServerCertificateSubject
= NULL
;
1282 if (http_credentials_src
->TransportCredentials
)
1284 SEC_WINNT_AUTH_IDENTITY_W
*cred_dst
;
1285 cred_dst
= http_credentials_dst
->TransportCredentials
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cred_dst
));
1286 if (!cred_dst
) goto error
;
1287 cred_dst
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1290 const SEC_WINNT_AUTH_IDENTITY_W
*cred_src
= http_credentials_src
->TransportCredentials
;
1291 cred_dst
->UserLength
= cred_src
->UserLength
;
1292 cred_dst
->PasswordLength
= cred_src
->PasswordLength
;
1293 cred_dst
->DomainLength
= cred_src
->DomainLength
;
1294 cred_dst
->User
= RPCRT4_strndupW(cred_src
->User
, cred_src
->UserLength
);
1295 cred_dst
->Password
= RPCRT4_strndupW(cred_src
->Password
, cred_src
->PasswordLength
);
1296 cred_dst
->Domain
= RPCRT4_strndupW(cred_src
->Domain
, cred_src
->DomainLength
);
1300 const SEC_WINNT_AUTH_IDENTITY_A
*cred_src
= (const SEC_WINNT_AUTH_IDENTITY_A
*)http_credentials_src
->TransportCredentials
;
1301 cred_dst
->UserLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, NULL
, 0);
1302 cred_dst
->DomainLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, NULL
, 0);
1303 cred_dst
->PasswordLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, NULL
, 0);
1304 cred_dst
->User
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->UserLength
* sizeof(WCHAR
));
1305 cred_dst
->Password
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->PasswordLength
* sizeof(WCHAR
));
1306 cred_dst
->Domain
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->DomainLength
* sizeof(WCHAR
));
1307 if (!cred_dst
->Password
|| !cred_dst
->Domain
) goto error
;
1308 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, cred_dst
->User
, cred_dst
->UserLength
);
1309 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, cred_dst
->Domain
, cred_dst
->DomainLength
);
1310 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, cred_dst
->Password
, cred_dst
->PasswordLength
);
1313 if (http_credentials_src
->NumberOfAuthnSchemes
)
1315 http_credentials_dst
->AuthnSchemes
= HeapAlloc(GetProcessHeap(), 0, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1316 if (!http_credentials_dst
->AuthnSchemes
) goto error
;
1317 memcpy(http_credentials_dst
->AuthnSchemes
, http_credentials_src
->AuthnSchemes
, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1319 if (http_credentials_src
->ServerCertificateSubject
)
1322 http_credentials_dst
->ServerCertificateSubject
=
1323 RPCRT4_strndupW(http_credentials_src
->ServerCertificateSubject
,
1324 strlenW(http_credentials_src
->ServerCertificateSubject
));
1326 http_credentials_dst
->ServerCertificateSubject
=
1327 RPCRT4_strdupAtoW((char *)http_credentials_src
->ServerCertificateSubject
);
1328 if (!http_credentials_dst
->ServerCertificateSubject
) goto error
;
1338 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
&&
1339 qos
->qos
->u
.HttpCredentials
)
1341 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1343 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1344 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1345 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1346 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1348 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1349 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1350 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1352 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1354 HeapFree(GetProcessHeap(), 0, qos
);
1355 return RPC_S_OUT_OF_RESOURCES
;
1358 ULONG
RpcQualityOfService_AddRef(RpcQualityOfService
*qos
)
1360 return InterlockedIncrement(&qos
->refs
);
1363 ULONG
RpcQualityOfService_Release(RpcQualityOfService
*qos
)
1365 ULONG refs
= InterlockedDecrement(&qos
->refs
);
1369 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1371 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1373 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1374 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1375 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1376 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1378 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1379 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1380 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1382 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1383 HeapFree(GetProcessHeap(), 0, qos
);
1388 BOOL
RpcQualityOfService_IsEqual(const RpcQualityOfService
*qos1
, const RpcQualityOfService
*qos2
)
1396 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
1397 qos1
->qos
->Capabilities
, qos1
->qos
->IdentityTracking
,
1398 qos1
->qos
->ImpersonationType
, qos1
->qos
->AdditionalSecurityInfoType
,
1399 qos2
->qos
->Capabilities
, qos2
->qos
->IdentityTracking
,
1400 qos2
->qos
->ImpersonationType
, qos2
->qos
->AdditionalSecurityInfoType
);
1402 if ((qos1
->qos
->Capabilities
!= qos2
->qos
->Capabilities
) ||
1403 (qos1
->qos
->IdentityTracking
!= qos2
->qos
->IdentityTracking
) ||
1404 (qos1
->qos
->ImpersonationType
!= qos2
->qos
->ImpersonationType
) ||
1405 (qos1
->qos
->AdditionalSecurityInfoType
!= qos2
->qos
->AdditionalSecurityInfoType
))
1408 if (qos1
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1410 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials1
= qos1
->qos
->u
.HttpCredentials
;
1411 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials2
= qos2
->qos
->u
.HttpCredentials
;
1413 if (http_credentials1
->Flags
!= http_credentials2
->Flags
)
1416 if (http_credentials1
->AuthenticationTarget
!= http_credentials2
->AuthenticationTarget
)
1419 if (http_credentials1
->NumberOfAuthnSchemes
!= http_credentials2
->NumberOfAuthnSchemes
)
1422 if ((!http_credentials1
->AuthnSchemes
&& http_credentials2
->AuthnSchemes
) ||
1423 (http_credentials1
->AuthnSchemes
&& !http_credentials2
->AuthnSchemes
))
1426 if (memcmp(http_credentials1
->AuthnSchemes
, http_credentials2
->AuthnSchemes
,
1427 http_credentials1
->NumberOfAuthnSchemes
* sizeof(http_credentials1
->AuthnSchemes
[0])))
1430 /* server certificate subject not currently used */
1432 if (http_credentials1
->TransportCredentials
!= http_credentials2
->TransportCredentials
)
1434 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= http_credentials1
->TransportCredentials
;
1435 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= http_credentials2
->TransportCredentials
;
1437 if (!identity1
|| !identity2
)
1440 /* compare user names */
1441 if (identity1
->UserLength
!= identity2
->UserLength
||
1442 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1444 /* compare domain names */
1445 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1446 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1448 /* compare passwords */
1449 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1450 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1458 /***********************************************************************
1459 * RpcRevertToSelf (RPCRT4.@)
1461 RPC_STATUS WINAPI
RpcRevertToSelf(void)
1464 return RpcRevertToSelfEx(NULL
);
1467 /***********************************************************************
1468 * RpcMgmtSetComTimeout (RPCRT4.@)
1470 RPC_STATUS WINAPI
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle
, unsigned int Timeout
)
1472 FIXME("(%p, %d): stub\n", BindingHandle
, Timeout
);
1476 /***********************************************************************
1477 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1479 RPCRTAPI RPC_STATUS RPC_ENTRY
1480 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1481 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1482 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1487 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1488 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1490 status
= RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
? &principal
: NULL
, AuthnLevel
,
1491 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1492 if (status
== RPC_S_OK
&& ServerPrincName
)
1494 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1495 RpcStringFreeW(&principal
);
1496 if (!*ServerPrincName
) return ERROR_OUTOFMEMORY
;
1502 /***********************************************************************
1503 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1505 RPCRTAPI RPC_STATUS RPC_ENTRY
1506 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1507 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1508 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1510 RpcBinding
*bind
= Binding
;
1512 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1513 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1515 if (!bind
->AuthInfo
) return RPC_S_BINDING_HAS_NO_AUTH
;
1519 FIXME("QOS not implemented\n");
1520 return RPC_S_INVALID_BINDING
;
1523 if (ServerPrincName
)
1525 if (bind
->AuthInfo
->server_principal_name
)
1527 *ServerPrincName
= RPCRT4_strdupW(bind
->AuthInfo
->server_principal_name
);
1528 if (!*ServerPrincName
) return ERROR_OUTOFMEMORY
;
1530 else *ServerPrincName
= NULL
;
1532 if (AuthnLevel
) *AuthnLevel
= bind
->AuthInfo
->AuthnLevel
;
1533 if (AuthnSvc
) *AuthnSvc
= bind
->AuthInfo
->AuthnSvc
;
1534 if (AuthIdentity
) *AuthIdentity
= bind
->AuthInfo
->identity
;
1537 FIXME("authorization service not implemented\n");
1538 *AuthzSvc
= RPC_C_AUTHZ_NONE
;
1544 /***********************************************************************
1545 * RpcBindingInqAuthInfoA (RPCRT4.@)
1547 RPCRTAPI RPC_STATUS RPC_ENTRY
1548 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1549 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1551 return RpcBindingInqAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1555 /***********************************************************************
1556 * RpcBindingInqAuthInfoW (RPCRT4.@)
1558 RPCRTAPI RPC_STATUS RPC_ENTRY
1559 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1560 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1562 return RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1566 /***********************************************************************
1567 * RpcBindingInqAuthClientA (RPCRT4.@)
1569 RPCRTAPI RPC_STATUS RPC_ENTRY
1570 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1571 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1574 return RpcBindingInqAuthClientExA(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1575 AuthnSvc
, AuthzSvc
, 0);
1578 /***********************************************************************
1579 * RpcBindingInqAuthClientW (RPCRT4.@)
1581 RPCRTAPI RPC_STATUS RPC_ENTRY
1582 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1583 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1586 return RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1587 AuthnSvc
, AuthzSvc
, 0);
1590 /***********************************************************************
1591 * RpcBindingInqAuthClientExA (RPCRT4.@)
1593 RPCRTAPI RPC_STATUS RPC_ENTRY
1594 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1595 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1596 ULONG
*AuthzSvc
, ULONG Flags
)
1601 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1602 AuthnSvc
, AuthzSvc
, Flags
);
1604 status
= RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
? &principal
: NULL
,
1605 AuthnLevel
, AuthnSvc
, AuthzSvc
, Flags
);
1606 if (status
== RPC_S_OK
&& ServerPrincName
)
1608 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1609 if (!*ServerPrincName
&& principal
) status
= ERROR_OUTOFMEMORY
;
1610 RpcStringFreeW(&principal
);
1616 /***********************************************************************
1617 * RpcBindingInqAuthClientExW (RPCRT4.@)
1619 RPCRTAPI RPC_STATUS RPC_ENTRY
1620 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1621 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1622 ULONG
*AuthzSvc
, ULONG Flags
)
1624 RpcBinding
*bind
= ClientBinding
;
1626 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1627 AuthnSvc
, AuthzSvc
, Flags
);
1629 if (!bind
->FromConn
) return RPC_S_INVALID_BINDING
;
1631 return rpcrt4_conn_inquire_auth_client(bind
->FromConn
, Privs
,
1632 ServerPrincName
, AuthnLevel
,
1633 AuthnSvc
, AuthzSvc
, Flags
);
1636 /***********************************************************************
1637 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1639 RPCRTAPI RPC_STATUS RPC_ENTRY
1640 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
,
1641 ULONG AuthnLevel
, ULONG AuthnSvc
,
1642 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1643 RPC_SECURITY_QOS
*SecurityQos
)
1645 RpcBinding
* bind
= Binding
;
1649 ULONG package_count
;
1651 PSecPkgInfoA packages
;
1654 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1655 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1661 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1662 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1663 if (SecurityQos
->Version
>= 2)
1665 const RPC_SECURITY_QOS_V2_A
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_A
*)SecurityQos
;
1666 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1667 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1668 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1669 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1670 SecurityQos2
->u
.HttpCredentials
->Flags
,
1671 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1672 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1673 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1674 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1675 SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
);
1678 status
= RpcQualityOfService_Create(SecurityQos
, FALSE
, &bind
->QOS
);
1679 if (status
!= RPC_S_OK
)
1684 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1688 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1689 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1691 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1692 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1693 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1695 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1697 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1698 bind
->AuthInfo
= NULL
;
1702 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1704 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1705 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1708 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1709 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1711 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1712 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1715 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1718 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1719 return RPC_S_SEC_PKG_ERROR
;
1722 for (i
= 0; i
< package_count
; i
++)
1723 if (packages
[i
].wRPCID
== AuthnSvc
)
1726 if (i
== package_count
)
1728 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1729 FreeContextBuffer(packages
);
1730 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1733 TRACE("found package %s for service %u\n", packages
[i
].Name
, AuthnSvc
);
1734 r
= AcquireCredentialsHandleA(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1735 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1736 cbMaxToken
= packages
[i
].cbMaxToken
;
1737 FreeContextBuffer(packages
);
1738 if (r
== ERROR_SUCCESS
)
1740 RpcAuthInfo
*new_auth_info
;
1741 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1742 AuthIdentity
, &new_auth_info
);
1745 new_auth_info
->server_principal_name
= RPCRT4_strdupAtoW((char *)ServerPrincName
);
1746 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1748 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1749 bind
->AuthInfo
= new_auth_info
;
1753 RpcAuthInfo_Release(new_auth_info
);
1754 r
= ERROR_OUTOFMEMORY
;
1758 FreeCredentialsHandle(&cred
);
1763 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1764 return RPC_S_SEC_PKG_ERROR
;
1768 /***********************************************************************
1769 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1771 RPCRTAPI RPC_STATUS RPC_ENTRY
1772 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1773 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1774 RPC_SECURITY_QOS
*SecurityQos
)
1776 RpcBinding
* bind
= Binding
;
1780 ULONG package_count
;
1782 PSecPkgInfoW packages
;
1785 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_w(ServerPrincName
),
1786 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1792 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1793 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1794 if (SecurityQos
->Version
>= 2)
1796 const RPC_SECURITY_QOS_V2_W
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_W
*)SecurityQos
;
1797 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1798 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1799 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1800 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1801 SecurityQos2
->u
.HttpCredentials
->Flags
,
1802 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1803 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1804 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1805 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1806 debugstr_w(SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
));
1809 status
= RpcQualityOfService_Create(SecurityQos
, TRUE
, &bind
->QOS
);
1810 if (status
!= RPC_S_OK
)
1815 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1819 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1820 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1822 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1823 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1824 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1826 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1828 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1829 bind
->AuthInfo
= NULL
;
1833 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1835 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1836 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1839 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1840 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1842 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1843 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1846 r
= EnumerateSecurityPackagesW(&package_count
, &packages
);
1849 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r
);
1850 return RPC_S_SEC_PKG_ERROR
;
1853 for (i
= 0; i
< package_count
; i
++)
1854 if (packages
[i
].wRPCID
== AuthnSvc
)
1857 if (i
== package_count
)
1859 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1860 FreeContextBuffer(packages
);
1861 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1864 TRACE("found package %s for service %u\n", debugstr_w(packages
[i
].Name
), AuthnSvc
);
1865 r
= AcquireCredentialsHandleW(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1866 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1867 cbMaxToken
= packages
[i
].cbMaxToken
;
1868 FreeContextBuffer(packages
);
1869 if (r
== ERROR_SUCCESS
)
1871 RpcAuthInfo
*new_auth_info
;
1872 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1873 AuthIdentity
, &new_auth_info
);
1876 new_auth_info
->server_principal_name
= RPCRT4_strdupW(ServerPrincName
);
1877 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1879 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1880 bind
->AuthInfo
= new_auth_info
;
1884 RpcAuthInfo_Release(new_auth_info
);
1885 r
= ERROR_OUTOFMEMORY
;
1889 FreeCredentialsHandle(&cred
);
1894 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r
);
1895 return RPC_S_SEC_PKG_ERROR
;
1899 /***********************************************************************
1900 * RpcBindingSetAuthInfoA (RPCRT4.@)
1902 RPCRTAPI RPC_STATUS RPC_ENTRY
1903 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
, ULONG AuthnLevel
,
1904 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1906 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1907 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1908 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1911 /***********************************************************************
1912 * RpcBindingSetAuthInfoW (RPCRT4.@)
1914 RPCRTAPI RPC_STATUS RPC_ENTRY
1915 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1916 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1918 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_w(ServerPrincName
),
1919 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1920 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1923 /***********************************************************************
1924 * RpcBindingSetOption (RPCRT4.@)
1926 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG_PTR OptionValue
)
1928 TRACE("(%p, %d, %ld)\n", BindingHandle
, Option
, OptionValue
);
1932 case RPC_C_OPT_COOKIE_AUTH
:
1934 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*cookie
= (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*)OptionValue
;
1935 RpcBinding
*binding
= BindingHandle
;
1936 int len
= MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, NULL
, 0);
1939 if (!(str
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
)))) return ERROR_OUTOFMEMORY
;
1940 MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, str
, len
);
1942 HeapFree(GetProcessHeap(), 0, binding
->CookieAuth
);
1943 binding
->CookieAuth
= str
;
1947 FIXME("option %u not supported\n", Option
);