rpcrt4/ndr_marshall.c: Bring the function definitions in sync with their declaration.
[wine] / dlls / rpcrt4 / rpc_binding.c
1 /*
2  * RPC binding API
3  *
4  * Copyright 2001 Ove Kåven, TransGaming Technologies
5  * Copyright 2003 Mike Hearn
6  * Copyright 2004 Filip Navara
7  * Copyright 2006 CodeWeavers
8  *
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.
13  *
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.
18  *
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
22  */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28
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"
36
37 #include "rpc.h"
38 #include "rpcndr.h"
39
40 #include "wine/debug.h"
41
42 #include "rpc_binding.h"
43 #include "rpc_message.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
46
47 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
48 {
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;
58 }
59
60 LPSTR RPCRT4_strdupWtoA(LPWSTR src)
61 {
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;
69 }
70
71 LPWSTR RPCRT4_strdupAtoW(LPSTR src)
72 {
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;
80 }
81
82 LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen)
83 {
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;
93 }
94
95 void RPCRT4_strfree(LPSTR src)
96 {
97   HeapFree(GetProcessHeap(), 0, src);
98 }
99
100 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
101 {
102   RpcBinding* NewBinding;
103
104   NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
105   NewBinding->refs = 1;
106   NewBinding->server = server;
107
108   *Binding = NewBinding;
109
110   return RPC_S_OK;
111 }
112
113 RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
114 {
115   RpcBinding* NewBinding;
116
117   RPCRT4_AllocBinding(&NewBinding, server);
118   NewBinding->Protseq = RPCRT4_strdupA(Protseq);
119
120   TRACE("binding: %p\n", NewBinding);
121   *Binding = NewBinding;
122
123   return RPC_S_OK;
124 }
125
126 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
127 {
128   RpcBinding* NewBinding;
129
130   RPCRT4_AllocBinding(&NewBinding, server);
131   NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
132
133   TRACE("binding: %p\n", NewBinding);
134   *Binding = NewBinding;
135
136   return RPC_S_OK;
137 }
138
139 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions)
140 {
141   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
142    debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
143
144   RPCRT4_strfree(Binding->NetworkAddr);
145   Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
146   RPCRT4_strfree(Binding->Endpoint);
147   if (Endpoint) {
148     Binding->Endpoint = RPCRT4_strdupA(Endpoint);
149   } else {
150     Binding->Endpoint = RPCRT4_strdupA("");
151   }
152   if (!Binding->Endpoint) ERR("out of memory?\n");
153
154   return RPC_S_OK;
155 }
156
157 RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
158 {
159   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, 
160    debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
161
162   RPCRT4_strfree(Binding->NetworkAddr);
163   Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
164   RPCRT4_strfree(Binding->Endpoint);
165   if (Endpoint) {
166     Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
167   } else {
168     Binding->Endpoint = RPCRT4_strdupA("");
169   }
170   if (!Binding->Endpoint) ERR("out of memory?\n");
171
172   return RPC_S_OK;
173 }
174
175 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
176 {
177   TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
178
179   RPCRT4_strfree(Binding->Endpoint);
180   Binding->Endpoint = RPCRT4_strdupA(Endpoint);
181
182   return RPC_S_OK;
183 }
184
185 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
186 {
187   TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); 
188   if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
189   else UuidCreateNil(&Binding->ObjectUuid);
190   return RPC_S_OK;
191 }
192
193 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
194 {
195   RpcBinding* NewBinding;
196   TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
197
198   RPCRT4_AllocBinding(&NewBinding, Connection->server);
199   NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
200   NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
201   NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
202   NewBinding->FromConn = Connection;
203
204   TRACE("binding: %p\n", NewBinding);
205   *Binding = NewBinding;
206
207   return RPC_S_OK;
208 }
209
210 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
211 {
212   InterlockedIncrement(&OldBinding->refs);
213   *Binding = OldBinding;
214   return RPC_S_OK;
215 }
216
217 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
218 {
219   if (InterlockedDecrement(&Binding->refs))
220     return RPC_S_OK;
221
222   TRACE("binding: %p\n", Binding);
223   /* FIXME: release connections */
224   RPCRT4_strfree(Binding->Endpoint);
225   RPCRT4_strfree(Binding->NetworkAddr);
226   RPCRT4_strfree(Binding->Protseq);
227   HeapFree(GetProcessHeap(), 0, Binding);
228   return RPC_S_OK;
229 }
230
231 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
232                               PRPC_SYNTAX_IDENTIFIER TransferSyntax,
233                               PRPC_SYNTAX_IDENTIFIER InterfaceId)
234 {
235   RpcConnection* NewConnection;
236   RPC_STATUS status;
237
238   TRACE("(Binding == ^%p)\n", Binding);
239
240   if (!Binding->server) {
241     /* try to find a compatible connection from the connection pool */
242     NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
243         Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
244         Binding->AuthInfo);
245     if (NewConnection) {
246       *Connection = NewConnection;
247       return RPC_S_OK;
248     }
249   } else {
250     /* we already have a connection with acceptable binding, so use it */
251     if (Binding->FromConn) {
252       *Connection = Binding->FromConn;
253       return RPC_S_OK;
254     }
255   }
256   
257   /* create a new connection */
258   RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq,
259                           Binding->NetworkAddr, Binding->Endpoint, NULL,
260                           Binding->AuthInfo, Binding);
261   status = RPCRT4_OpenClientConnection(NewConnection);
262   if (status != RPC_S_OK)
263   {
264     RPCRT4_DestroyConnection(NewConnection);
265     return status;
266   }
267  
268   /* we need to send a binding packet if we are client. */
269   if (!NewConnection->server) {
270     RpcPktHdr *hdr;
271     RpcPktHdr *response_hdr;
272     RPC_MESSAGE msg;
273
274     TRACE("sending bind request to server\n");
275
276     hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
277                                  RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
278                                  InterfaceId, TransferSyntax);
279
280     status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
281     RPCRT4_FreeHeader(hdr);
282     if (status != RPC_S_OK) {
283       RPCRT4_DestroyConnection(NewConnection);
284       return status;
285     }
286
287     status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
288     if (status != RPC_S_OK) {
289       ERR("receive failed\n");
290       RPCRT4_DestroyConnection(NewConnection);
291       return status;
292     }
293
294     if (response_hdr->common.ptype != PKT_BIND_ACK ||
295         response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
296       ERR("failed to bind for interface %s, %d.%d\n",
297         debugstr_guid(&InterfaceId->SyntaxGUID),
298         InterfaceId->SyntaxVersion.MajorVersion,
299         InterfaceId->SyntaxVersion.MinorVersion);
300       RPCRT4_FreeHeader(response_hdr);
301       RPCRT4_DestroyConnection(NewConnection);
302       return RPC_S_PROTOCOL_ERROR;
303     }
304
305     /* FIXME: do more checks? */
306
307     NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
308     NewConnection->ActiveInterface = *InterfaceId;
309     RPCRT4_FreeHeader(response_hdr);
310   }
311
312   if (Binding->server)
313     Binding->FromConn = NewConnection;
314   *Connection = NewConnection;
315
316   return RPC_S_OK;
317 }
318
319 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
320 {
321   TRACE("(Binding == ^%p)\n", Binding);
322   if (!Connection) return RPC_S_OK;
323   if (Binding->server) {
324     /* don't destroy a connection that is cached in the binding */
325     if (Binding->FromConn == Connection)
326       return RPC_S_OK;
327     return RPCRT4_DestroyConnection(Connection);
328   }
329   else {
330     RPCRT4_ReleaseIdleConnection(Connection);
331     return RPC_S_OK;
332   }
333 }
334
335 /* utility functions for string composing and parsing */
336 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
337 {
338   unsigned len = strlen(src);
339   memcpy(data, src, len*sizeof(CHAR));
340   return len;
341 }
342
343 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
344 {
345   unsigned len = strlenW(src);
346   memcpy(data, src, len*sizeof(WCHAR));
347   return len;
348 }
349
350 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
351 {
352   DWORD len = strlen(dst), slen = strlen(src);
353   LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
354   if (!ndst)
355   {
356     HeapFree(GetProcessHeap(), 0, dst);
357     return NULL;
358   }
359   ndst[len] = ',';
360   memcpy(ndst+len+1, src, slen+1);
361   return ndst;
362 }
363
364 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
365 {
366   DWORD len = strlenW(dst), slen = strlenW(src);
367   LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
368   if (!ndst) 
369   {
370     HeapFree(GetProcessHeap(), 0, dst);
371     return NULL;
372   }
373   ndst[len] = ',';
374   memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
375   return ndst;
376 }
377
378
379 /***********************************************************************
380  *             RpcStringBindingComposeA (RPCRT4.@)
381  */
382 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
383                                            RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
384                                            RPC_CSTR Options, RPC_CSTR *StringBinding )
385 {
386   DWORD len = 1;
387   LPSTR data;
388
389   TRACE( "(%s,%s,%s,%s,%s,%p)\n",
390         debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
391         debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
392         debugstr_a( (char*)Options ), StringBinding );
393
394   if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
395   if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
396   if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
397   if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
398   if (Options && *Options) len += strlen((char*)Options) + 2;
399
400   data = HeapAlloc(GetProcessHeap(), 0, len);
401   *StringBinding = (unsigned char*)data;
402
403   if (ObjUuid && *ObjUuid) {
404     data += RPCRT4_strcopyA(data, (char*)ObjUuid);
405     *data++ = '@';
406   }
407   if (Protseq && *Protseq) {
408     data += RPCRT4_strcopyA(data, (char*)Protseq);
409     *data++ = ':';
410   }
411   if (NetworkAddr && *NetworkAddr)
412     data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
413
414   if ((Endpoint && *Endpoint) ||
415       (Options && *Options)) {
416     *data++ = '[';
417     if (Endpoint && *Endpoint) {
418       data += RPCRT4_strcopyA(data, (char*)Endpoint);
419       if (Options && *Options) *data++ = ',';
420     }
421     if (Options && *Options) {
422       data += RPCRT4_strcopyA(data, (char*)Options);
423     }
424     *data++ = ']';
425   }
426   *data = 0;
427
428   return RPC_S_OK;
429 }
430
431 /***********************************************************************
432  *             RpcStringBindingComposeW (RPCRT4.@)
433  */
434 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
435                                             RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
436                                             RPC_WSTR Options, RPC_WSTR* StringBinding )
437 {
438   DWORD len = 1;
439   RPC_WSTR data;
440
441   TRACE("(%s,%s,%s,%s,%s,%p)\n",
442        debugstr_w( ObjUuid ), debugstr_w( Protseq ),
443        debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
444        debugstr_w( Options ), StringBinding);
445
446   if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
447   if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
448   if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
449   if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
450   if (Options && *Options) len += strlenW(Options) + 2;
451
452   data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
453   *StringBinding = data;
454
455   if (ObjUuid && *ObjUuid) {
456     data += RPCRT4_strcopyW(data, ObjUuid);
457     *data++ = '@';
458   }
459   if (Protseq && *Protseq) {
460     data += RPCRT4_strcopyW(data, Protseq);
461     *data++ = ':';
462   }
463   if (NetworkAddr && *NetworkAddr) {
464     data += RPCRT4_strcopyW(data, NetworkAddr);
465   }
466   if ((Endpoint && *Endpoint) ||
467       (Options && *Options)) {
468     *data++ = '[';
469     if (Endpoint && *Endpoint) {
470       data += RPCRT4_strcopyW(data, Endpoint);
471       if (Options && *Options) *data++ = ',';
472     }
473     if (Options && *Options) {
474       data += RPCRT4_strcopyW(data, Options);
475     }
476     *data++ = ']';
477   }
478   *data = 0;
479
480   return RPC_S_OK;
481 }
482
483
484 /***********************************************************************
485  *             RpcStringBindingParseA (RPCRT4.@)
486  */
487 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
488                                           RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
489                                           RPC_CSTR *Endpoint, RPC_CSTR *Options)
490 {
491   CHAR *data, *next;
492   static const char ep_opt[] = "endpoint=";
493
494   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
495        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
496
497   if (ObjUuid) *ObjUuid = NULL;
498   if (Protseq) *Protseq = NULL;
499   if (NetworkAddr) *NetworkAddr = NULL;
500   if (Endpoint) *Endpoint = NULL;
501   if (Options) *Options = NULL;
502
503   data = (char*) StringBinding;
504
505   next = strchr(data, '@');
506   if (next) {
507     if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
508     data = next+1;
509   }
510
511   next = strchr(data, ':');
512   if (next) {
513     if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
514     data = next+1;
515   }
516
517   next = strchr(data, '[');
518   if (next) {
519     CHAR *close, *opt;
520
521     if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
522     data = next+1;
523     close = strchr(data, ']');
524     if (!close) goto fail;
525
526     /* tokenize options */
527     while (data < close) {
528       next = strchr(data, ',');
529       if (!next || next > close) next = close;
530       /* FIXME: this is kind of inefficient */
531       opt = RPCRT4_strndupA(data, next - data);
532       data = next+1;
533
534       /* parse option */
535       next = strchr(opt, '=');
536       if (!next) {
537         /* not an option, must be an endpoint */
538         if (*Endpoint) goto fail;
539         *Endpoint = (unsigned char*) opt;
540       } else {
541         if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
542           /* endpoint option */
543           if (*Endpoint) goto fail;
544           *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
545           HeapFree(GetProcessHeap(), 0, opt);
546         } else {
547           /* network option */
548           if (*Options) {
549             /* FIXME: this is kind of inefficient */
550             *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
551             HeapFree(GetProcessHeap(), 0, opt);
552           } else 
553             *Options = (unsigned char*) opt;
554         }
555       }
556     }
557
558     data = close+1;
559     if (*data) goto fail;
560   }
561   else if (NetworkAddr) 
562     *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
563
564   return RPC_S_OK;
565
566 fail:
567   if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
568   if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
569   if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
570   if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
571   if (Options) RpcStringFreeA((unsigned char**)Options);
572   return RPC_S_INVALID_STRING_BINDING;
573 }
574
575 /***********************************************************************
576  *             RpcStringBindingParseW (RPCRT4.@)
577  */
578 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
579                                           RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
580                                           RPC_WSTR *Endpoint, RPC_WSTR *Options)
581 {
582   WCHAR *data, *next;
583   static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
584
585   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
586        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
587
588   if (ObjUuid) *ObjUuid = NULL;
589   if (Protseq) *Protseq = NULL;
590   if (NetworkAddr) *NetworkAddr = NULL;
591   if (Endpoint) *Endpoint = NULL;
592   if (Options) *Options = NULL;
593
594   data = StringBinding;
595
596   next = strchrW(data, '@');
597   if (next) {
598     if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
599     data = next+1;
600   }
601
602   next = strchrW(data, ':');
603   if (next) {
604     if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
605     data = next+1;
606   }
607
608   next = strchrW(data, '[');
609   if (next) {
610     WCHAR *close, *opt;
611
612     if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
613     data = next+1;
614     close = strchrW(data, ']');
615     if (!close) goto fail;
616
617     /* tokenize options */
618     while (data < close) {
619       next = strchrW(data, ',');
620       if (!next || next > close) next = close;
621       /* FIXME: this is kind of inefficient */
622       opt = RPCRT4_strndupW(data, next - data);
623       data = next+1;
624
625       /* parse option */
626       next = strchrW(opt, '=');
627       if (!next) {
628         /* not an option, must be an endpoint */
629         if (*Endpoint) goto fail;
630         *Endpoint = opt;
631       } else {
632         if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
633           /* endpoint option */
634           if (*Endpoint) goto fail;
635           *Endpoint = RPCRT4_strdupW(next+1);
636           HeapFree(GetProcessHeap(), 0, opt);
637         } else {
638           /* network option */
639           if (*Options) {
640             /* FIXME: this is kind of inefficient */
641             *Options = RPCRT4_strconcatW(*Options, opt);
642             HeapFree(GetProcessHeap(), 0, opt);
643           } else 
644             *Options = opt;
645         }
646       }
647     }
648
649     data = close+1;
650     if (*data) goto fail;
651   } else if (NetworkAddr) 
652     *NetworkAddr = RPCRT4_strdupW(data);
653
654   return RPC_S_OK;
655
656 fail:
657   if (ObjUuid) RpcStringFreeW(ObjUuid);
658   if (Protseq) RpcStringFreeW(Protseq);
659   if (NetworkAddr) RpcStringFreeW(NetworkAddr);
660   if (Endpoint) RpcStringFreeW(Endpoint);
661   if (Options) RpcStringFreeW(Options);
662   return RPC_S_INVALID_STRING_BINDING;
663 }
664
665 /***********************************************************************
666  *             RpcBindingFree (RPCRT4.@)
667  */
668 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
669 {
670   RPC_STATUS status;
671   TRACE("(%p) = %p\n", Binding, *Binding);
672   status = RPCRT4_DestroyBinding(*Binding);
673   if (status == RPC_S_OK) *Binding = 0;
674   return status;
675 }
676   
677 /***********************************************************************
678  *             RpcBindingVectorFree (RPCRT4.@)
679  */
680 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
681 {
682   RPC_STATUS status;
683   unsigned long c;
684
685   TRACE("(%p)\n", BindingVector);
686   for (c=0; c<(*BindingVector)->Count; c++) {
687     status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
688   }
689   HeapFree(GetProcessHeap(), 0, *BindingVector);
690   *BindingVector = NULL;
691   return RPC_S_OK;
692 }
693   
694 /***********************************************************************
695  *             RpcBindingInqObject (RPCRT4.@)
696  */
697 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
698 {
699   RpcBinding* bind = (RpcBinding*)Binding;
700
701   TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
702   memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
703   return RPC_S_OK;
704 }
705   
706 /***********************************************************************
707  *             RpcBindingSetObject (RPCRT4.@)
708  */
709 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
710 {
711   RpcBinding* bind = (RpcBinding*)Binding;
712
713   TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
714   if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
715   return RPCRT4_SetBindingObject(Binding, ObjectUuid);
716 }
717
718 /***********************************************************************
719  *             RpcBindingFromStringBindingA (RPCRT4.@)
720  */
721 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
722 {
723   RPC_STATUS ret;
724   RpcBinding* bind = NULL;
725   RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
726   UUID Uuid;
727
728   TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
729
730   ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
731                               &NetworkAddr, &Endpoint, &Options);
732   if (ret != RPC_S_OK) return ret;
733
734   ret = UuidFromStringA(ObjectUuid, &Uuid);
735
736   if (ret == RPC_S_OK)
737     ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
738   if (ret == RPC_S_OK)
739     ret = RPCRT4_SetBindingObject(bind, &Uuid);
740   if (ret == RPC_S_OK)
741     ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
742
743   RpcStringFreeA((unsigned char**)&Options);
744   RpcStringFreeA((unsigned char**)&Endpoint);
745   RpcStringFreeA((unsigned char**)&NetworkAddr);
746   RpcStringFreeA((unsigned char**)&Protseq);
747   RpcStringFreeA((unsigned char**)&ObjectUuid);
748
749   if (ret == RPC_S_OK) 
750     *Binding = (RPC_BINDING_HANDLE)bind;
751   else 
752     RPCRT4_DestroyBinding(bind);
753
754   return ret;
755 }
756
757 /***********************************************************************
758  *             RpcBindingFromStringBindingW (RPCRT4.@)
759  */
760 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
761 {
762   RPC_STATUS ret;
763   RpcBinding* bind = NULL;
764   RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
765   UUID Uuid;
766
767   TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
768
769   ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
770                               &NetworkAddr, &Endpoint, &Options);
771   if (ret != RPC_S_OK) return ret;
772
773   ret = UuidFromStringW(ObjectUuid, &Uuid);
774
775   if (ret == RPC_S_OK)
776     ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
777   if (ret == RPC_S_OK)
778     ret = RPCRT4_SetBindingObject(bind, &Uuid);
779   if (ret == RPC_S_OK)
780     ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
781
782   RpcStringFreeW(&Options);
783   RpcStringFreeW(&Endpoint);
784   RpcStringFreeW(&NetworkAddr);
785   RpcStringFreeW(&Protseq);
786   RpcStringFreeW(&ObjectUuid);
787
788   if (ret == RPC_S_OK)
789     *Binding = (RPC_BINDING_HANDLE)bind;
790   else
791     RPCRT4_DestroyBinding(bind);
792
793   return ret;
794 }
795   
796 /***********************************************************************
797  *             RpcBindingToStringBindingA (RPCRT4.@)
798  */
799 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
800 {
801   RPC_STATUS ret;
802   RpcBinding* bind = (RpcBinding*)Binding;
803   LPSTR ObjectUuid;
804
805   TRACE("(%p,%p)\n", Binding, StringBinding);
806
807   ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
808   if (ret != RPC_S_OK) return ret;
809
810   ret = RpcStringBindingComposeA((unsigned char*) ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
811                                  (unsigned char*) bind->Endpoint, NULL, StringBinding);
812
813   RpcStringFreeA((unsigned char**)&ObjectUuid);
814
815   return ret;
816 }
817   
818 /***********************************************************************
819  *             RpcBindingToStringBindingW (RPCRT4.@)
820  */
821 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
822 {
823   RPC_STATUS ret;
824   unsigned char *str = NULL;
825   TRACE("(%p,%p)\n", Binding, StringBinding);
826   ret = RpcBindingToStringBindingA(Binding, &str);
827   *StringBinding = RPCRT4_strdupAtoW((char*)str);
828   RpcStringFreeA((unsigned char**)&str);
829   return ret;
830 }
831
832 /***********************************************************************
833  *             I_RpcBindingSetAsync (RPCRT4.@)
834  * NOTES
835  *  Exists in win9x and winNT, but with different number of arguments
836  *  (9x version has 3 arguments, NT has 2).
837  */
838 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
839 {
840   RpcBinding* bind = (RpcBinding*)Binding;
841
842   TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
843
844   bind->BlockingFn = BlockingFn;
845
846   return RPC_S_OK;
847 }
848
849 /***********************************************************************
850  *             RpcBindingCopy (RPCRT4.@)
851  */
852 RPC_STATUS RPC_ENTRY RpcBindingCopy(
853   RPC_BINDING_HANDLE SourceBinding,
854   RPC_BINDING_HANDLE* DestinationBinding)
855 {
856   RpcBinding *DestBinding;
857   RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
858   RPC_STATUS status;
859
860   TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
861
862   status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
863   if (status != RPC_S_OK) return status;
864
865   DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
866   DestBinding->BlockingFn = SrcBinding->BlockingFn;
867   DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
868   DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
869   DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
870
871   if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
872   DestBinding->AuthInfo = SrcBinding->AuthInfo;
873
874   *DestinationBinding = DestBinding;
875   return RPC_S_OK;
876 }
877
878 /***********************************************************************
879  *             RpcImpersonateClient (RPCRT4.@)
880  *
881  * Impersonates the client connected via a binding handle so that security
882  * checks are done in the context of the client.
883  *
884  * PARAMS
885  *  BindingHandle [I] Handle to the binding to the client.
886  *
887  * RETURNS
888  *  Success: RPS_S_OK.
889  *  Failure: RPC_STATUS value.
890  *
891  * NOTES
892  *
893  * If BindingHandle is NULL then the function impersonates the client
894  * connected to the binding handle of the current thread.
895  */
896 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
897 {
898     FIXME("(%p): stub\n", BindingHandle);
899     ImpersonateSelf(SecurityImpersonation);
900     return RPC_S_OK;
901 }
902
903 /***********************************************************************
904  *             RpcRevertToSelfEx (RPCRT4.@)
905  *
906  * Stops impersonating the client connected to the binding handle so that security
907  * checks are no longer done in the context of the client.
908  *
909  * PARAMS
910  *  BindingHandle [I] Handle to the binding to the client.
911  *
912  * RETURNS
913  *  Success: RPS_S_OK.
914  *  Failure: RPC_STATUS value.
915  *
916  * NOTES
917  *
918  * If BindingHandle is NULL then the function stops impersonating the client
919  * connected to the binding handle of the current thread.
920  */
921 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
922 {
923     FIXME("(%p): stub\n", BindingHandle);
924     return RPC_S_OK;
925 }
926
927 static RPC_STATUS RpcAuthInfo_Create(unsigned long AuthnLevel, unsigned long AuthnSvc, CredHandle cred, TimeStamp exp, RpcAuthInfo **ret)
928 {
929     RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
930     if (!AuthInfo)
931         return ERROR_OUTOFMEMORY;
932
933     AuthInfo->AuthnLevel = AuthnLevel;
934     AuthInfo->AuthnSvc = AuthnSvc;
935     AuthInfo->cred = cred;
936     AuthInfo->exp = exp;
937     *ret = AuthInfo;
938     return RPC_S_OK;
939 }
940
941 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
942 {
943     return InterlockedIncrement(&AuthInfo->refs);
944 }
945
946 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
947 {
948     ULONG refs = InterlockedDecrement(&AuthInfo->refs);
949
950     if (!refs)
951     {
952         FreeCredentialsHandle(&AuthInfo->cred);
953         HeapFree(GetProcessHeap(), 0, AuthInfo);
954     }
955
956     return refs;
957 }
958
959 /***********************************************************************
960  *             RpcRevertToSelf (RPCRT4.@)
961  */
962 RPC_STATUS WINAPI RpcRevertToSelf(void)
963 {
964     FIXME("stub\n");
965     RevertToSelf();
966     return RPC_S_OK;
967 }
968
969 /***********************************************************************
970  *             RpcMgmtSetComTimeout (RPCRT4.@)
971  */
972 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
973 {
974     FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
975     return RPC_S_OK;
976 }
977
978 /***********************************************************************
979  *             RpcBindingInqAuthInfoExA (RPCRT4.@)
980  */
981 RPCRTAPI RPC_STATUS RPC_ENTRY
982 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
983                           unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
984                           unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
985 {
986     FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
987           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
988     return RPC_S_INVALID_BINDING;
989 }
990
991 /***********************************************************************
992  *             RpcBindingInqAuthInfoExW (RPCRT4.@)
993  */
994 RPCRTAPI RPC_STATUS RPC_ENTRY
995 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
996                           unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
997                           unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
998 {
999     FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1000           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1001     return RPC_S_INVALID_BINDING;
1002 }
1003
1004 /***********************************************************************
1005  *             RpcBindingInqAuthInfoA (RPCRT4.@)
1006  */
1007 RPCRTAPI RPC_STATUS RPC_ENTRY
1008 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
1009                         unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1010 {
1011     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1012           AuthnSvc, AuthIdentity, AuthzSvc);
1013     return RPC_S_INVALID_BINDING;
1014 }
1015
1016 /***********************************************************************
1017  *             RpcBindingInqAuthInfoW (RPCRT4.@)
1018  */
1019 RPCRTAPI RPC_STATUS RPC_ENTRY
1020 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
1021                         unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1022 {
1023     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1024           AuthnSvc, AuthIdentity, AuthzSvc);
1025     return RPC_S_INVALID_BINDING;
1026 }
1027
1028 /***********************************************************************
1029  *             RpcBindingSetAuthInfoExA (RPCRT4.@)
1030  */
1031 RPCRTAPI RPC_STATUS RPC_ENTRY
1032 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1033                           unsigned long AuthnLevel, unsigned long AuthnSvc,
1034                           RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1035                           RPC_SECURITY_QOS *SecurityQos )
1036 {
1037   RpcBinding* bind = (RpcBinding*)Binding;
1038   SECURITY_STATUS r;
1039   CredHandle cred;
1040   TimeStamp exp;
1041   ULONG package_count;
1042   ULONG i;
1043   PSecPkgInfoA packages;
1044
1045   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1046         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1047
1048   if (AuthnLevel != RPC_C_AUTHN_LEVEL_CONNECT)
1049   {
1050     FIXME("unsupported AuthnLevel %lu\n", AuthnLevel);
1051     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1052   }
1053
1054   if (AuthzSvr)
1055   {
1056     FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1057     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1058   }
1059
1060   if (SecurityQos)
1061     FIXME("SecurityQos ignored\n");
1062
1063   r = EnumerateSecurityPackagesA(&package_count, &packages);
1064   if (r != SEC_E_OK)
1065   {
1066     ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r);
1067     return RPC_S_SEC_PKG_ERROR;
1068   }
1069
1070   for (i = 0; i < package_count; i++)
1071     if (packages[i].wRPCID == AuthnSvc)
1072         break;
1073
1074   if (i == package_count)
1075   {
1076     FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1077     FreeContextBuffer(packages);
1078     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1079   }
1080
1081   TRACE("found package %s for service %ld\n", packages[i].Name, AuthnSvc);
1082   r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1083                                 AuthIdentity, NULL, NULL, &cred, &exp);
1084   FreeContextBuffer(packages);
1085   if (r == ERROR_SUCCESS)
1086   {
1087     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1088     bind->AuthInfo = NULL;
1089     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1090     if (r != RPC_S_OK)
1091       FreeCredentialsHandle(&cred);
1092     return RPC_S_OK;
1093   }
1094   else
1095   {
1096     ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r);
1097     return RPC_S_SEC_PKG_ERROR;
1098   }
1099 }
1100
1101 /***********************************************************************
1102  *             RpcBindingSetAuthInfoExW (RPCRT4.@)
1103  */
1104 RPCRTAPI RPC_STATUS RPC_ENTRY
1105 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1106                           unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1107                           RPC_SECURITY_QOS *SecurityQos )
1108 {
1109   RpcBinding* bind = (RpcBinding*)Binding;
1110   SECURITY_STATUS r;
1111   CredHandle cred;
1112   TimeStamp exp;
1113   ULONG package_count;
1114   ULONG i;
1115   PSecPkgInfoW packages;
1116
1117   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1118         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1119
1120   if (AuthnLevel != RPC_C_AUTHN_LEVEL_CONNECT)
1121   {
1122     FIXME("unsupported AuthnLevel %lu\n", AuthnLevel);
1123     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1124   }
1125
1126   if (AuthzSvr)
1127   {
1128     FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1129     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1130   }
1131
1132   if (SecurityQos)
1133     FIXME("SecurityQos ignored\n");
1134
1135   r = EnumerateSecurityPackagesW(&package_count, &packages);
1136   if (r != SEC_E_OK)
1137   {
1138     ERR("EnumerateSecurityPackagesA failed with error 0x%08lx\n", r);
1139     return RPC_S_SEC_PKG_ERROR;
1140   }
1141
1142   for (i = 0; i < package_count; i++)
1143     if (packages[i].wRPCID == AuthnSvc)
1144         break;
1145
1146   if (i == package_count)
1147   {
1148     FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1149     FreeContextBuffer(packages);
1150     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1151   }
1152
1153   TRACE("found package %s for service %ld\n", debugstr_w(packages[i].Name), AuthnSvc);
1154   r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1155                                 AuthIdentity, NULL, NULL, &cred, &exp);
1156   FreeContextBuffer(packages);
1157   if (r == ERROR_SUCCESS)
1158   {
1159     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1160     bind->AuthInfo = NULL;
1161     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1162     if (r != RPC_S_OK)
1163       FreeCredentialsHandle(&cred);
1164     return RPC_S_OK;
1165   }
1166   else
1167   {
1168     ERR("AcquireCredentialsHandleA failed with error 0x%08lx\n", r);
1169     return RPC_S_SEC_PKG_ERROR;
1170   }
1171 }
1172
1173 /***********************************************************************
1174  *             RpcBindingSetAuthInfoA (RPCRT4.@)
1175  */
1176 RPCRTAPI RPC_STATUS RPC_ENTRY
1177 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, unsigned long AuthnLevel,
1178                         unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1179 {
1180     TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1181           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1182     return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1183 }
1184
1185 /***********************************************************************
1186  *             RpcBindingSetAuthInfoW (RPCRT4.@)
1187  */
1188 RPCRTAPI RPC_STATUS RPC_ENTRY
1189 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1190                         unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1191 {
1192     TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1193           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1194     return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1195 }
1196
1197 /***********************************************************************
1198  *             RpcBindingSetOption (RPCRT4.@)
1199  */
1200 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1201 {
1202     FIXME("(%p, %ld, %ld): stub\n", BindingHandle, Option, OptionValue);
1203     return RPC_S_OK;
1204 }