include: Be consistent in naming regarding MSF's block.
[wine.git] / dlls / rpcrt4 / rpc_binding.c
blobfec9aa999aaaf1dcaeaa4ea64485e81f642b5f29
1 /*
2 * RPC binding API
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
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winnls.h"
33 #include "winerror.h"
34 #include "winternl.h"
36 #include "rpc.h"
37 #include "rpcndr.h"
39 #include "wine/debug.h"
41 #include "rpc_binding.h"
42 #include "rpc_assoc.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
46 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
48 DWORD len;
49 LPSTR s;
50 if (!src) return NULL;
51 if (slen == -1) slen = strlen(src);
52 len = slen;
53 s = malloc(len + 1);
54 memcpy(s, src, len);
55 s[len] = 0;
56 return s;
59 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
61 DWORD len;
62 LPSTR s;
63 if (!src) return NULL;
64 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
65 s = malloc(len);
66 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
67 return s;
70 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
72 DWORD len;
73 LPWSTR s;
74 if (!src) return NULL;
75 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
76 s = malloc(len * sizeof(WCHAR));
77 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
78 return s;
81 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
83 DWORD len;
84 LPWSTR s;
85 if (!src) return NULL;
86 len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
87 s = malloc(len * sizeof(WCHAR));
88 MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
89 return s;
92 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
94 DWORD len;
95 LPWSTR s;
96 if (!src) return NULL;
97 if (slen == -1) slen = lstrlenW(src);
98 len = slen;
99 s = malloc((len + 1) * sizeof(WCHAR));
100 memcpy(s, src, len*sizeof(WCHAR));
101 s[len] = 0;
102 return s;
105 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
107 RpcBinding* NewBinding;
109 NewBinding = calloc(1, sizeof(RpcBinding));
110 NewBinding->refs = 1;
111 NewBinding->server = server;
113 *Binding = NewBinding;
115 return RPC_S_OK;
118 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
120 RpcBinding* NewBinding;
122 RPCRT4_AllocBinding(&NewBinding, server);
123 NewBinding->Protseq = strdup(Protseq);
125 TRACE("binding: %p\n", NewBinding);
126 *Binding = NewBinding;
128 return RPC_S_OK;
131 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
133 RpcBinding* NewBinding;
135 RPCRT4_AllocBinding(&NewBinding, server);
136 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
138 TRACE("binding: %p\n", NewBinding);
139 *Binding = NewBinding;
141 return RPC_S_OK;
144 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
145 LPCSTR Endpoint, LPCSTR NetworkOptions)
147 RPC_STATUS status;
149 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
150 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
152 free(Binding->NetworkAddr);
153 Binding->NetworkAddr = strdup(NetworkAddr);
154 free(Binding->Endpoint);
155 Binding->Endpoint = strdup(Endpoint);
156 free(Binding->NetworkOptions);
157 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
159 /* only attempt to get an association if the binding is complete */
160 if (Endpoint && Endpoint[0] != '\0')
162 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
163 Binding->Endpoint, Binding->NetworkOptions,
164 &Binding->Assoc);
165 if (status != RPC_S_OK)
166 return status;
169 return RPC_S_OK;
172 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
173 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
175 RPC_STATUS status;
177 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
178 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
180 free(Binding->NetworkAddr);
181 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
182 free(Binding->Endpoint);
183 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
184 free(Binding->NetworkOptions);
185 Binding->NetworkOptions = wcsdup(NetworkOptions);
187 /* only attempt to get an association if the binding is complete */
188 if (Endpoint && Endpoint[0] != '\0')
190 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
191 Binding->Endpoint, Binding->NetworkOptions,
192 &Binding->Assoc);
193 if (status != RPC_S_OK)
194 return status;
197 return RPC_S_OK;
200 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
202 RPC_STATUS status;
204 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
206 free(Binding->Endpoint);
207 Binding->Endpoint = strdup(Endpoint);
209 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
210 Binding->Assoc = NULL;
211 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
212 Binding->Endpoint, Binding->NetworkOptions,
213 &Binding->Assoc);
214 if (status != RPC_S_OK)
215 return status;
217 return RPC_S_OK;
220 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
222 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
223 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
224 else UuidCreateNil(&Binding->ObjectUuid);
225 return RPC_S_OK;
228 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
230 RpcBinding* NewBinding;
231 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
233 RPCRT4_AllocBinding(&NewBinding, Connection->server);
234 NewBinding->Protseq = strdup(rpcrt4_conn_get_name(Connection));
235 NewBinding->NetworkAddr = strdup(Connection->NetworkAddr);
236 NewBinding->Endpoint = strdup(Connection->Endpoint);
237 NewBinding->FromConn = Connection;
239 TRACE("binding: %p\n", NewBinding);
240 *Binding = NewBinding;
242 return RPC_S_OK;
245 void RPCRT4_AddRefBinding(RpcBinding* Binding)
247 InterlockedIncrement(&Binding->refs);
250 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
252 if (InterlockedDecrement(&Binding->refs))
253 return RPC_S_OK;
255 TRACE("binding: %p\n", Binding);
256 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
257 free(Binding->Endpoint);
258 free(Binding->NetworkAddr);
259 free(Binding->Protseq);
260 free(Binding->NetworkOptions);
261 free(Binding->CookieAuth);
262 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
263 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
264 free(Binding);
265 return RPC_S_OK;
268 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
269 const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
270 const RPC_SYNTAX_IDENTIFIER *InterfaceId, BOOL *from_cache)
272 TRACE("(Binding == ^%p)\n", Binding);
274 if (!Binding->server) {
275 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
276 TransferSyntax, Binding->AuthInfo, Binding->QOS, Binding->CookieAuth, Connection, from_cache);
277 } else {
278 /* we already have a connection with acceptable binding, so use it */
279 if (Binding->FromConn) {
280 *Connection = Binding->FromConn;
281 return RPC_S_OK;
282 } else {
283 ERR("no connection in binding\n");
284 return RPC_S_INTERNAL_ERROR;
289 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
291 TRACE("(Binding == ^%p)\n", Binding);
292 if (!Connection) return RPC_S_OK;
293 if (Binding->server) {
294 /* don't destroy a connection that is cached in the binding */
295 if (Binding->FromConn != Connection)
296 RPCRT4_ReleaseConnection(Connection);
298 else {
299 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
301 return RPC_S_OK;
304 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
306 DWORD len = strlen(dst), slen = strlen(src);
307 char *ndst = realloc(dst, len + slen + 2);
308 if (!ndst)
310 free(dst);
311 return NULL;
313 ndst[len] = ',';
314 memcpy(ndst+len+1, src, slen+1);
315 return ndst;
318 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
320 DWORD len = lstrlenW(dst), slen = lstrlenW(src);
321 WCHAR *ndst = realloc(dst, (len + slen + 2) * sizeof(WCHAR));
322 if (!ndst)
324 free(dst);
325 return NULL;
327 ndst[len] = ',';
328 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
329 return ndst;
332 /* Copies the escaped version of a component into a string binding.
333 * Note: doesn't nul-terminate the string */
334 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
335 const unsigned char *component)
337 for (; *component; component++) {
338 switch (*component) {
339 case '@':
340 case ':':
341 case '[':
342 case ']':
343 case '\\':
344 *string_binding++ = '\\';
345 *string_binding++ = *component;
346 break;
347 default:
348 *string_binding++ = *component;
349 break;
352 return string_binding;
355 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
356 const WCHAR *component)
358 for (; *component; component++) {
359 switch (*component) {
360 case '@':
361 case ':':
362 case '[':
363 case ']':
364 case '\\':
365 *string_binding++ = '\\';
366 *string_binding++ = *component;
367 break;
368 default:
369 *string_binding++ = *component;
370 break;
373 return string_binding;
376 static const unsigned char *string_binding_find_delimiter(
377 const unsigned char *string_binding, unsigned char delim)
379 const unsigned char *next;
380 for (next = string_binding; *next; next++) {
381 if (*next == '\\') {
382 next++;
383 continue;
385 if (*next == delim)
386 return next;
388 return NULL;
391 static const WCHAR *string_binding_find_delimiterW(
392 const WCHAR *string_binding, WCHAR delim)
394 const WCHAR *next;
395 for (next = string_binding; *next; next++) {
396 if (*next == '\\') {
397 next++;
398 continue;
400 if (*next == delim)
401 return next;
403 return NULL;
406 static RPC_CSTR unescape_string_binding_component(
407 const unsigned char *string_binding, int len)
409 RPC_CSTR component, p;
411 if (len == -1) len = strlen((const char *)string_binding);
413 component = malloc((len + 1) * sizeof(*component));
414 if (!component) return NULL;
415 for (p = component; len > 0; string_binding++, len--) {
416 if (*string_binding == '\\') {
417 string_binding++;
418 len--;
419 *p++ = *string_binding;
420 } else {
421 *p++ = *string_binding;
424 *p = '\0';
425 return component;
428 static RPC_WSTR unescape_string_binding_componentW(
429 const WCHAR *string_binding, int len)
431 RPC_WSTR component, p;
433 if (len == -1) len = lstrlenW(string_binding);
435 component = malloc((len + 1) * sizeof(*component));
436 if (!component) return NULL;
437 for (p = component; len > 0; string_binding++, len--) {
438 if (*string_binding == '\\') {
439 string_binding++;
440 len--;
441 *p++ = *string_binding;
442 } else {
443 *p++ = *string_binding;
446 *p = '\0';
447 return component;
450 /***********************************************************************
451 * RpcStringBindingComposeA (RPCRT4.@)
453 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
454 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
455 RPC_CSTR Options, RPC_CSTR *StringBinding )
457 DWORD len = 1;
458 RPC_CSTR data;
460 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
461 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
462 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
463 debugstr_a( (char*)Options ), StringBinding );
465 /* overestimate for each component for escaping of delimiters */
466 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
467 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
468 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
469 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
470 if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
472 data = malloc(len);
473 *StringBinding = data;
475 if (ObjUuid && *ObjUuid) {
476 data = escape_string_binding_component(data, ObjUuid);
477 *data++ = '@';
479 if (Protseq && *Protseq) {
480 data = escape_string_binding_component(data, Protseq);
481 *data++ = ':';
483 if (NetworkAddr && *NetworkAddr)
484 data = escape_string_binding_component(data, NetworkAddr);
486 if ((Endpoint && *Endpoint) ||
487 (Options && *Options)) {
488 *data++ = '[';
489 if (Endpoint && *Endpoint) {
490 data = escape_string_binding_component(data, Endpoint);
491 if (Options && *Options) *data++ = ',';
493 if (Options && *Options) {
494 data = escape_string_binding_component(data, Options);
496 *data++ = ']';
498 *data = 0;
500 return RPC_S_OK;
503 /***********************************************************************
504 * RpcStringBindingComposeW (RPCRT4.@)
506 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
507 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
508 RPC_WSTR Options, RPC_WSTR* StringBinding )
510 DWORD len = 1;
511 RPC_WSTR data;
513 TRACE("(%s,%s,%s,%s,%s,%p)\n",
514 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
515 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
516 debugstr_w( Options ), StringBinding);
518 /* overestimate for each component for escaping of delimiters */
519 if (ObjUuid && *ObjUuid) len += lstrlenW(ObjUuid) * 2 + 1;
520 if (Protseq && *Protseq) len += lstrlenW(Protseq) * 2 + 1;
521 if (NetworkAddr && *NetworkAddr) len += lstrlenW(NetworkAddr) * 2;
522 if (Endpoint && *Endpoint) len += lstrlenW(Endpoint) * 2 + 2;
523 if (Options && *Options) len += lstrlenW(Options) * 2 + 2;
525 data = malloc(len * sizeof(WCHAR));
526 *StringBinding = data;
528 if (ObjUuid && *ObjUuid) {
529 data = escape_string_binding_componentW(data, ObjUuid);
530 *data++ = '@';
532 if (Protseq && *Protseq) {
533 data = escape_string_binding_componentW(data, Protseq);
534 *data++ = ':';
536 if (NetworkAddr && *NetworkAddr) {
537 data = escape_string_binding_componentW(data, NetworkAddr);
539 if ((Endpoint && *Endpoint) ||
540 (Options && *Options)) {
541 *data++ = '[';
542 if (Endpoint && *Endpoint) {
543 data = escape_string_binding_componentW(data, Endpoint);
544 if (Options && *Options) *data++ = ',';
546 if (Options && *Options) {
547 data = escape_string_binding_componentW(data, Options);
549 *data++ = ']';
551 *data = 0;
553 return RPC_S_OK;
557 /***********************************************************************
558 * RpcStringBindingParseA (RPCRT4.@)
560 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
561 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
562 RPC_CSTR *Endpoint, RPC_CSTR *Options)
564 const unsigned char *data, *next;
565 static const char ep_opt[] = "endpoint=";
566 BOOL endpoint_already_found = FALSE;
568 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
569 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
571 if (ObjUuid) *ObjUuid = NULL;
572 if (Protseq) *Protseq = NULL;
573 if (NetworkAddr) *NetworkAddr = NULL;
574 if (Endpoint) *Endpoint = NULL;
575 if (Options) *Options = NULL;
577 data = StringBinding;
579 next = string_binding_find_delimiter(data, '@');
580 if (next) {
581 UUID uuid;
582 RPC_STATUS status;
583 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
584 status = UuidFromStringA(str_uuid, &uuid);
585 if (status != RPC_S_OK) {
586 free(str_uuid);
587 return status;
589 if (ObjUuid)
590 *ObjUuid = str_uuid;
591 else
592 free(str_uuid);
593 data = next+1;
596 next = string_binding_find_delimiter(data, ':');
597 if (next) {
598 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
599 data = next+1;
602 next = string_binding_find_delimiter(data, '[');
603 if (next) {
604 const unsigned char *close;
605 RPC_CSTR opt;
607 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
608 data = next+1;
609 close = string_binding_find_delimiter(data, ']');
610 if (!close) goto fail;
612 /* tokenize options */
613 while (data < close) {
614 next = string_binding_find_delimiter(data, ',');
615 if (!next || next > close) next = close;
616 /* FIXME: this is kind of inefficient */
617 opt = unescape_string_binding_component(data, next - data);
618 data = next+1;
620 /* parse option */
621 next = string_binding_find_delimiter(opt, '=');
622 if (!next) {
623 /* not an option, must be an endpoint */
624 if (endpoint_already_found) goto fail;
625 if (Endpoint) *Endpoint = opt;
626 else free(opt);
627 endpoint_already_found = TRUE;
628 } else {
629 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
630 /* endpoint option */
631 if (endpoint_already_found) goto fail;
632 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
633 free(opt);
634 endpoint_already_found = TRUE;
635 } else {
636 /* network option */
637 if (Options) {
638 if (*Options) {
639 /* FIXME: this is kind of inefficient */
640 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
641 free(opt);
642 } else
643 *Options = opt;
644 } else
645 free(opt);
650 data = close+1;
651 if (*data) goto fail;
653 else if (NetworkAddr)
654 *NetworkAddr = unescape_string_binding_component(data, -1);
656 return RPC_S_OK;
658 fail:
659 if (ObjUuid) RpcStringFreeA(ObjUuid);
660 if (Protseq) RpcStringFreeA(Protseq);
661 if (NetworkAddr) RpcStringFreeA(NetworkAddr);
662 if (Endpoint) RpcStringFreeA(Endpoint);
663 if (Options) RpcStringFreeA(Options);
664 return RPC_S_INVALID_STRING_BINDING;
667 /***********************************************************************
668 * RpcStringBindingParseW (RPCRT4.@)
670 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
671 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
672 RPC_WSTR *Endpoint, RPC_WSTR *Options)
674 const WCHAR *data, *next;
675 BOOL endpoint_already_found = FALSE;
677 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
678 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
680 if (ObjUuid) *ObjUuid = NULL;
681 if (Protseq) *Protseq = NULL;
682 if (NetworkAddr) *NetworkAddr = NULL;
683 if (Endpoint) *Endpoint = NULL;
684 if (Options) *Options = NULL;
686 data = StringBinding;
688 next = string_binding_find_delimiterW(data, '@');
689 if (next) {
690 UUID uuid;
691 RPC_STATUS status;
692 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
693 status = UuidFromStringW(str_uuid, &uuid);
694 if (status != RPC_S_OK) {
695 free(str_uuid);
696 return status;
698 if (ObjUuid)
699 *ObjUuid = str_uuid;
700 else
701 free(str_uuid);
702 data = next+1;
705 next = string_binding_find_delimiterW(data, ':');
706 if (next) {
707 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
708 data = next+1;
711 next = string_binding_find_delimiterW(data, '[');
712 if (next) {
713 const WCHAR *close;
714 RPC_WSTR opt;
716 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
717 data = next+1;
718 close = string_binding_find_delimiterW(data, ']');
719 if (!close) goto fail;
721 /* tokenize options */
722 while (data < close) {
723 next = string_binding_find_delimiterW(data, ',');
724 if (!next || next > close) next = close;
725 /* FIXME: this is kind of inefficient */
726 opt = unescape_string_binding_componentW(data, next - data);
727 data = next+1;
729 /* parse option */
730 next = string_binding_find_delimiterW(opt, '=');
731 if (!next) {
732 /* not an option, must be an endpoint */
733 if (endpoint_already_found) goto fail;
734 if (Endpoint) *Endpoint = opt;
735 else free(opt);
736 endpoint_already_found = TRUE;
737 } else {
738 if (wcsncmp(opt, L"endpoint=", lstrlenW(L"endpoint=")) == 0) {
739 /* endpoint option */
740 if (endpoint_already_found) goto fail;
741 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
742 free(opt);
743 endpoint_already_found = TRUE;
744 } else {
745 /* network option */
746 if (Options) {
747 if (*Options) {
748 /* FIXME: this is kind of inefficient */
749 *Options = RPCRT4_strconcatW(*Options, opt);
750 free(opt);
751 } else
752 *Options = opt;
753 } else
754 free(opt);
759 data = close+1;
760 if (*data) goto fail;
761 } else if (NetworkAddr)
762 *NetworkAddr = unescape_string_binding_componentW(data, -1);
764 return RPC_S_OK;
766 fail:
767 if (ObjUuid) RpcStringFreeW(ObjUuid);
768 if (Protseq) RpcStringFreeW(Protseq);
769 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
770 if (Endpoint) RpcStringFreeW(Endpoint);
771 if (Options) RpcStringFreeW(Options);
772 return RPC_S_INVALID_STRING_BINDING;
775 /***********************************************************************
776 * RpcBindingFree (RPCRT4.@)
778 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
780 RPC_STATUS status;
781 TRACE("(%p) = %p\n", Binding, *Binding);
782 if (*Binding)
783 status = RPCRT4_ReleaseBinding(*Binding);
784 else
785 status = RPC_S_INVALID_BINDING;
786 if (status == RPC_S_OK) *Binding = NULL;
787 return status;
790 /***********************************************************************
791 * RpcBindingVectorFree (RPCRT4.@)
793 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
795 ULONG c;
797 TRACE("(%p)\n", BindingVector);
798 for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]);
799 free(*BindingVector);
800 *BindingVector = NULL;
801 return RPC_S_OK;
804 /***********************************************************************
805 * RpcBindingInqObject (RPCRT4.@)
807 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
809 RpcBinding* bind = Binding;
811 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
812 *ObjectUuid = bind->ObjectUuid;
813 return RPC_S_OK;
816 /***********************************************************************
817 * RpcBindingSetObject (RPCRT4.@)
819 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
821 RpcBinding* bind = Binding;
823 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
824 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
825 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
828 /***********************************************************************
829 * RpcBindingFromStringBindingA (RPCRT4.@)
831 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
833 RPC_STATUS ret;
834 RpcBinding* bind = NULL;
835 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
836 UUID Uuid;
838 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
840 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
841 &NetworkAddr, &Endpoint, &Options);
842 if (ret != RPC_S_OK) return ret;
844 ret = UuidFromStringA(ObjectUuid, &Uuid);
846 if (ret == RPC_S_OK)
847 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
848 if (ret == RPC_S_OK) {
849 ret = RPCRT4_SetBindingObject(bind, &Uuid);
850 if (ret == RPC_S_OK)
851 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
853 if (ret == RPC_S_OK)
854 *Binding = (RPC_BINDING_HANDLE)bind;
855 else
856 RPCRT4_ReleaseBinding(bind);
859 RpcStringFreeA(&Options);
860 RpcStringFreeA(&Endpoint);
861 RpcStringFreeA(&NetworkAddr);
862 RpcStringFreeA(&Protseq);
863 RpcStringFreeA(&ObjectUuid);
865 return ret;
868 /***********************************************************************
869 * RpcBindingFromStringBindingW (RPCRT4.@)
871 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
873 RPC_STATUS ret;
874 RpcBinding* bind = NULL;
875 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
876 UUID Uuid;
878 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
880 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
881 &NetworkAddr, &Endpoint, &Options);
882 if (ret != RPC_S_OK) return ret;
884 ret = UuidFromStringW(ObjectUuid, &Uuid);
886 if (ret == RPC_S_OK)
887 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
888 if (ret == RPC_S_OK) {
889 ret = RPCRT4_SetBindingObject(bind, &Uuid);
890 if (ret == RPC_S_OK)
891 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
893 if (ret == RPC_S_OK)
894 *Binding = (RPC_BINDING_HANDLE)bind;
895 else
896 RPCRT4_ReleaseBinding(bind);
899 RpcStringFreeW(&Options);
900 RpcStringFreeW(&Endpoint);
901 RpcStringFreeW(&NetworkAddr);
902 RpcStringFreeW(&Protseq);
903 RpcStringFreeW(&ObjectUuid);
905 return ret;
908 /***********************************************************************
909 * RpcBindingToStringBindingA (RPCRT4.@)
911 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
913 RPC_STATUS ret;
914 RpcBinding* bind = Binding;
915 RPC_CSTR ObjectUuid;
917 TRACE("(%p,%p)\n", Binding, StringBinding);
919 if (UuidIsNil(&bind->ObjectUuid, &ret))
920 ObjectUuid = NULL;
921 else
923 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
924 if (ret != RPC_S_OK) return ret;
927 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
928 (unsigned char*) bind->Endpoint, NULL, StringBinding);
930 RpcStringFreeA(&ObjectUuid);
932 return ret;
935 /***********************************************************************
936 * RpcBindingToStringBindingW (RPCRT4.@)
938 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
940 RPC_STATUS ret;
941 unsigned char *str = NULL;
942 TRACE("(%p,%p)\n", Binding, StringBinding);
943 ret = RpcBindingToStringBindingA(Binding, &str);
944 *StringBinding = RPCRT4_strdupAtoW((char*)str);
945 RpcStringFreeA(&str);
946 return ret;
949 /***********************************************************************
950 * I_RpcBindingInqTransportType (RPCRT4.@)
952 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
955 FIXME( "(%p,%p): stub\n", Binding, Type);
956 *Type = TRANSPORT_TYPE_LPC;
957 return RPC_S_OK;
960 /***********************************************************************
961 * I_RpcBindingSetAsync (RPCRT4.@)
962 * NOTES
963 * Exists in win9x and winNT, but with different number of arguments
964 * (9x version has 3 arguments, NT has 2).
966 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
968 RpcBinding* bind = Binding;
970 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
972 bind->BlockingFn = BlockingFn;
974 return RPC_S_OK;
977 /***********************************************************************
978 * RpcBindingCopy (RPCRT4.@)
980 RPC_STATUS RPC_ENTRY RpcBindingCopy(
981 RPC_BINDING_HANDLE SourceBinding,
982 RPC_BINDING_HANDLE* DestinationBinding)
984 RpcBinding *DestBinding;
985 RpcBinding *SrcBinding = SourceBinding;
986 RPC_STATUS status;
988 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
990 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
991 if (status != RPC_S_OK) return status;
993 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
994 DestBinding->BlockingFn = SrcBinding->BlockingFn;
995 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
996 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
997 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
998 DestBinding->NetworkOptions = wcsdup(SrcBinding->NetworkOptions);
999 DestBinding->CookieAuth = wcsdup(SrcBinding->CookieAuth);
1000 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1001 DestBinding->Assoc = SrcBinding->Assoc;
1003 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1004 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1005 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1006 DestBinding->QOS = SrcBinding->QOS;
1008 *DestinationBinding = DestBinding;
1009 return RPC_S_OK;
1012 /***********************************************************************
1013 * RpcBindingReset (RPCRT4.@)
1015 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
1017 RpcBinding *bind = Binding;
1019 TRACE("(%p)\n", Binding);
1021 free(bind->Endpoint);
1022 bind->Endpoint = NULL;
1023 if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
1024 bind->Assoc = NULL;
1026 return RPC_S_OK;
1029 /***********************************************************************
1030 * RpcImpersonateClient (RPCRT4.@)
1032 * Impersonates the client connected via a binding handle so that security
1033 * checks are done in the context of the client.
1035 * PARAMS
1036 * BindingHandle [I] Handle to the binding to the client.
1038 * RETURNS
1039 * Success: RPS_S_OK.
1040 * Failure: RPC_STATUS value.
1042 * NOTES
1044 * If BindingHandle is NULL then the function impersonates the client
1045 * connected to the binding handle of the current thread.
1047 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1049 RpcBinding *bind;
1051 TRACE("(%p)\n", BindingHandle);
1053 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1054 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1056 bind = BindingHandle;
1057 if (bind->FromConn)
1058 return rpcrt4_conn_impersonate_client(bind->FromConn);
1059 return RPC_S_WRONG_KIND_OF_BINDING;
1062 /***********************************************************************
1063 * RpcRevertToSelfEx (RPCRT4.@)
1065 * Stops impersonating the client connected to the binding handle so that security
1066 * checks are no longer done in the context of the client.
1068 * PARAMS
1069 * BindingHandle [I] Handle to the binding to the client.
1071 * RETURNS
1072 * Success: RPS_S_OK.
1073 * Failure: RPC_STATUS value.
1075 * NOTES
1077 * If BindingHandle is NULL then the function stops impersonating the client
1078 * connected to the binding handle of the current thread.
1080 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1082 RpcBinding *bind;
1084 TRACE("(%p)\n", BindingHandle);
1086 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1087 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1089 bind = BindingHandle;
1090 if (bind->FromConn)
1091 return rpcrt4_conn_revert_to_self(bind->FromConn);
1092 return RPC_S_WRONG_KIND_OF_BINDING;
1095 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1097 switch (AuthnLevel)
1099 case RPC_C_AUTHN_GSS_NEGOTIATE:
1100 case RPC_C_AUTHN_WINNT:
1101 case RPC_C_AUTHN_GSS_KERBEROS:
1102 return TRUE;
1103 default:
1104 return FALSE;
1108 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1109 CredHandle cred, TimeStamp exp,
1110 ULONG cbMaxToken,
1111 RPC_AUTH_IDENTITY_HANDLE identity,
1112 RpcAuthInfo **ret)
1114 RpcAuthInfo *AuthInfo = malloc(sizeof(*AuthInfo));
1115 if (!AuthInfo)
1116 return RPC_S_OUT_OF_MEMORY;
1118 AuthInfo->refs = 1;
1119 AuthInfo->AuthnLevel = AuthnLevel;
1120 AuthInfo->AuthnSvc = AuthnSvc;
1121 AuthInfo->cred = cred;
1122 AuthInfo->exp = exp;
1123 AuthInfo->cbMaxToken = cbMaxToken;
1124 AuthInfo->identity = identity;
1125 AuthInfo->server_principal_name = NULL;
1127 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1128 * enable better matching in RpcAuthInfo_IsEqual */
1129 if (identity && has_nt_auth_identity(AuthnSvc))
1131 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1132 AuthInfo->nt_identity = malloc(sizeof(*AuthInfo->nt_identity));
1133 if (!AuthInfo->nt_identity)
1135 free(AuthInfo);
1136 return RPC_S_OUT_OF_MEMORY;
1139 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1140 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1141 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1142 else
1143 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1144 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1145 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1146 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1147 else
1148 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1149 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1150 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1151 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1152 else
1153 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1154 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1156 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1157 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1158 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1160 free(AuthInfo->nt_identity->User);
1161 free(AuthInfo->nt_identity->Domain);
1162 free(AuthInfo->nt_identity->Password);
1163 free(AuthInfo->nt_identity);
1164 free(AuthInfo);
1165 return RPC_S_OUT_OF_MEMORY;
1168 else
1169 AuthInfo->nt_identity = NULL;
1170 *ret = AuthInfo;
1171 return RPC_S_OK;
1174 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1176 return InterlockedIncrement(&AuthInfo->refs);
1179 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1181 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1183 if (!refs)
1185 FreeCredentialsHandle(&AuthInfo->cred);
1186 if (AuthInfo->nt_identity)
1188 free(AuthInfo->nt_identity->User);
1189 free(AuthInfo->nt_identity->Domain);
1190 free(AuthInfo->nt_identity->Password);
1191 free(AuthInfo->nt_identity);
1193 free(AuthInfo->server_principal_name);
1194 free(AuthInfo);
1197 return refs;
1200 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1202 if (AuthInfo1 == AuthInfo2)
1203 return TRUE;
1205 if (!AuthInfo1 || !AuthInfo2)
1206 return FALSE;
1208 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1209 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1210 return FALSE;
1212 if (AuthInfo1->identity == AuthInfo2->identity)
1213 return TRUE;
1215 if (!AuthInfo1->identity || !AuthInfo2->identity)
1216 return FALSE;
1218 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1220 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1221 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1222 /* compare user names */
1223 if (identity1->UserLength != identity2->UserLength ||
1224 memcmp(identity1->User, identity2->User, identity1->UserLength))
1225 return FALSE;
1226 /* compare domain names */
1227 if (identity1->DomainLength != identity2->DomainLength ||
1228 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1229 return FALSE;
1230 /* compare passwords */
1231 if (identity1->PasswordLength != identity2->PasswordLength ||
1232 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1233 return FALSE;
1235 else
1236 return FALSE;
1238 return TRUE;
1241 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1243 RpcQualityOfService *qos = malloc(sizeof(*qos));
1245 if (!qos)
1246 return RPC_S_OUT_OF_RESOURCES;
1248 qos->refs = 1;
1249 qos->qos = malloc(sizeof(*qos->qos));
1250 if (!qos->qos) goto error;
1251 qos->qos->Version = qos_src->Version;
1252 qos->qos->Capabilities = qos_src->Capabilities;
1253 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1254 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1255 qos->qos->AdditionalSecurityInfoType = 0;
1257 if (qos_src->Version >= 2)
1259 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1260 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1261 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1263 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1264 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1266 http_credentials_dst = malloc(sizeof(*http_credentials_dst));
1267 qos->qos->u.HttpCredentials = http_credentials_dst;
1268 if (!http_credentials_dst) goto error;
1269 http_credentials_dst->TransportCredentials = NULL;
1270 http_credentials_dst->Flags = http_credentials_src->Flags;
1271 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1272 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1273 http_credentials_dst->AuthnSchemes = NULL;
1274 http_credentials_dst->ServerCertificateSubject = NULL;
1275 if (http_credentials_src->TransportCredentials)
1277 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1278 cred_dst = http_credentials_dst->TransportCredentials = calloc(1, sizeof(*cred_dst));
1279 if (!cred_dst) goto error;
1280 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1281 if (unicode)
1283 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1284 cred_dst->UserLength = cred_src->UserLength;
1285 cred_dst->PasswordLength = cred_src->PasswordLength;
1286 cred_dst->DomainLength = cred_src->DomainLength;
1287 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1288 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1289 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1291 else
1293 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1294 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1295 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1296 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1297 cred_dst->User = malloc(cred_dst->UserLength * sizeof(WCHAR));
1298 cred_dst->Password = malloc(cred_dst->PasswordLength * sizeof(WCHAR));
1299 cred_dst->Domain = malloc(cred_dst->DomainLength * sizeof(WCHAR));
1300 if (!cred_dst->Password || !cred_dst->Domain) goto error;
1301 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1302 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1303 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1306 if (http_credentials_src->NumberOfAuthnSchemes)
1308 http_credentials_dst->AuthnSchemes = malloc(http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1309 if (!http_credentials_dst->AuthnSchemes) goto error;
1310 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1312 if (http_credentials_src->ServerCertificateSubject)
1314 if (unicode)
1315 http_credentials_dst->ServerCertificateSubject =
1316 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1317 lstrlenW(http_credentials_src->ServerCertificateSubject));
1318 else
1319 http_credentials_dst->ServerCertificateSubject =
1320 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1321 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1325 *qos_dst = qos;
1326 return RPC_S_OK;
1328 error:
1329 if (qos->qos)
1331 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1332 qos->qos->u.HttpCredentials)
1334 if (qos->qos->u.HttpCredentials->TransportCredentials)
1336 free(qos->qos->u.HttpCredentials->TransportCredentials->User);
1337 free(qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1338 free(qos->qos->u.HttpCredentials->TransportCredentials->Password);
1339 free(qos->qos->u.HttpCredentials->TransportCredentials);
1341 free(qos->qos->u.HttpCredentials->AuthnSchemes);
1342 free(qos->qos->u.HttpCredentials->ServerCertificateSubject);
1343 free(qos->qos->u.HttpCredentials);
1345 free(qos->qos);
1347 free(qos);
1348 return RPC_S_OUT_OF_RESOURCES;
1351 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1353 return InterlockedIncrement(&qos->refs);
1356 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1358 ULONG refs = InterlockedDecrement(&qos->refs);
1360 if (!refs)
1362 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1364 if (qos->qos->u.HttpCredentials->TransportCredentials)
1366 free(qos->qos->u.HttpCredentials->TransportCredentials->User);
1367 free(qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1368 free(qos->qos->u.HttpCredentials->TransportCredentials->Password);
1369 free(qos->qos->u.HttpCredentials->TransportCredentials);
1371 free(qos->qos->u.HttpCredentials->AuthnSchemes);
1372 free(qos->qos->u.HttpCredentials->ServerCertificateSubject);
1373 free(qos->qos->u.HttpCredentials);
1375 free(qos->qos);
1376 free(qos);
1378 return refs;
1381 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1383 if (qos1 == qos2)
1384 return TRUE;
1386 if (!qos1 || !qos2)
1387 return FALSE;
1389 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1390 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1391 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1392 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1393 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1395 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1396 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1397 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1398 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1399 return FALSE;
1401 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1403 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1404 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1406 if (http_credentials1->Flags != http_credentials2->Flags)
1407 return FALSE;
1409 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1410 return FALSE;
1412 if (http_credentials1->NumberOfAuthnSchemes != http_credentials2->NumberOfAuthnSchemes)
1413 return FALSE;
1415 if ((!http_credentials1->AuthnSchemes && http_credentials2->AuthnSchemes) ||
1416 (http_credentials1->AuthnSchemes && !http_credentials2->AuthnSchemes))
1417 return FALSE;
1419 if (memcmp(http_credentials1->AuthnSchemes, http_credentials2->AuthnSchemes,
1420 http_credentials1->NumberOfAuthnSchemes * sizeof(http_credentials1->AuthnSchemes[0])))
1421 return FALSE;
1423 /* server certificate subject not currently used */
1425 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1427 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1428 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1430 if (!identity1 || !identity2)
1431 return FALSE;
1433 /* compare user names */
1434 if (identity1->UserLength != identity2->UserLength ||
1435 memcmp(identity1->User, identity2->User, identity1->UserLength))
1436 return FALSE;
1437 /* compare domain names */
1438 if (identity1->DomainLength != identity2->DomainLength ||
1439 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1440 return FALSE;
1441 /* compare passwords */
1442 if (identity1->PasswordLength != identity2->PasswordLength ||
1443 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1444 return FALSE;
1448 return TRUE;
1451 /***********************************************************************
1452 * RpcRevertToSelf (RPCRT4.@)
1454 RPC_STATUS WINAPI RpcRevertToSelf(void)
1456 TRACE("\n");
1457 return RpcRevertToSelfEx(NULL);
1460 /***********************************************************************
1461 * RpcMgmtSetComTimeout (RPCRT4.@)
1463 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1465 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1466 return RPC_S_OK;
1469 /***********************************************************************
1470 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1472 RPCRTAPI RPC_STATUS RPC_ENTRY
1473 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1474 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1475 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1477 RPC_STATUS status;
1478 RPC_WSTR principal;
1480 TRACE("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1481 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1483 status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
1484 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1485 if (status == RPC_S_OK && ServerPrincName)
1487 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1488 RpcStringFreeW(&principal);
1489 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1492 return status;
1495 /***********************************************************************
1496 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1498 RPCRTAPI RPC_STATUS RPC_ENTRY
1499 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1500 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1501 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1503 RpcBinding *bind = Binding;
1505 TRACE("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1506 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1508 if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
1510 if (SecurityQOS)
1512 FIXME("QOS not implemented\n");
1513 return RPC_S_INVALID_BINDING;
1516 if (ServerPrincName)
1518 if (bind->AuthInfo->server_principal_name)
1520 *ServerPrincName = wcsdup(bind->AuthInfo->server_principal_name);
1521 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1523 else *ServerPrincName = NULL;
1525 if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
1526 if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
1527 if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
1528 if (AuthzSvc)
1530 FIXME("authorization service not implemented\n");
1531 *AuthzSvc = RPC_C_AUTHZ_NONE;
1534 return RPC_S_OK;
1537 /***********************************************************************
1538 * RpcBindingInqAuthInfoA (RPCRT4.@)
1540 RPCRTAPI RPC_STATUS RPC_ENTRY
1541 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1542 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1544 return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1545 AuthzSvc, 0, NULL);
1548 /***********************************************************************
1549 * RpcBindingInqAuthInfoW (RPCRT4.@)
1551 RPCRTAPI RPC_STATUS RPC_ENTRY
1552 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1553 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1555 return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1556 AuthzSvc, 0, NULL);
1559 /***********************************************************************
1560 * RpcBindingInqAuthClientA (RPCRT4.@)
1562 RPCRTAPI RPC_STATUS RPC_ENTRY
1563 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1564 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1565 ULONG *AuthzSvc )
1567 return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1568 AuthnSvc, AuthzSvc, 0);
1571 /***********************************************************************
1572 * RpcBindingInqAuthClientW (RPCRT4.@)
1574 RPCRTAPI RPC_STATUS RPC_ENTRY
1575 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1576 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1577 ULONG *AuthzSvc )
1579 return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1580 AuthnSvc, AuthzSvc, 0);
1583 /***********************************************************************
1584 * RpcBindingInqAuthClientExA (RPCRT4.@)
1586 RPCRTAPI RPC_STATUS RPC_ENTRY
1587 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1588 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1589 ULONG *AuthzSvc, ULONG Flags )
1591 RPC_STATUS status;
1592 RPC_WSTR principal;
1594 TRACE("%p %p %p %p %p %p 0x%lx\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1595 AuthnSvc, AuthzSvc, Flags);
1597 status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
1598 AuthnLevel, AuthnSvc, AuthzSvc, Flags);
1599 if (status == RPC_S_OK && ServerPrincName)
1601 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1602 if (!*ServerPrincName && principal) status = RPC_S_OUT_OF_MEMORY;
1603 RpcStringFreeW(&principal);
1606 return status;
1609 /***********************************************************************
1610 * RpcBindingInqAuthClientExW (RPCRT4.@)
1612 RPCRTAPI RPC_STATUS RPC_ENTRY
1613 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1614 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1615 ULONG *AuthzSvc, ULONG Flags )
1617 RpcBinding *bind;
1619 TRACE("%p %p %p %p %p %p 0x%lx\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1620 AuthnSvc, AuthzSvc, Flags);
1622 if (!ClientBinding) ClientBinding = I_RpcGetCurrentCallHandle();
1623 if (!ClientBinding) return RPC_S_INVALID_BINDING;
1625 bind = ClientBinding;
1626 if (!bind->FromConn) return RPC_S_INVALID_BINDING;
1628 return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
1629 ServerPrincName, AuthnLevel,
1630 AuthnSvc, AuthzSvc, Flags);
1633 /***********************************************************************
1634 * RpcBindingServerFromClient (RPCRT4.@)
1636 RPCRTAPI RPC_STATUS RPC_ENTRY
1637 RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding)
1639 RpcBinding* bind = ClientBinding;
1640 RpcBinding* NewBinding;
1642 if (!bind)
1643 bind = I_RpcGetCurrentCallHandle();
1645 if (!bind->server)
1646 return RPC_S_INVALID_BINDING;
1648 RPCRT4_AllocBinding(&NewBinding, TRUE);
1649 NewBinding->Protseq = strdup(bind->Protseq);
1650 NewBinding->NetworkAddr = strdup(bind->NetworkAddr);
1652 *ServerBinding = NewBinding;
1654 return RPC_S_OK;
1657 /***********************************************************************
1658 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1660 RPCRTAPI RPC_STATUS RPC_ENTRY
1661 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1662 ULONG AuthnLevel, ULONG AuthnSvc,
1663 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1664 RPC_SECURITY_QOS *SecurityQos )
1666 RpcBinding* bind = Binding;
1667 SECURITY_STATUS r;
1668 CredHandle cred;
1669 TimeStamp exp;
1670 ULONG package_count;
1671 ULONG i;
1672 PSecPkgInfoA packages;
1673 ULONG cbMaxToken;
1675 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1676 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1678 if (SecurityQos)
1680 RPC_STATUS status;
1682 TRACE("SecurityQos { Version=%ld, Capabilities=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1683 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1684 if (SecurityQos->Version >= 2)
1686 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1687 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1688 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1689 TRACE(", { %p, 0x%lx, %ld, %ld, %p(%lu), %s }",
1690 SecurityQos2->u.HttpCredentials->TransportCredentials,
1691 SecurityQos2->u.HttpCredentials->Flags,
1692 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1693 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1694 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1695 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1696 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1698 TRACE("}\n");
1699 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1700 if (status != RPC_S_OK)
1701 return status;
1703 else
1705 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1706 bind->QOS = NULL;
1709 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1710 AuthnSvc = RPC_C_AUTHN_WINNT;
1712 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1713 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1714 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1716 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1718 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1719 bind->AuthInfo = NULL;
1720 return RPC_S_OK;
1723 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1725 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1726 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1729 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1730 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1732 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1733 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1736 r = EnumerateSecurityPackagesA(&package_count, &packages);
1737 if (r != SEC_E_OK)
1739 ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r);
1740 return RPC_S_SEC_PKG_ERROR;
1743 for (i = 0; i < package_count; i++)
1744 if (packages[i].wRPCID == AuthnSvc)
1745 break;
1747 if (i == package_count)
1749 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1750 FreeContextBuffer(packages);
1751 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1754 TRACE("found package %s for service %lu\n", packages[i].Name, AuthnSvc);
1755 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1756 AuthIdentity, NULL, NULL, &cred, &exp);
1757 cbMaxToken = packages[i].cbMaxToken;
1758 FreeContextBuffer(packages);
1759 if (r == ERROR_SUCCESS)
1761 RpcAuthInfo *new_auth_info;
1762 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1763 AuthIdentity, &new_auth_info);
1764 if (r == RPC_S_OK)
1766 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1767 if (!ServerPrincName || new_auth_info->server_principal_name)
1769 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1770 bind->AuthInfo = new_auth_info;
1772 else
1774 RpcAuthInfo_Release(new_auth_info);
1775 r = RPC_S_OUT_OF_MEMORY;
1778 else
1779 FreeCredentialsHandle(&cred);
1780 return r;
1782 else
1784 ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r);
1785 return RPC_S_SEC_PKG_ERROR;
1789 /***********************************************************************
1790 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1792 RPCRTAPI RPC_STATUS RPC_ENTRY
1793 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1794 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1795 RPC_SECURITY_QOS *SecurityQos )
1797 RpcBinding* bind = Binding;
1798 SECURITY_STATUS r;
1799 CredHandle cred;
1800 TimeStamp exp;
1801 ULONG package_count;
1802 ULONG i;
1803 PSecPkgInfoW packages;
1804 ULONG cbMaxToken;
1806 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w(ServerPrincName),
1807 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1809 if (SecurityQos)
1811 RPC_STATUS status;
1813 TRACE("SecurityQos { Version=%ld, Capabilities=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1814 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1815 if (SecurityQos->Version >= 2)
1817 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1818 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1819 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1820 TRACE(", { %p, 0x%lx, %ld, %ld, %p(%lu), %s }",
1821 SecurityQos2->u.HttpCredentials->TransportCredentials,
1822 SecurityQos2->u.HttpCredentials->Flags,
1823 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1824 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1825 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1826 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1827 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1829 TRACE("}\n");
1830 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1831 if (status != RPC_S_OK)
1832 return status;
1834 else
1836 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1837 bind->QOS = NULL;
1840 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1841 AuthnSvc = RPC_C_AUTHN_WINNT;
1843 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1844 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1845 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1847 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1849 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1850 bind->AuthInfo = NULL;
1851 return RPC_S_OK;
1854 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1856 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1857 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1860 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1861 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1863 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1864 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1867 r = EnumerateSecurityPackagesW(&package_count, &packages);
1868 if (r != SEC_E_OK)
1870 ERR("EnumerateSecurityPackagesW failed with error 0x%08lx\n", r);
1871 return RPC_S_SEC_PKG_ERROR;
1874 for (i = 0; i < package_count; i++)
1875 if (packages[i].wRPCID == AuthnSvc)
1876 break;
1878 if (i == package_count)
1880 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1881 FreeContextBuffer(packages);
1882 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1885 TRACE("found package %s for service %lu\n", debugstr_w(packages[i].Name), AuthnSvc);
1886 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1887 AuthIdentity, NULL, NULL, &cred, &exp);
1888 cbMaxToken = packages[i].cbMaxToken;
1889 FreeContextBuffer(packages);
1890 if (r == ERROR_SUCCESS)
1892 RpcAuthInfo *new_auth_info;
1893 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1894 AuthIdentity, &new_auth_info);
1895 if (r == RPC_S_OK)
1897 new_auth_info->server_principal_name = wcsdup(ServerPrincName);
1898 if (!ServerPrincName || new_auth_info->server_principal_name)
1900 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1901 bind->AuthInfo = new_auth_info;
1903 else
1905 RpcAuthInfo_Release(new_auth_info);
1906 r = RPC_S_OUT_OF_MEMORY;
1909 else
1910 FreeCredentialsHandle(&cred);
1911 return r;
1913 else
1915 ERR("AcquireCredentialsHandleW failed with error 0x%08lx\n", r);
1916 return RPC_S_SEC_PKG_ERROR;
1920 /***********************************************************************
1921 * RpcBindingSetAuthInfoA (RPCRT4.@)
1923 RPCRTAPI RPC_STATUS RPC_ENTRY
1924 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1925 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1927 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1928 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1929 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1932 /***********************************************************************
1933 * RpcBindingSetAuthInfoW (RPCRT4.@)
1935 RPCRTAPI RPC_STATUS RPC_ENTRY
1936 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1937 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1939 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w(ServerPrincName),
1940 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1941 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1944 /***********************************************************************
1945 * RpcBindingSetOption (RPCRT4.@)
1947 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1949 TRACE("(%p, %ld, %Id)\n", BindingHandle, Option, OptionValue);
1951 switch (Option)
1953 case RPC_C_OPT_COOKIE_AUTH:
1955 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *cookie = (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *)OptionValue;
1956 RpcBinding *binding = BindingHandle;
1957 int len = MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, NULL, 0);
1958 WCHAR *str;
1960 if (!(str = malloc((len + 1) * sizeof(WCHAR)))) return RPC_S_OUT_OF_MEMORY;
1961 MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, str, len);
1962 str[len] = 0;
1963 free(binding->CookieAuth);
1964 binding->CookieAuth = str;
1965 break;
1967 default:
1968 FIXME("option %lu not supported\n", Option);
1969 break;
1971 return RPC_S_OK;
1974 /***********************************************************************
1975 * I_RpcBindingInqLocalClientPID (RPCRT4.@)
1978 RPC_STATUS WINAPI I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding, ULONG *ClientPID)
1980 RpcConnection *connection = NULL;
1981 RpcBinding *binding;
1983 TRACE("%p %p\n", ClientBinding, ClientPID);
1985 binding = ClientBinding ? ClientBinding : RPCRT4_GetThreadCurrentCallHandle();
1986 if (!binding)
1987 return RPC_S_NO_CALL_ACTIVE;
1989 connection = binding->FromConn;
1990 if (!connection->ops->inquire_client_pid)
1991 return RPC_S_INVALID_BINDING;
1993 return connection->ops->inquire_client_pid(connection, ClientPID);