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