push 6495605bb529da27066f1c178d57d902552737a0
[wine/hacks.git] / dlls / rpcrt4 / rpc_binding.c
blob15f0e87a129498893a3fc999b8e8631d701fe445
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"
34 #include "wine/unicode.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 = HeapAlloc(GetProcessHeap(), 0, 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 = HeapAlloc(GetProcessHeap(), 0, 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 = HeapAlloc(GetProcessHeap(), 0, 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 = HeapAlloc(GetProcessHeap(), 0, 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 = strlenW(src);
98 len = slen;
99 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
100 memcpy(s, src, len*sizeof(WCHAR));
101 s[len] = 0;
102 return s;
105 void RPCRT4_strfree(LPSTR src)
107 HeapFree(GetProcessHeap(), 0, src);
110 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
112 RpcBinding* NewBinding;
114 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
115 NewBinding->refs = 1;
116 NewBinding->server = server;
118 *Binding = NewBinding;
120 return RPC_S_OK;
123 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
125 RpcBinding* NewBinding;
127 RPCRT4_AllocBinding(&NewBinding, server);
128 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
130 TRACE("binding: %p\n", NewBinding);
131 *Binding = NewBinding;
133 return RPC_S_OK;
136 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
138 RpcBinding* NewBinding;
140 RPCRT4_AllocBinding(&NewBinding, server);
141 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
143 TRACE("binding: %p\n", NewBinding);
144 *Binding = NewBinding;
146 return RPC_S_OK;
149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
150 LPCSTR Endpoint, LPCSTR NetworkOptions)
152 RPC_STATUS status;
154 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
155 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
157 RPCRT4_strfree(Binding->NetworkAddr);
158 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
159 RPCRT4_strfree(Binding->Endpoint);
160 if (Endpoint) {
161 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
162 } else {
163 Binding->Endpoint = RPCRT4_strdupA("");
165 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
166 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
167 if (!Binding->Endpoint) ERR("out of memory?\n");
169 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
170 Binding->Endpoint, Binding->NetworkOptions,
171 &Binding->Assoc);
172 if (status != RPC_S_OK)
173 return status;
175 return RPC_S_OK;
178 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
179 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
181 RPC_STATUS status;
183 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
184 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
186 RPCRT4_strfree(Binding->NetworkAddr);
187 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
188 RPCRT4_strfree(Binding->Endpoint);
189 if (Endpoint) {
190 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
191 } else {
192 Binding->Endpoint = RPCRT4_strdupA("");
194 if (!Binding->Endpoint) ERR("out of memory?\n");
195 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
196 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
198 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
199 Binding->Endpoint, Binding->NetworkOptions,
200 &Binding->Assoc);
201 if (status != RPC_S_OK)
202 return status;
204 return RPC_S_OK;
207 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
209 RPC_STATUS status;
211 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
213 RPCRT4_strfree(Binding->Endpoint);
214 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
216 RpcAssoc_Release(Binding->Assoc);
217 Binding->Assoc = NULL;
218 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
219 Binding->Endpoint, Binding->NetworkOptions,
220 &Binding->Assoc);
221 if (status != RPC_S_OK)
222 return status;
224 return RPC_S_OK;
227 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
229 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
230 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
231 else UuidCreateNil(&Binding->ObjectUuid);
232 return RPC_S_OK;
235 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
237 RpcBinding* NewBinding;
238 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
240 RPCRT4_AllocBinding(&NewBinding, Connection->server);
241 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
242 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
243 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
244 NewBinding->FromConn = Connection;
246 TRACE("binding: %p\n", NewBinding);
247 *Binding = NewBinding;
249 return RPC_S_OK;
252 void RPCRT4_AddRefBinding(RpcBinding* Binding)
254 InterlockedIncrement(&Binding->refs);
257 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
259 if (InterlockedDecrement(&Binding->refs))
260 return RPC_S_OK;
262 TRACE("binding: %p\n", Binding);
263 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
264 RPCRT4_strfree(Binding->Endpoint);
265 RPCRT4_strfree(Binding->NetworkAddr);
266 RPCRT4_strfree(Binding->Protseq);
267 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
268 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
269 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
270 HeapFree(GetProcessHeap(), 0, Binding);
271 return RPC_S_OK;
274 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
275 const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
276 const RPC_SYNTAX_IDENTIFIER *InterfaceId)
278 TRACE("(Binding == ^%p)\n", Binding);
280 if (!Binding->server) {
281 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
282 TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
283 } else {
284 /* we already have a connection with acceptable binding, so use it */
285 if (Binding->FromConn) {
286 *Connection = Binding->FromConn;
287 return RPC_S_OK;
288 } else {
289 ERR("no connection in binding\n");
290 return RPC_S_INTERNAL_ERROR;
295 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
297 TRACE("(Binding == ^%p)\n", Binding);
298 if (!Connection) return RPC_S_OK;
299 if (Binding->server) {
300 /* don't destroy a connection that is cached in the binding */
301 if (Binding->FromConn == Connection)
302 return RPC_S_OK;
303 return RPCRT4_DestroyConnection(Connection);
305 else {
306 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
307 return RPC_S_OK;
311 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
313 DWORD len = strlen(dst), slen = strlen(src);
314 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
315 if (!ndst)
317 HeapFree(GetProcessHeap(), 0, dst);
318 return NULL;
320 ndst[len] = ',';
321 memcpy(ndst+len+1, src, slen+1);
322 return ndst;
325 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
327 DWORD len = strlenW(dst), slen = strlenW(src);
328 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
329 if (!ndst)
331 HeapFree(GetProcessHeap(), 0, dst);
332 return NULL;
334 ndst[len] = ',';
335 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
336 return ndst;
339 /* Copies the escaped version of a component into a string binding.
340 * Note: doesn't nul-terminate the string */
341 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
342 const unsigned char *component)
344 for (; *component; component++) {
345 switch (*component) {
346 case '@':
347 case ':':
348 case '[':
349 case ']':
350 case '\\':
351 *string_binding++ = '\\';
352 *string_binding++ = *component;
353 break;
354 default:
355 *string_binding++ = *component;
356 break;
359 return string_binding;
362 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
363 const WCHAR *component)
365 for (; *component; component++) {
366 switch (*component) {
367 case '@':
368 case ':':
369 case '[':
370 case ']':
371 case '\\':
372 *string_binding++ = '\\';
373 *string_binding++ = *component;
374 break;
375 default:
376 *string_binding++ = *component;
377 break;
380 return string_binding;
383 static const unsigned char *string_binding_find_delimiter(
384 const unsigned char *string_binding, unsigned char delim)
386 const unsigned char *next;
387 for (next = string_binding; *next; next++) {
388 if (*next == '\\') {
389 next++;
390 continue;
392 if (*next == delim)
393 return next;
395 return NULL;
398 static const WCHAR *string_binding_find_delimiterW(
399 const WCHAR *string_binding, WCHAR delim)
401 const WCHAR *next;
402 for (next = string_binding; *next; next++) {
403 if (*next == '\\') {
404 next++;
405 continue;
407 if (*next == delim)
408 return next;
410 return NULL;
413 static RPC_CSTR unescape_string_binding_component(
414 const unsigned char *string_binding, int len)
416 RPC_CSTR component, p;
418 if (len == -1) len = strlen((const char *)string_binding);
420 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
421 if (!component) return NULL;
422 for (p = component; len > 0; string_binding++, len--) {
423 if (*string_binding == '\\') {
424 string_binding++;
425 len--;
426 *p++ = *string_binding;
427 } else {
428 *p++ = *string_binding;
431 *p = '\0';
432 return component;
435 static RPC_WSTR unescape_string_binding_componentW(
436 const WCHAR *string_binding, int len)
438 RPC_WSTR component, p;
440 if (len == -1) len = strlen((const char *)string_binding);
442 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
443 if (!component) return NULL;
444 for (p = component; len > 0; string_binding++, len--) {
445 if (*string_binding == '\\') {
446 string_binding++;
447 len--;
448 *p++ = *string_binding;
449 } else {
450 *p++ = *string_binding;
453 *p = '\0';
454 return component;
457 /***********************************************************************
458 * RpcStringBindingComposeA (RPCRT4.@)
460 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
461 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
462 RPC_CSTR Options, RPC_CSTR *StringBinding )
464 DWORD len = 1;
465 RPC_CSTR data;
467 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
468 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
469 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
470 debugstr_a( (char*)Options ), StringBinding );
472 /* overestimate for each component for escaping of delimiters */
473 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
474 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
475 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
476 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
477 if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
479 data = HeapAlloc(GetProcessHeap(), 0, len);
480 *StringBinding = data;
482 if (ObjUuid && *ObjUuid) {
483 data = escape_string_binding_component(data, ObjUuid);
484 *data++ = '@';
486 if (Protseq && *Protseq) {
487 data = escape_string_binding_component(data, Protseq);
488 *data++ = ':';
490 if (NetworkAddr && *NetworkAddr)
491 data = escape_string_binding_component(data, NetworkAddr);
493 if ((Endpoint && *Endpoint) ||
494 (Options && *Options)) {
495 *data++ = '[';
496 if (Endpoint && *Endpoint) {
497 data = escape_string_binding_component(data, Endpoint);
498 if (Options && *Options) *data++ = ',';
500 if (Options && *Options) {
501 data = escape_string_binding_component(data, Options);
503 *data++ = ']';
505 *data = 0;
507 return RPC_S_OK;
510 /***********************************************************************
511 * RpcStringBindingComposeW (RPCRT4.@)
513 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
514 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
515 RPC_WSTR Options, RPC_WSTR* StringBinding )
517 DWORD len = 1;
518 RPC_WSTR data;
520 TRACE("(%s,%s,%s,%s,%s,%p)\n",
521 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
522 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
523 debugstr_w( Options ), StringBinding);
525 /* overestimate for each component for escaping of delimiters */
526 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1;
527 if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1;
528 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2;
529 if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2;
530 if (Options && *Options) len += strlenW(Options) * 2 + 2;
532 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
533 *StringBinding = data;
535 if (ObjUuid && *ObjUuid) {
536 data = escape_string_binding_componentW(data, ObjUuid);
537 *data++ = '@';
539 if (Protseq && *Protseq) {
540 data = escape_string_binding_componentW(data, Protseq);
541 *data++ = ':';
543 if (NetworkAddr && *NetworkAddr) {
544 data = escape_string_binding_componentW(data, NetworkAddr);
546 if ((Endpoint && *Endpoint) ||
547 (Options && *Options)) {
548 *data++ = '[';
549 if (Endpoint && *Endpoint) {
550 data = escape_string_binding_componentW(data, Endpoint);
551 if (Options && *Options) *data++ = ',';
553 if (Options && *Options) {
554 data = escape_string_binding_componentW(data, Options);
556 *data++ = ']';
558 *data = 0;
560 return RPC_S_OK;
564 /***********************************************************************
565 * RpcStringBindingParseA (RPCRT4.@)
567 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
568 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
569 RPC_CSTR *Endpoint, RPC_CSTR *Options)
571 const unsigned char *data, *next;
572 static const char ep_opt[] = "endpoint=";
573 BOOL endpoint_already_found = FALSE;
575 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
576 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
578 if (ObjUuid) *ObjUuid = NULL;
579 if (Protseq) *Protseq = NULL;
580 if (NetworkAddr) *NetworkAddr = NULL;
581 if (Endpoint) *Endpoint = NULL;
582 if (Options) *Options = NULL;
584 data = StringBinding;
586 next = string_binding_find_delimiter(data, '@');
587 if (next) {
588 UUID uuid;
589 RPC_STATUS status;
590 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
591 status = UuidFromStringA(str_uuid, &uuid);
592 if (status != RPC_S_OK) {
593 HeapFree(GetProcessHeap(), 0, str_uuid);
594 return status;
596 if (ObjUuid)
597 *ObjUuid = str_uuid;
598 else
599 HeapFree(GetProcessHeap(), 0, str_uuid);
600 data = next+1;
603 next = string_binding_find_delimiter(data, ':');
604 if (next) {
605 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
606 data = next+1;
609 next = string_binding_find_delimiter(data, '[');
610 if (next) {
611 const unsigned char *close;
612 RPC_CSTR opt;
614 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
615 data = next+1;
616 close = string_binding_find_delimiter(data, ']');
617 if (!close) goto fail;
619 /* tokenize options */
620 while (data < close) {
621 next = string_binding_find_delimiter(data, ',');
622 if (!next || next > close) next = close;
623 /* FIXME: this is kind of inefficient */
624 opt = unescape_string_binding_component(data, next - data);
625 data = next+1;
627 /* parse option */
628 next = string_binding_find_delimiter(opt, '=');
629 if (!next) {
630 /* not an option, must be an endpoint */
631 if (endpoint_already_found) goto fail;
632 if (Endpoint) *Endpoint = opt;
633 else HeapFree(GetProcessHeap(), 0, opt);
634 endpoint_already_found = TRUE;
635 } else {
636 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
637 /* endpoint option */
638 if (endpoint_already_found) goto fail;
639 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
640 HeapFree(GetProcessHeap(), 0, opt);
641 endpoint_already_found = TRUE;
642 } else {
643 /* network option */
644 if (Options) {
645 if (*Options) {
646 /* FIXME: this is kind of inefficient */
647 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
648 HeapFree(GetProcessHeap(), 0, opt);
649 } else
650 *Options = opt;
651 } else
652 HeapFree(GetProcessHeap(), 0, opt);
657 data = close+1;
658 if (*data) goto fail;
660 else if (NetworkAddr)
661 *NetworkAddr = unescape_string_binding_component(data, -1);
663 return RPC_S_OK;
665 fail:
666 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
667 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
668 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
669 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
670 if (Options) RpcStringFreeA((unsigned char**)Options);
671 return RPC_S_INVALID_STRING_BINDING;
674 /***********************************************************************
675 * RpcStringBindingParseW (RPCRT4.@)
677 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
678 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
679 RPC_WSTR *Endpoint, RPC_WSTR *Options)
681 const WCHAR *data, *next;
682 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
683 BOOL endpoint_already_found = FALSE;
685 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
686 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
688 if (ObjUuid) *ObjUuid = NULL;
689 if (Protseq) *Protseq = NULL;
690 if (NetworkAddr) *NetworkAddr = NULL;
691 if (Endpoint) *Endpoint = NULL;
692 if (Options) *Options = NULL;
694 data = StringBinding;
696 next = string_binding_find_delimiterW(data, '@');
697 if (next) {
698 UUID uuid;
699 RPC_STATUS status;
700 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
701 status = UuidFromStringW(str_uuid, &uuid);
702 if (status != RPC_S_OK) {
703 HeapFree(GetProcessHeap(), 0, str_uuid);
704 return status;
706 if (ObjUuid)
707 *ObjUuid = str_uuid;
708 else
709 HeapFree(GetProcessHeap(), 0, str_uuid);
710 data = next+1;
713 next = string_binding_find_delimiterW(data, ':');
714 if (next) {
715 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
716 data = next+1;
719 next = string_binding_find_delimiterW(data, '[');
720 if (next) {
721 const WCHAR *close;
722 RPC_WSTR opt;
724 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
725 data = next+1;
726 close = string_binding_find_delimiterW(data, ']');
727 if (!close) goto fail;
729 /* tokenize options */
730 while (data < close) {
731 next = string_binding_find_delimiterW(data, ',');
732 if (!next || next > close) next = close;
733 /* FIXME: this is kind of inefficient */
734 opt = unescape_string_binding_componentW(data, next - data);
735 data = next+1;
737 /* parse option */
738 next = string_binding_find_delimiterW(opt, '=');
739 if (!next) {
740 /* not an option, must be an endpoint */
741 if (endpoint_already_found) goto fail;
742 if (Endpoint) *Endpoint = opt;
743 else HeapFree(GetProcessHeap(), 0, opt);
744 endpoint_already_found = TRUE;
745 } else {
746 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
747 /* endpoint option */
748 if (endpoint_already_found) goto fail;
749 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
750 HeapFree(GetProcessHeap(), 0, opt);
751 endpoint_already_found = TRUE;
752 } else {
753 /* network option */
754 if (Options) {
755 if (*Options) {
756 /* FIXME: this is kind of inefficient */
757 *Options = RPCRT4_strconcatW(*Options, opt);
758 HeapFree(GetProcessHeap(), 0, opt);
759 } else
760 *Options = opt;
761 } else
762 HeapFree(GetProcessHeap(), 0, opt);
767 data = close+1;
768 if (*data) goto fail;
769 } else if (NetworkAddr)
770 *NetworkAddr = unescape_string_binding_componentW(data, -1);
772 return RPC_S_OK;
774 fail:
775 if (ObjUuid) RpcStringFreeW(ObjUuid);
776 if (Protseq) RpcStringFreeW(Protseq);
777 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
778 if (Endpoint) RpcStringFreeW(Endpoint);
779 if (Options) RpcStringFreeW(Options);
780 return RPC_S_INVALID_STRING_BINDING;
783 /***********************************************************************
784 * RpcBindingFree (RPCRT4.@)
786 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
788 RPC_STATUS status;
789 TRACE("(%p) = %p\n", Binding, *Binding);
790 status = RPCRT4_ReleaseBinding(*Binding);
791 if (status == RPC_S_OK) *Binding = 0;
792 return status;
795 /***********************************************************************
796 * RpcBindingVectorFree (RPCRT4.@)
798 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
800 RPC_STATUS status;
801 unsigned long c;
803 TRACE("(%p)\n", BindingVector);
804 for (c=0; c<(*BindingVector)->Count; c++) {
805 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
807 HeapFree(GetProcessHeap(), 0, *BindingVector);
808 *BindingVector = NULL;
809 return RPC_S_OK;
812 /***********************************************************************
813 * RpcBindingInqObject (RPCRT4.@)
815 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
817 RpcBinding* bind = (RpcBinding*)Binding;
819 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
820 *ObjectUuid = bind->ObjectUuid;
821 return RPC_S_OK;
824 /***********************************************************************
825 * RpcBindingSetObject (RPCRT4.@)
827 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
829 RpcBinding* bind = (RpcBinding*)Binding;
831 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
832 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
833 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
836 /***********************************************************************
837 * RpcBindingFromStringBindingA (RPCRT4.@)
839 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
841 RPC_STATUS ret;
842 RpcBinding* bind = NULL;
843 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
844 UUID Uuid;
846 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
848 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
849 &NetworkAddr, &Endpoint, &Options);
850 if (ret != RPC_S_OK) return ret;
852 ret = UuidFromStringA(ObjectUuid, &Uuid);
854 if (ret == RPC_S_OK)
855 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
856 if (ret != RPC_S_OK) return ret;
857 ret = RPCRT4_SetBindingObject(bind, &Uuid);
858 if (ret == RPC_S_OK)
859 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
861 RpcStringFreeA((unsigned char**)&Options);
862 RpcStringFreeA((unsigned char**)&Endpoint);
863 RpcStringFreeA((unsigned char**)&NetworkAddr);
864 RpcStringFreeA((unsigned char**)&Protseq);
865 RpcStringFreeA((unsigned char**)&ObjectUuid);
867 if (ret == RPC_S_OK)
868 *Binding = (RPC_BINDING_HANDLE)bind;
869 else
870 RPCRT4_ReleaseBinding(bind);
872 return ret;
875 /***********************************************************************
876 * RpcBindingFromStringBindingW (RPCRT4.@)
878 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
880 RPC_STATUS ret;
881 RpcBinding* bind = NULL;
882 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
883 UUID Uuid;
885 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
887 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
888 &NetworkAddr, &Endpoint, &Options);
889 if (ret != RPC_S_OK) return ret;
891 ret = UuidFromStringW(ObjectUuid, &Uuid);
893 if (ret == RPC_S_OK)
894 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
895 if (ret != RPC_S_OK) return ret;
896 ret = RPCRT4_SetBindingObject(bind, &Uuid);
897 if (ret == RPC_S_OK)
898 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
900 RpcStringFreeW(&Options);
901 RpcStringFreeW(&Endpoint);
902 RpcStringFreeW(&NetworkAddr);
903 RpcStringFreeW(&Protseq);
904 RpcStringFreeW(&ObjectUuid);
906 if (ret == RPC_S_OK)
907 *Binding = (RPC_BINDING_HANDLE)bind;
908 else
909 RPCRT4_ReleaseBinding(bind);
911 return ret;
914 /***********************************************************************
915 * RpcBindingToStringBindingA (RPCRT4.@)
917 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
919 RPC_STATUS ret;
920 RpcBinding* bind = (RpcBinding*)Binding;
921 RPC_CSTR ObjectUuid;
923 TRACE("(%p,%p)\n", Binding, StringBinding);
925 if (UuidIsNil(&bind->ObjectUuid, &ret))
926 ObjectUuid = NULL;
927 else
929 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
930 if (ret != RPC_S_OK) return ret;
933 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
934 (unsigned char*) bind->Endpoint, NULL, StringBinding);
936 RpcStringFreeA(&ObjectUuid);
938 return ret;
941 /***********************************************************************
942 * RpcBindingToStringBindingW (RPCRT4.@)
944 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
946 RPC_STATUS ret;
947 unsigned char *str = NULL;
948 TRACE("(%p,%p)\n", Binding, StringBinding);
949 ret = RpcBindingToStringBindingA(Binding, &str);
950 *StringBinding = RPCRT4_strdupAtoW((char*)str);
951 RpcStringFreeA((unsigned char**)&str);
952 return ret;
955 /***********************************************************************
956 * I_RpcBindingInqTransportType (RPCRT4.@)
958 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
961 FIXME( "(%p,%p): stub\n", Binding, Type);
962 *Type = TRANSPORT_TYPE_LPC;
963 return RPC_S_OK;
966 /***********************************************************************
967 * I_RpcBindingSetAsync (RPCRT4.@)
968 * NOTES
969 * Exists in win9x and winNT, but with different number of arguments
970 * (9x version has 3 arguments, NT has 2).
972 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
974 RpcBinding* bind = (RpcBinding*)Binding;
976 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
978 bind->BlockingFn = BlockingFn;
980 return RPC_S_OK;
983 /***********************************************************************
984 * RpcBindingCopy (RPCRT4.@)
986 RPC_STATUS RPC_ENTRY RpcBindingCopy(
987 RPC_BINDING_HANDLE SourceBinding,
988 RPC_BINDING_HANDLE* DestinationBinding)
990 RpcBinding *DestBinding;
991 RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
992 RPC_STATUS status;
994 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
996 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
997 if (status != RPC_S_OK) return status;
999 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
1000 DestBinding->BlockingFn = SrcBinding->BlockingFn;
1001 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
1002 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
1003 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
1004 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
1005 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1006 DestBinding->Assoc = SrcBinding->Assoc;
1008 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1009 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1010 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1011 DestBinding->QOS = SrcBinding->QOS;
1013 *DestinationBinding = DestBinding;
1014 return RPC_S_OK;
1017 /***********************************************************************
1018 * RpcImpersonateClient (RPCRT4.@)
1020 * Impersonates the client connected via a binding handle so that security
1021 * checks are done in the context of the client.
1023 * PARAMS
1024 * BindingHandle [I] Handle to the binding to the client.
1026 * RETURNS
1027 * Success: RPS_S_OK.
1028 * Failure: RPC_STATUS value.
1030 * NOTES
1032 * If BindingHandle is NULL then the function impersonates the client
1033 * connected to the binding handle of the current thread.
1035 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1037 FIXME("(%p): stub\n", BindingHandle);
1038 ImpersonateSelf(SecurityImpersonation);
1039 return RPC_S_OK;
1042 /***********************************************************************
1043 * RpcRevertToSelfEx (RPCRT4.@)
1045 * Stops impersonating the client connected to the binding handle so that security
1046 * checks are no longer done in the context of the client.
1048 * PARAMS
1049 * BindingHandle [I] Handle to the binding to the client.
1051 * RETURNS
1052 * Success: RPS_S_OK.
1053 * Failure: RPC_STATUS value.
1055 * NOTES
1057 * If BindingHandle is NULL then the function stops impersonating the client
1058 * connected to the binding handle of the current thread.
1060 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1062 FIXME("(%p): stub\n", BindingHandle);
1063 return RPC_S_OK;
1066 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1068 switch (AuthnLevel)
1070 case RPC_C_AUTHN_GSS_NEGOTIATE:
1071 case RPC_C_AUTHN_WINNT:
1072 case RPC_C_AUTHN_GSS_KERBEROS:
1073 return TRUE;
1074 default:
1075 return FALSE;
1079 static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1080 CredHandle cred, TimeStamp exp,
1081 ULONG cbMaxToken,
1082 RPC_AUTH_IDENTITY_HANDLE identity,
1083 RpcAuthInfo **ret)
1085 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1086 if (!AuthInfo)
1087 return ERROR_OUTOFMEMORY;
1089 AuthInfo->refs = 1;
1090 AuthInfo->AuthnLevel = AuthnLevel;
1091 AuthInfo->AuthnSvc = AuthnSvc;
1092 AuthInfo->cred = cred;
1093 AuthInfo->exp = exp;
1094 AuthInfo->cbMaxToken = cbMaxToken;
1095 AuthInfo->identity = identity;
1096 AuthInfo->server_principal_name = NULL;
1098 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1099 * enable better matching in RpcAuthInfo_IsEqual */
1100 if (identity && has_nt_auth_identity(AuthnSvc))
1102 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1103 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1104 if (!AuthInfo->nt_identity)
1106 HeapFree(GetProcessHeap(), 0, AuthInfo);
1107 return ERROR_OUTOFMEMORY;
1110 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1111 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1112 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1113 else
1114 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1115 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1116 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1117 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1118 else
1119 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1120 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1121 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1122 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1123 else
1124 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1125 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1127 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1128 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1129 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1131 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1132 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1133 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1134 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1135 HeapFree(GetProcessHeap(), 0, AuthInfo);
1136 return ERROR_OUTOFMEMORY;
1139 else
1140 AuthInfo->nt_identity = NULL;
1141 *ret = AuthInfo;
1142 return RPC_S_OK;
1145 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1147 return InterlockedIncrement(&AuthInfo->refs);
1150 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1152 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1154 if (!refs)
1156 FreeCredentialsHandle(&AuthInfo->cred);
1157 if (AuthInfo->nt_identity)
1159 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1160 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1161 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1162 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1164 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
1165 HeapFree(GetProcessHeap(), 0, AuthInfo);
1168 return refs;
1171 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1173 if (AuthInfo1 == AuthInfo2)
1174 return TRUE;
1176 if (!AuthInfo1 || !AuthInfo2)
1177 return FALSE;
1179 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1180 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1181 return FALSE;
1183 if (AuthInfo1->identity == AuthInfo2->identity)
1184 return TRUE;
1186 if (!AuthInfo1->identity || !AuthInfo2->identity)
1187 return FALSE;
1189 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1191 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1192 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1193 /* compare user names */
1194 if (identity1->UserLength != identity2->UserLength ||
1195 memcmp(identity1->User, identity2->User, identity1->UserLength))
1196 return FALSE;
1197 /* compare domain names */
1198 if (identity1->DomainLength != identity2->DomainLength ||
1199 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1200 return FALSE;
1201 /* compare passwords */
1202 if (identity1->PasswordLength != identity2->PasswordLength ||
1203 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1204 return FALSE;
1206 else
1207 return FALSE;
1209 return TRUE;
1212 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1214 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1216 if (!qos)
1217 return RPC_S_OUT_OF_RESOURCES;
1219 qos->refs = 1;
1220 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1221 if (!qos->qos) goto error;
1222 qos->qos->Version = qos_src->Version;
1223 qos->qos->Capabilities = qos_src->Capabilities;
1224 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1225 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1226 qos->qos->AdditionalSecurityInfoType = 0;
1228 if (qos_src->Version >= 2)
1230 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1231 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1232 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1234 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1235 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1237 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1238 qos->qos->u.HttpCredentials = http_credentials_dst;
1239 if (!http_credentials_dst) goto error;
1240 http_credentials_dst->TransportCredentials = NULL;
1241 http_credentials_dst->Flags = http_credentials_src->Flags;
1242 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1243 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1244 http_credentials_dst->AuthnSchemes = NULL;
1245 http_credentials_dst->ServerCertificateSubject = NULL;
1246 if (http_credentials_src->TransportCredentials)
1248 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1249 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1250 if (!cred_dst) goto error;
1251 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1252 if (unicode)
1254 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1255 cred_dst->UserLength = cred_src->UserLength;
1256 cred_dst->PasswordLength = cred_src->PasswordLength;
1257 cred_dst->DomainLength = cred_src->DomainLength;
1258 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1259 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1260 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1262 else
1264 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1265 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1266 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1267 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1268 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1269 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1270 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1271 if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error;
1272 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1273 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1274 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1277 if (http_credentials_src->NumberOfAuthnSchemes)
1279 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1280 if (!http_credentials_dst->AuthnSchemes) goto error;
1281 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1283 if (http_credentials_src->ServerCertificateSubject)
1285 if (unicode)
1286 http_credentials_dst->ServerCertificateSubject =
1287 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1288 strlenW(http_credentials_src->ServerCertificateSubject));
1289 else
1290 http_credentials_dst->ServerCertificateSubject =
1291 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1292 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1296 *qos_dst = qos;
1297 return RPC_S_OK;
1299 error:
1300 if (qos->qos)
1302 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1303 qos->qos->u.HttpCredentials)
1305 if (qos->qos->u.HttpCredentials->TransportCredentials)
1307 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1308 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1309 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1310 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1312 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1313 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1314 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1316 HeapFree(GetProcessHeap(), 0, qos->qos);
1318 HeapFree(GetProcessHeap(), 0, qos);
1319 return RPC_S_OUT_OF_RESOURCES;
1322 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1324 return InterlockedIncrement(&qos->refs);
1327 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1329 ULONG refs = InterlockedDecrement(&qos->refs);
1331 if (!refs)
1333 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1335 if (qos->qos->u.HttpCredentials->TransportCredentials)
1337 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1338 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1339 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1340 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1342 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1343 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1344 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1346 HeapFree(GetProcessHeap(), 0, qos->qos);
1347 HeapFree(GetProcessHeap(), 0, qos);
1349 return refs;
1352 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1354 if (qos1 == qos2)
1355 return TRUE;
1357 if (!qos1 || !qos2)
1358 return FALSE;
1360 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1361 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1362 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1363 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1364 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1366 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1367 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1368 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1369 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1370 return FALSE;
1372 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1374 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1375 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1377 if (http_credentials1->Flags != http_credentials2->Flags)
1378 return FALSE;
1380 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1381 return FALSE;
1383 /* authentication schemes and server certificate subject not currently used */
1385 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1387 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1388 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1390 if (!identity1 || !identity2)
1391 return FALSE;
1393 /* compare user names */
1394 if (identity1->UserLength != identity2->UserLength ||
1395 memcmp(identity1->User, identity2->User, identity1->UserLength))
1396 return FALSE;
1397 /* compare domain names */
1398 if (identity1->DomainLength != identity2->DomainLength ||
1399 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1400 return FALSE;
1401 /* compare passwords */
1402 if (identity1->PasswordLength != identity2->PasswordLength ||
1403 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1404 return FALSE;
1408 return TRUE;
1411 /***********************************************************************
1412 * RpcRevertToSelf (RPCRT4.@)
1414 RPC_STATUS WINAPI RpcRevertToSelf(void)
1416 FIXME("stub\n");
1417 RevertToSelf();
1418 return RPC_S_OK;
1421 /***********************************************************************
1422 * RpcMgmtSetComTimeout (RPCRT4.@)
1424 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1426 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1427 return RPC_S_OK;
1430 /***********************************************************************
1431 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1433 RPCRTAPI RPC_STATUS RPC_ENTRY
1434 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1435 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1436 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1438 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1439 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1440 return RPC_S_INVALID_BINDING;
1443 /***********************************************************************
1444 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1446 RPCRTAPI RPC_STATUS RPC_ENTRY
1447 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1448 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1449 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1451 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1452 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1453 return RPC_S_INVALID_BINDING;
1456 /***********************************************************************
1457 * RpcBindingInqAuthInfoA (RPCRT4.@)
1459 RPCRTAPI RPC_STATUS RPC_ENTRY
1460 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1461 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1463 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1464 AuthnSvc, AuthIdentity, AuthzSvc);
1465 return RPC_S_INVALID_BINDING;
1468 /***********************************************************************
1469 * RpcBindingInqAuthInfoW (RPCRT4.@)
1471 RPCRTAPI RPC_STATUS RPC_ENTRY
1472 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1473 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1475 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1476 AuthnSvc, AuthIdentity, AuthzSvc);
1477 return RPC_S_INVALID_BINDING;
1480 /***********************************************************************
1481 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1483 RPCRTAPI RPC_STATUS RPC_ENTRY
1484 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1485 ULONG AuthnLevel, ULONG AuthnSvc,
1486 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1487 RPC_SECURITY_QOS *SecurityQos )
1489 RpcBinding* bind = (RpcBinding*)Binding;
1490 SECURITY_STATUS r;
1491 CredHandle cred;
1492 TimeStamp exp;
1493 ULONG package_count;
1494 ULONG i;
1495 PSecPkgInfoA packages;
1496 ULONG cbMaxToken;
1498 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1499 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1501 if (SecurityQos)
1503 RPC_STATUS status;
1505 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1506 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1507 if (SecurityQos->Version >= 2)
1509 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1510 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1511 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1512 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1513 SecurityQos2->u.HttpCredentials->TransportCredentials,
1514 SecurityQos2->u.HttpCredentials->Flags,
1515 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1516 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1517 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1518 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1520 TRACE("}\n");
1521 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1522 if (status != RPC_S_OK)
1523 return status;
1525 else
1527 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1528 bind->QOS = NULL;
1531 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1532 AuthnSvc = RPC_C_AUTHN_WINNT;
1534 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1535 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1536 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1538 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1540 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1541 bind->AuthInfo = NULL;
1542 return RPC_S_OK;
1545 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1547 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1548 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1551 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1552 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1554 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1555 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1558 r = EnumerateSecurityPackagesA(&package_count, &packages);
1559 if (r != SEC_E_OK)
1561 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1562 return RPC_S_SEC_PKG_ERROR;
1565 for (i = 0; i < package_count; i++)
1566 if (packages[i].wRPCID == AuthnSvc)
1567 break;
1569 if (i == package_count)
1571 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1572 FreeContextBuffer(packages);
1573 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1576 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1577 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1578 AuthIdentity, NULL, NULL, &cred, &exp);
1579 cbMaxToken = packages[i].cbMaxToken;
1580 FreeContextBuffer(packages);
1581 if (r == ERROR_SUCCESS)
1583 RpcAuthInfo *new_auth_info;
1584 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1585 AuthIdentity, &new_auth_info);
1586 if (r == RPC_S_OK)
1588 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1589 if (new_auth_info->server_principal_name)
1591 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1592 bind->AuthInfo = new_auth_info;
1594 else
1596 RpcAuthInfo_Release(new_auth_info);
1597 r = ERROR_OUTOFMEMORY;
1600 else
1601 FreeCredentialsHandle(&cred);
1602 return r;
1604 else
1606 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1607 return RPC_S_SEC_PKG_ERROR;
1611 /***********************************************************************
1612 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1614 RPCRTAPI RPC_STATUS RPC_ENTRY
1615 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1616 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1617 RPC_SECURITY_QOS *SecurityQos )
1619 RpcBinding* bind = (RpcBinding*)Binding;
1620 SECURITY_STATUS r;
1621 CredHandle cred;
1622 TimeStamp exp;
1623 ULONG package_count;
1624 ULONG i;
1625 PSecPkgInfoW packages;
1626 ULONG cbMaxToken;
1628 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1629 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1631 if (SecurityQos)
1633 RPC_STATUS status;
1635 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1636 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1637 if (SecurityQos->Version >= 2)
1639 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1640 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1641 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1642 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1643 SecurityQos2->u.HttpCredentials->TransportCredentials,
1644 SecurityQos2->u.HttpCredentials->Flags,
1645 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1646 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1647 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1648 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1650 TRACE("}\n");
1651 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1652 if (status != RPC_S_OK)
1653 return status;
1655 else
1657 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1658 bind->QOS = NULL;
1661 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1662 AuthnSvc = RPC_C_AUTHN_WINNT;
1664 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1665 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1666 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1668 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1670 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1671 bind->AuthInfo = NULL;
1672 return RPC_S_OK;
1675 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1677 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1678 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1681 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1682 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1684 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1685 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1688 r = EnumerateSecurityPackagesW(&package_count, &packages);
1689 if (r != SEC_E_OK)
1691 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r);
1692 return RPC_S_SEC_PKG_ERROR;
1695 for (i = 0; i < package_count; i++)
1696 if (packages[i].wRPCID == AuthnSvc)
1697 break;
1699 if (i == package_count)
1701 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1702 FreeContextBuffer(packages);
1703 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1706 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1707 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1708 AuthIdentity, NULL, NULL, &cred, &exp);
1709 cbMaxToken = packages[i].cbMaxToken;
1710 FreeContextBuffer(packages);
1711 if (r == ERROR_SUCCESS)
1713 RpcAuthInfo *new_auth_info;
1714 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1715 AuthIdentity, &new_auth_info);
1716 if (r == RPC_S_OK)
1718 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
1719 if (!ServerPrincName || new_auth_info->server_principal_name)
1721 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1722 bind->AuthInfo = new_auth_info;
1724 else
1726 RpcAuthInfo_Release(new_auth_info);
1727 r = ERROR_OUTOFMEMORY;
1730 else
1731 FreeCredentialsHandle(&cred);
1732 return r;
1734 else
1736 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r);
1737 return RPC_S_SEC_PKG_ERROR;
1741 /***********************************************************************
1742 * RpcBindingSetAuthInfoA (RPCRT4.@)
1744 RPCRTAPI RPC_STATUS RPC_ENTRY
1745 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1746 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1748 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1749 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1750 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1753 /***********************************************************************
1754 * RpcBindingSetAuthInfoW (RPCRT4.@)
1756 RPCRTAPI RPC_STATUS RPC_ENTRY
1757 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1758 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1760 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1761 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1762 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1765 /***********************************************************************
1766 * RpcBindingSetOption (RPCRT4.@)
1768 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1770 FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue);
1771 return RPC_S_OK;