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 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
680 BOOL endpoint_already_found
= FALSE
;
682 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
683 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
685 if (ObjUuid
) *ObjUuid
= NULL
;
686 if (Protseq
) *Protseq
= NULL
;
687 if (NetworkAddr
) *NetworkAddr
= NULL
;
688 if (Endpoint
) *Endpoint
= NULL
;
689 if (Options
) *Options
= NULL
;
691 data
= StringBinding
;
693 next
= string_binding_find_delimiterW(data
, '@');
697 RPC_WSTR str_uuid
= unescape_string_binding_componentW(data
, next
- data
);
698 status
= UuidFromStringW(str_uuid
, &uuid
);
699 if (status
!= RPC_S_OK
) {
700 HeapFree(GetProcessHeap(), 0, str_uuid
);
706 HeapFree(GetProcessHeap(), 0, str_uuid
);
710 next
= string_binding_find_delimiterW(data
, ':');
712 if (Protseq
) *Protseq
= unescape_string_binding_componentW(data
, next
- data
);
716 next
= string_binding_find_delimiterW(data
, '[');
721 if (NetworkAddr
) *NetworkAddr
= unescape_string_binding_componentW(data
, next
- data
);
723 close
= string_binding_find_delimiterW(data
, ']');
724 if (!close
) goto fail
;
726 /* tokenize options */
727 while (data
< close
) {
728 next
= string_binding_find_delimiterW(data
, ',');
729 if (!next
|| next
> close
) next
= close
;
730 /* FIXME: this is kind of inefficient */
731 opt
= unescape_string_binding_componentW(data
, next
- data
);
735 next
= string_binding_find_delimiterW(opt
, '=');
737 /* not an option, must be an endpoint */
738 if (endpoint_already_found
) goto fail
;
739 if (Endpoint
) *Endpoint
= opt
;
740 else HeapFree(GetProcessHeap(), 0, opt
);
741 endpoint_already_found
= TRUE
;
743 if (wcsncmp(opt
, ep_opt
, lstrlenW(ep_opt
)) == 0) {
744 /* endpoint option */
745 if (endpoint_already_found
) goto fail
;
746 if (Endpoint
) *Endpoint
= unescape_string_binding_componentW(next
+1, -1);
747 HeapFree(GetProcessHeap(), 0, opt
);
748 endpoint_already_found
= TRUE
;
753 /* FIXME: this is kind of inefficient */
754 *Options
= RPCRT4_strconcatW(*Options
, opt
);
755 HeapFree(GetProcessHeap(), 0, opt
);
759 HeapFree(GetProcessHeap(), 0, opt
);
765 if (*data
) goto fail
;
766 } else if (NetworkAddr
)
767 *NetworkAddr
= unescape_string_binding_componentW(data
, -1);
772 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
773 if (Protseq
) RpcStringFreeW(Protseq
);
774 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
775 if (Endpoint
) RpcStringFreeW(Endpoint
);
776 if (Options
) RpcStringFreeW(Options
);
777 return RPC_S_INVALID_STRING_BINDING
;
780 /***********************************************************************
781 * RpcBindingFree (RPCRT4.@)
783 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
786 TRACE("(%p) = %p\n", Binding
, *Binding
);
788 status
= RPCRT4_ReleaseBinding(*Binding
);
790 status
= RPC_S_INVALID_BINDING
;
791 if (status
== RPC_S_OK
) *Binding
= NULL
;
795 /***********************************************************************
796 * RpcBindingVectorFree (RPCRT4.@)
798 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
802 TRACE("(%p)\n", BindingVector
);
803 for (c
=0; c
<(*BindingVector
)->Count
; c
++) RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
804 HeapFree(GetProcessHeap(), 0, *BindingVector
);
805 *BindingVector
= NULL
;
809 /***********************************************************************
810 * RpcBindingInqObject (RPCRT4.@)
812 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
814 RpcBinding
* bind
= Binding
;
816 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
817 *ObjectUuid
= bind
->ObjectUuid
;
821 /***********************************************************************
822 * RpcBindingSetObject (RPCRT4.@)
824 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
826 RpcBinding
* bind
= Binding
;
828 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
829 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
830 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
833 /***********************************************************************
834 * RpcBindingFromStringBindingA (RPCRT4.@)
836 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( RPC_CSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
839 RpcBinding
* bind
= NULL
;
840 RPC_CSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
843 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
845 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
846 &NetworkAddr
, &Endpoint
, &Options
);
847 if (ret
!= RPC_S_OK
) return ret
;
849 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
852 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
853 if (ret
== RPC_S_OK
) {
854 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
856 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
859 *Binding
= (RPC_BINDING_HANDLE
)bind
;
861 RPCRT4_ReleaseBinding(bind
);
864 RpcStringFreeA(&Options
);
865 RpcStringFreeA(&Endpoint
);
866 RpcStringFreeA(&NetworkAddr
);
867 RpcStringFreeA(&Protseq
);
868 RpcStringFreeA(&ObjectUuid
);
873 /***********************************************************************
874 * RpcBindingFromStringBindingW (RPCRT4.@)
876 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( RPC_WSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
879 RpcBinding
* bind
= NULL
;
880 RPC_WSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
883 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
885 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
886 &NetworkAddr
, &Endpoint
, &Options
);
887 if (ret
!= RPC_S_OK
) return ret
;
889 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
892 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
893 if (ret
== RPC_S_OK
) {
894 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
896 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
899 *Binding
= (RPC_BINDING_HANDLE
)bind
;
901 RPCRT4_ReleaseBinding(bind
);
904 RpcStringFreeW(&Options
);
905 RpcStringFreeW(&Endpoint
);
906 RpcStringFreeW(&NetworkAddr
);
907 RpcStringFreeW(&Protseq
);
908 RpcStringFreeW(&ObjectUuid
);
913 /***********************************************************************
914 * RpcBindingToStringBindingA (RPCRT4.@)
916 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*StringBinding
)
919 RpcBinding
* bind
= Binding
;
922 TRACE("(%p,%p)\n", Binding
, StringBinding
);
924 if (UuidIsNil(&bind
->ObjectUuid
, &ret
))
928 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
929 if (ret
!= RPC_S_OK
) return ret
;
932 ret
= RpcStringBindingComposeA(ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
933 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
935 RpcStringFreeA(&ObjectUuid
);
940 /***********************************************************************
941 * RpcBindingToStringBindingW (RPCRT4.@)
943 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*StringBinding
)
946 unsigned char *str
= NULL
;
947 TRACE("(%p,%p)\n", Binding
, StringBinding
);
948 ret
= RpcBindingToStringBindingA(Binding
, &str
);
949 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
950 RpcStringFreeA(&str
);
954 /***********************************************************************
955 * I_RpcBindingInqTransportType (RPCRT4.@)
957 RPC_STATUS WINAPI
I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding
, unsigned int * Type
)
960 FIXME( "(%p,%p): stub\n", Binding
, Type
);
961 *Type
= TRANSPORT_TYPE_LPC
;
965 /***********************************************************************
966 * I_RpcBindingSetAsync (RPCRT4.@)
968 * Exists in win9x and winNT, but with different number of arguments
969 * (9x version has 3 arguments, NT has 2).
971 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
973 RpcBinding
* bind
= Binding
;
975 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
977 bind
->BlockingFn
= BlockingFn
;
982 /***********************************************************************
983 * RpcBindingCopy (RPCRT4.@)
985 RPC_STATUS RPC_ENTRY
RpcBindingCopy(
986 RPC_BINDING_HANDLE SourceBinding
,
987 RPC_BINDING_HANDLE
* DestinationBinding
)
989 RpcBinding
*DestBinding
;
990 RpcBinding
*SrcBinding
= SourceBinding
;
993 TRACE("(%p, %p)\n", SourceBinding
, DestinationBinding
);
995 status
= RPCRT4_AllocBinding(&DestBinding
, SrcBinding
->server
);
996 if (status
!= RPC_S_OK
) return status
;
998 DestBinding
->ObjectUuid
= SrcBinding
->ObjectUuid
;
999 DestBinding
->BlockingFn
= SrcBinding
->BlockingFn
;
1000 DestBinding
->Protseq
= RPCRT4_strndupA(SrcBinding
->Protseq
, -1);
1001 DestBinding
->NetworkAddr
= RPCRT4_strndupA(SrcBinding
->NetworkAddr
, -1);
1002 DestBinding
->Endpoint
= RPCRT4_strndupA(SrcBinding
->Endpoint
, -1);
1003 DestBinding
->NetworkOptions
= RPCRT4_strdupW(SrcBinding
->NetworkOptions
);
1004 DestBinding
->CookieAuth
= RPCRT4_strdupW(SrcBinding
->CookieAuth
);
1005 if (SrcBinding
->Assoc
) SrcBinding
->Assoc
->refs
++;
1006 DestBinding
->Assoc
= SrcBinding
->Assoc
;
1008 if (SrcBinding
->AuthInfo
) RpcAuthInfo_AddRef(SrcBinding
->AuthInfo
);
1009 DestBinding
->AuthInfo
= SrcBinding
->AuthInfo
;
1010 if (SrcBinding
->QOS
) RpcQualityOfService_AddRef(SrcBinding
->QOS
);
1011 DestBinding
->QOS
= SrcBinding
->QOS
;
1013 *DestinationBinding
= DestBinding
;
1017 /***********************************************************************
1018 * RpcBindingReset (RPCRT4.@)
1020 RPC_STATUS RPC_ENTRY
RpcBindingReset(RPC_BINDING_HANDLE Binding
)
1022 RpcBinding
*bind
= Binding
;
1024 TRACE("(%p)\n", Binding
);
1026 RPCRT4_strfree(bind
->Endpoint
);
1027 bind
->Endpoint
= NULL
;
1028 if (bind
->Assoc
) RpcAssoc_Release(bind
->Assoc
);
1034 /***********************************************************************
1035 * RpcImpersonateClient (RPCRT4.@)
1037 * Impersonates the client connected via a binding handle so that security
1038 * checks are done in the context of the client.
1041 * BindingHandle [I] Handle to the binding to the client.
1044 * Success: RPS_S_OK.
1045 * Failure: RPC_STATUS value.
1049 * If BindingHandle is NULL then the function impersonates the client
1050 * connected to the binding handle of the current thread.
1052 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
1056 TRACE("(%p)\n", BindingHandle
);
1058 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1059 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1061 bind
= BindingHandle
;
1063 return rpcrt4_conn_impersonate_client(bind
->FromConn
);
1064 return RPC_S_WRONG_KIND_OF_BINDING
;
1067 /***********************************************************************
1068 * RpcRevertToSelfEx (RPCRT4.@)
1070 * Stops impersonating the client connected to the binding handle so that security
1071 * checks are no longer done in the context of the client.
1074 * BindingHandle [I] Handle to the binding to the client.
1077 * Success: RPS_S_OK.
1078 * Failure: RPC_STATUS value.
1082 * If BindingHandle is NULL then the function stops impersonating the client
1083 * connected to the binding handle of the current thread.
1085 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
1089 TRACE("(%p)\n", BindingHandle
);
1091 if (!BindingHandle
) BindingHandle
= I_RpcGetCurrentCallHandle();
1092 if (!BindingHandle
) return RPC_S_INVALID_BINDING
;
1094 bind
= BindingHandle
;
1096 return rpcrt4_conn_revert_to_self(bind
->FromConn
);
1097 return RPC_S_WRONG_KIND_OF_BINDING
;
1100 static inline BOOL
has_nt_auth_identity(ULONG AuthnLevel
)
1104 case RPC_C_AUTHN_GSS_NEGOTIATE
:
1105 case RPC_C_AUTHN_WINNT
:
1106 case RPC_C_AUTHN_GSS_KERBEROS
:
1113 RPC_STATUS
RpcAuthInfo_Create(ULONG AuthnLevel
, ULONG AuthnSvc
,
1114 CredHandle cred
, TimeStamp exp
,
1116 RPC_AUTH_IDENTITY_HANDLE identity
,
1119 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
1121 return RPC_S_OUT_OF_MEMORY
;
1124 AuthInfo
->AuthnLevel
= AuthnLevel
;
1125 AuthInfo
->AuthnSvc
= AuthnSvc
;
1126 AuthInfo
->cred
= cred
;
1127 AuthInfo
->exp
= exp
;
1128 AuthInfo
->cbMaxToken
= cbMaxToken
;
1129 AuthInfo
->identity
= identity
;
1130 AuthInfo
->server_principal_name
= NULL
;
1132 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1133 * enable better matching in RpcAuthInfo_IsEqual */
1134 if (identity
&& has_nt_auth_identity(AuthnSvc
))
1136 const SEC_WINNT_AUTH_IDENTITY_W
*nt_identity
= identity
;
1137 AuthInfo
->nt_identity
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
->nt_identity
));
1138 if (!AuthInfo
->nt_identity
)
1140 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1141 return RPC_S_OUT_OF_MEMORY
;
1144 AuthInfo
->nt_identity
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1145 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1146 AuthInfo
->nt_identity
->User
= RPCRT4_strndupW(nt_identity
->User
, nt_identity
->UserLength
);
1148 AuthInfo
->nt_identity
->User
= RPCRT4_strndupAtoW((const char *)nt_identity
->User
, nt_identity
->UserLength
);
1149 AuthInfo
->nt_identity
->UserLength
= nt_identity
->UserLength
;
1150 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1151 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupW(nt_identity
->Domain
, nt_identity
->DomainLength
);
1153 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupAtoW((const char *)nt_identity
->Domain
, nt_identity
->DomainLength
);
1154 AuthInfo
->nt_identity
->DomainLength
= nt_identity
->DomainLength
;
1155 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1156 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupW(nt_identity
->Password
, nt_identity
->PasswordLength
);
1158 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupAtoW((const char *)nt_identity
->Password
, nt_identity
->PasswordLength
);
1159 AuthInfo
->nt_identity
->PasswordLength
= nt_identity
->PasswordLength
;
1161 if ((nt_identity
->User
&& !AuthInfo
->nt_identity
->User
) ||
1162 (nt_identity
->Domain
&& !AuthInfo
->nt_identity
->Domain
) ||
1163 (nt_identity
->Password
&& !AuthInfo
->nt_identity
->Password
))
1165 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1166 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1167 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1168 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1169 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1170 return RPC_S_OUT_OF_MEMORY
;
1174 AuthInfo
->nt_identity
= NULL
;
1179 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
1181 return InterlockedIncrement(&AuthInfo
->refs
);
1184 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
1186 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
1190 FreeCredentialsHandle(&AuthInfo
->cred
);
1191 if (AuthInfo
->nt_identity
)
1193 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1194 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1195 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1196 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1198 HeapFree(GetProcessHeap(), 0, AuthInfo
->server_principal_name
);
1199 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1205 BOOL
RpcAuthInfo_IsEqual(const RpcAuthInfo
*AuthInfo1
, const RpcAuthInfo
*AuthInfo2
)
1207 if (AuthInfo1
== AuthInfo2
)
1210 if (!AuthInfo1
|| !AuthInfo2
)
1213 if ((AuthInfo1
->AuthnLevel
!= AuthInfo2
->AuthnLevel
) ||
1214 (AuthInfo1
->AuthnSvc
!= AuthInfo2
->AuthnSvc
))
1217 if (AuthInfo1
->identity
== AuthInfo2
->identity
)
1220 if (!AuthInfo1
->identity
|| !AuthInfo2
->identity
)
1223 if (has_nt_auth_identity(AuthInfo1
->AuthnSvc
))
1225 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= AuthInfo1
->nt_identity
;
1226 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= AuthInfo2
->nt_identity
;
1227 /* compare user names */
1228 if (identity1
->UserLength
!= identity2
->UserLength
||
1229 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1231 /* compare domain names */
1232 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1233 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1235 /* compare passwords */
1236 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1237 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1246 static RPC_STATUS
RpcQualityOfService_Create(const RPC_SECURITY_QOS
*qos_src
, BOOL unicode
, RpcQualityOfService
**qos_dst
)
1248 RpcQualityOfService
*qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
));
1251 return RPC_S_OUT_OF_RESOURCES
;
1254 qos
->qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
->qos
));
1255 if (!qos
->qos
) goto error
;
1256 qos
->qos
->Version
= qos_src
->Version
;
1257 qos
->qos
->Capabilities
= qos_src
->Capabilities
;
1258 qos
->qos
->IdentityTracking
= qos_src
->IdentityTracking
;
1259 qos
->qos
->ImpersonationType
= qos_src
->ImpersonationType
;
1260 qos
->qos
->AdditionalSecurityInfoType
= 0;
1262 if (qos_src
->Version
>= 2)
1264 const RPC_SECURITY_QOS_V2_W
*qos_src2
= (const RPC_SECURITY_QOS_V2_W
*)qos_src
;
1265 qos
->qos
->AdditionalSecurityInfoType
= qos_src2
->AdditionalSecurityInfoType
;
1266 if (qos_src2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1268 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_src
= qos_src2
->u
.HttpCredentials
;
1269 RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_dst
;
1271 http_credentials_dst
= HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst
));
1272 qos
->qos
->u
.HttpCredentials
= http_credentials_dst
;
1273 if (!http_credentials_dst
) goto error
;
1274 http_credentials_dst
->TransportCredentials
= NULL
;
1275 http_credentials_dst
->Flags
= http_credentials_src
->Flags
;
1276 http_credentials_dst
->AuthenticationTarget
= http_credentials_src
->AuthenticationTarget
;
1277 http_credentials_dst
->NumberOfAuthnSchemes
= http_credentials_src
->NumberOfAuthnSchemes
;
1278 http_credentials_dst
->AuthnSchemes
= NULL
;
1279 http_credentials_dst
->ServerCertificateSubject
= NULL
;
1280 if (http_credentials_src
->TransportCredentials
)
1282 SEC_WINNT_AUTH_IDENTITY_W
*cred_dst
;
1283 cred_dst
= http_credentials_dst
->TransportCredentials
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cred_dst
));
1284 if (!cred_dst
) goto error
;
1285 cred_dst
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1288 const SEC_WINNT_AUTH_IDENTITY_W
*cred_src
= http_credentials_src
->TransportCredentials
;
1289 cred_dst
->UserLength
= cred_src
->UserLength
;
1290 cred_dst
->PasswordLength
= cred_src
->PasswordLength
;
1291 cred_dst
->DomainLength
= cred_src
->DomainLength
;
1292 cred_dst
->User
= RPCRT4_strndupW(cred_src
->User
, cred_src
->UserLength
);
1293 cred_dst
->Password
= RPCRT4_strndupW(cred_src
->Password
, cred_src
->PasswordLength
);
1294 cred_dst
->Domain
= RPCRT4_strndupW(cred_src
->Domain
, cred_src
->DomainLength
);
1298 const SEC_WINNT_AUTH_IDENTITY_A
*cred_src
= (const SEC_WINNT_AUTH_IDENTITY_A
*)http_credentials_src
->TransportCredentials
;
1299 cred_dst
->UserLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, NULL
, 0);
1300 cred_dst
->DomainLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, NULL
, 0);
1301 cred_dst
->PasswordLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, NULL
, 0);
1302 cred_dst
->User
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->UserLength
* sizeof(WCHAR
));
1303 cred_dst
->Password
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->PasswordLength
* sizeof(WCHAR
));
1304 cred_dst
->Domain
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->DomainLength
* sizeof(WCHAR
));
1305 if (!cred_dst
->Password
|| !cred_dst
->Domain
) goto error
;
1306 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, cred_dst
->User
, cred_dst
->UserLength
);
1307 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, cred_dst
->Domain
, cred_dst
->DomainLength
);
1308 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, cred_dst
->Password
, cred_dst
->PasswordLength
);
1311 if (http_credentials_src
->NumberOfAuthnSchemes
)
1313 http_credentials_dst
->AuthnSchemes
= HeapAlloc(GetProcessHeap(), 0, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1314 if (!http_credentials_dst
->AuthnSchemes
) goto error
;
1315 memcpy(http_credentials_dst
->AuthnSchemes
, http_credentials_src
->AuthnSchemes
, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1317 if (http_credentials_src
->ServerCertificateSubject
)
1320 http_credentials_dst
->ServerCertificateSubject
=
1321 RPCRT4_strndupW(http_credentials_src
->ServerCertificateSubject
,
1322 lstrlenW(http_credentials_src
->ServerCertificateSubject
));
1324 http_credentials_dst
->ServerCertificateSubject
=
1325 RPCRT4_strdupAtoW((char *)http_credentials_src
->ServerCertificateSubject
);
1326 if (!http_credentials_dst
->ServerCertificateSubject
) goto error
;
1336 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
&&
1337 qos
->qos
->u
.HttpCredentials
)
1339 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1341 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1342 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1343 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1344 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1346 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1347 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1348 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1350 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1352 HeapFree(GetProcessHeap(), 0, qos
);
1353 return RPC_S_OUT_OF_RESOURCES
;
1356 ULONG
RpcQualityOfService_AddRef(RpcQualityOfService
*qos
)
1358 return InterlockedIncrement(&qos
->refs
);
1361 ULONG
RpcQualityOfService_Release(RpcQualityOfService
*qos
)
1363 ULONG refs
= InterlockedDecrement(&qos
->refs
);
1367 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1369 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1371 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1372 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1373 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1374 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1376 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1377 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1378 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1380 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1381 HeapFree(GetProcessHeap(), 0, qos
);
1386 BOOL
RpcQualityOfService_IsEqual(const RpcQualityOfService
*qos1
, const RpcQualityOfService
*qos2
)
1394 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
1395 qos1
->qos
->Capabilities
, qos1
->qos
->IdentityTracking
,
1396 qos1
->qos
->ImpersonationType
, qos1
->qos
->AdditionalSecurityInfoType
,
1397 qos2
->qos
->Capabilities
, qos2
->qos
->IdentityTracking
,
1398 qos2
->qos
->ImpersonationType
, qos2
->qos
->AdditionalSecurityInfoType
);
1400 if ((qos1
->qos
->Capabilities
!= qos2
->qos
->Capabilities
) ||
1401 (qos1
->qos
->IdentityTracking
!= qos2
->qos
->IdentityTracking
) ||
1402 (qos1
->qos
->ImpersonationType
!= qos2
->qos
->ImpersonationType
) ||
1403 (qos1
->qos
->AdditionalSecurityInfoType
!= qos2
->qos
->AdditionalSecurityInfoType
))
1406 if (qos1
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1408 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials1
= qos1
->qos
->u
.HttpCredentials
;
1409 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials2
= qos2
->qos
->u
.HttpCredentials
;
1411 if (http_credentials1
->Flags
!= http_credentials2
->Flags
)
1414 if (http_credentials1
->AuthenticationTarget
!= http_credentials2
->AuthenticationTarget
)
1417 if (http_credentials1
->NumberOfAuthnSchemes
!= http_credentials2
->NumberOfAuthnSchemes
)
1420 if ((!http_credentials1
->AuthnSchemes
&& http_credentials2
->AuthnSchemes
) ||
1421 (http_credentials1
->AuthnSchemes
&& !http_credentials2
->AuthnSchemes
))
1424 if (memcmp(http_credentials1
->AuthnSchemes
, http_credentials2
->AuthnSchemes
,
1425 http_credentials1
->NumberOfAuthnSchemes
* sizeof(http_credentials1
->AuthnSchemes
[0])))
1428 /* server certificate subject not currently used */
1430 if (http_credentials1
->TransportCredentials
!= http_credentials2
->TransportCredentials
)
1432 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= http_credentials1
->TransportCredentials
;
1433 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= http_credentials2
->TransportCredentials
;
1435 if (!identity1
|| !identity2
)
1438 /* compare user names */
1439 if (identity1
->UserLength
!= identity2
->UserLength
||
1440 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1442 /* compare domain names */
1443 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1444 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1446 /* compare passwords */
1447 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1448 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1456 /***********************************************************************
1457 * RpcRevertToSelf (RPCRT4.@)
1459 RPC_STATUS WINAPI
RpcRevertToSelf(void)
1462 return RpcRevertToSelfEx(NULL
);
1465 /***********************************************************************
1466 * RpcMgmtSetComTimeout (RPCRT4.@)
1468 RPC_STATUS WINAPI
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle
, unsigned int Timeout
)
1470 FIXME("(%p, %d): stub\n", BindingHandle
, Timeout
);
1474 /***********************************************************************
1475 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1477 RPCRTAPI RPC_STATUS RPC_ENTRY
1478 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1479 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1480 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1485 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1486 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1488 status
= RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
? &principal
: NULL
, AuthnLevel
,
1489 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1490 if (status
== RPC_S_OK
&& ServerPrincName
)
1492 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1493 RpcStringFreeW(&principal
);
1494 if (!*ServerPrincName
) return RPC_S_OUT_OF_MEMORY
;
1500 /***********************************************************************
1501 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1503 RPCRTAPI RPC_STATUS RPC_ENTRY
1504 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1505 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1506 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1508 RpcBinding
*bind
= Binding
;
1510 TRACE("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1511 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1513 if (!bind
->AuthInfo
) return RPC_S_BINDING_HAS_NO_AUTH
;
1517 FIXME("QOS not implemented\n");
1518 return RPC_S_INVALID_BINDING
;
1521 if (ServerPrincName
)
1523 if (bind
->AuthInfo
->server_principal_name
)
1525 *ServerPrincName
= RPCRT4_strdupW(bind
->AuthInfo
->server_principal_name
);
1526 if (!*ServerPrincName
) return RPC_S_OUT_OF_MEMORY
;
1528 else *ServerPrincName
= NULL
;
1530 if (AuthnLevel
) *AuthnLevel
= bind
->AuthInfo
->AuthnLevel
;
1531 if (AuthnSvc
) *AuthnSvc
= bind
->AuthInfo
->AuthnSvc
;
1532 if (AuthIdentity
) *AuthIdentity
= bind
->AuthInfo
->identity
;
1535 FIXME("authorization service not implemented\n");
1536 *AuthzSvc
= RPC_C_AUTHZ_NONE
;
1542 /***********************************************************************
1543 * RpcBindingInqAuthInfoA (RPCRT4.@)
1545 RPCRTAPI RPC_STATUS RPC_ENTRY
1546 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1547 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1549 return RpcBindingInqAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1553 /***********************************************************************
1554 * RpcBindingInqAuthInfoW (RPCRT4.@)
1556 RPCRTAPI RPC_STATUS RPC_ENTRY
1557 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1558 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1560 return RpcBindingInqAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
,
1564 /***********************************************************************
1565 * RpcBindingInqAuthClientA (RPCRT4.@)
1567 RPCRTAPI RPC_STATUS RPC_ENTRY
1568 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1569 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1572 return RpcBindingInqAuthClientExA(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1573 AuthnSvc
, AuthzSvc
, 0);
1576 /***********************************************************************
1577 * RpcBindingInqAuthClientW (RPCRT4.@)
1579 RPCRTAPI RPC_STATUS RPC_ENTRY
1580 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1581 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1584 return RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1585 AuthnSvc
, AuthzSvc
, 0);
1588 /***********************************************************************
1589 * RpcBindingInqAuthClientExA (RPCRT4.@)
1591 RPCRTAPI RPC_STATUS RPC_ENTRY
1592 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1593 RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1594 ULONG
*AuthzSvc
, ULONG Flags
)
1599 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1600 AuthnSvc
, AuthzSvc
, Flags
);
1602 status
= RpcBindingInqAuthClientExW(ClientBinding
, Privs
, ServerPrincName
? &principal
: NULL
,
1603 AuthnLevel
, AuthnSvc
, AuthzSvc
, Flags
);
1604 if (status
== RPC_S_OK
&& ServerPrincName
)
1606 *ServerPrincName
= (RPC_CSTR
)RPCRT4_strdupWtoA(principal
);
1607 if (!*ServerPrincName
&& principal
) status
= RPC_S_OUT_OF_MEMORY
;
1608 RpcStringFreeW(&principal
);
1614 /***********************************************************************
1615 * RpcBindingInqAuthClientExW (RPCRT4.@)
1617 RPCRTAPI RPC_STATUS RPC_ENTRY
1618 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding
, RPC_AUTHZ_HANDLE
*Privs
,
1619 RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
, ULONG
*AuthnSvc
,
1620 ULONG
*AuthzSvc
, ULONG Flags
)
1624 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding
, Privs
, ServerPrincName
, AuthnLevel
,
1625 AuthnSvc
, AuthzSvc
, Flags
);
1627 if (!ClientBinding
) ClientBinding
= I_RpcGetCurrentCallHandle();
1628 if (!ClientBinding
) return RPC_S_INVALID_BINDING
;
1630 bind
= ClientBinding
;
1631 if (!bind
->FromConn
) return RPC_S_INVALID_BINDING
;
1633 return rpcrt4_conn_inquire_auth_client(bind
->FromConn
, Privs
,
1634 ServerPrincName
, AuthnLevel
,
1635 AuthnSvc
, AuthzSvc
, Flags
);
1638 /***********************************************************************
1639 * RpcBindingServerFromClient (RPCRT4.@)
1641 RPCRTAPI RPC_STATUS RPC_ENTRY
1642 RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding
, RPC_BINDING_HANDLE
* ServerBinding
)
1644 RpcBinding
* bind
= ClientBinding
;
1645 RpcBinding
* NewBinding
;
1648 bind
= I_RpcGetCurrentCallHandle();
1651 return RPC_S_INVALID_BINDING
;
1653 RPCRT4_AllocBinding(&NewBinding
, TRUE
);
1654 NewBinding
->Protseq
= RPCRT4_strdupA(bind
->Protseq
);
1655 NewBinding
->NetworkAddr
= RPCRT4_strdupA(bind
->NetworkAddr
);
1657 *ServerBinding
= NewBinding
;
1662 /***********************************************************************
1663 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1665 RPCRTAPI RPC_STATUS RPC_ENTRY
1666 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
,
1667 ULONG AuthnLevel
, ULONG AuthnSvc
,
1668 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1669 RPC_SECURITY_QOS
*SecurityQos
)
1671 RpcBinding
* bind
= Binding
;
1675 ULONG package_count
;
1677 PSecPkgInfoA packages
;
1680 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1681 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1687 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1688 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1689 if (SecurityQos
->Version
>= 2)
1691 const RPC_SECURITY_QOS_V2_A
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_A
*)SecurityQos
;
1692 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1693 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1694 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1695 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1696 SecurityQos2
->u
.HttpCredentials
->Flags
,
1697 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1698 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1699 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1700 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1701 SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
);
1704 status
= RpcQualityOfService_Create(SecurityQos
, FALSE
, &bind
->QOS
);
1705 if (status
!= RPC_S_OK
)
1710 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1714 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1715 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1717 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1718 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1719 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1721 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1723 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1724 bind
->AuthInfo
= NULL
;
1728 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1730 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1731 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1734 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1735 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1737 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1738 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1741 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1744 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1745 return RPC_S_SEC_PKG_ERROR
;
1748 for (i
= 0; i
< package_count
; i
++)
1749 if (packages
[i
].wRPCID
== AuthnSvc
)
1752 if (i
== package_count
)
1754 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1755 FreeContextBuffer(packages
);
1756 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1759 TRACE("found package %s for service %u\n", packages
[i
].Name
, AuthnSvc
);
1760 r
= AcquireCredentialsHandleA(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1761 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1762 cbMaxToken
= packages
[i
].cbMaxToken
;
1763 FreeContextBuffer(packages
);
1764 if (r
== ERROR_SUCCESS
)
1766 RpcAuthInfo
*new_auth_info
;
1767 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1768 AuthIdentity
, &new_auth_info
);
1771 new_auth_info
->server_principal_name
= RPCRT4_strdupAtoW((char *)ServerPrincName
);
1772 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1774 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1775 bind
->AuthInfo
= new_auth_info
;
1779 RpcAuthInfo_Release(new_auth_info
);
1780 r
= RPC_S_OUT_OF_MEMORY
;
1784 FreeCredentialsHandle(&cred
);
1789 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1790 return RPC_S_SEC_PKG_ERROR
;
1794 /***********************************************************************
1795 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1797 RPCRTAPI RPC_STATUS RPC_ENTRY
1798 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1799 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1800 RPC_SECURITY_QOS
*SecurityQos
)
1802 RpcBinding
* bind
= Binding
;
1806 ULONG package_count
;
1808 PSecPkgInfoW packages
;
1811 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_w(ServerPrincName
),
1812 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1818 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1819 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1820 if (SecurityQos
->Version
>= 2)
1822 const RPC_SECURITY_QOS_V2_W
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_W
*)SecurityQos
;
1823 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2
->AdditionalSecurityInfoType
);
1824 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1825 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1826 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1827 SecurityQos2
->u
.HttpCredentials
->Flags
,
1828 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1829 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1830 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1831 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
? *SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
: 0,
1832 debugstr_w(SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
));
1835 status
= RpcQualityOfService_Create(SecurityQos
, TRUE
, &bind
->QOS
);
1836 if (status
!= RPC_S_OK
)
1841 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1845 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1846 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1848 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1849 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1850 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1852 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1854 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1855 bind
->AuthInfo
= NULL
;
1859 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1861 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1862 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1865 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1866 if (AuthzSvr
&& AuthnSvc
!= RPC_C_AUTHN_WINNT
)
1868 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1869 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1872 r
= EnumerateSecurityPackagesW(&package_count
, &packages
);
1875 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r
);
1876 return RPC_S_SEC_PKG_ERROR
;
1879 for (i
= 0; i
< package_count
; i
++)
1880 if (packages
[i
].wRPCID
== AuthnSvc
)
1883 if (i
== package_count
)
1885 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1886 FreeContextBuffer(packages
);
1887 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1890 TRACE("found package %s for service %u\n", debugstr_w(packages
[i
].Name
), AuthnSvc
);
1891 r
= AcquireCredentialsHandleW(NULL
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1892 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1893 cbMaxToken
= packages
[i
].cbMaxToken
;
1894 FreeContextBuffer(packages
);
1895 if (r
== ERROR_SUCCESS
)
1897 RpcAuthInfo
*new_auth_info
;
1898 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1899 AuthIdentity
, &new_auth_info
);
1902 new_auth_info
->server_principal_name
= RPCRT4_strdupW(ServerPrincName
);
1903 if (!ServerPrincName
|| new_auth_info
->server_principal_name
)
1905 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1906 bind
->AuthInfo
= new_auth_info
;
1910 RpcAuthInfo_Release(new_auth_info
);
1911 r
= RPC_S_OUT_OF_MEMORY
;
1915 FreeCredentialsHandle(&cred
);
1920 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r
);
1921 return RPC_S_SEC_PKG_ERROR
;
1925 /***********************************************************************
1926 * RpcBindingSetAuthInfoA (RPCRT4.@)
1928 RPCRTAPI RPC_STATUS RPC_ENTRY
1929 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
, ULONG AuthnLevel
,
1930 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1932 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1933 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1934 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1937 /***********************************************************************
1938 * RpcBindingSetAuthInfoW (RPCRT4.@)
1940 RPCRTAPI RPC_STATUS RPC_ENTRY
1941 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1942 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1944 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_w(ServerPrincName
),
1945 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1946 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1949 /***********************************************************************
1950 * RpcBindingSetOption (RPCRT4.@)
1952 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG_PTR OptionValue
)
1954 TRACE("(%p, %d, %ld)\n", BindingHandle
, Option
, OptionValue
);
1958 case RPC_C_OPT_COOKIE_AUTH
:
1960 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*cookie
= (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR
*)OptionValue
;
1961 RpcBinding
*binding
= BindingHandle
;
1962 int len
= MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, NULL
, 0);
1965 if (!(str
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
)))) return RPC_S_OUT_OF_MEMORY
;
1966 MultiByteToWideChar(CP_ACP
, 0, cookie
->Buffer
, cookie
->BufferSize
, str
, len
);
1968 HeapFree(GetProcessHeap(), 0, binding
->CookieAuth
);
1969 binding
->CookieAuth
= str
;
1973 FIXME("option %u not supported\n", Option
);
1979 /***********************************************************************
1980 * I_RpcBindingInqLocalClientPID (RPCRT4.@)
1983 RPC_STATUS WINAPI
I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding
, ULONG
*ClientPID
)
1985 FIXME("%p %p: stub\n", ClientBinding
, ClientPID
);
1986 return RPC_S_INVALID_BINDING
;