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
38 #include "wine/debug.h"
40 #include "rpc_binding.h"
41 #include "rpc_assoc.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(rpc
);
45 LPSTR
RPCRT4_strndupA(LPCSTR src
, INT slen
)
49 if (!src
) return NULL
;
50 if (slen
== -1) slen
= strlen(src
);
52 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
58 LPSTR
RPCRT4_strdupWtoA(LPCWSTR src
)
62 if (!src
) return NULL
;
63 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
64 s
= HeapAlloc(GetProcessHeap(), 0, len
);
65 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
69 LPWSTR
RPCRT4_strdupAtoW(LPCSTR src
)
73 if (!src
) return NULL
;
74 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
75 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
76 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
80 static LPWSTR
RPCRT4_strndupAtoW(LPCSTR src
, INT slen
)
84 if (!src
) return NULL
;
85 len
= MultiByteToWideChar(CP_ACP
, 0, src
, slen
, NULL
, 0);
86 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
87 MultiByteToWideChar(CP_ACP
, 0, src
, slen
, s
, len
);
91 LPWSTR
RPCRT4_strndupW(LPCWSTR src
, INT slen
)
95 if (!src
) return NULL
;
96 if (slen
== -1) slen
= lstrlenW(src
);
98 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
99 memcpy(s
, src
, len
*sizeof(WCHAR
));
104 void RPCRT4_strfree(LPSTR src
)
106 HeapFree(GetProcessHeap(), 0, src
);
109 static RPC_STATUS
RPCRT4_AllocBinding(RpcBinding
** Binding
, BOOL server
)
111 RpcBinding
* NewBinding
;
113 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
114 NewBinding
->refs
= 1;
115 NewBinding
->server
= server
;
117 *Binding
= NewBinding
;
122 static RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPCSTR Protseq
)
124 RpcBinding
* NewBinding
;
126 RPCRT4_AllocBinding(&NewBinding
, server
);
127 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
129 TRACE("binding: %p\n", NewBinding
);
130 *Binding
= NewBinding
;
135 static RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPCWSTR Protseq
)
137 RpcBinding
* NewBinding
;
139 RPCRT4_AllocBinding(&NewBinding
, server
);
140 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
142 TRACE("binding: %p\n", NewBinding
);
143 *Binding
= NewBinding
;
148 static RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPCSTR NetworkAddr
,
149 LPCSTR Endpoint
, LPCSTR NetworkOptions
)
153 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding
,
154 debugstr_a(NetworkAddr
), debugstr_a(Endpoint
), debugstr_a(NetworkOptions
));
156 RPCRT4_strfree(Binding
->NetworkAddr
);
157 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
158 RPCRT4_strfree(Binding
->Endpoint
);
159 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
160 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
161 Binding
->NetworkOptions
= RPCRT4_strdupAtoW(NetworkOptions
);
163 /* only attempt to get an association if the binding is complete */
164 if (Endpoint
&& Endpoint
[0] != '\0')
166 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
167 Binding
->Endpoint
, Binding
->NetworkOptions
,
169 if (status
!= RPC_S_OK
)
176 static RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPCWSTR NetworkAddr
,
177 LPCWSTR Endpoint
, LPCWSTR NetworkOptions
)
181 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding
,
182 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
184 RPCRT4_strfree(Binding
->NetworkAddr
);
185 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
186 RPCRT4_strfree(Binding
->Endpoint
);
187 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
188 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
189 Binding
->NetworkOptions
= RPCRT4_strdupW(NetworkOptions
);
191 /* only attempt to get an association if the binding is complete */
192 if (Endpoint
&& Endpoint
[0] != '\0')
194 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
195 Binding
->Endpoint
, Binding
->NetworkOptions
,
197 if (status
!= RPC_S_OK
)
204 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPCSTR Endpoint
)
208 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
210 RPCRT4_strfree(Binding
->Endpoint
);
211 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
213 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
214 Binding
->Assoc
= NULL
;
215 status
= RPCRT4_GetAssociation(Binding
->Protseq
, Binding
->NetworkAddr
,
216 Binding
->Endpoint
, Binding
->NetworkOptions
,
218 if (status
!= RPC_S_OK
)
224 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, const UUID
* ObjectUuid
)
226 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
227 if (ObjectUuid
) Binding
->ObjectUuid
= *ObjectUuid
;
228 else UuidCreateNil(&Binding
->ObjectUuid
);
232 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
234 RpcBinding
* NewBinding
;
235 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding
, Connection
);
237 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
238 NewBinding
->Protseq
= RPCRT4_strdupA(rpcrt4_conn_get_name(Connection
));
239 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
240 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
241 NewBinding
->FromConn
= Connection
;
243 TRACE("binding: %p\n", NewBinding
);
244 *Binding
= NewBinding
;
249 void RPCRT4_AddRefBinding(RpcBinding
* Binding
)
251 InterlockedIncrement(&Binding
->refs
);
254 RPC_STATUS
RPCRT4_ReleaseBinding(RpcBinding
* Binding
)
256 if (InterlockedDecrement(&Binding
->refs
))
259 TRACE("binding: %p\n", Binding
);
260 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
261 RPCRT4_strfree(Binding
->Endpoint
);
262 RPCRT4_strfree(Binding
->NetworkAddr
);
263 RPCRT4_strfree(Binding
->Protseq
);
264 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
265 HeapFree(GetProcessHeap(), 0, Binding
->CookieAuth
);
266 if (Binding
->AuthInfo
) RpcAuthInfo_Release(Binding
->AuthInfo
);
267 if (Binding
->QOS
) RpcQualityOfService_Release(Binding
->QOS
);
268 HeapFree(GetProcessHeap(), 0, Binding
);
272 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
,
273 const RPC_SYNTAX_IDENTIFIER
*TransferSyntax
,
274 const RPC_SYNTAX_IDENTIFIER
*InterfaceId
, BOOL
*from_cache
)
276 TRACE("(Binding == ^%p)\n", Binding
);
278 if (!Binding
->server
) {
279 return RpcAssoc_GetClientConnection(Binding
->Assoc
, InterfaceId
,
280 TransferSyntax
, Binding
->AuthInfo
, Binding
->QOS
, Binding
->CookieAuth
, Connection
, from_cache
);
282 /* we already have a connection with acceptable binding, so use it */
283 if (Binding
->FromConn
) {
284 *Connection
= Binding
->FromConn
;
287 ERR("no connection in binding\n");
288 return RPC_S_INTERNAL_ERROR
;
293 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
295 TRACE("(Binding == ^%p)\n", Binding
);
296 if (!Connection
) return RPC_S_OK
;
297 if (Binding
->server
) {
298 /* don't destroy a connection that is cached in the binding */
299 if (Binding
->FromConn
!= Connection
)
300 RPCRT4_ReleaseConnection(Connection
);
303 RpcAssoc_ReleaseIdleConnection(Binding
->Assoc
, Connection
);
308 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
310 DWORD len
= strlen(dst
), slen
= strlen(src
);
311 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
314 HeapFree(GetProcessHeap(), 0, dst
);
318 memcpy(ndst
+len
+1, src
, slen
+1);
322 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
324 DWORD len
= lstrlenW(dst
), slen
= lstrlenW(src
);
325 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
328 HeapFree(GetProcessHeap(), 0, dst
);
332 memcpy(ndst
+len
+1, src
, (slen
+1)*sizeof(WCHAR
));
336 /* Copies the escaped version of a component into a string binding.
337 * Note: doesn't nul-terminate the string */
338 static RPC_CSTR
escape_string_binding_component(RPC_CSTR string_binding
,
339 const unsigned char *component
)
341 for (; *component
; component
++) {
342 switch (*component
) {
348 *string_binding
++ = '\\';
349 *string_binding
++ = *component
;
352 *string_binding
++ = *component
;
356 return string_binding
;
359 static RPC_WSTR
escape_string_binding_componentW(RPC_WSTR string_binding
,
360 const WCHAR
*component
)
362 for (; *component
; component
++) {
363 switch (*component
) {
369 *string_binding
++ = '\\';
370 *string_binding
++ = *component
;
373 *string_binding
++ = *component
;
377 return string_binding
;
380 static const unsigned char *string_binding_find_delimiter(
381 const unsigned char *string_binding
, unsigned char delim
)
383 const unsigned char *next
;
384 for (next
= string_binding
; *next
; next
++) {
395 static const WCHAR
*string_binding_find_delimiterW(
396 const WCHAR
*string_binding
, WCHAR delim
)
399 for (next
= string_binding
; *next
; next
++) {
410 static RPC_CSTR
unescape_string_binding_component(
411 const unsigned char *string_binding
, int len
)
413 RPC_CSTR component
, p
;
415 if (len
== -1) len
= strlen((const char *)string_binding
);
417 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
418 if (!component
) return NULL
;
419 for (p
= component
; len
> 0; string_binding
++, len
--) {
420 if (*string_binding
== '\\') {
423 *p
++ = *string_binding
;
425 *p
++ = *string_binding
;
432 static RPC_WSTR
unescape_string_binding_componentW(
433 const WCHAR
*string_binding
, int len
)
435 RPC_WSTR component
, p
;
437 if (len
== -1) len
= lstrlenW(string_binding
);
439 component
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(*component
));
440 if (!component
) return NULL
;
441 for (p
= component
; len
> 0; string_binding
++, len
--) {
442 if (*string_binding
== '\\') {
445 *p
++ = *string_binding
;
447 *p
++ = *string_binding
;
454 /***********************************************************************
455 * RpcStringBindingComposeA (RPCRT4.@)
457 RPC_STATUS WINAPI
RpcStringBindingComposeA(RPC_CSTR ObjUuid
, RPC_CSTR Protseq
,
458 RPC_CSTR NetworkAddr
, RPC_CSTR Endpoint
,
459 RPC_CSTR Options
, RPC_CSTR
*StringBinding
)
464 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
465 debugstr_a( (char*)ObjUuid
), debugstr_a( (char*)Protseq
),
466 debugstr_a( (char*)NetworkAddr
), debugstr_a( (char*)Endpoint
),
467 debugstr_a( (char*)Options
), StringBinding
);
469 /* overestimate for each component for escaping of delimiters */
470 if (ObjUuid
&& *ObjUuid
) len
+= strlen((char*)ObjUuid
) * 2 + 1;
471 if (Protseq
&& *Protseq
) len
+= strlen((char*)Protseq
) * 2 + 1;
472 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen((char*)NetworkAddr
) * 2;
473 if (Endpoint
&& *Endpoint
) len
+= strlen((char*)Endpoint
) * 2 + 2;
474 if (Options
&& *Options
) len
+= strlen((char*)Options
) * 2 + 2;
476 data
= HeapAlloc(GetProcessHeap(), 0, len
);
477 *StringBinding
= data
;
479 if (ObjUuid
&& *ObjUuid
) {
480 data
= escape_string_binding_component(data
, ObjUuid
);
483 if (Protseq
&& *Protseq
) {
484 data
= escape_string_binding_component(data
, Protseq
);
487 if (NetworkAddr
&& *NetworkAddr
)
488 data
= escape_string_binding_component(data
, NetworkAddr
);
490 if ((Endpoint
&& *Endpoint
) ||
491 (Options
&& *Options
)) {
493 if (Endpoint
&& *Endpoint
) {
494 data
= escape_string_binding_component(data
, Endpoint
);
495 if (Options
&& *Options
) *data
++ = ',';
497 if (Options
&& *Options
) {
498 data
= escape_string_binding_component(data
, Options
);
507 /***********************************************************************
508 * RpcStringBindingComposeW (RPCRT4.@)
510 RPC_STATUS WINAPI
RpcStringBindingComposeW( RPC_WSTR ObjUuid
, RPC_WSTR Protseq
,
511 RPC_WSTR NetworkAddr
, RPC_WSTR Endpoint
,
512 RPC_WSTR Options
, RPC_WSTR
* StringBinding
)
517 TRACE("(%s,%s,%s,%s,%s,%p)\n",
518 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
519 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
520 debugstr_w( Options
), StringBinding
);
522 /* overestimate for each component for escaping of delimiters */
523 if (ObjUuid
&& *ObjUuid
) len
+= lstrlenW(ObjUuid
) * 2 + 1;
524 if (Protseq
&& *Protseq
) len
+= lstrlenW(Protseq
) * 2 + 1;
525 if (NetworkAddr
&& *NetworkAddr
) len
+= lstrlenW(NetworkAddr
) * 2;
526 if (Endpoint
&& *Endpoint
) len
+= lstrlenW(Endpoint
) * 2 + 2;
527 if (Options
&& *Options
) len
+= lstrlenW(Options
) * 2 + 2;
529 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
530 *StringBinding
= data
;
532 if (ObjUuid
&& *ObjUuid
) {
533 data
= escape_string_binding_componentW(data
, ObjUuid
);
536 if (Protseq
&& *Protseq
) {
537 data
= escape_string_binding_componentW(data
, Protseq
);
540 if (NetworkAddr
&& *NetworkAddr
) {
541 data
= escape_string_binding_componentW(data
, NetworkAddr
);
543 if ((Endpoint
&& *Endpoint
) ||
544 (Options
&& *Options
)) {
546 if (Endpoint
&& *Endpoint
) {
547 data
= escape_string_binding_componentW(data
, Endpoint
);
548 if (Options
&& *Options
) *data
++ = ',';
550 if (Options
&& *Options
) {
551 data
= escape_string_binding_componentW(data
, Options
);
561 /***********************************************************************
562 * RpcStringBindingParseA (RPCRT4.@)
564 RPC_STATUS WINAPI
RpcStringBindingParseA( RPC_CSTR StringBinding
, RPC_CSTR
*ObjUuid
,
565 RPC_CSTR
*Protseq
, RPC_CSTR
*NetworkAddr
,
566 RPC_CSTR
*Endpoint
, RPC_CSTR
*Options
)
568 const unsigned char *data
, *next
;
569 static const char ep_opt
[] = "endpoint=";
570 BOOL endpoint_already_found
= FALSE
;
572 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding
),
573 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
575 if (ObjUuid
) *ObjUuid
= NULL
;
576 if (Protseq
) *Protseq
= NULL
;
577 if (NetworkAddr
) *NetworkAddr
= NULL
;
578 if (Endpoint
) *Endpoint
= NULL
;
579 if (Options
) *Options
= NULL
;
581 data
= StringBinding
;
583 next
= string_binding_find_delimiter(data
, '@');
587 RPC_CSTR str_uuid
= unescape_string_binding_component(data
, next
- data
);
588 status
= UuidFromStringA(str_uuid
, &uuid
);
589 if (status
!= RPC_S_OK
) {
590 HeapFree(GetProcessHeap(), 0, str_uuid
);
596 HeapFree(GetProcessHeap(), 0, str_uuid
);
600 next
= string_binding_find_delimiter(data
, ':');
602 if (Protseq
) *Protseq
= unescape_string_binding_component(data
, next
- data
);
606 next
= string_binding_find_delimiter(data
, '[');
608 const unsigned char *close
;
611 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_component(data
, next
- data
);
613 close
= string_binding_find_delimiter(data
, ']');
614 if (!close
) goto fail
;
616 /* tokenize options */
617 while (data
< close
) {
618 next
= string_binding_find_delimiter(data
, ',');
619 if (!next
|| next
> close
) next
= close
;
620 /* FIXME: this is kind of inefficient */
621 opt
= unescape_string_binding_component(data
, next
- data
);
625 next
= string_binding_find_delimiter(opt
, '=');
627 /* not an option, must be an endpoint */
628 if (endpoint_already_found
) goto fail
;
629 if (Endpoint
) *Endpoint
= opt
;
630 else HeapFree(GetProcessHeap(), 0, opt
);
631 endpoint_already_found
= TRUE
;
633 if (strncmp((const char *)opt
, ep_opt
, strlen(ep_opt
)) == 0) {
634 /* endpoint option */
635 if (endpoint_already_found
) goto fail
;
636 if (Endpoint
) *Endpoint
= unescape_string_binding_component(next
+1, -1);
637 HeapFree(GetProcessHeap(), 0, opt
);
638 endpoint_already_found
= TRUE
;
643 /* FIXME: this is kind of inefficient */
644 *Options
= (unsigned char*) RPCRT4_strconcatA( (char*)*Options
, (char *)opt
);
645 HeapFree(GetProcessHeap(), 0, opt
);
649 HeapFree(GetProcessHeap(), 0, opt
);
655 if (*data
) goto fail
;
657 else if (NetworkAddr
)
658 *NetworkAddr
= unescape_string_binding_component(data
, -1);
663 if (ObjUuid
) RpcStringFreeA(ObjUuid
);
664 if (Protseq
) RpcStringFreeA(Protseq
);
665 if (NetworkAddr
) RpcStringFreeA(NetworkAddr
);
666 if (Endpoint
) RpcStringFreeA(Endpoint
);
667 if (Options
) RpcStringFreeA(Options
);
668 return RPC_S_INVALID_STRING_BINDING
;
671 /***********************************************************************
672 * RpcStringBindingParseW (RPCRT4.@)
674 RPC_STATUS WINAPI
RpcStringBindingParseW( RPC_WSTR StringBinding
, RPC_WSTR
*ObjUuid
,
675 RPC_WSTR
*Protseq
, RPC_WSTR
*NetworkAddr
,
676 RPC_WSTR
*Endpoint
, RPC_WSTR
*Options
)
678 const WCHAR
*data
, *next
;
679 BOOL endpoint_already_found
= FALSE
;
681 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
682 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
684 if (ObjUuid
) *ObjUuid
= NULL
;
685 if (Protseq
) *Protseq
= NULL
;
686 if (NetworkAddr
) *NetworkAddr
= NULL
;
687 if (Endpoint
) *Endpoint
= NULL
;
688 if (Options
) *Options
= NULL
;
690 data
= StringBinding
;
692 next
= string_binding_find_delimiterW(data
, '@');
696 RPC_WSTR str_uuid
= unescape_string_binding_componentW(data
, next
- data
);
697 status
= UuidFromStringW(str_uuid
, &uuid
);
698 if (status
!= RPC_S_OK
) {
699 HeapFree(GetProcessHeap(), 0, str_uuid
);
705 HeapFree(GetProcessHeap(), 0, str_uuid
);
709 next
= string_binding_find_delimiterW(data
, ':');
711 if (Protseq
) *Protseq
= unescape_string_binding_componentW(data
, next
- data
);
715 next
= string_binding_find_delimiterW(data
, '[');
720 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_componentW(data
, next
- data
);
722 close
= string_binding_find_delimiterW(data
, ']');
723 if (!close
) goto fail
;
725 /* tokenize options */
726 while (data
< close
) {
727 next
= string_binding_find_delimiterW(data
, ',');
728 if (!next
|| next
> close
) next
= close
;
729 /* FIXME: this is kind of inefficient */
730 opt
= unescape_string_binding_componentW(data
, next
- data
);
734 next
= string_binding_find_delimiterW(opt
, '=');
736 /* not an option, must be an endpoint */
737 if (endpoint_already_found
) goto fail
;
738 if (Endpoint
) *Endpoint
= opt
;
739 else HeapFree(GetProcessHeap(), 0, opt
);
740 endpoint_already_found
= TRUE
;
742 if (wcsncmp(opt
, L
"endpoint=", lstrlenW(L
"endpoint=")) == 0) {
743 /* endpoint option */
744 if (endpoint_already_found
) goto fail
;
745 if (Endpoint
) *Endpoint
= unescape_string_binding_componentW(next
+1, -1);
746 HeapFree(GetProcessHeap(), 0, opt
);
747 endpoint_already_found
= TRUE
;
752 /* FIXME: this is kind of inefficient */
753 *Options
= RPCRT4_strconcatW(*Options
, opt
);
754 HeapFree(GetProcessHeap(), 0, opt
);
758 HeapFree(GetProcessHeap(), 0, opt
);
764 if (*data
) goto fail
;
765 } else if (NetworkAddr
)
766 *NetworkAddr
= unescape_string_binding_componentW(data
, -1);
771 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
772 if (Protseq
) RpcStringFreeW(Protseq
);
773 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
774 if (Endpoint
) RpcStringFreeW(Endpoint
);
775 if (Options
) RpcStringFreeW(Options
);
776 return RPC_S_INVALID_STRING_BINDING
;
779 /***********************************************************************
780 * RpcBindingFree (RPCRT4.@)
782 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
785 TRACE("(%p) = %p\n", Binding
, *Binding
);
787 status
= RPCRT4_ReleaseBinding(*Binding
);
789 status
= RPC_S_INVALID_BINDING
;
790 if (status
== RPC_S_OK
) *Binding
= NULL
;
794 /***********************************************************************
795 * RpcBindingVectorFree (RPCRT4.@)
797 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
801 TRACE("(%p)\n", BindingVector
);
802 for (c
=0; c
<(*BindingVector
)->Count
; c
++) RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
803 HeapFree(GetProcessHeap(), 0, *BindingVector
);
804 *BindingVector
= NULL
;
808 /***********************************************************************
809 * RpcBindingInqObject (RPCRT4.@)
811 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
813 RpcBinding
* bind
= Binding
;
815 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
816 *ObjectUuid
= bind
->ObjectUuid
;
820 /***********************************************************************
821 * RpcBindingSetObject (RPCRT4.@)
823 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
825 RpcBinding
* bind
= Binding
;
827 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
828 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
829 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
832 /***********************************************************************
833 * RpcBindingFromStringBindingA (RPCRT4.@)
835 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( RPC_CSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
838 RpcBinding
* bind
= NULL
;
839 RPC_CSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
842 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
844 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
845 &NetworkAddr
, &Endpoint
, &Options
);
846 if (ret
!= RPC_S_OK
) return ret
;
848 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
851 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
852 if (ret
== RPC_S_OK
) {
853 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
855 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
858 *Binding
= (RPC_BINDING_HANDLE
)bind
;
860 RPCRT4_ReleaseBinding(bind
);
863 RpcStringFreeA(&Options
);
864 RpcStringFreeA(&Endpoint
);
865 RpcStringFreeA(&NetworkAddr
);
866 RpcStringFreeA(&Protseq
);
867 RpcStringFreeA(&ObjectUuid
);
872 /***********************************************************************
873 * RpcBindingFromStringBindingW (RPCRT4.@)
875 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( RPC_WSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
878 RpcBinding
* bind
= NULL
;
879 RPC_WSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
882 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
884 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
885 &NetworkAddr
, &Endpoint
, &Options
);
886 if (ret
!= RPC_S_OK
) return ret
;
888 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
891 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
892 if (ret
== RPC_S_OK
) {
893 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
895 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
898 *Binding
= (RPC_BINDING_HANDLE
)bind
;
900 RPCRT4_ReleaseBinding(bind
);
903 RpcStringFreeW(&Options
);
904 RpcStringFreeW(&Endpoint
);
905 RpcStringFreeW(&NetworkAddr
);
906 RpcStringFreeW(&Protseq
);
907 RpcStringFreeW(&ObjectUuid
);
912 /***********************************************************************
913 * RpcBindingToStringBindingA (RPCRT4.@)
915 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*StringBinding
)
918 RpcBinding
* bind
= Binding
;
921 TRACE("(%p,%p)\n", Binding
, StringBinding
);
923 if (UuidIsNil(&bind
->ObjectUuid
, &ret
))
927 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
928 if (ret
!= RPC_S_OK
) return ret
;
931 ret
= RpcStringBindingComposeA(ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
932 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
934 RpcStringFreeA(&ObjectUuid
);
939 /***********************************************************************
940 * RpcBindingToStringBindingW (RPCRT4.@)
942 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*StringBinding
)
945 unsigned char *str
= NULL
;
946 TRACE("(%p,%p)\n", Binding
, StringBinding
);
947 ret
= RpcBindingToStringBindingA(Binding
, &str
);
948 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
949 RpcStringFreeA(&str
);
953 /***********************************************************************
954 * I_RpcBindingInqTransportType (RPCRT4.@)
956 RPC_STATUS WINAPI
I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding
, unsigned int * Type
)
959 FIXME( "(%p,%p): stub\n", Binding
, Type
);
960 *Type
= TRANSPORT_TYPE_LPC
;
964 /***********************************************************************
965 * I_RpcBindingSetAsync (RPCRT4.@)
967 * Exists in win9x and winNT, but with different number of arguments
968 * (9x version has 3 arguments, NT has 2).
970 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
972 RpcBinding
* bind
= Binding
;
974 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
976 bind
->BlockingFn
= BlockingFn
;
981 /***********************************************************************
982 * RpcBindingCopy (RPCRT4.@)
984 RPC_STATUS RPC_ENTRY
RpcBindingCopy(
985 RPC_BINDING_HANDLE SourceBinding
,
986 RPC_BINDING_HANDLE
* DestinationBinding
)
988 RpcBinding
*DestBinding
;
989 RpcBinding
*SrcBinding
= SourceBinding
;
992 TRACE("(%p, %p)\n", SourceBinding
, DestinationBinding
);
994 status
= RPCRT4_AllocBinding(&DestBinding
, SrcBinding
->server
);
995 if (status
!= RPC_S_OK
) return status
;
997 DestBinding
->ObjectUuid
= SrcBinding
->ObjectUuid
;
998 DestBinding
->BlockingFn
= SrcBinding
->BlockingFn
;
999 DestBinding
->Protseq
= RPCRT4_strndupA(SrcBinding
->Protseq
, -1);
1000 DestBinding
->NetworkAddr
= RPCRT4_strndupA(SrcBinding
->NetworkAddr
, -1);
1001 DestBinding
->Endpoint
= RPCRT4_strndupA(SrcBinding
->Endpoint
, -1);
1002 DestBinding
->NetworkOptions
= RPCRT4_strdupW(SrcBinding
->NetworkOptions
);
1003 DestBinding
->CookieAuth
= RPCRT4_strdupW(SrcBinding
->CookieAuth
);
1004 if (SrcBinding
->Assoc
) SrcBinding
->Assoc
->refs
++;
1005 DestBinding
->Assoc
= SrcBinding
->Assoc
;
1007 if (SrcBinding
->AuthInfo
) RpcAuthInfo_AddRef(SrcBinding
->AuthInfo
);
1008 DestBinding
->AuthInfo
= SrcBinding
->AuthInfo
;
1009 if (SrcBinding
->QOS
) RpcQualityOfService_AddRef(SrcBinding
->QOS
);
1010 DestBinding
->QOS
= SrcBinding
->QOS
;
1012 *DestinationBinding
= DestBinding
;
1016 /***********************************************************************
1017 * RpcBindingReset (RPCRT4.@)
1019 RPC_STATUS RPC_ENTRY
RpcBindingReset(RPC_BINDING_HANDLE Binding
)
1021 RpcBinding
*bind
= Binding
;
1023 TRACE("(%p)\n", Binding
);
1025 RPCRT4_strfree(bind
->Endpoint
);
1026 bind
->Endpoint
= NULL
;
1027 if (bind
->Assoc
) RpcAssoc_Release(bind
->Assoc
);
1033 /***********************************************************************
1034 * RpcImpersonateClient (RPCRT4.@)
1036 * Impersonates the client connected via a binding handle so that security
1037 * checks are done in the context of the client.
1040 * BindingHandle [I] Handle to the binding to the client.
1043 * Success: RPS_S_OK.
1044 * Failure: RPC_STATUS value.
1048 * If BindingHandle is NULL then the function impersonates the client
1049 * connected to the binding handle of the current thread.
1051 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
1055 TRACE("(%p)\n", BindingHandle
);
1057 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1058 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1060 bind
= BindingHandle
;
1062 return rpcrt4_conn_impersonate_client(bind
->FromConn
);
1063 return RPC_S_WRONG_KIND_OF_BINDING
;
1066 /***********************************************************************
1067 * RpcRevertToSelfEx (RPCRT4.@)
1069 * Stops impersonating the client connected to the binding handle so that security
1070 * checks are no longer done in the context of the client.
1073 * BindingHandle [I] Handle to the binding to the client.
1076 * Success: RPS_S_OK.
1077 * Failure: RPC_STATUS value.
1081 * If BindingHandle is NULL then the function stops impersonating the client
1082 * connected to the binding handle of the current thread.
1084 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
1088 TRACE("(%p)\n", BindingHandle
);
1090 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1091 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1093 bind
= BindingHandle
;
1095 return rpcrt4_conn_revert_to_self(bind
->FromConn
);
1096 return RPC_S_WRONG_KIND_OF_BINDING
;
1099 static inline BOOL
has_nt_auth_identity(ULONG AuthnLevel
)
1103 case RPC_C_AUTHN_GSS_NEGOTIATE
:
1104 case RPC_C_AUTHN_WINNT
:
1105 case RPC_C_AUTHN_GSS_KERBEROS
:
1112 RPC_STATUS
RpcAuthInfo_Create(ULONG AuthnLevel
, ULONG AuthnSvc
,
1113 CredHandle cred
, TimeStamp exp
,
1115 RPC_AUTH_IDENTITY_HANDLE identity
,
1118 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
1120 return RPC_S_OUT_OF_MEMORY
;
1123 AuthInfo
->AuthnLevel
= AuthnLevel
;
1124 AuthInfo
->AuthnSvc
= AuthnSvc
;
1125 AuthInfo
->cred
= cred
;
1126 AuthInfo
->exp
= exp
;
1127 AuthInfo
->cbMaxToken
= cbMaxToken
;
1128 AuthInfo
->identity
= identity
;
1129 AuthInfo
->server_principal_name
= NULL
;
1131 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1132 * enable better matching in RpcAuthInfo_IsEqual */
1133 if (identity
&& has_nt_auth_identity(AuthnSvc
))
1135 const SEC_WINNT_AUTH_IDENTITY_W
*nt_identity
= identity
;
1136 AuthInfo
->nt_identity
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
->nt_identity
));
1137 if (!AuthInfo
->nt_identity
)
1139 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1140 return RPC_S_OUT_OF_MEMORY
;
1143 AuthInfo
->nt_identity
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1144 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1145 AuthInfo
->nt_identity
->User
= RPCRT4_strndupW(nt_identity
->User
, nt_identity
->UserLength
);
1147 AuthInfo
->nt_identity
->User
= RPCRT4_strndupAtoW((const char *)nt_identity
->User
, nt_identity
->UserLength
);
1148 AuthInfo
->nt_identity
->UserLength
= nt_identity
->UserLength
;
1149 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1150 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupW(nt_identity
->Domain
, nt_identity
->DomainLength
);
1152 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupAtoW((const char *)nt_identity
->Domain
, nt_identity
->DomainLength
);
1153 AuthInfo
->nt_identity
->DomainLength
= nt_identity
->DomainLength
;
1154 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1155 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupW(nt_identity
->Password
, nt_identity
->PasswordLength
);
1157 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupAtoW((const char *)nt_identity
->Password
, nt_identity
->PasswordLength
);
1158 AuthInfo
->nt_identity
->PasswordLength
= nt_identity
->PasswordLength
;
1160 if ((nt_identity
->User
&& !AuthInfo
->nt_identity
->User
) ||
1161 (nt_identity
->Domain
&& !AuthInfo
->nt_identity
->Domain
) ||
1162 (nt_identity
->Password
&& !AuthInfo
->nt_identity
->Password
))
1164 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1165 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1166 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1167 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1168 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1169 return RPC_S_OUT_OF_MEMORY
;
1173 AuthInfo
->nt_identity
= NULL
;
1178 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
1180 return InterlockedIncrement(&AuthInfo
->refs
);
1183 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
1185 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
1189 FreeCredentialsHandle(&AuthInfo
->cred
);
1190 if (AuthInfo
->nt_identity
)
1192 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1193 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1194 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1195 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1197 HeapFree(GetProcessHeap(), 0, AuthInfo
->server_principal_name
);
1198 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1204 BOOL
RpcAuthInfo_IsEqual(const RpcAuthInfo
*AuthInfo1
, const RpcAuthInfo
*AuthInfo2
)
1206 if (AuthInfo1
== AuthInfo2
)
1209 if (!AuthInfo1
|| !AuthInfo2
)
1212 if ((AuthInfo1
->AuthnLevel
!= AuthInfo2
->AuthnLevel
) ||
1213 (AuthInfo1
->AuthnSvc
!= AuthInfo2
->AuthnSvc
))
1216 if (AuthInfo1
->identity
== AuthInfo2
->identity
)
1219 if (!AuthInfo1
->identity
|| !AuthInfo2
->identity
)
1222 if (has_nt_auth_identity(AuthInfo1
->AuthnSvc
))
1224 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= AuthInfo1
->nt_identity
;
1225 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= AuthInfo2
->nt_identity
;
1226 /* compare user names */
1227 if (identity1
->UserLength
!= identity2
->UserLength
||
1228 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1230 /* compare domain names */
1231 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1232 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1234 /* compare passwords */
1235 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1236 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1245 static RPC_STATUS
RpcQualityOfService_Create(const RPC_SECURITY_QOS
*qos_src
, BOOL unicode
, RpcQualityOfService
**qos_dst
)
1247 RpcQualityOfService
*qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
));
1250 return RPC_S_OUT_OF_RESOURCES
;
1253 qos
->qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
->qos
));
1254 if (!qos
->qos
) goto error
;
1255 qos
->qos
->Version
= qos_src
->Version
;
1256 qos
->qos
->Capabilities
= qos_src
->Capabilities
;
1257 qos
->qos
->IdentityTracking
= qos_src
->IdentityTracking
;
1258 qos
->qos
->ImpersonationType
= qos_src
->ImpersonationType
;
1259 qos
->qos
->AdditionalSecurityInfoType
= 0;
1261 if (qos_src
->Version
>= 2)
1263 const RPC_SECURITY_QOS_V2_W
*qos_src2
= (const RPC_SECURITY_QOS_V2_W
*)qos_src
;
1264 qos
->qos
->AdditionalSecurityInfoType
= qos_src2
->AdditionalSecurityInfoType
;
1265 if (qos_src2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1267 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_src
= qos_src2
->u
.HttpCredentials
;
1268 RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_dst
;
1270 http_credentials_dst
= HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst
));
1271 qos
->qos
->u
.HttpCredentials
= http_credentials_dst
;
1272 if (!http_credentials_dst
) goto error
;
1273 http_credentials_dst
->TransportCredentials
= NULL
;
1274 http_credentials_dst
->Flags
= http_credentials_src
->Flags
;
1275 http_credentials_dst
->AuthenticationTarget
= http_credentials_src
->AuthenticationTarget
;
1276 http_credentials_dst
->NumberOfAuthnSchemes
= http_credentials_src
->NumberOfAuthnSchemes
;
1277 http_credentials_dst
->AuthnSchemes
= NULL
;
1278 http_credentials_dst
->ServerCertificateSubject
= NULL
;
1279 if (http_credentials_src
->TransportCredentials
)
1281 SEC_WINNT_AUTH_IDENTITY_W
*cred_dst
;
1282 cred_dst
= http_credentials_dst
->TransportCredentials
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cred_dst
));
1283 if (!cred_dst
) goto error
;
1284 cred_dst
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1287 const SEC_WINNT_AUTH_IDENTITY_W
*cred_src
= http_credentials_src
->TransportCredentials
;
1288 cred_dst
->UserLength
= cred_src
->UserLength
;
1289 cred_dst
->PasswordLength
= cred_src
->PasswordLength
;
1290 cred_dst
->DomainLength
= cred_src
->DomainLength
;
1291 cred_dst
->User
= RPCRT4_strndupW(cred_src
->User
, cred_src
->UserLength
);
1292 cred_dst
->Password
= RPCRT4_strndupW(cred_src
->Password
, cred_src
->PasswordLength
);
1293 cred_dst
->Domain
= RPCRT4_strndupW(cred_src
->Domain
, cred_src
->DomainLength
);
1297 const SEC_WINNT_AUTH_IDENTITY_A
*cred_src
= (const SEC_WINNT_AUTH_IDENTITY_A
*)http_credentials_src
->TransportCredentials
;
1298 cred_dst
->UserLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, NULL
, 0);
1299 cred_dst
->DomainLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, NULL
, 0);
1300 cred_dst
->PasswordLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, NULL
, 0);
1301 cred_dst
->User
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->UserLength
* sizeof(WCHAR
));
1302 cred_dst
->Password
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->PasswordLength
* sizeof(WCHAR
));
1303 cred_dst
->Domain
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->DomainLength
* sizeof(WCHAR
));
1304 if (!cred_dst
->Password
|| !cred_dst
->Domain
) goto error
;
1305 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, cred_dst
->User
, cred_dst
->UserLength
);
1306 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, cred_dst
->Domain
, cred_dst
->DomainLength
);
1307 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, cred_dst
->Password
, cred_dst
->PasswordLength
);
1310 if (http_credentials_src
->NumberOfAuthnSchemes
)
1312 http_credentials_dst
->AuthnSchemes
= HeapAlloc(GetProcessHeap(), 0, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1313 if (!http_credentials_dst
->AuthnSchemes
) goto error
;
1314 memcpy(http_credentials_dst
->AuthnSchemes
, http_credentials_src
->AuthnSchemes
, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1316 if (http_credentials_src
->ServerCertificateSubject
)
1319 http_credentials_dst
->ServerCertificateSubject
=
1320 RPCRT4_strndupW(http_credentials_src
->ServerCertificateSubject
,
1321 lstrlenW(http_credentials_src
->ServerCertificateSubject
));
1323 http_credentials_dst
->ServerCertificateSubject
=
1324 RPCRT4_strdupAtoW((char *)http_credentials_src
->ServerCertificateSubject
);
1325 if (!http_credentials_dst
->ServerCertificateSubject
) goto error
;
1335 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
&&
1336 qos
->qos
->u
.HttpCredentials
)
1338 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1340 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1341 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1342 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1343 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1345 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1346 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1347 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1349 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1351 HeapFree(GetProcessHeap(), 0, qos
);
1352 return RPC_S_OUT_OF_RESOURCES
;
1355 ULONG
RpcQualityOfService_AddRef(RpcQualityOfService
*qos
)
1357 return InterlockedIncrement(&qos
->refs
);
1360 ULONG
RpcQualityOfService_Release(RpcQualityOfService
*qos
)
1362 ULONG refs
= InterlockedDecrement(&qos
->refs
);
1366 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1368 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1370 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1371 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1372 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1373 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1375 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1376 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1377 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1379 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1380 HeapFree(GetProcessHeap(), 0, qos
);
1385 BOOL
RpcQualityOfService_IsEqual(const RpcQualityOfService
*qos1
, const RpcQualityOfService
*qos2
)
1393 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
1394 qos1
->qos
->Capabilities
, qos1
->qos
->IdentityTracking
,
1395 qos1
->qos
->ImpersonationType
, qos1
->qos
->AdditionalSecurityInfoType
,
1396 qos2
->qos
->Capabilities
, qos2
->qos
->IdentityTracking
,
1397 qos2
->qos
->ImpersonationType
, qos2
->qos
->AdditionalSecurityInfoType
);
1399 if ((qos1
->qos
->Capabilities
!= qos2
->qos
->Capabilities
) ||
1400 (qos1
->qos
->IdentityTracking
!= qos2
->qos
->IdentityTracking
) ||
1401 (qos1
->qos
->ImpersonationType
!= qos2
->qos
->ImpersonationType
) ||
1402 (qos1
->qos
->AdditionalSecurityInfoType
!= qos2
->qos
->AdditionalSecurityInfoType
))
1405 if (qos1
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1407 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials1
= qos1
->qos
->u
.HttpCredentials
;
1408 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials2
= qos2
->qos
->u
.HttpCredentials
;
1410 if (http_credentials1
->Flags
!= http_credentials2
->Flags
)
1413 if (http_credentials1
->AuthenticationTarget
!= http_credentials2
->AuthenticationTarget
)
1416 if (http_credentials1
->NumberOfAuthnSchemes
!= http_credentials2
->NumberOfAuthnSchemes
)
1419 if ((!http_credentials1
->AuthnSchemes
&& http_credentials2
->AuthnSchemes
) ||
1420 (http_credentials1
->AuthnSchemes
&& !http_credentials2
->AuthnSchemes
))
1423 if (memcmp(http_credentials1
->AuthnSchemes
, http_credentials2
->AuthnSchemes
,
1424 http_credentials1
->NumberOfAuthnSchemes
* sizeof(http_credentials1
->AuthnSchemes
[0])))
1427 /* server certificate subject not currently used */
1429 if (http_credentials1
->TransportCredentials
!= http_credentials2
->TransportCredentials
)
1431 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= http_credentials1
->TransportCredentials
;
1432 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= http_credentials2
->TransportCredentials
;
1434 if (!identity1
|| !identity2
)
1437 /* compare user names */
1438 if (identity1
->UserLength
!= identity2
->UserLength
||
1439 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1441 /* compare domain names */
1442 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1443 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1445 /* compare passwords */
1446 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1447 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1455 /***********************************************************************
1456 * RpcRevertToSelf (RPCRT4.@)
1458 RPC_STATUS WINAPI
RpcRevertToSelf(void)
1461 return RpcRevertToSelfEx(NULL
);
1464 /***********************************************************************
1465 * RpcMgmtSetComTimeout (RPCRT4.@)
1467 RPC_STATUS WINAPI
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle
, unsigned int Timeout
)
1469 FIXME("(%p, %d): stub\n", BindingHandle
, Timeout
);
1473 /***********************************************************************
1474 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1476 RPCRTAPI RPC_STATUS RPC_ENTRY
1477 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1478 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1479 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1484 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1485 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1487 status
= RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
? &principal
: NULL
, AuthnLevel
,
1488 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1489 if (status
== RPC_S_OK
&& ServerPrincName
)
1491 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1492 RpcStringFreeW(&principal
);
1493 if (!*ServerPrincName
) return RPC_S_OUT_OF_MEMORY
;
1499 /***********************************************************************
1500 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1502 RPCRTAPI RPC_STATUS RPC_ENTRY
1503 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1504 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1505 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1507 RpcBinding
*bind
= Binding
;
1509 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1510 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1512 if (!bind
->AuthInfo
) return RPC_S_BINDING_HAS_NO_AUTH
;
1516 FIXME("QOS not implemented\n");
1517 return RPC_S_INVALID_BINDING
;
1520 if (ServerPrincName
)
1522 if (bind
->AuthInfo
->server_principal_name
)
1524 *ServerPrincName
= RPCRT4_strdupW(bind
->AuthInfo
->server_principal_name
);
1525 if (!*ServerPrincName
) return RPC_S_OUT_OF_MEMORY
;
1527 else *ServerPrincName
= NULL
;
1529 if (AuthnLevel
) *AuthnLevel
= bind
->AuthInfo
->AuthnLevel
;
1530 if (AuthnSvc
) *AuthnSvc
= bind
->AuthInfo
->AuthnSvc
;
1531 if (AuthIdentity
) *AuthIdentity
= bind
->AuthInfo
->identity
;
1534 FIXME("authorization service not implemented\n");
1535 *AuthzSvc
= RPC_C_AUTHZ_NONE
;
1541 /***********************************************************************
1542 * RpcBindingInqAuthInfoA (RPCRT4.@)
1544 RPCRTAPI RPC_STATUS RPC_ENTRY
1545 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1546 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1548 return RpcBindingInqAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1552 /***********************************************************************
1553 * RpcBindingInqAuthInfoW (RPCRT4.@)
1555 RPCRTAPI RPC_STATUS RPC_ENTRY
1556 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1557 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1559 return RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1563 /***********************************************************************
1564 * RpcBindingInqAuthClientA (RPCRT4.@)
1566 RPCRTAPI RPC_STATUS RPC_ENTRY
1567 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1568 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1571 return RpcBindingInqAuthClientExA(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1572 AuthnSvc
, AuthzSvc
, 0);
1575 /***********************************************************************
1576 * RpcBindingInqAuthClientW (RPCRT4.@)
1578 RPCRTAPI RPC_STATUS RPC_ENTRY
1579 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1580 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1583 return RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1584 AuthnSvc
, AuthzSvc
, 0);
1587 /***********************************************************************
1588 * RpcBindingInqAuthClientExA (RPCRT4.@)
1590 RPCRTAPI RPC_STATUS RPC_ENTRY
1591 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1592 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1593 ULONG
*AuthzSvc
, ULONG Flags
)
1598 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1599 AuthnSvc
, AuthzSvc
, Flags
);
1601 status
= RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
? &principal
: NULL
,
1602 AuthnLevel
, AuthnSvc
, AuthzSvc
, Flags
);
1603 if (status
== RPC_S_OK
&& ServerPrincName
)
1605 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1606 if (!*ServerPrincName
&& principal
) status
= RPC_S_OUT_OF_MEMORY
;
1607 RpcStringFreeW(&principal
);
1613 /***********************************************************************
1614 * RpcBindingInqAuthClientExW (RPCRT4.@)
1616 RPCRTAPI RPC_STATUS RPC_ENTRY
1617 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1618 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1619 ULONG
*AuthzSvc
, ULONG Flags
)
1623 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1624 AuthnSvc
, AuthzSvc
, Flags
);
1626 if (!ClientBinding
) ClientBinding
= I_RpcGetCurrentCallHandle();
1627 if (!ClientBinding
) return RPC_S_INVALID_BINDING
;
1629 bind
= ClientBinding
;
1630 if (!bind
->FromConn
) return RPC_S_INVALID_BINDING
;
1632 return rpcrt4_conn_inquire_auth_client(bind
->FromConn
, Privs
,
1633 ServerPrincName
, AuthnLevel
,
1634 AuthnSvc
, AuthzSvc
, Flags
);
1637 /***********************************************************************
1638 * RpcBindingServerFromClient (RPCRT4.@)
1640 RPCRTAPI RPC_STATUS RPC_ENTRY
1641 RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding
, RPC_BINDING_HANDLE
* ServerBinding
)
1643 RpcBinding
* bind
= ClientBinding
;
1644 RpcBinding
* NewBinding
;
1647 bind
= I_RpcGetCurrentCallHandle();
1650 return RPC_S_INVALID_BINDING
;
1652 RPCRT4_AllocBinding(&NewBinding
, TRUE
);
1653 NewBinding
->Protseq
= RPCRT4_strdupA(bind
->Protseq
);
1654 NewBinding
->NetworkAddr
= RPCRT4_strdupA(bind
->NetworkAddr
);
1656 *ServerBinding
= NewBinding
;
1661 /***********************************************************************
1662 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1664 RPCRTAPI RPC_STATUS RPC_ENTRY
1665 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
,
1666 ULONG AuthnLevel
, ULONG AuthnSvc
,
1667 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1668 RPC_SECURITY_QOS
*SecurityQos
)
1670 RpcBinding
* bind
= Binding
;
1674 ULONG package_count
;
1676 PSecPkgInfoA packages
;
1679 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1680 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1686 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1687 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1688 if (SecurityQos
->Version
>= 2)
1690 const RPC_SECURITY_QOS_V2_A
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_A
*)SecurityQos
;
1691 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1692 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1693 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1694 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1695 SecurityQos2
->u
.HttpCredentials
->Flags
,
1696 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1697 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1698 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1699 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1700 SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
);
1703 status
= RpcQualityOfService_Create(SecurityQos
, FALSE
, &bind
->QOS
);
1704 if (status
!= RPC_S_OK
)
1709 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1713 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1714 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1716 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1717 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1718 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1720 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1722 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1723 bind
->AuthInfo
= NULL
;
1727 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1729 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1730 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1733 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1734 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1736 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1737 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1740 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1743 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1744 return RPC_S_SEC_PKG_ERROR
;
1747 for (i
= 0; i
< package_count
; i
++)
1748 if (packages
[i
].wRPCID
== AuthnSvc
)
1751 if (i
== package_count
)
1753 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1754 FreeContextBuffer(packages
);
1755 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1758 TRACE("found package %s for service %u\n", packages
[i
].Name
, AuthnSvc
);
1759 r
= AcquireCredentialsHandleA(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1760 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1761 cbMaxToken
= packages
[i
].cbMaxToken
;
1762 FreeContextBuffer(packages
);
1763 if (r
== ERROR_SUCCESS
)
1765 RpcAuthInfo
*new_auth_info
;
1766 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1767 AuthIdentity
, &new_auth_info
);
1770 new_auth_info
->server_principal_name
= RPCRT4_strdupAtoW((char *)ServerPrincName
);
1771 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1773 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1774 bind
->AuthInfo
= new_auth_info
;
1778 RpcAuthInfo_Release(new_auth_info
);
1779 r
= RPC_S_OUT_OF_MEMORY
;
1783 FreeCredentialsHandle(&cred
);
1788 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1789 return RPC_S_SEC_PKG_ERROR
;
1793 /***********************************************************************
1794 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1796 RPCRTAPI RPC_STATUS RPC_ENTRY
1797 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1798 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1799 RPC_SECURITY_QOS
*SecurityQos
)
1801 RpcBinding
* bind
= Binding
;
1805 ULONG package_count
;
1807 PSecPkgInfoW packages
;
1810 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_w(ServerPrincName
),
1811 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1817 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1818 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1819 if (SecurityQos
->Version
>= 2)
1821 const RPC_SECURITY_QOS_V2_W
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_W
*)SecurityQos
;
1822 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1823 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1824 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1825 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1826 SecurityQos2
->u
.HttpCredentials
->Flags
,
1827 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1828 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1829 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1830 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1831 debugstr_w(SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
));
1834 status
= RpcQualityOfService_Create(SecurityQos
, TRUE
, &bind
->QOS
);
1835 if (status
!= RPC_S_OK
)
1840 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1844 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1845 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1847 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1848 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1849 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1851 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1853 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1854 bind
->AuthInfo
= NULL
;
1858 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1860 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1861 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1864 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1865 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1867 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1868 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1871 r
= EnumerateSecurityPackagesW(&package_count
, &packages
);
1874 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r
);
1875 return RPC_S_SEC_PKG_ERROR
;
1878 for (i
= 0; i
< package_count
; i
++)
1879 if (packages
[i
].wRPCID
== AuthnSvc
)
1882 if (i
== package_count
)
1884 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1885 FreeContextBuffer(packages
);
1886 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1889 TRACE("found package %s for service %u\n", debugstr_w(packages
[i
].Name
), AuthnSvc
);
1890 r
= AcquireCredentialsHandleW(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1891 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1892 cbMaxToken
= packages
[i
].cbMaxToken
;
1893 FreeContextBuffer(packages
);
1894 if (r
== ERROR_SUCCESS
)
1896 RpcAuthInfo
*new_auth_info
;
1897 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1898 AuthIdentity
, &new_auth_info
);
1901 new_auth_info
->server_principal_name
= RPCRT4_strdupW(ServerPrincName
);
1902 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1904 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1905 bind
->AuthInfo
= new_auth_info
;
1909 RpcAuthInfo_Release(new_auth_info
);
1910 r
= RPC_S_OUT_OF_MEMORY
;
1914 FreeCredentialsHandle(&cred
);
1919 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r
);
1920 return RPC_S_SEC_PKG_ERROR
;
1924 /***********************************************************************
1925 * RpcBindingSetAuthInfoA (RPCRT4.@)
1927 RPCRTAPI RPC_STATUS RPC_ENTRY
1928 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
, ULONG AuthnLevel
,
1929 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1931 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1932 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1933 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1936 /***********************************************************************
1937 * RpcBindingSetAuthInfoW (RPCRT4.@)
1939 RPCRTAPI RPC_STATUS RPC_ENTRY
1940 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1941 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1943 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_w(ServerPrincName
),
1944 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1945 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1948 /***********************************************************************
1949 * RpcBindingSetOption (RPCRT4.@)
1951 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG_PTR OptionValue
)
1953 TRACE("(%p, %d, %ld)\n", BindingHandle
, Option
, OptionValue
);
1957 case RPC_C_OPT_COOKIE_AUTH
:
1959 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*cookie
= (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*)OptionValue
;
1960 RpcBinding
*binding
= BindingHandle
;
1961 int len
= MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, NULL
, 0);
1964 if (!(str
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
)))) return RPC_S_OUT_OF_MEMORY
;
1965 MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, str
, len
);
1967 HeapFree(GetProcessHeap(), 0, binding
->CookieAuth
);
1968 binding
->CookieAuth
= str
;
1972 FIXME("option %u not supported\n", Option
);
1978 /***********************************************************************
1979 * I_RpcBindingInqLocalClientPID (RPCRT4.@)
1982 RPC_STATUS WINAPI
I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding
, ULONG
*ClientPID
)
1984 FIXME("%p %p: stub\n", ClientBinding
, ClientPID
);
1985 return RPC_S_INVALID_BINDING
;