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
34 #include "wine/unicode.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)
50 if (!src) return NULL;
51 if (slen == -1) slen = strlen(src);
53 s = HeapAlloc(GetProcessHeap(), 0, len+1);
59 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
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);
70 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
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);
81 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
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);
92 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
96 if (!src) return NULL;
97 if (slen == -1) slen = strlenW(src);
99 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
100 memcpy(s, src, len*sizeof(WCHAR));
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;
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;
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;
149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
150 LPCSTR Endpoint, LPCSTR NetworkOptions)
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 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
161 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
162 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
164 /* only attempt to get an association if the binding is complete */
165 if (Endpoint && Endpoint[0] != '\0')
167 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
168 Binding->Endpoint, Binding->NetworkOptions,
170 if (status != RPC_S_OK)
177 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
178 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
182 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
183 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
185 RPCRT4_strfree(Binding->NetworkAddr);
186 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
187 RPCRT4_strfree(Binding->Endpoint);
188 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
189 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
190 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
192 /* only attempt to get an association if the binding is complete */
193 if (Endpoint && Endpoint[0] != '\0')
195 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
196 Binding->Endpoint, Binding->NetworkOptions,
198 if (status != RPC_S_OK)
205 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
209 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
211 RPCRT4_strfree(Binding->Endpoint);
212 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
214 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
215 Binding->Assoc = NULL;
216 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
217 Binding->Endpoint, Binding->NetworkOptions,
219 if (status != RPC_S_OK)
225 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
227 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
228 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
229 else UuidCreateNil(&Binding->ObjectUuid);
233 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
235 RpcBinding* NewBinding;
236 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
238 RPCRT4_AllocBinding(&NewBinding, Connection->server);
239 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
240 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
241 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
242 NewBinding->FromConn = Connection;
244 TRACE("binding: %p\n", NewBinding);
245 *Binding = NewBinding;
250 void RPCRT4_AddRefBinding(RpcBinding* Binding)
252 InterlockedIncrement(&Binding->refs);
255 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
257 if (InterlockedDecrement(&Binding->refs))
260 TRACE("binding: %p\n", Binding);
261 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
262 RPCRT4_strfree(Binding->Endpoint);
263 RPCRT4_strfree(Binding->NetworkAddr);
264 RPCRT4_strfree(Binding->Protseq);
265 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
266 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
267 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
268 HeapFree(GetProcessHeap(), 0, Binding);
272 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
273 const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
274 const RPC_SYNTAX_IDENTIFIER *InterfaceId)
276 TRACE("(Binding == ^%p)\n", Binding);
278 if (!Binding->server) {
279 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
280 TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
282 /* we already have a connection with acceptable binding, so use it */
283 if (Binding->FromConn) {
284 *Connection = Binding->FromConn;
287 ERR("no connection in binding\n");
288 return RPC_S_INTERNAL_ERROR;
293 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
295 TRACE("(Binding == ^%p)\n", Binding);
296 if (!Connection) return RPC_S_OK;
297 if (Binding->server) {
298 /* don't destroy a connection that is cached in the binding */
299 if (Binding->FromConn == Connection)
301 return RPCRT4_DestroyConnection(Connection);
304 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
309 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
311 DWORD len = strlen(dst), slen = strlen(src);
312 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
315 HeapFree(GetProcessHeap(), 0, dst);
319 memcpy(ndst+len+1, src, slen+1);
323 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
325 DWORD len = strlenW(dst), slen = strlenW(src);
326 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
329 HeapFree(GetProcessHeap(), 0, dst);
333 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
337 /* Copies the escaped version of a component into a string binding.
338 * Note: doesn't nul-terminate the string */
339 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
340 const unsigned char *component)
342 for (; *component; component++) {
343 switch (*component) {
349 *string_binding++ = '\\';
350 *string_binding++ = *component;
353 *string_binding++ = *component;
357 return string_binding;
360 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
361 const WCHAR *component)
363 for (; *component; component++) {
364 switch (*component) {
370 *string_binding++ = '\\';
371 *string_binding++ = *component;
374 *string_binding++ = *component;
378 return string_binding;
381 static const unsigned char *string_binding_find_delimiter(
382 const unsigned char *string_binding, unsigned char delim)
384 const unsigned char *next;
385 for (next = string_binding; *next; next++) {
396 static const WCHAR *string_binding_find_delimiterW(
397 const WCHAR *string_binding, WCHAR delim)
400 for (next = string_binding; *next; next++) {
411 static RPC_CSTR unescape_string_binding_component(
412 const unsigned char *string_binding, int len)
414 RPC_CSTR component, p;
416 if (len == -1) len = strlen((const char *)string_binding);
418 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
419 if (!component) return NULL;
420 for (p = component; len > 0; string_binding++, len--) {
421 if (*string_binding == '\\') {
424 *p++ = *string_binding;
426 *p++ = *string_binding;
433 static RPC_WSTR unescape_string_binding_componentW(
434 const WCHAR *string_binding, int len)
436 RPC_WSTR component, p;
438 if (len == -1) len = strlenW(string_binding);
440 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
441 if (!component) return NULL;
442 for (p = component; len > 0; string_binding++, len--) {
443 if (*string_binding == '\\') {
446 *p++ = *string_binding;
448 *p++ = *string_binding;
455 /***********************************************************************
456 * RpcStringBindingComposeA (RPCRT4.@)
458 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
459 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
460 RPC_CSTR Options, RPC_CSTR *StringBinding )
465 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
466 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
467 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
468 debugstr_a( (char*)Options ), StringBinding );
470 /* overestimate for each component for escaping of delimiters */
471 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
472 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
473 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
474 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
475 if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
477 data = HeapAlloc(GetProcessHeap(), 0, len);
478 *StringBinding = data;
480 if (ObjUuid && *ObjUuid) {
481 data = escape_string_binding_component(data, ObjUuid);
484 if (Protseq && *Protseq) {
485 data = escape_string_binding_component(data, Protseq);
488 if (NetworkAddr && *NetworkAddr)
489 data = escape_string_binding_component(data, NetworkAddr);
491 if ((Endpoint && *Endpoint) ||
492 (Options && *Options)) {
494 if (Endpoint && *Endpoint) {
495 data = escape_string_binding_component(data, Endpoint);
496 if (Options && *Options) *data++ = ',';
498 if (Options && *Options) {
499 data = escape_string_binding_component(data, Options);
508 /***********************************************************************
509 * RpcStringBindingComposeW (RPCRT4.@)
511 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
512 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
513 RPC_WSTR Options, RPC_WSTR* StringBinding )
518 TRACE("(%s,%s,%s,%s,%s,%p)\n",
519 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
520 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
521 debugstr_w( Options ), StringBinding);
523 /* overestimate for each component for escaping of delimiters */
524 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1;
525 if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1;
526 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2;
527 if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2;
528 if (Options && *Options) len += strlenW(Options) * 2 + 2;
530 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
531 *StringBinding = data;
533 if (ObjUuid && *ObjUuid) {
534 data = escape_string_binding_componentW(data, ObjUuid);
537 if (Protseq && *Protseq) {
538 data = escape_string_binding_componentW(data, Protseq);
541 if (NetworkAddr && *NetworkAddr) {
542 data = escape_string_binding_componentW(data, NetworkAddr);
544 if ((Endpoint && *Endpoint) ||
545 (Options && *Options)) {
547 if (Endpoint && *Endpoint) {
548 data = escape_string_binding_componentW(data, Endpoint);
549 if (Options && *Options) *data++ = ',';
551 if (Options && *Options) {
552 data = escape_string_binding_componentW(data, Options);
562 /***********************************************************************
563 * RpcStringBindingParseA (RPCRT4.@)
565 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
566 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
567 RPC_CSTR *Endpoint, RPC_CSTR *Options)
569 const unsigned char *data, *next;
570 static const char ep_opt[] = "endpoint=";
571 BOOL endpoint_already_found = FALSE;
573 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
574 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
576 if (ObjUuid) *ObjUuid = NULL;
577 if (Protseq) *Protseq = NULL;
578 if (NetworkAddr) *NetworkAddr = NULL;
579 if (Endpoint) *Endpoint = NULL;
580 if (Options) *Options = NULL;
582 data = StringBinding;
584 next = string_binding_find_delimiter(data, '@');
588 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
589 status = UuidFromStringA(str_uuid, &uuid);
590 if (status != RPC_S_OK) {
591 HeapFree(GetProcessHeap(), 0, str_uuid);
597 HeapFree(GetProcessHeap(), 0, str_uuid);
601 next = string_binding_find_delimiter(data, ':');
603 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
607 next = string_binding_find_delimiter(data, '[');
609 const unsigned char *close;
612 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
614 close = string_binding_find_delimiter(data, ']');
615 if (!close) goto fail;
617 /* tokenize options */
618 while (data < close) {
619 next = string_binding_find_delimiter(data, ',');
620 if (!next || next > close) next = close;
621 /* FIXME: this is kind of inefficient */
622 opt = unescape_string_binding_component(data, next - data);
626 next = string_binding_find_delimiter(opt, '=');
628 /* not an option, must be an endpoint */
629 if (endpoint_already_found) goto fail;
630 if (Endpoint) *Endpoint = opt;
631 else HeapFree(GetProcessHeap(), 0, opt);
632 endpoint_already_found = TRUE;
634 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
635 /* endpoint option */
636 if (endpoint_already_found) goto fail;
637 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
638 HeapFree(GetProcessHeap(), 0, opt);
639 endpoint_already_found = TRUE;
644 /* FIXME: this is kind of inefficient */
645 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
646 HeapFree(GetProcessHeap(), 0, opt);
650 HeapFree(GetProcessHeap(), 0, opt);
656 if (*data) goto fail;
658 else if (NetworkAddr)
659 *NetworkAddr = unescape_string_binding_component(data, -1);
664 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
665 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
666 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
667 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
668 if (Options) RpcStringFreeA((unsigned char**)Options);
669 return RPC_S_INVALID_STRING_BINDING;
672 /***********************************************************************
673 * RpcStringBindingParseW (RPCRT4.@)
675 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
676 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
677 RPC_WSTR *Endpoint, RPC_WSTR *Options)
679 const WCHAR *data, *next;
680 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
681 BOOL endpoint_already_found = FALSE;
683 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
684 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
686 if (ObjUuid) *ObjUuid = NULL;
687 if (Protseq) *Protseq = NULL;
688 if (NetworkAddr) *NetworkAddr = NULL;
689 if (Endpoint) *Endpoint = NULL;
690 if (Options) *Options = NULL;
692 data = StringBinding;
694 next = string_binding_find_delimiterW(data, '@');
698 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
699 status = UuidFromStringW(str_uuid, &uuid);
700 if (status != RPC_S_OK) {
701 HeapFree(GetProcessHeap(), 0, str_uuid);
707 HeapFree(GetProcessHeap(), 0, str_uuid);
711 next = string_binding_find_delimiterW(data, ':');
713 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
717 next = string_binding_find_delimiterW(data, '[');
722 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
724 close = string_binding_find_delimiterW(data, ']');
725 if (!close) goto fail;
727 /* tokenize options */
728 while (data < close) {
729 next = string_binding_find_delimiterW(data, ',');
730 if (!next || next > close) next = close;
731 /* FIXME: this is kind of inefficient */
732 opt = unescape_string_binding_componentW(data, next - data);
736 next = string_binding_find_delimiterW(opt, '=');
738 /* not an option, must be an endpoint */
739 if (endpoint_already_found) goto fail;
740 if (Endpoint) *Endpoint = opt;
741 else HeapFree(GetProcessHeap(), 0, opt);
742 endpoint_already_found = TRUE;
744 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
745 /* endpoint option */
746 if (endpoint_already_found) goto fail;
747 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
748 HeapFree(GetProcessHeap(), 0, opt);
749 endpoint_already_found = TRUE;
754 /* FIXME: this is kind of inefficient */
755 *Options = RPCRT4_strconcatW(*Options, opt);
756 HeapFree(GetProcessHeap(), 0, opt);
760 HeapFree(GetProcessHeap(), 0, opt);
766 if (*data) goto fail;
767 } else if (NetworkAddr)
768 *NetworkAddr = unescape_string_binding_componentW(data, -1);
773 if (ObjUuid) RpcStringFreeW(ObjUuid);
774 if (Protseq) RpcStringFreeW(Protseq);
775 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
776 if (Endpoint) RpcStringFreeW(Endpoint);
777 if (Options) RpcStringFreeW(Options);
778 return RPC_S_INVALID_STRING_BINDING;
781 /***********************************************************************
782 * RpcBindingFree (RPCRT4.@)
784 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
787 TRACE("(%p) = %p\n", Binding, *Binding);
788 status = RPCRT4_ReleaseBinding(*Binding);
789 if (status == RPC_S_OK) *Binding = 0;
793 /***********************************************************************
794 * RpcBindingVectorFree (RPCRT4.@)
796 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
801 TRACE("(%p)\n", BindingVector);
802 for (c=0; c<(*BindingVector)->Count; c++) {
803 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
805 HeapFree(GetProcessHeap(), 0, *BindingVector);
806 *BindingVector = NULL;
810 /***********************************************************************
811 * RpcBindingInqObject (RPCRT4.@)
813 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
815 RpcBinding* bind = (RpcBinding*)Binding;
817 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
818 *ObjectUuid = bind->ObjectUuid;
822 /***********************************************************************
823 * RpcBindingSetObject (RPCRT4.@)
825 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
827 RpcBinding* bind = (RpcBinding*)Binding;
829 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
830 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
831 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
834 /***********************************************************************
835 * RpcBindingFromStringBindingA (RPCRT4.@)
837 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
840 RpcBinding* bind = NULL;
841 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
844 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
846 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
847 &NetworkAddr, &Endpoint, &Options);
848 if (ret != RPC_S_OK) return ret;
850 ret = UuidFromStringA(ObjectUuid, &Uuid);
853 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
854 if (ret != RPC_S_OK) return ret;
855 ret = RPCRT4_SetBindingObject(bind, &Uuid);
857 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
859 RpcStringFreeA((unsigned char**)&Options);
860 RpcStringFreeA((unsigned char**)&Endpoint);
861 RpcStringFreeA((unsigned char**)&NetworkAddr);
862 RpcStringFreeA((unsigned char**)&Protseq);
863 RpcStringFreeA((unsigned char**)&ObjectUuid);
866 *Binding = (RPC_BINDING_HANDLE)bind;
868 RPCRT4_ReleaseBinding(bind);
873 /***********************************************************************
874 * RpcBindingFromStringBindingW (RPCRT4.@)
876 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
879 RpcBinding* bind = NULL;
880 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
883 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
885 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
886 &NetworkAddr, &Endpoint, &Options);
887 if (ret != RPC_S_OK) return ret;
889 ret = UuidFromStringW(ObjectUuid, &Uuid);
892 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
893 if (ret != RPC_S_OK) return ret;
894 ret = RPCRT4_SetBindingObject(bind, &Uuid);
896 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
898 RpcStringFreeW(&Options);
899 RpcStringFreeW(&Endpoint);
900 RpcStringFreeW(&NetworkAddr);
901 RpcStringFreeW(&Protseq);
902 RpcStringFreeW(&ObjectUuid);
905 *Binding = (RPC_BINDING_HANDLE)bind;
907 RPCRT4_ReleaseBinding(bind);
912 /***********************************************************************
913 * RpcBindingToStringBindingA (RPCRT4.@)
915 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
918 RpcBinding* bind = (RpcBinding*)Binding;
921 TRACE("(%p,%p)\n", Binding, StringBinding);
923 if (UuidIsNil(&bind->ObjectUuid, &ret))
927 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
928 if (ret != RPC_S_OK) return ret;
931 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
932 (unsigned char*) bind->Endpoint, NULL, StringBinding);
934 RpcStringFreeA(&ObjectUuid);
939 /***********************************************************************
940 * RpcBindingToStringBindingW (RPCRT4.@)
942 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
945 unsigned char *str = NULL;
946 TRACE("(%p,%p)\n", Binding, StringBinding);
947 ret = RpcBindingToStringBindingA(Binding, &str);
948 *StringBinding = RPCRT4_strdupAtoW((char*)str);
949 RpcStringFreeA((unsigned char**)&str);
953 /***********************************************************************
954 * I_RpcBindingInqTransportType (RPCRT4.@)
956 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
959 FIXME( "(%p,%p): stub\n", Binding, Type);
960 *Type = TRANSPORT_TYPE_LPC;
964 /***********************************************************************
965 * I_RpcBindingSetAsync (RPCRT4.@)
967 * Exists in win9x and winNT, but with different number of arguments
968 * (9x version has 3 arguments, NT has 2).
970 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
972 RpcBinding* bind = (RpcBinding*)Binding;
974 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
976 bind->BlockingFn = BlockingFn;
981 /***********************************************************************
982 * RpcBindingCopy (RPCRT4.@)
984 RPC_STATUS RPC_ENTRY RpcBindingCopy(
985 RPC_BINDING_HANDLE SourceBinding,
986 RPC_BINDING_HANDLE* DestinationBinding)
988 RpcBinding *DestBinding;
989 RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
992 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
994 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
995 if (status != RPC_S_OK) return status;
997 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
998 DestBinding->BlockingFn = SrcBinding->BlockingFn;
999 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
1000 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
1001 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
1002 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
1003 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1004 DestBinding->Assoc = SrcBinding->Assoc;
1006 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1007 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1008 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1009 DestBinding->QOS = SrcBinding->QOS;
1011 *DestinationBinding = DestBinding;
1015 /***********************************************************************
1016 * RpcBindingReset (RPCRT4.@)
1018 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
1020 RpcBinding *bind = Binding;
1022 TRACE("(%p)\n", Binding);
1024 RPCRT4_strfree(bind->Endpoint);
1025 bind->Endpoint = NULL;
1026 if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
1032 /***********************************************************************
1033 * RpcImpersonateClient (RPCRT4.@)
1035 * Impersonates the client connected via a binding handle so that security
1036 * checks are done in the context of the client.
1039 * BindingHandle [I] Handle to the binding to the client.
1042 * Success: RPS_S_OK.
1043 * Failure: RPC_STATUS value.
1047 * If BindingHandle is NULL then the function impersonates the client
1048 * connected to the binding handle of the current thread.
1050 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1052 FIXME("(%p): stub\n", BindingHandle);
1053 ImpersonateSelf(SecurityImpersonation);
1057 /***********************************************************************
1058 * RpcRevertToSelfEx (RPCRT4.@)
1060 * Stops impersonating the client connected to the binding handle so that security
1061 * checks are no longer done in the context of the client.
1064 * BindingHandle [I] Handle to the binding to the client.
1067 * Success: RPS_S_OK.
1068 * Failure: RPC_STATUS value.
1072 * If BindingHandle is NULL then the function stops impersonating the client
1073 * connected to the binding handle of the current thread.
1075 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1077 FIXME("(%p): stub\n", BindingHandle);
1081 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1085 case RPC_C_AUTHN_GSS_NEGOTIATE:
1086 case RPC_C_AUTHN_WINNT:
1087 case RPC_C_AUTHN_GSS_KERBEROS:
1094 static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1095 CredHandle cred, TimeStamp exp,
1097 RPC_AUTH_IDENTITY_HANDLE identity,
1100 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1102 return ERROR_OUTOFMEMORY;
1105 AuthInfo->AuthnLevel = AuthnLevel;
1106 AuthInfo->AuthnSvc = AuthnSvc;
1107 AuthInfo->cred = cred;
1108 AuthInfo->exp = exp;
1109 AuthInfo->cbMaxToken = cbMaxToken;
1110 AuthInfo->identity = identity;
1111 AuthInfo->server_principal_name = NULL;
1113 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1114 * enable better matching in RpcAuthInfo_IsEqual */
1115 if (identity && has_nt_auth_identity(AuthnSvc))
1117 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1118 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1119 if (!AuthInfo->nt_identity)
1121 HeapFree(GetProcessHeap(), 0, AuthInfo);
1122 return ERROR_OUTOFMEMORY;
1125 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1126 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1127 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1129 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1130 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1131 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1132 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1134 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1135 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1136 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1137 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1139 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1140 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1142 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1143 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1144 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1146 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1147 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1148 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1149 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1150 HeapFree(GetProcessHeap(), 0, AuthInfo);
1151 return ERROR_OUTOFMEMORY;
1155 AuthInfo->nt_identity = NULL;
1160 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1162 return InterlockedIncrement(&AuthInfo->refs);
1165 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1167 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1171 FreeCredentialsHandle(&AuthInfo->cred);
1172 if (AuthInfo->nt_identity)
1174 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1175 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1176 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1177 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1179 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
1180 HeapFree(GetProcessHeap(), 0, AuthInfo);
1186 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1188 if (AuthInfo1 == AuthInfo2)
1191 if (!AuthInfo1 || !AuthInfo2)
1194 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1195 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1198 if (AuthInfo1->identity == AuthInfo2->identity)
1201 if (!AuthInfo1->identity || !AuthInfo2->identity)
1204 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1206 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1207 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1208 /* compare user names */
1209 if (identity1->UserLength != identity2->UserLength ||
1210 memcmp(identity1->User, identity2->User, identity1->UserLength))
1212 /* compare domain names */
1213 if (identity1->DomainLength != identity2->DomainLength ||
1214 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1216 /* compare passwords */
1217 if (identity1->PasswordLength != identity2->PasswordLength ||
1218 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1227 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1229 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1232 return RPC_S_OUT_OF_RESOURCES;
1235 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1236 if (!qos->qos) goto error;
1237 qos->qos->Version = qos_src->Version;
1238 qos->qos->Capabilities = qos_src->Capabilities;
1239 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1240 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1241 qos->qos->AdditionalSecurityInfoType = 0;
1243 if (qos_src->Version >= 2)
1245 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1246 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1247 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1249 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1250 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1252 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1253 qos->qos->u.HttpCredentials = http_credentials_dst;
1254 if (!http_credentials_dst) goto error;
1255 http_credentials_dst->TransportCredentials = NULL;
1256 http_credentials_dst->Flags = http_credentials_src->Flags;
1257 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1258 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1259 http_credentials_dst->AuthnSchemes = NULL;
1260 http_credentials_dst->ServerCertificateSubject = NULL;
1261 if (http_credentials_src->TransportCredentials)
1263 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1264 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1265 if (!cred_dst) goto error;
1266 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1269 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1270 cred_dst->UserLength = cred_src->UserLength;
1271 cred_dst->PasswordLength = cred_src->PasswordLength;
1272 cred_dst->DomainLength = cred_src->DomainLength;
1273 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1274 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1275 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1279 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1280 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1281 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1282 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1283 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1284 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1285 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1286 if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error;
1287 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1288 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1289 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1292 if (http_credentials_src->NumberOfAuthnSchemes)
1294 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1295 if (!http_credentials_dst->AuthnSchemes) goto error;
1296 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1298 if (http_credentials_src->ServerCertificateSubject)
1301 http_credentials_dst->ServerCertificateSubject =
1302 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1303 strlenW(http_credentials_src->ServerCertificateSubject));
1305 http_credentials_dst->ServerCertificateSubject =
1306 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1307 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1317 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1318 qos->qos->u.HttpCredentials)
1320 if (qos->qos->u.HttpCredentials->TransportCredentials)
1322 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1323 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1324 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1325 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1327 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1328 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1329 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1331 HeapFree(GetProcessHeap(), 0, qos->qos);
1333 HeapFree(GetProcessHeap(), 0, qos);
1334 return RPC_S_OUT_OF_RESOURCES;
1337 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1339 return InterlockedIncrement(&qos->refs);
1342 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1344 ULONG refs = InterlockedDecrement(&qos->refs);
1348 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1350 if (qos->qos->u.HttpCredentials->TransportCredentials)
1352 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1353 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1354 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1355 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1357 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1358 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1359 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1361 HeapFree(GetProcessHeap(), 0, qos->qos);
1362 HeapFree(GetProcessHeap(), 0, qos);
1367 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1375 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1376 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1377 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1378 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1379 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1381 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1382 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1383 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1384 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1387 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1389 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1390 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1392 if (http_credentials1->Flags != http_credentials2->Flags)
1395 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1398 /* authentication schemes and server certificate subject not currently used */
1400 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1402 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1403 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1405 if (!identity1 || !identity2)
1408 /* compare user names */
1409 if (identity1->UserLength != identity2->UserLength ||
1410 memcmp(identity1->User, identity2->User, identity1->UserLength))
1412 /* compare domain names */
1413 if (identity1->DomainLength != identity2->DomainLength ||
1414 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1416 /* compare passwords */
1417 if (identity1->PasswordLength != identity2->PasswordLength ||
1418 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1426 /***********************************************************************
1427 * RpcRevertToSelf (RPCRT4.@)
1429 RPC_STATUS WINAPI RpcRevertToSelf(void)
1436 /***********************************************************************
1437 * RpcMgmtSetComTimeout (RPCRT4.@)
1439 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1441 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1445 /***********************************************************************
1446 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1448 RPCRTAPI RPC_STATUS RPC_ENTRY
1449 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1450 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1451 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1453 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1454 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1455 return RPC_S_INVALID_BINDING;
1458 /***********************************************************************
1459 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1461 RPCRTAPI RPC_STATUS RPC_ENTRY
1462 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1463 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1464 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1466 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1467 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1468 return RPC_S_INVALID_BINDING;
1471 /***********************************************************************
1472 * RpcBindingInqAuthInfoA (RPCRT4.@)
1474 RPCRTAPI RPC_STATUS RPC_ENTRY
1475 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1476 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1478 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1479 AuthnSvc, AuthIdentity, AuthzSvc);
1480 return RPC_S_INVALID_BINDING;
1483 /***********************************************************************
1484 * RpcBindingInqAuthInfoW (RPCRT4.@)
1486 RPCRTAPI RPC_STATUS RPC_ENTRY
1487 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1488 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1490 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1491 AuthnSvc, AuthIdentity, AuthzSvc);
1492 return RPC_S_INVALID_BINDING;
1495 /***********************************************************************
1496 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1498 RPCRTAPI RPC_STATUS RPC_ENTRY
1499 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1500 ULONG AuthnLevel, ULONG AuthnSvc,
1501 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1502 RPC_SECURITY_QOS *SecurityQos )
1504 RpcBinding* bind = (RpcBinding*)Binding;
1508 ULONG package_count;
1510 PSecPkgInfoA packages;
1513 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1514 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1520 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1521 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1522 if (SecurityQos->Version >= 2)
1524 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1525 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1526 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1527 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1528 SecurityQos2->u.HttpCredentials->TransportCredentials,
1529 SecurityQos2->u.HttpCredentials->Flags,
1530 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1531 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1532 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1533 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1536 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1537 if (status != RPC_S_OK)
1542 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1546 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1547 AuthnSvc = RPC_C_AUTHN_WINNT;
1549 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1550 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1551 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1553 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1555 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1556 bind->AuthInfo = NULL;
1560 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1562 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1563 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1566 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1567 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1569 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1570 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1573 r = EnumerateSecurityPackagesA(&package_count, &packages);
1576 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1577 return RPC_S_SEC_PKG_ERROR;
1580 for (i = 0; i < package_count; i++)
1581 if (packages[i].wRPCID == AuthnSvc)
1584 if (i == package_count)
1586 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1587 FreeContextBuffer(packages);
1588 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1591 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1592 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1593 AuthIdentity, NULL, NULL, &cred, &exp);
1594 cbMaxToken = packages[i].cbMaxToken;
1595 FreeContextBuffer(packages);
1596 if (r == ERROR_SUCCESS)
1598 RpcAuthInfo *new_auth_info;
1599 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1600 AuthIdentity, &new_auth_info);
1603 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1604 if (new_auth_info->server_principal_name)
1606 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1607 bind->AuthInfo = new_auth_info;
1611 RpcAuthInfo_Release(new_auth_info);
1612 r = ERROR_OUTOFMEMORY;
1616 FreeCredentialsHandle(&cred);
1621 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1622 return RPC_S_SEC_PKG_ERROR;
1626 /***********************************************************************
1627 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1629 RPCRTAPI RPC_STATUS RPC_ENTRY
1630 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1631 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1632 RPC_SECURITY_QOS *SecurityQos )
1634 RpcBinding* bind = (RpcBinding*)Binding;
1638 ULONG package_count;
1640 PSecPkgInfoW packages;
1643 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1644 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1650 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1651 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1652 if (SecurityQos->Version >= 2)
1654 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1655 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1656 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1657 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1658 SecurityQos2->u.HttpCredentials->TransportCredentials,
1659 SecurityQos2->u.HttpCredentials->Flags,
1660 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1661 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1662 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1663 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1666 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1667 if (status != RPC_S_OK)
1672 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1676 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1677 AuthnSvc = RPC_C_AUTHN_WINNT;
1679 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1680 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1681 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1683 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1685 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1686 bind->AuthInfo = NULL;
1690 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1692 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1693 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1696 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1697 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1699 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1700 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1703 r = EnumerateSecurityPackagesW(&package_count, &packages);
1706 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r);
1707 return RPC_S_SEC_PKG_ERROR;
1710 for (i = 0; i < package_count; i++)
1711 if (packages[i].wRPCID == AuthnSvc)
1714 if (i == package_count)
1716 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1717 FreeContextBuffer(packages);
1718 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1721 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1722 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1723 AuthIdentity, NULL, NULL, &cred, &exp);
1724 cbMaxToken = packages[i].cbMaxToken;
1725 FreeContextBuffer(packages);
1726 if (r == ERROR_SUCCESS)
1728 RpcAuthInfo *new_auth_info;
1729 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1730 AuthIdentity, &new_auth_info);
1733 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
1734 if (!ServerPrincName || new_auth_info->server_principal_name)
1736 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1737 bind->AuthInfo = new_auth_info;
1741 RpcAuthInfo_Release(new_auth_info);
1742 r = ERROR_OUTOFMEMORY;
1746 FreeCredentialsHandle(&cred);
1751 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r);
1752 return RPC_S_SEC_PKG_ERROR;
1756 /***********************************************************************
1757 * RpcBindingSetAuthInfoA (RPCRT4.@)
1759 RPCRTAPI RPC_STATUS RPC_ENTRY
1760 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1761 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1763 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1764 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1765 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1768 /***********************************************************************
1769 * RpcBindingSetAuthInfoW (RPCRT4.@)
1771 RPCRTAPI RPC_STATUS RPC_ENTRY
1772 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1773 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1775 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1776 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1777 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1780 /***********************************************************************
1781 * RpcBindingSetOption (RPCRT4.@)
1783 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1785 FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue);