comctl32: toolbar: Don't execute TB_GETBUTTONINFO if cbSize is invalid.
[wine/multimedia.git] / dlls / rpcrt4 / rpc_binding.c
blobad96ac6496eb12b186bc3bb5016a3234f690211b
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 "winreg.h"
34 #include "winternl.h"
35 #include "wine/unicode.h"
37 #include "rpc.h"
38 #include "rpcndr.h"
40 #include "wine/debug.h"
42 #include "rpc_binding.h"
43 #include "rpc_message.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
47 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
49 DWORD len;
50 LPSTR s;
51 if (!src) return NULL;
52 if (slen == -1) slen = strlen(src);
53 len = slen;
54 s = HeapAlloc(GetProcessHeap(), 0, len+1);
55 memcpy(s, src, len);
56 s[len] = 0;
57 return s;
60 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
62 DWORD len;
63 LPSTR s;
64 if (!src) return NULL;
65 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
66 s = HeapAlloc(GetProcessHeap(), 0, len);
67 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
68 return s;
71 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
73 DWORD len;
74 LPWSTR s;
75 if (!src) return NULL;
76 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
77 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
78 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
79 return s;
82 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
84 DWORD len;
85 LPWSTR s;
86 if (!src) return NULL;
87 if (slen == -1) slen = strlenW(src);
88 len = slen;
89 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
90 memcpy(s, src, len*sizeof(WCHAR));
91 s[len] = 0;
92 return s;
95 void RPCRT4_strfree(LPSTR src)
97 HeapFree(GetProcessHeap(), 0, src);
100 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
102 RpcBinding* NewBinding;
104 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
105 NewBinding->refs = 1;
106 NewBinding->server = server;
108 *Binding = NewBinding;
110 return RPC_S_OK;
113 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
115 RpcBinding* NewBinding;
117 RPCRT4_AllocBinding(&NewBinding, server);
118 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
120 TRACE("binding: %p\n", NewBinding);
121 *Binding = NewBinding;
123 return RPC_S_OK;
126 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
128 RpcBinding* NewBinding;
130 RPCRT4_AllocBinding(&NewBinding, server);
131 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
133 TRACE("binding: %p\n", NewBinding);
134 *Binding = NewBinding;
136 return RPC_S_OK;
139 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
140 LPCSTR Endpoint, LPCSTR NetworkOptions)
142 RPC_STATUS status;
144 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
145 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
147 RPCRT4_strfree(Binding->NetworkAddr);
148 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
149 RPCRT4_strfree(Binding->Endpoint);
150 if (Endpoint) {
151 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
152 } else {
153 Binding->Endpoint = RPCRT4_strdupA("");
155 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
156 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
157 if (!Binding->Endpoint) ERR("out of memory?\n");
159 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
160 Binding->Endpoint, Binding->NetworkOptions,
161 &Binding->Assoc);
162 if (status != RPC_S_OK)
163 return status;
165 return RPC_S_OK;
168 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
169 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
171 RPC_STATUS status;
173 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
174 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
176 RPCRT4_strfree(Binding->NetworkAddr);
177 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
178 RPCRT4_strfree(Binding->Endpoint);
179 if (Endpoint) {
180 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
181 } else {
182 Binding->Endpoint = RPCRT4_strdupA("");
184 if (!Binding->Endpoint) ERR("out of memory?\n");
185 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
186 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
188 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
189 Binding->Endpoint, Binding->NetworkOptions,
190 &Binding->Assoc);
191 if (status != RPC_S_OK)
192 return status;
194 return RPC_S_OK;
197 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
199 RPC_STATUS status;
201 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
203 RPCRT4_strfree(Binding->Endpoint);
204 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
206 RpcAssoc_Release(Binding->Assoc);
207 Binding->Assoc = NULL;
208 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
209 Binding->Endpoint, Binding->NetworkOptions,
210 &Binding->Assoc);
211 if (status != RPC_S_OK)
212 return status;
214 return RPC_S_OK;
217 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
219 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
220 if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
221 else UuidCreateNil(&Binding->ObjectUuid);
222 return RPC_S_OK;
225 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
227 RpcBinding* NewBinding;
228 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
230 RPCRT4_AllocBinding(&NewBinding, Connection->server);
231 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
232 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
233 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
234 NewBinding->FromConn = Connection;
236 TRACE("binding: %p\n", NewBinding);
237 *Binding = NewBinding;
239 return RPC_S_OK;
242 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
244 InterlockedIncrement(&OldBinding->refs);
245 *Binding = OldBinding;
246 return RPC_S_OK;
249 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
251 if (InterlockedDecrement(&Binding->refs))
252 return RPC_S_OK;
254 TRACE("binding: %p\n", Binding);
255 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
256 RPCRT4_strfree(Binding->Endpoint);
257 RPCRT4_strfree(Binding->NetworkAddr);
258 RPCRT4_strfree(Binding->Protseq);
259 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
260 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
261 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
262 HeapFree(GetProcessHeap(), 0, Binding);
263 return RPC_S_OK;
266 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
267 PRPC_SYNTAX_IDENTIFIER TransferSyntax,
268 PRPC_SYNTAX_IDENTIFIER InterfaceId)
270 RpcConnection* NewConnection;
271 RPC_STATUS status;
273 TRACE("(Binding == ^%p)\n", Binding);
275 if (!Binding->server) {
276 /* try to find a compatible connection from the connection pool */
277 NewConnection = RpcAssoc_GetIdleConnection(Binding->Assoc, InterfaceId,
278 TransferSyntax, Binding->AuthInfo, Binding->QOS);
279 if (NewConnection) {
280 *Connection = NewConnection;
281 return RPC_S_OK;
283 } else {
284 /* we already have a connection with acceptable binding, so use it */
285 if (Binding->FromConn) {
286 *Connection = Binding->FromConn;
287 return RPC_S_OK;
291 /* create a new connection */
292 status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
293 Binding->Protseq, Binding->NetworkAddr,
294 Binding->Endpoint, Binding->NetworkOptions,
295 Binding->AuthInfo, Binding->QOS, Binding);
296 if (status != RPC_S_OK)
297 return status;
299 status = RPCRT4_OpenClientConnection(NewConnection);
300 if (status != RPC_S_OK)
302 RPCRT4_DestroyConnection(NewConnection);
303 return status;
306 /* we need to send a binding packet if we are client. */
307 if (!NewConnection->server) {
308 RpcPktHdr *hdr;
309 RpcPktHdr *response_hdr;
310 RPC_MESSAGE msg;
312 TRACE("sending bind request to server\n");
314 hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
315 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
316 InterfaceId, TransferSyntax);
318 status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
319 RPCRT4_FreeHeader(hdr);
320 if (status != RPC_S_OK) {
321 RPCRT4_DestroyConnection(NewConnection);
322 return status;
325 status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
326 if (status != RPC_S_OK) {
327 ERR("receive failed\n");
328 RPCRT4_DestroyConnection(NewConnection);
329 return status;
332 if (response_hdr->common.ptype != PKT_BIND_ACK ||
333 response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
334 ERR("failed to bind for interface %s, %d.%d\n",
335 debugstr_guid(&InterfaceId->SyntaxGUID),
336 InterfaceId->SyntaxVersion.MajorVersion,
337 InterfaceId->SyntaxVersion.MinorVersion);
338 RPCRT4_FreeHeader(response_hdr);
339 RPCRT4_DestroyConnection(NewConnection);
340 return RPC_S_PROTOCOL_ERROR;
343 /* FIXME: do more checks? */
345 NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
346 NewConnection->ActiveInterface = *InterfaceId;
347 RPCRT4_FreeHeader(response_hdr);
350 if (Binding->server)
351 Binding->FromConn = NewConnection;
352 *Connection = NewConnection;
354 return RPC_S_OK;
357 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
359 TRACE("(Binding == ^%p)\n", Binding);
360 if (!Connection) return RPC_S_OK;
361 if (Binding->server) {
362 /* don't destroy a connection that is cached in the binding */
363 if (Binding->FromConn == Connection)
364 return RPC_S_OK;
365 return RPCRT4_DestroyConnection(Connection);
367 else {
368 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
369 return RPC_S_OK;
373 /* utility functions for string composing and parsing */
374 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
376 unsigned len = strlen(src);
377 memcpy(data, src, len*sizeof(CHAR));
378 return len;
381 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
383 unsigned len = strlenW(src);
384 memcpy(data, src, len*sizeof(WCHAR));
385 return len;
388 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
390 DWORD len = strlen(dst), slen = strlen(src);
391 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
392 if (!ndst)
394 HeapFree(GetProcessHeap(), 0, dst);
395 return NULL;
397 ndst[len] = ',';
398 memcpy(ndst+len+1, src, slen+1);
399 return ndst;
402 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
404 DWORD len = strlenW(dst), slen = strlenW(src);
405 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
406 if (!ndst)
408 HeapFree(GetProcessHeap(), 0, dst);
409 return NULL;
411 ndst[len] = ',';
412 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
413 return ndst;
417 /***********************************************************************
418 * RpcStringBindingComposeA (RPCRT4.@)
420 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
421 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
422 RPC_CSTR Options, RPC_CSTR *StringBinding )
424 DWORD len = 1;
425 LPSTR data;
427 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
428 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
429 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
430 debugstr_a( (char*)Options ), StringBinding );
432 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
433 if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
434 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
435 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
436 if (Options && *Options) len += strlen((char*)Options) + 2;
438 data = HeapAlloc(GetProcessHeap(), 0, len);
439 *StringBinding = (unsigned char*)data;
441 if (ObjUuid && *ObjUuid) {
442 data += RPCRT4_strcopyA(data, (char*)ObjUuid);
443 *data++ = '@';
445 if (Protseq && *Protseq) {
446 data += RPCRT4_strcopyA(data, (char*)Protseq);
447 *data++ = ':';
449 if (NetworkAddr && *NetworkAddr)
450 data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
452 if ((Endpoint && *Endpoint) ||
453 (Options && *Options)) {
454 *data++ = '[';
455 if (Endpoint && *Endpoint) {
456 data += RPCRT4_strcopyA(data, (char*)Endpoint);
457 if (Options && *Options) *data++ = ',';
459 if (Options && *Options) {
460 data += RPCRT4_strcopyA(data, (char*)Options);
462 *data++ = ']';
464 *data = 0;
466 return RPC_S_OK;
469 /***********************************************************************
470 * RpcStringBindingComposeW (RPCRT4.@)
472 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
473 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
474 RPC_WSTR Options, RPC_WSTR* StringBinding )
476 DWORD len = 1;
477 RPC_WSTR data;
479 TRACE("(%s,%s,%s,%s,%s,%p)\n",
480 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
481 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
482 debugstr_w( Options ), StringBinding);
484 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
485 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
486 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
487 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
488 if (Options && *Options) len += strlenW(Options) + 2;
490 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
491 *StringBinding = data;
493 if (ObjUuid && *ObjUuid) {
494 data += RPCRT4_strcopyW(data, ObjUuid);
495 *data++ = '@';
497 if (Protseq && *Protseq) {
498 data += RPCRT4_strcopyW(data, Protseq);
499 *data++ = ':';
501 if (NetworkAddr && *NetworkAddr) {
502 data += RPCRT4_strcopyW(data, NetworkAddr);
504 if ((Endpoint && *Endpoint) ||
505 (Options && *Options)) {
506 *data++ = '[';
507 if (Endpoint && *Endpoint) {
508 data += RPCRT4_strcopyW(data, Endpoint);
509 if (Options && *Options) *data++ = ',';
511 if (Options && *Options) {
512 data += RPCRT4_strcopyW(data, Options);
514 *data++ = ']';
516 *data = 0;
518 return RPC_S_OK;
522 /***********************************************************************
523 * RpcStringBindingParseA (RPCRT4.@)
525 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
526 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
527 RPC_CSTR *Endpoint, RPC_CSTR *Options)
529 CHAR *data, *next;
530 static const char ep_opt[] = "endpoint=";
532 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
533 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
535 if (ObjUuid) *ObjUuid = NULL;
536 if (Protseq) *Protseq = NULL;
537 if (NetworkAddr) *NetworkAddr = NULL;
538 if (Endpoint) *Endpoint = NULL;
539 if (Options) *Options = NULL;
541 data = (char*) StringBinding;
543 next = strchr(data, '@');
544 if (next) {
545 if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
546 data = next+1;
549 next = strchr(data, ':');
550 if (next) {
551 if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
552 data = next+1;
555 next = strchr(data, '[');
556 if (next) {
557 CHAR *close, *opt;
559 if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
560 data = next+1;
561 close = strchr(data, ']');
562 if (!close) goto fail;
564 /* tokenize options */
565 while (data < close) {
566 next = strchr(data, ',');
567 if (!next || next > close) next = close;
568 /* FIXME: this is kind of inefficient */
569 opt = RPCRT4_strndupA(data, next - data);
570 data = next+1;
572 /* parse option */
573 next = strchr(opt, '=');
574 if (!next) {
575 /* not an option, must be an endpoint */
576 if (*Endpoint) goto fail;
577 *Endpoint = (unsigned char*) opt;
578 } else {
579 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
580 /* endpoint option */
581 if (*Endpoint) goto fail;
582 *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
583 HeapFree(GetProcessHeap(), 0, opt);
584 } else {
585 /* network option */
586 if (*Options) {
587 /* FIXME: this is kind of inefficient */
588 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
589 HeapFree(GetProcessHeap(), 0, opt);
590 } else
591 *Options = (unsigned char*) opt;
596 data = close+1;
597 if (*data) goto fail;
599 else if (NetworkAddr)
600 *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
602 return RPC_S_OK;
604 fail:
605 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
606 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
607 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
608 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
609 if (Options) RpcStringFreeA((unsigned char**)Options);
610 return RPC_S_INVALID_STRING_BINDING;
613 /***********************************************************************
614 * RpcStringBindingParseW (RPCRT4.@)
616 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
617 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
618 RPC_WSTR *Endpoint, RPC_WSTR *Options)
620 WCHAR *data, *next;
621 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
623 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
624 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
626 if (ObjUuid) *ObjUuid = NULL;
627 if (Protseq) *Protseq = NULL;
628 if (NetworkAddr) *NetworkAddr = NULL;
629 if (Endpoint) *Endpoint = NULL;
630 if (Options) *Options = NULL;
632 data = StringBinding;
634 next = strchrW(data, '@');
635 if (next) {
636 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
637 data = next+1;
640 next = strchrW(data, ':');
641 if (next) {
642 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
643 data = next+1;
646 next = strchrW(data, '[');
647 if (next) {
648 WCHAR *close, *opt;
650 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
651 data = next+1;
652 close = strchrW(data, ']');
653 if (!close) goto fail;
655 /* tokenize options */
656 while (data < close) {
657 next = strchrW(data, ',');
658 if (!next || next > close) next = close;
659 /* FIXME: this is kind of inefficient */
660 opt = RPCRT4_strndupW(data, next - data);
661 data = next+1;
663 /* parse option */
664 next = strchrW(opt, '=');
665 if (!next) {
666 /* not an option, must be an endpoint */
667 if (*Endpoint) goto fail;
668 *Endpoint = opt;
669 } else {
670 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
671 /* endpoint option */
672 if (*Endpoint) goto fail;
673 *Endpoint = RPCRT4_strdupW(next+1);
674 HeapFree(GetProcessHeap(), 0, opt);
675 } else {
676 /* network option */
677 if (*Options) {
678 /* FIXME: this is kind of inefficient */
679 *Options = RPCRT4_strconcatW(*Options, opt);
680 HeapFree(GetProcessHeap(), 0, opt);
681 } else
682 *Options = opt;
687 data = close+1;
688 if (*data) goto fail;
689 } else if (NetworkAddr)
690 *NetworkAddr = RPCRT4_strdupW(data);
692 return RPC_S_OK;
694 fail:
695 if (ObjUuid) RpcStringFreeW(ObjUuid);
696 if (Protseq) RpcStringFreeW(Protseq);
697 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
698 if (Endpoint) RpcStringFreeW(Endpoint);
699 if (Options) RpcStringFreeW(Options);
700 return RPC_S_INVALID_STRING_BINDING;
703 /***********************************************************************
704 * RpcBindingFree (RPCRT4.@)
706 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
708 RPC_STATUS status;
709 TRACE("(%p) = %p\n", Binding, *Binding);
710 status = RPCRT4_DestroyBinding(*Binding);
711 if (status == RPC_S_OK) *Binding = 0;
712 return status;
715 /***********************************************************************
716 * RpcBindingVectorFree (RPCRT4.@)
718 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
720 RPC_STATUS status;
721 unsigned long c;
723 TRACE("(%p)\n", BindingVector);
724 for (c=0; c<(*BindingVector)->Count; c++) {
725 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
727 HeapFree(GetProcessHeap(), 0, *BindingVector);
728 *BindingVector = NULL;
729 return RPC_S_OK;
732 /***********************************************************************
733 * RpcBindingInqObject (RPCRT4.@)
735 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
737 RpcBinding* bind = (RpcBinding*)Binding;
739 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
740 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
741 return RPC_S_OK;
744 /***********************************************************************
745 * RpcBindingSetObject (RPCRT4.@)
747 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
749 RpcBinding* bind = (RpcBinding*)Binding;
751 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
752 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
753 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
756 /***********************************************************************
757 * RpcBindingFromStringBindingA (RPCRT4.@)
759 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
761 RPC_STATUS ret;
762 RpcBinding* bind = NULL;
763 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
764 UUID Uuid;
766 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
768 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
769 &NetworkAddr, &Endpoint, &Options);
770 if (ret != RPC_S_OK) return ret;
772 ret = UuidFromStringA(ObjectUuid, &Uuid);
774 if (ret == RPC_S_OK)
775 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
776 if (ret == RPC_S_OK)
777 ret = RPCRT4_SetBindingObject(bind, &Uuid);
778 if (ret == RPC_S_OK)
779 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
781 RpcStringFreeA((unsigned char**)&Options);
782 RpcStringFreeA((unsigned char**)&Endpoint);
783 RpcStringFreeA((unsigned char**)&NetworkAddr);
784 RpcStringFreeA((unsigned char**)&Protseq);
785 RpcStringFreeA((unsigned char**)&ObjectUuid);
787 if (ret == RPC_S_OK)
788 *Binding = (RPC_BINDING_HANDLE)bind;
789 else
790 RPCRT4_DestroyBinding(bind);
792 return ret;
795 /***********************************************************************
796 * RpcBindingFromStringBindingW (RPCRT4.@)
798 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
800 RPC_STATUS ret;
801 RpcBinding* bind = NULL;
802 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
803 UUID Uuid;
805 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
807 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
808 &NetworkAddr, &Endpoint, &Options);
809 if (ret != RPC_S_OK) return ret;
811 ret = UuidFromStringW(ObjectUuid, &Uuid);
813 if (ret == RPC_S_OK)
814 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
815 if (ret == RPC_S_OK)
816 ret = RPCRT4_SetBindingObject(bind, &Uuid);
817 if (ret == RPC_S_OK)
818 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
820 RpcStringFreeW(&Options);
821 RpcStringFreeW(&Endpoint);
822 RpcStringFreeW(&NetworkAddr);
823 RpcStringFreeW(&Protseq);
824 RpcStringFreeW(&ObjectUuid);
826 if (ret == RPC_S_OK)
827 *Binding = (RPC_BINDING_HANDLE)bind;
828 else
829 RPCRT4_DestroyBinding(bind);
831 return ret;
834 /***********************************************************************
835 * RpcBindingToStringBindingA (RPCRT4.@)
837 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
839 RPC_STATUS ret;
840 RpcBinding* bind = (RpcBinding*)Binding;
841 RPC_CSTR ObjectUuid;
843 TRACE("(%p,%p)\n", Binding, StringBinding);
845 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
846 if (ret != RPC_S_OK) return ret;
848 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
849 (unsigned char*) bind->Endpoint, NULL, StringBinding);
851 RpcStringFreeA(&ObjectUuid);
853 return ret;
856 /***********************************************************************
857 * RpcBindingToStringBindingW (RPCRT4.@)
859 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
861 RPC_STATUS ret;
862 unsigned char *str = NULL;
863 TRACE("(%p,%p)\n", Binding, StringBinding);
864 ret = RpcBindingToStringBindingA(Binding, &str);
865 *StringBinding = RPCRT4_strdupAtoW((char*)str);
866 RpcStringFreeA((unsigned char**)&str);
867 return ret;
870 /***********************************************************************
871 * I_RpcBindingSetAsync (RPCRT4.@)
872 * NOTES
873 * Exists in win9x and winNT, but with different number of arguments
874 * (9x version has 3 arguments, NT has 2).
876 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
878 RpcBinding* bind = (RpcBinding*)Binding;
880 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
882 bind->BlockingFn = BlockingFn;
884 return RPC_S_OK;
887 /***********************************************************************
888 * RpcBindingCopy (RPCRT4.@)
890 RPC_STATUS RPC_ENTRY RpcBindingCopy(
891 RPC_BINDING_HANDLE SourceBinding,
892 RPC_BINDING_HANDLE* DestinationBinding)
894 RpcBinding *DestBinding;
895 RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
896 RPC_STATUS status;
898 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
900 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
901 if (status != RPC_S_OK) return status;
903 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
904 DestBinding->BlockingFn = SrcBinding->BlockingFn;
905 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
906 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
907 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
908 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
909 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
910 DestBinding->Assoc = SrcBinding->Assoc;
912 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
913 DestBinding->AuthInfo = SrcBinding->AuthInfo;
914 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
915 DestBinding->QOS = SrcBinding->QOS;
917 *DestinationBinding = DestBinding;
918 return RPC_S_OK;
921 /***********************************************************************
922 * RpcImpersonateClient (RPCRT4.@)
924 * Impersonates the client connected via a binding handle so that security
925 * checks are done in the context of the client.
927 * PARAMS
928 * BindingHandle [I] Handle to the binding to the client.
930 * RETURNS
931 * Success: RPS_S_OK.
932 * Failure: RPC_STATUS value.
934 * NOTES
936 * If BindingHandle is NULL then the function impersonates the client
937 * connected to the binding handle of the current thread.
939 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
941 FIXME("(%p): stub\n", BindingHandle);
942 ImpersonateSelf(SecurityImpersonation);
943 return RPC_S_OK;
946 /***********************************************************************
947 * RpcRevertToSelfEx (RPCRT4.@)
949 * Stops impersonating the client connected to the binding handle so that security
950 * checks are no longer done in the context of the client.
952 * PARAMS
953 * BindingHandle [I] Handle to the binding to the client.
955 * RETURNS
956 * Success: RPS_S_OK.
957 * Failure: RPC_STATUS value.
959 * NOTES
961 * If BindingHandle is NULL then the function stops impersonating the client
962 * connected to the binding handle of the current thread.
964 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
966 FIXME("(%p): stub\n", BindingHandle);
967 return RPC_S_OK;
970 static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
971 CredHandle cred, TimeStamp exp,
972 ULONG cbMaxToken, RpcAuthInfo **ret)
974 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
975 if (!AuthInfo)
976 return ERROR_OUTOFMEMORY;
978 AuthInfo->refs = 1;
979 AuthInfo->AuthnLevel = AuthnLevel;
980 AuthInfo->AuthnSvc = AuthnSvc;
981 AuthInfo->cred = cred;
982 AuthInfo->exp = exp;
983 AuthInfo->cbMaxToken = cbMaxToken;
984 *ret = AuthInfo;
985 return RPC_S_OK;
988 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
990 return InterlockedIncrement(&AuthInfo->refs);
993 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
995 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
997 if (!refs)
999 FreeCredentialsHandle(&AuthInfo->cred);
1000 HeapFree(GetProcessHeap(), 0, AuthInfo);
1003 return refs;
1006 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1008 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1010 if (!qos)
1011 return RPC_S_OUT_OF_RESOURCES;
1013 qos->refs = 1;
1014 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1015 if (!qos->qos) goto error;
1016 qos->qos->Version = qos_src->Version;
1017 qos->qos->Capabilities = qos_src->Capabilities;
1018 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1019 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1020 qos->qos->AdditionalSecurityInfoType = 0;
1022 if (qos_src->Version >= 2)
1024 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1025 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1026 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1028 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1029 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1031 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1032 qos->qos->u.HttpCredentials = http_credentials_dst;
1033 if (!http_credentials_dst) goto error;
1034 http_credentials_dst->TransportCredentials = NULL;
1035 http_credentials_dst->Flags = http_credentials_src->Flags;
1036 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1037 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1038 http_credentials_dst->AuthnSchemes = NULL;
1039 http_credentials_dst->ServerCertificateSubject = NULL;
1040 if (http_credentials_src->TransportCredentials)
1042 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1043 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1044 if (!cred_dst) goto error;
1045 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1046 if (unicode)
1048 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1049 cred_dst->UserLength = cred_src->UserLength;
1050 cred_dst->PasswordLength = cred_src->PasswordLength;
1051 cred_dst->DomainLength = cred_src->DomainLength;
1052 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1053 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1054 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1056 else
1058 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1059 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1060 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1061 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1062 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1063 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1064 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1065 if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error;
1066 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1067 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1068 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1071 if (http_credentials_src->NumberOfAuthnSchemes)
1073 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1074 if (!http_credentials_dst->AuthnSchemes) goto error;
1075 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1077 if (http_credentials_src->ServerCertificateSubject)
1079 if (unicode)
1080 http_credentials_dst->ServerCertificateSubject =
1081 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1082 strlenW(http_credentials_src->ServerCertificateSubject));
1083 else
1084 http_credentials_dst->ServerCertificateSubject =
1085 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1086 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1090 *qos_dst = qos;
1091 return RPC_S_OK;
1093 error:
1094 if (qos->qos)
1096 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1097 qos->qos->u.HttpCredentials)
1099 if (qos->qos->u.HttpCredentials->TransportCredentials)
1101 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1102 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1103 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1104 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1106 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1107 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1108 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1110 HeapFree(GetProcessHeap(), 0, qos->qos);
1112 HeapFree(GetProcessHeap(), 0, qos);
1113 return RPC_S_OUT_OF_RESOURCES;
1116 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1118 return InterlockedIncrement(&qos->refs);
1121 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1123 ULONG refs = InterlockedDecrement(&qos->refs);
1125 if (!refs)
1127 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1129 if (qos->qos->u.HttpCredentials->TransportCredentials)
1131 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1132 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1133 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1134 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1136 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1137 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1138 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1140 HeapFree(GetProcessHeap(), 0, qos->qos);
1141 HeapFree(GetProcessHeap(), 0, qos);
1143 return refs;
1146 /***********************************************************************
1147 * RpcRevertToSelf (RPCRT4.@)
1149 RPC_STATUS WINAPI RpcRevertToSelf(void)
1151 FIXME("stub\n");
1152 RevertToSelf();
1153 return RPC_S_OK;
1156 /***********************************************************************
1157 * RpcMgmtSetComTimeout (RPCRT4.@)
1159 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1161 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1162 return RPC_S_OK;
1165 /***********************************************************************
1166 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1168 RPCRTAPI RPC_STATUS RPC_ENTRY
1169 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1170 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1171 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1173 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1174 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1175 return RPC_S_INVALID_BINDING;
1178 /***********************************************************************
1179 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1181 RPCRTAPI RPC_STATUS RPC_ENTRY
1182 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1183 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1184 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1186 FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1187 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1188 return RPC_S_INVALID_BINDING;
1191 /***********************************************************************
1192 * RpcBindingInqAuthInfoA (RPCRT4.@)
1194 RPCRTAPI RPC_STATUS RPC_ENTRY
1195 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1196 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1198 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1199 AuthnSvc, AuthIdentity, AuthzSvc);
1200 return RPC_S_INVALID_BINDING;
1203 /***********************************************************************
1204 * RpcBindingInqAuthInfoW (RPCRT4.@)
1206 RPCRTAPI RPC_STATUS RPC_ENTRY
1207 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1208 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1210 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1211 AuthnSvc, AuthIdentity, AuthzSvc);
1212 return RPC_S_INVALID_BINDING;
1215 /***********************************************************************
1216 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1218 RPCRTAPI RPC_STATUS RPC_ENTRY
1219 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1220 ULONG AuthnLevel, ULONG AuthnSvc,
1221 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1222 RPC_SECURITY_QOS *SecurityQos )
1224 RpcBinding* bind = (RpcBinding*)Binding;
1225 SECURITY_STATUS r;
1226 CredHandle cred;
1227 TimeStamp exp;
1228 ULONG package_count;
1229 ULONG i;
1230 PSecPkgInfoA packages;
1231 ULONG cbMaxToken;
1233 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1234 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1236 if (SecurityQos)
1238 RPC_STATUS status;
1240 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1241 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1242 if (SecurityQos->Version >= 2)
1244 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1245 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1246 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1247 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1248 SecurityQos2->u.HttpCredentials->TransportCredentials,
1249 SecurityQos2->u.HttpCredentials->Flags,
1250 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1251 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1252 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1253 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1255 TRACE("}\n");
1256 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1257 if (status != RPC_S_OK)
1258 return status;
1260 else
1262 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1263 bind->QOS = NULL;
1266 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1267 AuthnSvc = RPC_C_AUTHN_WINNT;
1269 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1270 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1271 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1273 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1275 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1276 bind->AuthInfo = NULL;
1277 return RPC_S_OK;
1280 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1282 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1283 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1286 if (AuthzSvr)
1288 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1289 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1292 r = EnumerateSecurityPackagesA(&package_count, &packages);
1293 if (r != SEC_E_OK)
1295 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1296 return RPC_S_SEC_PKG_ERROR;
1299 for (i = 0; i < package_count; i++)
1300 if (packages[i].wRPCID == AuthnSvc)
1301 break;
1303 if (i == package_count)
1305 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1306 FreeContextBuffer(packages);
1307 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1310 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1311 r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1312 AuthIdentity, NULL, NULL, &cred, &exp);
1313 cbMaxToken = packages[i].cbMaxToken;
1314 FreeContextBuffer(packages);
1315 if (r == ERROR_SUCCESS)
1317 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1318 bind->AuthInfo = NULL;
1319 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1320 &bind->AuthInfo);
1321 if (r != RPC_S_OK)
1322 FreeCredentialsHandle(&cred);
1323 return RPC_S_OK;
1325 else
1327 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1328 return RPC_S_SEC_PKG_ERROR;
1332 /***********************************************************************
1333 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1335 RPCRTAPI RPC_STATUS RPC_ENTRY
1336 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1337 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1338 RPC_SECURITY_QOS *SecurityQos )
1340 RpcBinding* bind = (RpcBinding*)Binding;
1341 SECURITY_STATUS r;
1342 CredHandle cred;
1343 TimeStamp exp;
1344 ULONG package_count;
1345 ULONG i;
1346 PSecPkgInfoW packages;
1347 ULONG cbMaxToken;
1349 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1350 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1352 if (SecurityQos)
1354 RPC_STATUS status;
1356 TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1357 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1358 if (SecurityQos->Version >= 2)
1360 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1361 TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1362 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1363 TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1364 SecurityQos2->u.HttpCredentials->TransportCredentials,
1365 SecurityQos2->u.HttpCredentials->Flags,
1366 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1367 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1368 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1369 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1371 TRACE("}\n");
1372 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1373 if (status != RPC_S_OK)
1374 return status;
1376 else
1378 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1379 bind->QOS = NULL;
1382 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1383 AuthnSvc = RPC_C_AUTHN_WINNT;
1385 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1386 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1387 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1389 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1391 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1392 bind->AuthInfo = NULL;
1393 return RPC_S_OK;
1396 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1398 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1399 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1402 if (AuthzSvr)
1404 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1405 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1408 r = EnumerateSecurityPackagesW(&package_count, &packages);
1409 if (r != SEC_E_OK)
1411 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1412 return RPC_S_SEC_PKG_ERROR;
1415 for (i = 0; i < package_count; i++)
1416 if (packages[i].wRPCID == AuthnSvc)
1417 break;
1419 if (i == package_count)
1421 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1422 FreeContextBuffer(packages);
1423 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1426 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1427 r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1428 AuthIdentity, NULL, NULL, &cred, &exp);
1429 cbMaxToken = packages[i].cbMaxToken;
1430 FreeContextBuffer(packages);
1431 if (r == ERROR_SUCCESS)
1433 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1434 bind->AuthInfo = NULL;
1435 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1436 &bind->AuthInfo);
1437 if (r != RPC_S_OK)
1438 FreeCredentialsHandle(&cred);
1439 return RPC_S_OK;
1441 else
1443 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1444 return RPC_S_SEC_PKG_ERROR;
1448 /***********************************************************************
1449 * RpcBindingSetAuthInfoA (RPCRT4.@)
1451 RPCRTAPI RPC_STATUS RPC_ENTRY
1452 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1453 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1455 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1456 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1457 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1460 /***********************************************************************
1461 * RpcBindingSetAuthInfoW (RPCRT4.@)
1463 RPCRTAPI RPC_STATUS RPC_ENTRY
1464 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1465 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1467 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1468 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1469 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1472 /***********************************************************************
1473 * RpcBindingSetOption (RPCRT4.@)
1475 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1477 FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue);
1478 return RPC_S_OK;