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