l3codeca.acm: Avoid mpg123 functions with suffix.
[wine.git] / dlls / rpcrt4 / rpc_binding.c
blobba7ef4184196123d5f6d9054634df0be2deae923
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 <string.h>
27 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "winerror.h"
33 #include "winternl.h"
35 #include "rpc.h"
36 #include "rpcndr.h"
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)
47 DWORD len;
48 LPSTR s;
49 if (!src) return NULL;
50 if (slen == -1) slen = strlen(src);
51 len = slen;
52 s = HeapAlloc(GetProcessHeap(), 0, len+1);
53 memcpy(s, src, len);
54 s[len] = 0;
55 return s;
58 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
60 DWORD len;
61 LPSTR s;
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);
66 return s;
69 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
71 DWORD len;
72 LPWSTR s;
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);
77 return s;
80 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
82 DWORD len;
83 LPWSTR s;
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);
88 return s;
91 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
93 DWORD len;
94 LPWSTR s;
95 if (!src) return NULL;
96 if (slen == -1) slen = lstrlenW(src);
97 len = slen;
98 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
99 memcpy(s, src, len*sizeof(WCHAR));
100 s[len] = 0;
101 return s;
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;
119 return RPC_S_OK;
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;
132 return RPC_S_OK;
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;
145 return RPC_S_OK;
148 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
149 LPCSTR Endpoint, LPCSTR NetworkOptions)
151 RPC_STATUS status;
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,
168 &Binding->Assoc);
169 if (status != RPC_S_OK)
170 return status;
173 return RPC_S_OK;
176 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
177 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
179 RPC_STATUS status;
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,
196 &Binding->Assoc);
197 if (status != RPC_S_OK)
198 return status;
201 return RPC_S_OK;
204 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
206 RPC_STATUS status;
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,
217 &Binding->Assoc);
218 if (status != RPC_S_OK)
219 return status;
221 return 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);
229 return RPC_S_OK;
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;
246 return RPC_S_OK;
249 void RPCRT4_AddRefBinding(RpcBinding* Binding)
251 InterlockedIncrement(&Binding->refs);
254 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
256 if (InterlockedDecrement(&Binding->refs))
257 return RPC_S_OK;
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);
269 return RPC_S_OK;
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);
281 } else {
282 /* we already have a connection with acceptable binding, so use it */
283 if (Binding->FromConn) {
284 *Connection = Binding->FromConn;
285 return RPC_S_OK;
286 } else {
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);
302 else {
303 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
305 return RPC_S_OK;
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));
312 if (!ndst)
314 HeapFree(GetProcessHeap(), 0, dst);
315 return NULL;
317 ndst[len] = ',';
318 memcpy(ndst+len+1, src, slen+1);
319 return ndst;
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));
326 if (!ndst)
328 HeapFree(GetProcessHeap(), 0, dst);
329 return NULL;
331 ndst[len] = ',';
332 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
333 return ndst;
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) {
343 case '@':
344 case ':':
345 case '[':
346 case ']':
347 case '\\':
348 *string_binding++ = '\\';
349 *string_binding++ = *component;
350 break;
351 default:
352 *string_binding++ = *component;
353 break;
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) {
364 case '@':
365 case ':':
366 case '[':
367 case ']':
368 case '\\':
369 *string_binding++ = '\\';
370 *string_binding++ = *component;
371 break;
372 default:
373 *string_binding++ = *component;
374 break;
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++) {
385 if (*next == '\\') {
386 next++;
387 continue;
389 if (*next == delim)
390 return next;
392 return NULL;
395 static const WCHAR *string_binding_find_delimiterW(
396 const WCHAR *string_binding, WCHAR delim)
398 const WCHAR *next;
399 for (next = string_binding; *next; next++) {
400 if (*next == '\\') {
401 next++;
402 continue;
404 if (*next == delim)
405 return next;
407 return NULL;
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 == '\\') {
421 string_binding++;
422 len--;
423 *p++ = *string_binding;
424 } else {
425 *p++ = *string_binding;
428 *p = '\0';
429 return component;
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 == '\\') {
443 string_binding++;
444 len--;
445 *p++ = *string_binding;
446 } else {
447 *p++ = *string_binding;
450 *p = '\0';
451 return component;
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 )
461 DWORD len = 1;
462 RPC_CSTR data;
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);
481 *data++ = '@';
483 if (Protseq && *Protseq) {
484 data = escape_string_binding_component(data, Protseq);
485 *data++ = ':';
487 if (NetworkAddr && *NetworkAddr)
488 data = escape_string_binding_component(data, NetworkAddr);
490 if ((Endpoint && *Endpoint) ||
491 (Options && *Options)) {
492 *data++ = '[';
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);
500 *data++ = ']';
502 *data = 0;
504 return RPC_S_OK;
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 )
514 DWORD len = 1;
515 RPC_WSTR data;
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);
534 *data++ = '@';
536 if (Protseq && *Protseq) {
537 data = escape_string_binding_componentW(data, Protseq);
538 *data++ = ':';
540 if (NetworkAddr && *NetworkAddr) {
541 data = escape_string_binding_componentW(data, NetworkAddr);
543 if ((Endpoint && *Endpoint) ||
544 (Options && *Options)) {
545 *data++ = '[';
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);
553 *data++ = ']';
555 *data = 0;
557 return RPC_S_OK;
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, '@');
584 if (next) {
585 UUID uuid;
586 RPC_STATUS status;
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);
591 return status;
593 if (ObjUuid)
594 *ObjUuid = str_uuid;
595 else
596 HeapFree(GetProcessHeap(), 0, str_uuid);
597 data = next+1;
600 next = string_binding_find_delimiter(data, ':');
601 if (next) {
602 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
603 data = next+1;
606 next = string_binding_find_delimiter(data, '[');
607 if (next) {
608 const unsigned char *close;
609 RPC_CSTR opt;
611 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
612 data = next+1;
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);
622 data = next+1;
624 /* parse option */
625 next = string_binding_find_delimiter(opt, '=');
626 if (!next) {
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;
632 } else {
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;
639 } else {
640 /* network option */
641 if (Options) {
642 if (*Options) {
643 /* FIXME: this is kind of inefficient */
644 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
645 HeapFree(GetProcessHeap(), 0, opt);
646 } else
647 *Options = opt;
648 } else
649 HeapFree(GetProcessHeap(), 0, opt);
654 data = close+1;
655 if (*data) goto fail;
657 else if (NetworkAddr)
658 *NetworkAddr = unescape_string_binding_component(data, -1);
660 return RPC_S_OK;
662 fail:
663 if (ObjUuid) RpcStringFreeA(ObjUuid);
664 if (Protseq) RpcStringFreeA(Protseq);
665 if (NetworkAddr) RpcStringFreeA(NetworkAddr);
666 if (Endpoint) RpcStringFreeA(Endpoint);
667 if (Options) RpcStringFreeA(Options);
668 return RPC_S_INVALID_STRING_BINDING;
671 /***********************************************************************
672 * RpcStringBindingParseW (RPCRT4.@)
674 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
675 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
676 RPC_WSTR *Endpoint, RPC_WSTR *Options)
678 const WCHAR *data, *next;
679 BOOL endpoint_already_found = FALSE;
681 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
682 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
684 if (ObjUuid) *ObjUuid = NULL;
685 if (Protseq) *Protseq = NULL;
686 if (NetworkAddr) *NetworkAddr = NULL;
687 if (Endpoint) *Endpoint = NULL;
688 if (Options) *Options = NULL;
690 data = StringBinding;
692 next = string_binding_find_delimiterW(data, '@');
693 if (next) {
694 UUID uuid;
695 RPC_STATUS status;
696 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
697 status = UuidFromStringW(str_uuid, &uuid);
698 if (status != RPC_S_OK) {
699 HeapFree(GetProcessHeap(), 0, str_uuid);
700 return status;
702 if (ObjUuid)
703 *ObjUuid = str_uuid;
704 else
705 HeapFree(GetProcessHeap(), 0, str_uuid);
706 data = next+1;
709 next = string_binding_find_delimiterW(data, ':');
710 if (next) {
711 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
712 data = next+1;
715 next = string_binding_find_delimiterW(data, '[');
716 if (next) {
717 const WCHAR *close;
718 RPC_WSTR opt;
720 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
721 data = next+1;
722 close = string_binding_find_delimiterW(data, ']');
723 if (!close) goto fail;
725 /* tokenize options */
726 while (data < close) {
727 next = string_binding_find_delimiterW(data, ',');
728 if (!next || next > close) next = close;
729 /* FIXME: this is kind of inefficient */
730 opt = unescape_string_binding_componentW(data, next - data);
731 data = next+1;
733 /* parse option */
734 next = string_binding_find_delimiterW(opt, '=');
735 if (!next) {
736 /* not an option, must be an endpoint */
737 if (endpoint_already_found) goto fail;
738 if (Endpoint) *Endpoint = opt;
739 else HeapFree(GetProcessHeap(), 0, opt);
740 endpoint_already_found = TRUE;
741 } else {
742 if (wcsncmp(opt, L"endpoint=", lstrlenW(L"endpoint=")) == 0) {
743 /* endpoint option */
744 if (endpoint_already_found) goto fail;
745 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
746 HeapFree(GetProcessHeap(), 0, opt);
747 endpoint_already_found = TRUE;
748 } else {
749 /* network option */
750 if (Options) {
751 if (*Options) {
752 /* FIXME: this is kind of inefficient */
753 *Options = RPCRT4_strconcatW(*Options, opt);
754 HeapFree(GetProcessHeap(), 0, opt);
755 } else
756 *Options = opt;
757 } else
758 HeapFree(GetProcessHeap(), 0, opt);
763 data = close+1;
764 if (*data) goto fail;
765 } else if (NetworkAddr)
766 *NetworkAddr = unescape_string_binding_componentW(data, -1);
768 return RPC_S_OK;
770 fail:
771 if (ObjUuid) RpcStringFreeW(ObjUuid);
772 if (Protseq) RpcStringFreeW(Protseq);
773 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
774 if (Endpoint) RpcStringFreeW(Endpoint);
775 if (Options) RpcStringFreeW(Options);
776 return RPC_S_INVALID_STRING_BINDING;
779 /***********************************************************************
780 * RpcBindingFree (RPCRT4.@)
782 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
784 RPC_STATUS status;
785 TRACE("(%p) = %p\n", Binding, *Binding);
786 if (*Binding)
787 status = RPCRT4_ReleaseBinding(*Binding);
788 else
789 status = RPC_S_INVALID_BINDING;
790 if (status == RPC_S_OK) *Binding = NULL;
791 return status;
794 /***********************************************************************
795 * RpcBindingVectorFree (RPCRT4.@)
797 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
799 ULONG c;
801 TRACE("(%p)\n", BindingVector);
802 for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]);
803 HeapFree(GetProcessHeap(), 0, *BindingVector);
804 *BindingVector = NULL;
805 return RPC_S_OK;
808 /***********************************************************************
809 * RpcBindingInqObject (RPCRT4.@)
811 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
813 RpcBinding* bind = Binding;
815 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
816 *ObjectUuid = bind->ObjectUuid;
817 return RPC_S_OK;
820 /***********************************************************************
821 * RpcBindingSetObject (RPCRT4.@)
823 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
825 RpcBinding* bind = Binding;
827 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
828 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
829 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
832 /***********************************************************************
833 * RpcBindingFromStringBindingA (RPCRT4.@)
835 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
837 RPC_STATUS ret;
838 RpcBinding* bind = NULL;
839 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
840 UUID Uuid;
842 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
844 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
845 &NetworkAddr, &Endpoint, &Options);
846 if (ret != RPC_S_OK) return ret;
848 ret = UuidFromStringA(ObjectUuid, &Uuid);
850 if (ret == RPC_S_OK)
851 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
852 if (ret == RPC_S_OK) {
853 ret = RPCRT4_SetBindingObject(bind, &Uuid);
854 if (ret == RPC_S_OK)
855 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
857 if (ret == RPC_S_OK)
858 *Binding = (RPC_BINDING_HANDLE)bind;
859 else
860 RPCRT4_ReleaseBinding(bind);
863 RpcStringFreeA(&Options);
864 RpcStringFreeA(&Endpoint);
865 RpcStringFreeA(&NetworkAddr);
866 RpcStringFreeA(&Protseq);
867 RpcStringFreeA(&ObjectUuid);
869 return ret;
872 /***********************************************************************
873 * RpcBindingFromStringBindingW (RPCRT4.@)
875 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
877 RPC_STATUS ret;
878 RpcBinding* bind = NULL;
879 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
880 UUID Uuid;
882 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
884 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
885 &NetworkAddr, &Endpoint, &Options);
886 if (ret != RPC_S_OK) return ret;
888 ret = UuidFromStringW(ObjectUuid, &Uuid);
890 if (ret == RPC_S_OK)
891 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
892 if (ret == RPC_S_OK) {
893 ret = RPCRT4_SetBindingObject(bind, &Uuid);
894 if (ret == RPC_S_OK)
895 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
897 if (ret == RPC_S_OK)
898 *Binding = (RPC_BINDING_HANDLE)bind;
899 else
900 RPCRT4_ReleaseBinding(bind);
903 RpcStringFreeW(&Options);
904 RpcStringFreeW(&Endpoint);
905 RpcStringFreeW(&NetworkAddr);
906 RpcStringFreeW(&Protseq);
907 RpcStringFreeW(&ObjectUuid);
909 return ret;
912 /***********************************************************************
913 * RpcBindingToStringBindingA (RPCRT4.@)
915 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
917 RPC_STATUS ret;
918 RpcBinding* bind = Binding;
919 RPC_CSTR ObjectUuid;
921 TRACE("(%p,%p)\n", Binding, StringBinding);
923 if (UuidIsNil(&bind->ObjectUuid, &ret))
924 ObjectUuid = NULL;
925 else
927 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
928 if (ret != RPC_S_OK) return ret;
931 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
932 (unsigned char*) bind->Endpoint, NULL, StringBinding);
934 RpcStringFreeA(&ObjectUuid);
936 return ret;
939 /***********************************************************************
940 * RpcBindingToStringBindingW (RPCRT4.@)
942 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
944 RPC_STATUS ret;
945 unsigned char *str = NULL;
946 TRACE("(%p,%p)\n", Binding, StringBinding);
947 ret = RpcBindingToStringBindingA(Binding, &str);
948 *StringBinding = RPCRT4_strdupAtoW((char*)str);
949 RpcStringFreeA(&str);
950 return ret;
953 /***********************************************************************
954 * I_RpcBindingInqTransportType (RPCRT4.@)
956 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
959 FIXME( "(%p,%p): stub\n", Binding, Type);
960 *Type = TRANSPORT_TYPE_LPC;
961 return RPC_S_OK;
964 /***********************************************************************
965 * I_RpcBindingSetAsync (RPCRT4.@)
966 * NOTES
967 * Exists in win9x and winNT, but with different number of arguments
968 * (9x version has 3 arguments, NT has 2).
970 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
972 RpcBinding* bind = Binding;
974 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
976 bind->BlockingFn = BlockingFn;
978 return RPC_S_OK;
981 /***********************************************************************
982 * RpcBindingCopy (RPCRT4.@)
984 RPC_STATUS RPC_ENTRY RpcBindingCopy(
985 RPC_BINDING_HANDLE SourceBinding,
986 RPC_BINDING_HANDLE* DestinationBinding)
988 RpcBinding *DestBinding;
989 RpcBinding *SrcBinding = SourceBinding;
990 RPC_STATUS status;
992 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
994 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
995 if (status != RPC_S_OK) return status;
997 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
998 DestBinding->BlockingFn = SrcBinding->BlockingFn;
999 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
1000 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
1001 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
1002 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
1003 DestBinding->CookieAuth = RPCRT4_strdupW(SrcBinding->CookieAuth);
1004 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1005 DestBinding->Assoc = SrcBinding->Assoc;
1007 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1008 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1009 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1010 DestBinding->QOS = SrcBinding->QOS;
1012 *DestinationBinding = DestBinding;
1013 return RPC_S_OK;
1016 /***********************************************************************
1017 * RpcBindingReset (RPCRT4.@)
1019 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
1021 RpcBinding *bind = Binding;
1023 TRACE("(%p)\n", Binding);
1025 RPCRT4_strfree(bind->Endpoint);
1026 bind->Endpoint = NULL;
1027 if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
1028 bind->Assoc = NULL;
1030 return RPC_S_OK;
1033 /***********************************************************************
1034 * RpcImpersonateClient (RPCRT4.@)
1036 * Impersonates the client connected via a binding handle so that security
1037 * checks are done in the context of the client.
1039 * PARAMS
1040 * BindingHandle [I] Handle to the binding to the client.
1042 * RETURNS
1043 * Success: RPS_S_OK.
1044 * Failure: RPC_STATUS value.
1046 * NOTES
1048 * If BindingHandle is NULL then the function impersonates the client
1049 * connected to the binding handle of the current thread.
1051 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1053 RpcBinding *bind;
1055 TRACE("(%p)\n", BindingHandle);
1057 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1058 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1060 bind = BindingHandle;
1061 if (bind->FromConn)
1062 return rpcrt4_conn_impersonate_client(bind->FromConn);
1063 return RPC_S_WRONG_KIND_OF_BINDING;
1066 /***********************************************************************
1067 * RpcRevertToSelfEx (RPCRT4.@)
1069 * Stops impersonating the client connected to the binding handle so that security
1070 * checks are no longer done in the context of the client.
1072 * PARAMS
1073 * BindingHandle [I] Handle to the binding to the client.
1075 * RETURNS
1076 * Success: RPS_S_OK.
1077 * Failure: RPC_STATUS value.
1079 * NOTES
1081 * If BindingHandle is NULL then the function stops impersonating the client
1082 * connected to the binding handle of the current thread.
1084 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1086 RpcBinding *bind;
1088 TRACE("(%p)\n", BindingHandle);
1090 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1091 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1093 bind = BindingHandle;
1094 if (bind->FromConn)
1095 return rpcrt4_conn_revert_to_self(bind->FromConn);
1096 return RPC_S_WRONG_KIND_OF_BINDING;
1099 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1101 switch (AuthnLevel)
1103 case RPC_C_AUTHN_GSS_NEGOTIATE:
1104 case RPC_C_AUTHN_WINNT:
1105 case RPC_C_AUTHN_GSS_KERBEROS:
1106 return TRUE;
1107 default:
1108 return FALSE;
1112 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1113 CredHandle cred, TimeStamp exp,
1114 ULONG cbMaxToken,
1115 RPC_AUTH_IDENTITY_HANDLE identity,
1116 RpcAuthInfo **ret)
1118 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1119 if (!AuthInfo)
1120 return RPC_S_OUT_OF_MEMORY;
1122 AuthInfo->refs = 1;
1123 AuthInfo->AuthnLevel = AuthnLevel;
1124 AuthInfo->AuthnSvc = AuthnSvc;
1125 AuthInfo->cred = cred;
1126 AuthInfo->exp = exp;
1127 AuthInfo->cbMaxToken = cbMaxToken;
1128 AuthInfo->identity = identity;
1129 AuthInfo->server_principal_name = NULL;
1131 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1132 * enable better matching in RpcAuthInfo_IsEqual */
1133 if (identity && has_nt_auth_identity(AuthnSvc))
1135 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1136 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1137 if (!AuthInfo->nt_identity)
1139 HeapFree(GetProcessHeap(), 0, AuthInfo);
1140 return RPC_S_OUT_OF_MEMORY;
1143 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1144 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1145 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1146 else
1147 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1148 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1149 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1150 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1151 else
1152 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1153 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1154 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1155 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1156 else
1157 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1158 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1160 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1161 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1162 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1164 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1165 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1166 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1167 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1168 HeapFree(GetProcessHeap(), 0, AuthInfo);
1169 return RPC_S_OUT_OF_MEMORY;
1172 else
1173 AuthInfo->nt_identity = NULL;
1174 *ret = AuthInfo;
1175 return RPC_S_OK;
1178 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1180 return InterlockedIncrement(&AuthInfo->refs);
1183 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1185 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1187 if (!refs)
1189 FreeCredentialsHandle(&AuthInfo->cred);
1190 if (AuthInfo->nt_identity)
1192 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1193 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1194 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1195 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1197 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
1198 HeapFree(GetProcessHeap(), 0, AuthInfo);
1201 return refs;
1204 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1206 if (AuthInfo1 == AuthInfo2)
1207 return TRUE;
1209 if (!AuthInfo1 || !AuthInfo2)
1210 return FALSE;
1212 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1213 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1214 return FALSE;
1216 if (AuthInfo1->identity == AuthInfo2->identity)
1217 return TRUE;
1219 if (!AuthInfo1->identity || !AuthInfo2->identity)
1220 return FALSE;
1222 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1224 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1225 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1226 /* compare user names */
1227 if (identity1->UserLength != identity2->UserLength ||
1228 memcmp(identity1->User, identity2->User, identity1->UserLength))
1229 return FALSE;
1230 /* compare domain names */
1231 if (identity1->DomainLength != identity2->DomainLength ||
1232 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1233 return FALSE;
1234 /* compare passwords */
1235 if (identity1->PasswordLength != identity2->PasswordLength ||
1236 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1237 return FALSE;
1239 else
1240 return FALSE;
1242 return TRUE;
1245 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1247 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1249 if (!qos)
1250 return RPC_S_OUT_OF_RESOURCES;
1252 qos->refs = 1;
1253 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1254 if (!qos->qos) goto error;
1255 qos->qos->Version = qos_src->Version;
1256 qos->qos->Capabilities = qos_src->Capabilities;
1257 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1258 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1259 qos->qos->AdditionalSecurityInfoType = 0;
1261 if (qos_src->Version >= 2)
1263 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1264 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1265 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1267 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1268 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1270 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1271 qos->qos->u.HttpCredentials = http_credentials_dst;
1272 if (!http_credentials_dst) goto error;
1273 http_credentials_dst->TransportCredentials = NULL;
1274 http_credentials_dst->Flags = http_credentials_src->Flags;
1275 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1276 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1277 http_credentials_dst->AuthnSchemes = NULL;
1278 http_credentials_dst->ServerCertificateSubject = NULL;
1279 if (http_credentials_src->TransportCredentials)
1281 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1282 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1283 if (!cred_dst) goto error;
1284 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1285 if (unicode)
1287 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1288 cred_dst->UserLength = cred_src->UserLength;
1289 cred_dst->PasswordLength = cred_src->PasswordLength;
1290 cred_dst->DomainLength = cred_src->DomainLength;
1291 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1292 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1293 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1295 else
1297 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1298 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1299 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1300 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1301 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1302 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1303 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1304 if (!cred_dst->Password || !cred_dst->Domain) goto error;
1305 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1306 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1307 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1310 if (http_credentials_src->NumberOfAuthnSchemes)
1312 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1313 if (!http_credentials_dst->AuthnSchemes) goto error;
1314 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1316 if (http_credentials_src->ServerCertificateSubject)
1318 if (unicode)
1319 http_credentials_dst->ServerCertificateSubject =
1320 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1321 lstrlenW(http_credentials_src->ServerCertificateSubject));
1322 else
1323 http_credentials_dst->ServerCertificateSubject =
1324 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1325 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1329 *qos_dst = qos;
1330 return RPC_S_OK;
1332 error:
1333 if (qos->qos)
1335 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1336 qos->qos->u.HttpCredentials)
1338 if (qos->qos->u.HttpCredentials->TransportCredentials)
1340 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1341 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1342 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1343 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1345 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1346 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1347 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1349 HeapFree(GetProcessHeap(), 0, qos->qos);
1351 HeapFree(GetProcessHeap(), 0, qos);
1352 return RPC_S_OUT_OF_RESOURCES;
1355 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1357 return InterlockedIncrement(&qos->refs);
1360 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1362 ULONG refs = InterlockedDecrement(&qos->refs);
1364 if (!refs)
1366 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1368 if (qos->qos->u.HttpCredentials->TransportCredentials)
1370 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1371 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1372 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1373 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1375 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1376 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1377 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1379 HeapFree(GetProcessHeap(), 0, qos->qos);
1380 HeapFree(GetProcessHeap(), 0, qos);
1382 return refs;
1385 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1387 if (qos1 == qos2)
1388 return TRUE;
1390 if (!qos1 || !qos2)
1391 return FALSE;
1393 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1394 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1395 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1396 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1397 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1399 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1400 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1401 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1402 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1403 return FALSE;
1405 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1407 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1408 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1410 if (http_credentials1->Flags != http_credentials2->Flags)
1411 return FALSE;
1413 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1414 return FALSE;
1416 if (http_credentials1->NumberOfAuthnSchemes != http_credentials2->NumberOfAuthnSchemes)
1417 return FALSE;
1419 if ((!http_credentials1->AuthnSchemes && http_credentials2->AuthnSchemes) ||
1420 (http_credentials1->AuthnSchemes && !http_credentials2->AuthnSchemes))
1421 return FALSE;
1423 if (memcmp(http_credentials1->AuthnSchemes, http_credentials2->AuthnSchemes,
1424 http_credentials1->NumberOfAuthnSchemes * sizeof(http_credentials1->AuthnSchemes[0])))
1425 return FALSE;
1427 /* server certificate subject not currently used */
1429 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1431 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1432 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1434 if (!identity1 || !identity2)
1435 return FALSE;
1437 /* compare user names */
1438 if (identity1->UserLength != identity2->UserLength ||
1439 memcmp(identity1->User, identity2->User, identity1->UserLength))
1440 return FALSE;
1441 /* compare domain names */
1442 if (identity1->DomainLength != identity2->DomainLength ||
1443 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1444 return FALSE;
1445 /* compare passwords */
1446 if (identity1->PasswordLength != identity2->PasswordLength ||
1447 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1448 return FALSE;
1452 return TRUE;
1455 /***********************************************************************
1456 * RpcRevertToSelf (RPCRT4.@)
1458 RPC_STATUS WINAPI RpcRevertToSelf(void)
1460 TRACE("\n");
1461 return RpcRevertToSelfEx(NULL);
1464 /***********************************************************************
1465 * RpcMgmtSetComTimeout (RPCRT4.@)
1467 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1469 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1470 return RPC_S_OK;
1473 /***********************************************************************
1474 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1476 RPCRTAPI RPC_STATUS RPC_ENTRY
1477 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1478 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1479 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1481 RPC_STATUS status;
1482 RPC_WSTR principal;
1484 TRACE("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1485 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1487 status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
1488 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1489 if (status == RPC_S_OK && ServerPrincName)
1491 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1492 RpcStringFreeW(&principal);
1493 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1496 return status;
1499 /***********************************************************************
1500 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1502 RPCRTAPI RPC_STATUS RPC_ENTRY
1503 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1504 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1505 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1507 RpcBinding *bind = Binding;
1509 TRACE("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1510 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1512 if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
1514 if (SecurityQOS)
1516 FIXME("QOS not implemented\n");
1517 return RPC_S_INVALID_BINDING;
1520 if (ServerPrincName)
1522 if (bind->AuthInfo->server_principal_name)
1524 *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name);
1525 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1527 else *ServerPrincName = NULL;
1529 if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
1530 if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
1531 if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
1532 if (AuthzSvc)
1534 FIXME("authorization service not implemented\n");
1535 *AuthzSvc = RPC_C_AUTHZ_NONE;
1538 return RPC_S_OK;
1541 /***********************************************************************
1542 * RpcBindingInqAuthInfoA (RPCRT4.@)
1544 RPCRTAPI RPC_STATUS RPC_ENTRY
1545 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1546 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1548 return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1549 AuthzSvc, 0, NULL);
1552 /***********************************************************************
1553 * RpcBindingInqAuthInfoW (RPCRT4.@)
1555 RPCRTAPI RPC_STATUS RPC_ENTRY
1556 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1557 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1559 return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1560 AuthzSvc, 0, NULL);
1563 /***********************************************************************
1564 * RpcBindingInqAuthClientA (RPCRT4.@)
1566 RPCRTAPI RPC_STATUS RPC_ENTRY
1567 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1568 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1569 ULONG *AuthzSvc )
1571 return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1572 AuthnSvc, AuthzSvc, 0);
1575 /***********************************************************************
1576 * RpcBindingInqAuthClientW (RPCRT4.@)
1578 RPCRTAPI RPC_STATUS RPC_ENTRY
1579 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1580 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1581 ULONG *AuthzSvc )
1583 return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1584 AuthnSvc, AuthzSvc, 0);
1587 /***********************************************************************
1588 * RpcBindingInqAuthClientExA (RPCRT4.@)
1590 RPCRTAPI RPC_STATUS RPC_ENTRY
1591 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1592 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1593 ULONG *AuthzSvc, ULONG Flags )
1595 RPC_STATUS status;
1596 RPC_WSTR principal;
1598 TRACE("%p %p %p %p %p %p 0x%lx\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1599 AuthnSvc, AuthzSvc, Flags);
1601 status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
1602 AuthnLevel, AuthnSvc, AuthzSvc, Flags);
1603 if (status == RPC_S_OK && ServerPrincName)
1605 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1606 if (!*ServerPrincName && principal) status = RPC_S_OUT_OF_MEMORY;
1607 RpcStringFreeW(&principal);
1610 return status;
1613 /***********************************************************************
1614 * RpcBindingInqAuthClientExW (RPCRT4.@)
1616 RPCRTAPI RPC_STATUS RPC_ENTRY
1617 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1618 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1619 ULONG *AuthzSvc, ULONG Flags )
1621 RpcBinding *bind;
1623 TRACE("%p %p %p %p %p %p 0x%lx\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1624 AuthnSvc, AuthzSvc, Flags);
1626 if (!ClientBinding) ClientBinding = I_RpcGetCurrentCallHandle();
1627 if (!ClientBinding) return RPC_S_INVALID_BINDING;
1629 bind = ClientBinding;
1630 if (!bind->FromConn) return RPC_S_INVALID_BINDING;
1632 return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
1633 ServerPrincName, AuthnLevel,
1634 AuthnSvc, AuthzSvc, Flags);
1637 /***********************************************************************
1638 * RpcBindingServerFromClient (RPCRT4.@)
1640 RPCRTAPI RPC_STATUS RPC_ENTRY
1641 RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding)
1643 RpcBinding* bind = ClientBinding;
1644 RpcBinding* NewBinding;
1646 if (!bind)
1647 bind = I_RpcGetCurrentCallHandle();
1649 if (!bind->server)
1650 return RPC_S_INVALID_BINDING;
1652 RPCRT4_AllocBinding(&NewBinding, TRUE);
1653 NewBinding->Protseq = RPCRT4_strdupA(bind->Protseq);
1654 NewBinding->NetworkAddr = RPCRT4_strdupA(bind->NetworkAddr);
1656 *ServerBinding = NewBinding;
1658 return RPC_S_OK;
1661 /***********************************************************************
1662 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1664 RPCRTAPI RPC_STATUS RPC_ENTRY
1665 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1666 ULONG AuthnLevel, ULONG AuthnSvc,
1667 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1668 RPC_SECURITY_QOS *SecurityQos )
1670 RpcBinding* bind = Binding;
1671 SECURITY_STATUS r;
1672 CredHandle cred;
1673 TimeStamp exp;
1674 ULONG package_count;
1675 ULONG i;
1676 PSecPkgInfoA packages;
1677 ULONG cbMaxToken;
1679 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1680 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1682 if (SecurityQos)
1684 RPC_STATUS status;
1686 TRACE("SecurityQos { Version=%ld, Capabilities=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1687 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1688 if (SecurityQos->Version >= 2)
1690 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1691 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1692 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1693 TRACE(", { %p, 0x%lx, %ld, %ld, %p(%lu), %s }",
1694 SecurityQos2->u.HttpCredentials->TransportCredentials,
1695 SecurityQos2->u.HttpCredentials->Flags,
1696 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1697 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1698 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1699 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1700 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1702 TRACE("}\n");
1703 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1704 if (status != RPC_S_OK)
1705 return status;
1707 else
1709 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1710 bind->QOS = NULL;
1713 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1714 AuthnSvc = RPC_C_AUTHN_WINNT;
1716 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1717 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1718 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1720 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1722 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1723 bind->AuthInfo = NULL;
1724 return RPC_S_OK;
1727 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1729 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1730 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1733 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1734 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1736 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1737 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1740 r = EnumerateSecurityPackagesA(&package_count, &packages);
1741 if (r != SEC_E_OK)
1743 ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r);
1744 return RPC_S_SEC_PKG_ERROR;
1747 for (i = 0; i < package_count; i++)
1748 if (packages[i].wRPCID == AuthnSvc)
1749 break;
1751 if (i == package_count)
1753 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1754 FreeContextBuffer(packages);
1755 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1758 TRACE("found package %s for service %lu\n", packages[i].Name, AuthnSvc);
1759 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1760 AuthIdentity, NULL, NULL, &cred, &exp);
1761 cbMaxToken = packages[i].cbMaxToken;
1762 FreeContextBuffer(packages);
1763 if (r == ERROR_SUCCESS)
1765 RpcAuthInfo *new_auth_info;
1766 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1767 AuthIdentity, &new_auth_info);
1768 if (r == RPC_S_OK)
1770 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1771 if (!ServerPrincName || new_auth_info->server_principal_name)
1773 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1774 bind->AuthInfo = new_auth_info;
1776 else
1778 RpcAuthInfo_Release(new_auth_info);
1779 r = RPC_S_OUT_OF_MEMORY;
1782 else
1783 FreeCredentialsHandle(&cred);
1784 return r;
1786 else
1788 ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r);
1789 return RPC_S_SEC_PKG_ERROR;
1793 /***********************************************************************
1794 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1796 RPCRTAPI RPC_STATUS RPC_ENTRY
1797 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1798 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1799 RPC_SECURITY_QOS *SecurityQos )
1801 RpcBinding* bind = Binding;
1802 SECURITY_STATUS r;
1803 CredHandle cred;
1804 TimeStamp exp;
1805 ULONG package_count;
1806 ULONG i;
1807 PSecPkgInfoW packages;
1808 ULONG cbMaxToken;
1810 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w(ServerPrincName),
1811 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1813 if (SecurityQos)
1815 RPC_STATUS status;
1817 TRACE("SecurityQos { Version=%ld, Capabilities=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1818 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1819 if (SecurityQos->Version >= 2)
1821 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1822 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1823 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1824 TRACE(", { %p, 0x%lx, %ld, %ld, %p(%lu), %s }",
1825 SecurityQos2->u.HttpCredentials->TransportCredentials,
1826 SecurityQos2->u.HttpCredentials->Flags,
1827 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1828 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1829 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1830 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1831 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1833 TRACE("}\n");
1834 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1835 if (status != RPC_S_OK)
1836 return status;
1838 else
1840 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1841 bind->QOS = NULL;
1844 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1845 AuthnSvc = RPC_C_AUTHN_WINNT;
1847 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1848 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1849 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1851 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1853 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1854 bind->AuthInfo = NULL;
1855 return RPC_S_OK;
1858 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1860 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1861 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1864 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1865 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1867 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1868 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1871 r = EnumerateSecurityPackagesW(&package_count, &packages);
1872 if (r != SEC_E_OK)
1874 ERR("EnumerateSecurityPackagesW failed with error 0x%08lx\n", r);
1875 return RPC_S_SEC_PKG_ERROR;
1878 for (i = 0; i < package_count; i++)
1879 if (packages[i].wRPCID == AuthnSvc)
1880 break;
1882 if (i == package_count)
1884 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1885 FreeContextBuffer(packages);
1886 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1889 TRACE("found package %s for service %lu\n", debugstr_w(packages[i].Name), AuthnSvc);
1890 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1891 AuthIdentity, NULL, NULL, &cred, &exp);
1892 cbMaxToken = packages[i].cbMaxToken;
1893 FreeContextBuffer(packages);
1894 if (r == ERROR_SUCCESS)
1896 RpcAuthInfo *new_auth_info;
1897 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1898 AuthIdentity, &new_auth_info);
1899 if (r == RPC_S_OK)
1901 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
1902 if (!ServerPrincName || new_auth_info->server_principal_name)
1904 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1905 bind->AuthInfo = new_auth_info;
1907 else
1909 RpcAuthInfo_Release(new_auth_info);
1910 r = RPC_S_OUT_OF_MEMORY;
1913 else
1914 FreeCredentialsHandle(&cred);
1915 return r;
1917 else
1919 ERR("AcquireCredentialsHandleW failed with error 0x%08lx\n", r);
1920 return RPC_S_SEC_PKG_ERROR;
1924 /***********************************************************************
1925 * RpcBindingSetAuthInfoA (RPCRT4.@)
1927 RPCRTAPI RPC_STATUS RPC_ENTRY
1928 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1929 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1931 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1932 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1933 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1936 /***********************************************************************
1937 * RpcBindingSetAuthInfoW (RPCRT4.@)
1939 RPCRTAPI RPC_STATUS RPC_ENTRY
1940 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1941 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1943 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w(ServerPrincName),
1944 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1945 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1948 /***********************************************************************
1949 * RpcBindingSetOption (RPCRT4.@)
1951 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1953 TRACE("(%p, %ld, %Id)\n", BindingHandle, Option, OptionValue);
1955 switch (Option)
1957 case RPC_C_OPT_COOKIE_AUTH:
1959 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *cookie = (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *)OptionValue;
1960 RpcBinding *binding = BindingHandle;
1961 int len = MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, NULL, 0);
1962 WCHAR *str;
1964 if (!(str = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)))) return RPC_S_OUT_OF_MEMORY;
1965 MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, str, len);
1966 str[len] = 0;
1967 HeapFree(GetProcessHeap(), 0, binding->CookieAuth);
1968 binding->CookieAuth = str;
1969 break;
1971 default:
1972 FIXME("option %lu not supported\n", Option);
1973 break;
1975 return RPC_S_OK;
1978 /***********************************************************************
1979 * I_RpcBindingInqLocalClientPID (RPCRT4.@)
1982 RPC_STATUS WINAPI I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding, ULONG *ClientPID)
1984 FIXME("%p %p: stub\n", ClientBinding, ClientPID);
1985 return RPC_S_INVALID_BINDING;