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
35 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 #include "rpc_binding.h"
43 #include "rpc_message.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
47 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
51 if (!src) return NULL;
52 if (slen == -1) slen = strlen(src);
54 s = HeapAlloc(GetProcessHeap(), 0, len+1);
60 LPSTR RPCRT4_strdupWtoA(LPWSTR src)
64 if (!src) return NULL;
65 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
66 s = HeapAlloc(GetProcessHeap(), 0, len);
67 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
71 LPWSTR RPCRT4_strdupAtoW(LPSTR src)
75 if (!src) return NULL;
76 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
77 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
78 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
82 LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen)
86 if (!src) return NULL;
87 if (slen == -1) slen = strlenW(src);
89 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
90 memcpy(s, src, len*sizeof(WCHAR));
95 void RPCRT4_strfree(LPSTR src)
97 HeapFree(GetProcessHeap(), 0, src);
100 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
102 RpcBinding* NewBinding;
104 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
105 NewBinding->refs = 1;
106 NewBinding->server = server;
108 *Binding = NewBinding;
113 RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
115 RpcBinding* NewBinding;
117 RPCRT4_AllocBinding(&NewBinding, server);
118 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
120 TRACE("binding: %p\n", NewBinding);
121 *Binding = NewBinding;
126 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
128 RpcBinding* NewBinding;
130 RPCRT4_AllocBinding(&NewBinding, server);
131 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
133 TRACE("binding: %p\n", NewBinding);
134 *Binding = NewBinding;
139 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions)
141 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
142 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
144 RPCRT4_strfree(Binding->NetworkAddr);
145 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
146 RPCRT4_strfree(Binding->Endpoint);
148 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
150 Binding->Endpoint = RPCRT4_strdupA("");
152 if (!Binding->Endpoint) ERR("out of memory?\n");
157 RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
159 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
160 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
162 RPCRT4_strfree(Binding->NetworkAddr);
163 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
164 RPCRT4_strfree(Binding->Endpoint);
166 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
168 Binding->Endpoint = RPCRT4_strdupA("");
170 if (!Binding->Endpoint) ERR("out of memory?\n");
175 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
177 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
179 RPCRT4_strfree(Binding->Endpoint);
180 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
185 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
187 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
188 if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
189 else UuidCreateNil(&Binding->ObjectUuid);
193 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
195 RpcBinding* NewBinding;
196 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
198 RPCRT4_AllocBinding(&NewBinding, Connection->server);
199 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
200 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
201 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
202 NewBinding->FromConn = Connection;
204 TRACE("binding: %p\n", NewBinding);
205 *Binding = NewBinding;
210 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
212 InterlockedIncrement(&OldBinding->refs);
213 *Binding = OldBinding;
217 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
219 if (InterlockedDecrement(&Binding->refs))
222 TRACE("binding: %p\n", Binding);
223 /* FIXME: release connections */
224 RPCRT4_strfree(Binding->Endpoint);
225 RPCRT4_strfree(Binding->NetworkAddr);
226 RPCRT4_strfree(Binding->Protseq);
227 HeapFree(GetProcessHeap(), 0, Binding);
231 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
232 PRPC_SYNTAX_IDENTIFIER TransferSyntax,
233 PRPC_SYNTAX_IDENTIFIER InterfaceId)
235 RpcConnection* NewConnection;
238 TRACE("(Binding == ^%p)\n", Binding);
240 if (!Binding->server) {
241 /* try to find a compatible connection from the connection pool */
242 NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
243 Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
246 *Connection = NewConnection;
250 /* we already have a connection with acceptable binding, so use it */
251 if (Binding->FromConn) {
252 *Connection = Binding->FromConn;
257 /* create a new connection */
258 status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
259 Binding->Protseq, Binding->NetworkAddr,
260 Binding->Endpoint, NULL, Binding->AuthInfo,
262 if (status != RPC_S_OK)
265 status = RPCRT4_OpenClientConnection(NewConnection);
266 if (status != RPC_S_OK)
268 RPCRT4_DestroyConnection(NewConnection);
272 /* we need to send a binding packet if we are client. */
273 if (!NewConnection->server) {
275 RpcPktHdr *response_hdr;
278 TRACE("sending bind request to server\n");
280 hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
281 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
282 InterfaceId, TransferSyntax);
284 status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
285 RPCRT4_FreeHeader(hdr);
286 if (status != RPC_S_OK) {
287 RPCRT4_DestroyConnection(NewConnection);
291 status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
292 if (status != RPC_S_OK) {
293 ERR("receive failed\n");
294 RPCRT4_DestroyConnection(NewConnection);
298 if (response_hdr->common.ptype != PKT_BIND_ACK ||
299 response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
300 ERR("failed to bind for interface %s, %d.%d\n",
301 debugstr_guid(&InterfaceId->SyntaxGUID),
302 InterfaceId->SyntaxVersion.MajorVersion,
303 InterfaceId->SyntaxVersion.MinorVersion);
304 RPCRT4_FreeHeader(response_hdr);
305 RPCRT4_DestroyConnection(NewConnection);
306 return RPC_S_PROTOCOL_ERROR;
309 /* FIXME: do more checks? */
311 NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
312 NewConnection->ActiveInterface = *InterfaceId;
313 RPCRT4_FreeHeader(response_hdr);
317 Binding->FromConn = NewConnection;
318 *Connection = NewConnection;
323 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
325 TRACE("(Binding == ^%p)\n", Binding);
326 if (!Connection) return RPC_S_OK;
327 if (Binding->server) {
328 /* don't destroy a connection that is cached in the binding */
329 if (Binding->FromConn == Connection)
331 return RPCRT4_DestroyConnection(Connection);
334 RPCRT4_ReleaseIdleConnection(Connection);
339 /* utility functions for string composing and parsing */
340 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
342 unsigned len = strlen(src);
343 memcpy(data, src, len*sizeof(CHAR));
347 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
349 unsigned len = strlenW(src);
350 memcpy(data, src, len*sizeof(WCHAR));
354 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
356 DWORD len = strlen(dst), slen = strlen(src);
357 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
360 HeapFree(GetProcessHeap(), 0, dst);
364 memcpy(ndst+len+1, src, slen+1);
368 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
370 DWORD len = strlenW(dst), slen = strlenW(src);
371 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
374 HeapFree(GetProcessHeap(), 0, dst);
378 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
383 /***********************************************************************
384 * RpcStringBindingComposeA (RPCRT4.@)
386 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
387 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
388 RPC_CSTR Options, RPC_CSTR *StringBinding )
393 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
394 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
395 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
396 debugstr_a( (char*)Options ), StringBinding );
398 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
399 if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
400 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
401 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
402 if (Options && *Options) len += strlen((char*)Options) + 2;
404 data = HeapAlloc(GetProcessHeap(), 0, len);
405 *StringBinding = (unsigned char*)data;
407 if (ObjUuid && *ObjUuid) {
408 data += RPCRT4_strcopyA(data, (char*)ObjUuid);
411 if (Protseq && *Protseq) {
412 data += RPCRT4_strcopyA(data, (char*)Protseq);
415 if (NetworkAddr && *NetworkAddr)
416 data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
418 if ((Endpoint && *Endpoint) ||
419 (Options && *Options)) {
421 if (Endpoint && *Endpoint) {
422 data += RPCRT4_strcopyA(data, (char*)Endpoint);
423 if (Options && *Options) *data++ = ',';
425 if (Options && *Options) {
426 data += RPCRT4_strcopyA(data, (char*)Options);
435 /***********************************************************************
436 * RpcStringBindingComposeW (RPCRT4.@)
438 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
439 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
440 RPC_WSTR Options, RPC_WSTR* StringBinding )
445 TRACE("(%s,%s,%s,%s,%s,%p)\n",
446 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
447 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
448 debugstr_w( Options ), StringBinding);
450 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
451 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
452 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
453 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
454 if (Options && *Options) len += strlenW(Options) + 2;
456 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
457 *StringBinding = data;
459 if (ObjUuid && *ObjUuid) {
460 data += RPCRT4_strcopyW(data, ObjUuid);
463 if (Protseq && *Protseq) {
464 data += RPCRT4_strcopyW(data, Protseq);
467 if (NetworkAddr && *NetworkAddr) {
468 data += RPCRT4_strcopyW(data, NetworkAddr);
470 if ((Endpoint && *Endpoint) ||
471 (Options && *Options)) {
473 if (Endpoint && *Endpoint) {
474 data += RPCRT4_strcopyW(data, Endpoint);
475 if (Options && *Options) *data++ = ',';
477 if (Options && *Options) {
478 data += RPCRT4_strcopyW(data, Options);
488 /***********************************************************************
489 * RpcStringBindingParseA (RPCRT4.@)
491 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
492 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
493 RPC_CSTR *Endpoint, RPC_CSTR *Options)
496 static const char ep_opt[] = "endpoint=";
498 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
499 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
501 if (ObjUuid) *ObjUuid = NULL;
502 if (Protseq) *Protseq = NULL;
503 if (NetworkAddr) *NetworkAddr = NULL;
504 if (Endpoint) *Endpoint = NULL;
505 if (Options) *Options = NULL;
507 data = (char*) StringBinding;
509 next = strchr(data, '@');
511 if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
515 next = strchr(data, ':');
517 if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
521 next = strchr(data, '[');
525 if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
527 close = strchr(data, ']');
528 if (!close) goto fail;
530 /* tokenize options */
531 while (data < close) {
532 next = strchr(data, ',');
533 if (!next || next > close) next = close;
534 /* FIXME: this is kind of inefficient */
535 opt = RPCRT4_strndupA(data, next - data);
539 next = strchr(opt, '=');
541 /* not an option, must be an endpoint */
542 if (*Endpoint) goto fail;
543 *Endpoint = (unsigned char*) opt;
545 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
546 /* endpoint option */
547 if (*Endpoint) goto fail;
548 *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
549 HeapFree(GetProcessHeap(), 0, opt);
553 /* FIXME: this is kind of inefficient */
554 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
555 HeapFree(GetProcessHeap(), 0, opt);
557 *Options = (unsigned char*) opt;
563 if (*data) goto fail;
565 else if (NetworkAddr)
566 *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
571 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
572 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
573 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
574 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
575 if (Options) RpcStringFreeA((unsigned char**)Options);
576 return RPC_S_INVALID_STRING_BINDING;
579 /***********************************************************************
580 * RpcStringBindingParseW (RPCRT4.@)
582 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
583 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
584 RPC_WSTR *Endpoint, RPC_WSTR *Options)
587 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
589 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
590 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
592 if (ObjUuid) *ObjUuid = NULL;
593 if (Protseq) *Protseq = NULL;
594 if (NetworkAddr) *NetworkAddr = NULL;
595 if (Endpoint) *Endpoint = NULL;
596 if (Options) *Options = NULL;
598 data = StringBinding;
600 next = strchrW(data, '@');
602 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
606 next = strchrW(data, ':');
608 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
612 next = strchrW(data, '[');
616 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
618 close = strchrW(data, ']');
619 if (!close) goto fail;
621 /* tokenize options */
622 while (data < close) {
623 next = strchrW(data, ',');
624 if (!next || next > close) next = close;
625 /* FIXME: this is kind of inefficient */
626 opt = RPCRT4_strndupW(data, next - data);
630 next = strchrW(opt, '=');
632 /* not an option, must be an endpoint */
633 if (*Endpoint) goto fail;
636 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
637 /* endpoint option */
638 if (*Endpoint) goto fail;
639 *Endpoint = RPCRT4_strdupW(next+1);
640 HeapFree(GetProcessHeap(), 0, opt);
644 /* FIXME: this is kind of inefficient */
645 *Options = RPCRT4_strconcatW(*Options, opt);
646 HeapFree(GetProcessHeap(), 0, opt);
654 if (*data) goto fail;
655 } else if (NetworkAddr)
656 *NetworkAddr = RPCRT4_strdupW(data);
661 if (ObjUuid) RpcStringFreeW(ObjUuid);
662 if (Protseq) RpcStringFreeW(Protseq);
663 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
664 if (Endpoint) RpcStringFreeW(Endpoint);
665 if (Options) RpcStringFreeW(Options);
666 return RPC_S_INVALID_STRING_BINDING;
669 /***********************************************************************
670 * RpcBindingFree (RPCRT4.@)
672 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
675 TRACE("(%p) = %p\n", Binding, *Binding);
676 status = RPCRT4_DestroyBinding(*Binding);
677 if (status == RPC_S_OK) *Binding = 0;
681 /***********************************************************************
682 * RpcBindingVectorFree (RPCRT4.@)
684 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
689 TRACE("(%p)\n", BindingVector);
690 for (c=0; c<(*BindingVector)->Count; c++) {
691 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
693 HeapFree(GetProcessHeap(), 0, *BindingVector);
694 *BindingVector = NULL;
698 /***********************************************************************
699 * RpcBindingInqObject (RPCRT4.@)
701 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
703 RpcBinding* bind = (RpcBinding*)Binding;
705 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
706 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
710 /***********************************************************************
711 * RpcBindingSetObject (RPCRT4.@)
713 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
715 RpcBinding* bind = (RpcBinding*)Binding;
717 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
718 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
719 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
722 /***********************************************************************
723 * RpcBindingFromStringBindingA (RPCRT4.@)
725 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
728 RpcBinding* bind = NULL;
729 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
732 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
734 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
735 &NetworkAddr, &Endpoint, &Options);
736 if (ret != RPC_S_OK) return ret;
738 ret = UuidFromStringA(ObjectUuid, &Uuid);
741 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
743 ret = RPCRT4_SetBindingObject(bind, &Uuid);
745 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
747 RpcStringFreeA((unsigned char**)&Options);
748 RpcStringFreeA((unsigned char**)&Endpoint);
749 RpcStringFreeA((unsigned char**)&NetworkAddr);
750 RpcStringFreeA((unsigned char**)&Protseq);
751 RpcStringFreeA((unsigned char**)&ObjectUuid);
754 *Binding = (RPC_BINDING_HANDLE)bind;
756 RPCRT4_DestroyBinding(bind);
761 /***********************************************************************
762 * RpcBindingFromStringBindingW (RPCRT4.@)
764 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
767 RpcBinding* bind = NULL;
768 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
771 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
773 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
774 &NetworkAddr, &Endpoint, &Options);
775 if (ret != RPC_S_OK) return ret;
777 ret = UuidFromStringW(ObjectUuid, &Uuid);
780 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
782 ret = RPCRT4_SetBindingObject(bind, &Uuid);
784 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
786 RpcStringFreeW(&Options);
787 RpcStringFreeW(&Endpoint);
788 RpcStringFreeW(&NetworkAddr);
789 RpcStringFreeW(&Protseq);
790 RpcStringFreeW(&ObjectUuid);
793 *Binding = (RPC_BINDING_HANDLE)bind;
795 RPCRT4_DestroyBinding(bind);
800 /***********************************************************************
801 * RpcBindingToStringBindingA (RPCRT4.@)
803 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
806 RpcBinding* bind = (RpcBinding*)Binding;
809 TRACE("(%p,%p)\n", Binding, StringBinding);
811 ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
812 if (ret != RPC_S_OK) return ret;
814 ret = RpcStringBindingComposeA((unsigned char*) ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
815 (unsigned char*) bind->Endpoint, NULL, StringBinding);
817 RpcStringFreeA((unsigned char**)&ObjectUuid);
822 /***********************************************************************
823 * RpcBindingToStringBindingW (RPCRT4.@)
825 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
828 unsigned char *str = NULL;
829 TRACE("(%p,%p)\n", Binding, StringBinding);
830 ret = RpcBindingToStringBindingA(Binding, &str);
831 *StringBinding = RPCRT4_strdupAtoW((char*)str);
832 RpcStringFreeA((unsigned char**)&str);
836 /***********************************************************************
837 * I_RpcBindingSetAsync (RPCRT4.@)
839 * Exists in win9x and winNT, but with different number of arguments
840 * (9x version has 3 arguments, NT has 2).
842 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
844 RpcBinding* bind = (RpcBinding*)Binding;
846 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
848 bind->BlockingFn = BlockingFn;
853 /***********************************************************************
854 * RpcBindingCopy (RPCRT4.@)
856 RPC_STATUS RPC_ENTRY RpcBindingCopy(
857 RPC_BINDING_HANDLE SourceBinding,
858 RPC_BINDING_HANDLE* DestinationBinding)
860 RpcBinding *DestBinding;
861 RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
864 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
866 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
867 if (status != RPC_S_OK) return status;
869 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
870 DestBinding->BlockingFn = SrcBinding->BlockingFn;
871 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
872 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
873 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
875 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
876 DestBinding->AuthInfo = SrcBinding->AuthInfo;
878 *DestinationBinding = DestBinding;
882 /***********************************************************************
883 * RpcImpersonateClient (RPCRT4.@)
885 * Impersonates the client connected via a binding handle so that security
886 * checks are done in the context of the client.
889 * BindingHandle [I] Handle to the binding to the client.
893 * Failure: RPC_STATUS value.
897 * If BindingHandle is NULL then the function impersonates the client
898 * connected to the binding handle of the current thread.
900 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
902 FIXME("(%p): stub\n", BindingHandle);
903 ImpersonateSelf(SecurityImpersonation);
907 /***********************************************************************
908 * RpcRevertToSelfEx (RPCRT4.@)
910 * Stops impersonating the client connected to the binding handle so that security
911 * checks are no longer done in the context of the client.
914 * BindingHandle [I] Handle to the binding to the client.
918 * Failure: RPC_STATUS value.
922 * If BindingHandle is NULL then the function stops impersonating the client
923 * connected to the binding handle of the current thread.
925 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
927 FIXME("(%p): stub\n", BindingHandle);
931 static RPC_STATUS RpcAuthInfo_Create(unsigned long AuthnLevel, unsigned long AuthnSvc, CredHandle cred, TimeStamp exp, RpcAuthInfo **ret)
933 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
935 return ERROR_OUTOFMEMORY;
937 AuthInfo->AuthnLevel = AuthnLevel;
938 AuthInfo->AuthnSvc = AuthnSvc;
939 AuthInfo->cred = cred;
945 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
947 return InterlockedIncrement(&AuthInfo->refs);
950 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
952 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
956 FreeCredentialsHandle(&AuthInfo->cred);
957 HeapFree(GetProcessHeap(), 0, AuthInfo);
963 /***********************************************************************
964 * RpcRevertToSelf (RPCRT4.@)
966 RPC_STATUS WINAPI RpcRevertToSelf(void)
973 /***********************************************************************
974 * RpcMgmtSetComTimeout (RPCRT4.@)
976 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
978 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
982 /***********************************************************************
983 * RpcBindingInqAuthInfoExA (RPCRT4.@)
985 RPCRTAPI RPC_STATUS RPC_ENTRY
986 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
987 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
988 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
990 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
991 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
992 return RPC_S_INVALID_BINDING;
995 /***********************************************************************
996 * RpcBindingInqAuthInfoExW (RPCRT4.@)
998 RPCRTAPI RPC_STATUS RPC_ENTRY
999 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
1000 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
1001 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1003 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1004 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1005 return RPC_S_INVALID_BINDING;
1008 /***********************************************************************
1009 * RpcBindingInqAuthInfoA (RPCRT4.@)
1011 RPCRTAPI RPC_STATUS RPC_ENTRY
1012 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
1013 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1015 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1016 AuthnSvc, AuthIdentity, AuthzSvc);
1017 return RPC_S_INVALID_BINDING;
1020 /***********************************************************************
1021 * RpcBindingInqAuthInfoW (RPCRT4.@)
1023 RPCRTAPI RPC_STATUS RPC_ENTRY
1024 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
1025 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1027 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1028 AuthnSvc, AuthIdentity, AuthzSvc);
1029 return RPC_S_INVALID_BINDING;
1032 /***********************************************************************
1033 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1035 RPCRTAPI RPC_STATUS RPC_ENTRY
1036 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1037 unsigned long AuthnLevel, unsigned long AuthnSvc,
1038 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1039 RPC_SECURITY_QOS *SecurityQos )
1041 RpcBinding* bind = (RpcBinding*)Binding;
1045 ULONG package_count;
1047 PSecPkgInfoA packages;
1049 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1050 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1052 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1053 AuthnSvc = RPC_C_AUTHN_WINNT;
1055 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1056 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1057 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1059 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1061 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1062 bind->AuthInfo = NULL;
1066 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1068 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1069 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1074 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1075 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1079 FIXME("SecurityQos ignored\n");
1081 r = EnumerateSecurityPackagesA(&package_count, &packages);
1084 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1085 return RPC_S_SEC_PKG_ERROR;
1088 for (i = 0; i < package_count; i++)
1089 if (packages[i].wRPCID == AuthnSvc)
1092 if (i == package_count)
1094 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1095 FreeContextBuffer(packages);
1096 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1099 TRACE("found package %s for service %ld\n", packages[i].Name, AuthnSvc);
1100 r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1101 AuthIdentity, NULL, NULL, &cred, &exp);
1102 FreeContextBuffer(packages);
1103 if (r == ERROR_SUCCESS)
1105 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1106 bind->AuthInfo = NULL;
1107 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1109 FreeCredentialsHandle(&cred);
1114 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1115 return RPC_S_SEC_PKG_ERROR;
1119 /***********************************************************************
1120 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1122 RPCRTAPI RPC_STATUS RPC_ENTRY
1123 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1124 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1125 RPC_SECURITY_QOS *SecurityQos )
1127 RpcBinding* bind = (RpcBinding*)Binding;
1131 ULONG package_count;
1133 PSecPkgInfoW packages;
1135 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1136 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1138 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1139 AuthnSvc = RPC_C_AUTHN_WINNT;
1141 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1142 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1143 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1145 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1147 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1148 bind->AuthInfo = NULL;
1152 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1154 FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1155 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1160 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1161 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1165 FIXME("SecurityQos ignored\n");
1167 r = EnumerateSecurityPackagesW(&package_count, &packages);
1170 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1171 return RPC_S_SEC_PKG_ERROR;
1174 for (i = 0; i < package_count; i++)
1175 if (packages[i].wRPCID == AuthnSvc)
1178 if (i == package_count)
1180 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1181 FreeContextBuffer(packages);
1182 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1185 TRACE("found package %s for service %ld\n", debugstr_w(packages[i].Name), AuthnSvc);
1186 r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1187 AuthIdentity, NULL, NULL, &cred, &exp);
1188 FreeContextBuffer(packages);
1189 if (r == ERROR_SUCCESS)
1191 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1192 bind->AuthInfo = NULL;
1193 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1195 FreeCredentialsHandle(&cred);
1200 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1201 return RPC_S_SEC_PKG_ERROR;
1205 /***********************************************************************
1206 * RpcBindingSetAuthInfoA (RPCRT4.@)
1208 RPCRTAPI RPC_STATUS RPC_ENTRY
1209 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, unsigned long AuthnLevel,
1210 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1212 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1213 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1214 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1217 /***********************************************************************
1218 * RpcBindingSetAuthInfoW (RPCRT4.@)
1220 RPCRTAPI RPC_STATUS RPC_ENTRY
1221 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1222 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1224 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1225 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1226 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1229 /***********************************************************************
1230 * RpcBindingSetOption (RPCRT4.@)
1232 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1234 FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue);