rpcrt4: Remove the unused AuthInfo field from the RpcAssoc structure and Used from...
[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 "winternl.h"
34 #include "wine/unicode.h"
35
36 #include "rpc.h"
37 #include "rpcndr.h"
38
39 #include "wine/debug.h"
40
41 #include "rpc_binding.h"
42 #include "rpc_message.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
45
46 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
47 {
48   DWORD len;
49   LPSTR s;
50   if (!src) return NULL;
51   if (slen == -1) slen = strlen(src);
52   len = slen;
53   s = HeapAlloc(GetProcessHeap(), 0, len+1);
54   memcpy(s, src, len);
55   s[len] = 0;
56   return s;
57 }
58
59 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
60 {
61   DWORD len;
62   LPSTR s;
63   if (!src) return NULL;
64   len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
65   s = HeapAlloc(GetProcessHeap(), 0, len);
66   WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
67   return s;
68 }
69
70 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
71 {
72   DWORD len;
73   LPWSTR s;
74   if (!src) return NULL;
75   len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
76   s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
77   MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
78   return s;
79 }
80
81 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
82 {
83   DWORD len;
84   LPWSTR s;
85   if (!src) return NULL;
86   len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
87   s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
88   MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
89   return s;
90 }
91
92 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
93 {
94   DWORD len;
95   LPWSTR s;
96   if (!src) return NULL;
97   if (slen == -1) slen = strlenW(src);
98   len = slen;
99   s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
100   memcpy(s, src, len*sizeof(WCHAR));
101   s[len] = 0;
102   return s;
103 }
104
105 void RPCRT4_strfree(LPSTR src)
106 {
107   HeapFree(GetProcessHeap(), 0, src);
108 }
109
110 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
111 {
112   RpcBinding* NewBinding;
113
114   NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
115   NewBinding->refs = 1;
116   NewBinding->server = server;
117
118   *Binding = NewBinding;
119
120   return RPC_S_OK;
121 }
122
123 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
124 {
125   RpcBinding* NewBinding;
126
127   RPCRT4_AllocBinding(&NewBinding, server);
128   NewBinding->Protseq = RPCRT4_strdupA(Protseq);
129
130   TRACE("binding: %p\n", NewBinding);
131   *Binding = NewBinding;
132
133   return RPC_S_OK;
134 }
135
136 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
137 {
138   RpcBinding* NewBinding;
139
140   RPCRT4_AllocBinding(&NewBinding, server);
141   NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
142
143   TRACE("binding: %p\n", NewBinding);
144   *Binding = NewBinding;
145
146   return RPC_S_OK;
147 }
148
149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
150                                           LPCSTR Endpoint, LPCSTR NetworkOptions)
151 {
152   RPC_STATUS status;
153
154   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
155    debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
156
157   RPCRT4_strfree(Binding->NetworkAddr);
158   Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
159   RPCRT4_strfree(Binding->Endpoint);
160   if (Endpoint) {
161     Binding->Endpoint = RPCRT4_strdupA(Endpoint);
162   } else {
163     Binding->Endpoint = RPCRT4_strdupA("");
164   }
165   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
166   Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
167   if (!Binding->Endpoint) ERR("out of memory?\n");
168
169   status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
170                                  Binding->Endpoint, Binding->NetworkOptions,
171                                  &Binding->Assoc);
172   if (status != RPC_S_OK)
173       return status;
174
175   return RPC_S_OK;
176 }
177
178 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
179                                           LPCWSTR Endpoint, LPCWSTR NetworkOptions)
180 {
181   RPC_STATUS status;
182
183   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, 
184    debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
185
186   RPCRT4_strfree(Binding->NetworkAddr);
187   Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
188   RPCRT4_strfree(Binding->Endpoint);
189   if (Endpoint) {
190     Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
191   } else {
192     Binding->Endpoint = RPCRT4_strdupA("");
193   }
194   if (!Binding->Endpoint) ERR("out of memory?\n");
195   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
196   Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
197
198   status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
199                                  Binding->Endpoint, Binding->NetworkOptions,
200                                  &Binding->Assoc);
201   if (status != RPC_S_OK)
202       return status;
203
204   return RPC_S_OK;
205 }
206
207 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
208 {
209   RPC_STATUS status;
210
211   TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
212
213   RPCRT4_strfree(Binding->Endpoint);
214   Binding->Endpoint = RPCRT4_strdupA(Endpoint);
215
216   RpcAssoc_Release(Binding->Assoc);
217   Binding->Assoc = NULL;
218   status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
219                                  Binding->Endpoint, Binding->NetworkOptions,
220                                  &Binding->Assoc);
221   if (status != RPC_S_OK)
222       return status;
223
224   return RPC_S_OK;
225 }
226
227 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
228 {
229   TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); 
230   if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
231   else UuidCreateNil(&Binding->ObjectUuid);
232   return RPC_S_OK;
233 }
234
235 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
236 {
237   RpcBinding* NewBinding;
238   TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
239
240   RPCRT4_AllocBinding(&NewBinding, Connection->server);
241   NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
242   NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
243   NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
244   NewBinding->FromConn = Connection;
245
246   TRACE("binding: %p\n", NewBinding);
247   *Binding = NewBinding;
248
249   return RPC_S_OK;
250 }
251
252 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
253 {
254   InterlockedIncrement(&OldBinding->refs);
255   *Binding = OldBinding;
256   return RPC_S_OK;
257 }
258
259 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
260 {
261   if (InterlockedDecrement(&Binding->refs))
262     return RPC_S_OK;
263
264   TRACE("binding: %p\n", Binding);
265   if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
266   RPCRT4_strfree(Binding->Endpoint);
267   RPCRT4_strfree(Binding->NetworkAddr);
268   RPCRT4_strfree(Binding->Protseq);
269   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
270   if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
271   if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
272   HeapFree(GetProcessHeap(), 0, Binding);
273   return RPC_S_OK;
274 }
275
276 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
277                               PRPC_SYNTAX_IDENTIFIER TransferSyntax,
278                               PRPC_SYNTAX_IDENTIFIER InterfaceId)
279 {
280   RpcConnection* NewConnection;
281   RPC_STATUS status;
282
283   TRACE("(Binding == ^%p)\n", Binding);
284
285   if (!Binding->server) {
286     /* try to find a compatible connection from the connection pool */
287     NewConnection = RpcAssoc_GetIdleConnection(Binding->Assoc, InterfaceId,
288         TransferSyntax, Binding->AuthInfo, Binding->QOS);
289     if (NewConnection) {
290       *Connection = NewConnection;
291       return RPC_S_OK;
292     }
293   } else {
294     /* we already have a connection with acceptable binding, so use it */
295     if (Binding->FromConn) {
296       *Connection = Binding->FromConn;
297       return RPC_S_OK;
298     }
299   }
300   
301   /* create a new connection */
302   status = RPCRT4_CreateConnection(&NewConnection, Binding->server,
303                                    Binding->Protseq, Binding->NetworkAddr,
304                                    Binding->Endpoint, Binding->NetworkOptions,
305                                    Binding->AuthInfo, Binding->QOS);
306   if (status != RPC_S_OK)
307     return status;
308
309   status = RPCRT4_OpenClientConnection(NewConnection);
310   if (status != RPC_S_OK)
311   {
312     RPCRT4_DestroyConnection(NewConnection);
313     return status;
314   }
315  
316   /* we need to send a binding packet if we are client. */
317   if (!NewConnection->server) {
318     RpcPktHdr *hdr;
319     RpcPktHdr *response_hdr;
320     RPC_MESSAGE msg;
321
322     TRACE("sending bind request to server\n");
323
324     hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
325                                  RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
326                                  Binding->Assoc->assoc_group_id,
327                                  InterfaceId, TransferSyntax);
328
329     status = RPCRT4_Send(NewConnection, hdr, NULL, 0);
330     RPCRT4_FreeHeader(hdr);
331     if (status != RPC_S_OK) {
332       RPCRT4_DestroyConnection(NewConnection);
333       return status;
334     }
335
336     status = RPCRT4_Receive(NewConnection, &response_hdr, &msg);
337     if (status != RPC_S_OK) {
338       ERR("receive failed\n");
339       RPCRT4_DestroyConnection(NewConnection);
340       return status;
341     }
342
343     if (response_hdr->common.ptype != PKT_BIND_ACK ||
344         response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) {
345       ERR("failed to bind for interface %s, %d.%d\n",
346         debugstr_guid(&InterfaceId->SyntaxGUID),
347         InterfaceId->SyntaxVersion.MajorVersion,
348         InterfaceId->SyntaxVersion.MinorVersion);
349       RPCRT4_FreeHeader(response_hdr);
350       RPCRT4_DestroyConnection(NewConnection);
351       return RPC_S_PROTOCOL_ERROR;
352     }
353
354     /* FIXME: do more checks? */
355
356     NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
357     NewConnection->ActiveInterface = *InterfaceId;
358     RPCRT4_FreeHeader(response_hdr);
359   }
360
361   if (Binding->server)
362     Binding->FromConn = NewConnection;
363   *Connection = NewConnection;
364
365   return RPC_S_OK;
366 }
367
368 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
369 {
370   TRACE("(Binding == ^%p)\n", Binding);
371   if (!Connection) return RPC_S_OK;
372   if (Binding->server) {
373     /* don't destroy a connection that is cached in the binding */
374     if (Binding->FromConn == Connection)
375       return RPC_S_OK;
376     return RPCRT4_DestroyConnection(Connection);
377   }
378   else {
379     RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
380     return RPC_S_OK;
381   }
382 }
383
384 /* utility functions for string composing and parsing */
385 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
386 {
387   unsigned len = strlen(src);
388   memcpy(data, src, len*sizeof(CHAR));
389   return len;
390 }
391
392 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
393 {
394   unsigned len = strlenW(src);
395   memcpy(data, src, len*sizeof(WCHAR));
396   return len;
397 }
398
399 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
400 {
401   DWORD len = strlen(dst), slen = strlen(src);
402   LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
403   if (!ndst)
404   {
405     HeapFree(GetProcessHeap(), 0, dst);
406     return NULL;
407   }
408   ndst[len] = ',';
409   memcpy(ndst+len+1, src, slen+1);
410   return ndst;
411 }
412
413 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
414 {
415   DWORD len = strlenW(dst), slen = strlenW(src);
416   LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
417   if (!ndst) 
418   {
419     HeapFree(GetProcessHeap(), 0, dst);
420     return NULL;
421   }
422   ndst[len] = ',';
423   memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
424   return ndst;
425 }
426
427
428 /***********************************************************************
429  *             RpcStringBindingComposeA (RPCRT4.@)
430  */
431 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
432                                            RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
433                                            RPC_CSTR Options, RPC_CSTR *StringBinding )
434 {
435   DWORD len = 1;
436   LPSTR data;
437
438   TRACE( "(%s,%s,%s,%s,%s,%p)\n",
439         debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
440         debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
441         debugstr_a( (char*)Options ), StringBinding );
442
443   if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1;
444   if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1;
445   if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr);
446   if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2;
447   if (Options && *Options) len += strlen((char*)Options) + 2;
448
449   data = HeapAlloc(GetProcessHeap(), 0, len);
450   *StringBinding = (unsigned char*)data;
451
452   if (ObjUuid && *ObjUuid) {
453     data += RPCRT4_strcopyA(data, (char*)ObjUuid);
454     *data++ = '@';
455   }
456   if (Protseq && *Protseq) {
457     data += RPCRT4_strcopyA(data, (char*)Protseq);
458     *data++ = ':';
459   }
460   if (NetworkAddr && *NetworkAddr)
461     data += RPCRT4_strcopyA(data, (char*)NetworkAddr);
462
463   if ((Endpoint && *Endpoint) ||
464       (Options && *Options)) {
465     *data++ = '[';
466     if (Endpoint && *Endpoint) {
467       data += RPCRT4_strcopyA(data, (char*)Endpoint);
468       if (Options && *Options) *data++ = ',';
469     }
470     if (Options && *Options) {
471       data += RPCRT4_strcopyA(data, (char*)Options);
472     }
473     *data++ = ']';
474   }
475   *data = 0;
476
477   return RPC_S_OK;
478 }
479
480 /***********************************************************************
481  *             RpcStringBindingComposeW (RPCRT4.@)
482  */
483 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
484                                             RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
485                                             RPC_WSTR Options, RPC_WSTR* StringBinding )
486 {
487   DWORD len = 1;
488   RPC_WSTR data;
489
490   TRACE("(%s,%s,%s,%s,%s,%p)\n",
491        debugstr_w( ObjUuid ), debugstr_w( Protseq ),
492        debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
493        debugstr_w( Options ), StringBinding);
494
495   if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
496   if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
497   if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
498   if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
499   if (Options && *Options) len += strlenW(Options) + 2;
500
501   data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
502   *StringBinding = data;
503
504   if (ObjUuid && *ObjUuid) {
505     data += RPCRT4_strcopyW(data, ObjUuid);
506     *data++ = '@';
507   }
508   if (Protseq && *Protseq) {
509     data += RPCRT4_strcopyW(data, Protseq);
510     *data++ = ':';
511   }
512   if (NetworkAddr && *NetworkAddr) {
513     data += RPCRT4_strcopyW(data, NetworkAddr);
514   }
515   if ((Endpoint && *Endpoint) ||
516       (Options && *Options)) {
517     *data++ = '[';
518     if (Endpoint && *Endpoint) {
519       data += RPCRT4_strcopyW(data, Endpoint);
520       if (Options && *Options) *data++ = ',';
521     }
522     if (Options && *Options) {
523       data += RPCRT4_strcopyW(data, Options);
524     }
525     *data++ = ']';
526   }
527   *data = 0;
528
529   return RPC_S_OK;
530 }
531
532
533 /***********************************************************************
534  *             RpcStringBindingParseA (RPCRT4.@)
535  */
536 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
537                                           RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
538                                           RPC_CSTR *Endpoint, RPC_CSTR *Options)
539 {
540   CHAR *data, *next;
541   static const char ep_opt[] = "endpoint=";
542
543   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
544        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
545
546   if (ObjUuid) *ObjUuid = NULL;
547   if (Protseq) *Protseq = NULL;
548   if (NetworkAddr) *NetworkAddr = NULL;
549   if (Endpoint) *Endpoint = NULL;
550   if (Options) *Options = NULL;
551
552   data = (char*) StringBinding;
553
554   next = strchr(data, '@');
555   if (next) {
556     if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data);
557     data = next+1;
558   }
559
560   next = strchr(data, ':');
561   if (next) {
562     if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data);
563     data = next+1;
564   }
565
566   next = strchr(data, '[');
567   if (next) {
568     CHAR *close, *opt;
569
570     if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data);
571     data = next+1;
572     close = strchr(data, ']');
573     if (!close) goto fail;
574
575     /* tokenize options */
576     while (data < close) {
577       next = strchr(data, ',');
578       if (!next || next > close) next = close;
579       /* FIXME: this is kind of inefficient */
580       opt = RPCRT4_strndupA(data, next - data);
581       data = next+1;
582
583       /* parse option */
584       next = strchr(opt, '=');
585       if (!next) {
586         /* not an option, must be an endpoint */
587         if (*Endpoint) goto fail;
588         *Endpoint = (unsigned char*) opt;
589       } else {
590         if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
591           /* endpoint option */
592           if (*Endpoint) goto fail;
593           *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1);
594           HeapFree(GetProcessHeap(), 0, opt);
595         } else {
596           /* network option */
597           if (*Options) {
598             /* FIXME: this is kind of inefficient */
599             *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt);
600             HeapFree(GetProcessHeap(), 0, opt);
601           } else 
602             *Options = (unsigned char*) opt;
603         }
604       }
605     }
606
607     data = close+1;
608     if (*data) goto fail;
609   }
610   else if (NetworkAddr) 
611     *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data);
612
613   return RPC_S_OK;
614
615 fail:
616   if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
617   if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
618   if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
619   if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
620   if (Options) RpcStringFreeA((unsigned char**)Options);
621   return RPC_S_INVALID_STRING_BINDING;
622 }
623
624 /***********************************************************************
625  *             RpcStringBindingParseW (RPCRT4.@)
626  */
627 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
628                                           RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
629                                           RPC_WSTR *Endpoint, RPC_WSTR *Options)
630 {
631   WCHAR *data, *next;
632   static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
633
634   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
635        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
636
637   if (ObjUuid) *ObjUuid = NULL;
638   if (Protseq) *Protseq = NULL;
639   if (NetworkAddr) *NetworkAddr = NULL;
640   if (Endpoint) *Endpoint = NULL;
641   if (Options) *Options = NULL;
642
643   data = StringBinding;
644
645   next = strchrW(data, '@');
646   if (next) {
647     if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
648     data = next+1;
649   }
650
651   next = strchrW(data, ':');
652   if (next) {
653     if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
654     data = next+1;
655   }
656
657   next = strchrW(data, '[');
658   if (next) {
659     WCHAR *close, *opt;
660
661     if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
662     data = next+1;
663     close = strchrW(data, ']');
664     if (!close) goto fail;
665
666     /* tokenize options */
667     while (data < close) {
668       next = strchrW(data, ',');
669       if (!next || next > close) next = close;
670       /* FIXME: this is kind of inefficient */
671       opt = RPCRT4_strndupW(data, next - data);
672       data = next+1;
673
674       /* parse option */
675       next = strchrW(opt, '=');
676       if (!next) {
677         /* not an option, must be an endpoint */
678         if (*Endpoint) goto fail;
679         *Endpoint = opt;
680       } else {
681         if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
682           /* endpoint option */
683           if (*Endpoint) goto fail;
684           *Endpoint = RPCRT4_strdupW(next+1);
685           HeapFree(GetProcessHeap(), 0, opt);
686         } else {
687           /* network option */
688           if (*Options) {
689             /* FIXME: this is kind of inefficient */
690             *Options = RPCRT4_strconcatW(*Options, opt);
691             HeapFree(GetProcessHeap(), 0, opt);
692           } else 
693             *Options = opt;
694         }
695       }
696     }
697
698     data = close+1;
699     if (*data) goto fail;
700   } else if (NetworkAddr) 
701     *NetworkAddr = RPCRT4_strdupW(data);
702
703   return RPC_S_OK;
704
705 fail:
706   if (ObjUuid) RpcStringFreeW(ObjUuid);
707   if (Protseq) RpcStringFreeW(Protseq);
708   if (NetworkAddr) RpcStringFreeW(NetworkAddr);
709   if (Endpoint) RpcStringFreeW(Endpoint);
710   if (Options) RpcStringFreeW(Options);
711   return RPC_S_INVALID_STRING_BINDING;
712 }
713
714 /***********************************************************************
715  *             RpcBindingFree (RPCRT4.@)
716  */
717 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
718 {
719   RPC_STATUS status;
720   TRACE("(%p) = %p\n", Binding, *Binding);
721   status = RPCRT4_DestroyBinding(*Binding);
722   if (status == RPC_S_OK) *Binding = 0;
723   return status;
724 }
725   
726 /***********************************************************************
727  *             RpcBindingVectorFree (RPCRT4.@)
728  */
729 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
730 {
731   RPC_STATUS status;
732   unsigned long c;
733
734   TRACE("(%p)\n", BindingVector);
735   for (c=0; c<(*BindingVector)->Count; c++) {
736     status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
737   }
738   HeapFree(GetProcessHeap(), 0, *BindingVector);
739   *BindingVector = NULL;
740   return RPC_S_OK;
741 }
742   
743 /***********************************************************************
744  *             RpcBindingInqObject (RPCRT4.@)
745  */
746 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
747 {
748   RpcBinding* bind = (RpcBinding*)Binding;
749
750   TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
751   memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
752   return RPC_S_OK;
753 }
754   
755 /***********************************************************************
756  *             RpcBindingSetObject (RPCRT4.@)
757  */
758 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
759 {
760   RpcBinding* bind = (RpcBinding*)Binding;
761
762   TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
763   if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
764   return RPCRT4_SetBindingObject(Binding, ObjectUuid);
765 }
766
767 /***********************************************************************
768  *             RpcBindingFromStringBindingA (RPCRT4.@)
769  */
770 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
771 {
772   RPC_STATUS ret;
773   RpcBinding* bind = NULL;
774   RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
775   UUID Uuid;
776
777   TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
778
779   ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
780                               &NetworkAddr, &Endpoint, &Options);
781   if (ret != RPC_S_OK) return ret;
782
783   ret = UuidFromStringA(ObjectUuid, &Uuid);
784
785   if (ret == RPC_S_OK)
786     ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
787   if (ret == RPC_S_OK)
788     ret = RPCRT4_SetBindingObject(bind, &Uuid);
789   if (ret == RPC_S_OK)
790     ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
791
792   RpcStringFreeA((unsigned char**)&Options);
793   RpcStringFreeA((unsigned char**)&Endpoint);
794   RpcStringFreeA((unsigned char**)&NetworkAddr);
795   RpcStringFreeA((unsigned char**)&Protseq);
796   RpcStringFreeA((unsigned char**)&ObjectUuid);
797
798   if (ret == RPC_S_OK) 
799     *Binding = (RPC_BINDING_HANDLE)bind;
800   else 
801     RPCRT4_DestroyBinding(bind);
802
803   return ret;
804 }
805
806 /***********************************************************************
807  *             RpcBindingFromStringBindingW (RPCRT4.@)
808  */
809 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
810 {
811   RPC_STATUS ret;
812   RpcBinding* bind = NULL;
813   RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
814   UUID Uuid;
815
816   TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
817
818   ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
819                               &NetworkAddr, &Endpoint, &Options);
820   if (ret != RPC_S_OK) return ret;
821
822   ret = UuidFromStringW(ObjectUuid, &Uuid);
823
824   if (ret == RPC_S_OK)
825     ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
826   if (ret == RPC_S_OK)
827     ret = RPCRT4_SetBindingObject(bind, &Uuid);
828   if (ret == RPC_S_OK)
829     ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
830
831   RpcStringFreeW(&Options);
832   RpcStringFreeW(&Endpoint);
833   RpcStringFreeW(&NetworkAddr);
834   RpcStringFreeW(&Protseq);
835   RpcStringFreeW(&ObjectUuid);
836
837   if (ret == RPC_S_OK)
838     *Binding = (RPC_BINDING_HANDLE)bind;
839   else
840     RPCRT4_DestroyBinding(bind);
841
842   return ret;
843 }
844   
845 /***********************************************************************
846  *             RpcBindingToStringBindingA (RPCRT4.@)
847  */
848 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
849 {
850   RPC_STATUS ret;
851   RpcBinding* bind = (RpcBinding*)Binding;
852   RPC_CSTR ObjectUuid;
853
854   TRACE("(%p,%p)\n", Binding, StringBinding);
855
856   ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
857   if (ret != RPC_S_OK) return ret;
858
859   ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
860                                  (unsigned char*) bind->Endpoint, NULL, StringBinding);
861
862   RpcStringFreeA(&ObjectUuid);
863
864   return ret;
865 }
866   
867 /***********************************************************************
868  *             RpcBindingToStringBindingW (RPCRT4.@)
869  */
870 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
871 {
872   RPC_STATUS ret;
873   unsigned char *str = NULL;
874   TRACE("(%p,%p)\n", Binding, StringBinding);
875   ret = RpcBindingToStringBindingA(Binding, &str);
876   *StringBinding = RPCRT4_strdupAtoW((char*)str);
877   RpcStringFreeA((unsigned char**)&str);
878   return ret;
879 }
880
881 /***********************************************************************
882  *             I_RpcBindingSetAsync (RPCRT4.@)
883  * NOTES
884  *  Exists in win9x and winNT, but with different number of arguments
885  *  (9x version has 3 arguments, NT has 2).
886  */
887 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
888 {
889   RpcBinding* bind = (RpcBinding*)Binding;
890
891   TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
892
893   bind->BlockingFn = BlockingFn;
894
895   return RPC_S_OK;
896 }
897
898 /***********************************************************************
899  *             RpcBindingCopy (RPCRT4.@)
900  */
901 RPC_STATUS RPC_ENTRY RpcBindingCopy(
902   RPC_BINDING_HANDLE SourceBinding,
903   RPC_BINDING_HANDLE* DestinationBinding)
904 {
905   RpcBinding *DestBinding;
906   RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
907   RPC_STATUS status;
908
909   TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
910
911   status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
912   if (status != RPC_S_OK) return status;
913
914   DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
915   DestBinding->BlockingFn = SrcBinding->BlockingFn;
916   DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
917   DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
918   DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
919   DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
920   if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
921   DestBinding->Assoc = SrcBinding->Assoc;
922
923   if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
924   DestBinding->AuthInfo = SrcBinding->AuthInfo;
925   if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
926   DestBinding->QOS = SrcBinding->QOS;
927
928   *DestinationBinding = DestBinding;
929   return RPC_S_OK;
930 }
931
932 /***********************************************************************
933  *             RpcImpersonateClient (RPCRT4.@)
934  *
935  * Impersonates the client connected via a binding handle so that security
936  * checks are done in the context of the client.
937  *
938  * PARAMS
939  *  BindingHandle [I] Handle to the binding to the client.
940  *
941  * RETURNS
942  *  Success: RPS_S_OK.
943  *  Failure: RPC_STATUS value.
944  *
945  * NOTES
946  *
947  * If BindingHandle is NULL then the function impersonates the client
948  * connected to the binding handle of the current thread.
949  */
950 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
951 {
952     FIXME("(%p): stub\n", BindingHandle);
953     ImpersonateSelf(SecurityImpersonation);
954     return RPC_S_OK;
955 }
956
957 /***********************************************************************
958  *             RpcRevertToSelfEx (RPCRT4.@)
959  *
960  * Stops impersonating the client connected to the binding handle so that security
961  * checks are no longer done in the context of the client.
962  *
963  * PARAMS
964  *  BindingHandle [I] Handle to the binding to the client.
965  *
966  * RETURNS
967  *  Success: RPS_S_OK.
968  *  Failure: RPC_STATUS value.
969  *
970  * NOTES
971  *
972  * If BindingHandle is NULL then the function stops impersonating the client
973  * connected to the binding handle of the current thread.
974  */
975 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
976 {
977     FIXME("(%p): stub\n", BindingHandle);
978     return RPC_S_OK;
979 }
980
981 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
982 {
983     switch (AuthnLevel)
984     {
985     case RPC_C_AUTHN_GSS_NEGOTIATE:
986     case RPC_C_AUTHN_WINNT:
987     case RPC_C_AUTHN_GSS_KERBEROS:
988         return TRUE;
989     default:
990         return FALSE;
991     }
992 }
993
994 static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
995                                      CredHandle cred, TimeStamp exp,
996                                      ULONG cbMaxToken,
997                                      RPC_AUTH_IDENTITY_HANDLE identity,
998                                      RpcAuthInfo **ret)
999 {
1000     RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1001     if (!AuthInfo)
1002         return ERROR_OUTOFMEMORY;
1003
1004     AuthInfo->refs = 1;
1005     AuthInfo->AuthnLevel = AuthnLevel;
1006     AuthInfo->AuthnSvc = AuthnSvc;
1007     AuthInfo->cred = cred;
1008     AuthInfo->exp = exp;
1009     AuthInfo->cbMaxToken = cbMaxToken;
1010     AuthInfo->identity = identity;
1011
1012     /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1013      * enable better matching in RpcAuthInfo_IsEqual */
1014     if (identity && has_nt_auth_identity(AuthnSvc))
1015     {
1016         const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1017         AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1018         if (!AuthInfo->nt_identity)
1019         {
1020             HeapFree(GetProcessHeap(), 0, AuthInfo);
1021             return ERROR_OUTOFMEMORY;
1022         }
1023
1024         AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1025         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1026             AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1027         else
1028             AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1029         AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1030         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1031             AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1032         else
1033             AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1034         AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1035         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1036             AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1037         else
1038             AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1039         AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1040
1041         if (!AuthInfo->nt_identity->User ||
1042             !AuthInfo->nt_identity->Domain ||
1043             !AuthInfo->nt_identity->Password)
1044         {
1045             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1046             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1047             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1048             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1049             HeapFree(GetProcessHeap(), 0, AuthInfo);
1050             return ERROR_OUTOFMEMORY;
1051         }
1052     }
1053     else
1054         AuthInfo->nt_identity = NULL;
1055     *ret = AuthInfo;
1056     return RPC_S_OK;
1057 }
1058
1059 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1060 {
1061     return InterlockedIncrement(&AuthInfo->refs);
1062 }
1063
1064 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1065 {
1066     ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1067
1068     if (!refs)
1069     {
1070         FreeCredentialsHandle(&AuthInfo->cred);
1071         if (AuthInfo->nt_identity)
1072         {
1073             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1074             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1075             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1076             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1077         }
1078         HeapFree(GetProcessHeap(), 0, AuthInfo);
1079     }
1080
1081     return refs;
1082 }
1083
1084 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1085 {
1086     if (AuthInfo1 == AuthInfo2)
1087         return TRUE;
1088
1089     if (!AuthInfo1 || !AuthInfo2)
1090         return FALSE;
1091
1092     if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1093         (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1094         return FALSE;
1095
1096     if (AuthInfo1->identity == AuthInfo2->identity)
1097         return TRUE;
1098
1099     if (!AuthInfo1->identity || !AuthInfo2->identity)
1100         return FALSE;
1101
1102     if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1103     {
1104         const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1105         const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1106         /* compare user names */
1107         if (identity1->UserLength != identity2->UserLength ||
1108             memcmp(identity1->User, identity2->User, identity1->UserLength))
1109             return FALSE;
1110         /* compare domain names */
1111         if (identity1->DomainLength != identity2->DomainLength ||
1112             memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1113             return FALSE;
1114         /* compare passwords */
1115         if (identity1->PasswordLength != identity2->PasswordLength ||
1116             memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1117             return FALSE;
1118     }
1119     else
1120         return FALSE;
1121
1122     return TRUE;
1123 }
1124
1125 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1126 {
1127     RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1128
1129     if (!qos)
1130         return RPC_S_OUT_OF_RESOURCES;
1131
1132     qos->refs = 1;
1133     qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1134     if (!qos->qos) goto error;
1135     qos->qos->Version = qos_src->Version;
1136     qos->qos->Capabilities = qos_src->Capabilities;
1137     qos->qos->IdentityTracking = qos_src->IdentityTracking;
1138     qos->qos->ImpersonationType = qos_src->ImpersonationType;
1139     qos->qos->AdditionalSecurityInfoType = 0;
1140
1141     if (qos_src->Version >= 2)
1142     {
1143         const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1144         qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1145         if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1146         {
1147             const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1148             RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1149
1150             http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1151             qos->qos->u.HttpCredentials = http_credentials_dst;
1152             if (!http_credentials_dst) goto error;
1153             http_credentials_dst->TransportCredentials = NULL;
1154             http_credentials_dst->Flags = http_credentials_src->Flags;
1155             http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1156             http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1157             http_credentials_dst->AuthnSchemes = NULL;
1158             http_credentials_dst->ServerCertificateSubject = NULL;
1159             if (http_credentials_src->TransportCredentials)
1160             {
1161                 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1162                 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1163                 if (!cred_dst) goto error;
1164                 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1165                 if (unicode)
1166                 {
1167                     const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1168                     cred_dst->UserLength = cred_src->UserLength;
1169                     cred_dst->PasswordLength = cred_src->PasswordLength;
1170                     cred_dst->DomainLength = cred_src->DomainLength;
1171                     cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1172                     cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1173                     cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1174                 }
1175                 else
1176                 {
1177                     const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1178                     cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1179                     cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1180                     cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1181                     cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1182                     cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1183                     cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1184                     if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error;
1185                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1186                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1187                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1188                 }
1189             }
1190             if (http_credentials_src->NumberOfAuthnSchemes)
1191             {
1192                 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1193                 if (!http_credentials_dst->AuthnSchemes) goto error;
1194                 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1195             }
1196             if (http_credentials_src->ServerCertificateSubject)
1197             {
1198                 if (unicode)
1199                     http_credentials_dst->ServerCertificateSubject =
1200                         RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1201                                         strlenW(http_credentials_src->ServerCertificateSubject));
1202                 else
1203                     http_credentials_dst->ServerCertificateSubject =
1204                         RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1205                 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1206             }
1207         }
1208     }
1209     *qos_dst = qos;
1210     return RPC_S_OK;
1211
1212 error:
1213     if (qos->qos)
1214     {
1215         if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1216             qos->qos->u.HttpCredentials)
1217         {
1218             if (qos->qos->u.HttpCredentials->TransportCredentials)
1219             {
1220                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1221                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1222                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1223                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1224             }
1225             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1226             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1227             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1228         }
1229         HeapFree(GetProcessHeap(), 0, qos->qos);
1230     }
1231     HeapFree(GetProcessHeap(), 0, qos);
1232     return RPC_S_OUT_OF_RESOURCES;
1233 }
1234
1235 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1236 {
1237     return InterlockedIncrement(&qos->refs);
1238 }
1239
1240 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1241 {
1242     ULONG refs = InterlockedDecrement(&qos->refs);
1243
1244     if (!refs)
1245     {
1246         if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1247         {
1248             if (qos->qos->u.HttpCredentials->TransportCredentials)
1249             {
1250                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1251                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1252                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1253                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1254             }
1255             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1256             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1257             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1258         }
1259         HeapFree(GetProcessHeap(), 0, qos->qos);
1260         HeapFree(GetProcessHeap(), 0, qos);
1261     }
1262     return refs;
1263 }
1264
1265 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1266 {
1267     if (qos1 == qos2)
1268         return TRUE;
1269
1270     if (!qos1 || !qos2)
1271         return FALSE;
1272
1273     TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n",
1274         qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1275         qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1276         qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1277         qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1278
1279     if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1280         (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1281         (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1282         (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1283         return FALSE;
1284
1285     if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1286     {
1287         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1288         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1289
1290         if (http_credentials1->Flags != http_credentials2->Flags)
1291             return FALSE;
1292
1293         if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1294             return FALSE;
1295
1296         /* authentication schemes and server certificate subject not currently used */
1297
1298         if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1299         {
1300             const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1301             const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1302
1303             if (!identity1 || !identity2)
1304                 return FALSE;
1305
1306             /* compare user names */
1307             if (identity1->UserLength != identity2->UserLength ||
1308                 memcmp(identity1->User, identity2->User, identity1->UserLength))
1309                 return FALSE;
1310             /* compare domain names */
1311             if (identity1->DomainLength != identity2->DomainLength ||
1312                 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1313                 return FALSE;
1314             /* compare passwords */
1315             if (identity1->PasswordLength != identity2->PasswordLength ||
1316                 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1317                 return FALSE;
1318         }
1319     }
1320
1321     return TRUE;
1322 }
1323
1324 /***********************************************************************
1325  *             RpcRevertToSelf (RPCRT4.@)
1326  */
1327 RPC_STATUS WINAPI RpcRevertToSelf(void)
1328 {
1329     FIXME("stub\n");
1330     RevertToSelf();
1331     return RPC_S_OK;
1332 }
1333
1334 /***********************************************************************
1335  *             RpcMgmtSetComTimeout (RPCRT4.@)
1336  */
1337 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1338 {
1339     FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1340     return RPC_S_OK;
1341 }
1342
1343 /***********************************************************************
1344  *             RpcBindingInqAuthInfoExA (RPCRT4.@)
1345  */
1346 RPCRTAPI RPC_STATUS RPC_ENTRY
1347 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1348                           ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1349                           ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1350 {
1351     FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1352           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1353     return RPC_S_INVALID_BINDING;
1354 }
1355
1356 /***********************************************************************
1357  *             RpcBindingInqAuthInfoExW (RPCRT4.@)
1358  */
1359 RPCRTAPI RPC_STATUS RPC_ENTRY
1360 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1361                           ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1362                           ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1363 {
1364     FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1365           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1366     return RPC_S_INVALID_BINDING;
1367 }
1368
1369 /***********************************************************************
1370  *             RpcBindingInqAuthInfoA (RPCRT4.@)
1371  */
1372 RPCRTAPI RPC_STATUS RPC_ENTRY
1373 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1374                         ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1375 {
1376     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1377           AuthnSvc, AuthIdentity, AuthzSvc);
1378     return RPC_S_INVALID_BINDING;
1379 }
1380
1381 /***********************************************************************
1382  *             RpcBindingInqAuthInfoW (RPCRT4.@)
1383  */
1384 RPCRTAPI RPC_STATUS RPC_ENTRY
1385 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1386                         ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1387 {
1388     FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel,
1389           AuthnSvc, AuthIdentity, AuthzSvc);
1390     return RPC_S_INVALID_BINDING;
1391 }
1392
1393 /***********************************************************************
1394  *             RpcBindingSetAuthInfoExA (RPCRT4.@)
1395  */
1396 RPCRTAPI RPC_STATUS RPC_ENTRY
1397 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1398                           ULONG AuthnLevel, ULONG AuthnSvc,
1399                           RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1400                           RPC_SECURITY_QOS *SecurityQos )
1401 {
1402   RpcBinding* bind = (RpcBinding*)Binding;
1403   SECURITY_STATUS r;
1404   CredHandle cred;
1405   TimeStamp exp;
1406   ULONG package_count;
1407   ULONG i;
1408   PSecPkgInfoA packages;
1409   ULONG cbMaxToken;
1410
1411   TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1412         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1413
1414   if (SecurityQos)
1415   {
1416       RPC_STATUS status;
1417
1418       TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1419             SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1420       if (SecurityQos->Version >= 2)
1421       {
1422           const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1423           TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1424           if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1425               TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1426                     SecurityQos2->u.HttpCredentials->TransportCredentials,
1427                     SecurityQos2->u.HttpCredentials->Flags,
1428                     SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1429                     SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1430                     SecurityQos2->u.HttpCredentials->AuthnSchemes,
1431                     SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1432       }
1433       TRACE("}\n");
1434       status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1435       if (status != RPC_S_OK)
1436           return status;
1437   }
1438   else
1439   {
1440       if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1441       bind->QOS = NULL;
1442   }
1443
1444   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1445     AuthnSvc = RPC_C_AUTHN_WINNT;
1446
1447   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1448   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1449     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1450
1451   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1452   {
1453     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1454     bind->AuthInfo = NULL;
1455     return RPC_S_OK;
1456   }
1457
1458   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1459   {
1460     FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1461     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1462   }
1463
1464   if (AuthzSvr)
1465   {
1466     FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1467     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1468   }
1469
1470   r = EnumerateSecurityPackagesA(&package_count, &packages);
1471   if (r != SEC_E_OK)
1472   {
1473     ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1474     return RPC_S_SEC_PKG_ERROR;
1475   }
1476
1477   for (i = 0; i < package_count; i++)
1478     if (packages[i].wRPCID == AuthnSvc)
1479         break;
1480
1481   if (i == package_count)
1482   {
1483     FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1484     FreeContextBuffer(packages);
1485     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1486   }
1487
1488   TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1489   r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1490                                 AuthIdentity, NULL, NULL, &cred, &exp);
1491   cbMaxToken = packages[i].cbMaxToken;
1492   FreeContextBuffer(packages);
1493   if (r == ERROR_SUCCESS)
1494   {
1495     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1496     bind->AuthInfo = NULL;
1497     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1498                            AuthIdentity, &bind->AuthInfo);
1499     if (r != RPC_S_OK)
1500       FreeCredentialsHandle(&cred);
1501     return RPC_S_OK;
1502   }
1503   else
1504   {
1505     ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1506     return RPC_S_SEC_PKG_ERROR;
1507   }
1508 }
1509
1510 /***********************************************************************
1511  *             RpcBindingSetAuthInfoExW (RPCRT4.@)
1512  */
1513 RPCRTAPI RPC_STATUS RPC_ENTRY
1514 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1515                           ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1516                           RPC_SECURITY_QOS *SecurityQos )
1517 {
1518   RpcBinding* bind = (RpcBinding*)Binding;
1519   SECURITY_STATUS r;
1520   CredHandle cred;
1521   TimeStamp exp;
1522   ULONG package_count;
1523   ULONG i;
1524   PSecPkgInfoW packages;
1525   ULONG cbMaxToken;
1526
1527   TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1528         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1529
1530   if (SecurityQos)
1531   {
1532       RPC_STATUS status;
1533
1534       TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld",
1535             SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1536       if (SecurityQos->Version >= 2)
1537       {
1538           const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1539           TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType);
1540           if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1541               TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }",
1542                     SecurityQos2->u.HttpCredentials->TransportCredentials,
1543                     SecurityQos2->u.HttpCredentials->Flags,
1544                     SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1545                     SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1546                     SecurityQos2->u.HttpCredentials->AuthnSchemes,
1547                     debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1548       }
1549       TRACE("}\n");
1550       status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1551       if (status != RPC_S_OK)
1552           return status;
1553   }
1554   else
1555   {
1556       if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1557       bind->QOS = NULL;
1558   }
1559
1560   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1561     AuthnSvc = RPC_C_AUTHN_WINNT;
1562
1563   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1564   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1565     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1566
1567   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1568   {
1569     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1570     bind->AuthInfo = NULL;
1571     return RPC_S_OK;
1572   }
1573
1574   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1575   {
1576     FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1577     return RPC_S_UNKNOWN_AUTHN_LEVEL;
1578   }
1579
1580   if (AuthzSvr)
1581   {
1582     FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1583     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1584   }
1585
1586   r = EnumerateSecurityPackagesW(&package_count, &packages);
1587   if (r != SEC_E_OK)
1588   {
1589     ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1590     return RPC_S_SEC_PKG_ERROR;
1591   }
1592
1593   for (i = 0; i < package_count; i++)
1594     if (packages[i].wRPCID == AuthnSvc)
1595         break;
1596
1597   if (i == package_count)
1598   {
1599     FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1600     FreeContextBuffer(packages);
1601     return RPC_S_UNKNOWN_AUTHN_SERVICE;
1602   }
1603
1604   TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1605   r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1606                                 AuthIdentity, NULL, NULL, &cred, &exp);
1607   cbMaxToken = packages[i].cbMaxToken;
1608   FreeContextBuffer(packages);
1609   if (r == ERROR_SUCCESS)
1610   {
1611     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1612     bind->AuthInfo = NULL;
1613     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1614                            AuthIdentity, &bind->AuthInfo);
1615     if (r != RPC_S_OK)
1616       FreeCredentialsHandle(&cred);
1617     return RPC_S_OK;
1618   }
1619   else
1620   {
1621     ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1622     return RPC_S_SEC_PKG_ERROR;
1623   }
1624 }
1625
1626 /***********************************************************************
1627  *             RpcBindingSetAuthInfoA (RPCRT4.@)
1628  */
1629 RPCRTAPI RPC_STATUS RPC_ENTRY
1630 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1631                         ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1632 {
1633     TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1634           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1635     return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1636 }
1637
1638 /***********************************************************************
1639  *             RpcBindingSetAuthInfoW (RPCRT4.@)
1640  */
1641 RPCRTAPI RPC_STATUS RPC_ENTRY
1642 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1643                         ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1644 {
1645     TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
1646           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1647     return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1648 }
1649
1650 /***********************************************************************
1651  *             RpcBindingSetOption (RPCRT4.@)
1652  */
1653 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue)
1654 {
1655     FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue);
1656     return RPC_S_OK;
1657 }