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