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