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 "wine/winternl.h"
34
35 #include "rpc.h"
36 #include "rpcndr.h"
37
38 #include "wine/debug.h"
39
40 #include "rpc_binding.h"
41 #include "rpc_assoc.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
44
RPCRT4_strndupA(LPCSTR src,INT slen)45 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
46 {
47 DWORD len;
48 LPSTR s;
49 if (!src) return NULL;
50 if (slen == -1) slen = strlen(src);
51 len = slen;
52 s = HeapAlloc(GetProcessHeap(), 0, len+1);
53 memcpy(s, src, len);
54 s[len] = 0;
55 return s;
56 }
57
RPCRT4_strdupWtoA(LPCWSTR src)58 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
59 {
60 DWORD len;
61 LPSTR s;
62 if (!src) return NULL;
63 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
64 s = HeapAlloc(GetProcessHeap(), 0, len);
65 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
66 return s;
67 }
68
RPCRT4_strdupAtoW(LPCSTR src)69 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
70 {
71 DWORD len;
72 LPWSTR s;
73 if (!src) return NULL;
74 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
75 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
76 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
77 return s;
78 }
79
RPCRT4_strndupAtoW(LPCSTR src,INT slen)80 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
81 {
82 DWORD len;
83 LPWSTR s;
84 if (!src) return NULL;
85 len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
86 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
87 MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
88 return s;
89 }
90
RPCRT4_strndupW(LPCWSTR src,INT slen)91 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
92 {
93 DWORD len;
94 LPWSTR s;
95 if (!src) return NULL;
96 if (slen == -1) slen = lstrlenW(src);
97 len = slen;
98 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
99 memcpy(s, src, len*sizeof(WCHAR));
100 s[len] = 0;
101 return s;
102 }
103
RPCRT4_strfree(LPSTR src)104 void RPCRT4_strfree(LPSTR src)
105 {
106 HeapFree(GetProcessHeap(), 0, src);
107 }
108
RPCRT4_AllocBinding(RpcBinding ** Binding,BOOL server)109 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
110 {
111 RpcBinding* NewBinding;
112
113 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
114 NewBinding->refs = 1;
115 NewBinding->server = server;
116
117 *Binding = NewBinding;
118
119 return RPC_S_OK;
120 }
121
RPCRT4_CreateBindingA(RpcBinding ** Binding,BOOL server,LPCSTR Protseq)122 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
123 {
124 RpcBinding* NewBinding;
125
126 RPCRT4_AllocBinding(&NewBinding, server);
127 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
128
129 TRACE("binding: %p\n", NewBinding);
130 *Binding = NewBinding;
131
132 return RPC_S_OK;
133 }
134
RPCRT4_CreateBindingW(RpcBinding ** Binding,BOOL server,LPCWSTR Protseq)135 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
136 {
137 RpcBinding* NewBinding;
138
139 RPCRT4_AllocBinding(&NewBinding, server);
140 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
141
142 TRACE("binding: %p\n", NewBinding);
143 *Binding = NewBinding;
144
145 return RPC_S_OK;
146 }
147
RPCRT4_CompleteBindingA(RpcBinding * Binding,LPCSTR NetworkAddr,LPCSTR Endpoint,LPCSTR NetworkOptions)148 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
149 LPCSTR Endpoint, LPCSTR NetworkOptions)
150 {
151 RPC_STATUS status;
152
153 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
154 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
155
156 RPCRT4_strfree(Binding->NetworkAddr);
157 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
158 RPCRT4_strfree(Binding->Endpoint);
159 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
160 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
161 Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
162
163 /* only attempt to get an association if the binding is complete */
164 if (Endpoint && Endpoint[0] != '\0')
165 {
166 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
167 Binding->Endpoint, Binding->NetworkOptions,
168 &Binding->Assoc);
169 if (status != RPC_S_OK)
170 return status;
171 }
172
173 return RPC_S_OK;
174 }
175
RPCRT4_CompleteBindingW(RpcBinding * Binding,LPCWSTR NetworkAddr,LPCWSTR Endpoint,LPCWSTR NetworkOptions)176 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
177 LPCWSTR Endpoint, LPCWSTR NetworkOptions)
178 {
179 RPC_STATUS status;
180
181 TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
182 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
183
184 RPCRT4_strfree(Binding->NetworkAddr);
185 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
186 RPCRT4_strfree(Binding->Endpoint);
187 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
188 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
189 Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
190
191 /* only attempt to get an association if the binding is complete */
192 if (Endpoint && Endpoint[0] != '\0')
193 {
194 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
195 Binding->Endpoint, Binding->NetworkOptions,
196 &Binding->Assoc);
197 if (status != RPC_S_OK)
198 return status;
199 }
200
201 return RPC_S_OK;
202 }
203
RPCRT4_ResolveBinding(RpcBinding * Binding,LPCSTR Endpoint)204 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
205 {
206 RPC_STATUS status;
207
208 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
209
210 RPCRT4_strfree(Binding->Endpoint);
211 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
212
213 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
214 Binding->Assoc = NULL;
215 status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
216 Binding->Endpoint, Binding->NetworkOptions,
217 &Binding->Assoc);
218 if (status != RPC_S_OK)
219 return status;
220
221 return RPC_S_OK;
222 }
223
RPCRT4_SetBindingObject(RpcBinding * Binding,const UUID * ObjectUuid)224 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
225 {
226 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
227 if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
228 else UuidCreateNil(&Binding->ObjectUuid);
229 return RPC_S_OK;
230 }
231
RPCRT4_MakeBinding(RpcBinding ** Binding,RpcConnection * Connection)232 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
233 {
234 RpcBinding* NewBinding;
235 TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
236
237 RPCRT4_AllocBinding(&NewBinding, Connection->server);
238 NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
239 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
240 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
241 NewBinding->FromConn = Connection;
242
243 TRACE("binding: %p\n", NewBinding);
244 *Binding = NewBinding;
245
246 return RPC_S_OK;
247 }
248
RPCRT4_AddRefBinding(RpcBinding * Binding)249 void RPCRT4_AddRefBinding(RpcBinding* Binding)
250 {
251 InterlockedIncrement(&Binding->refs);
252 }
253
RPCRT4_ReleaseBinding(RpcBinding * Binding)254 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
255 {
256 if (InterlockedDecrement(&Binding->refs))
257 return RPC_S_OK;
258
259 TRACE("binding: %p\n", Binding);
260 if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
261 RPCRT4_strfree(Binding->Endpoint);
262 RPCRT4_strfree(Binding->NetworkAddr);
263 RPCRT4_strfree(Binding->Protseq);
264 HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
265 HeapFree(GetProcessHeap(), 0, Binding->CookieAuth);
266 if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
267 if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
268 HeapFree(GetProcessHeap(), 0, Binding);
269 return RPC_S_OK;
270 }
271
RPCRT4_OpenBinding(RpcBinding * Binding,RpcConnection ** Connection,const RPC_SYNTAX_IDENTIFIER * TransferSyntax,const RPC_SYNTAX_IDENTIFIER * InterfaceId,BOOL * from_cache)272 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
273 const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
274 const RPC_SYNTAX_IDENTIFIER *InterfaceId, BOOL *from_cache)
275 {
276 TRACE("(Binding == ^%p)\n", Binding);
277
278 if (!Binding->server) {
279 return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
280 TransferSyntax, Binding->AuthInfo, Binding->QOS, Binding->CookieAuth, Connection, from_cache);
281 } else {
282 /* we already have a connection with acceptable binding, so use it */
283 if (Binding->FromConn) {
284 *Connection = Binding->FromConn;
285 return RPC_S_OK;
286 } else {
287 ERR("no connection in binding\n");
288 return RPC_S_INTERNAL_ERROR;
289 }
290 }
291 }
292
RPCRT4_CloseBinding(RpcBinding * Binding,RpcConnection * Connection)293 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
294 {
295 TRACE("(Binding == ^%p)\n", Binding);
296 if (!Connection) return RPC_S_OK;
297 if (Binding->server) {
298 /* don't destroy a connection that is cached in the binding */
299 if (Binding->FromConn != Connection)
300 RPCRT4_ReleaseConnection(Connection);
301 }
302 else {
303 RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
304 }
305 return RPC_S_OK;
306 }
307
RPCRT4_strconcatA(LPSTR dst,LPCSTR src)308 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
309 {
310 DWORD len = strlen(dst), slen = strlen(src);
311 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
312 if (!ndst)
313 {
314 HeapFree(GetProcessHeap(), 0, dst);
315 return NULL;
316 }
317 ndst[len] = ',';
318 memcpy(ndst+len+1, src, slen+1);
319 return ndst;
320 }
321
RPCRT4_strconcatW(LPWSTR dst,LPCWSTR src)322 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
323 {
324 DWORD len = lstrlenW(dst), slen = lstrlenW(src);
325 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
326 if (!ndst)
327 {
328 HeapFree(GetProcessHeap(), 0, dst);
329 return NULL;
330 }
331 ndst[len] = ',';
332 memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
333 return ndst;
334 }
335
336 /* Copies the escaped version of a component into a string binding.
337 * Note: doesn't nul-terminate the string */
escape_string_binding_component(RPC_CSTR string_binding,const unsigned char * component)338 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
339 const unsigned char *component)
340 {
341 for (; *component; component++) {
342 switch (*component) {
343 case '@':
344 case ':':
345 case '[':
346 case ']':
347 case '\\':
348 *string_binding++ = '\\';
349 *string_binding++ = *component;
350 break;
351 default:
352 *string_binding++ = *component;
353 break;
354 }
355 }
356 return string_binding;
357 }
358
escape_string_binding_componentW(RPC_WSTR string_binding,const WCHAR * component)359 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
360 const WCHAR *component)
361 {
362 for (; *component; component++) {
363 switch (*component) {
364 case '@':
365 case ':':
366 case '[':
367 case ']':
368 case '\\':
369 *string_binding++ = '\\';
370 *string_binding++ = *component;
371 break;
372 default:
373 *string_binding++ = *component;
374 break;
375 }
376 }
377 return string_binding;
378 }
379
string_binding_find_delimiter(const unsigned char * string_binding,unsigned char delim)380 static const unsigned char *string_binding_find_delimiter(
381 const unsigned char *string_binding, unsigned char delim)
382 {
383 const unsigned char *next;
384 for (next = string_binding; *next; next++) {
385 if (*next == '\\') {
386 next++;
387 continue;
388 }
389 if (*next == delim)
390 return next;
391 }
392 return NULL;
393 }
394
string_binding_find_delimiterW(const WCHAR * string_binding,WCHAR delim)395 static const WCHAR *string_binding_find_delimiterW(
396 const WCHAR *string_binding, WCHAR delim)
397 {
398 const WCHAR *next;
399 for (next = string_binding; *next; next++) {
400 if (*next == '\\') {
401 next++;
402 continue;
403 }
404 if (*next == delim)
405 return next;
406 }
407 return NULL;
408 }
409
unescape_string_binding_component(const unsigned char * string_binding,int len)410 static RPC_CSTR unescape_string_binding_component(
411 const unsigned char *string_binding, int len)
412 {
413 RPC_CSTR component, p;
414
415 if (len == -1) len = strlen((const char *)string_binding);
416
417 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
418 if (!component) return NULL;
419 for (p = component; len > 0; string_binding++, len--) {
420 if (*string_binding == '\\') {
421 string_binding++;
422 len--;
423 *p++ = *string_binding;
424 } else {
425 *p++ = *string_binding;
426 }
427 }
428 *p = '\0';
429 return component;
430 }
431
unescape_string_binding_componentW(const WCHAR * string_binding,int len)432 static RPC_WSTR unescape_string_binding_componentW(
433 const WCHAR *string_binding, int len)
434 {
435 RPC_WSTR component, p;
436
437 if (len == -1) len = lstrlenW(string_binding);
438
439 component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
440 if (!component) return NULL;
441 for (p = component; len > 0; string_binding++, len--) {
442 if (*string_binding == '\\') {
443 string_binding++;
444 len--;
445 *p++ = *string_binding;
446 } else {
447 *p++ = *string_binding;
448 }
449 }
450 *p = '\0';
451 return component;
452 }
453
454 /***********************************************************************
455 * RpcStringBindingComposeA (RPCRT4.@)
456 */
RpcStringBindingComposeA(RPC_CSTR ObjUuid,RPC_CSTR Protseq,RPC_CSTR NetworkAddr,RPC_CSTR Endpoint,RPC_CSTR Options,RPC_CSTR * StringBinding)457 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
458 RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
459 RPC_CSTR Options, RPC_CSTR *StringBinding )
460 {
461 DWORD len = 1;
462 RPC_CSTR data;
463
464 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
465 debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
466 debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
467 debugstr_a( (char*)Options ), StringBinding );
468
469 /* overestimate for each component for escaping of delimiters */
470 if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
471 if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
472 if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
473 if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
474 if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
475
476 data = HeapAlloc(GetProcessHeap(), 0, len);
477 *StringBinding = data;
478
479 if (ObjUuid && *ObjUuid) {
480 data = escape_string_binding_component(data, ObjUuid);
481 *data++ = '@';
482 }
483 if (Protseq && *Protseq) {
484 data = escape_string_binding_component(data, Protseq);
485 *data++ = ':';
486 }
487 if (NetworkAddr && *NetworkAddr)
488 data = escape_string_binding_component(data, NetworkAddr);
489
490 if ((Endpoint && *Endpoint) ||
491 (Options && *Options)) {
492 *data++ = '[';
493 if (Endpoint && *Endpoint) {
494 data = escape_string_binding_component(data, Endpoint);
495 if (Options && *Options) *data++ = ',';
496 }
497 if (Options && *Options) {
498 data = escape_string_binding_component(data, Options);
499 }
500 *data++ = ']';
501 }
502 *data = 0;
503
504 return RPC_S_OK;
505 }
506
507 /***********************************************************************
508 * RpcStringBindingComposeW (RPCRT4.@)
509 */
RpcStringBindingComposeW(RPC_WSTR ObjUuid,RPC_WSTR Protseq,RPC_WSTR NetworkAddr,RPC_WSTR Endpoint,RPC_WSTR Options,RPC_WSTR * StringBinding)510 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
511 RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
512 RPC_WSTR Options, RPC_WSTR* StringBinding )
513 {
514 DWORD len = 1;
515 RPC_WSTR data;
516
517 TRACE("(%s,%s,%s,%s,%s,%p)\n",
518 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
519 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
520 debugstr_w( Options ), StringBinding);
521
522 /* overestimate for each component for escaping of delimiters */
523 if (ObjUuid && *ObjUuid) len += lstrlenW(ObjUuid) * 2 + 1;
524 if (Protseq && *Protseq) len += lstrlenW(Protseq) * 2 + 1;
525 if (NetworkAddr && *NetworkAddr) len += lstrlenW(NetworkAddr) * 2;
526 if (Endpoint && *Endpoint) len += lstrlenW(Endpoint) * 2 + 2;
527 if (Options && *Options) len += lstrlenW(Options) * 2 + 2;
528
529 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
530 *StringBinding = data;
531
532 if (ObjUuid && *ObjUuid) {
533 data = escape_string_binding_componentW(data, ObjUuid);
534 *data++ = '@';
535 }
536 if (Protseq && *Protseq) {
537 data = escape_string_binding_componentW(data, Protseq);
538 *data++ = ':';
539 }
540 if (NetworkAddr && *NetworkAddr) {
541 data = escape_string_binding_componentW(data, NetworkAddr);
542 }
543 if ((Endpoint && *Endpoint) ||
544 (Options && *Options)) {
545 *data++ = '[';
546 if (Endpoint && *Endpoint) {
547 data = escape_string_binding_componentW(data, Endpoint);
548 if (Options && *Options) *data++ = ',';
549 }
550 if (Options && *Options) {
551 data = escape_string_binding_componentW(data, Options);
552 }
553 *data++ = ']';
554 }
555 *data = 0;
556
557 return RPC_S_OK;
558 }
559
560
561 /***********************************************************************
562 * RpcStringBindingParseA (RPCRT4.@)
563 */
RpcStringBindingParseA(RPC_CSTR StringBinding,RPC_CSTR * ObjUuid,RPC_CSTR * Protseq,RPC_CSTR * NetworkAddr,RPC_CSTR * Endpoint,RPC_CSTR * Options)564 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
565 RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
566 RPC_CSTR *Endpoint, RPC_CSTR *Options)
567 {
568 const unsigned char *data, *next;
569 static const char ep_opt[] = "endpoint=";
570 BOOL endpoint_already_found = FALSE;
571
572 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
573 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
574
575 if (ObjUuid) *ObjUuid = NULL;
576 if (Protseq) *Protseq = NULL;
577 if (NetworkAddr) *NetworkAddr = NULL;
578 if (Endpoint) *Endpoint = NULL;
579 if (Options) *Options = NULL;
580
581 data = StringBinding;
582
583 next = string_binding_find_delimiter(data, '@');
584 if (next) {
585 UUID uuid;
586 RPC_STATUS status;
587 RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
588 status = UuidFromStringA(str_uuid, &uuid);
589 if (status != RPC_S_OK) {
590 HeapFree(GetProcessHeap(), 0, str_uuid);
591 return status;
592 }
593 if (ObjUuid)
594 *ObjUuid = str_uuid;
595 else
596 HeapFree(GetProcessHeap(), 0, str_uuid);
597 data = next+1;
598 }
599
600 next = string_binding_find_delimiter(data, ':');
601 if (next) {
602 if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
603 data = next+1;
604 } else {
605 goto fail;
606 }
607
608 next = string_binding_find_delimiter(data, '[');
609 if (next) {
610 const unsigned char *close;
611 RPC_CSTR opt;
612
613 if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
614 data = next+1;
615 close = string_binding_find_delimiter(data, ']');
616 if (!close) goto fail;
617
618 /* tokenize options */
619 while (data < close) {
620 next = string_binding_find_delimiter(data, ',');
621 if (!next || next > close) next = close;
622 /* FIXME: this is kind of inefficient */
623 opt = unescape_string_binding_component(data, next - data);
624 data = next+1;
625
626 /* parse option */
627 next = string_binding_find_delimiter(opt, '=');
628 if (!next) {
629 /* not an option, must be an endpoint */
630 if (endpoint_already_found) goto fail;
631 if (Endpoint) *Endpoint = opt;
632 else HeapFree(GetProcessHeap(), 0, opt);
633 endpoint_already_found = TRUE;
634 } else {
635 if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
636 /* endpoint option */
637 if (endpoint_already_found) goto fail;
638 if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
639 HeapFree(GetProcessHeap(), 0, opt);
640 endpoint_already_found = TRUE;
641 } else {
642 /* network option */
643 if (Options) {
644 if (*Options) {
645 /* FIXME: this is kind of inefficient */
646 *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
647 HeapFree(GetProcessHeap(), 0, opt);
648 } else
649 *Options = opt;
650 } else
651 HeapFree(GetProcessHeap(), 0, opt);
652 }
653 }
654 }
655
656 data = close+1;
657 if (*data) goto fail;
658 }
659 else if (NetworkAddr)
660 *NetworkAddr = unescape_string_binding_component(data, -1);
661
662 return RPC_S_OK;
663
664 fail:
665 if (ObjUuid) RpcStringFreeA(ObjUuid);
666 if (Protseq) RpcStringFreeA(Protseq);
667 if (NetworkAddr) RpcStringFreeA(NetworkAddr);
668 if (Endpoint) RpcStringFreeA(Endpoint);
669 if (Options) RpcStringFreeA(Options);
670 return RPC_S_INVALID_STRING_BINDING;
671 }
672
673 /***********************************************************************
674 * RpcStringBindingParseW (RPCRT4.@)
675 */
RpcStringBindingParseW(RPC_WSTR StringBinding,RPC_WSTR * ObjUuid,RPC_WSTR * Protseq,RPC_WSTR * NetworkAddr,RPC_WSTR * Endpoint,RPC_WSTR * Options)676 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
677 RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
678 RPC_WSTR *Endpoint, RPC_WSTR *Options)
679 {
680 const WCHAR *data, *next;
681 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
682 BOOL endpoint_already_found = FALSE;
683
684 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
685 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
686
687 if (ObjUuid) *ObjUuid = NULL;
688 if (Protseq) *Protseq = NULL;
689 if (NetworkAddr) *NetworkAddr = NULL;
690 if (Endpoint) *Endpoint = NULL;
691 if (Options) *Options = NULL;
692
693 data = StringBinding;
694
695 next = string_binding_find_delimiterW(data, '@');
696 if (next) {
697 UUID uuid;
698 RPC_STATUS status;
699 RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
700 status = UuidFromStringW(str_uuid, &uuid);
701 if (status != RPC_S_OK) {
702 HeapFree(GetProcessHeap(), 0, str_uuid);
703 return status;
704 }
705 if (ObjUuid)
706 *ObjUuid = str_uuid;
707 else
708 HeapFree(GetProcessHeap(), 0, str_uuid);
709 data = next+1;
710 }
711
712 next = string_binding_find_delimiterW(data, ':');
713 if (next) {
714 if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
715 data = next+1;
716 } else {
717 goto fail;
718 }
719
720 next = string_binding_find_delimiterW(data, '[');
721 if (next) {
722 const WCHAR *close;
723 RPC_WSTR opt;
724
725 if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
726 data = next+1;
727 close = string_binding_find_delimiterW(data, ']');
728 if (!close) goto fail;
729
730 /* tokenize options */
731 while (data < close) {
732 next = string_binding_find_delimiterW(data, ',');
733 if (!next || next > close) next = close;
734 /* FIXME: this is kind of inefficient */
735 opt = unescape_string_binding_componentW(data, next - data);
736 data = next+1;
737
738 /* parse option */
739 next = string_binding_find_delimiterW(opt, '=');
740 if (!next) {
741 /* not an option, must be an endpoint */
742 if (endpoint_already_found) goto fail;
743 if (Endpoint) *Endpoint = opt;
744 else HeapFree(GetProcessHeap(), 0, opt);
745 endpoint_already_found = TRUE;
746 } else {
747 if (wcsncmp(opt, ep_opt, lstrlenW(ep_opt)) == 0) {
748 /* endpoint option */
749 if (endpoint_already_found) goto fail;
750 if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
751 HeapFree(GetProcessHeap(), 0, opt);
752 endpoint_already_found = TRUE;
753 } else {
754 /* network option */
755 if (Options) {
756 if (*Options) {
757 /* FIXME: this is kind of inefficient */
758 *Options = RPCRT4_strconcatW(*Options, opt);
759 HeapFree(GetProcessHeap(), 0, opt);
760 } else
761 *Options = opt;
762 } else
763 HeapFree(GetProcessHeap(), 0, opt);
764 }
765 }
766 }
767
768 data = close+1;
769 if (*data) goto fail;
770 } else if (NetworkAddr)
771 *NetworkAddr = unescape_string_binding_componentW(data, -1);
772
773 return RPC_S_OK;
774
775 fail:
776 if (ObjUuid) RpcStringFreeW(ObjUuid);
777 if (Protseq) RpcStringFreeW(Protseq);
778 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
779 if (Endpoint) RpcStringFreeW(Endpoint);
780 if (Options) RpcStringFreeW(Options);
781 return RPC_S_INVALID_STRING_BINDING;
782 }
783
784 /***********************************************************************
785 * RpcBindingFree (RPCRT4.@)
786 */
RpcBindingFree(RPC_BINDING_HANDLE * Binding)787 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
788 {
789 RPC_STATUS status;
790 TRACE("(%p) = %p\n", Binding, *Binding);
791 if (*Binding)
792 status = RPCRT4_ReleaseBinding(*Binding);
793 else
794 status = RPC_S_INVALID_BINDING;
795 if (status == RPC_S_OK) *Binding = NULL;
796 return status;
797 }
798
799 /***********************************************************************
800 * RpcBindingVectorFree (RPCRT4.@)
801 */
RpcBindingVectorFree(RPC_BINDING_VECTOR ** BindingVector)802 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
803 {
804 ULONG c;
805
806 TRACE("(%p)\n", BindingVector);
807 for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]);
808 HeapFree(GetProcessHeap(), 0, *BindingVector);
809 *BindingVector = NULL;
810 return RPC_S_OK;
811 }
812
813 /***********************************************************************
814 * RpcBindingInqObject (RPCRT4.@)
815 */
RpcBindingInqObject(RPC_BINDING_HANDLE Binding,UUID * ObjectUuid)816 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
817 {
818 RpcBinding* bind = Binding;
819
820 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
821 *ObjectUuid = bind->ObjectUuid;
822 return RPC_S_OK;
823 }
824
825 /***********************************************************************
826 * RpcBindingSetObject (RPCRT4.@)
827 */
RpcBindingSetObject(RPC_BINDING_HANDLE Binding,UUID * ObjectUuid)828 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
829 {
830 RpcBinding* bind = Binding;
831
832 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
833 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
834 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
835 }
836
837 /***********************************************************************
838 * RpcBindingFromStringBindingA (RPCRT4.@)
839 */
RpcBindingFromStringBindingA(RPC_CSTR StringBinding,RPC_BINDING_HANDLE * Binding)840 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
841 {
842 RPC_STATUS ret;
843 RpcBinding* bind = NULL;
844 RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
845 UUID Uuid;
846
847 TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
848
849 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
850 &NetworkAddr, &Endpoint, &Options);
851 if (ret != RPC_S_OK) return ret;
852
853 ret = UuidFromStringA(ObjectUuid, &Uuid);
854
855 if (ret == RPC_S_OK)
856 ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
857 if (ret == RPC_S_OK) {
858 ret = RPCRT4_SetBindingObject(bind, &Uuid);
859 if (ret == RPC_S_OK)
860 ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
861
862 if (ret == RPC_S_OK)
863 *Binding = (RPC_BINDING_HANDLE)bind;
864 else
865 RPCRT4_ReleaseBinding(bind);
866 }
867
868 RpcStringFreeA(&Options);
869 RpcStringFreeA(&Endpoint);
870 RpcStringFreeA(&NetworkAddr);
871 RpcStringFreeA(&Protseq);
872 RpcStringFreeA(&ObjectUuid);
873
874 return ret;
875 }
876
877 /***********************************************************************
878 * RpcBindingFromStringBindingW (RPCRT4.@)
879 */
RpcBindingFromStringBindingW(RPC_WSTR StringBinding,RPC_BINDING_HANDLE * Binding)880 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
881 {
882 RPC_STATUS ret;
883 RpcBinding* bind = NULL;
884 RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
885 UUID Uuid;
886
887 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
888
889 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
890 &NetworkAddr, &Endpoint, &Options);
891 if (ret != RPC_S_OK) return ret;
892
893 ret = UuidFromStringW(ObjectUuid, &Uuid);
894
895 if (ret == RPC_S_OK)
896 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
897 if (ret == RPC_S_OK) {
898 ret = RPCRT4_SetBindingObject(bind, &Uuid);
899 if (ret == RPC_S_OK)
900 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
901
902 if (ret == RPC_S_OK)
903 *Binding = (RPC_BINDING_HANDLE)bind;
904 else
905 RPCRT4_ReleaseBinding(bind);
906 }
907
908 RpcStringFreeW(&Options);
909 RpcStringFreeW(&Endpoint);
910 RpcStringFreeW(&NetworkAddr);
911 RpcStringFreeW(&Protseq);
912 RpcStringFreeW(&ObjectUuid);
913
914 return ret;
915 }
916
917 /***********************************************************************
918 * RpcBindingToStringBindingA (RPCRT4.@)
919 */
RpcBindingToStringBindingA(RPC_BINDING_HANDLE Binding,RPC_CSTR * StringBinding)920 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
921 {
922 RPC_STATUS ret;
923 RpcBinding* bind = Binding;
924 RPC_CSTR ObjectUuid;
925
926 TRACE("(%p,%p)\n", Binding, StringBinding);
927
928 if (UuidIsNil(&bind->ObjectUuid, &ret))
929 ObjectUuid = NULL;
930 else
931 {
932 ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
933 if (ret != RPC_S_OK) return ret;
934 }
935
936 ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
937 (unsigned char*) bind->Endpoint, NULL, StringBinding);
938
939 RpcStringFreeA(&ObjectUuid);
940
941 return ret;
942 }
943
944 /***********************************************************************
945 * RpcBindingToStringBindingW (RPCRT4.@)
946 */
RpcBindingToStringBindingW(RPC_BINDING_HANDLE Binding,RPC_WSTR * StringBinding)947 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
948 {
949 RPC_STATUS ret;
950 unsigned char *str = NULL;
951 TRACE("(%p,%p)\n", Binding, StringBinding);
952 ret = RpcBindingToStringBindingA(Binding, &str);
953 *StringBinding = RPCRT4_strdupAtoW((char*)str);
954 RpcStringFreeA(&str);
955 return ret;
956 }
957
958 /***********************************************************************
959 * I_RpcBindingInqTransportType (RPCRT4.@)
960 */
I_RpcBindingInqTransportType(RPC_BINDING_HANDLE Binding,unsigned int * Type)961 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
962 {
963
964 FIXME( "(%p,%p): stub\n", Binding, Type);
965 *Type = TRANSPORT_TYPE_LPC;
966 return RPC_S_OK;
967 }
968
969 /***********************************************************************
970 * I_RpcBindingSetAsync (RPCRT4.@)
971 * NOTES
972 * Exists in win9x and winNT, but with different number of arguments
973 * (9x version has 3 arguments, NT has 2).
974 */
I_RpcBindingSetAsync(RPC_BINDING_HANDLE Binding,RPC_BLOCKING_FN BlockingFn)975 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
976 {
977 RpcBinding* bind = Binding;
978
979 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
980
981 bind->BlockingFn = BlockingFn;
982
983 return RPC_S_OK;
984 }
985
986 /***********************************************************************
987 * RpcBindingCopy (RPCRT4.@)
988 */
RpcBindingCopy(RPC_BINDING_HANDLE SourceBinding,RPC_BINDING_HANDLE * DestinationBinding)989 RPC_STATUS RPC_ENTRY RpcBindingCopy(
990 RPC_BINDING_HANDLE SourceBinding,
991 RPC_BINDING_HANDLE* DestinationBinding)
992 {
993 RpcBinding *DestBinding;
994 RpcBinding *SrcBinding = SourceBinding;
995 RPC_STATUS status;
996
997 TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
998
999 status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
1000 if (status != RPC_S_OK) return status;
1001
1002 DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
1003 DestBinding->BlockingFn = SrcBinding->BlockingFn;
1004 DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
1005 DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
1006 DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
1007 DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
1008 DestBinding->CookieAuth = RPCRT4_strdupW(SrcBinding->CookieAuth);
1009 if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
1010 DestBinding->Assoc = SrcBinding->Assoc;
1011
1012 if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
1013 DestBinding->AuthInfo = SrcBinding->AuthInfo;
1014 if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
1015 DestBinding->QOS = SrcBinding->QOS;
1016
1017 *DestinationBinding = DestBinding;
1018 return RPC_S_OK;
1019 }
1020
1021 /***********************************************************************
1022 * RpcBindingReset (RPCRT4.@)
1023 */
RpcBindingReset(RPC_BINDING_HANDLE Binding)1024 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
1025 {
1026 RpcBinding *bind = Binding;
1027
1028 TRACE("(%p)\n", Binding);
1029
1030 RPCRT4_strfree(bind->Endpoint);
1031 bind->Endpoint = NULL;
1032 if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
1033 bind->Assoc = NULL;
1034
1035 return RPC_S_OK;
1036 }
1037
1038 /***********************************************************************
1039 * RpcImpersonateClient (RPCRT4.@)
1040 *
1041 * Impersonates the client connected via a binding handle so that security
1042 * checks are done in the context of the client.
1043 *
1044 * PARAMS
1045 * BindingHandle [I] Handle to the binding to the client.
1046 *
1047 * RETURNS
1048 * Success: RPS_S_OK.
1049 * Failure: RPC_STATUS value.
1050 *
1051 * NOTES
1052 *
1053 * If BindingHandle is NULL then the function impersonates the client
1054 * connected to the binding handle of the current thread.
1055 */
RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)1056 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
1057 {
1058 RpcBinding *bind;
1059
1060 TRACE("(%p)\n", BindingHandle);
1061
1062 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1063 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1064
1065 bind = BindingHandle;
1066 if (bind->FromConn)
1067 return rpcrt4_conn_impersonate_client(bind->FromConn);
1068 return RPC_S_WRONG_KIND_OF_BINDING;
1069 }
1070
1071 /***********************************************************************
1072 * RpcRevertToSelfEx (RPCRT4.@)
1073 *
1074 * Stops impersonating the client connected to the binding handle so that security
1075 * checks are no longer done in the context of the client.
1076 *
1077 * PARAMS
1078 * BindingHandle [I] Handle to the binding to the client.
1079 *
1080 * RETURNS
1081 * Success: RPS_S_OK.
1082 * Failure: RPC_STATUS value.
1083 *
1084 * NOTES
1085 *
1086 * If BindingHandle is NULL then the function stops impersonating the client
1087 * connected to the binding handle of the current thread.
1088 */
RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)1089 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
1090 {
1091 RpcBinding *bind;
1092
1093 TRACE("(%p)\n", BindingHandle);
1094
1095 if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
1096 if (!BindingHandle) return RPC_S_INVALID_BINDING;
1097
1098 bind = BindingHandle;
1099 if (bind->FromConn)
1100 return rpcrt4_conn_revert_to_self(bind->FromConn);
1101 return RPC_S_WRONG_KIND_OF_BINDING;
1102 }
1103
has_nt_auth_identity(ULONG AuthnLevel)1104 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
1105 {
1106 switch (AuthnLevel)
1107 {
1108 case RPC_C_AUTHN_GSS_NEGOTIATE:
1109 case RPC_C_AUTHN_WINNT:
1110 case RPC_C_AUTHN_GSS_KERBEROS:
1111 return TRUE;
1112 default:
1113 return FALSE;
1114 }
1115 }
1116
RpcAuthInfo_Create(ULONG AuthnLevel,ULONG AuthnSvc,CredHandle cred,TimeStamp exp,ULONG cbMaxToken,RPC_AUTH_IDENTITY_HANDLE identity,RpcAuthInfo ** ret)1117 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
1118 CredHandle cred, TimeStamp exp,
1119 ULONG cbMaxToken,
1120 RPC_AUTH_IDENTITY_HANDLE identity,
1121 RpcAuthInfo **ret)
1122 {
1123 RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
1124 if (!AuthInfo)
1125 return RPC_S_OUT_OF_MEMORY;
1126
1127 AuthInfo->refs = 1;
1128 AuthInfo->AuthnLevel = AuthnLevel;
1129 AuthInfo->AuthnSvc = AuthnSvc;
1130 AuthInfo->cred = cred;
1131 AuthInfo->exp = exp;
1132 AuthInfo->cbMaxToken = cbMaxToken;
1133 AuthInfo->identity = identity;
1134 AuthInfo->server_principal_name = NULL;
1135
1136 /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
1137 * enable better matching in RpcAuthInfo_IsEqual */
1138 if (identity && has_nt_auth_identity(AuthnSvc))
1139 {
1140 const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
1141 AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
1142 if (!AuthInfo->nt_identity)
1143 {
1144 HeapFree(GetProcessHeap(), 0, AuthInfo);
1145 return RPC_S_OUT_OF_MEMORY;
1146 }
1147
1148 AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1149 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1150 AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
1151 else
1152 AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
1153 AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
1154 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1155 AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
1156 else
1157 AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
1158 AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
1159 if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
1160 AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
1161 else
1162 AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
1163 AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
1164
1165 if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
1166 (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
1167 (nt_identity->Password && !AuthInfo->nt_identity->Password))
1168 {
1169 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1170 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1171 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1172 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1173 HeapFree(GetProcessHeap(), 0, AuthInfo);
1174 return RPC_S_OUT_OF_MEMORY;
1175 }
1176 }
1177 else
1178 AuthInfo->nt_identity = NULL;
1179 *ret = AuthInfo;
1180 return RPC_S_OK;
1181 }
1182
RpcAuthInfo_AddRef(RpcAuthInfo * AuthInfo)1183 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
1184 {
1185 return InterlockedIncrement(&AuthInfo->refs);
1186 }
1187
RpcAuthInfo_Release(RpcAuthInfo * AuthInfo)1188 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
1189 {
1190 ULONG refs = InterlockedDecrement(&AuthInfo->refs);
1191
1192 if (!refs)
1193 {
1194 FreeCredentialsHandle(&AuthInfo->cred);
1195 if (AuthInfo->nt_identity)
1196 {
1197 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
1198 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
1199 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
1200 HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
1201 }
1202 HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
1203 HeapFree(GetProcessHeap(), 0, AuthInfo);
1204 }
1205
1206 return refs;
1207 }
1208
RpcAuthInfo_IsEqual(const RpcAuthInfo * AuthInfo1,const RpcAuthInfo * AuthInfo2)1209 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
1210 {
1211 if (AuthInfo1 == AuthInfo2)
1212 return TRUE;
1213
1214 if (!AuthInfo1 || !AuthInfo2)
1215 return FALSE;
1216
1217 if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
1218 (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
1219 return FALSE;
1220
1221 if (AuthInfo1->identity == AuthInfo2->identity)
1222 return TRUE;
1223
1224 if (!AuthInfo1->identity || !AuthInfo2->identity)
1225 return FALSE;
1226
1227 if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
1228 {
1229 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
1230 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
1231 /* compare user names */
1232 if (identity1->UserLength != identity2->UserLength ||
1233 memcmp(identity1->User, identity2->User, identity1->UserLength))
1234 return FALSE;
1235 /* compare domain names */
1236 if (identity1->DomainLength != identity2->DomainLength ||
1237 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1238 return FALSE;
1239 /* compare passwords */
1240 if (identity1->PasswordLength != identity2->PasswordLength ||
1241 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1242 return FALSE;
1243 }
1244 else
1245 return FALSE;
1246
1247 return TRUE;
1248 }
1249
RpcQualityOfService_Create(const RPC_SECURITY_QOS * qos_src,BOOL unicode,RpcQualityOfService ** qos_dst)1250 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
1251 {
1252 RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
1253
1254 if (!qos)
1255 return RPC_S_OUT_OF_RESOURCES;
1256
1257 qos->refs = 1;
1258 qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
1259 if (!qos->qos) goto error;
1260 qos->qos->Version = qos_src->Version;
1261 qos->qos->Capabilities = qos_src->Capabilities;
1262 qos->qos->IdentityTracking = qos_src->IdentityTracking;
1263 qos->qos->ImpersonationType = qos_src->ImpersonationType;
1264 qos->qos->AdditionalSecurityInfoType = 0;
1265
1266 if (qos_src->Version >= 2)
1267 {
1268 const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
1269 qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
1270 if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1271 {
1272 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
1273 RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
1274
1275 http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
1276 qos->qos->u.HttpCredentials = http_credentials_dst;
1277 if (!http_credentials_dst) goto error;
1278 http_credentials_dst->TransportCredentials = NULL;
1279 http_credentials_dst->Flags = http_credentials_src->Flags;
1280 http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
1281 http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
1282 http_credentials_dst->AuthnSchemes = NULL;
1283 http_credentials_dst->ServerCertificateSubject = NULL;
1284 if (http_credentials_src->TransportCredentials)
1285 {
1286 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
1287 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
1288 if (!cred_dst) goto error;
1289 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
1290 if (unicode)
1291 {
1292 const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
1293 cred_dst->UserLength = cred_src->UserLength;
1294 cred_dst->PasswordLength = cred_src->PasswordLength;
1295 cred_dst->DomainLength = cred_src->DomainLength;
1296 cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
1297 cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
1298 cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
1299 }
1300 else
1301 {
1302 const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
1303 cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
1304 cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
1305 cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
1306 cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
1307 cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
1308 cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
1309 if (!cred_dst->Password || !cred_dst->Domain) goto error;
1310 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
1311 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
1312 MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
1313 }
1314 }
1315 if (http_credentials_src->NumberOfAuthnSchemes)
1316 {
1317 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1318 if (!http_credentials_dst->AuthnSchemes) goto error;
1319 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
1320 }
1321 if (http_credentials_src->ServerCertificateSubject)
1322 {
1323 if (unicode)
1324 http_credentials_dst->ServerCertificateSubject =
1325 RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
1326 lstrlenW(http_credentials_src->ServerCertificateSubject));
1327 else
1328 http_credentials_dst->ServerCertificateSubject =
1329 RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
1330 if (!http_credentials_dst->ServerCertificateSubject) goto error;
1331 }
1332 }
1333 }
1334 *qos_dst = qos;
1335 return RPC_S_OK;
1336
1337 error:
1338 if (qos->qos)
1339 {
1340 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
1341 qos->qos->u.HttpCredentials)
1342 {
1343 if (qos->qos->u.HttpCredentials->TransportCredentials)
1344 {
1345 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1346 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1347 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1348 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1349 }
1350 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1351 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1352 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1353 }
1354 HeapFree(GetProcessHeap(), 0, qos->qos);
1355 }
1356 HeapFree(GetProcessHeap(), 0, qos);
1357 return RPC_S_OUT_OF_RESOURCES;
1358 }
1359
RpcQualityOfService_AddRef(RpcQualityOfService * qos)1360 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
1361 {
1362 return InterlockedIncrement(&qos->refs);
1363 }
1364
RpcQualityOfService_Release(RpcQualityOfService * qos)1365 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
1366 {
1367 ULONG refs = InterlockedDecrement(&qos->refs);
1368
1369 if (!refs)
1370 {
1371 if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1372 {
1373 if (qos->qos->u.HttpCredentials->TransportCredentials)
1374 {
1375 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
1376 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
1377 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
1378 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
1379 }
1380 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
1381 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
1382 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
1383 }
1384 HeapFree(GetProcessHeap(), 0, qos->qos);
1385 HeapFree(GetProcessHeap(), 0, qos);
1386 }
1387 return refs;
1388 }
1389
RpcQualityOfService_IsEqual(const RpcQualityOfService * qos1,const RpcQualityOfService * qos2)1390 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
1391 {
1392 if (qos1 == qos2)
1393 return TRUE;
1394
1395 if (!qos1 || !qos2)
1396 return FALSE;
1397
1398 TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
1399 qos1->qos->Capabilities, qos1->qos->IdentityTracking,
1400 qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
1401 qos2->qos->Capabilities, qos2->qos->IdentityTracking,
1402 qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
1403
1404 if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
1405 (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
1406 (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
1407 (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
1408 return FALSE;
1409
1410 if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1411 {
1412 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
1413 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
1414
1415 if (http_credentials1->Flags != http_credentials2->Flags)
1416 return FALSE;
1417
1418 if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
1419 return FALSE;
1420
1421 if (http_credentials1->NumberOfAuthnSchemes != http_credentials2->NumberOfAuthnSchemes)
1422 return FALSE;
1423
1424 if ((!http_credentials1->AuthnSchemes && http_credentials2->AuthnSchemes) ||
1425 (http_credentials1->AuthnSchemes && !http_credentials2->AuthnSchemes))
1426 return FALSE;
1427
1428 if (memcmp(http_credentials1->AuthnSchemes, http_credentials2->AuthnSchemes,
1429 http_credentials1->NumberOfAuthnSchemes * sizeof(http_credentials1->AuthnSchemes[0])))
1430 return FALSE;
1431
1432 /* server certificate subject not currently used */
1433
1434 if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
1435 {
1436 const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
1437 const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
1438
1439 if (!identity1 || !identity2)
1440 return FALSE;
1441
1442 /* compare user names */
1443 if (identity1->UserLength != identity2->UserLength ||
1444 memcmp(identity1->User, identity2->User, identity1->UserLength))
1445 return FALSE;
1446 /* compare domain names */
1447 if (identity1->DomainLength != identity2->DomainLength ||
1448 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
1449 return FALSE;
1450 /* compare passwords */
1451 if (identity1->PasswordLength != identity2->PasswordLength ||
1452 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
1453 return FALSE;
1454 }
1455 }
1456
1457 return TRUE;
1458 }
1459
1460 /***********************************************************************
1461 * RpcRevertToSelf (RPCRT4.@)
1462 */
RpcRevertToSelf(void)1463 RPC_STATUS WINAPI RpcRevertToSelf(void)
1464 {
1465 TRACE("\n");
1466 return RpcRevertToSelfEx(NULL);
1467 }
1468
1469 /***********************************************************************
1470 * RpcMgmtSetComTimeout (RPCRT4.@)
1471 */
RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle,unsigned int Timeout)1472 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
1473 {
1474 FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
1475 return RPC_S_OK;
1476 }
1477
1478 /***********************************************************************
1479 * RpcBindingInqAuthInfoExA (RPCRT4.@)
1480 */
1481 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoExA(RPC_BINDING_HANDLE Binding,RPC_CSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,RPC_AUTH_IDENTITY_HANDLE * AuthIdentity,ULONG * AuthzSvc,ULONG RpcQosVersion,RPC_SECURITY_QOS * SecurityQOS)1482 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1483 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1484 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1485 {
1486 RPC_STATUS status;
1487 RPC_WSTR principal;
1488
1489 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1490 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1491
1492 status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
1493 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1494 if (status == RPC_S_OK && ServerPrincName)
1495 {
1496 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1497 RpcStringFreeW(&principal);
1498 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1499 }
1500
1501 return status;
1502 }
1503
1504 /***********************************************************************
1505 * RpcBindingInqAuthInfoExW (RPCRT4.@)
1506 */
1507 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoExW(RPC_BINDING_HANDLE Binding,RPC_WSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,RPC_AUTH_IDENTITY_HANDLE * AuthIdentity,ULONG * AuthzSvc,ULONG RpcQosVersion,RPC_SECURITY_QOS * SecurityQOS)1508 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1509 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
1510 ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
1511 {
1512 RpcBinding *bind = Binding;
1513
1514 TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
1515 AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
1516
1517 if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
1518
1519 if (SecurityQOS)
1520 {
1521 FIXME("QOS not implemented\n");
1522 return RPC_S_INVALID_BINDING;
1523 }
1524
1525 if (ServerPrincName)
1526 {
1527 if (bind->AuthInfo->server_principal_name)
1528 {
1529 *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name);
1530 if (!*ServerPrincName) return RPC_S_OUT_OF_MEMORY;
1531 }
1532 else *ServerPrincName = NULL;
1533 }
1534 if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
1535 if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
1536 if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
1537 if (AuthzSvc)
1538 {
1539 FIXME("authorization service not implemented\n");
1540 *AuthzSvc = RPC_C_AUTHZ_NONE;
1541 }
1542
1543 return RPC_S_OK;
1544 }
1545
1546 /***********************************************************************
1547 * RpcBindingInqAuthInfoA (RPCRT4.@)
1548 */
1549 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoA(RPC_BINDING_HANDLE Binding,RPC_CSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,RPC_AUTH_IDENTITY_HANDLE * AuthIdentity,ULONG * AuthzSvc)1550 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
1551 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1552 {
1553 return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1554 AuthzSvc, 0, NULL);
1555 }
1556
1557 /***********************************************************************
1558 * RpcBindingInqAuthInfoW (RPCRT4.@)
1559 */
1560 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthInfoW(RPC_BINDING_HANDLE Binding,RPC_WSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,RPC_AUTH_IDENTITY_HANDLE * AuthIdentity,ULONG * AuthzSvc)1561 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
1562 ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
1563 {
1564 return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
1565 AuthzSvc, 0, NULL);
1566 }
1567
1568 /***********************************************************************
1569 * RpcBindingInqAuthClientA (RPCRT4.@)
1570 */
1571 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientA(RPC_BINDING_HANDLE ClientBinding,RPC_AUTHZ_HANDLE * Privs,RPC_CSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,ULONG * AuthzSvc)1572 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1573 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1574 ULONG *AuthzSvc )
1575 {
1576 return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1577 AuthnSvc, AuthzSvc, 0);
1578 }
1579
1580 /***********************************************************************
1581 * RpcBindingInqAuthClientW (RPCRT4.@)
1582 */
1583 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientW(RPC_BINDING_HANDLE ClientBinding,RPC_AUTHZ_HANDLE * Privs,RPC_WSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,ULONG * AuthzSvc)1584 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1585 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1586 ULONG *AuthzSvc )
1587 {
1588 return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
1589 AuthnSvc, AuthzSvc, 0);
1590 }
1591
1592 /***********************************************************************
1593 * RpcBindingInqAuthClientExA (RPCRT4.@)
1594 */
1595 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientExA(RPC_BINDING_HANDLE ClientBinding,RPC_AUTHZ_HANDLE * Privs,RPC_CSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,ULONG * AuthzSvc,ULONG Flags)1596 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1597 RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1598 ULONG *AuthzSvc, ULONG Flags )
1599 {
1600 RPC_STATUS status;
1601 RPC_WSTR principal;
1602
1603 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1604 AuthnSvc, AuthzSvc, Flags);
1605
1606 status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
1607 AuthnLevel, AuthnSvc, AuthzSvc, Flags);
1608 if (status == RPC_S_OK && ServerPrincName)
1609 {
1610 *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
1611 if (!*ServerPrincName && principal) status = RPC_S_OUT_OF_MEMORY;
1612 RpcStringFreeW(&principal);
1613 }
1614
1615 return status;
1616 }
1617
1618 /***********************************************************************
1619 * RpcBindingInqAuthClientExW (RPCRT4.@)
1620 */
1621 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingInqAuthClientExW(RPC_BINDING_HANDLE ClientBinding,RPC_AUTHZ_HANDLE * Privs,RPC_WSTR * ServerPrincName,ULONG * AuthnLevel,ULONG * AuthnSvc,ULONG * AuthzSvc,ULONG Flags)1622 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
1623 RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
1624 ULONG *AuthzSvc, ULONG Flags )
1625 {
1626 RpcBinding *bind;
1627
1628 TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
1629 AuthnSvc, AuthzSvc, Flags);
1630
1631 if (!ClientBinding) ClientBinding = I_RpcGetCurrentCallHandle();
1632 if (!ClientBinding) return RPC_S_INVALID_BINDING;
1633
1634 bind = ClientBinding;
1635 if (!bind->FromConn) return RPC_S_INVALID_BINDING;
1636
1637 return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
1638 ServerPrincName, AuthnLevel,
1639 AuthnSvc, AuthzSvc, Flags);
1640 }
1641
1642 /***********************************************************************
1643 * RpcBindingServerFromClient (RPCRT4.@)
1644 */
1645 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding,RPC_BINDING_HANDLE * ServerBinding)1646 RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding)
1647 {
1648 RpcBinding* bind = ClientBinding;
1649 RpcBinding* NewBinding;
1650
1651 if (!bind)
1652 bind = I_RpcGetCurrentCallHandle();
1653
1654 if (!bind->server)
1655 return RPC_S_INVALID_BINDING;
1656
1657 RPCRT4_AllocBinding(&NewBinding, TRUE);
1658 NewBinding->Protseq = RPCRT4_strdupA(bind->Protseq);
1659 NewBinding->NetworkAddr = RPCRT4_strdupA(bind->NetworkAddr);
1660
1661 *ServerBinding = NewBinding;
1662
1663 return RPC_S_OK;
1664 }
1665
1666 /***********************************************************************
1667 * RpcBindingSetAuthInfoExA (RPCRT4.@)
1668 */
1669 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoExA(RPC_BINDING_HANDLE Binding,RPC_CSTR ServerPrincName,ULONG AuthnLevel,ULONG AuthnSvc,RPC_AUTH_IDENTITY_HANDLE AuthIdentity,ULONG AuthzSvr,RPC_SECURITY_QOS * SecurityQos)1670 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
1671 ULONG AuthnLevel, ULONG AuthnSvc,
1672 RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1673 RPC_SECURITY_QOS *SecurityQos )
1674 {
1675 RpcBinding* bind = Binding;
1676 SECURITY_STATUS r;
1677 CredHandle cred;
1678 TimeStamp exp;
1679 ULONG package_count;
1680 ULONG i;
1681 PSecPkgInfoA packages;
1682 ULONG cbMaxToken;
1683
1684 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
1685 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1686
1687 if (SecurityQos)
1688 {
1689 RPC_STATUS status;
1690
1691 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1692 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1693 if (SecurityQos->Version >= 2)
1694 {
1695 const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
1696 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
1697 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1698 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1699 SecurityQos2->u.HttpCredentials->TransportCredentials,
1700 SecurityQos2->u.HttpCredentials->Flags,
1701 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1702 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1703 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1704 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1705 SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
1706 }
1707 TRACE("}\n");
1708 status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
1709 if (status != RPC_S_OK)
1710 return status;
1711 }
1712 else
1713 {
1714 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1715 bind->QOS = NULL;
1716 }
1717
1718 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1719 AuthnSvc = RPC_C_AUTHN_WINNT;
1720
1721 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1722 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1723 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1724
1725 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1726 {
1727 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1728 bind->AuthInfo = NULL;
1729 return RPC_S_OK;
1730 }
1731
1732 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1733 {
1734 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1735 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1736 }
1737
1738 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1739 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1740 {
1741 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1742 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1743 }
1744
1745 r = EnumerateSecurityPackagesA(&package_count, &packages);
1746 if (r != SEC_E_OK)
1747 {
1748 ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
1749 return RPC_S_SEC_PKG_ERROR;
1750 }
1751
1752 for (i = 0; i < package_count; i++)
1753 if (packages[i].wRPCID == AuthnSvc)
1754 break;
1755
1756 if (i == package_count)
1757 {
1758 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1759 FreeContextBuffer(packages);
1760 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1761 }
1762
1763 TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
1764 r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1765 AuthIdentity, NULL, NULL, &cred, &exp);
1766 cbMaxToken = packages[i].cbMaxToken;
1767 FreeContextBuffer(packages);
1768 if (r == ERROR_SUCCESS)
1769 {
1770 RpcAuthInfo *new_auth_info;
1771 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1772 AuthIdentity, &new_auth_info);
1773 if (r == RPC_S_OK)
1774 {
1775 new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
1776 if (!ServerPrincName || new_auth_info->server_principal_name)
1777 {
1778 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1779 bind->AuthInfo = new_auth_info;
1780 }
1781 else
1782 {
1783 RpcAuthInfo_Release(new_auth_info);
1784 r = RPC_S_OUT_OF_MEMORY;
1785 }
1786 }
1787 else
1788 FreeCredentialsHandle(&cred);
1789 return r;
1790 }
1791 else
1792 {
1793 ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
1794 return RPC_S_SEC_PKG_ERROR;
1795 }
1796 }
1797
1798 /***********************************************************************
1799 * RpcBindingSetAuthInfoExW (RPCRT4.@)
1800 */
1801 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoExW(RPC_BINDING_HANDLE Binding,RPC_WSTR ServerPrincName,ULONG AuthnLevel,ULONG AuthnSvc,RPC_AUTH_IDENTITY_HANDLE AuthIdentity,ULONG AuthzSvr,RPC_SECURITY_QOS * SecurityQos)1802 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1803 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
1804 RPC_SECURITY_QOS *SecurityQos )
1805 {
1806 RpcBinding* bind = Binding;
1807 SECURITY_STATUS r;
1808 CredHandle cred;
1809 TimeStamp exp;
1810 ULONG package_count;
1811 ULONG i;
1812 PSecPkgInfoW packages;
1813 ULONG cbMaxToken;
1814
1815 TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
1816 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
1817
1818 if (SecurityQos)
1819 {
1820 RPC_STATUS status;
1821
1822 TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
1823 SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
1824 if (SecurityQos->Version >= 2)
1825 {
1826 const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
1827 TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
1828 if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
1829 TRACE(", { %p, 0x%x, %d, %d, %p(%u), %s }",
1830 SecurityQos2->u.HttpCredentials->TransportCredentials,
1831 SecurityQos2->u.HttpCredentials->Flags,
1832 SecurityQos2->u.HttpCredentials->AuthenticationTarget,
1833 SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
1834 SecurityQos2->u.HttpCredentials->AuthnSchemes,
1835 SecurityQos2->u.HttpCredentials->AuthnSchemes ? *SecurityQos2->u.HttpCredentials->AuthnSchemes : 0,
1836 debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
1837 }
1838 TRACE("}\n");
1839 status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
1840 if (status != RPC_S_OK)
1841 return status;
1842 }
1843 else
1844 {
1845 if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
1846 bind->QOS = NULL;
1847 }
1848
1849 if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
1850 AuthnSvc = RPC_C_AUTHN_WINNT;
1851
1852 /* FIXME: the mapping should probably be retrieved using SSPI somehow */
1853 if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
1854 AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
1855
1856 if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
1857 {
1858 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1859 bind->AuthInfo = NULL;
1860 return RPC_S_OK;
1861 }
1862
1863 if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
1864 {
1865 FIXME("unknown AuthnLevel %u\n", AuthnLevel);
1866 return RPC_S_UNKNOWN_AUTHN_LEVEL;
1867 }
1868
1869 /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
1870 if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
1871 {
1872 FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
1873 return RPC_S_UNKNOWN_AUTHZ_SERVICE;
1874 }
1875
1876 r = EnumerateSecurityPackagesW(&package_count, &packages);
1877 if (r != SEC_E_OK)
1878 {
1879 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r);
1880 return RPC_S_SEC_PKG_ERROR;
1881 }
1882
1883 for (i = 0; i < package_count; i++)
1884 if (packages[i].wRPCID == AuthnSvc)
1885 break;
1886
1887 if (i == package_count)
1888 {
1889 FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
1890 FreeContextBuffer(packages);
1891 return RPC_S_UNKNOWN_AUTHN_SERVICE;
1892 }
1893
1894 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
1895 r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
1896 AuthIdentity, NULL, NULL, &cred, &exp);
1897 cbMaxToken = packages[i].cbMaxToken;
1898 FreeContextBuffer(packages);
1899 if (r == ERROR_SUCCESS)
1900 {
1901 RpcAuthInfo *new_auth_info;
1902 r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
1903 AuthIdentity, &new_auth_info);
1904 if (r == RPC_S_OK)
1905 {
1906 new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
1907 if (!ServerPrincName || new_auth_info->server_principal_name)
1908 {
1909 if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
1910 bind->AuthInfo = new_auth_info;
1911 }
1912 else
1913 {
1914 RpcAuthInfo_Release(new_auth_info);
1915 r = RPC_S_OUT_OF_MEMORY;
1916 }
1917 }
1918 else
1919 FreeCredentialsHandle(&cred);
1920 return r;
1921 }
1922 else
1923 {
1924 ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r);
1925 return RPC_S_SEC_PKG_ERROR;
1926 }
1927 }
1928
1929 /***********************************************************************
1930 * RpcBindingSetAuthInfoA (RPCRT4.@)
1931 */
1932 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoA(RPC_BINDING_HANDLE Binding,RPC_CSTR ServerPrincName,ULONG AuthnLevel,ULONG AuthnSvc,RPC_AUTH_IDENTITY_HANDLE AuthIdentity,ULONG AuthzSvr)1933 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
1934 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1935 {
1936 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
1937 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1938 return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1939 }
1940
1941 /***********************************************************************
1942 * RpcBindingSetAuthInfoW (RPCRT4.@)
1943 */
1944 RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoW(RPC_BINDING_HANDLE Binding,RPC_WSTR ServerPrincName,ULONG AuthnLevel,ULONG AuthnSvc,RPC_AUTH_IDENTITY_HANDLE AuthIdentity,ULONG AuthzSvr)1945 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
1946 ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
1947 {
1948 TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
1949 AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
1950 return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
1951 }
1952
1953 /***********************************************************************
1954 * RpcBindingSetOption (RPCRT4.@)
1955 */
RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle,ULONG Option,ULONG_PTR OptionValue)1956 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
1957 {
1958 TRACE("(%p, %d, %ld)\n", BindingHandle, Option, OptionValue);
1959
1960 switch (Option)
1961 {
1962 case RPC_C_OPT_COOKIE_AUTH:
1963 {
1964 RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *cookie = (RPC_C_OPT_COOKIE_AUTH_DESCRIPTOR *)OptionValue;
1965 RpcBinding *binding = BindingHandle;
1966 int len = MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, NULL, 0);
1967 WCHAR *str;
1968
1969 if (!(str = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)))) return RPC_S_OUT_OF_MEMORY;
1970 MultiByteToWideChar(CP_ACP, 0, cookie->Buffer, cookie->BufferSize, str, len);
1971 str[len] = 0;
1972 HeapFree(GetProcessHeap(), 0, binding->CookieAuth);
1973 binding->CookieAuth = str;
1974 break;
1975 }
1976 default:
1977 FIXME("option %u not supported\n", Option);
1978 break;
1979 }
1980 return RPC_S_OK;
1981 }
1982
1983 /***********************************************************************
1984 * I_RpcBindingInqLocalClientPID (RPCRT4.@)
1985 */
1986
I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding,ULONG * ClientPID)1987 RPC_STATUS WINAPI I_RpcBindingInqLocalClientPID(RPC_BINDING_HANDLE ClientBinding, ULONG *ClientPID)
1988 {
1989 FIXME("%p %p: stub\n", ClientBinding, ClientPID);
1990 return RPC_S_INVALID_BINDING;
1991 }
1992