rpcrt4: Support all available security packages in RpcBindingSetAuthInfoExA, instead...
[wine/multimedia.git] / dlls / rpcrt4 / rpc_binding.c
blob73bff581e680c9c82f057bac836c03e2bf596331
1 /*
2 * RPC binding API
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * TODO:
23 * - a whole lot
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "winerror.h"
35 #include "winreg.h"
36 #include "winternl.h"
37 #include "wine/unicode.h"
39 #include "rpc.h"
40 #include "rpcndr.h"
42 #include "wine/debug.h"
44 #include "rpc_binding.h"
45 #include "rpc_message.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
49 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
51 DWORD len;
52 LPSTR s;
53 if (!src) return NULL;
54 if (slen == -1) slen = strlen(src);
55 len = slen;
56 s = HeapAlloc(GetProcessHeap(), 0, len+1);
57 memcpy(s, src, len);
58 s[len] = 0;
59 return s;
62 LPSTR RPCRT4_strdupWtoA(LPWSTR src)
64 DWORD len;
65 LPSTR s;
66 if (!src) return NULL;
67 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
68 s = HeapAlloc(GetProcessHeap(), 0, len);
69 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
70 return s;
73 LPWSTR RPCRT4_strdupAtoW(LPSTR src)
75 DWORD len;
76 LPWSTR s;
77 if (!src) return NULL;
78 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
79 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
80 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
81 return s;
84 LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen)
86 DWORD len;
87 LPWSTR s;
88 if (!src) return NULL;
89 if (slen == -1) slen = strlenW(src);
90 len = slen;
91 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
92 memcpy(s, src, len*sizeof(WCHAR));
93 s[len] = 0;
94 return s;
97 void RPCRT4_strfree(LPSTR src)
99 HeapFree(GetProcessHeap(), 0, src);
102 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
104 RpcBinding* NewBinding;
106 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
107 NewBinding->refs = 1;
108 NewBinding->server = server;
110 *Binding = NewBinding;
112 return RPC_S_OK;
115 RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
117 RpcBinding* NewBinding;
119 RPCRT4_AllocBinding(&NewBinding, server);
120 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
122 TRACE("binding: %p\n", NewBinding);
123 *Binding = NewBinding;
125 return RPC_S_OK;
128 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
130 RpcBinding* NewBinding;
132 RPCRT4_AllocBinding(&NewBinding, server);
133 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
135 TRACE("binding: %p\n", NewBinding);
136 *Binding = NewBinding;
138 return RPC_S_OK;
141 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions)
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 if (!Binding->Endpoint) ERR("out of memory?\n");
156 return RPC_S_OK;
159 RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
161 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding,
162 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
164 RPCRT4_strfree(Binding->NetworkAddr);
165 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
166 RPCRT4_strfree(Binding->Endpoint);
167 if (Endpoint) {
168 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
169 } else {
170 Binding->Endpoint = RPCRT4_strdupA("");
172 if (!Binding->Endpoint) ERR("out of memory?\n");
174 return RPC_S_OK;
177 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
179 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
181 RPCRT4_strfree(Binding->Endpoint);
182 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
184 return RPC_S_OK;
187 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
189 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
190 if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
191 else UuidCreateNil(&Binding->ObjectUuid);
192 return RPC_S_OK;
195 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
197 RpcBinding* NewBinding;
198 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
200 RPCRT4_AllocBinding(&NewBinding, Connection->server);
201 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
202 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
203 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
204 NewBinding->FromConn = Connection;
206 TRACE("binding: %p\n", NewBinding);
207 *Binding = NewBinding;
209 return RPC_S_OK;
212 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
214 InterlockedIncrement(&OldBinding->refs);
215 *Binding = OldBinding;
216 return RPC_S_OK;
219 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
221 if (InterlockedDecrement(&Binding->refs))
222 return RPC_S_OK;
224 TRACE("binding: %p\n", Binding);
225 /* FIXME: release connections */
226 RPCRT4_strfree(Binding->Endpoint);
227 RPCRT4_strfree(Binding->NetworkAddr);
228 RPCRT4_strfree(Binding->Protseq);
229 HeapFree(GetProcessHeap(), 0, Binding);
230 return RPC_S_OK;
233 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
234 PRPC_SYNTAX_IDENTIFIER TransferSyntax,
235 PRPC_SYNTAX_IDENTIFIER InterfaceId)
237 RpcConnection* NewConnection;
238 RPC_STATUS status;
240 TRACE("(Binding == ^%p)\n", Binding);
242 /* if we try to bind a new interface and the connection is already opened,
243 * close the current connection and create a new with the new binding. */
244 if (!Binding->server && Binding->FromConn &&
245 (Binding->AuthInfo == Binding->FromConn->AuthInfo) &&
246 memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
247 sizeof(RPC_SYNTAX_IDENTIFIER))) {
249 TRACE("releasing pre-existing connection\n");
250 RPCRT4_DestroyConnection(Binding->FromConn);
251 Binding->FromConn = NULL;
252 } else {
253 /* we already have a connection with acceptable binding, so use it */
254 if (Binding->FromConn) {
255 *Connection = Binding->FromConn;
256 return RPC_S_OK;
260 /* create a new connection */
261 RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq,
262 Binding->NetworkAddr, Binding->Endpoint, NULL,
263 Binding->AuthInfo, Binding);
264 *Connection = NewConnection;
265 status = RPCRT4_OpenConnection(NewConnection);
266 if (status != RPC_S_OK) {
267 return status;
270 /* we need to send a binding packet if we are client. */
271 if (!(*Connection)->server) {
272 RpcPktHdr *hdr;
273 RpcPktHdr *response_hdr;
274 RPC_MESSAGE msg;
276 TRACE("sending bind request to server\n");
278 hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
279 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
280 InterfaceId, TransferSyntax);
282 status = RPCRT4_Send(*Connection, hdr, NULL, 0);
283 RPCRT4_FreeHeader(hdr);
284 if (status != RPC_S_OK) {
285 RPCRT4_DestroyConnection(*Connection);
286 return status;
289 status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
290 if (status != RPC_S_OK) {
291 ERR("receive failed\n");
292 RPCRT4_DestroyConnection(*Connection);
293 return status;
296 if (response_hdr->common.ptype != PKT_BIND_ACK ||
297 response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
298 ERR("failed to bind\n");
299 RPCRT4_FreeHeader(response_hdr);
300 RPCRT4_DestroyConnection(*Connection);
301 return RPC_S_PROTOCOL_ERROR;
304 /* FIXME: do more checks? */
306 (*Connection)->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
307 (*Connection)->ActiveInterface = *InterfaceId;
308 RPCRT4_FreeHeader(response_hdr);
310 Binding->FromConn = *Connection;
312 return RPC_S_OK;
315 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
317 TRACE("(Binding == ^%p)\n", Binding);
318 if (!Connection) return RPC_S_OK;
319 if (Binding->FromConn == Connection) return RPC_S_OK;
320 return RPCRT4_DestroyConnection(Connection);
323 /* utility functions for string composing and parsing */
324 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
326 unsigned len = strlen(src);
327 memcpy(data, src, len*sizeof(CHAR));
328 return len;
331 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
333 unsigned len = strlenW(src);
334 memcpy(data, src, len*sizeof(WCHAR));
335 return len;
338 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
340 DWORD len = strlen(dst), slen = strlen(src);
341 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
342 if (!ndst)
344 HeapFree(GetProcessHeap(), 0, dst);
345 return NULL;
347 ndst[len] = ',';
348 memcpy(ndst+len+1, src, slen+1);
349 return ndst;
352 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
354 DWORD len = strlenW(dst), slen = strlenW(src);
355 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
356 if (!ndst)
358 HeapFree(GetProcessHeap(), 0, dst);
359 return NULL;
361 ndst[len] = ',';
362 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
363 return ndst;
367 /***********************************************************************
368 * RpcStringBindingComposeA (RPCRT4.@)
370 RPC_STATUS WINAPI RpcStringBindingComposeA(unsigned char *ObjUuid, unsigned char *Protseq,
371 unsigned char *NetworkAddr, unsigned char *Endpoint,
372 unsigned char *Options, unsigned char** StringBinding )
374 DWORD len = 1;
375 LPSTR data;
377 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
378 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
379 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
380 debugstr_a( (char*)Options ), StringBinding );
382 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
383 if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
384 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
385 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
386 if (Options && *Options) len += strlen((char*)Options) + 2;
388 data = HeapAlloc(GetProcessHeap(), 0, len);
389 *StringBinding = (unsigned char*)data;
391 if (ObjUuid && *ObjUuid) {
392 data += RPCRT4_strcopyA(data, (char*)ObjUuid);
393 *data++ = '@';
395 if (Protseq && *Protseq) {
396 data += RPCRT4_strcopyA(data, (char*)Protseq);
397 *data++ = ':';
399 if (NetworkAddr && *NetworkAddr)
400 data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
402 if ((Endpoint && *Endpoint) ||
403 (Options && *Options)) {
404 *data++ = '[';
405 if (Endpoint && *Endpoint) {
406 data += RPCRT4_strcopyA(data, (char*)Endpoint);
407 if (Options && *Options) *data++ = ',';
409 if (Options && *Options) {
410 data += RPCRT4_strcopyA(data, (char*)Options);
412 *data++ = ']';
414 *data = 0;
416 return RPC_S_OK;
419 /***********************************************************************
420 * RpcStringBindingComposeW (RPCRT4.@)
422 RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,
423 LPWSTR NetworkAddr, LPWSTR Endpoint,
424 LPWSTR Options, LPWSTR* StringBinding )
426 DWORD len = 1;
427 LPWSTR data;
429 TRACE("(%s,%s,%s,%s,%s,%p)\n",
430 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
431 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
432 debugstr_w( Options ), StringBinding);
434 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
435 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
436 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
437 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
438 if (Options && *Options) len += strlenW(Options) + 2;
440 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
441 *StringBinding = data;
443 if (ObjUuid && *ObjUuid) {
444 data += RPCRT4_strcopyW(data, ObjUuid);
445 *data++ = '@';
447 if (Protseq && *Protseq) {
448 data += RPCRT4_strcopyW(data, Protseq);
449 *data++ = ':';
451 if (NetworkAddr && *NetworkAddr) {
452 data += RPCRT4_strcopyW(data, NetworkAddr);
454 if ((Endpoint && *Endpoint) ||
455 (Options && *Options)) {
456 *data++ = '[';
457 if (Endpoint && *Endpoint) {
458 data += RPCRT4_strcopyW(data, Endpoint);
459 if (Options && *Options) *data++ = ',';
461 if (Options && *Options) {
462 data += RPCRT4_strcopyW(data, Options);
464 *data++ = ']';
466 *data = 0;
468 return RPC_S_OK;
472 /***********************************************************************
473 * RpcStringBindingParseA (RPCRT4.@)
475 RPC_STATUS WINAPI RpcStringBindingParseA( unsigned char *StringBinding, unsigned char **ObjUuid,
476 unsigned char **Protseq, unsigned char **NetworkAddr,
477 unsigned char **Endpoint, unsigned char **Options)
479 CHAR *data, *next;
480 static const char ep_opt[] = "endpoint=";
482 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
483 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
485 if (ObjUuid) *ObjUuid = NULL;
486 if (Protseq) *Protseq = NULL;
487 if (NetworkAddr) *NetworkAddr = NULL;
488 if (Endpoint) *Endpoint = NULL;
489 if (Options) *Options = NULL;
491 data = (char*) StringBinding;
493 next = strchr(data, '@');
494 if (next) {
495 if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
496 data = next+1;
499 next = strchr(data, ':');
500 if (next) {
501 if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
502 data = next+1;
505 next = strchr(data, '[');
506 if (next) {
507 CHAR *close, *opt;
509 if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
510 data = next+1;
511 close = strchr(data, ']');
512 if (!close) goto fail;
514 /* tokenize options */
515 while (data < close) {
516 next = strchr(data, ',');
517 if (!next || next > close) next = close;
518 /* FIXME: this is kind of inefficient */
519 opt = RPCRT4_strndupA(data, next - data);
520 data = next+1;
522 /* parse option */
523 next = strchr(opt, '=');
524 if (!next) {
525 /* not an option, must be an endpoint */
526 if (*Endpoint) goto fail;
527 *Endpoint = (unsigned char*) opt;
528 } else {
529 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
530 /* endpoint option */
531 if (*Endpoint) goto fail;
532 *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
533 HeapFree(GetProcessHeap(), 0, opt);
534 } else {
535 /* network option */
536 if (*Options) {
537 /* FIXME: this is kind of inefficient */
538 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
539 HeapFree(GetProcessHeap(), 0, opt);
540 } else
541 *Options = (unsigned char*) opt;
546 data = close+1;
547 if (*data) goto fail;
549 else if (NetworkAddr)
550 *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
552 return RPC_S_OK;
554 fail:
555 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
556 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
557 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
558 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
559 if (Options) RpcStringFreeA((unsigned char**)Options);
560 return RPC_S_INVALID_STRING_BINDING;
563 /***********************************************************************
564 * RpcStringBindingParseW (RPCRT4.@)
566 RPC_STATUS WINAPI RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR *ObjUuid,
567 LPWSTR *Protseq, LPWSTR *NetworkAddr,
568 LPWSTR *Endpoint, LPWSTR *Options)
570 WCHAR *data, *next;
571 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
573 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
574 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
576 if (ObjUuid) *ObjUuid = NULL;
577 if (Protseq) *Protseq = NULL;
578 if (NetworkAddr) *NetworkAddr = NULL;
579 if (Endpoint) *Endpoint = NULL;
580 if (Options) *Options = NULL;
582 data = StringBinding;
584 next = strchrW(data, '@');
585 if (next) {
586 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
587 data = next+1;
590 next = strchrW(data, ':');
591 if (next) {
592 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
593 data = next+1;
596 next = strchrW(data, '[');
597 if (next) {
598 WCHAR *close, *opt;
600 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
601 data = next+1;
602 close = strchrW(data, ']');
603 if (!close) goto fail;
605 /* tokenize options */
606 while (data < close) {
607 next = strchrW(data, ',');
608 if (!next || next > close) next = close;
609 /* FIXME: this is kind of inefficient */
610 opt = RPCRT4_strndupW(data, next - data);
611 data = next+1;
613 /* parse option */
614 next = strchrW(opt, '=');
615 if (!next) {
616 /* not an option, must be an endpoint */
617 if (*Endpoint) goto fail;
618 *Endpoint = opt;
619 } else {
620 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
621 /* endpoint option */
622 if (*Endpoint) goto fail;
623 *Endpoint = RPCRT4_strdupW(next+1);
624 HeapFree(GetProcessHeap(), 0, opt);
625 } else {
626 /* network option */
627 if (*Options) {
628 /* FIXME: this is kind of inefficient */
629 *Options = RPCRT4_strconcatW(*Options, opt);
630 HeapFree(GetProcessHeap(), 0, opt);
631 } else
632 *Options = opt;
637 data = close+1;
638 if (*data) goto fail;
639 } else if (NetworkAddr)
640 *NetworkAddr = RPCRT4_strdupW(data);
642 return RPC_S_OK;
644 fail:
645 if (ObjUuid) RpcStringFreeW(ObjUuid);
646 if (Protseq) RpcStringFreeW(Protseq);
647 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
648 if (Endpoint) RpcStringFreeW(Endpoint);
649 if (Options) RpcStringFreeW(Options);
650 return RPC_S_INVALID_STRING_BINDING;
653 /***********************************************************************
654 * RpcBindingFree (RPCRT4.@)
656 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
658 RPC_STATUS status;
659 TRACE("(%p) = %p\n", Binding, *Binding);
660 status = RPCRT4_DestroyBinding(*Binding);
661 if (status == RPC_S_OK) *Binding = 0;
662 return status;
665 /***********************************************************************
666 * RpcBindingVectorFree (RPCRT4.@)
668 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
670 RPC_STATUS status;
671 unsigned long c;
673 TRACE("(%p)\n", BindingVector);
674 for (c=0; c<(*BindingVector)->Count; c++) {
675 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
677 HeapFree(GetProcessHeap(), 0, *BindingVector);
678 *BindingVector = NULL;
679 return RPC_S_OK;
682 /***********************************************************************
683 * RpcBindingInqObject (RPCRT4.@)
685 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
687 RpcBinding* bind = (RpcBinding*)Binding;
689 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
690 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
691 return RPC_S_OK;
694 /***********************************************************************
695 * RpcBindingSetObject (RPCRT4.@)
697 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
699 RpcBinding* bind = (RpcBinding*)Binding;
701 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
702 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
703 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
706 /***********************************************************************
707 * RpcBindingFromStringBindingA (RPCRT4.@)
709 RPC_STATUS WINAPI RpcBindingFromStringBindingA( unsigned char *StringBinding, RPC_BINDING_HANDLE* Binding )
711 RPC_STATUS ret;
712 RpcBinding* bind = NULL;
713 unsigned char *ObjectUuid, *Protseq, *NetworkAddr, *Endpoint, *Options;
714 UUID Uuid;
716 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
718 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
719 &NetworkAddr, &Endpoint, &Options);
720 if (ret != RPC_S_OK) return ret;
722 ret = UuidFromStringA(ObjectUuid, &Uuid);
724 if (ret == RPC_S_OK)
725 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
726 if (ret == RPC_S_OK)
727 ret = RPCRT4_SetBindingObject(bind, &Uuid);
728 if (ret == RPC_S_OK)
729 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
731 RpcStringFreeA((unsigned char**)&Options);
732 RpcStringFreeA((unsigned char**)&Endpoint);
733 RpcStringFreeA((unsigned char**)&NetworkAddr);
734 RpcStringFreeA((unsigned char**)&Protseq);
735 RpcStringFreeA((unsigned char**)&ObjectUuid);
737 if (ret == RPC_S_OK)
738 *Binding = (RPC_BINDING_HANDLE)bind;
739 else
740 RPCRT4_DestroyBinding(bind);
742 return ret;
745 /***********************************************************************
746 * RpcBindingFromStringBindingW (RPCRT4.@)
748 RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
750 RPC_STATUS ret;
751 RpcBinding* bind = NULL;
752 LPWSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
753 UUID Uuid;
755 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
757 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
758 &NetworkAddr, &Endpoint, &Options);
759 if (ret != RPC_S_OK) return ret;
761 ret = UuidFromStringW(ObjectUuid, &Uuid);
763 if (ret == RPC_S_OK)
764 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
765 if (ret == RPC_S_OK)
766 ret = RPCRT4_SetBindingObject(bind, &Uuid);
767 if (ret == RPC_S_OK)
768 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
770 RpcStringFreeW(&Options);
771 RpcStringFreeW(&Endpoint);
772 RpcStringFreeW(&NetworkAddr);
773 RpcStringFreeW(&Protseq);
774 RpcStringFreeW(&ObjectUuid);
776 if (ret == RPC_S_OK)
777 *Binding = (RPC_BINDING_HANDLE)bind;
778 else
779 RPCRT4_DestroyBinding(bind);
781 return ret;
784 /***********************************************************************
785 * RpcBindingToStringBindingA (RPCRT4.@)
787 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, unsigned char** StringBinding )
789 RPC_STATUS ret;
790 RpcBinding* bind = (RpcBinding*)Binding;
791 LPSTR ObjectUuid;
793 TRACE("(%p,%p)\n", Binding, StringBinding);
795 ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
796 if (ret != RPC_S_OK) return ret;
798 ret = RpcStringBindingComposeA((unsigned char*) ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
799 (unsigned char*) bind->Endpoint, NULL, StringBinding);
801 RpcStringFreeA((unsigned char**)&ObjectUuid);
803 return ret;
806 /***********************************************************************
807 * RpcBindingToStringBindingW (RPCRT4.@)
809 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, unsigned short** StringBinding )
811 RPC_STATUS ret;
812 unsigned char *str = NULL;
813 TRACE("(%p,%p)\n", Binding, StringBinding);
814 ret = RpcBindingToStringBindingA(Binding, &str);
815 *StringBinding = RPCRT4_strdupAtoW((char*)str);
816 RpcStringFreeA((unsigned char**)&str);
817 return ret;
820 /***********************************************************************
821 * I_RpcBindingSetAsync (RPCRT4.@)
822 * NOTES
823 * Exists in win9x and winNT, but with different number of arguments
824 * (9x version has 3 arguments, NT has 2).
826 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
828 RpcBinding* bind = (RpcBinding*)Binding;
830 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
832 bind->BlockingFn = BlockingFn;
834 return RPC_S_OK;
837 /***********************************************************************
838 * RpcNetworkIsProtseqValidA (RPCRT4.@)
840 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(unsigned char *protseq) {
841 UNICODE_STRING protseqW;
843 if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */
845 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) {
846 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
847 RtlFreeUnicodeString(&protseqW);
848 return ret;
849 } else return RPC_S_OUT_OF_MEMORY;
852 /***********************************************************************
853 * RpcNetworkIsProtseqValidW (RPCRT4.@)
855 * Checks if the given protocol sequence is known by the RPC system.
856 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
858 * We currently support:
859 * ncalrpc local-only rpc over LPC (LPC is not really used)
860 * ncacn_np rpc over named pipes
862 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(LPWSTR protseq) {
863 static const WCHAR protseqsW[][15] = {
864 {'n','c','a','l','r','p','c',0},
865 {'n','c','a','c','n','_','n','p',0}
867 static const int count = sizeof(protseqsW) / sizeof(protseqsW[0]);
868 int i;
870 if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */
872 for (i = 0; i < count; i++) {
873 if (!strcmpW(protseq, protseqsW[i])) return RPC_S_OK;
876 FIXME("Unknown protseq %s - we probably need to implement it one day\n", debugstr_w(protseq));
877 return RPC_S_PROTSEQ_NOT_SUPPORTED;
880 /***********************************************************************
881 * RpcImpersonateClient (RPCRT4.@)
883 * Impersonates the client connected via a binding handle so that security
884 * checks are done in the context of the client.
886 * PARAMS
887 * BindingHandle [I] Handle to the binding to the client.
889 * RETURNS
890 * Success: RPS_S_OK.
891 * Failure: RPC_STATUS value.
893 * NOTES
895 * If BindingHandle is NULL then the function impersonates the client
896 * connected to the binding handle of the current thread.
898 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
900 FIXME("(%p): stub\n", BindingHandle);
901 return RPC_S_OK;
904 /***********************************************************************
905 * RpcRevertToSelfEx (RPCRT4.@)
907 * Stops impersonating the client connected to the binding handle so that security
908 * checks are no longer done in the context of the client.
910 * PARAMS
911 * BindingHandle [I] Handle to the binding to the client.
913 * RETURNS
914 * Success: RPS_S_OK.
915 * Failure: RPC_STATUS value.
917 * NOTES
919 * If BindingHandle is NULL then the function stops impersonating the client
920 * connected to the binding handle of the current thread.
922 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
924 FIXME("(%p): stub\n", BindingHandle);
925 return RPC_S_OK;
928 static RPC_STATUS RpcAuthInfo_Create(unsigned long AuthnLevel, unsigned long AuthnSvc, CredHandle cred, TimeStamp exp, RpcAuthInfo **ret)
930 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
931 if (!AuthInfo)
932 return ERROR_OUTOFMEMORY;
934 AuthInfo->AuthnLevel = AuthnLevel;
935 AuthInfo->AuthnSvc = AuthnSvc;
936 AuthInfo->cred = cred;
937 AuthInfo->exp = exp;
938 *ret = AuthInfo;
939 return RPC_S_OK;
942 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
944 return InterlockedIncrement(&AuthInfo->refs);
947 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
949 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
951 if (!refs)
953 FreeCredentialsHandle(&AuthInfo->cred);
954 HeapFree(GetProcessHeap(), 0, AuthInfo);
957 return refs;
960 /***********************************************************************
961 * RpcBindingInqAuthInfoExA (RPCRT4.@)
963 RPCRTAPI RPC_STATUS RPC_ENTRY
964 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, unsigned char ** ServerPrincName, unsigned long *AuthnLevel,
965 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
966 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
968 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
969 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
970 return RPC_S_INVALID_BINDING;
973 /***********************************************************************
974 * RpcBindingInqAuthInfoExW (RPCRT4.@)
976 RPCRTAPI RPC_STATUS RPC_ENTRY
977 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, unsigned short ** ServerPrincName, unsigned long *AuthnLevel,
978 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
979 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
981 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
982 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
983 return RPC_S_INVALID_BINDING;
986 /***********************************************************************
987 * RpcBindingInqAuthInfoA (RPCRT4.@)
989 RPCRTAPI RPC_STATUS RPC_ENTRY
990 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, unsigned char ** ServerPrincName, unsigned long *AuthnLevel,
991 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
993 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
994 AuthnSvc, AuthIdentity, AuthzSvc);
995 return RPC_S_INVALID_BINDING;
998 /***********************************************************************
999 * RpcBindingInqAuthInfoW (RPCRT4.@)
1001 RPCRTAPI RPC_STATUS RPC_ENTRY
1002 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, unsigned short ** ServerPrincName, unsigned long *AuthnLevel,
1003 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1005 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1006 AuthnSvc, AuthIdentity, AuthzSvc);
1007 return RPC_S_INVALID_BINDING;
1010 /***********************************************************************
1011 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1013 RPCRTAPI RPC_STATUS RPC_ENTRY
1014 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, unsigned char *ServerPrincName,
1015 unsigned long AuthnLevel, unsigned long AuthnSvc,
1016 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1017 RPC_SECURITY_QOS *SecurityQos )
1019 RpcBinding* bind = (RpcBinding*)Binding;
1020 SECURITY_STATUS r;
1021 CredHandle cred;
1022 TimeStamp exp;
1023 ULONG package_count;
1024 ULONG i;
1025 PSecPkgInfoA packages;
1027 TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1028 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1030 if (!AuthIdentity)
1031 return RPC_S_INVALID_AUTH_IDENTITY;
1033 if (AuthnLevel != RPC_C_AUTHN_LEVEL_CONNECT)
1035 FIXME("unsupported AuthnLevel %lu\n", AuthnLevel);
1036 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1039 if (AuthzSvr)
1041 FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1042 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1045 if (SecurityQos)
1046 FIXME("SecurityQos ignored\n");
1048 r = EnumerateSecurityPackagesA(&package_count, &packages);
1049 if (r != SEC_E_OK)
1051 ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r);
1052 return RPC_S_SEC_PKG_ERROR;
1055 for (i = 0; i < package_count; i++)
1056 if (packages[i].wRPCID == AuthnSvc)
1057 break;
1059 if (i == package_count)
1061 FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1062 FreeContextBuffer(packages);
1063 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1066 TRACE("found package %s for service %ld\n", packages[i].Name, AuthnSvc);
1067 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1068 AuthIdentity, NULL, NULL, &cred, &exp);
1069 FreeContextBuffer(packages);
1070 if (r == ERROR_SUCCESS)
1072 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1073 bind->AuthInfo = NULL;
1074 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1075 if (r != RPC_S_OK)
1076 FreeCredentialsHandle(&cred);
1077 return RPC_S_OK;
1079 else
1081 ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r);
1082 return RPC_S_SEC_PKG_ERROR;
1086 /***********************************************************************
1087 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1089 RPCRTAPI RPC_STATUS RPC_ENTRY
1090 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, unsigned short *ServerPrincName, unsigned long AuthnLevel,
1091 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1092 RPC_SECURITY_QOS *SecurityQos )
1094 FIXME("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1095 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1096 return RPC_S_OK;
1099 /***********************************************************************
1100 * RpcBindingSetAuthInfoA (RPCRT4.@)
1102 RPCRTAPI RPC_STATUS RPC_ENTRY
1103 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, unsigned char *ServerPrincName, unsigned long AuthnLevel,
1104 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1106 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1107 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1108 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1111 /***********************************************************************
1112 * RpcBindingSetAuthInfoW (RPCRT4.@)
1114 RPCRTAPI RPC_STATUS RPC_ENTRY
1115 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, unsigned short *ServerPrincName, unsigned long AuthnLevel,
1116 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1118 TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1119 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1120 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1123 /***********************************************************************
1124 * RpcBindingSetOption (RPCRT4.@)
1126 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1128 FIXME("(%p, %ld, %ld): stub\n", BindingHandle, Option, OptionValue);
1129 return RPC_S_OK;