d3d9: Hold the lock in stateblock methods.
[wine.git] / dlls / rpcrt4 / rpc_binding.c
blob4f276ae99518d24597bbc251156282a6000d646b
1 /*
2 * RPC binding API
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "winerror.h"
33 #include "winternl.h"
34 #include "wine/unicode.h"
36 #include "rpc.h"
37 #include "rpcndr.h"
39 #include "wine/debug.h"
41 #include "rpc_binding.h"
42 #include "rpc_message.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
46 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
48 DWORD len;
49 LPSTR s;
50 if (!src) return NULL;
51 if (slen == -1) slen = strlen(src);
52 len = slen;
53 s = HeapAlloc(GetProcessHeap(), 0, len+1);
54 memcpy(s, src, len);
55 s[len] = 0;
56 return s;
59 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
61 DWORD len;
62 LPSTR s;
63 if (!src) return NULL;
64 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
65 s = HeapAlloc(GetProcessHeap(), 0, len);
66 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
67 return s;
70 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
72 DWORD len;
73 LPWSTR s;
74 if (!src) return NULL;
75 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
76 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
77 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
78 return s;
81 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
83 DWORD len;
84 LPWSTR s;
85 if (!src) return NULL;
86 if (slen == -1) slen = strlenW(src);
87 len = slen;
88 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
89 memcpy(s, src, len*sizeof(WCHAR));
90 s[len] = 0;
91 return s;
94 void RPCRT4_strfree(LPSTR src)
96 HeapFree(GetProcessHeap(), 0, src);
99 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
101 RpcBinding* NewBinding;
103 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
104 NewBinding->refs = 1;
105 NewBinding->server = server;
107 *Binding = NewBinding;
109 return RPC_S_OK;
112 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
114 RpcBinding* NewBinding;
116 RPCRT4_AllocBinding(&NewBinding, server);
117 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
119 TRACE("binding: %p\n", NewBinding);
120 *Binding = NewBinding;
122 return RPC_S_OK;
125 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
127 RpcBinding* NewBinding;
129 RPCRT4_AllocBinding(&NewBinding, server);
130 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
132 TRACE("binding: %p\n", NewBinding);
133 *Binding = NewBinding;
135 return RPC_S_OK;
138 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
139 LPCSTR Endpoint, LPCSTR NetworkOptions)
141 RPC_STATUS status;
143 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
144 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
146 RPCRT4_strfree(Binding->NetworkAddr);
147 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
148 RPCRT4_strfree(Binding->Endpoint);
149 if (Endpoint) {
150 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
151 } else {
152 Binding->Endpoint = RPCRT4_strdupA("");
154 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
155 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
156 if (!Binding->Endpoint) ERR("out of memory?\n");
158 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
159 Binding->Endpoint, Binding->NetworkOptions,
160 &Binding->Assoc);
161 if (status != RPC_S_OK)
162 return status;
164 return RPC_S_OK;
167 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
168 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
170 RPC_STATUS status;
172 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
173 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
175 RPCRT4_strfree(Binding->NetworkAddr);
176 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
177 RPCRT4_strfree(Binding->Endpoint);
178 if (Endpoint) {
179 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
180 } else {
181 Binding->Endpoint = RPCRT4_strdupA("");
183 if (!Binding->Endpoint) ERR("out of memory?\n");
184 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
185 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
187 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
188 Binding->Endpoint, Binding->NetworkOptions,
189 &Binding->Assoc);
190 if (status != RPC_S_OK)
191 return status;
193 return RPC_S_OK;
196 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
198 RPC_STATUS status;
200 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
202 RPCRT4_strfree(Binding->Endpoint);
203 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
205 RpcAssoc_Release(Binding->Assoc);
206 Binding->Assoc = NULL;
207 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
208 Binding->Endpoint, Binding->NetworkOptions,
209 &Binding->Assoc);
210 if (status != RPC_S_OK)
211 return status;
213 return RPC_S_OK;
216 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
218 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
219 if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
220 else UuidCreateNil(&Binding->ObjectUuid);
221 return RPC_S_OK;
224 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
226 RpcBinding* NewBinding;
227 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
229 RPCRT4_AllocBinding(&NewBinding, Connection->server);
230 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
231 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
232 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
233 NewBinding->FromConn = Connection;
235 TRACE("binding: %p\n", NewBinding);
236 *Binding = NewBinding;
238 return RPC_S_OK;
241 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
243 InterlockedIncrement(&OldBinding->refs);
244 *Binding = OldBinding;
245 return RPC_S_OK;
248 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
250 if (InterlockedDecrement(&Binding->refs))
251 return RPC_S_OK;
253 TRACE("binding: %p\n", Binding);
254 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
255 RPCRT4_strfree(Binding->Endpoint);
256 RPCRT4_strfree(Binding->NetworkAddr);
257 RPCRT4_strfree(Binding->Protseq);
258 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
259 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
260 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
261 HeapFree(GetProcessHeap(), 0, Binding);
262 return RPC_S_OK;
265 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
266 PRPC_SYNTAX_IDENTIFIER TransferSyntax,
267 PRPC_SYNTAX_IDENTIFIER InterfaceId)
269 RpcConnection* NewConnection;
270 RPC_STATUS status;
272 TRACE("(Binding == ^%p)\n", Binding);
274 if (!Binding->server) {
275 /* try to find a compatible connection from the connection pool */
276 NewConnection = RpcAssoc_GetIdleConnection(Binding->Assoc, InterfaceId,
277 TransferSyntax, Binding->AuthInfo, Binding->QOS);
278 if (NewConnection) {
279 *Connection = NewConnection;
280 return RPC_S_OK;
282 } else {
283 /* we already have a connection with acceptable binding, so use it */
284 if (Binding->FromConn) {
285 *Connection = Binding->FromConn;
286 return RPC_S_OK;
290 /* create a new connection */
291 status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
292 Binding->Protseq, Binding->NetworkAddr,
293 Binding->Endpoint, Binding->NetworkOptions,
294 Binding->AuthInfo, Binding->QOS, Binding);
295 if (status != RPC_S_OK)
296 return status;
298 status = RPCRT4_OpenClientConnection(NewConnection);
299 if (status != RPC_S_OK)
301 RPCRT4_DestroyConnection(NewConnection);
302 return status;
305 /* we need to send a binding packet if we are client. */
306 if (!NewConnection->server) {
307 RpcPktHdr *hdr;
308 RpcPktHdr *response_hdr;
309 RPC_MESSAGE msg;
311 TRACE("sending bind request to server\n");
313 hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
314 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
315 InterfaceId, TransferSyntax);
317 status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
318 RPCRT4_FreeHeader(hdr);
319 if (status != RPC_S_OK) {
320 RPCRT4_DestroyConnection(NewConnection);
321 return status;
324 status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
325 if (status != RPC_S_OK) {
326 ERR("receive failed\n");
327 RPCRT4_DestroyConnection(NewConnection);
328 return status;
331 if (response_hdr->common.ptype != PKT_BIND_ACK ||
332 response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
333 ERR("failed to bind for interface %s, %d.%d\n",
334 debugstr_guid(&InterfaceId->SyntaxGUID),
335 InterfaceId->SyntaxVersion.MajorVersion,
336 InterfaceId->SyntaxVersion.MinorVersion);
337 RPCRT4_FreeHeader(response_hdr);
338 RPCRT4_DestroyConnection(NewConnection);
339 return RPC_S_PROTOCOL_ERROR;
342 /* FIXME: do more checks? */
344 NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
345 NewConnection->ActiveInterface = *InterfaceId;
346 RPCRT4_FreeHeader(response_hdr);
349 if (Binding->server)
350 Binding->FromConn = NewConnection;
351 *Connection = NewConnection;
353 return RPC_S_OK;
356 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
358 TRACE("(Binding == ^%p)\n", Binding);
359 if (!Connection) return RPC_S_OK;
360 if (Binding->server) {
361 /* don't destroy a connection that is cached in the binding */
362 if (Binding->FromConn == Connection)
363 return RPC_S_OK;
364 return RPCRT4_DestroyConnection(Connection);
366 else {
367 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
368 return RPC_S_OK;
372 /* utility functions for string composing and parsing */
373 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
375 unsigned len = strlen(src);
376 memcpy(data, src, len*sizeof(CHAR));
377 return len;
380 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
382 unsigned len = strlenW(src);
383 memcpy(data, src, len*sizeof(WCHAR));
384 return len;
387 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
389 DWORD len = strlen(dst), slen = strlen(src);
390 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
391 if (!ndst)
393 HeapFree(GetProcessHeap(), 0, dst);
394 return NULL;
396 ndst[len] = ',';
397 memcpy(ndst+len+1, src, slen+1);
398 return ndst;
401 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
403 DWORD len = strlenW(dst), slen = strlenW(src);
404 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
405 if (!ndst)
407 HeapFree(GetProcessHeap(), 0, dst);
408 return NULL;
410 ndst[len] = ',';
411 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
412 return ndst;
416 /***********************************************************************
417 * RpcStringBindingComposeA (RPCRT4.@)
419 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
420 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
421 RPC_CSTR Options, RPC_CSTR *StringBinding )
423 DWORD len = 1;
424 LPSTR data;
426 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
427 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
428 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
429 debugstr_a( (char*)Options ), StringBinding );
431 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
432 if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
433 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
434 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
435 if (Options && *Options) len += strlen((char*)Options) + 2;
437 data = HeapAlloc(GetProcessHeap(), 0, len);
438 *StringBinding = (unsigned char*)data;
440 if (ObjUuid && *ObjUuid) {
441 data += RPCRT4_strcopyA(data, (char*)ObjUuid);
442 *data++ = '@';
444 if (Protseq && *Protseq) {
445 data += RPCRT4_strcopyA(data, (char*)Protseq);
446 *data++ = ':';
448 if (NetworkAddr && *NetworkAddr)
449 data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
451 if ((Endpoint && *Endpoint) ||
452 (Options && *Options)) {
453 *data++ = '[';
454 if (Endpoint && *Endpoint) {
455 data += RPCRT4_strcopyA(data, (char*)Endpoint);
456 if (Options && *Options) *data++ = ',';
458 if (Options && *Options) {
459 data += RPCRT4_strcopyA(data, (char*)Options);
461 *data++ = ']';
463 *data = 0;
465 return RPC_S_OK;
468 /***********************************************************************
469 * RpcStringBindingComposeW (RPCRT4.@)
471 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
472 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
473 RPC_WSTR Options, RPC_WSTR* StringBinding )
475 DWORD len = 1;
476 RPC_WSTR data;
478 TRACE("(%s,%s,%s,%s,%s,%p)\n",
479 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
480 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
481 debugstr_w( Options ), StringBinding);
483 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
484 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
485 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
486 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
487 if (Options && *Options) len += strlenW(Options) + 2;
489 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
490 *StringBinding = data;
492 if (ObjUuid && *ObjUuid) {
493 data += RPCRT4_strcopyW(data, ObjUuid);
494 *data++ = '@';
496 if (Protseq && *Protseq) {
497 data += RPCRT4_strcopyW(data, Protseq);
498 *data++ = ':';
500 if (NetworkAddr && *NetworkAddr) {
501 data += RPCRT4_strcopyW(data, NetworkAddr);
503 if ((Endpoint && *Endpoint) ||
504 (Options && *Options)) {
505 *data++ = '[';
506 if (Endpoint && *Endpoint) {
507 data += RPCRT4_strcopyW(data, Endpoint);
508 if (Options && *Options) *data++ = ',';
510 if (Options && *Options) {
511 data += RPCRT4_strcopyW(data, Options);
513 *data++ = ']';
515 *data = 0;
517 return RPC_S_OK;
521 /***********************************************************************
522 * RpcStringBindingParseA (RPCRT4.@)
524 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
525 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
526 RPC_CSTR *Endpoint, RPC_CSTR *Options)
528 CHAR *data, *next;
529 static const char ep_opt[] = "endpoint=";
531 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
532 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
534 if (ObjUuid) *ObjUuid = NULL;
535 if (Protseq) *Protseq = NULL;
536 if (NetworkAddr) *NetworkAddr = NULL;
537 if (Endpoint) *Endpoint = NULL;
538 if (Options) *Options = NULL;
540 data = (char*) StringBinding;
542 next = strchr(data, '@');
543 if (next) {
544 if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
545 data = next+1;
548 next = strchr(data, ':');
549 if (next) {
550 if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
551 data = next+1;
554 next = strchr(data, '[');
555 if (next) {
556 CHAR *close, *opt;
558 if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
559 data = next+1;
560 close = strchr(data, ']');
561 if (!close) goto fail;
563 /* tokenize options */
564 while (data < close) {
565 next = strchr(data, ',');
566 if (!next || next > close) next = close;
567 /* FIXME: this is kind of inefficient */
568 opt = RPCRT4_strndupA(data, next - data);
569 data = next+1;
571 /* parse option */
572 next = strchr(opt, '=');
573 if (!next) {
574 /* not an option, must be an endpoint */
575 if (*Endpoint) goto fail;
576 *Endpoint = (unsigned char*) opt;
577 } else {
578 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
579 /* endpoint option */
580 if (*Endpoint) goto fail;
581 *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
582 HeapFree(GetProcessHeap(), 0, opt);
583 } else {
584 /* network option */
585 if (*Options) {
586 /* FIXME: this is kind of inefficient */
587 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
588 HeapFree(GetProcessHeap(), 0, opt);
589 } else
590 *Options = (unsigned char*) opt;
595 data = close+1;
596 if (*data) goto fail;
598 else if (NetworkAddr)
599 *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
601 return RPC_S_OK;
603 fail:
604 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
605 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
606 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
607 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
608 if (Options) RpcStringFreeA((unsigned char**)Options);
609 return RPC_S_INVALID_STRING_BINDING;
612 /***********************************************************************
613 * RpcStringBindingParseW (RPCRT4.@)
615 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
616 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
617 RPC_WSTR *Endpoint, RPC_WSTR *Options)
619 WCHAR *data, *next;
620 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
622 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
623 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
625 if (ObjUuid) *ObjUuid = NULL;
626 if (Protseq) *Protseq = NULL;
627 if (NetworkAddr) *NetworkAddr = NULL;
628 if (Endpoint) *Endpoint = NULL;
629 if (Options) *Options = NULL;
631 data = StringBinding;
633 next = strchrW(data, '@');
634 if (next) {
635 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
636 data = next+1;
639 next = strchrW(data, ':');
640 if (next) {
641 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
642 data = next+1;
645 next = strchrW(data, '[');
646 if (next) {
647 WCHAR *close, *opt;
649 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
650 data = next+1;
651 close = strchrW(data, ']');
652 if (!close) goto fail;
654 /* tokenize options */
655 while (data < close) {
656 next = strchrW(data, ',');
657 if (!next || next > close) next = close;
658 /* FIXME: this is kind of inefficient */
659 opt = RPCRT4_strndupW(data, next - data);
660 data = next+1;
662 /* parse option */
663 next = strchrW(opt, '=');
664 if (!next) {
665 /* not an option, must be an endpoint */
666 if (*Endpoint) goto fail;
667 *Endpoint = opt;
668 } else {
669 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
670 /* endpoint option */
671 if (*Endpoint) goto fail;
672 *Endpoint = RPCRT4_strdupW(next+1);
673 HeapFree(GetProcessHeap(), 0, opt);
674 } else {
675 /* network option */
676 if (*Options) {
677 /* FIXME: this is kind of inefficient */
678 *Options = RPCRT4_strconcatW(*Options, opt);
679 HeapFree(GetProcessHeap(), 0, opt);
680 } else
681 *Options = opt;
686 data = close+1;
687 if (*data) goto fail;
688 } else if (NetworkAddr)
689 *NetworkAddr = RPCRT4_strdupW(data);
691 return RPC_S_OK;
693 fail:
694 if (ObjUuid) RpcStringFreeW(ObjUuid);
695 if (Protseq) RpcStringFreeW(Protseq);
696 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
697 if (Endpoint) RpcStringFreeW(Endpoint);
698 if (Options) RpcStringFreeW(Options);
699 return RPC_S_INVALID_STRING_BINDING;
702 /***********************************************************************
703 * RpcBindingFree (RPCRT4.@)
705 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
707 RPC_STATUS status;
708 TRACE("(%p) = %p\n", Binding, *Binding);
709 status = RPCRT4_DestroyBinding(*Binding);
710 if (status == RPC_S_OK) *Binding = 0;
711 return status;
714 /***********************************************************************
715 * RpcBindingVectorFree (RPCRT4.@)
717 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
719 RPC_STATUS status;
720 unsigned long c;
722 TRACE("(%p)\n", BindingVector);
723 for (c=0; c<(*BindingVector)->Count; c++) {
724 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
726 HeapFree(GetProcessHeap(), 0, *BindingVector);
727 *BindingVector = NULL;
728 return RPC_S_OK;
731 /***********************************************************************
732 * RpcBindingInqObject (RPCRT4.@)
734 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
736 RpcBinding* bind = (RpcBinding*)Binding;
738 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
739 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
740 return RPC_S_OK;
743 /***********************************************************************
744 * RpcBindingSetObject (RPCRT4.@)
746 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
748 RpcBinding* bind = (RpcBinding*)Binding;
750 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
751 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
752 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
755 /***********************************************************************
756 * RpcBindingFromStringBindingA (RPCRT4.@)
758 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
760 RPC_STATUS ret;
761 RpcBinding* bind = NULL;
762 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
763 UUID Uuid;
765 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
767 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
768 &NetworkAddr, &Endpoint, &Options);
769 if (ret != RPC_S_OK) return ret;
771 ret = UuidFromStringA(ObjectUuid, &Uuid);
773 if (ret == RPC_S_OK)
774 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
775 if (ret == RPC_S_OK)
776 ret = RPCRT4_SetBindingObject(bind, &Uuid);
777 if (ret == RPC_S_OK)
778 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
780 RpcStringFreeA((unsigned char**)&Options);
781 RpcStringFreeA((unsigned char**)&Endpoint);
782 RpcStringFreeA((unsigned char**)&NetworkAddr);
783 RpcStringFreeA((unsigned char**)&Protseq);
784 RpcStringFreeA((unsigned char**)&ObjectUuid);
786 if (ret == RPC_S_OK)
787 *Binding = (RPC_BINDING_HANDLE)bind;
788 else
789 RPCRT4_DestroyBinding(bind);
791 return ret;
794 /***********************************************************************
795 * RpcBindingFromStringBindingW (RPCRT4.@)
797 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
799 RPC_STATUS ret;
800 RpcBinding* bind = NULL;
801 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
802 UUID Uuid;
804 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
806 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
807 &NetworkAddr, &Endpoint, &Options);
808 if (ret != RPC_S_OK) return ret;
810 ret = UuidFromStringW(ObjectUuid, &Uuid);
812 if (ret == RPC_S_OK)
813 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
814 if (ret == RPC_S_OK)
815 ret = RPCRT4_SetBindingObject(bind, &Uuid);
816 if (ret == RPC_S_OK)
817 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
819 RpcStringFreeW(&Options);
820 RpcStringFreeW(&Endpoint);
821 RpcStringFreeW(&NetworkAddr);
822 RpcStringFreeW(&Protseq);
823 RpcStringFreeW(&ObjectUuid);
825 if (ret == RPC_S_OK)
826 *Binding = (RPC_BINDING_HANDLE)bind;
827 else
828 RPCRT4_DestroyBinding(bind);
830 return ret;
833 /***********************************************************************
834 * RpcBindingToStringBindingA (RPCRT4.@)
836 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
838 RPC_STATUS ret;
839 RpcBinding* bind = (RpcBinding*)Binding;
840 RPC_CSTR ObjectUuid;
842 TRACE("(%p,%p)\n", Binding, StringBinding);
844 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
845 if (ret != RPC_S_OK) return ret;
847 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
848 (unsigned char*) bind->Endpoint, NULL, StringBinding);
850 RpcStringFreeA(&ObjectUuid);
852 return ret;
855 /***********************************************************************
856 * RpcBindingToStringBindingW (RPCRT4.@)
858 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
860 RPC_STATUS ret;
861 unsigned char *str = NULL;
862 TRACE("(%p,%p)\n", Binding, StringBinding);
863 ret = RpcBindingToStringBindingA(Binding, &str);
864 *StringBinding = RPCRT4_strdupAtoW((char*)str);
865 RpcStringFreeA((unsigned char**)&str);
866 return ret;
869 /***********************************************************************
870 * I_RpcBindingSetAsync (RPCRT4.@)
871 * NOTES
872 * Exists in win9x and winNT, but with different number of arguments
873 * (9x version has 3 arguments, NT has 2).
875 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
877 RpcBinding* bind = (RpcBinding*)Binding;
879 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
881 bind->BlockingFn = BlockingFn;
883 return RPC_S_OK;
886 /***********************************************************************
887 * RpcBindingCopy (RPCRT4.@)
889 RPC_STATUS RPC_ENTRY RpcBindingCopy(
890 RPC_BINDING_HANDLE SourceBinding,
891 RPC_BINDING_HANDLE* DestinationBinding)
893 RpcBinding *DestBinding;
894 RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
895 RPC_STATUS status;
897 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
899 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
900 if (status != RPC_S_OK) return status;
902 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
903 DestBinding->BlockingFn = SrcBinding->BlockingFn;
904 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
905 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
906 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
907 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
908 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
909 DestBinding->Assoc = SrcBinding->Assoc;
911 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
912 DestBinding->AuthInfo = SrcBinding->AuthInfo;
913 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
914 DestBinding->QOS = SrcBinding->QOS;
916 *DestinationBinding = DestBinding;
917 return RPC_S_OK;
920 /***********************************************************************
921 * RpcImpersonateClient (RPCRT4.@)
923 * Impersonates the client connected via a binding handle so that security
924 * checks are done in the context of the client.
926 * PARAMS
927 * BindingHandle [I] Handle to the binding to the client.
929 * RETURNS
930 * Success: RPS_S_OK.
931 * Failure: RPC_STATUS value.
933 * NOTES
935 * If BindingHandle is NULL then the function impersonates the client
936 * connected to the binding handle of the current thread.
938 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
940 FIXME("(%p): stub\n", BindingHandle);
941 ImpersonateSelf(SecurityImpersonation);
942 return RPC_S_OK;
945 /***********************************************************************
946 * RpcRevertToSelfEx (RPCRT4.@)
948 * Stops impersonating the client connected to the binding handle so that security
949 * checks are no longer done in the context of the client.
951 * PARAMS
952 * BindingHandle [I] Handle to the binding to the client.
954 * RETURNS
955 * Success: RPS_S_OK.
956 * Failure: RPC_STATUS value.
958 * NOTES
960 * If BindingHandle is NULL then the function stops impersonating the client
961 * connected to the binding handle of the current thread.
963 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
965 FIXME("(%p): stub\n", BindingHandle);
966 return RPC_S_OK;
969 static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
970 CredHandle cred, TimeStamp exp,
971 ULONG cbMaxToken, RpcAuthInfo **ret)
973 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
974 if (!AuthInfo)
975 return ERROR_OUTOFMEMORY;
977 AuthInfo->refs = 1;
978 AuthInfo->AuthnLevel = AuthnLevel;
979 AuthInfo->AuthnSvc = AuthnSvc;
980 AuthInfo->cred = cred;
981 AuthInfo->exp = exp;
982 AuthInfo->cbMaxToken = cbMaxToken;
983 *ret = AuthInfo;
984 return RPC_S_OK;
987 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
989 return InterlockedIncrement(&AuthInfo->refs);
992 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
994 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
996 if (!refs)
998 FreeCredentialsHandle(&AuthInfo->cred);
999 HeapFree(GetProcessHeap(), 0, AuthInfo);
1002 return refs;
1005 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1007 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1009 if (!qos)
1010 return RPC_S_OUT_OF_RESOURCES;
1012 qos->refs = 1;
1013 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1014 if (!qos->qos) goto error;
1015 qos->qos->Version = qos_src->Version;
1016 qos->qos->Capabilities = qos_src->Capabilities;
1017 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1018 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1019 qos->qos->AdditionalSecurityInfoType = 0;
1021 if (qos_src->Version >= 2)
1023 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1024 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1025 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1027 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1028 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1030 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1031 qos->qos->u.HttpCredentials = http_credentials_dst;
1032 if (!http_credentials_dst) goto error;
1033 http_credentials_dst->TransportCredentials = NULL;
1034 http_credentials_dst->Flags = http_credentials_src->Flags;
1035 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1036 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1037 http_credentials_dst->AuthnSchemes = NULL;
1038 http_credentials_dst->ServerCertificateSubject = NULL;
1039 if (http_credentials_src->TransportCredentials)
1041 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1042 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1043 if (!cred_dst) goto error;
1044 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1045 if (unicode)
1047 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1048 cred_dst->UserLength = cred_src->UserLength;
1049 cred_dst->PasswordLength = cred_src->PasswordLength;
1050 cred_dst->DomainLength = cred_src->DomainLength;
1051 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1052 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1053 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1055 else
1057 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1058 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1059 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1060 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1061 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1062 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1063 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1064 if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error;
1065 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1066 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1067 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1070 if (http_credentials_src->NumberOfAuthnSchemes)
1072 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1073 if (!http_credentials_dst->AuthnSchemes) goto error;
1074 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1076 if (http_credentials_src->ServerCertificateSubject)
1078 if (unicode)
1079 http_credentials_dst->ServerCertificateSubject =
1080 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1081 strlenW(http_credentials_src->ServerCertificateSubject));
1082 else
1083 http_credentials_dst->ServerCertificateSubject =
1084 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1085 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1089 *qos_dst = qos;
1090 return RPC_S_OK;
1092 error:
1093 if (qos->qos)
1095 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1096 qos->qos->u.HttpCredentials)
1098 if (qos->qos->u.HttpCredentials->TransportCredentials)
1100 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1101 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1102 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1103 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1105 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1106 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1107 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1109 HeapFree(GetProcessHeap(), 0, qos->qos);
1111 HeapFree(GetProcessHeap(), 0, qos);
1112 return RPC_S_OUT_OF_RESOURCES;
1115 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1117 return InterlockedIncrement(&qos->refs);
1120 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1122 ULONG refs = InterlockedDecrement(&qos->refs);
1124 if (!refs)
1126 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1128 if (qos->qos->u.HttpCredentials->TransportCredentials)
1130 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1131 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1132 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1133 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1135 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1136 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1137 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1139 HeapFree(GetProcessHeap(), 0, qos->qos);
1140 HeapFree(GetProcessHeap(), 0, qos);
1142 return refs;
1145 /***********************************************************************
1146 * RpcRevertToSelf (RPCRT4.@)
1148 RPC_STATUS WINAPI RpcRevertToSelf(void)
1150 FIXME("stub\n");
1151 RevertToSelf();
1152 return RPC_S_OK;
1155 /***********************************************************************
1156 * RpcMgmtSetComTimeout (RPCRT4.@)
1158 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1160 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1161 return RPC_S_OK;
1164 /***********************************************************************
1165 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1167 RPCRTAPI RPC_STATUS RPC_ENTRY
1168 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1169 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1170 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1172 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1173 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1174 return RPC_S_INVALID_BINDING;
1177 /***********************************************************************
1178 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1180 RPCRTAPI RPC_STATUS RPC_ENTRY
1181 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1182 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1183 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1185 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1186 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1187 return RPC_S_INVALID_BINDING;
1190 /***********************************************************************
1191 * RpcBindingInqAuthInfoA (RPCRT4.@)
1193 RPCRTAPI RPC_STATUS RPC_ENTRY
1194 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1195 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1197 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1198 AuthnSvc, AuthIdentity, AuthzSvc);
1199 return RPC_S_INVALID_BINDING;
1202 /***********************************************************************
1203 * RpcBindingInqAuthInfoW (RPCRT4.@)
1205 RPCRTAPI RPC_STATUS RPC_ENTRY
1206 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1207 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1209 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1210 AuthnSvc, AuthIdentity, AuthzSvc);
1211 return RPC_S_INVALID_BINDING;
1214 /***********************************************************************
1215 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1217 RPCRTAPI RPC_STATUS RPC_ENTRY
1218 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1219 ULONG AuthnLevel, ULONG AuthnSvc,
1220 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1221 RPC_SECURITY_QOS *SecurityQos )
1223 RpcBinding* bind = (RpcBinding*)Binding;
1224 SECURITY_STATUS r;
1225 CredHandle cred;
1226 TimeStamp exp;
1227 ULONG package_count;
1228 ULONG i;
1229 PSecPkgInfoA packages;
1230 ULONG cbMaxToken;
1232 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1233 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1235 if (SecurityQos)
1237 RPC_STATUS status;
1239 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1240 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1241 if (SecurityQos->Version >= 2)
1243 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1244 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1245 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1246 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1247 SecurityQos2->u.HttpCredentials->TransportCredentials,
1248 SecurityQos2->u.HttpCredentials->Flags,
1249 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1250 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1251 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1252 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1254 TRACE("}\n");
1255 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1256 if (status != RPC_S_OK)
1257 return status;
1259 else
1261 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1262 bind->QOS = NULL;
1265 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1266 AuthnSvc = RPC_C_AUTHN_WINNT;
1268 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1269 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1270 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1272 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1274 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1275 bind->AuthInfo = NULL;
1276 return RPC_S_OK;
1279 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1281 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1282 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1285 if (AuthzSvr)
1287 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1288 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1291 r = EnumerateSecurityPackagesA(&package_count, &packages);
1292 if (r != SEC_E_OK)
1294 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1295 return RPC_S_SEC_PKG_ERROR;
1298 for (i = 0; i < package_count; i++)
1299 if (packages[i].wRPCID == AuthnSvc)
1300 break;
1302 if (i == package_count)
1304 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1305 FreeContextBuffer(packages);
1306 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1309 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1310 r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1311 AuthIdentity, NULL, NULL, &cred, &exp);
1312 cbMaxToken = packages[i].cbMaxToken;
1313 FreeContextBuffer(packages);
1314 if (r == ERROR_SUCCESS)
1316 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1317 bind->AuthInfo = NULL;
1318 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1319 &bind->AuthInfo);
1320 if (r != RPC_S_OK)
1321 FreeCredentialsHandle(&cred);
1322 return RPC_S_OK;
1324 else
1326 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1327 return RPC_S_SEC_PKG_ERROR;
1331 /***********************************************************************
1332 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1334 RPCRTAPI RPC_STATUS RPC_ENTRY
1335 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1336 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1337 RPC_SECURITY_QOS *SecurityQos )
1339 RpcBinding* bind = (RpcBinding*)Binding;
1340 SECURITY_STATUS r;
1341 CredHandle cred;
1342 TimeStamp exp;
1343 ULONG package_count;
1344 ULONG i;
1345 PSecPkgInfoW packages;
1346 ULONG cbMaxToken;
1348 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1349 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1351 if (SecurityQos)
1353 RPC_STATUS status;
1355 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1356 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1357 if (SecurityQos->Version >= 2)
1359 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1360 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1361 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1362 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1363 SecurityQos2->u.HttpCredentials->TransportCredentials,
1364 SecurityQos2->u.HttpCredentials->Flags,
1365 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1366 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1367 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1368 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1370 TRACE("}\n");
1371 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1372 if (status != RPC_S_OK)
1373 return status;
1375 else
1377 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1378 bind->QOS = NULL;
1381 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1382 AuthnSvc = RPC_C_AUTHN_WINNT;
1384 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1385 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1386 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1388 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1390 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1391 bind->AuthInfo = NULL;
1392 return RPC_S_OK;
1395 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1397 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1398 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1401 if (AuthzSvr)
1403 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1404 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1407 r = EnumerateSecurityPackagesW(&package_count, &packages);
1408 if (r != SEC_E_OK)
1410 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1411 return RPC_S_SEC_PKG_ERROR;
1414 for (i = 0; i < package_count; i++)
1415 if (packages[i].wRPCID == AuthnSvc)
1416 break;
1418 if (i == package_count)
1420 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1421 FreeContextBuffer(packages);
1422 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1425 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1426 r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1427 AuthIdentity, NULL, NULL, &cred, &exp);
1428 cbMaxToken = packages[i].cbMaxToken;
1429 FreeContextBuffer(packages);
1430 if (r == ERROR_SUCCESS)
1432 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1433 bind->AuthInfo = NULL;
1434 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1435 &bind->AuthInfo);
1436 if (r != RPC_S_OK)
1437 FreeCredentialsHandle(&cred);
1438 return RPC_S_OK;
1440 else
1442 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1443 return RPC_S_SEC_PKG_ERROR;
1447 /***********************************************************************
1448 * RpcBindingSetAuthInfoA (RPCRT4.@)
1450 RPCRTAPI RPC_STATUS RPC_ENTRY
1451 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1452 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1454 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1455 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1456 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1459 /***********************************************************************
1460 * RpcBindingSetAuthInfoW (RPCRT4.@)
1462 RPCRTAPI RPC_STATUS RPC_ENTRY
1463 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1464 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1466 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1467 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1468 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1471 /***********************************************************************
1472 * RpcBindingSetOption (RPCRT4.@)
1474 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1476 FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue);
1477 return RPC_S_OK;