4 * Copyright 2001 Ove Kåven, TransGaming Technologies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 #include "rpc_binding.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
43 LPSTR
RPCRT4_strndupA(LPSTR src
, INT slen
)
47 if (!src
) return NULL
;
48 if (slen
== -1) slen
= strlen(src
);
50 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
56 LPSTR
RPCRT4_strdupWtoA(LPWSTR src
)
60 if (!src
) return NULL
;
61 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
62 s
= HeapAlloc(GetProcessHeap(), 0, len
);
63 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
67 LPWSTR
RPCRT4_strdupAtoW(LPSTR src
)
71 if (!src
) return NULL
;
72 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
73 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
74 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
78 LPWSTR
RPCRT4_strndupW(LPWSTR src
, INT slen
)
82 if (!src
) return NULL
;
83 if (slen
== -1) slen
= strlenW(src
);
85 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
86 memcpy(s
, src
, len
*sizeof(WCHAR
));
91 void RPCRT4_strfree(LPSTR src
)
93 if (src
) HeapFree(GetProcessHeap(), 0, src
);
96 RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPSTR Protseq
)
98 RpcBinding
* NewBinding
;
100 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
101 NewBinding
->refs
= 1;
102 NewBinding
->server
= server
;
103 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
105 TRACE("binding: %p\n", NewBinding
);
106 *Binding
= NewBinding
;
111 RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPWSTR Protseq
)
113 RpcBinding
* NewBinding
;
115 TRACE("(*Binding == ^%p, server == %s, Protseq == \"%s\")\n", *Binding
, server
? "Yes" : "No", debugstr_w(Protseq
));
117 ERR("!RpcBinding?\n");
118 assert(FALSE
); /* we will crash below anyhow... */
121 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
122 NewBinding
->refs
= 1;
123 NewBinding
->server
= server
;
124 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
126 TRACE("binding: %p\n", NewBinding
);
127 *Binding
= NewBinding
;
132 RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
135 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
, NetworkAddr
, Endpoint
, NetworkOptions
);
137 RPCRT4_strfree(Binding
->NetworkAddr
);
138 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
139 RPCRT4_strfree(Binding
->Endpoint
);
140 if (Binding
->Endpoint
) {
141 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
143 Binding
->Endpoint
= RPCRT4_strdupA("");
149 RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPWSTR NetworkAddr
, LPWSTR Endpoint
, LPWSTR NetworkOptions
)
152 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
153 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
155 RPCRT4_strfree(Binding
->NetworkAddr
);
156 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
157 RPCRT4_strfree(Binding
->Endpoint
);
158 if (Binding
->Endpoint
) {
159 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
161 Binding
->Endpoint
= RPCRT4_strdupA("");
167 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPSTR Endpoint
)
169 RPCRT4_strfree(Binding
->Endpoint
);
170 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
175 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, UUID
* ObjectUuid
)
177 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
178 if (ObjectUuid
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
179 else UuidCreateNil(&Binding
->ObjectUuid
);
183 RPC_STATUS
RPCRT4_SpawnBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
185 RpcBinding
* NewBinding
;
187 TRACE("(*RpcBinding == ^%p, OldBinding == ^%p)\n", *Binding
, OldBinding
);
190 /* we will crash below anyhow... */
194 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
195 NewBinding
->refs
= 1;
196 NewBinding
->server
= OldBinding
->server
;
197 NewBinding
->Protseq
= RPCRT4_strdupA(OldBinding
->Protseq
);
198 NewBinding
->NetworkAddr
= RPCRT4_strdupA(OldBinding
->NetworkAddr
);
199 NewBinding
->Endpoint
= RPCRT4_strdupA(OldBinding
->Endpoint
);
200 /* because of the way named pipes work, we'll transfer the connected pipe
201 * to the child, then reopen the server binding to continue listening */
202 NewBinding
->conn
= OldBinding
->conn
;
203 NewBinding
->ovl
= OldBinding
->ovl
;
204 OldBinding
->conn
= 0;
205 memset(&OldBinding
->ovl
, 0, sizeof(OldBinding
->ovl
));
206 *Binding
= NewBinding
;
207 RPCRT4_OpenBinding(OldBinding
);
212 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
214 InterlockedIncrement(&OldBinding
->refs
);
215 *Binding
= OldBinding
;
219 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
221 if (InterlockedDecrement(&Binding
->refs
))
224 TRACE("binding: %p\n", Binding
);
225 RPCRT4_CloseBinding(Binding
);
226 RPCRT4_strfree(Binding
->Endpoint
);
227 RPCRT4_strfree(Binding
->NetworkAddr
);
228 RPCRT4_strfree(Binding
->Protseq
);
229 HeapFree(GetProcessHeap(), 0, Binding
);
233 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
)
235 TRACE("(Binding == ^%p)\n", Binding
);
236 if (!Binding
->conn
) {
237 if (Binding
->server
) { /* server */
238 /* protseq=ncalrpc: supposed to use NT LPC ports,
239 * but we'll implement it with named pipes for now */
240 if (strcmp(Binding
->Protseq
, "ncalrpc") == 0) {
241 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
243 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
244 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
245 TRACE("listening on %s\n", pname
);
246 Binding
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
247 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
248 HeapFree(GetProcessHeap(), 0, pname
);
249 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
250 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
251 if (!ConnectNamedPipe(Binding
->conn
, &Binding
->ovl
)) {
252 DWORD err
= GetLastError();
253 if (err
== ERROR_PIPE_CONNECTED
) {
254 SetEvent(Binding
->ovl
.hEvent
);
260 /* protseq=ncacn_np: named pipes */
261 else if (strcmp(Binding
->Protseq
, "ncacn_np") == 0) {
262 static LPSTR prefix
= "\\\\.";
264 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
265 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
266 TRACE("listening on %s\n", pname
);
267 Binding
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
268 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
269 HeapFree(GetProcessHeap(), 0, pname
);
270 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
271 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
272 if (!ConnectNamedPipe(Binding
->conn
, &Binding
->ovl
)) {
273 DWORD err
= GetLastError();
274 if (err
== ERROR_PIPE_CONNECTED
) {
275 SetEvent(Binding
->ovl
.hEvent
);
282 ERR("protseq %s not supported\n", Binding
->Protseq
);
283 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
287 /* protseq=ncalrpc: supposed to use NT LPC ports,
288 * but we'll implement it with named pipes for now */
289 if (strcmp(Binding
->Protseq
, "ncalrpc") == 0) {
290 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
295 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
296 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
297 TRACE("connecting to %s\n", pname
);
299 if (WaitNamedPipeA(pname
, NMPWAIT_WAIT_FOREVER
)) {
300 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
301 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
302 if (conn
!= INVALID_HANDLE_VALUE
) break;
303 err
= GetLastError();
304 if (err
== ERROR_PIPE_BUSY
) continue;
305 TRACE("connection failed, error=%lx\n", err
);
306 HeapFree(GetProcessHeap(), 0, pname
);
309 err
= GetLastError();
310 TRACE("connection failed, error=%lx\n", err
);
311 HeapFree(GetProcessHeap(), 0, pname
);
317 HeapFree(GetProcessHeap(), 0, pname
);
318 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
319 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
320 Binding
->conn
= conn
;
322 /* protseq=ncacn_np: named pipes */
323 else if (strcmp(Binding
->Protseq
, "ncacn_np") == 0) {
324 static LPSTR prefix
= "\\\\.";
329 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
330 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
331 TRACE("connecting to %s\n", pname
);
332 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
333 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
334 if (conn
== INVALID_HANDLE_VALUE
) {
335 err
= GetLastError();
336 /* we don't need to handle ERROR_PIPE_BUSY here,
337 * the doc says that it is returned to the app */
338 TRACE("connection failed, error=%lx\n", err
);
339 HeapFree(GetProcessHeap(), 0, pname
);
344 HeapFree(GetProcessHeap(), 0, pname
);
345 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
346 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
347 Binding
->conn
= conn
;
349 ERR("protseq %s not supported\n", Binding
->Protseq
);
350 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
357 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
)
359 TRACE("(Binding == ^%p)\n", Binding
);
361 CancelIo(Binding
->conn
);
362 CloseHandle(Binding
->conn
);
365 if (Binding
->ovl
.hEvent
) {
366 CloseHandle(Binding
->ovl
.hEvent
);
367 Binding
->ovl
.hEvent
= 0;
372 /* utility functions for string composing and parsing */
373 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
375 unsigned len
= strlen(src
);
376 memcpy(data
, src
, len
*sizeof(CHAR
));
380 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
382 unsigned len
= strlenW(src
);
383 memcpy(data
, src
, len
*sizeof(WCHAR
));
387 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
389 DWORD len
= strlen(dst
), slen
= strlen(src
);
390 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
391 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
393 memcpy(ndst
+len
+1, src
, slen
*sizeof(CHAR
));
394 ndst
[len
+slen
+1] = 0;
398 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
400 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
401 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
402 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
404 memcpy(ndst
+len
+1, src
, slen
*sizeof(WCHAR
));
405 ndst
[len
+slen
+1] = 0;
410 /***********************************************************************
411 * RpcStringBindingComposeA (RPCRT4.@)
413 RPC_STATUS WINAPI
RpcStringBindingComposeA( LPSTR ObjUuid
, LPSTR Protseq
,
414 LPSTR NetworkAddr
, LPSTR Endpoint
,
415 LPSTR Options
, LPSTR
* StringBinding
)
420 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
421 debugstr_a( ObjUuid
), debugstr_a( Protseq
),
422 debugstr_a( NetworkAddr
), debugstr_a( Endpoint
),
423 debugstr_a( Options
), StringBinding
);
425 if (ObjUuid
&& *ObjUuid
) len
+= strlen(ObjUuid
) + 1;
426 if (Protseq
&& *Protseq
) len
+= strlen(Protseq
) + 1;
427 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen(NetworkAddr
);
428 if (Endpoint
&& *Endpoint
) len
+= strlen(Endpoint
) + 2;
429 if (Options
&& *Options
) len
+= strlen(Options
) + 2;
431 data
= HeapAlloc(GetProcessHeap(), 0, len
);
432 *StringBinding
= data
;
434 if (ObjUuid
&& *ObjUuid
) {
435 data
+= RPCRT4_strcopyA(data
, ObjUuid
);
438 if (Protseq
&& *Protseq
) {
439 data
+= RPCRT4_strcopyA(data
, Protseq
);
442 if (NetworkAddr
&& *NetworkAddr
)
443 data
+= RPCRT4_strcopyA(data
, NetworkAddr
);
445 if ((Endpoint
&& *Endpoint
) ||
446 (Options
&& *Options
)) {
448 if (Endpoint
&& *Endpoint
) {
449 data
+= RPCRT4_strcopyA(data
, Endpoint
);
450 if (Options
&& *Options
) *data
++ = ',';
452 if (Options
&& *Options
) {
453 data
+= RPCRT4_strcopyA(data
, Options
);
462 /***********************************************************************
463 * RpcStringBindingComposeW (RPCRT4.@)
465 RPC_STATUS WINAPI
RpcStringBindingComposeW( LPWSTR ObjUuid
, LPWSTR Protseq
,
466 LPWSTR NetworkAddr
, LPWSTR Endpoint
,
467 LPWSTR Options
, LPWSTR
* StringBinding
)
472 TRACE("(%s,%s,%s,%s,%s,%p)\n",
473 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
474 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
475 debugstr_w( Options
), StringBinding
);
477 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
478 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
479 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
480 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
481 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
483 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
484 *StringBinding
= data
;
486 if (ObjUuid
&& *ObjUuid
) {
487 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
490 if (Protseq
&& *Protseq
) {
491 data
+= RPCRT4_strcopyW(data
, Protseq
);
494 if (NetworkAddr
&& *NetworkAddr
) {
495 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
497 if ((Endpoint
&& *Endpoint
) ||
498 (Options
&& *Options
)) {
500 if (Endpoint
&& *Endpoint
) {
501 data
+= RPCRT4_strcopyW(data
, Endpoint
);
502 if (Options
&& *Options
) *data
++ = ',';
504 if (Options
&& *Options
) {
505 data
+= RPCRT4_strcopyW(data
, Options
);
515 /***********************************************************************
516 * RpcStringBindingParseA (RPCRT4.@)
518 RPC_STATUS WINAPI
RpcStringBindingParseA( LPSTR StringBinding
, LPSTR
*ObjUuid
,
519 LPSTR
*Protseq
, LPSTR
*NetworkAddr
,
520 LPSTR
*Endpoint
, LPSTR
*Options
)
523 static const char ep_opt
[] = "endpoint=";
525 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding
),
526 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
528 if (ObjUuid
) *ObjUuid
= NULL
;
529 if (Protseq
) *Protseq
= NULL
;
530 if (NetworkAddr
) *NetworkAddr
= NULL
;
531 if (Endpoint
) *Endpoint
= NULL
;
532 if (Options
) *Options
= NULL
;
534 data
= StringBinding
;
536 next
= strchr(data
, '@');
538 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupA(data
, next
- data
);
542 next
= strchr(data
, ':');
544 if (Protseq
) *Protseq
= RPCRT4_strndupA(data
, next
- data
);
548 next
= strchr(data
, '[');
552 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupA(data
, next
- data
);
554 close
= strchr(data
, ']');
555 if (!close
) goto fail
;
557 /* tokenize options */
558 while (data
< close
) {
559 next
= strchr(data
, ',');
560 if (!next
|| next
> close
) next
= close
;
561 /* FIXME: this is kind of inefficient */
562 opt
= RPCRT4_strndupA(data
, next
- data
);
566 next
= strchr(opt
, '=');
568 /* not an option, must be an endpoint */
569 if (*Endpoint
) goto fail
;
572 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
573 /* endpoint option */
574 if (*Endpoint
) goto fail
;
575 *Endpoint
= RPCRT4_strdupA(next
+1);
576 HeapFree(GetProcessHeap(), 0, opt
);
580 /* FIXME: this is kind of inefficient */
581 *Options
= RPCRT4_strconcatA(*Options
, opt
);
582 HeapFree(GetProcessHeap(), 0, opt
);
590 if (*data
) goto fail
;
592 else if (NetworkAddr
)
593 *NetworkAddr
= RPCRT4_strdupA(data
);
598 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
599 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
600 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
601 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
602 if (Options
) RpcStringFreeA((unsigned char**)Options
);
603 return RPC_S_INVALID_STRING_BINDING
;
606 /***********************************************************************
607 * RpcStringBindingParseW (RPCRT4.@)
609 RPC_STATUS WINAPI
RpcStringBindingParseW( LPWSTR StringBinding
, LPWSTR
*ObjUuid
,
610 LPWSTR
*Protseq
, LPWSTR
*NetworkAddr
,
611 LPWSTR
*Endpoint
, LPWSTR
*Options
)
614 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
616 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
617 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
619 if (ObjUuid
) *ObjUuid
= NULL
;
620 if (Protseq
) *Protseq
= NULL
;
621 if (NetworkAddr
) *NetworkAddr
= NULL
;
622 if (Endpoint
) *Endpoint
= NULL
;
623 if (Options
) *Options
= NULL
;
625 data
= StringBinding
;
627 next
= strchrW(data
, '@');
629 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
633 next
= strchrW(data
, ':');
635 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
639 next
= strchrW(data
, '[');
643 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
645 close
= strchrW(data
, ']');
646 if (!close
) goto fail
;
648 /* tokenize options */
649 while (data
< close
) {
650 next
= strchrW(data
, ',');
651 if (!next
|| next
> close
) next
= close
;
652 /* FIXME: this is kind of inefficient */
653 opt
= RPCRT4_strndupW(data
, next
- data
);
657 next
= strchrW(opt
, '=');
659 /* not an option, must be an endpoint */
660 if (*Endpoint
) goto fail
;
663 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
664 /* endpoint option */
665 if (*Endpoint
) goto fail
;
666 *Endpoint
= RPCRT4_strdupW(next
+1);
667 HeapFree(GetProcessHeap(), 0, opt
);
671 /* FIXME: this is kind of inefficient */
672 *Options
= RPCRT4_strconcatW(*Options
, opt
);
673 HeapFree(GetProcessHeap(), 0, opt
);
681 if (*data
) goto fail
;
682 } else if (NetworkAddr
)
683 *NetworkAddr
= RPCRT4_strdupW(data
);
688 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
689 if (Protseq
) RpcStringFreeW(Protseq
);
690 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
691 if (Endpoint
) RpcStringFreeW(Endpoint
);
692 if (Options
) RpcStringFreeW(Options
);
693 return RPC_S_INVALID_STRING_BINDING
;
696 /***********************************************************************
697 * RpcBindingFree (RPCRT4.@)
699 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
702 TRACE("(%p) = %p\n", Binding
, *Binding
);
703 status
= RPCRT4_DestroyBinding(*Binding
);
704 if (status
== RPC_S_OK
) *Binding
= 0;
708 /***********************************************************************
709 * RpcBindingVectorFree (RPCRT4.@)
711 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
716 TRACE("(%p)\n", BindingVector
);
717 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
718 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
720 HeapFree(GetProcessHeap(), 0, *BindingVector
);
721 *BindingVector
= NULL
;
725 /***********************************************************************
726 * RpcBindingInqObject (RPCRT4.@)
728 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
730 RpcBinding
* bind
= (RpcBinding
*)Binding
;
732 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
733 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
737 /***********************************************************************
738 * RpcBindingSetObject (RPCRT4.@)
740 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
742 RpcBinding
* bind
= (RpcBinding
*)Binding
;
744 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
745 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
746 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
749 /***********************************************************************
750 * RpcBindingFromStringBindingA (RPCRT4.@)
752 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( LPSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
755 RpcBinding
* bind
= NULL
;
756 LPSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
759 TRACE("(%s,%p)\n", debugstr_a(StringBinding
), Binding
);
761 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
762 &NetworkAddr
, &Endpoint
, &Options
);
763 if (ret
!= RPC_S_OK
) return ret
;
765 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
768 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, Protseq
);
770 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
772 ret
= RPCRT4_CompleteBindingA(bind
, NetworkAddr
, Endpoint
, Options
);
774 RpcStringFreeA((unsigned char**)&Options
);
775 RpcStringFreeA((unsigned char**)&Endpoint
);
776 RpcStringFreeA((unsigned char**)&NetworkAddr
);
777 RpcStringFreeA((unsigned char**)&Protseq
);
778 RpcStringFreeA((unsigned char**)&ObjectUuid
);
781 *Binding
= (RPC_BINDING_HANDLE
)bind
;
783 RPCRT4_DestroyBinding(bind
);
788 /***********************************************************************
789 * RpcBindingFromStringBindingW (RPCRT4.@)
791 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( LPWSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
794 RpcBinding
* bind
= NULL
;
795 LPWSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
798 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
800 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
801 &NetworkAddr
, &Endpoint
, &Options
);
802 if (ret
!= RPC_S_OK
) return ret
;
804 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
807 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
809 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
811 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
813 RpcStringFreeW(&Options
);
814 RpcStringFreeW(&Endpoint
);
815 RpcStringFreeW(&NetworkAddr
);
816 RpcStringFreeW(&Protseq
);
817 RpcStringFreeW(&ObjectUuid
);
820 *Binding
= (RPC_BINDING_HANDLE
)bind
;
822 RPCRT4_DestroyBinding(bind
);
827 /***********************************************************************
828 * RpcBindingToStringBindingA (RPCRT4.@)
830 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, LPSTR
* StringBinding
)
833 RpcBinding
* bind
= (RpcBinding
*)Binding
;
836 TRACE("(%p,%p)\n", Binding
, StringBinding
);
838 ret
= UuidToStringA(&bind
->ObjectUuid
, (unsigned char**)&ObjectUuid
);
839 if (ret
!= RPC_S_OK
) return ret
;
841 ret
= RpcStringBindingComposeA(ObjectUuid
, bind
->Protseq
, bind
->NetworkAddr
,
842 bind
->Endpoint
, NULL
, StringBinding
);
844 RpcStringFreeA((unsigned char**)&ObjectUuid
);
849 /***********************************************************************
850 * RpcBindingToStringBindingW (RPCRT4.@)
852 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, LPWSTR
* StringBinding
)
856 TRACE("(%p,%p)\n", Binding
, StringBinding
);
857 ret
= RpcBindingToStringBindingA(Binding
, &str
);
858 *StringBinding
= RPCRT4_strdupAtoW(str
);
859 RpcStringFreeA((unsigned char**)&str
);
863 /***********************************************************************
864 * I_RpcBindingSetAsync (RPCRT4.@)
866 * Exists in win9x and winNT, but with different number of arguments
867 * (9x version has 3 arguments, NT has 2).
869 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
871 RpcBinding
* bind
= (RpcBinding
*)Binding
;
873 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
875 bind
->BlockingFn
= BlockingFn
;