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