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_message.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
);
161 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
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
,
172 if (status
!= RPC_S_OK
)
178 static RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPCWSTR NetworkAddr
,
179 LPCWSTR Endpoint
, LPCWSTR NetworkOptions
)
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
);
190 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
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
,
201 if (status
!= RPC_S_OK
)
207 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPCSTR Endpoint
)
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
,
221 if (status
!= 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
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
231 else UuidCreateNil(&Binding
->ObjectUuid
);
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
;
252 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
254 InterlockedIncrement(&OldBinding
->refs
);
255 *Binding
= OldBinding
;
259 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
261 if (InterlockedDecrement(&Binding
->refs
))
264 TRACE("binding: %p\n", Binding
);
265 if (Binding
->Assoc
) RpcAssoc_Release(Binding
->Assoc
);
266 RPCRT4_strfree(Binding
->Endpoint
);
267 RPCRT4_strfree(Binding
->NetworkAddr
);
268 RPCRT4_strfree(Binding
->Protseq
);
269 HeapFree(GetProcessHeap(), 0, Binding
->NetworkOptions
);
270 if (Binding
->AuthInfo
) RpcAuthInfo_Release(Binding
->AuthInfo
);
271 if (Binding
->QOS
) RpcQualityOfService_Release(Binding
->QOS
);
272 HeapFree(GetProcessHeap(), 0, Binding
);
276 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
,
277 PRPC_SYNTAX_IDENTIFIER TransferSyntax
,
278 PRPC_SYNTAX_IDENTIFIER InterfaceId
)
280 RpcConnection
* NewConnection
;
283 TRACE("(Binding == ^%p)\n", Binding
);
285 if (!Binding
->server
) {
286 /* try to find a compatible connection from the connection pool */
287 NewConnection
= RpcAssoc_GetIdleConnection(Binding
->Assoc
, InterfaceId
,
288 TransferSyntax
, Binding
->AuthInfo
, Binding
->QOS
);
290 *Connection
= NewConnection
;
294 /* we already have a connection with acceptable binding, so use it */
295 if (Binding
->FromConn
) {
296 *Connection
= Binding
->FromConn
;
301 /* create a new connection */
302 status
= RPCRT4_CreateConnection(&NewConnection
, Binding
->server
,
303 Binding
->Protseq
, Binding
->NetworkAddr
,
304 Binding
->Endpoint
, Binding
->NetworkOptions
,
305 Binding
->AuthInfo
, Binding
->QOS
);
306 if (status
!= RPC_S_OK
)
309 status
= RPCRT4_OpenClientConnection(NewConnection
);
310 if (status
!= RPC_S_OK
)
312 RPCRT4_DestroyConnection(NewConnection
);
316 /* we need to send a binding packet if we are client. */
317 if (!NewConnection
->server
) {
319 RpcPktHdr
*response_hdr
;
322 TRACE("sending bind request to server\n");
324 hdr
= RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION
,
325 RPC_MAX_PACKET_SIZE
, RPC_MAX_PACKET_SIZE
,
326 Binding
->Assoc
->assoc_group_id
,
327 InterfaceId
, TransferSyntax
);
329 status
= RPCRT4_Send(NewConnection
, hdr
, NULL
, 0);
330 RPCRT4_FreeHeader(hdr
);
331 if (status
!= RPC_S_OK
) {
332 RPCRT4_DestroyConnection(NewConnection
);
336 status
= RPCRT4_Receive(NewConnection
, &response_hdr
, &msg
);
337 if (status
!= RPC_S_OK
) {
338 ERR("receive failed\n");
339 RPCRT4_DestroyConnection(NewConnection
);
343 if (response_hdr
->common
.ptype
!= PKT_BIND_ACK
||
344 response_hdr
->bind_ack
.max_tsize
< RPC_MIN_PACKET_SIZE
) {
345 ERR("failed to bind for interface %s, %d.%d\n",
346 debugstr_guid(&InterfaceId
->SyntaxGUID
),
347 InterfaceId
->SyntaxVersion
.MajorVersion
,
348 InterfaceId
->SyntaxVersion
.MinorVersion
);
349 RPCRT4_FreeHeader(response_hdr
);
350 RPCRT4_DestroyConnection(NewConnection
);
351 return RPC_S_PROTOCOL_ERROR
;
354 /* FIXME: do more checks? */
356 NewConnection
->MaxTransmissionSize
= response_hdr
->bind_ack
.max_tsize
;
357 NewConnection
->assoc_group_id
= response_hdr
->bind_ack
.assoc_gid
;
358 NewConnection
->ActiveInterface
= *InterfaceId
;
359 RPCRT4_FreeHeader(response_hdr
);
363 Binding
->FromConn
= NewConnection
;
364 *Connection
= NewConnection
;
369 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
371 TRACE("(Binding == ^%p)\n", Binding
);
372 if (!Connection
) return RPC_S_OK
;
373 if (Binding
->server
) {
374 /* don't destroy a connection that is cached in the binding */
375 if (Binding
->FromConn
== Connection
)
377 return RPCRT4_DestroyConnection(Connection
);
380 RpcAssoc_ReleaseIdleConnection(Binding
->Assoc
, Connection
);
385 /* utility functions for string composing and parsing */
386 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
388 unsigned len
= strlen(src
);
389 memcpy(data
, src
, len
*sizeof(CHAR
));
393 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
395 unsigned len
= strlenW(src
);
396 memcpy(data
, src
, len
*sizeof(WCHAR
));
400 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
402 DWORD len
= strlen(dst
), slen
= strlen(src
);
403 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
406 HeapFree(GetProcessHeap(), 0, dst
);
410 memcpy(ndst
+len
+1, src
, slen
+1);
414 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
416 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
417 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
420 HeapFree(GetProcessHeap(), 0, dst
);
424 memcpy(ndst
+len
+1, src
, (slen
+1)*sizeof(WCHAR
));
429 /***********************************************************************
430 * RpcStringBindingComposeA (RPCRT4.@)
432 RPC_STATUS WINAPI
RpcStringBindingComposeA(RPC_CSTR ObjUuid
, RPC_CSTR Protseq
,
433 RPC_CSTR NetworkAddr
, RPC_CSTR Endpoint
,
434 RPC_CSTR Options
, RPC_CSTR
*StringBinding
)
439 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
440 debugstr_a( (char*)ObjUuid
), debugstr_a( (char*)Protseq
),
441 debugstr_a( (char*)NetworkAddr
), debugstr_a( (char*)Endpoint
),
442 debugstr_a( (char*)Options
), StringBinding
);
444 if (ObjUuid
&& *ObjUuid
) len
+= strlen((char*)ObjUuid
) + 1;
445 if (Protseq
&& *Protseq
) len
+= strlen((char*)Protseq
) + 1;
446 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen((char*)NetworkAddr
);
447 if (Endpoint
&& *Endpoint
) len
+= strlen((char*)Endpoint
) + 2;
448 if (Options
&& *Options
) len
+= strlen((char*)Options
) + 2;
450 data
= HeapAlloc(GetProcessHeap(), 0, len
);
451 *StringBinding
= (unsigned char*)data
;
453 if (ObjUuid
&& *ObjUuid
) {
454 data
+= RPCRT4_strcopyA(data
, (char*)ObjUuid
);
457 if (Protseq
&& *Protseq
) {
458 data
+= RPCRT4_strcopyA(data
, (char*)Protseq
);
461 if (NetworkAddr
&& *NetworkAddr
)
462 data
+= RPCRT4_strcopyA(data
, (char*)NetworkAddr
);
464 if ((Endpoint
&& *Endpoint
) ||
465 (Options
&& *Options
)) {
467 if (Endpoint
&& *Endpoint
) {
468 data
+= RPCRT4_strcopyA(data
, (char*)Endpoint
);
469 if (Options
&& *Options
) *data
++ = ',';
471 if (Options
&& *Options
) {
472 data
+= RPCRT4_strcopyA(data
, (char*)Options
);
481 /***********************************************************************
482 * RpcStringBindingComposeW (RPCRT4.@)
484 RPC_STATUS WINAPI
RpcStringBindingComposeW( RPC_WSTR ObjUuid
, RPC_WSTR Protseq
,
485 RPC_WSTR NetworkAddr
, RPC_WSTR Endpoint
,
486 RPC_WSTR Options
, RPC_WSTR
* StringBinding
)
491 TRACE("(%s,%s,%s,%s,%s,%p)\n",
492 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
493 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
494 debugstr_w( Options
), StringBinding
);
496 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
497 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
498 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
499 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
500 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
502 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
503 *StringBinding
= data
;
505 if (ObjUuid
&& *ObjUuid
) {
506 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
509 if (Protseq
&& *Protseq
) {
510 data
+= RPCRT4_strcopyW(data
, Protseq
);
513 if (NetworkAddr
&& *NetworkAddr
) {
514 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
516 if ((Endpoint
&& *Endpoint
) ||
517 (Options
&& *Options
)) {
519 if (Endpoint
&& *Endpoint
) {
520 data
+= RPCRT4_strcopyW(data
, Endpoint
);
521 if (Options
&& *Options
) *data
++ = ',';
523 if (Options
&& *Options
) {
524 data
+= RPCRT4_strcopyW(data
, Options
);
534 /***********************************************************************
535 * RpcStringBindingParseA (RPCRT4.@)
537 RPC_STATUS WINAPI
RpcStringBindingParseA( RPC_CSTR StringBinding
, RPC_CSTR
*ObjUuid
,
538 RPC_CSTR
*Protseq
, RPC_CSTR
*NetworkAddr
,
539 RPC_CSTR
*Endpoint
, RPC_CSTR
*Options
)
542 static const char ep_opt
[] = "endpoint=";
544 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding
),
545 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
547 if (ObjUuid
) *ObjUuid
= NULL
;
548 if (Protseq
) *Protseq
= NULL
;
549 if (NetworkAddr
) *NetworkAddr
= NULL
;
550 if (Endpoint
) *Endpoint
= NULL
;
551 if (Options
) *Options
= NULL
;
553 data
= (char*) StringBinding
;
555 next
= strchr(data
, '@');
557 if (ObjUuid
) *ObjUuid
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
561 next
= strchr(data
, ':');
563 if (Protseq
) *Protseq
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
567 next
= strchr(data
, '[');
571 if (NetworkAddr
) *NetworkAddr
= (unsigned char*)RPCRT4_strndupA(data
, next
- data
);
573 close
= strchr(data
, ']');
574 if (!close
) goto fail
;
576 /* tokenize options */
577 while (data
< close
) {
578 next
= strchr(data
, ',');
579 if (!next
|| next
> close
) next
= close
;
580 /* FIXME: this is kind of inefficient */
581 opt
= RPCRT4_strndupA(data
, next
- data
);
585 next
= strchr(opt
, '=');
587 /* not an option, must be an endpoint */
588 if (*Endpoint
) goto fail
;
589 *Endpoint
= (unsigned char*) opt
;
591 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
592 /* endpoint option */
593 if (*Endpoint
) goto fail
;
594 *Endpoint
= (unsigned char*) RPCRT4_strdupA(next
+1);
595 HeapFree(GetProcessHeap(), 0, opt
);
599 /* FIXME: this is kind of inefficient */
600 *Options
= (unsigned char*) RPCRT4_strconcatA( (char*)*Options
, opt
);
601 HeapFree(GetProcessHeap(), 0, opt
);
603 *Options
= (unsigned char*) opt
;
609 if (*data
) goto fail
;
611 else if (NetworkAddr
)
612 *NetworkAddr
= (unsigned char*)RPCRT4_strdupA(data
);
617 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
618 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
619 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
620 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
621 if (Options
) RpcStringFreeA((unsigned char**)Options
);
622 return RPC_S_INVALID_STRING_BINDING
;
625 /***********************************************************************
626 * RpcStringBindingParseW (RPCRT4.@)
628 RPC_STATUS WINAPI
RpcStringBindingParseW( RPC_WSTR StringBinding
, RPC_WSTR
*ObjUuid
,
629 RPC_WSTR
*Protseq
, RPC_WSTR
*NetworkAddr
,
630 RPC_WSTR
*Endpoint
, RPC_WSTR
*Options
)
633 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
635 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
636 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
638 if (ObjUuid
) *ObjUuid
= NULL
;
639 if (Protseq
) *Protseq
= NULL
;
640 if (NetworkAddr
) *NetworkAddr
= NULL
;
641 if (Endpoint
) *Endpoint
= NULL
;
642 if (Options
) *Options
= NULL
;
644 data
= StringBinding
;
646 next
= strchrW(data
, '@');
648 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
652 next
= strchrW(data
, ':');
654 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
658 next
= strchrW(data
, '[');
662 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
664 close
= strchrW(data
, ']');
665 if (!close
) goto fail
;
667 /* tokenize options */
668 while (data
< close
) {
669 next
= strchrW(data
, ',');
670 if (!next
|| next
> close
) next
= close
;
671 /* FIXME: this is kind of inefficient */
672 opt
= RPCRT4_strndupW(data
, next
- data
);
676 next
= strchrW(opt
, '=');
678 /* not an option, must be an endpoint */
679 if (*Endpoint
) goto fail
;
682 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
683 /* endpoint option */
684 if (*Endpoint
) goto fail
;
685 *Endpoint
= RPCRT4_strdupW(next
+1);
686 HeapFree(GetProcessHeap(), 0, opt
);
690 /* FIXME: this is kind of inefficient */
691 *Options
= RPCRT4_strconcatW(*Options
, opt
);
692 HeapFree(GetProcessHeap(), 0, opt
);
700 if (*data
) goto fail
;
701 } else if (NetworkAddr
)
702 *NetworkAddr
= RPCRT4_strdupW(data
);
707 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
708 if (Protseq
) RpcStringFreeW(Protseq
);
709 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
710 if (Endpoint
) RpcStringFreeW(Endpoint
);
711 if (Options
) RpcStringFreeW(Options
);
712 return RPC_S_INVALID_STRING_BINDING
;
715 /***********************************************************************
716 * RpcBindingFree (RPCRT4.@)
718 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
721 TRACE("(%p) = %p\n", Binding
, *Binding
);
722 status
= RPCRT4_DestroyBinding(*Binding
);
723 if (status
== RPC_S_OK
) *Binding
= 0;
727 /***********************************************************************
728 * RpcBindingVectorFree (RPCRT4.@)
730 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
735 TRACE("(%p)\n", BindingVector
);
736 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
737 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
739 HeapFree(GetProcessHeap(), 0, *BindingVector
);
740 *BindingVector
= NULL
;
744 /***********************************************************************
745 * RpcBindingInqObject (RPCRT4.@)
747 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
749 RpcBinding
* bind
= (RpcBinding
*)Binding
;
751 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
752 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
756 /***********************************************************************
757 * RpcBindingSetObject (RPCRT4.@)
759 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
761 RpcBinding
* bind
= (RpcBinding
*)Binding
;
763 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
764 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
765 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
768 /***********************************************************************
769 * RpcBindingFromStringBindingA (RPCRT4.@)
771 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( RPC_CSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
774 RpcBinding
* bind
= NULL
;
775 RPC_CSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
778 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding
), Binding
);
780 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
781 &NetworkAddr
, &Endpoint
, &Options
);
782 if (ret
!= RPC_S_OK
) return ret
;
784 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
787 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, (char*)Protseq
);
789 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
791 ret
= RPCRT4_CompleteBindingA(bind
, (char*)NetworkAddr
, (char*)Endpoint
, (char*)Options
);
793 RpcStringFreeA((unsigned char**)&Options
);
794 RpcStringFreeA((unsigned char**)&Endpoint
);
795 RpcStringFreeA((unsigned char**)&NetworkAddr
);
796 RpcStringFreeA((unsigned char**)&Protseq
);
797 RpcStringFreeA((unsigned char**)&ObjectUuid
);
800 *Binding
= (RPC_BINDING_HANDLE
)bind
;
802 RPCRT4_DestroyBinding(bind
);
807 /***********************************************************************
808 * RpcBindingFromStringBindingW (RPCRT4.@)
810 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( RPC_WSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
813 RpcBinding
* bind
= NULL
;
814 RPC_WSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
817 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
819 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
820 &NetworkAddr
, &Endpoint
, &Options
);
821 if (ret
!= RPC_S_OK
) return ret
;
823 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
826 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
828 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
830 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
832 RpcStringFreeW(&Options
);
833 RpcStringFreeW(&Endpoint
);
834 RpcStringFreeW(&NetworkAddr
);
835 RpcStringFreeW(&Protseq
);
836 RpcStringFreeW(&ObjectUuid
);
839 *Binding
= (RPC_BINDING_HANDLE
)bind
;
841 RPCRT4_DestroyBinding(bind
);
846 /***********************************************************************
847 * RpcBindingToStringBindingA (RPCRT4.@)
849 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*StringBinding
)
852 RpcBinding
* bind
= (RpcBinding
*)Binding
;
855 TRACE("(%p,%p)\n", Binding
, StringBinding
);
857 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
858 if (ret
!= RPC_S_OK
) return ret
;
860 ret
= RpcStringBindingComposeA(ObjectUuid
, (unsigned char*)bind
->Protseq
, (unsigned char*) bind
->NetworkAddr
,
861 (unsigned char*) bind
->Endpoint
, NULL
, StringBinding
);
863 RpcStringFreeA(&ObjectUuid
);
868 /***********************************************************************
869 * RpcBindingToStringBindingW (RPCRT4.@)
871 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*StringBinding
)
874 unsigned char *str
= NULL
;
875 TRACE("(%p,%p)\n", Binding
, StringBinding
);
876 ret
= RpcBindingToStringBindingA(Binding
, &str
);
877 *StringBinding
= RPCRT4_strdupAtoW((char*)str
);
878 RpcStringFreeA((unsigned char**)&str
);
882 /***********************************************************************
883 * I_RpcBindingSetAsync (RPCRT4.@)
885 * Exists in win9x and winNT, but with different number of arguments
886 * (9x version has 3 arguments, NT has 2).
888 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
890 RpcBinding
* bind
= (RpcBinding
*)Binding
;
892 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
894 bind
->BlockingFn
= BlockingFn
;
899 /***********************************************************************
900 * RpcBindingCopy (RPCRT4.@)
902 RPC_STATUS RPC_ENTRY
RpcBindingCopy(
903 RPC_BINDING_HANDLE SourceBinding
,
904 RPC_BINDING_HANDLE
* DestinationBinding
)
906 RpcBinding
*DestBinding
;
907 RpcBinding
*SrcBinding
= (RpcBinding
*)SourceBinding
;
910 TRACE("(%p, %p)\n", SourceBinding
, DestinationBinding
);
912 status
= RPCRT4_AllocBinding(&DestBinding
, SrcBinding
->server
);
913 if (status
!= RPC_S_OK
) return status
;
915 DestBinding
->ObjectUuid
= SrcBinding
->ObjectUuid
;
916 DestBinding
->BlockingFn
= SrcBinding
->BlockingFn
;
917 DestBinding
->Protseq
= RPCRT4_strndupA(SrcBinding
->Protseq
, -1);
918 DestBinding
->NetworkAddr
= RPCRT4_strndupA(SrcBinding
->NetworkAddr
, -1);
919 DestBinding
->Endpoint
= RPCRT4_strndupA(SrcBinding
->Endpoint
, -1);
920 DestBinding
->NetworkOptions
= RPCRT4_strdupW(SrcBinding
->NetworkOptions
);
921 if (SrcBinding
->Assoc
) SrcBinding
->Assoc
->refs
++;
922 DestBinding
->Assoc
= SrcBinding
->Assoc
;
924 if (SrcBinding
->AuthInfo
) RpcAuthInfo_AddRef(SrcBinding
->AuthInfo
);
925 DestBinding
->AuthInfo
= SrcBinding
->AuthInfo
;
926 if (SrcBinding
->QOS
) RpcQualityOfService_AddRef(SrcBinding
->QOS
);
927 DestBinding
->QOS
= SrcBinding
->QOS
;
929 *DestinationBinding
= DestBinding
;
933 /***********************************************************************
934 * RpcImpersonateClient (RPCRT4.@)
936 * Impersonates the client connected via a binding handle so that security
937 * checks are done in the context of the client.
940 * BindingHandle [I] Handle to the binding to the client.
944 * Failure: RPC_STATUS value.
948 * If BindingHandle is NULL then the function impersonates the client
949 * connected to the binding handle of the current thread.
951 RPC_STATUS WINAPI
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle
)
953 FIXME("(%p): stub\n", BindingHandle
);
954 ImpersonateSelf(SecurityImpersonation
);
958 /***********************************************************************
959 * RpcRevertToSelfEx (RPCRT4.@)
961 * Stops impersonating the client connected to the binding handle so that security
962 * checks are no longer done in the context of the client.
965 * BindingHandle [I] Handle to the binding to the client.
969 * Failure: RPC_STATUS value.
973 * If BindingHandle is NULL then the function stops impersonating the client
974 * connected to the binding handle of the current thread.
976 RPC_STATUS WINAPI
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle
)
978 FIXME("(%p): stub\n", BindingHandle
);
982 static inline BOOL
has_nt_auth_identity(ULONG AuthnLevel
)
986 case RPC_C_AUTHN_GSS_NEGOTIATE
:
987 case RPC_C_AUTHN_WINNT
:
988 case RPC_C_AUTHN_GSS_KERBEROS
:
995 static RPC_STATUS
RpcAuthInfo_Create(ULONG AuthnLevel
, ULONG AuthnSvc
,
996 CredHandle cred
, TimeStamp exp
,
998 RPC_AUTH_IDENTITY_HANDLE identity
,
1001 RpcAuthInfo
*AuthInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
));
1003 return ERROR_OUTOFMEMORY
;
1006 AuthInfo
->AuthnLevel
= AuthnLevel
;
1007 AuthInfo
->AuthnSvc
= AuthnSvc
;
1008 AuthInfo
->cred
= cred
;
1009 AuthInfo
->exp
= exp
;
1010 AuthInfo
->cbMaxToken
= cbMaxToken
;
1011 AuthInfo
->identity
= identity
;
1013 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1014 * enable better matching in RpcAuthInfo_IsEqual */
1015 if (identity
&& has_nt_auth_identity(AuthnSvc
))
1017 const SEC_WINNT_AUTH_IDENTITY_W
*nt_identity
= identity
;
1018 AuthInfo
->nt_identity
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo
->nt_identity
));
1019 if (!AuthInfo
->nt_identity
)
1021 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1022 return ERROR_OUTOFMEMORY
;
1025 AuthInfo
->nt_identity
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1026 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1027 AuthInfo
->nt_identity
->User
= RPCRT4_strndupW(nt_identity
->User
, nt_identity
->UserLength
);
1029 AuthInfo
->nt_identity
->User
= RPCRT4_strndupAtoW((const char *)nt_identity
->User
, nt_identity
->UserLength
);
1030 AuthInfo
->nt_identity
->UserLength
= nt_identity
->UserLength
;
1031 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1032 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupW(nt_identity
->Domain
, nt_identity
->DomainLength
);
1034 AuthInfo
->nt_identity
->Domain
= RPCRT4_strndupAtoW((const char *)nt_identity
->Domain
, nt_identity
->DomainLength
);
1035 AuthInfo
->nt_identity
->DomainLength
= nt_identity
->DomainLength
;
1036 if (nt_identity
->Flags
& SEC_WINNT_AUTH_IDENTITY_UNICODE
)
1037 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupW(nt_identity
->Password
, nt_identity
->PasswordLength
);
1039 AuthInfo
->nt_identity
->Password
= RPCRT4_strndupAtoW((const char *)nt_identity
->Password
, nt_identity
->PasswordLength
);
1040 AuthInfo
->nt_identity
->PasswordLength
= nt_identity
->PasswordLength
;
1042 if (!AuthInfo
->nt_identity
->User
||
1043 !AuthInfo
->nt_identity
->Domain
||
1044 !AuthInfo
->nt_identity
->Password
)
1046 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1047 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1048 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Password
);
1049 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1050 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1051 return ERROR_OUTOFMEMORY
;
1055 AuthInfo
->nt_identity
= NULL
;
1060 ULONG
RpcAuthInfo_AddRef(RpcAuthInfo
*AuthInfo
)
1062 return InterlockedIncrement(&AuthInfo
->refs
);
1065 ULONG
RpcAuthInfo_Release(RpcAuthInfo
*AuthInfo
)
1067 ULONG refs
= InterlockedDecrement(&AuthInfo
->refs
);
1071 FreeCredentialsHandle(&AuthInfo
->cred
);
1072 if (AuthInfo
->nt_identity
)
1074 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1075 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->Domain
);
1076 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
->User
);
1077 HeapFree(GetProcessHeap(), 0, AuthInfo
->nt_identity
);
1079 HeapFree(GetProcessHeap(), 0, AuthInfo
);
1085 BOOL
RpcAuthInfo_IsEqual(const RpcAuthInfo
*AuthInfo1
, const RpcAuthInfo
*AuthInfo2
)
1087 if (AuthInfo1
== AuthInfo2
)
1090 if (!AuthInfo1
|| !AuthInfo2
)
1093 if ((AuthInfo1
->AuthnLevel
!= AuthInfo2
->AuthnLevel
) ||
1094 (AuthInfo1
->AuthnSvc
!= AuthInfo2
->AuthnSvc
))
1097 if (AuthInfo1
->identity
== AuthInfo2
->identity
)
1100 if (!AuthInfo1
->identity
|| !AuthInfo2
->identity
)
1103 if (has_nt_auth_identity(AuthInfo1
->AuthnSvc
))
1105 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= AuthInfo1
->nt_identity
;
1106 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= AuthInfo2
->nt_identity
;
1107 /* compare user names */
1108 if (identity1
->UserLength
!= identity2
->UserLength
||
1109 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1111 /* compare domain names */
1112 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1113 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1115 /* compare passwords */
1116 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1117 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1126 static RPC_STATUS
RpcQualityOfService_Create(const RPC_SECURITY_QOS
*qos_src
, BOOL unicode
, RpcQualityOfService
**qos_dst
)
1128 RpcQualityOfService
*qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
));
1131 return RPC_S_OUT_OF_RESOURCES
;
1134 qos
->qos
= HeapAlloc(GetProcessHeap(), 0, sizeof(*qos
->qos
));
1135 if (!qos
->qos
) goto error
;
1136 qos
->qos
->Version
= qos_src
->Version
;
1137 qos
->qos
->Capabilities
= qos_src
->Capabilities
;
1138 qos
->qos
->IdentityTracking
= qos_src
->IdentityTracking
;
1139 qos
->qos
->ImpersonationType
= qos_src
->ImpersonationType
;
1140 qos
->qos
->AdditionalSecurityInfoType
= 0;
1142 if (qos_src
->Version
>= 2)
1144 const RPC_SECURITY_QOS_V2_W
*qos_src2
= (const RPC_SECURITY_QOS_V2_W
*)qos_src
;
1145 qos
->qos
->AdditionalSecurityInfoType
= qos_src2
->AdditionalSecurityInfoType
;
1146 if (qos_src2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1148 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_src
= qos_src2
->u
.HttpCredentials
;
1149 RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials_dst
;
1151 http_credentials_dst
= HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst
));
1152 qos
->qos
->u
.HttpCredentials
= http_credentials_dst
;
1153 if (!http_credentials_dst
) goto error
;
1154 http_credentials_dst
->TransportCredentials
= NULL
;
1155 http_credentials_dst
->Flags
= http_credentials_src
->Flags
;
1156 http_credentials_dst
->AuthenticationTarget
= http_credentials_src
->AuthenticationTarget
;
1157 http_credentials_dst
->NumberOfAuthnSchemes
= http_credentials_src
->NumberOfAuthnSchemes
;
1158 http_credentials_dst
->AuthnSchemes
= NULL
;
1159 http_credentials_dst
->ServerCertificateSubject
= NULL
;
1160 if (http_credentials_src
->TransportCredentials
)
1162 SEC_WINNT_AUTH_IDENTITY_W
*cred_dst
;
1163 cred_dst
= http_credentials_dst
->TransportCredentials
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*cred_dst
));
1164 if (!cred_dst
) goto error
;
1165 cred_dst
->Flags
= SEC_WINNT_AUTH_IDENTITY_UNICODE
;
1168 const SEC_WINNT_AUTH_IDENTITY_W
*cred_src
= http_credentials_src
->TransportCredentials
;
1169 cred_dst
->UserLength
= cred_src
->UserLength
;
1170 cred_dst
->PasswordLength
= cred_src
->PasswordLength
;
1171 cred_dst
->DomainLength
= cred_src
->DomainLength
;
1172 cred_dst
->User
= RPCRT4_strndupW(cred_src
->User
, cred_src
->UserLength
);
1173 cred_dst
->Password
= RPCRT4_strndupW(cred_src
->Password
, cred_src
->PasswordLength
);
1174 cred_dst
->Domain
= RPCRT4_strndupW(cred_src
->Domain
, cred_src
->DomainLength
);
1178 const SEC_WINNT_AUTH_IDENTITY_A
*cred_src
= (const SEC_WINNT_AUTH_IDENTITY_A
*)http_credentials_src
->TransportCredentials
;
1179 cred_dst
->UserLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, NULL
, 0);
1180 cred_dst
->DomainLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, NULL
, 0);
1181 cred_dst
->PasswordLength
= MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, NULL
, 0);
1182 cred_dst
->User
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->UserLength
* sizeof(WCHAR
));
1183 cred_dst
->Password
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->PasswordLength
* sizeof(WCHAR
));
1184 cred_dst
->Domain
= HeapAlloc(GetProcessHeap(), 0, cred_dst
->DomainLength
* sizeof(WCHAR
));
1185 if (!cred_dst
|| !cred_dst
->Password
|| !cred_dst
->Domain
) goto error
;
1186 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->User
, cred_src
->UserLength
, cred_dst
->User
, cred_dst
->UserLength
);
1187 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Domain
, cred_src
->DomainLength
, cred_dst
->Domain
, cred_dst
->DomainLength
);
1188 MultiByteToWideChar(CP_ACP
, 0, (char *)cred_src
->Password
, cred_src
->PasswordLength
, cred_dst
->Password
, cred_dst
->PasswordLength
);
1191 if (http_credentials_src
->NumberOfAuthnSchemes
)
1193 http_credentials_dst
->AuthnSchemes
= HeapAlloc(GetProcessHeap(), 0, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1194 if (!http_credentials_dst
->AuthnSchemes
) goto error
;
1195 memcpy(http_credentials_dst
->AuthnSchemes
, http_credentials_src
->AuthnSchemes
, http_credentials_src
->NumberOfAuthnSchemes
* sizeof(*http_credentials_dst
->AuthnSchemes
));
1197 if (http_credentials_src
->ServerCertificateSubject
)
1200 http_credentials_dst
->ServerCertificateSubject
=
1201 RPCRT4_strndupW(http_credentials_src
->ServerCertificateSubject
,
1202 strlenW(http_credentials_src
->ServerCertificateSubject
));
1204 http_credentials_dst
->ServerCertificateSubject
=
1205 RPCRT4_strdupAtoW((char *)http_credentials_src
->ServerCertificateSubject
);
1206 if (!http_credentials_dst
->ServerCertificateSubject
) goto error
;
1216 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
&&
1217 qos
->qos
->u
.HttpCredentials
)
1219 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1221 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1222 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1223 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1224 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1226 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1227 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1228 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1230 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1232 HeapFree(GetProcessHeap(), 0, qos
);
1233 return RPC_S_OUT_OF_RESOURCES
;
1236 ULONG
RpcQualityOfService_AddRef(RpcQualityOfService
*qos
)
1238 return InterlockedIncrement(&qos
->refs
);
1241 ULONG
RpcQualityOfService_Release(RpcQualityOfService
*qos
)
1243 ULONG refs
= InterlockedDecrement(&qos
->refs
);
1247 if (qos
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1249 if (qos
->qos
->u
.HttpCredentials
->TransportCredentials
)
1251 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->User
);
1252 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Domain
);
1253 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
->Password
);
1254 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->TransportCredentials
);
1256 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->AuthnSchemes
);
1257 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
->ServerCertificateSubject
);
1258 HeapFree(GetProcessHeap(), 0, qos
->qos
->u
.HttpCredentials
);
1260 HeapFree(GetProcessHeap(), 0, qos
->qos
);
1261 HeapFree(GetProcessHeap(), 0, qos
);
1266 BOOL
RpcQualityOfService_IsEqual(const RpcQualityOfService
*qos1
, const RpcQualityOfService
*qos2
)
1274 TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1275 qos1
->qos
->Capabilities
, qos1
->qos
->IdentityTracking
,
1276 qos1
->qos
->ImpersonationType
, qos1
->qos
->AdditionalSecurityInfoType
,
1277 qos2
->qos
->Capabilities
, qos2
->qos
->IdentityTracking
,
1278 qos2
->qos
->ImpersonationType
, qos2
->qos
->AdditionalSecurityInfoType
);
1280 if ((qos1
->qos
->Capabilities
!= qos2
->qos
->Capabilities
) ||
1281 (qos1
->qos
->IdentityTracking
!= qos2
->qos
->IdentityTracking
) ||
1282 (qos1
->qos
->ImpersonationType
!= qos2
->qos
->ImpersonationType
) ||
1283 (qos1
->qos
->AdditionalSecurityInfoType
!= qos2
->qos
->AdditionalSecurityInfoType
))
1286 if (qos1
->qos
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1288 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials1
= qos1
->qos
->u
.HttpCredentials
;
1289 const RPC_HTTP_TRANSPORT_CREDENTIALS_W
*http_credentials2
= qos2
->qos
->u
.HttpCredentials
;
1291 if (http_credentials1
->Flags
!= http_credentials2
->Flags
)
1294 if (http_credentials1
->AuthenticationTarget
!= http_credentials2
->AuthenticationTarget
)
1297 /* authentication schemes and server certificate subject not currently used */
1299 if (http_credentials1
->TransportCredentials
!= http_credentials2
->TransportCredentials
)
1301 const SEC_WINNT_AUTH_IDENTITY_W
*identity1
= http_credentials1
->TransportCredentials
;
1302 const SEC_WINNT_AUTH_IDENTITY_W
*identity2
= http_credentials2
->TransportCredentials
;
1304 if (!identity1
|| !identity2
)
1307 /* compare user names */
1308 if (identity1
->UserLength
!= identity2
->UserLength
||
1309 memcmp(identity1
->User
, identity2
->User
, identity1
->UserLength
))
1311 /* compare domain names */
1312 if (identity1
->DomainLength
!= identity2
->DomainLength
||
1313 memcmp(identity1
->Domain
, identity2
->Domain
, identity1
->DomainLength
))
1315 /* compare passwords */
1316 if (identity1
->PasswordLength
!= identity2
->PasswordLength
||
1317 memcmp(identity1
->Password
, identity2
->Password
, identity1
->PasswordLength
))
1325 /***********************************************************************
1326 * RpcRevertToSelf (RPCRT4.@)
1328 RPC_STATUS WINAPI
RpcRevertToSelf(void)
1335 /***********************************************************************
1336 * RpcMgmtSetComTimeout (RPCRT4.@)
1338 RPC_STATUS WINAPI
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle
, unsigned int Timeout
)
1340 FIXME("(%p, %d): stub\n", BindingHandle
, Timeout
);
1344 /***********************************************************************
1345 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1347 RPCRTAPI RPC_STATUS RPC_ENTRY
1348 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1349 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1350 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1352 FIXME("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1353 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1354 return RPC_S_INVALID_BINDING
;
1357 /***********************************************************************
1358 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1360 RPCRTAPI RPC_STATUS RPC_ENTRY
1361 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1362 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
,
1363 ULONG RpcQosVersion
, RPC_SECURITY_QOS
*SecurityQOS
)
1365 FIXME("%p %p %p %p %p %p %u %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1366 AuthnSvc
, AuthIdentity
, AuthzSvc
, RpcQosVersion
, SecurityQOS
);
1367 return RPC_S_INVALID_BINDING
;
1370 /***********************************************************************
1371 * RpcBindingInqAuthInfoA (RPCRT4.@)
1373 RPCRTAPI RPC_STATUS RPC_ENTRY
1374 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1375 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1377 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1378 AuthnSvc
, AuthIdentity
, AuthzSvc
);
1379 return RPC_S_INVALID_BINDING
;
1382 /***********************************************************************
1383 * RpcBindingInqAuthInfoW (RPCRT4.@)
1385 RPCRTAPI RPC_STATUS RPC_ENTRY
1386 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR
*ServerPrincName
, ULONG
*AuthnLevel
,
1387 ULONG
*AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE
*AuthIdentity
, ULONG
*AuthzSvc
)
1389 FIXME("%p %p %p %p %p %p\n", Binding
, ServerPrincName
, AuthnLevel
,
1390 AuthnSvc
, AuthIdentity
, AuthzSvc
);
1391 return RPC_S_INVALID_BINDING
;
1394 /***********************************************************************
1395 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1397 RPCRTAPI RPC_STATUS RPC_ENTRY
1398 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
,
1399 ULONG AuthnLevel
, ULONG AuthnSvc
,
1400 RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1401 RPC_SECURITY_QOS
*SecurityQos
)
1403 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1407 ULONG package_count
;
1409 PSecPkgInfoA packages
;
1412 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1413 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1419 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1420 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1421 if (SecurityQos
->Version
>= 2)
1423 const RPC_SECURITY_QOS_V2_A
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_A
*)SecurityQos
;
1424 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2
->AdditionalSecurityInfoType
);
1425 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1426 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1427 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1428 SecurityQos2
->u
.HttpCredentials
->Flags
,
1429 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1430 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1431 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1432 SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
);
1435 status
= RpcQualityOfService_Create(SecurityQos
, FALSE
, &bind
->QOS
);
1436 if (status
!= RPC_S_OK
)
1441 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1445 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1446 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1448 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1449 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1450 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1452 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1454 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1455 bind
->AuthInfo
= NULL
;
1459 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1461 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1462 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1467 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1468 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1471 r
= EnumerateSecurityPackagesA(&package_count
, &packages
);
1474 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1475 return RPC_S_SEC_PKG_ERROR
;
1478 for (i
= 0; i
< package_count
; i
++)
1479 if (packages
[i
].wRPCID
== AuthnSvc
)
1482 if (i
== package_count
)
1484 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1485 FreeContextBuffer(packages
);
1486 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1489 TRACE("found package %s for service %u\n", packages
[i
].Name
, AuthnSvc
);
1490 r
= AcquireCredentialsHandleA((SEC_CHAR
*)ServerPrincName
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1491 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1492 cbMaxToken
= packages
[i
].cbMaxToken
;
1493 FreeContextBuffer(packages
);
1494 if (r
== ERROR_SUCCESS
)
1496 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1497 bind
->AuthInfo
= NULL
;
1498 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1499 AuthIdentity
, &bind
->AuthInfo
);
1501 FreeCredentialsHandle(&cred
);
1506 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1507 return RPC_S_SEC_PKG_ERROR
;
1511 /***********************************************************************
1512 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1514 RPCRTAPI RPC_STATUS RPC_ENTRY
1515 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1516 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
,
1517 RPC_SECURITY_QOS
*SecurityQos
)
1519 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1523 ULONG package_count
;
1525 PSecPkgInfoW packages
;
1528 TRACE("%p %s %u %u %p %u %p\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1529 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, SecurityQos
);
1535 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1536 SecurityQos
->Version
, SecurityQos
->Capabilities
, SecurityQos
->IdentityTracking
, SecurityQos
->ImpersonationType
);
1537 if (SecurityQos
->Version
>= 2)
1539 const RPC_SECURITY_QOS_V2_W
*SecurityQos2
= (const RPC_SECURITY_QOS_V2_W
*)SecurityQos
;
1540 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2
->AdditionalSecurityInfoType
);
1541 if (SecurityQos2
->AdditionalSecurityInfoType
== RPC_C_AUTHN_INFO_TYPE_HTTP
)
1542 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1543 SecurityQos2
->u
.HttpCredentials
->TransportCredentials
,
1544 SecurityQos2
->u
.HttpCredentials
->Flags
,
1545 SecurityQos2
->u
.HttpCredentials
->AuthenticationTarget
,
1546 SecurityQos2
->u
.HttpCredentials
->NumberOfAuthnSchemes
,
1547 SecurityQos2
->u
.HttpCredentials
->AuthnSchemes
,
1548 debugstr_w(SecurityQos2
->u
.HttpCredentials
->ServerCertificateSubject
));
1551 status
= RpcQualityOfService_Create(SecurityQos
, TRUE
, &bind
->QOS
);
1552 if (status
!= RPC_S_OK
)
1557 if (bind
->QOS
) RpcQualityOfService_Release(bind
->QOS
);
1561 if (AuthnSvc
== RPC_C_AUTHN_DEFAULT
)
1562 AuthnSvc
= RPC_C_AUTHN_WINNT
;
1564 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1565 if (AuthnLevel
== RPC_C_AUTHN_LEVEL_DEFAULT
)
1566 AuthnLevel
= RPC_C_AUTHN_LEVEL_NONE
;
1568 if ((AuthnLevel
== RPC_C_AUTHN_LEVEL_NONE
) || (AuthnSvc
== RPC_C_AUTHN_NONE
))
1570 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1571 bind
->AuthInfo
= NULL
;
1575 if (AuthnLevel
> RPC_C_AUTHN_LEVEL_PKT_PRIVACY
)
1577 FIXME("unknown AuthnLevel %u\n", AuthnLevel
);
1578 return RPC_S_UNKNOWN_AUTHN_LEVEL
;
1583 FIXME("unsupported AuthzSvr %u\n", AuthzSvr
);
1584 return RPC_S_UNKNOWN_AUTHZ_SERVICE
;
1587 r
= EnumerateSecurityPackagesW(&package_count
, &packages
);
1590 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r
);
1591 return RPC_S_SEC_PKG_ERROR
;
1594 for (i
= 0; i
< package_count
; i
++)
1595 if (packages
[i
].wRPCID
== AuthnSvc
)
1598 if (i
== package_count
)
1600 FIXME("unsupported AuthnSvc %u\n", AuthnSvc
);
1601 FreeContextBuffer(packages
);
1602 return RPC_S_UNKNOWN_AUTHN_SERVICE
;
1605 TRACE("found package %s for service %u\n", debugstr_w(packages
[i
].Name
), AuthnSvc
);
1606 r
= AcquireCredentialsHandleW((SEC_WCHAR
*)ServerPrincName
, packages
[i
].Name
, SECPKG_CRED_OUTBOUND
, NULL
,
1607 AuthIdentity
, NULL
, NULL
, &cred
, &exp
);
1608 cbMaxToken
= packages
[i
].cbMaxToken
;
1609 FreeContextBuffer(packages
);
1610 if (r
== ERROR_SUCCESS
)
1612 if (bind
->AuthInfo
) RpcAuthInfo_Release(bind
->AuthInfo
);
1613 bind
->AuthInfo
= NULL
;
1614 r
= RpcAuthInfo_Create(AuthnLevel
, AuthnSvc
, cred
, exp
, cbMaxToken
,
1615 AuthIdentity
, &bind
->AuthInfo
);
1617 FreeCredentialsHandle(&cred
);
1622 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r
);
1623 return RPC_S_SEC_PKG_ERROR
;
1627 /***********************************************************************
1628 * RpcBindingSetAuthInfoA (RPCRT4.@)
1630 RPCRTAPI RPC_STATUS RPC_ENTRY
1631 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding
, RPC_CSTR ServerPrincName
, ULONG AuthnLevel
,
1632 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1634 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_a((const char*)ServerPrincName
),
1635 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1636 return RpcBindingSetAuthInfoExA(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1639 /***********************************************************************
1640 * RpcBindingSetAuthInfoW (RPCRT4.@)
1642 RPCRTAPI RPC_STATUS RPC_ENTRY
1643 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding
, RPC_WSTR ServerPrincName
, ULONG AuthnLevel
,
1644 ULONG AuthnSvc
, RPC_AUTH_IDENTITY_HANDLE AuthIdentity
, ULONG AuthzSvr
)
1646 TRACE("%p %s %u %u %p %u\n", Binding
, debugstr_w((const WCHAR
*)ServerPrincName
),
1647 AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
);
1648 return RpcBindingSetAuthInfoExW(Binding
, ServerPrincName
, AuthnLevel
, AuthnSvc
, AuthIdentity
, AuthzSvr
, NULL
);
1651 /***********************************************************************
1652 * RpcBindingSetOption (RPCRT4.@)
1654 RPC_STATUS WINAPI
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle
, ULONG Option
, ULONG OptionValue
)
1656 FIXME("(%p, %d, %d): stub\n", BindingHandle
, Option
, OptionValue
);