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
32 #include "wine/unicode.h"
36 #include "wine/debug.h"
38 #include "rpc_binding.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
42 LPSTR
RPCRT4_strndupA(LPSTR src
, INT slen
)
46 if (!src
) return NULL
;
47 if (slen
== -1) slen
= strlen(src
);
49 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
55 LPSTR
RPCRT4_strdupWtoA(LPWSTR src
)
59 if (!src
) return NULL
;
60 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
61 s
= HeapAlloc(GetProcessHeap(), 0, len
);
62 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
66 LPWSTR
RPCRT4_strdupAtoW(LPSTR src
)
70 if (!src
) return NULL
;
71 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
72 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
73 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
77 LPWSTR
RPCRT4_strndupW(LPWSTR src
, INT slen
)
81 if (!src
) return NULL
;
82 if (slen
== -1) slen
= strlenW(src
);
84 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
85 memcpy(s
, src
, len
*sizeof(WCHAR
));
90 void RPCRT4_strfree(LPSTR src
)
92 if (src
) HeapFree(GetProcessHeap(), 0, src
);
95 RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPSTR Protseq
)
97 RpcBinding
* NewBinding
;
99 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
100 NewBinding
->refs
= 1;
101 NewBinding
->server
= server
;
102 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
104 TRACE("binding: %p\n", NewBinding
);
105 *Binding
= NewBinding
;
110 RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPWSTR Protseq
)
112 RpcBinding
* NewBinding
;
114 TRACE(" (*Binding == ^%p, server == %s, Protseq == \"%s\")\n", *Binding
, server
? "Yes" : "No", debugstr_w(Protseq
));
116 ERR("!RpcBinding?\n");
117 *((char *)0) = 0; /* we will crash below anyhow... */
120 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
121 NewBinding
->refs
= 1;
122 NewBinding
->server
= server
;
123 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
125 TRACE("binding: %p\n", NewBinding
);
126 *Binding
= NewBinding
;
131 RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
134 TRACE(" (RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
, NetworkAddr
, Endpoint
, NetworkOptions
);
136 RPCRT4_strfree(Binding
->NetworkAddr
);
137 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
138 RPCRT4_strfree(Binding
->Endpoint
);
139 if (Binding
->Endpoint
) {
140 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
142 Binding
->Endpoint
= RPCRT4_strdupA("");
148 RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPWSTR NetworkAddr
, LPWSTR Endpoint
, LPWSTR NetworkOptions
)
151 TRACE(" (RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
152 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
154 RPCRT4_strfree(Binding
->NetworkAddr
);
155 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
156 RPCRT4_strfree(Binding
->Endpoint
);
157 if (Binding
->Endpoint
) {
158 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
160 Binding
->Endpoint
= RPCRT4_strdupA("");
166 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPSTR Endpoint
)
168 RPCRT4_strfree(Binding
->Endpoint
);
169 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
174 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, UUID
* ObjectUuid
)
176 TRACE(" (*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
177 if (ObjectUuid
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
178 else UuidCreateNil(&Binding
->ObjectUuid
);
182 RPC_STATUS
RPCRT4_SpawnBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
184 RpcBinding
* NewBinding
;
186 TRACE(" (*RpcBinding == ^%p, OldBinding == ^%p)\n", *Binding
, OldBinding
);
189 /* we will crash below anyhow... */
193 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
194 NewBinding
->refs
= 1;
195 NewBinding
->server
= OldBinding
->server
;
196 NewBinding
->Protseq
= RPCRT4_strdupA(OldBinding
->Protseq
);
197 NewBinding
->NetworkAddr
= RPCRT4_strdupA(OldBinding
->NetworkAddr
);
198 NewBinding
->Endpoint
= RPCRT4_strdupA(OldBinding
->Endpoint
);
199 /* because of the way named pipes work, we'll transfer the connected pipe
200 * to the child, then reopen the server binding to continue listening */
201 NewBinding
->conn
= OldBinding
->conn
;
202 NewBinding
->ovl
= OldBinding
->ovl
;
203 OldBinding
->conn
= 0;
204 memset(&OldBinding
->ovl
, 0, sizeof(OldBinding
->ovl
));
205 *Binding
= NewBinding
;
206 RPCRT4_OpenBinding(OldBinding
);
211 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
213 InterlockedIncrement(&OldBinding
->refs
);
214 *Binding
= OldBinding
;
218 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
220 if (InterlockedDecrement(&Binding
->refs
))
223 TRACE("binding: %p\n", Binding
);
224 RPCRT4_CloseBinding(Binding
);
225 RPCRT4_strfree(Binding
->Endpoint
);
226 RPCRT4_strfree(Binding
->NetworkAddr
);
227 RPCRT4_strfree(Binding
->Protseq
);
228 HeapFree(GetProcessHeap(), 0, Binding
);
232 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
)
234 TRACE(" (Binding == ^%p)\n", Binding
);
235 if (!Binding
->conn
) {
236 if (Binding
->server
) { /* server */
237 /* protseq=ncalrpc: supposed to use NT LPC ports,
238 * but we'll implement it with named pipes for now */
239 if (strcmp(Binding
->Protseq
, "ncalrpc") == 0) {
240 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
242 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
243 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
244 TRACE("listening on %s\n", pname
);
245 Binding
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
246 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
247 HeapFree(GetProcessHeap(), 0, pname
);
248 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
249 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
250 if (!ConnectNamedPipe(Binding
->conn
, &Binding
->ovl
)) {
251 DWORD err
= GetLastError();
252 if (err
== ERROR_PIPE_CONNECTED
) {
253 SetEvent(Binding
->ovl
.hEvent
);
259 /* protseq=ncacn_np: named pipes */
260 else if (strcmp(Binding
->Protseq
, "ncacn_np") == 0) {
261 static LPSTR prefix
= "\\\\.";
263 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
264 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
265 TRACE("listening on %s\n", pname
);
266 Binding
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
267 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
268 HeapFree(GetProcessHeap(), 0, pname
);
269 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
270 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
271 if (!ConnectNamedPipe(Binding
->conn
, &Binding
->ovl
)) {
272 DWORD err
= GetLastError();
273 if (err
== ERROR_PIPE_CONNECTED
) {
274 SetEvent(Binding
->ovl
.hEvent
);
281 ERR("protseq %s not supported\n", Binding
->Protseq
);
282 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
286 /* protseq=ncalrpc: supposed to use NT LPC ports,
287 * but we'll implement it with named pipes for now */
288 if (strcmp(Binding
->Protseq
, "ncalrpc") == 0) {
289 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
294 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
295 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
296 TRACE("connecting to %s\n", pname
);
298 if (WaitNamedPipeA(pname
, NMPWAIT_WAIT_FOREVER
)) {
299 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
300 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
301 if (conn
!= INVALID_HANDLE_VALUE
) break;
302 err
= GetLastError();
303 if (err
== ERROR_PIPE_BUSY
) continue;
304 TRACE("connection failed, error=%lx\n", err
);
305 HeapFree(GetProcessHeap(), 0, pname
);
308 err
= GetLastError();
309 TRACE("connection failed, error=%lx\n", err
);
310 HeapFree(GetProcessHeap(), 0, pname
);
316 HeapFree(GetProcessHeap(), 0, pname
);
317 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
318 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
319 Binding
->conn
= conn
;
321 /* protseq=ncacn_np: named pipes */
322 else if (strcmp(Binding
->Protseq
, "ncacn_np") == 0) {
323 static LPSTR prefix
= "\\\\.";
328 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Binding
->Endpoint
) + 1);
329 strcat(strcpy(pname
, prefix
), Binding
->Endpoint
);
330 TRACE("connecting to %s\n", pname
);
331 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
332 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
333 if (conn
== INVALID_HANDLE_VALUE
) {
334 err
= GetLastError();
335 /* we don't need to handle ERROR_PIPE_BUSY here,
336 * the doc says that it is returned to the app */
337 TRACE("connection failed, error=%lx\n", err
);
338 HeapFree(GetProcessHeap(), 0, pname
);
343 HeapFree(GetProcessHeap(), 0, pname
);
344 memset(&Binding
->ovl
, 0, sizeof(Binding
->ovl
));
345 Binding
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
346 Binding
->conn
= conn
;
348 ERR("protseq %s not supported\n", Binding
->Protseq
);
349 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
356 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
)
358 TRACE(" (Binding == ^%p)\n", Binding
);
360 CancelIo(Binding
->conn
);
361 CloseHandle(Binding
->conn
);
364 if (Binding
->ovl
.hEvent
) {
365 CloseHandle(Binding
->ovl
.hEvent
);
366 Binding
->ovl
.hEvent
= 0;
371 /* utility functions for string composing and parsing */
372 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
374 unsigned len
= strlen(src
);
375 memcpy(data
, src
, len
*sizeof(CHAR
));
379 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
381 unsigned len
= strlenW(src
);
382 memcpy(data
, src
, len
*sizeof(WCHAR
));
386 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
388 DWORD len
= strlen(dst
), slen
= strlen(src
);
389 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
390 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
392 memcpy(ndst
+len
+1, src
, slen
*sizeof(CHAR
));
393 ndst
[len
+slen
+1] = 0;
397 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
399 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
400 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
401 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
403 memcpy(ndst
+len
+1, src
, slen
*sizeof(WCHAR
));
404 ndst
[len
+slen
+1] = 0;
409 /***********************************************************************
410 * RpcStringBindingComposeA (RPCRT4.@)
412 RPC_STATUS WINAPI
RpcStringBindingComposeA( LPSTR ObjUuid
, LPSTR Protseq
,
413 LPSTR NetworkAddr
, LPSTR Endpoint
,
414 LPSTR Options
, LPSTR
* StringBinding
)
419 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
420 debugstr_a( ObjUuid
), debugstr_a( Protseq
),
421 debugstr_a( NetworkAddr
), debugstr_a( Endpoint
),
422 debugstr_a( Options
), StringBinding
);
424 if (ObjUuid
&& *ObjUuid
) len
+= strlen(ObjUuid
) + 1;
425 if (Protseq
&& *Protseq
) len
+= strlen(Protseq
) + 1;
426 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen(NetworkAddr
);
427 if (Endpoint
&& *Endpoint
) len
+= strlen(Endpoint
) + 2;
428 if (Options
&& *Options
) len
+= strlen(Options
) + 2;
430 data
= HeapAlloc(GetProcessHeap(), 0, len
);
431 *StringBinding
= data
;
433 if (ObjUuid
&& *ObjUuid
) {
434 data
+= RPCRT4_strcopyA(data
, ObjUuid
);
437 if (Protseq
&& *Protseq
) {
438 data
+= RPCRT4_strcopyA(data
, Protseq
);
441 if (NetworkAddr
&& *NetworkAddr
)
442 data
+= RPCRT4_strcopyA(data
, NetworkAddr
);
444 if ((Endpoint
&& *Endpoint
) ||
445 (Options
&& *Options
)) {
447 if (Endpoint
&& *Endpoint
) {
448 data
+= RPCRT4_strcopyA(data
, Endpoint
);
449 if (Options
&& *Options
) *data
++ = ',';
451 if (Options
&& *Options
) {
452 data
+= RPCRT4_strcopyA(data
, Options
);
461 /***********************************************************************
462 * RpcStringBindingComposeW (RPCRT4.@)
464 RPC_STATUS WINAPI
RpcStringBindingComposeW( LPWSTR ObjUuid
, LPWSTR Protseq
,
465 LPWSTR NetworkAddr
, LPWSTR Endpoint
,
466 LPWSTR Options
, LPWSTR
* StringBinding
)
471 TRACE("(%s,%s,%s,%s,%s,%p)\n",
472 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
473 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
474 debugstr_w( Options
), StringBinding
);
476 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
477 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
478 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
479 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
480 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
482 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
483 *StringBinding
= data
;
485 if (ObjUuid
&& *ObjUuid
) {
486 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
489 if (Protseq
&& *Protseq
) {
490 data
+= RPCRT4_strcopyW(data
, Protseq
);
493 if (NetworkAddr
&& *NetworkAddr
) {
494 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
496 if ((Endpoint
&& *Endpoint
) ||
497 (Options
&& *Options
)) {
499 if (Endpoint
&& *Endpoint
) {
500 data
+= RPCRT4_strcopyW(data
, Endpoint
);
501 if (Options
&& *Options
) *data
++ = ',';
503 if (Options
&& *Options
) {
504 data
+= RPCRT4_strcopyW(data
, Options
);
514 /***********************************************************************
515 * RpcStringBindingParseA (RPCRT4.@)
517 RPC_STATUS WINAPI
RpcStringBindingParseA( LPSTR StringBinding
, LPSTR
*ObjUuid
,
518 LPSTR
*Protseq
, LPSTR
*NetworkAddr
,
519 LPSTR
*Endpoint
, LPSTR
*Options
)
522 static const char ep_opt
[] = "endpoint=";
524 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding
),
525 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
527 if (ObjUuid
) *ObjUuid
= NULL
;
528 if (Protseq
) *Protseq
= NULL
;
529 if (NetworkAddr
) *NetworkAddr
= NULL
;
530 if (Endpoint
) *Endpoint
= NULL
;
531 if (Options
) *Options
= NULL
;
533 data
= StringBinding
;
535 next
= strchr(data
, '@');
537 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupA(data
, next
- data
);
541 next
= strchr(data
, ':');
543 if (Protseq
) *Protseq
= RPCRT4_strndupA(data
, next
- data
);
547 next
= strchr(data
, '[');
551 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupA(data
, next
- data
);
553 close
= strchr(data
, ']');
554 if (!close
) goto fail
;
556 /* tokenize options */
557 while (data
< close
) {
558 next
= strchr(data
, ',');
559 if (!next
|| next
> close
) next
= close
;
560 /* FIXME: this is kind of inefficient */
561 opt
= RPCRT4_strndupA(data
, next
- data
);
565 next
= strchr(opt
, '=');
567 /* not an option, must be an endpoint */
568 if (*Endpoint
) goto fail
;
571 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
572 /* endpoint option */
573 if (*Endpoint
) goto fail
;
574 *Endpoint
= RPCRT4_strdupA(next
+1);
575 HeapFree(GetProcessHeap(), 0, opt
);
579 /* FIXME: this is kind of inefficient */
580 *Options
= RPCRT4_strconcatA(*Options
, opt
);
581 HeapFree(GetProcessHeap(), 0, opt
);
589 if (*data
) goto fail
;
591 else if (NetworkAddr
)
592 *NetworkAddr
= RPCRT4_strdupA(data
);
597 if (ObjUuid
) RpcStringFreeA(ObjUuid
);
598 if (Protseq
) RpcStringFreeA(Protseq
);
599 if (NetworkAddr
) RpcStringFreeA(NetworkAddr
);
600 if (Endpoint
) RpcStringFreeA(Endpoint
);
601 if (Options
) RpcStringFreeA(Options
);
602 return RPC_S_INVALID_STRING_BINDING
;
605 /***********************************************************************
606 * RpcStringBindingParseW (RPCRT4.@)
608 RPC_STATUS WINAPI
RpcStringBindingParseW( LPWSTR StringBinding
, LPWSTR
*ObjUuid
,
609 LPWSTR
*Protseq
, LPWSTR
*NetworkAddr
,
610 LPWSTR
*Endpoint
, LPWSTR
*Options
)
613 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
615 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
616 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
618 if (ObjUuid
) *ObjUuid
= NULL
;
619 if (Protseq
) *Protseq
= NULL
;
620 if (NetworkAddr
) *NetworkAddr
= NULL
;
621 if (Endpoint
) *Endpoint
= NULL
;
622 if (Options
) *Options
= NULL
;
624 data
= StringBinding
;
626 next
= strchrW(data
, '@');
628 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
632 next
= strchrW(data
, ':');
634 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
638 next
= strchrW(data
, '[');
642 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
644 close
= strchrW(data
, ']');
645 if (!close
) goto fail
;
647 /* tokenize options */
648 while (data
< close
) {
649 next
= strchrW(data
, ',');
650 if (!next
|| next
> close
) next
= close
;
651 /* FIXME: this is kind of inefficient */
652 opt
= RPCRT4_strndupW(data
, next
- data
);
656 next
= strchrW(opt
, '=');
658 /* not an option, must be an endpoint */
659 if (*Endpoint
) goto fail
;
662 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
663 /* endpoint option */
664 if (*Endpoint
) goto fail
;
665 *Endpoint
= RPCRT4_strdupW(next
+1);
666 HeapFree(GetProcessHeap(), 0, opt
);
670 /* FIXME: this is kind of inefficient */
671 *Options
= RPCRT4_strconcatW(*Options
, opt
);
672 HeapFree(GetProcessHeap(), 0, opt
);
680 if (*data
) goto fail
;
681 } else if (NetworkAddr
)
682 *NetworkAddr
= RPCRT4_strdupW(data
);
687 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
688 if (Protseq
) RpcStringFreeW(Protseq
);
689 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
690 if (Endpoint
) RpcStringFreeW(Endpoint
);
691 if (Options
) RpcStringFreeW(Options
);
692 return RPC_S_INVALID_STRING_BINDING
;
695 /***********************************************************************
696 * RpcBindingFree (RPCRT4.@)
698 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
701 TRACE("(%p) = %p\n", Binding
, *Binding
);
702 status
= RPCRT4_DestroyBinding(*Binding
);
703 if (status
== RPC_S_OK
) *Binding
= 0;
707 /***********************************************************************
708 * RpcBindingVectorFree (RPCRT4.@)
710 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
715 TRACE("(%p)\n", BindingVector
);
716 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
717 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
719 HeapFree(GetProcessHeap(), 0, *BindingVector
);
720 *BindingVector
= NULL
;
724 /***********************************************************************
725 * RpcBindingInqObject (RPCRT4.@)
727 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
729 RpcBinding
* bind
= (RpcBinding
*)Binding
;
731 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
732 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
736 /***********************************************************************
737 * RpcBindingSetObject (RPCRT4.@)
739 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
741 RpcBinding
* bind
= (RpcBinding
*)Binding
;
743 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
744 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
745 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
748 /***********************************************************************
749 * RpcBindingFromStringBindingA (RPCRT4.@)
751 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( LPSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
754 RpcBinding
* bind
= NULL
;
755 LPSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
758 TRACE("(%s,%p)\n", debugstr_a(StringBinding
), Binding
);
760 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
761 &NetworkAddr
, &Endpoint
, &Options
);
762 if (ret
!= RPC_S_OK
) return ret
;
764 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
767 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, Protseq
);
769 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
771 ret
= RPCRT4_CompleteBindingA(bind
, NetworkAddr
, Endpoint
, Options
);
773 RpcStringFreeA(&Options
);
774 RpcStringFreeA(&Endpoint
);
775 RpcStringFreeA(&NetworkAddr
);
776 RpcStringFreeA(&Protseq
);
777 RpcStringFreeA(&ObjectUuid
);
780 *Binding
= (RPC_BINDING_HANDLE
)bind
;
782 RPCRT4_DestroyBinding(bind
);
787 /***********************************************************************
788 * RpcBindingFromStringBindingW (RPCRT4.@)
790 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( LPWSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
793 RpcBinding
* bind
= NULL
;
794 LPWSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
797 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
799 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
800 &NetworkAddr
, &Endpoint
, &Options
);
801 if (ret
!= RPC_S_OK
) return ret
;
803 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
806 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
808 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
810 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
812 RpcStringFreeW(&Options
);
813 RpcStringFreeW(&Endpoint
);
814 RpcStringFreeW(&NetworkAddr
);
815 RpcStringFreeW(&Protseq
);
816 RpcStringFreeW(&ObjectUuid
);
819 *Binding
= (RPC_BINDING_HANDLE
)bind
;
821 RPCRT4_DestroyBinding(bind
);
826 /***********************************************************************
827 * RpcBindingToStringBindingA (RPCRT4.@)
829 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, LPSTR
* StringBinding
)
832 RpcBinding
* bind
= (RpcBinding
*)Binding
;
835 TRACE("(%p,%p)\n", Binding
, StringBinding
);
837 ret
= UuidToStringA(&bind
->ObjectUuid
, &ObjectUuid
);
838 if (ret
!= RPC_S_OK
) return ret
;
840 ret
= RpcStringBindingComposeA(ObjectUuid
, bind
->Protseq
, bind
->NetworkAddr
,
841 bind
->Endpoint
, NULL
, StringBinding
);
843 RpcStringFreeA(&ObjectUuid
);
848 /***********************************************************************
849 * RpcBindingToStringBindingW (RPCRT4.@)
851 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, LPWSTR
* StringBinding
)
855 TRACE("(%p,%p)\n", Binding
, StringBinding
);
856 ret
= RpcBindingToStringBindingA(Binding
, &str
);
857 *StringBinding
= RPCRT4_strdupAtoW(str
);
858 RpcStringFreeA(&str
);
862 /***********************************************************************
863 * I_RpcBindingSetAsync (RPCRT4.@)
865 * Exists in win9x and winNT, but with different number of arguments
866 * (9x version has 3 arguments, NT has 2).
868 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
, unsigned long ServerTid
)
870 RpcBinding
* bind
= (RpcBinding
*)Binding
;
872 TRACE( "(%p,%p,%ld): stub\n", Binding
, BlockingFn
, ServerTid
);
874 bind
->BlockingFn
= BlockingFn
;
875 bind
->ServerTid
= ServerTid
;