opengl32: Avoid generating a wrapper for internal functions when we can call the...
[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   status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
259                                    Binding->Protseq, Binding->NetworkAddr,
260                                    Binding->Endpoint, NULL, Binding->AuthInfo,
261                                    Binding);
262   if (status != RPC_S_OK)
263     return status;
264
265   status = RPCRT4_OpenClientConnection(NewConnection);
266   if (status != RPC_S_OK)
267   {
268     RPCRT4_DestroyConnection(NewConnection);
269     return status;
270   }
271  
272   /* we need to send a binding packet if we are client. */
273   if (!NewConnection->server) {
274     RpcPktHdr *hdr;
275     RpcPktHdr *response_hdr;
276     RPC_MESSAGE msg;
277
278     TRACE("sending bind request to server\n");
279
280     hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
281                                  RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
282                                  InterfaceId, TransferSyntax);
283
284     status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
285     RPCRT4_FreeHeader(hdr);
286     if (status != RPC_S_OK) {
287       RPCRT4_DestroyConnection(NewConnection);
288       return status;
289     }
290
291     status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
292     if (status != RPC_S_OK) {
293       ERR("receive failed\n");
294       RPCRT4_DestroyConnection(NewConnection);
295       return status;
296     }
297
298     if (response_hdr->common.ptype != PKT_BIND_ACK ||
299         response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
300       ERR("failed to bind for interface %s, %d.%d\n",
301         debugstr_guid(&InterfaceId->SyntaxGUID),
302         InterfaceId->SyntaxVersion.MajorVersion,
303         InterfaceId->SyntaxVersion.MinorVersion);
304       RPCRT4_FreeHeader(response_hdr);
305       RPCRT4_DestroyConnection(NewConnection);
306       return RPC_S_PROTOCOL_ERROR;
307     }
308
309     /* FIXME: do more checks? */
310
311     NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
312     NewConnection->ActiveInterface = *InterfaceId;
313     RPCRT4_FreeHeader(response_hdr);
314   }
315
316   if (Binding->server)
317     Binding->FromConn = NewConnection;
318   *Connection = NewConnection;
319
320   return RPC_S_OK;
321 }
322
323 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
324 {
325   TRACE("(Binding == ^%p)\n", Binding);
326   if (!Connection) return RPC_S_OK;
327   if (Binding->server) {
328     /* don't destroy a connection that is cached in the binding */
329     if (Binding->FromConn == Connection)
330       return RPC_S_OK;
331     return RPCRT4_DestroyConnection(Connection);
332   }
333   else {
334     RPCRT4_ReleaseIdleConnection(Connection);
335     return RPC_S_OK;
336   }
337 }
338
339 /* utility functions for string composing and parsing */
340 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
341 {
342   unsigned len = strlen(src);
343   memcpy(data, src, len*sizeof(CHAR));
344   return len;
345 }
346
347 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
348 {
349   unsigned len = strlenW(src);
350   memcpy(data, src, len*sizeof(WCHAR));
351   return len;
352 }
353
354 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
355 {
356   DWORD len = strlen(dst), slen = strlen(src);
357   LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
358   if (!ndst)
359   {
360     HeapFree(GetProcessHeap(), 0, dst);
361     return NULL;
362   }
363   ndst[len] = ',';
364   memcpy(ndst+len+1, src, slen+1);
365   return ndst;
366 }
367
368 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
369 {
370   DWORD len = strlenW(dst), slen = strlenW(src);
371   LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
372   if (!ndst) 
373   {
374     HeapFree(GetProcessHeap(), 0, dst);
375     return NULL;
376   }
377   ndst[len] = ',';
378   memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
379   return ndst;
380 }
381
382
383 /***********************************************************************
384  *             RpcStringBindingComposeA (RPCRT4.@)
385  */
386 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
387                                            RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
388                                            RPC_CSTR Options, RPC_CSTR *StringBinding )
389 {
390   DWORD len = 1;
391   LPSTR data;
392
393   TRACE( "(%s,%s,%s,%s,%s,%p)\n",
394         debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
395         debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
396         debugstr_a( (char*)Options ), StringBinding );
397
398   if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
399   if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
400   if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
401   if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
402   if (Options && *Options) len += strlen((char*)Options) + 2;
403
404   data = HeapAlloc(GetProcessHeap(), 0, len);
405   *StringBinding = (unsigned char*)data;
406
407   if (ObjUuid && *ObjUuid) {
408     data += RPCRT4_strcopyA(data, (char*)ObjUuid);
409     *data++ = '@';
410   }
411   if (Protseq && *Protseq) {
412     data += RPCRT4_strcopyA(data, (char*)Protseq);
413     *data++ = ':';
414   }
415   if (NetworkAddr && *NetworkAddr)
416     data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
417
418   if ((Endpoint && *Endpoint) ||
419       (Options && *Options)) {
420     *data++ = '[';
421     if (Endpoint && *Endpoint) {
422       data += RPCRT4_strcopyA(data, (char*)Endpoint);
423       if (Options && *Options) *data++ = ',';
424     }
425     if (Options && *Options) {
426       data += RPCRT4_strcopyA(data, (char*)Options);
427     }
428     *data++ = ']';
429   }
430   *data = 0;
431
432   return RPC_S_OK;
433 }
434
435 /***********************************************************************
436  *             RpcStringBindingComposeW (RPCRT4.@)
437  */
438 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
439                                             RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
440                                             RPC_WSTR Options, RPC_WSTR* StringBinding )
441 {
442   DWORD len = 1;
443   RPC_WSTR data;
444
445   TRACE("(%s,%s,%s,%s,%s,%p)\n",
446        debugstr_w( ObjUuid ), debugstr_w( Protseq ),
447        debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
448        debugstr_w( Options ), StringBinding);
449
450   if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
451   if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
452   if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
453   if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
454   if (Options && *Options) len += strlenW(Options) + 2;
455
456   data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
457   *StringBinding = data;
458
459   if (ObjUuid && *ObjUuid) {
460     data += RPCRT4_strcopyW(data, ObjUuid);
461     *data++ = '@';
462   }
463   if (Protseq && *Protseq) {
464     data += RPCRT4_strcopyW(data, Protseq);
465     *data++ = ':';
466   }
467   if (NetworkAddr && *NetworkAddr) {
468     data += RPCRT4_strcopyW(data, NetworkAddr);
469   }
470   if ((Endpoint && *Endpoint) ||
471       (Options && *Options)) {
472     *data++ = '[';
473     if (Endpoint && *Endpoint) {
474       data += RPCRT4_strcopyW(data, Endpoint);
475       if (Options && *Options) *data++ = ',';
476     }
477     if (Options && *Options) {
478       data += RPCRT4_strcopyW(data, Options);
479     }
480     *data++ = ']';
481   }
482   *data = 0;
483
484   return RPC_S_OK;
485 }
486
487
488 /***********************************************************************
489  *             RpcStringBindingParseA (RPCRT4.@)
490  */
491 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
492                                           RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
493                                           RPC_CSTR *Endpoint, RPC_CSTR *Options)
494 {
495   CHAR *data, *next;
496   static const char ep_opt[] = "endpoint=";
497
498   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
499        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
500
501   if (ObjUuid) *ObjUuid = NULL;
502   if (Protseq) *Protseq = NULL;
503   if (NetworkAddr) *NetworkAddr = NULL;
504   if (Endpoint) *Endpoint = NULL;
505   if (Options) *Options = NULL;
506
507   data = (char*) StringBinding;
508
509   next = strchr(data, '@');
510   if (next) {
511     if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
512     data = next+1;
513   }
514
515   next = strchr(data, ':');
516   if (next) {
517     if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
518     data = next+1;
519   }
520
521   next = strchr(data, '[');
522   if (next) {
523     CHAR *close, *opt;
524
525     if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
526     data = next+1;
527     close = strchr(data, ']');
528     if (!close) goto fail;
529
530     /* tokenize options */
531     while (data < close) {
532       next = strchr(data, ',');
533       if (!next || next > close) next = close;
534       /* FIXME: this is kind of inefficient */
535       opt = RPCRT4_strndupA(data, next - data);
536       data = next+1;
537
538       /* parse option */
539       next = strchr(opt, '=');
540       if (!next) {
541         /* not an option, must be an endpoint */
542         if (*Endpoint) goto fail;
543         *Endpoint = (unsigned char*) opt;
544       } else {
545         if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
546           /* endpoint option */
547           if (*Endpoint) goto fail;
548           *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
549           HeapFree(GetProcessHeap(), 0, opt);
550         } else {
551           /* network option */
552           if (*Options) {
553             /* FIXME: this is kind of inefficient */
554             *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
555             HeapFree(GetProcessHeap(), 0, opt);
556           } else 
557             *Options = (unsigned char*) opt;
558         }
559       }
560     }
561
562     data = close+1;
563     if (*data) goto fail;
564   }
565   else if (NetworkAddr) 
566     *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
567
568   return RPC_S_OK;
569
570 fail:
571   if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
572   if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
573   if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
574   if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
575   if (Options) RpcStringFreeA((unsigned char**)Options);
576   return RPC_S_INVALID_STRING_BINDING;
577 }
578
579 /***********************************************************************
580  *             RpcStringBindingParseW (RPCRT4.@)
581  */
582 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
583                                           RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
584                                           RPC_WSTR *Endpoint, RPC_WSTR *Options)
585 {
586   WCHAR *data, *next;
587   static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
588
589   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
590        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
591
592   if (ObjUuid) *ObjUuid = NULL;
593   if (Protseq) *Protseq = NULL;
594   if (NetworkAddr) *NetworkAddr = NULL;
595   if (Endpoint) *Endpoint = NULL;
596   if (Options) *Options = NULL;
597
598   data = StringBinding;
599
600   next = strchrW(data, '@');
601   if (next) {
602     if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
603     data = next+1;
604   }
605
606   next = strchrW(data, ':');
607   if (next) {
608     if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
609     data = next+1;
610   }
611
612   next = strchrW(data, '[');
613   if (next) {
614     WCHAR *close, *opt;
615
616     if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
617     data = next+1;
618     close = strchrW(data, ']');
619     if (!close) goto fail;
620
621     /* tokenize options */
622     while (data < close) {
623       next = strchrW(data, ',');
624       if (!next || next > close) next = close;
625       /* FIXME: this is kind of inefficient */
626       opt = RPCRT4_strndupW(data, next - data);
627       data = next+1;
628
629       /* parse option */
630       next = strchrW(opt, '=');
631       if (!next) {
632         /* not an option, must be an endpoint */
633         if (*Endpoint) goto fail;
634         *Endpoint = opt;
635       } else {
636         if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
637           /* endpoint option */
638           if (*Endpoint) goto fail;
639           *Endpoint = RPCRT4_strdupW(next+1);
640           HeapFree(GetProcessHeap(), 0, opt);
641         } else {
642           /* network option */
643           if (*Options) {
644             /* FIXME: this is kind of inefficient */
645             *Options = RPCRT4_strconcatW(*Options, opt);
646             HeapFree(GetProcessHeap(), 0, opt);
647           } else 
648             *Options = opt;
649         }
650       }
651     }
652
653     data = close+1;
654     if (*data) goto fail;
655   } else if (NetworkAddr) 
656     *NetworkAddr = RPCRT4_strdupW(data);
657
658   return RPC_S_OK;
659
660 fail:
661   if (ObjUuid) RpcStringFreeW(ObjUuid);
662   if (Protseq) RpcStringFreeW(Protseq);
663   if (NetworkAddr) RpcStringFreeW(NetworkAddr);
664   if (Endpoint) RpcStringFreeW(Endpoint);
665   if (Options) RpcStringFreeW(Options);
666   return RPC_S_INVALID_STRING_BINDING;
667 }
668
669 /***********************************************************************
670  *             RpcBindingFree (RPCRT4.@)
671  */
672 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
673 {
674   RPC_STATUS status;
675   TRACE("(%p) = %p\n", Binding, *Binding);
676   status = RPCRT4_DestroyBinding(*Binding);
677   if (status == RPC_S_OK) *Binding = 0;
678   return status;
679 }
680   
681 /***********************************************************************
682  *             RpcBindingVectorFree (RPCRT4.@)
683  */
684 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
685 {
686   RPC_STATUS status;
687   unsigned long c;
688
689   TRACE("(%p)\n", BindingVector);
690   for (c=0; c<(*BindingVector)->Count; c++) {
691     status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
692   }
693   HeapFree(GetProcessHeap(), 0, *BindingVector);
694   *BindingVector = NULL;
695   return RPC_S_OK;
696 }
697   
698 /***********************************************************************
699  *             RpcBindingInqObject (RPCRT4.@)
700  */
701 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
702 {
703   RpcBinding* bind = (RpcBinding*)Binding;
704
705   TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
706   memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
707   return RPC_S_OK;
708 }
709   
710 /***********************************************************************
711  *             RpcBindingSetObject (RPCRT4.@)
712  */
713 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
714 {
715   RpcBinding* bind = (RpcBinding*)Binding;
716
717   TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
718   if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
719   return RPCRT4_SetBindingObject(Binding, ObjectUuid);
720 }
721
722 /***********************************************************************
723  *             RpcBindingFromStringBindingA (RPCRT4.@)
724  */
725 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
726 {
727   RPC_STATUS ret;
728   RpcBinding* bind = NULL;
729   RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
730   UUID Uuid;
731
732   TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
733
734   ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
735                               &NetworkAddr, &Endpoint, &Options);
736   if (ret != RPC_S_OK) return ret;
737
738   ret = UuidFromStringA(ObjectUuid, &Uuid);
739
740   if (ret == RPC_S_OK)
741     ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
742   if (ret == RPC_S_OK)
743     ret = RPCRT4_SetBindingObject(bind, &Uuid);
744   if (ret == RPC_S_OK)
745     ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
746
747   RpcStringFreeA((unsigned char**)&Options);
748   RpcStringFreeA((unsigned char**)&Endpoint);
749   RpcStringFreeA((unsigned char**)&NetworkAddr);
750   RpcStringFreeA((unsigned char**)&Protseq);
751   RpcStringFreeA((unsigned char**)&ObjectUuid);
752
753   if (ret == RPC_S_OK) 
754     *Binding = (RPC_BINDING_HANDLE)bind;
755   else 
756     RPCRT4_DestroyBinding(bind);
757
758   return ret;
759 }
760
761 /***********************************************************************
762  *             RpcBindingFromStringBindingW (RPCRT4.@)
763  */
764 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
765 {
766   RPC_STATUS ret;
767   RpcBinding* bind = NULL;
768   RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
769   UUID Uuid;
770
771   TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
772
773   ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
774                               &NetworkAddr, &Endpoint, &Options);
775   if (ret != RPC_S_OK) return ret;
776
777   ret = UuidFromStringW(ObjectUuid, &Uuid);
778
779   if (ret == RPC_S_OK)
780     ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
781   if (ret == RPC_S_OK)
782     ret = RPCRT4_SetBindingObject(bind, &Uuid);
783   if (ret == RPC_S_OK)
784     ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
785
786   RpcStringFreeW(&Options);
787   RpcStringFreeW(&Endpoint);
788   RpcStringFreeW(&NetworkAddr);
789   RpcStringFreeW(&Protseq);
790   RpcStringFreeW(&ObjectUuid);
791
792   if (ret == RPC_S_OK)
793     *Binding = (RPC_BINDING_HANDLE)bind;
794   else
795     RPCRT4_DestroyBinding(bind);
796
797   return ret;
798 }
799   
800 /***********************************************************************
801  *             RpcBindingToStringBindingA (RPCRT4.@)
802  */
803 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
804 {
805   RPC_STATUS ret;
806   RpcBinding* bind = (RpcBinding*)Binding;
807   LPSTR ObjectUuid;
808
809   TRACE("(%p,%p)\n", Binding, StringBinding);
810
811   ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
812   if (ret != RPC_S_OK) return ret;
813
814   ret = RpcStringBindingComposeA((unsigned char*) ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
815                                  (unsigned char*) bind->Endpoint, NULL, StringBinding);
816
817   RpcStringFreeA((unsigned char**)&ObjectUuid);
818
819   return ret;
820 }
821   
822 /***********************************************************************
823  *             RpcBindingToStringBindingW (RPCRT4.@)
824  */
825 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
826 {
827   RPC_STATUS ret;
828   unsigned char *str = NULL;
829   TRACE("(%p,%p)\n", Binding, StringBinding);
830   ret = RpcBindingToStringBindingA(Binding, &str);
831   *StringBinding = RPCRT4_strdupAtoW((char*)str);
832   RpcStringFreeA((unsigned char**)&str);
833   return ret;
834 }
835
836 /***********************************************************************
837  *             I_RpcBindingSetAsync (RPCRT4.@)
838  * NOTES
839  *  Exists in win9x and winNT, but with different number of arguments
840  *  (9x version has 3 arguments, NT has 2).
841  */
842 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
843 {
844   RpcBinding* bind = (RpcBinding*)Binding;
845
846   TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
847
848   bind->BlockingFn = BlockingFn;
849
850   return RPC_S_OK;
851 }
852
853 /***********************************************************************
854  *             RpcBindingCopy (RPCRT4.@)
855  */
856 RPC_STATUS RPC_ENTRY RpcBindingCopy(
857   RPC_BINDING_HANDLE SourceBinding,
858   RPC_BINDING_HANDLE* DestinationBinding)
859 {
860   RpcBinding *DestBinding;
861   RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
862   RPC_STATUS status;
863
864   TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
865
866   status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
867   if (status != RPC_S_OK) return status;
868
869   DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
870   DestBinding->BlockingFn = SrcBinding->BlockingFn;
871   DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
872   DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
873   DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
874
875   if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
876   DestBinding->AuthInfo = SrcBinding->AuthInfo;
877
878   *DestinationBinding = DestBinding;
879   return RPC_S_OK;
880 }
881
882 /***********************************************************************
883  *             RpcImpersonateClient (RPCRT4.@)
884  *
885  * Impersonates the client connected via a binding handle so that security
886  * checks are done in the context of the client.
887  *
888  * PARAMS
889  *  BindingHandle [I] Handle to the binding to the client.
890  *
891  * RETURNS
892  *  Success: RPS_S_OK.
893  *  Failure: RPC_STATUS value.
894  *
895  * NOTES
896  *
897  * If BindingHandle is NULL then the function impersonates the client
898  * connected to the binding handle of the current thread.
899  */
900 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
901 {
902     FIXME("(%p): stub\n", BindingHandle);
903     ImpersonateSelf(SecurityImpersonation);
904     return RPC_S_OK;
905 }
906
907 /***********************************************************************
908  *             RpcRevertToSelfEx (RPCRT4.@)
909  *
910  * Stops impersonating the client connected to the binding handle so that security
911  * checks are no longer done in the context of the client.
912  *
913  * PARAMS
914  *  BindingHandle [I] Handle to the binding to the client.
915  *
916  * RETURNS
917  *  Success: RPS_S_OK.
918  *  Failure: RPC_STATUS value.
919  *
920  * NOTES
921  *
922  * If BindingHandle is NULL then the function stops impersonating the client
923  * connected to the binding handle of the current thread.
924  */
925 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
926 {
927     FIXME("(%p): stub\n", BindingHandle);
928     return RPC_S_OK;
929 }
930
931 static RPC_STATUS RpcAuthInfo_Create(unsigned long AuthnLevel, unsigned long AuthnSvc, CredHandle cred, TimeStamp exp, RpcAuthInfo **ret)
932 {
933     RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
934     if (!AuthInfo)
935         return ERROR_OUTOFMEMORY;
936
937     AuthInfo->AuthnLevel = AuthnLevel;
938     AuthInfo->AuthnSvc = AuthnSvc;
939     AuthInfo->cred = cred;
940     AuthInfo->exp = exp;
941     *ret = AuthInfo;
942     return RPC_S_OK;
943 }
944
945 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
946 {
947     return InterlockedIncrement(&AuthInfo->refs);
948 }
949
950 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
951 {
952     ULONG refs = InterlockedDecrement(&AuthInfo->refs);
953
954     if (!refs)
955     {
956         FreeCredentialsHandle(&AuthInfo->cred);
957         HeapFree(GetProcessHeap(), 0, AuthInfo);
958     }
959
960     return refs;
961 }
962
963 /***********************************************************************
964  *             RpcRevertToSelf (RPCRT4.@)
965  */
966 RPC_STATUS WINAPI RpcRevertToSelf(void)
967 {
968     FIXME("stub\n");
969     RevertToSelf();
970     return RPC_S_OK;
971 }
972
973 /***********************************************************************
974  *             RpcMgmtSetComTimeout (RPCRT4.@)
975  */
976 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
977 {
978     FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
979     return RPC_S_OK;
980 }
981
982 /***********************************************************************
983  *             RpcBindingInqAuthInfoExA (RPCRT4.@)
984  */
985 RPCRTAPI RPC_STATUS RPC_ENTRY
986 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
987                           unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
988                           unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
989 {
990     FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
991           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
992     return RPC_S_INVALID_BINDING;
993 }
994
995 /***********************************************************************
996  *             RpcBindingInqAuthInfoExW (RPCRT4.@)
997  */
998 RPCRTAPI RPC_STATUS RPC_ENTRY
999 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
1000                           unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc,
1001                           unsigned long RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1002 {
1003     FIXME("%p %p %p %p %p %p %lu %p\n", Binding, ServerPrincName, AuthnLevel,
1004           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1005     return RPC_S_INVALID_BINDING;
1006 }
1007
1008 /***********************************************************************
1009  *             RpcBindingInqAuthInfoA (RPCRT4.@)
1010  */
1011 RPCRTAPI RPC_STATUS RPC_ENTRY
1012 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, unsigned long *AuthnLevel,
1013                         unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1014 {
1015     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1016           AuthnSvc, AuthIdentity, AuthzSvc);
1017     return RPC_S_INVALID_BINDING;
1018 }
1019
1020 /***********************************************************************
1021  *             RpcBindingInqAuthInfoW (RPCRT4.@)
1022  */
1023 RPCRTAPI RPC_STATUS RPC_ENTRY
1024 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, unsigned long *AuthnLevel,
1025                         unsigned long *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, unsigned long *AuthzSvc )
1026 {
1027     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1028           AuthnSvc, AuthIdentity, AuthzSvc);
1029     return RPC_S_INVALID_BINDING;
1030 }
1031
1032 /***********************************************************************
1033  *             RpcBindingSetAuthInfoExA (RPCRT4.@)
1034  */
1035 RPCRTAPI RPC_STATUS RPC_ENTRY
1036 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1037                           unsigned long AuthnLevel, unsigned long AuthnSvc,
1038                           RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1039                           RPC_SECURITY_QOS *SecurityQos )
1040 {
1041   RpcBinding* bind = (RpcBinding*)Binding;
1042   SECURITY_STATUS r;
1043   CredHandle cred;
1044   TimeStamp exp;
1045   ULONG package_count;
1046   ULONG i;
1047   PSecPkgInfoA packages;
1048
1049   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1050         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1051
1052   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1053     AuthnSvc = RPC_C_AUTHN_WINNT;
1054
1055   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1056   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1057     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1058
1059   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1060   {
1061     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1062     bind->AuthInfo = NULL;
1063     return RPC_S_OK;
1064   }
1065
1066   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1067   {
1068     FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1069     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1070   }
1071
1072   if (AuthzSvr)
1073   {
1074     FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1075     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1076   }
1077
1078   if (SecurityQos)
1079     FIXME("SecurityQos ignored\n");
1080
1081   r = EnumerateSecurityPackagesA(&package_count, &packages);
1082   if (r != SEC_E_OK)
1083   {
1084     ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1085     return RPC_S_SEC_PKG_ERROR;
1086   }
1087
1088   for (i = 0; i < package_count; i++)
1089     if (packages[i].wRPCID == AuthnSvc)
1090         break;
1091
1092   if (i == package_count)
1093   {
1094     FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1095     FreeContextBuffer(packages);
1096     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1097   }
1098
1099   TRACE("found package %s for service %ld\n", packages[i].Name, AuthnSvc);
1100   r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1101                                 AuthIdentity, NULL, NULL, &cred, &exp);
1102   FreeContextBuffer(packages);
1103   if (r == ERROR_SUCCESS)
1104   {
1105     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1106     bind->AuthInfo = NULL;
1107     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1108     if (r != RPC_S_OK)
1109       FreeCredentialsHandle(&cred);
1110     return RPC_S_OK;
1111   }
1112   else
1113   {
1114     ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1115     return RPC_S_SEC_PKG_ERROR;
1116   }
1117 }
1118
1119 /***********************************************************************
1120  *             RpcBindingSetAuthInfoExW (RPCRT4.@)
1121  */
1122 RPCRTAPI RPC_STATUS RPC_ENTRY
1123 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1124                           unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr,
1125                           RPC_SECURITY_QOS *SecurityQos )
1126 {
1127   RpcBinding* bind = (RpcBinding*)Binding;
1128   SECURITY_STATUS r;
1129   CredHandle cred;
1130   TimeStamp exp;
1131   ULONG package_count;
1132   ULONG i;
1133   PSecPkgInfoW packages;
1134
1135   TRACE("%p %s %lu %lu %p %lu %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1136         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1137
1138   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1139     AuthnSvc = RPC_C_AUTHN_WINNT;
1140
1141   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1142   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1143     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1144
1145   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1146   {
1147     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1148     bind->AuthInfo = NULL;
1149     return RPC_S_OK;
1150   }
1151
1152   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1153   {
1154     FIXME("unknown AuthnLevel %lu\n", AuthnLevel);
1155     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1156   }
1157
1158   if (AuthzSvr)
1159   {
1160     FIXME("unsupported AuthzSvr %lu\n", AuthzSvr);
1161     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1162   }
1163
1164   if (SecurityQos)
1165     FIXME("SecurityQos ignored\n");
1166
1167   r = EnumerateSecurityPackagesW(&package_count, &packages);
1168   if (r != SEC_E_OK)
1169   {
1170     ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1171     return RPC_S_SEC_PKG_ERROR;
1172   }
1173
1174   for (i = 0; i < package_count; i++)
1175     if (packages[i].wRPCID == AuthnSvc)
1176         break;
1177
1178   if (i == package_count)
1179   {
1180     FIXME("unsupported AuthnSvc %lu\n", AuthnSvc);
1181     FreeContextBuffer(packages);
1182     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1183   }
1184
1185   TRACE("found package %s for service %ld\n", debugstr_w(packages[i].Name), AuthnSvc);
1186   r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1187                                 AuthIdentity, NULL, NULL, &cred, &exp);
1188   FreeContextBuffer(packages);
1189   if (r == ERROR_SUCCESS)
1190   {
1191     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1192     bind->AuthInfo = NULL;
1193     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, &bind->AuthInfo);
1194     if (r != RPC_S_OK)
1195       FreeCredentialsHandle(&cred);
1196     return RPC_S_OK;
1197   }
1198   else
1199   {
1200     ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1201     return RPC_S_SEC_PKG_ERROR;
1202   }
1203 }
1204
1205 /***********************************************************************
1206  *             RpcBindingSetAuthInfoA (RPCRT4.@)
1207  */
1208 RPCRTAPI RPC_STATUS RPC_ENTRY
1209 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, unsigned long AuthnLevel,
1210                         unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1211 {
1212     TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_a((const char*)ServerPrincName),
1213           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1214     return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1215 }
1216
1217 /***********************************************************************
1218  *             RpcBindingSetAuthInfoW (RPCRT4.@)
1219  */
1220 RPCRTAPI RPC_STATUS RPC_ENTRY
1221 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, unsigned long AuthnLevel,
1222                         unsigned long AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, unsigned long AuthzSvr )
1223 {
1224     TRACE("%p %s %lu %lu %p %lu\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1225           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1226     return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1227 }
1228
1229 /***********************************************************************
1230  *             RpcBindingSetOption (RPCRT4.@)
1231  */
1232 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1233 {
1234     FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue);
1235     return RPC_S_OK;
1236 }