oleaut32: Correctly handle the case when the number of bytes in a BSTR is odd.
[wine/hacks.git] / dlls / rpcrt4 / rpc_binding.c
blob58e5eefbbfc7345dcea1249155d369812d248e3d
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 memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
246 sizeof(RPC_SYNTAX_IDENTIFIER))) {
248 TRACE("releasing pre-existing connection\n");
249 RPCRT4_DestroyConnection(Binding->FromConn);
250 Binding->FromConn = NULL;
251 } else {
252 /* we already have a connection with acceptable binding, so use it */
253 if (Binding->FromConn) {
254 *Connection = Binding->FromConn;
255 return RPC_S_OK;
259 /* create a new connection */
260 RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL, Binding);
261 *Connection = NewConnection;
262 status = RPCRT4_OpenConnection(NewConnection);
263 if (status != RPC_S_OK) {
264 return status;
267 /* we need to send a binding packet if we are client. */
268 if (!(*Connection)->server) {
269 RpcPktHdr *hdr;
270 LONG count;
271 BYTE *response;
272 RpcPktHdr *response_hdr;
274 TRACE("sending bind request to server\n");
276 hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
277 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
278 InterfaceId, TransferSyntax);
280 status = RPCRT4_Send(*Connection, hdr, NULL, 0);
281 RPCRT4_FreeHeader(hdr);
282 if (status != RPC_S_OK) {
283 RPCRT4_DestroyConnection(*Connection);
284 return status;
287 response = HeapAlloc(GetProcessHeap(), 0, RPC_MAX_PACKET_SIZE);
288 if (response == NULL) {
289 WARN("Can't allocate memory for binding response\n");
290 RPCRT4_DestroyConnection(*Connection);
291 return E_OUTOFMEMORY;
294 count = rpcrt4_conn_read(NewConnection, response, RPC_MAX_PACKET_SIZE);
295 if (count < sizeof(response_hdr->common)) {
296 WARN("received invalid header\n");
297 HeapFree(GetProcessHeap(), 0, response);
298 RPCRT4_DestroyConnection(*Connection);
299 return RPC_S_PROTOCOL_ERROR;
302 response_hdr = (RpcPktHdr*)response;
304 if (response_hdr->common.rpc_ver != RPC_VER_MAJOR ||
305 response_hdr->common.rpc_ver_minor != RPC_VER_MINOR ||
306 response_hdr->common.ptype != PKT_BIND_ACK) {
307 WARN("invalid protocol version or rejection packet\n");
308 HeapFree(GetProcessHeap(), 0, response);
309 RPCRT4_DestroyConnection(*Connection);
310 return RPC_S_PROTOCOL_ERROR;
313 if (response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
314 WARN("server doesn't allow large enough packets\n");
315 HeapFree(GetProcessHeap(), 0, response);
316 RPCRT4_DestroyConnection(*Connection);
317 return RPC_S_PROTOCOL_ERROR;
320 /* FIXME: do more checks? */
322 (*Connection)->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
323 (*Connection)->ActiveInterface = *InterfaceId;
324 HeapFree(GetProcessHeap(), 0, response);
327 return RPC_S_OK;
330 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
332 TRACE("(Binding == ^%p)\n", Binding);
333 if (!Connection) return RPC_S_OK;
334 if (Binding->FromConn == Connection) return RPC_S_OK;
335 return RPCRT4_DestroyConnection(Connection);
338 /* utility functions for string composing and parsing */
339 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
341 unsigned len = strlen(src);
342 memcpy(data, src, len*sizeof(CHAR));
343 return len;
346 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
348 unsigned len = strlenW(src);
349 memcpy(data, src, len*sizeof(WCHAR));
350 return len;
353 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
355 DWORD len = strlen(dst), slen = strlen(src);
356 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
357 if (!ndst)
359 HeapFree(GetProcessHeap(), 0, dst);
360 return NULL;
362 ndst[len] = ',';
363 memcpy(ndst+len+1, src, slen+1);
364 return ndst;
367 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
369 DWORD len = strlenW(dst), slen = strlenW(src);
370 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
371 if (!ndst)
373 HeapFree(GetProcessHeap(), 0, dst);
374 return NULL;
376 ndst[len] = ',';
377 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
378 return ndst;
382 /***********************************************************************
383 * RpcStringBindingComposeA (RPCRT4.@)
385 RPC_STATUS WINAPI RpcStringBindingComposeA(unsigned char *ObjUuid, unsigned char *Protseq,
386 unsigned char *NetworkAddr, unsigned char *Endpoint,
387 unsigned char *Options, unsigned char** StringBinding )
389 DWORD len = 1;
390 LPSTR data;
392 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
393 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
394 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
395 debugstr_a( (char*)Options ), StringBinding );
397 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
398 if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
399 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
400 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
401 if (Options && *Options) len += strlen((char*)Options) + 2;
403 data = HeapAlloc(GetProcessHeap(), 0, len);
404 *StringBinding = (unsigned char*)data;
406 if (ObjUuid && *ObjUuid) {
407 data += RPCRT4_strcopyA(data, (char*)ObjUuid);
408 *data++ = '@';
410 if (Protseq && *Protseq) {
411 data += RPCRT4_strcopyA(data, (char*)Protseq);
412 *data++ = ':';
414 if (NetworkAddr && *NetworkAddr)
415 data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
417 if ((Endpoint && *Endpoint) ||
418 (Options && *Options)) {
419 *data++ = '[';
420 if (Endpoint && *Endpoint) {
421 data += RPCRT4_strcopyA(data, (char*)Endpoint);
422 if (Options && *Options) *data++ = ',';
424 if (Options && *Options) {
425 data += RPCRT4_strcopyA(data, (char*)Options);
427 *data++ = ']';
429 *data = 0;
431 return RPC_S_OK;
434 /***********************************************************************
435 * RpcStringBindingComposeW (RPCRT4.@)
437 RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,
438 LPWSTR NetworkAddr, LPWSTR Endpoint,
439 LPWSTR Options, LPWSTR* StringBinding )
441 DWORD len = 1;
442 LPWSTR data;
444 TRACE("(%s,%s,%s,%s,%s,%p)\n",
445 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
446 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
447 debugstr_w( Options ), StringBinding);
449 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
450 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
451 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
452 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
453 if (Options && *Options) len += strlenW(Options) + 2;
455 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
456 *StringBinding = data;
458 if (ObjUuid && *ObjUuid) {
459 data += RPCRT4_strcopyW(data, ObjUuid);
460 *data++ = '@';
462 if (Protseq && *Protseq) {
463 data += RPCRT4_strcopyW(data, Protseq);
464 *data++ = ':';
466 if (NetworkAddr && *NetworkAddr) {
467 data += RPCRT4_strcopyW(data, NetworkAddr);
469 if ((Endpoint && *Endpoint) ||
470 (Options && *Options)) {
471 *data++ = '[';
472 if (Endpoint && *Endpoint) {
473 data += RPCRT4_strcopyW(data, Endpoint);
474 if (Options && *Options) *data++ = ',';
476 if (Options && *Options) {
477 data += RPCRT4_strcopyW(data, Options);
479 *data++ = ']';
481 *data = 0;
483 return RPC_S_OK;
487 /***********************************************************************
488 * RpcStringBindingParseA (RPCRT4.@)
490 RPC_STATUS WINAPI RpcStringBindingParseA( unsigned char *StringBinding, unsigned char **ObjUuid,
491 unsigned char **Protseq, unsigned char **NetworkAddr,
492 unsigned char **Endpoint, unsigned char **Options)
494 CHAR *data, *next;
495 static const char ep_opt[] = "endpoint=";
497 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
498 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
500 if (ObjUuid) *ObjUuid = NULL;
501 if (Protseq) *Protseq = NULL;
502 if (NetworkAddr) *NetworkAddr = NULL;
503 if (Endpoint) *Endpoint = NULL;
504 if (Options) *Options = NULL;
506 data = (char*) StringBinding;
508 next = strchr(data, '@');
509 if (next) {
510 if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
511 data = next+1;
514 next = strchr(data, ':');
515 if (next) {
516 if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
517 data = next+1;
520 next = strchr(data, '[');
521 if (next) {
522 CHAR *close, *opt;
524 if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
525 data = next+1;
526 close = strchr(data, ']');
527 if (!close) goto fail;
529 /* tokenize options */
530 while (data < close) {
531 next = strchr(data, ',');
532 if (!next || next > close) next = close;
533 /* FIXME: this is kind of inefficient */
534 opt = RPCRT4_strndupA(data, next - data);
535 data = next+1;
537 /* parse option */
538 next = strchr(opt, '=');
539 if (!next) {
540 /* not an option, must be an endpoint */
541 if (*Endpoint) goto fail;
542 *Endpoint = (unsigned char*) opt;
543 } else {
544 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
545 /* endpoint option */
546 if (*Endpoint) goto fail;
547 *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
548 HeapFree(GetProcessHeap(), 0, opt);
549 } else {
550 /* network option */
551 if (*Options) {
552 /* FIXME: this is kind of inefficient */
553 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
554 HeapFree(GetProcessHeap(), 0, opt);
555 } else
556 *Options = (unsigned char*) opt;
561 data = close+1;
562 if (*data) goto fail;
564 else if (NetworkAddr)
565 *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
567 return RPC_S_OK;
569 fail:
570 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
571 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
572 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
573 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
574 if (Options) RpcStringFreeA((unsigned char**)Options);
575 return RPC_S_INVALID_STRING_BINDING;
578 /***********************************************************************
579 * RpcStringBindingParseW (RPCRT4.@)
581 RPC_STATUS WINAPI RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR *ObjUuid,
582 LPWSTR *Protseq, LPWSTR *NetworkAddr,
583 LPWSTR *Endpoint, LPWSTR *Options)
585 WCHAR *data, *next;
586 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
588 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
589 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
591 if (ObjUuid) *ObjUuid = NULL;
592 if (Protseq) *Protseq = NULL;
593 if (NetworkAddr) *NetworkAddr = NULL;
594 if (Endpoint) *Endpoint = NULL;
595 if (Options) *Options = NULL;
597 data = StringBinding;
599 next = strchrW(data, '@');
600 if (next) {
601 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
602 data = next+1;
605 next = strchrW(data, ':');
606 if (next) {
607 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
608 data = next+1;
611 next = strchrW(data, '[');
612 if (next) {
613 WCHAR *close, *opt;
615 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
616 data = next+1;
617 close = strchrW(data, ']');
618 if (!close) goto fail;
620 /* tokenize options */
621 while (data < close) {
622 next = strchrW(data, ',');
623 if (!next || next > close) next = close;
624 /* FIXME: this is kind of inefficient */
625 opt = RPCRT4_strndupW(data, next - data);
626 data = next+1;
628 /* parse option */
629 next = strchrW(opt, '=');
630 if (!next) {
631 /* not an option, must be an endpoint */
632 if (*Endpoint) goto fail;
633 *Endpoint = opt;
634 } else {
635 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
636 /* endpoint option */
637 if (*Endpoint) goto fail;
638 *Endpoint = RPCRT4_strdupW(next+1);
639 HeapFree(GetProcessHeap(), 0, opt);
640 } else {
641 /* network option */
642 if (*Options) {
643 /* FIXME: this is kind of inefficient */
644 *Options = RPCRT4_strconcatW(*Options, opt);
645 HeapFree(GetProcessHeap(), 0, opt);
646 } else
647 *Options = opt;
652 data = close+1;
653 if (*data) goto fail;
654 } else if (NetworkAddr)
655 *NetworkAddr = RPCRT4_strdupW(data);
657 return RPC_S_OK;
659 fail:
660 if (ObjUuid) RpcStringFreeW(ObjUuid);
661 if (Protseq) RpcStringFreeW(Protseq);
662 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
663 if (Endpoint) RpcStringFreeW(Endpoint);
664 if (Options) RpcStringFreeW(Options);
665 return RPC_S_INVALID_STRING_BINDING;
668 /***********************************************************************
669 * RpcBindingFree (RPCRT4.@)
671 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
673 RPC_STATUS status;
674 TRACE("(%p) = %p\n", Binding, *Binding);
675 status = RPCRT4_DestroyBinding(*Binding);
676 if (status == RPC_S_OK) *Binding = 0;
677 return status;
680 /***********************************************************************
681 * RpcBindingVectorFree (RPCRT4.@)
683 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
685 RPC_STATUS status;
686 unsigned long c;
688 TRACE("(%p)\n", BindingVector);
689 for (c=0; c<(*BindingVector)->Count; c++) {
690 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
692 HeapFree(GetProcessHeap(), 0, *BindingVector);
693 *BindingVector = NULL;
694 return RPC_S_OK;
697 /***********************************************************************
698 * RpcBindingInqObject (RPCRT4.@)
700 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
702 RpcBinding* bind = (RpcBinding*)Binding;
704 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
705 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
706 return RPC_S_OK;
709 /***********************************************************************
710 * RpcBindingSetObject (RPCRT4.@)
712 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
714 RpcBinding* bind = (RpcBinding*)Binding;
716 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
717 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
718 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
721 /***********************************************************************
722 * RpcBindingFromStringBindingA (RPCRT4.@)
724 RPC_STATUS WINAPI RpcBindingFromStringBindingA( unsigned char *StringBinding, RPC_BINDING_HANDLE* Binding )
726 RPC_STATUS ret;
727 RpcBinding* bind = NULL;
728 unsigned char *ObjectUuid, *Protseq, *NetworkAddr, *Endpoint, *Options;
729 UUID Uuid;
731 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
733 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
734 &NetworkAddr, &Endpoint, &Options);
735 if (ret != RPC_S_OK) return ret;
737 ret = UuidFromStringA(ObjectUuid, &Uuid);
739 if (ret == RPC_S_OK)
740 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
741 if (ret == RPC_S_OK)
742 ret = RPCRT4_SetBindingObject(bind, &Uuid);
743 if (ret == RPC_S_OK)
744 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
746 RpcStringFreeA((unsigned char**)&Options);
747 RpcStringFreeA((unsigned char**)&Endpoint);
748 RpcStringFreeA((unsigned char**)&NetworkAddr);
749 RpcStringFreeA((unsigned char**)&Protseq);
750 RpcStringFreeA((unsigned char**)&ObjectUuid);
752 if (ret == RPC_S_OK)
753 *Binding = (RPC_BINDING_HANDLE)bind;
754 else
755 RPCRT4_DestroyBinding(bind);
757 return ret;
760 /***********************************************************************
761 * RpcBindingFromStringBindingW (RPCRT4.@)
763 RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
765 RPC_STATUS ret;
766 RpcBinding* bind = NULL;
767 LPWSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
768 UUID Uuid;
770 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
772 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
773 &NetworkAddr, &Endpoint, &Options);
774 if (ret != RPC_S_OK) return ret;
776 ret = UuidFromStringW(ObjectUuid, &Uuid);
778 if (ret == RPC_S_OK)
779 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
780 if (ret == RPC_S_OK)
781 ret = RPCRT4_SetBindingObject(bind, &Uuid);
782 if (ret == RPC_S_OK)
783 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
785 RpcStringFreeW(&Options);
786 RpcStringFreeW(&Endpoint);
787 RpcStringFreeW(&NetworkAddr);
788 RpcStringFreeW(&Protseq);
789 RpcStringFreeW(&ObjectUuid);
791 if (ret == RPC_S_OK)
792 *Binding = (RPC_BINDING_HANDLE)bind;
793 else
794 RPCRT4_DestroyBinding(bind);
796 return ret;
799 /***********************************************************************
800 * RpcBindingToStringBindingA (RPCRT4.@)
802 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, unsigned char** StringBinding )
804 RPC_STATUS ret;
805 RpcBinding* bind = (RpcBinding*)Binding;
806 LPSTR ObjectUuid;
808 TRACE("(%p,%p)\n", Binding, StringBinding);
810 ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
811 if (ret != RPC_S_OK) return ret;
813 ret = RpcStringBindingComposeA((unsigned char*) ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
814 (unsigned char*) bind->Endpoint, NULL, StringBinding);
816 RpcStringFreeA((unsigned char**)&ObjectUuid);
818 return ret;
821 /***********************************************************************
822 * RpcBindingToStringBindingW (RPCRT4.@)
824 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, unsigned short** StringBinding )
826 RPC_STATUS ret;
827 unsigned char *str = NULL;
828 TRACE("(%p,%p)\n", Binding, StringBinding);
829 ret = RpcBindingToStringBindingA(Binding, &str);
830 *StringBinding = RPCRT4_strdupAtoW((char*)str);
831 RpcStringFreeA((unsigned char**)&str);
832 return ret;
835 /***********************************************************************
836 * I_RpcBindingSetAsync (RPCRT4.@)
837 * NOTES
838 * Exists in win9x and winNT, but with different number of arguments
839 * (9x version has 3 arguments, NT has 2).
841 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
843 RpcBinding* bind = (RpcBinding*)Binding;
845 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
847 bind->BlockingFn = BlockingFn;
849 return RPC_S_OK;
852 /***********************************************************************
853 * RpcNetworkIsProtseqValidA (RPCRT4.@)
855 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(unsigned char *protseq) {
856 UNICODE_STRING protseqW;
858 if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */
860 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) {
861 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
862 RtlFreeUnicodeString(&protseqW);
863 return ret;
864 } else return RPC_S_OUT_OF_MEMORY;
867 /***********************************************************************
868 * RpcNetworkIsProtseqValidW (RPCRT4.@)
870 * Checks if the given protocol sequence is known by the RPC system.
871 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
873 * We currently support:
874 * ncalrpc local-only rpc over LPC (LPC is not really used)
875 * ncacn_np rpc over named pipes
877 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(LPWSTR protseq) {
878 static const WCHAR protseqsW[][15] = {
879 {'n','c','a','l','r','p','c',0},
880 {'n','c','a','c','n','_','n','p',0}
882 static const int count = sizeof(protseqsW) / sizeof(protseqsW[0]);
883 int i;
885 if (!protseq) return RPC_S_INVALID_RPC_PROTSEQ; /* ? */
887 for (i = 0; i < count; i++) {
888 if (!strcmpW(protseq, protseqsW[i])) return RPC_S_OK;
891 FIXME("Unknown protseq %s - we probably need to implement it one day\n", debugstr_w(protseq));
892 return RPC_S_PROTSEQ_NOT_SUPPORTED;
895 /***********************************************************************
896 * RpcImpersonateClient (RPCRT4.@)
898 * Impersonates the client connected via a binding handle so that security
899 * checks are done in the context of the client.
901 * PARAMS
902 * BindingHandle [I] Handle to the binding to the client.
904 * RETURNS
905 * Success: RPS_S_OK.
906 * Failure: RPC_STATUS value.
908 * NOTES
910 * If BindingHandle is NULL then the function impersonates the client
911 * connected to the binding handle of the current thread.
913 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
915 FIXME("(%p): stub\n", BindingHandle);
916 return RPC_S_OK;
919 /***********************************************************************
920 * RpcRevertToSelfEx (RPCRT4.@)
922 * Stops impersonating the client connected to the binding handle so that security
923 * checks are no longer done in the context of the client.
925 * PARAMS
926 * BindingHandle [I] Handle to the binding to the client.
928 * RETURNS
929 * Success: RPS_S_OK.
930 * Failure: RPC_STATUS value.
932 * NOTES
934 * If BindingHandle is NULL then the function stops impersonating the client
935 * connected to the binding handle of the current thread.
937 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
939 FIXME("(%p): stub\n", BindingHandle);
940 return RPC_S_OK;
943 /***********************************************************************
944 * RpcBindingInqAuthInfoExA (RPCRT4.@)
946 RPCRTAPI RPC_STATUS RPC_ENTRY
947 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, unsigned char ** ServerPrincName, unsigned long *AuthnLevel,
948 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
949 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
951 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
952 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
953 return RPC_S_INVALID_BINDING;
956 /***********************************************************************
957 * RpcBindingInqAuthInfoExW (RPCRT4.@)
959 RPCRTAPI RPC_STATUS RPC_ENTRY
960 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, unsigned short ** ServerPrincName, unsigned long *AuthnLevel,
961 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
962 unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
964 FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
965 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
966 return RPC_S_INVALID_BINDING;
969 /***********************************************************************
970 * RpcBindingInqAuthInfoA (RPCRT4.@)
972 RPCRTAPI RPC_STATUS RPC_ENTRY
973 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, unsigned char ** ServerPrincName, unsigned long *AuthnLevel,
974 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
976 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
977 AuthnSvc, AuthIdentity, AuthzSvc);
978 return RPC_S_INVALID_BINDING;
981 /***********************************************************************
982 * RpcBindingInqAuthInfoW (RPCRT4.@)
984 RPCRTAPI RPC_STATUS RPC_ENTRY
985 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, unsigned short ** ServerPrincName, unsigned long *AuthnLevel,
986 unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
988 FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
989 AuthnSvc, AuthIdentity, AuthzSvc);
990 return RPC_S_INVALID_BINDING;
993 /***********************************************************************
994 * RpcBindingSetAuthInfoExA (RPCRT4.@)
996 RPCRTAPI RPC_STATUS RPC_ENTRY
997 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, unsigned char *ServerPrincName,
998 unsigned long AuthnLevel, unsigned long AuthnSvc,
999 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1000 RPC_SECURITY_QOS *SecurityQos )
1002 FIXME("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1003 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1004 return RPC_S_OK;
1007 /***********************************************************************
1008 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1010 RPCRTAPI RPC_STATUS RPC_ENTRY
1011 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, unsigned short *ServerPrincName, unsigned long AuthnLevel,
1012 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1013 RPC_SECURITY_QOS *SecurityQos )
1015 FIXME("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1016 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1017 return RPC_S_OK;
1020 /***********************************************************************
1021 * RpcBindingSetAuthInfoA (RPCRT4.@)
1023 RPCRTAPI RPC_STATUS RPC_ENTRY
1024 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, unsigned char *ServerPrincName, unsigned long AuthnLevel,
1025 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1027 FIXME("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1028 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1029 return RPC_S_OK;
1032 /***********************************************************************
1033 * RpcBindingSetAuthInfoW (RPCRT4.@)
1035 RPCRTAPI RPC_STATUS RPC_ENTRY
1036 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, unsigned short *ServerPrincName, unsigned long AuthnLevel,
1037 unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1039 FIXME("%p %s %lu %lu %p %lu\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1040 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1041 return RPC_S_OK;
1044 /***********************************************************************
1045 * RpcBindingSetOption (RPCRT4.@)
1047 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1049 FIXME("(%p, %ld, %ld): stub\n", BindingHandle, Option, OptionValue);
1050 return RPC_S_OK;