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_CreateConnection(RpcConnection
** Connection
, BOOL server
, LPSTR Protseq
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
98 RpcConnection
* NewConnection
;
100 NewConnection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcConnection
));
101 NewConnection
->server
= server
;
102 NewConnection
->Protseq
= RPCRT4_strdupA(Protseq
);
103 NewConnection
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
104 NewConnection
->Endpoint
= RPCRT4_strdupA(Endpoint
);
106 TRACE("connection: %p\n", NewConnection
);
107 *Connection
= NewConnection
;
112 RPC_STATUS
RPCRT4_DestroyConnection(RpcConnection
* Connection
)
114 TRACE("connection: %p\n", Connection
);
115 if (Connection
->Used
) ERR("connection is still in use\n");
116 RPCRT4_CloseConnection(Connection
);
117 RPCRT4_strfree(Connection
->Endpoint
);
118 RPCRT4_strfree(Connection
->NetworkAddr
);
119 RPCRT4_strfree(Connection
->Protseq
);
120 HeapFree(GetProcessHeap(), 0, Connection
);
124 RPC_STATUS
RPCRT4_OpenConnection(RpcConnection
* Connection
)
126 TRACE("(Connection == ^%p)\n", Connection
);
127 if (!Connection
->conn
) {
128 if (Connection
->server
) { /* server */
129 /* protseq=ncalrpc: supposed to use NT LPC ports,
130 * but we'll implement it with named pipes for now */
131 if (strcmp(Connection
->Protseq
, "ncalrpc") == 0) {
132 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
134 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
135 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
136 TRACE("listening on %s\n", pname
);
137 Connection
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
138 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
139 HeapFree(GetProcessHeap(), 0, pname
);
140 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
141 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
142 if (!ConnectNamedPipe(Connection
->conn
, &Connection
->ovl
)) {
143 DWORD err
= GetLastError();
144 if (err
== ERROR_PIPE_CONNECTED
) {
145 SetEvent(Connection
->ovl
.hEvent
);
151 /* protseq=ncacn_np: named pipes */
152 else if (strcmp(Connection
->Protseq
, "ncacn_np") == 0) {
153 static LPSTR prefix
= "\\\\.";
155 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
156 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
157 TRACE("listening on %s\n", pname
);
158 Connection
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
159 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
160 HeapFree(GetProcessHeap(), 0, pname
);
161 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
162 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
163 if (!ConnectNamedPipe(Connection
->conn
, &Connection
->ovl
)) {
164 DWORD err
= GetLastError();
165 if (err
== ERROR_PIPE_CONNECTED
) {
166 SetEvent(Connection
->ovl
.hEvent
);
173 ERR("protseq %s not supported\n", Connection
->Protseq
);
174 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
178 /* protseq=ncalrpc: supposed to use NT LPC ports,
179 * but we'll implement it with named pipes for now */
180 if (strcmp(Connection
->Protseq
, "ncalrpc") == 0) {
181 static LPSTR prefix
= "\\\\.\\pipe\\lrpc\\";
186 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
187 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
188 TRACE("connecting to %s\n", pname
);
190 if (WaitNamedPipeA(pname
, NMPWAIT_WAIT_FOREVER
)) {
191 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
192 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
193 if (conn
!= INVALID_HANDLE_VALUE
) break;
194 err
= GetLastError();
195 if (err
== ERROR_PIPE_BUSY
) continue;
196 TRACE("connection failed, error=%lx\n", err
);
197 HeapFree(GetProcessHeap(), 0, pname
);
200 err
= GetLastError();
201 TRACE("connection failed, error=%lx\n", err
);
202 HeapFree(GetProcessHeap(), 0, pname
);
208 HeapFree(GetProcessHeap(), 0, pname
);
209 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
210 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
211 Connection
->conn
= conn
;
213 /* protseq=ncacn_np: named pipes */
214 else if (strcmp(Connection
->Protseq
, "ncacn_np") == 0) {
215 static LPSTR prefix
= "\\\\.";
220 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
221 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
222 TRACE("connecting to %s\n", pname
);
223 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
224 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
225 if (conn
== INVALID_HANDLE_VALUE
) {
226 err
= GetLastError();
227 /* we don't need to handle ERROR_PIPE_BUSY here,
228 * the doc says that it is returned to the app */
229 TRACE("connection failed, error=%lx\n", err
);
230 HeapFree(GetProcessHeap(), 0, pname
);
235 HeapFree(GetProcessHeap(), 0, pname
);
236 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
237 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
238 Connection
->conn
= conn
;
240 ERR("protseq %s not supported\n", Connection
->Protseq
);
241 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
248 RPC_STATUS
RPCRT4_CloseConnection(RpcConnection
* Connection
)
250 TRACE("(Connection == ^%p)\n", Connection
);
251 if (Connection
->conn
) {
252 CancelIo(Connection
->conn
);
253 CloseHandle(Connection
->conn
);
254 Connection
->conn
= 0;
256 if (Connection
->ovl
.hEvent
) {
257 CloseHandle(Connection
->ovl
.hEvent
);
258 Connection
->ovl
.hEvent
= 0;
263 RPC_STATUS
RPCRT4_SpawnConnection(RpcConnection
** Connection
, RpcConnection
* OldConnection
)
265 RpcConnection
* NewConnection
;
266 RPC_STATUS err
= RPCRT4_CreateConnection(&NewConnection
, OldConnection
->server
, OldConnection
->Protseq
,
267 OldConnection
->NetworkAddr
, OldConnection
->Endpoint
, NULL
);
268 if (err
== RPC_S_OK
) {
269 /* because of the way named pipes work, we'll transfer the connected pipe
270 * to the child, then reopen the server binding to continue listening */
271 NewConnection
->conn
= OldConnection
->conn
;
272 NewConnection
->ovl
= OldConnection
->ovl
;
273 OldConnection
->conn
= 0;
274 memset(&OldConnection
->ovl
, 0, sizeof(OldConnection
->ovl
));
275 *Connection
= NewConnection
;
276 RPCRT4_OpenConnection(OldConnection
);
281 RPC_STATUS
RPCRT4_AllocBinding(RpcBinding
** Binding
, BOOL server
)
283 RpcBinding
* NewBinding
;
285 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
286 NewBinding
->refs
= 1;
287 NewBinding
->server
= server
;
289 *Binding
= NewBinding
;
294 RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPSTR Protseq
)
296 RpcBinding
* NewBinding
;
298 RPCRT4_AllocBinding(&NewBinding
, server
);
299 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
301 TRACE("binding: %p\n", NewBinding
);
302 *Binding
= NewBinding
;
307 RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPWSTR Protseq
)
309 RpcBinding
* NewBinding
;
311 RPCRT4_AllocBinding(&NewBinding
, server
);
312 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
314 TRACE("binding: %p\n", NewBinding
);
315 *Binding
= NewBinding
;
320 RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
322 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
323 debugstr_a(NetworkAddr
), debugstr_a(Endpoint
), debugstr_a(NetworkOptions
));
325 RPCRT4_strfree(Binding
->NetworkAddr
);
326 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
327 RPCRT4_strfree(Binding
->Endpoint
);
329 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
331 Binding
->Endpoint
= RPCRT4_strdupA("");
333 if (!Binding
->Endpoint
) ERR("out of memory?\n");
338 RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPWSTR NetworkAddr
, LPWSTR Endpoint
, LPWSTR NetworkOptions
)
340 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
341 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
343 RPCRT4_strfree(Binding
->NetworkAddr
);
344 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
345 RPCRT4_strfree(Binding
->Endpoint
);
347 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
349 Binding
->Endpoint
= RPCRT4_strdupA("");
351 if (!Binding
->Endpoint
) ERR("out of memory?\n");
356 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPSTR Endpoint
)
358 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
360 RPCRT4_strfree(Binding
->Endpoint
);
361 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
366 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, UUID
* ObjectUuid
)
368 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
369 if (ObjectUuid
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
370 else UuidCreateNil(&Binding
->ObjectUuid
);
374 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
376 RpcBinding
* NewBinding
;
377 TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding
, Connection
);
379 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
380 NewBinding
->Protseq
= RPCRT4_strdupA(Connection
->Protseq
);
381 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
382 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
383 NewBinding
->FromConn
= Connection
;
385 TRACE("binding: %p\n", NewBinding
);
386 *Binding
= NewBinding
;
391 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
393 InterlockedIncrement(&OldBinding
->refs
);
394 *Binding
= OldBinding
;
398 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
400 if (InterlockedDecrement(&Binding
->refs
))
403 TRACE("binding: %p\n", Binding
);
404 /* FIXME: release connections */
405 RPCRT4_strfree(Binding
->Endpoint
);
406 RPCRT4_strfree(Binding
->NetworkAddr
);
407 RPCRT4_strfree(Binding
->Protseq
);
408 HeapFree(GetProcessHeap(), 0, Binding
);
412 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
)
414 RpcConnection
* NewConnection
;
415 TRACE("(Binding == ^%p)\n", Binding
);
416 if (Binding
->FromConn
) {
417 *Connection
= Binding
->FromConn
;
421 /* FIXME: cache connections */
422 RPCRT4_CreateConnection(&NewConnection
, Binding
->server
, Binding
->Protseq
, Binding
->NetworkAddr
, Binding
->Endpoint
, NULL
);
423 NewConnection
->Used
= Binding
;
424 *Connection
= NewConnection
;
425 return RPCRT4_OpenConnection(NewConnection
);
428 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
430 TRACE("(Binding == ^%p)\n", Binding
);
431 if (!Connection
) return RPC_S_OK
;
432 if (Binding
->FromConn
== Connection
) return RPC_S_OK
;
433 Connection
->Used
= NULL
;
434 return RPCRT4_DestroyConnection(Connection
);
437 /* utility functions for string composing and parsing */
438 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
440 unsigned len
= strlen(src
);
441 memcpy(data
, src
, len
*sizeof(CHAR
));
445 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
447 unsigned len
= strlenW(src
);
448 memcpy(data
, src
, len
*sizeof(WCHAR
));
452 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
454 DWORD len
= strlen(dst
), slen
= strlen(src
);
455 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
456 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
458 memcpy(ndst
+len
+1, src
, slen
*sizeof(CHAR
));
459 ndst
[len
+slen
+1] = 0;
463 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
465 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
466 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
467 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
469 memcpy(ndst
+len
+1, src
, slen
*sizeof(WCHAR
));
470 ndst
[len
+slen
+1] = 0;
475 /***********************************************************************
476 * RpcStringBindingComposeA (RPCRT4.@)
478 RPC_STATUS WINAPI
RpcStringBindingComposeA( LPSTR ObjUuid
, LPSTR Protseq
,
479 LPSTR NetworkAddr
, LPSTR Endpoint
,
480 LPSTR Options
, LPSTR
* StringBinding
)
485 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
486 debugstr_a( ObjUuid
), debugstr_a( Protseq
),
487 debugstr_a( NetworkAddr
), debugstr_a( Endpoint
),
488 debugstr_a( Options
), StringBinding
);
490 if (ObjUuid
&& *ObjUuid
) len
+= strlen(ObjUuid
) + 1;
491 if (Protseq
&& *Protseq
) len
+= strlen(Protseq
) + 1;
492 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen(NetworkAddr
);
493 if (Endpoint
&& *Endpoint
) len
+= strlen(Endpoint
) + 2;
494 if (Options
&& *Options
) len
+= strlen(Options
) + 2;
496 data
= HeapAlloc(GetProcessHeap(), 0, len
);
497 *StringBinding
= data
;
499 if (ObjUuid
&& *ObjUuid
) {
500 data
+= RPCRT4_strcopyA(data
, ObjUuid
);
503 if (Protseq
&& *Protseq
) {
504 data
+= RPCRT4_strcopyA(data
, Protseq
);
507 if (NetworkAddr
&& *NetworkAddr
)
508 data
+= RPCRT4_strcopyA(data
, NetworkAddr
);
510 if ((Endpoint
&& *Endpoint
) ||
511 (Options
&& *Options
)) {
513 if (Endpoint
&& *Endpoint
) {
514 data
+= RPCRT4_strcopyA(data
, Endpoint
);
515 if (Options
&& *Options
) *data
++ = ',';
517 if (Options
&& *Options
) {
518 data
+= RPCRT4_strcopyA(data
, Options
);
527 /***********************************************************************
528 * RpcStringBindingComposeW (RPCRT4.@)
530 RPC_STATUS WINAPI
RpcStringBindingComposeW( LPWSTR ObjUuid
, LPWSTR Protseq
,
531 LPWSTR NetworkAddr
, LPWSTR Endpoint
,
532 LPWSTR Options
, LPWSTR
* StringBinding
)
537 TRACE("(%s,%s,%s,%s,%s,%p)\n",
538 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
539 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
540 debugstr_w( Options
), StringBinding
);
542 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
543 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
544 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
545 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
546 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
548 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
549 *StringBinding
= data
;
551 if (ObjUuid
&& *ObjUuid
) {
552 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
555 if (Protseq
&& *Protseq
) {
556 data
+= RPCRT4_strcopyW(data
, Protseq
);
559 if (NetworkAddr
&& *NetworkAddr
) {
560 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
562 if ((Endpoint
&& *Endpoint
) ||
563 (Options
&& *Options
)) {
565 if (Endpoint
&& *Endpoint
) {
566 data
+= RPCRT4_strcopyW(data
, Endpoint
);
567 if (Options
&& *Options
) *data
++ = ',';
569 if (Options
&& *Options
) {
570 data
+= RPCRT4_strcopyW(data
, Options
);
580 /***********************************************************************
581 * RpcStringBindingParseA (RPCRT4.@)
583 RPC_STATUS WINAPI
RpcStringBindingParseA( LPSTR StringBinding
, LPSTR
*ObjUuid
,
584 LPSTR
*Protseq
, LPSTR
*NetworkAddr
,
585 LPSTR
*Endpoint
, LPSTR
*Options
)
588 static const char ep_opt
[] = "endpoint=";
590 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding
),
591 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
593 if (ObjUuid
) *ObjUuid
= NULL
;
594 if (Protseq
) *Protseq
= NULL
;
595 if (NetworkAddr
) *NetworkAddr
= NULL
;
596 if (Endpoint
) *Endpoint
= NULL
;
597 if (Options
) *Options
= NULL
;
599 data
= StringBinding
;
601 next
= strchr(data
, '@');
603 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupA(data
, next
- data
);
607 next
= strchr(data
, ':');
609 if (Protseq
) *Protseq
= RPCRT4_strndupA(data
, next
- data
);
613 next
= strchr(data
, '[');
617 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupA(data
, next
- data
);
619 close
= strchr(data
, ']');
620 if (!close
) goto fail
;
622 /* tokenize options */
623 while (data
< close
) {
624 next
= strchr(data
, ',');
625 if (!next
|| next
> close
) next
= close
;
626 /* FIXME: this is kind of inefficient */
627 opt
= RPCRT4_strndupA(data
, next
- data
);
631 next
= strchr(opt
, '=');
633 /* not an option, must be an endpoint */
634 if (*Endpoint
) goto fail
;
637 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
638 /* endpoint option */
639 if (*Endpoint
) goto fail
;
640 *Endpoint
= RPCRT4_strdupA(next
+1);
641 HeapFree(GetProcessHeap(), 0, opt
);
645 /* FIXME: this is kind of inefficient */
646 *Options
= RPCRT4_strconcatA(*Options
, opt
);
647 HeapFree(GetProcessHeap(), 0, opt
);
655 if (*data
) goto fail
;
657 else if (NetworkAddr
)
658 *NetworkAddr
= RPCRT4_strdupA(data
);
663 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
664 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
665 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
666 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
667 if (Options
) RpcStringFreeA((unsigned char**)Options
);
668 return RPC_S_INVALID_STRING_BINDING
;
671 /***********************************************************************
672 * RpcStringBindingParseW (RPCRT4.@)
674 RPC_STATUS WINAPI
RpcStringBindingParseW( LPWSTR StringBinding
, LPWSTR
*ObjUuid
,
675 LPWSTR
*Protseq
, LPWSTR
*NetworkAddr
,
676 LPWSTR
*Endpoint
, LPWSTR
*Options
)
679 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
681 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
682 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
684 if (ObjUuid
) *ObjUuid
= NULL
;
685 if (Protseq
) *Protseq
= NULL
;
686 if (NetworkAddr
) *NetworkAddr
= NULL
;
687 if (Endpoint
) *Endpoint
= NULL
;
688 if (Options
) *Options
= NULL
;
690 data
= StringBinding
;
692 next
= strchrW(data
, '@');
694 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
698 next
= strchrW(data
, ':');
700 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
704 next
= strchrW(data
, '[');
708 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
710 close
= strchrW(data
, ']');
711 if (!close
) goto fail
;
713 /* tokenize options */
714 while (data
< close
) {
715 next
= strchrW(data
, ',');
716 if (!next
|| next
> close
) next
= close
;
717 /* FIXME: this is kind of inefficient */
718 opt
= RPCRT4_strndupW(data
, next
- data
);
722 next
= strchrW(opt
, '=');
724 /* not an option, must be an endpoint */
725 if (*Endpoint
) goto fail
;
728 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
729 /* endpoint option */
730 if (*Endpoint
) goto fail
;
731 *Endpoint
= RPCRT4_strdupW(next
+1);
732 HeapFree(GetProcessHeap(), 0, opt
);
736 /* FIXME: this is kind of inefficient */
737 *Options
= RPCRT4_strconcatW(*Options
, opt
);
738 HeapFree(GetProcessHeap(), 0, opt
);
746 if (*data
) goto fail
;
747 } else if (NetworkAddr
)
748 *NetworkAddr
= RPCRT4_strdupW(data
);
753 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
754 if (Protseq
) RpcStringFreeW(Protseq
);
755 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
756 if (Endpoint
) RpcStringFreeW(Endpoint
);
757 if (Options
) RpcStringFreeW(Options
);
758 return RPC_S_INVALID_STRING_BINDING
;
761 /***********************************************************************
762 * RpcBindingFree (RPCRT4.@)
764 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
767 TRACE("(%p) = %p\n", Binding
, *Binding
);
768 status
= RPCRT4_DestroyBinding(*Binding
);
769 if (status
== RPC_S_OK
) *Binding
= 0;
773 /***********************************************************************
774 * RpcBindingVectorFree (RPCRT4.@)
776 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
781 TRACE("(%p)\n", BindingVector
);
782 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
783 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
785 HeapFree(GetProcessHeap(), 0, *BindingVector
);
786 *BindingVector
= NULL
;
790 /***********************************************************************
791 * RpcBindingInqObject (RPCRT4.@)
793 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
795 RpcBinding
* bind
= (RpcBinding
*)Binding
;
797 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
798 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
802 /***********************************************************************
803 * RpcBindingSetObject (RPCRT4.@)
805 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
807 RpcBinding
* bind
= (RpcBinding
*)Binding
;
809 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
810 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
811 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
814 /***********************************************************************
815 * RpcBindingFromStringBindingA (RPCRT4.@)
817 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( LPSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
820 RpcBinding
* bind
= NULL
;
821 LPSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
824 TRACE("(%s,%p)\n", debugstr_a(StringBinding
), Binding
);
826 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
827 &NetworkAddr
, &Endpoint
, &Options
);
828 if (ret
!= RPC_S_OK
) return ret
;
830 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
833 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, Protseq
);
835 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
837 ret
= RPCRT4_CompleteBindingA(bind
, NetworkAddr
, Endpoint
, Options
);
839 RpcStringFreeA((unsigned char**)&Options
);
840 RpcStringFreeA((unsigned char**)&Endpoint
);
841 RpcStringFreeA((unsigned char**)&NetworkAddr
);
842 RpcStringFreeA((unsigned char**)&Protseq
);
843 RpcStringFreeA((unsigned char**)&ObjectUuid
);
846 *Binding
= (RPC_BINDING_HANDLE
)bind
;
848 RPCRT4_DestroyBinding(bind
);
853 /***********************************************************************
854 * RpcBindingFromStringBindingW (RPCRT4.@)
856 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( LPWSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
859 RpcBinding
* bind
= NULL
;
860 LPWSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
863 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
865 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
866 &NetworkAddr
, &Endpoint
, &Options
);
867 if (ret
!= RPC_S_OK
) return ret
;
869 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
872 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
874 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
876 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
878 RpcStringFreeW(&Options
);
879 RpcStringFreeW(&Endpoint
);
880 RpcStringFreeW(&NetworkAddr
);
881 RpcStringFreeW(&Protseq
);
882 RpcStringFreeW(&ObjectUuid
);
885 *Binding
= (RPC_BINDING_HANDLE
)bind
;
887 RPCRT4_DestroyBinding(bind
);
892 /***********************************************************************
893 * RpcBindingToStringBindingA (RPCRT4.@)
895 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, LPSTR
* StringBinding
)
898 RpcBinding
* bind
= (RpcBinding
*)Binding
;
901 TRACE("(%p,%p)\n", Binding
, StringBinding
);
903 ret
= UuidToStringA(&bind
->ObjectUuid
, (unsigned char**)&ObjectUuid
);
904 if (ret
!= RPC_S_OK
) return ret
;
906 ret
= RpcStringBindingComposeA(ObjectUuid
, bind
->Protseq
, bind
->NetworkAddr
,
907 bind
->Endpoint
, NULL
, StringBinding
);
909 RpcStringFreeA((unsigned char**)&ObjectUuid
);
914 /***********************************************************************
915 * RpcBindingToStringBindingW (RPCRT4.@)
917 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, LPWSTR
* StringBinding
)
921 TRACE("(%p,%p)\n", Binding
, StringBinding
);
922 ret
= RpcBindingToStringBindingA(Binding
, &str
);
923 *StringBinding
= RPCRT4_strdupAtoW(str
);
924 RpcStringFreeA((unsigned char**)&str
);
928 /***********************************************************************
929 * I_RpcBindingSetAsync (RPCRT4.@)
931 * Exists in win9x and winNT, but with different number of arguments
932 * (9x version has 3 arguments, NT has 2).
934 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
936 RpcBinding
* bind
= (RpcBinding
*)Binding
;
938 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
940 bind
->BlockingFn
= BlockingFn
;