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
34 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 #include "rpc_binding.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
44 static RpcConnection
* conn_cache
;
46 static CRITICAL_SECTION conn_cache_cs
;
47 static CRITICAL_SECTION_DEBUG critsect_debug
=
50 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
51 0, 0, { 0, (DWORD
)(__FILE__
": conn_cache_cs") }
53 static CRITICAL_SECTION conn_cache_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
55 LPSTR
RPCRT4_strndupA(LPCSTR src
, INT slen
)
59 if (!src
) return NULL
;
60 if (slen
== -1) slen
= strlen(src
);
62 s
= HeapAlloc(GetProcessHeap(), 0, len
+1);
68 LPSTR
RPCRT4_strdupWtoA(LPWSTR src
)
72 if (!src
) return NULL
;
73 len
= WideCharToMultiByte(CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
74 s
= HeapAlloc(GetProcessHeap(), 0, len
);
75 WideCharToMultiByte(CP_ACP
, 0, src
, -1, s
, len
, NULL
, NULL
);
79 LPWSTR
RPCRT4_strdupAtoW(LPSTR src
)
83 if (!src
) return NULL
;
84 len
= MultiByteToWideChar(CP_ACP
, 0, src
, -1, NULL
, 0);
85 s
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
86 MultiByteToWideChar(CP_ACP
, 0, src
, -1, s
, len
);
90 LPWSTR
RPCRT4_strndupW(LPWSTR src
, INT slen
)
94 if (!src
) return NULL
;
95 if (slen
== -1) slen
= strlenW(src
);
97 s
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
98 memcpy(s
, src
, len
*sizeof(WCHAR
));
103 void RPCRT4_strfree(LPSTR src
)
105 if (src
) HeapFree(GetProcessHeap(), 0, src
);
108 RPC_STATUS
RPCRT4_CreateConnection(RpcConnection
** Connection
, BOOL server
, LPSTR Protseq
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
, RpcBinding
* Binding
)
110 RpcConnection
* NewConnection
;
112 NewConnection
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcConnection
));
113 NewConnection
->server
= server
;
114 NewConnection
->Protseq
= RPCRT4_strdupA(Protseq
);
115 NewConnection
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
116 NewConnection
->Endpoint
= RPCRT4_strdupA(Endpoint
);
117 NewConnection
->Used
= Binding
;
119 EnterCriticalSection(&conn_cache_cs
);
120 NewConnection
->Next
= conn_cache
;
121 conn_cache
= NewConnection
;
122 LeaveCriticalSection(&conn_cache_cs
);
124 TRACE("connection: %p\n", NewConnection
);
125 *Connection
= NewConnection
;
130 RPC_STATUS
RPCRT4_DestroyConnection(RpcConnection
* Connection
)
132 RpcConnection
* PrevConnection
;
134 TRACE("connection: %p\n", Connection
);
135 if (Connection
->Used
) ERR("connection is still in use\n");
137 EnterCriticalSection(&conn_cache_cs
);
138 PrevConnection
= conn_cache
;
139 while (PrevConnection
&& PrevConnection
->Next
!= Connection
)
140 PrevConnection
= PrevConnection
->Next
;
141 if (PrevConnection
) PrevConnection
->Next
= Connection
->Next
;
142 LeaveCriticalSection(&conn_cache_cs
);
144 RPCRT4_CloseConnection(Connection
);
145 RPCRT4_strfree(Connection
->Endpoint
);
146 RPCRT4_strfree(Connection
->NetworkAddr
);
147 RPCRT4_strfree(Connection
->Protseq
);
148 HeapFree(GetProcessHeap(), 0, Connection
);
152 RPC_STATUS
RPCRT4_GetConnection(RpcConnection
** Connection
, BOOL server
, LPSTR Protseq
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
, RpcBinding
* Binding
)
154 RpcConnection
* NewConnection
;
157 EnterCriticalSection(&conn_cache_cs
);
158 for (NewConnection
= conn_cache
; NewConnection
; NewConnection
= NewConnection
->Next
) {
159 if (NewConnection
->Used
) continue;
160 if (NewConnection
->server
!= server
) continue;
161 if (Protseq
&& strcmp(NewConnection
->Protseq
, Protseq
)) continue;
162 if (NetworkAddr
&& strcmp(NewConnection
->NetworkAddr
, NetworkAddr
)) continue;
163 if (Endpoint
&& strcmp(NewConnection
->Endpoint
, Endpoint
)) continue;
164 /* this connection fits the bill */
165 NewConnection
->Used
= Binding
;
168 LeaveCriticalSection(&conn_cache_cs
);
170 TRACE("cached connection: %p\n", NewConnection
);
171 *Connection
= NewConnection
;
175 return RPCRT4_CreateConnection(Connection
, server
, Protseq
, NetworkAddr
, Endpoint
, NetworkOptions
, Binding
);
178 RPC_STATUS
RPCRT4_ReleaseConnection(RpcConnection
* Connection
)
180 TRACE("connection: %p\n", Connection
);
181 Connection
->Used
= NULL
;
182 if (!Connection
->server
) {
183 /* cache the open connection for reuse later */
184 /* FIXME: we should probably clean the cache someday */
187 return RPCRT4_DestroyConnection(Connection
);
190 RPC_STATUS
RPCRT4_OpenConnection(RpcConnection
* Connection
)
192 TRACE("(Connection == ^%p)\n", Connection
);
193 if (!Connection
->conn
) {
194 if (Connection
->server
) { /* server */
195 /* protseq=ncalrpc: supposed to use NT LPC ports,
196 * but we'll implement it with named pipes for now */
197 if (strcmp(Connection
->Protseq
, "ncalrpc") == 0) {
198 static LPCSTR prefix
= "\\\\.\\pipe\\lrpc\\";
200 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
201 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
202 TRACE("listening on %s\n", pname
);
203 Connection
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
204 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
205 HeapFree(GetProcessHeap(), 0, pname
);
206 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
207 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
208 if (!ConnectNamedPipe(Connection
->conn
, &Connection
->ovl
)) {
209 DWORD err
= GetLastError();
210 if (err
== ERROR_PIPE_CONNECTED
) {
211 SetEvent(Connection
->ovl
.hEvent
);
217 /* protseq=ncacn_np: named pipes */
218 else if (strcmp(Connection
->Protseq
, "ncacn_np") == 0) {
219 static LPCSTR prefix
= "\\\\.";
221 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
222 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
223 TRACE("listening on %s\n", pname
);
224 Connection
->conn
= CreateNamedPipeA(pname
, PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
,
225 0, PIPE_UNLIMITED_INSTANCES
, 0, 0, 5000, NULL
);
226 HeapFree(GetProcessHeap(), 0, pname
);
227 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
228 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
229 if (!ConnectNamedPipe(Connection
->conn
, &Connection
->ovl
)) {
230 DWORD err
= GetLastError();
231 if (err
== ERROR_PIPE_CONNECTED
) {
232 SetEvent(Connection
->ovl
.hEvent
);
239 ERR("protseq %s not supported\n", Connection
->Protseq
);
240 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
244 /* protseq=ncalrpc: supposed to use NT LPC ports,
245 * but we'll implement it with named pipes for now */
246 if (strcmp(Connection
->Protseq
, "ncalrpc") == 0) {
247 static LPCSTR prefix
= "\\\\.\\pipe\\lrpc\\";
252 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
253 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
254 TRACE("connecting to %s\n", pname
);
256 if (WaitNamedPipeA(pname
, NMPWAIT_WAIT_FOREVER
)) {
257 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
258 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
259 if (conn
!= INVALID_HANDLE_VALUE
) break;
260 err
= GetLastError();
261 if (err
== ERROR_PIPE_BUSY
) continue;
262 TRACE("connection failed, error=%lx\n", err
);
263 HeapFree(GetProcessHeap(), 0, pname
);
266 err
= GetLastError();
267 TRACE("connection failed, error=%lx\n", err
);
268 HeapFree(GetProcessHeap(), 0, pname
);
274 HeapFree(GetProcessHeap(), 0, pname
);
275 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
276 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
277 Connection
->conn
= conn
;
279 /* protseq=ncacn_np: named pipes */
280 else if (strcmp(Connection
->Protseq
, "ncacn_np") == 0) {
281 static LPCSTR prefix
= "\\\\.";
286 pname
= HeapAlloc(GetProcessHeap(), 0, strlen(prefix
) + strlen(Connection
->Endpoint
) + 1);
287 strcat(strcpy(pname
, prefix
), Connection
->Endpoint
);
288 TRACE("connecting to %s\n", pname
);
289 conn
= CreateFileA(pname
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
290 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
291 if (conn
== INVALID_HANDLE_VALUE
) {
292 err
= GetLastError();
293 /* we don't need to handle ERROR_PIPE_BUSY here,
294 * the doc says that it is returned to the app */
295 TRACE("connection failed, error=%lx\n", err
);
296 HeapFree(GetProcessHeap(), 0, pname
);
301 HeapFree(GetProcessHeap(), 0, pname
);
302 memset(&Connection
->ovl
, 0, sizeof(Connection
->ovl
));
303 Connection
->ovl
.hEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
304 Connection
->conn
= conn
;
306 ERR("protseq %s not supported\n", Connection
->Protseq
);
307 return RPC_S_PROTSEQ_NOT_SUPPORTED
;
314 RPC_STATUS
RPCRT4_CloseConnection(RpcConnection
* Connection
)
316 TRACE("(Connection == ^%p)\n", Connection
);
317 if (Connection
->conn
) {
318 CancelIo(Connection
->conn
);
319 CloseHandle(Connection
->conn
);
320 Connection
->conn
= 0;
322 if (Connection
->ovl
.hEvent
) {
323 CloseHandle(Connection
->ovl
.hEvent
);
324 Connection
->ovl
.hEvent
= 0;
329 RPC_STATUS
RPCRT4_SpawnConnection(RpcConnection
** Connection
, RpcConnection
* OldConnection
)
331 RpcConnection
* NewConnection
;
332 RPC_STATUS err
= RPCRT4_CreateConnection(&NewConnection
, OldConnection
->server
, OldConnection
->Protseq
,
333 OldConnection
->NetworkAddr
, OldConnection
->Endpoint
, NULL
, NULL
);
334 if (err
== RPC_S_OK
) {
335 /* because of the way named pipes work, we'll transfer the connected pipe
336 * to the child, then reopen the server binding to continue listening */
337 NewConnection
->conn
= OldConnection
->conn
;
338 NewConnection
->ovl
= OldConnection
->ovl
;
339 OldConnection
->conn
= 0;
340 memset(&OldConnection
->ovl
, 0, sizeof(OldConnection
->ovl
));
341 *Connection
= NewConnection
;
342 RPCRT4_OpenConnection(OldConnection
);
347 RPC_STATUS
RPCRT4_AllocBinding(RpcBinding
** Binding
, BOOL server
)
349 RpcBinding
* NewBinding
;
351 NewBinding
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RpcBinding
));
352 NewBinding
->refs
= 1;
353 NewBinding
->server
= server
;
355 *Binding
= NewBinding
;
360 RPC_STATUS
RPCRT4_CreateBindingA(RpcBinding
** Binding
, BOOL server
, LPSTR Protseq
)
362 RpcBinding
* NewBinding
;
364 RPCRT4_AllocBinding(&NewBinding
, server
);
365 NewBinding
->Protseq
= RPCRT4_strdupA(Protseq
);
367 TRACE("binding: %p\n", NewBinding
);
368 *Binding
= NewBinding
;
373 RPC_STATUS
RPCRT4_CreateBindingW(RpcBinding
** Binding
, BOOL server
, LPWSTR Protseq
)
375 RpcBinding
* NewBinding
;
377 RPCRT4_AllocBinding(&NewBinding
, server
);
378 NewBinding
->Protseq
= RPCRT4_strdupWtoA(Protseq
);
380 TRACE("binding: %p\n", NewBinding
);
381 *Binding
= NewBinding
;
386 RPC_STATUS
RPCRT4_CompleteBindingA(RpcBinding
* Binding
, LPSTR NetworkAddr
, LPSTR Endpoint
, LPSTR NetworkOptions
)
388 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
389 debugstr_a(NetworkAddr
), debugstr_a(Endpoint
), debugstr_a(NetworkOptions
));
391 RPCRT4_strfree(Binding
->NetworkAddr
);
392 Binding
->NetworkAddr
= RPCRT4_strdupA(NetworkAddr
);
393 RPCRT4_strfree(Binding
->Endpoint
);
395 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
397 Binding
->Endpoint
= RPCRT4_strdupA("");
399 if (!Binding
->Endpoint
) ERR("out of memory?\n");
404 RPC_STATUS
RPCRT4_CompleteBindingW(RpcBinding
* Binding
, LPWSTR NetworkAddr
, LPWSTR Endpoint
, LPWSTR NetworkOptions
)
406 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding
,
407 debugstr_w(NetworkAddr
), debugstr_w(Endpoint
), debugstr_w(NetworkOptions
));
409 RPCRT4_strfree(Binding
->NetworkAddr
);
410 Binding
->NetworkAddr
= RPCRT4_strdupWtoA(NetworkAddr
);
411 RPCRT4_strfree(Binding
->Endpoint
);
413 Binding
->Endpoint
= RPCRT4_strdupWtoA(Endpoint
);
415 Binding
->Endpoint
= RPCRT4_strdupA("");
417 if (!Binding
->Endpoint
) ERR("out of memory?\n");
422 RPC_STATUS
RPCRT4_ResolveBinding(RpcBinding
* Binding
, LPSTR Endpoint
)
424 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding
, Endpoint
);
426 RPCRT4_strfree(Binding
->Endpoint
);
427 Binding
->Endpoint
= RPCRT4_strdupA(Endpoint
);
432 RPC_STATUS
RPCRT4_SetBindingObject(RpcBinding
* Binding
, UUID
* ObjectUuid
)
434 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding
, debugstr_guid(ObjectUuid
));
435 if (ObjectUuid
) memcpy(&Binding
->ObjectUuid
, ObjectUuid
, sizeof(UUID
));
436 else UuidCreateNil(&Binding
->ObjectUuid
);
440 RPC_STATUS
RPCRT4_MakeBinding(RpcBinding
** Binding
, RpcConnection
* Connection
)
442 RpcBinding
* NewBinding
;
443 TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding
, Connection
);
445 RPCRT4_AllocBinding(&NewBinding
, Connection
->server
);
446 NewBinding
->Protseq
= RPCRT4_strdupA(Connection
->Protseq
);
447 NewBinding
->NetworkAddr
= RPCRT4_strdupA(Connection
->NetworkAddr
);
448 NewBinding
->Endpoint
= RPCRT4_strdupA(Connection
->Endpoint
);
449 NewBinding
->FromConn
= Connection
;
451 TRACE("binding: %p\n", NewBinding
);
452 *Binding
= NewBinding
;
457 RPC_STATUS
RPCRT4_ExportBinding(RpcBinding
** Binding
, RpcBinding
* OldBinding
)
459 InterlockedIncrement(&OldBinding
->refs
);
460 *Binding
= OldBinding
;
464 RPC_STATUS
RPCRT4_DestroyBinding(RpcBinding
* Binding
)
466 if (InterlockedDecrement(&Binding
->refs
))
469 TRACE("binding: %p\n", Binding
);
470 /* FIXME: release connections */
471 RPCRT4_strfree(Binding
->Endpoint
);
472 RPCRT4_strfree(Binding
->NetworkAddr
);
473 RPCRT4_strfree(Binding
->Protseq
);
474 HeapFree(GetProcessHeap(), 0, Binding
);
478 RPC_STATUS
RPCRT4_OpenBinding(RpcBinding
* Binding
, RpcConnection
** Connection
)
480 RpcConnection
* NewConnection
;
481 TRACE("(Binding == ^%p)\n", Binding
);
482 if (Binding
->FromConn
) {
483 *Connection
= Binding
->FromConn
;
487 RPCRT4_GetConnection(&NewConnection
, Binding
->server
, Binding
->Protseq
, Binding
->NetworkAddr
, Binding
->Endpoint
, NULL
, Binding
);
488 *Connection
= NewConnection
;
489 return RPCRT4_OpenConnection(NewConnection
);
492 RPC_STATUS
RPCRT4_CloseBinding(RpcBinding
* Binding
, RpcConnection
* Connection
)
494 TRACE("(Binding == ^%p)\n", Binding
);
495 if (!Connection
) return RPC_S_OK
;
496 if (Binding
->FromConn
== Connection
) return RPC_S_OK
;
497 return RPCRT4_ReleaseConnection(Connection
);
500 /* utility functions for string composing and parsing */
501 static unsigned RPCRT4_strcopyA(LPSTR data
, LPCSTR src
)
503 unsigned len
= strlen(src
);
504 memcpy(data
, src
, len
*sizeof(CHAR
));
508 static unsigned RPCRT4_strcopyW(LPWSTR data
, LPCWSTR src
)
510 unsigned len
= strlenW(src
);
511 memcpy(data
, src
, len
*sizeof(WCHAR
));
515 static LPSTR
RPCRT4_strconcatA(LPSTR dst
, LPCSTR src
)
517 DWORD len
= strlen(dst
), slen
= strlen(src
);
518 LPSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(CHAR
));
519 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
521 memcpy(ndst
+len
+1, src
, slen
*sizeof(CHAR
));
522 ndst
[len
+slen
+1] = 0;
526 static LPWSTR
RPCRT4_strconcatW(LPWSTR dst
, LPCWSTR src
)
528 DWORD len
= strlenW(dst
), slen
= strlenW(src
);
529 LPWSTR ndst
= HeapReAlloc(GetProcessHeap(), 0, dst
, (len
+slen
+2)*sizeof(WCHAR
));
530 if (!ndst
) HeapFree(GetProcessHeap(), 0, dst
);
532 memcpy(ndst
+len
+1, src
, slen
*sizeof(WCHAR
));
533 ndst
[len
+slen
+1] = 0;
538 /***********************************************************************
539 * RpcStringBindingComposeA (RPCRT4.@)
541 RPC_STATUS WINAPI
RpcStringBindingComposeA( LPSTR ObjUuid
, LPSTR Protseq
,
542 LPSTR NetworkAddr
, LPSTR Endpoint
,
543 LPSTR Options
, LPSTR
* StringBinding
)
548 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
549 debugstr_a( ObjUuid
), debugstr_a( Protseq
),
550 debugstr_a( NetworkAddr
), debugstr_a( Endpoint
),
551 debugstr_a( Options
), StringBinding
);
553 if (ObjUuid
&& *ObjUuid
) len
+= strlen(ObjUuid
) + 1;
554 if (Protseq
&& *Protseq
) len
+= strlen(Protseq
) + 1;
555 if (NetworkAddr
&& *NetworkAddr
) len
+= strlen(NetworkAddr
);
556 if (Endpoint
&& *Endpoint
) len
+= strlen(Endpoint
) + 2;
557 if (Options
&& *Options
) len
+= strlen(Options
) + 2;
559 data
= HeapAlloc(GetProcessHeap(), 0, len
);
560 *StringBinding
= data
;
562 if (ObjUuid
&& *ObjUuid
) {
563 data
+= RPCRT4_strcopyA(data
, ObjUuid
);
566 if (Protseq
&& *Protseq
) {
567 data
+= RPCRT4_strcopyA(data
, Protseq
);
570 if (NetworkAddr
&& *NetworkAddr
)
571 data
+= RPCRT4_strcopyA(data
, NetworkAddr
);
573 if ((Endpoint
&& *Endpoint
) ||
574 (Options
&& *Options
)) {
576 if (Endpoint
&& *Endpoint
) {
577 data
+= RPCRT4_strcopyA(data
, Endpoint
);
578 if (Options
&& *Options
) *data
++ = ',';
580 if (Options
&& *Options
) {
581 data
+= RPCRT4_strcopyA(data
, Options
);
590 /***********************************************************************
591 * RpcStringBindingComposeW (RPCRT4.@)
593 RPC_STATUS WINAPI
RpcStringBindingComposeW( LPWSTR ObjUuid
, LPWSTR Protseq
,
594 LPWSTR NetworkAddr
, LPWSTR Endpoint
,
595 LPWSTR Options
, LPWSTR
* StringBinding
)
600 TRACE("(%s,%s,%s,%s,%s,%p)\n",
601 debugstr_w( ObjUuid
), debugstr_w( Protseq
),
602 debugstr_w( NetworkAddr
), debugstr_w( Endpoint
),
603 debugstr_w( Options
), StringBinding
);
605 if (ObjUuid
&& *ObjUuid
) len
+= strlenW(ObjUuid
) + 1;
606 if (Protseq
&& *Protseq
) len
+= strlenW(Protseq
) + 1;
607 if (NetworkAddr
&& *NetworkAddr
) len
+= strlenW(NetworkAddr
);
608 if (Endpoint
&& *Endpoint
) len
+= strlenW(Endpoint
) + 2;
609 if (Options
&& *Options
) len
+= strlenW(Options
) + 2;
611 data
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
612 *StringBinding
= data
;
614 if (ObjUuid
&& *ObjUuid
) {
615 data
+= RPCRT4_strcopyW(data
, ObjUuid
);
618 if (Protseq
&& *Protseq
) {
619 data
+= RPCRT4_strcopyW(data
, Protseq
);
622 if (NetworkAddr
&& *NetworkAddr
) {
623 data
+= RPCRT4_strcopyW(data
, NetworkAddr
);
625 if ((Endpoint
&& *Endpoint
) ||
626 (Options
&& *Options
)) {
628 if (Endpoint
&& *Endpoint
) {
629 data
+= RPCRT4_strcopyW(data
, Endpoint
);
630 if (Options
&& *Options
) *data
++ = ',';
632 if (Options
&& *Options
) {
633 data
+= RPCRT4_strcopyW(data
, Options
);
643 /***********************************************************************
644 * RpcStringBindingParseA (RPCRT4.@)
646 RPC_STATUS WINAPI
RpcStringBindingParseA( LPSTR StringBinding
, LPSTR
*ObjUuid
,
647 LPSTR
*Protseq
, LPSTR
*NetworkAddr
,
648 LPSTR
*Endpoint
, LPSTR
*Options
)
651 static const char ep_opt
[] = "endpoint=";
653 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding
),
654 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
656 if (ObjUuid
) *ObjUuid
= NULL
;
657 if (Protseq
) *Protseq
= NULL
;
658 if (NetworkAddr
) *NetworkAddr
= NULL
;
659 if (Endpoint
) *Endpoint
= NULL
;
660 if (Options
) *Options
= NULL
;
662 data
= StringBinding
;
664 next
= strchr(data
, '@');
666 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupA(data
, next
- data
);
670 next
= strchr(data
, ':');
672 if (Protseq
) *Protseq
= RPCRT4_strndupA(data
, next
- data
);
676 next
= strchr(data
, '[');
680 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupA(data
, next
- data
);
682 close
= strchr(data
, ']');
683 if (!close
) goto fail
;
685 /* tokenize options */
686 while (data
< close
) {
687 next
= strchr(data
, ',');
688 if (!next
|| next
> close
) next
= close
;
689 /* FIXME: this is kind of inefficient */
690 opt
= RPCRT4_strndupA(data
, next
- data
);
694 next
= strchr(opt
, '=');
696 /* not an option, must be an endpoint */
697 if (*Endpoint
) goto fail
;
700 if (strncmp(opt
, ep_opt
, strlen(ep_opt
)) == 0) {
701 /* endpoint option */
702 if (*Endpoint
) goto fail
;
703 *Endpoint
= RPCRT4_strdupA(next
+1);
704 HeapFree(GetProcessHeap(), 0, opt
);
708 /* FIXME: this is kind of inefficient */
709 *Options
= RPCRT4_strconcatA(*Options
, opt
);
710 HeapFree(GetProcessHeap(), 0, opt
);
718 if (*data
) goto fail
;
720 else if (NetworkAddr
)
721 *NetworkAddr
= RPCRT4_strdupA(data
);
726 if (ObjUuid
) RpcStringFreeA((unsigned char**)ObjUuid
);
727 if (Protseq
) RpcStringFreeA((unsigned char**)Protseq
);
728 if (NetworkAddr
) RpcStringFreeA((unsigned char**)NetworkAddr
);
729 if (Endpoint
) RpcStringFreeA((unsigned char**)Endpoint
);
730 if (Options
) RpcStringFreeA((unsigned char**)Options
);
731 return RPC_S_INVALID_STRING_BINDING
;
734 /***********************************************************************
735 * RpcStringBindingParseW (RPCRT4.@)
737 RPC_STATUS WINAPI
RpcStringBindingParseW( LPWSTR StringBinding
, LPWSTR
*ObjUuid
,
738 LPWSTR
*Protseq
, LPWSTR
*NetworkAddr
,
739 LPWSTR
*Endpoint
, LPWSTR
*Options
)
742 static const WCHAR ep_opt
[] = {'e','n','d','p','o','i','n','t','=',0};
744 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding
),
745 ObjUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
);
747 if (ObjUuid
) *ObjUuid
= NULL
;
748 if (Protseq
) *Protseq
= NULL
;
749 if (NetworkAddr
) *NetworkAddr
= NULL
;
750 if (Endpoint
) *Endpoint
= NULL
;
751 if (Options
) *Options
= NULL
;
753 data
= StringBinding
;
755 next
= strchrW(data
, '@');
757 if (ObjUuid
) *ObjUuid
= RPCRT4_strndupW(data
, next
- data
);
761 next
= strchrW(data
, ':');
763 if (Protseq
) *Protseq
= RPCRT4_strndupW(data
, next
- data
);
767 next
= strchrW(data
, '[');
771 if (NetworkAddr
) *NetworkAddr
= RPCRT4_strndupW(data
, next
- data
);
773 close
= strchrW(data
, ']');
774 if (!close
) goto fail
;
776 /* tokenize options */
777 while (data
< close
) {
778 next
= strchrW(data
, ',');
779 if (!next
|| next
> close
) next
= close
;
780 /* FIXME: this is kind of inefficient */
781 opt
= RPCRT4_strndupW(data
, next
- data
);
785 next
= strchrW(opt
, '=');
787 /* not an option, must be an endpoint */
788 if (*Endpoint
) goto fail
;
791 if (strncmpW(opt
, ep_opt
, strlenW(ep_opt
)) == 0) {
792 /* endpoint option */
793 if (*Endpoint
) goto fail
;
794 *Endpoint
= RPCRT4_strdupW(next
+1);
795 HeapFree(GetProcessHeap(), 0, opt
);
799 /* FIXME: this is kind of inefficient */
800 *Options
= RPCRT4_strconcatW(*Options
, opt
);
801 HeapFree(GetProcessHeap(), 0, opt
);
809 if (*data
) goto fail
;
810 } else if (NetworkAddr
)
811 *NetworkAddr
= RPCRT4_strdupW(data
);
816 if (ObjUuid
) RpcStringFreeW(ObjUuid
);
817 if (Protseq
) RpcStringFreeW(Protseq
);
818 if (NetworkAddr
) RpcStringFreeW(NetworkAddr
);
819 if (Endpoint
) RpcStringFreeW(Endpoint
);
820 if (Options
) RpcStringFreeW(Options
);
821 return RPC_S_INVALID_STRING_BINDING
;
824 /***********************************************************************
825 * RpcBindingFree (RPCRT4.@)
827 RPC_STATUS WINAPI
RpcBindingFree( RPC_BINDING_HANDLE
* Binding
)
830 TRACE("(%p) = %p\n", Binding
, *Binding
);
831 status
= RPCRT4_DestroyBinding(*Binding
);
832 if (status
== RPC_S_OK
) *Binding
= 0;
836 /***********************************************************************
837 * RpcBindingVectorFree (RPCRT4.@)
839 RPC_STATUS WINAPI
RpcBindingVectorFree( RPC_BINDING_VECTOR
** BindingVector
)
844 TRACE("(%p)\n", BindingVector
);
845 for (c
=0; c
<(*BindingVector
)->Count
; c
++) {
846 status
= RpcBindingFree(&(*BindingVector
)->BindingH
[c
]);
848 HeapFree(GetProcessHeap(), 0, *BindingVector
);
849 *BindingVector
= NULL
;
853 /***********************************************************************
854 * RpcBindingInqObject (RPCRT4.@)
856 RPC_STATUS WINAPI
RpcBindingInqObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
858 RpcBinding
* bind
= (RpcBinding
*)Binding
;
860 TRACE("(%p,%p) = %s\n", Binding
, ObjectUuid
, debugstr_guid(&bind
->ObjectUuid
));
861 memcpy(ObjectUuid
, &bind
->ObjectUuid
, sizeof(UUID
));
865 /***********************************************************************
866 * RpcBindingSetObject (RPCRT4.@)
868 RPC_STATUS WINAPI
RpcBindingSetObject( RPC_BINDING_HANDLE Binding
, UUID
* ObjectUuid
)
870 RpcBinding
* bind
= (RpcBinding
*)Binding
;
872 TRACE("(%p,%s)\n", Binding
, debugstr_guid(ObjectUuid
));
873 if (bind
->server
) return RPC_S_WRONG_KIND_OF_BINDING
;
874 return RPCRT4_SetBindingObject(Binding
, ObjectUuid
);
877 /***********************************************************************
878 * RpcBindingFromStringBindingA (RPCRT4.@)
880 RPC_STATUS WINAPI
RpcBindingFromStringBindingA( LPSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
883 RpcBinding
* bind
= NULL
;
884 LPSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
887 TRACE("(%s,%p)\n", debugstr_a(StringBinding
), Binding
);
889 ret
= RpcStringBindingParseA(StringBinding
, &ObjectUuid
, &Protseq
,
890 &NetworkAddr
, &Endpoint
, &Options
);
891 if (ret
!= RPC_S_OK
) return ret
;
893 ret
= UuidFromStringA(ObjectUuid
, &Uuid
);
896 ret
= RPCRT4_CreateBindingA(&bind
, FALSE
, Protseq
);
898 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
900 ret
= RPCRT4_CompleteBindingA(bind
, NetworkAddr
, Endpoint
, Options
);
902 RpcStringFreeA((unsigned char**)&Options
);
903 RpcStringFreeA((unsigned char**)&Endpoint
);
904 RpcStringFreeA((unsigned char**)&NetworkAddr
);
905 RpcStringFreeA((unsigned char**)&Protseq
);
906 RpcStringFreeA((unsigned char**)&ObjectUuid
);
909 *Binding
= (RPC_BINDING_HANDLE
)bind
;
911 RPCRT4_DestroyBinding(bind
);
916 /***********************************************************************
917 * RpcBindingFromStringBindingW (RPCRT4.@)
919 RPC_STATUS WINAPI
RpcBindingFromStringBindingW( LPWSTR StringBinding
, RPC_BINDING_HANDLE
* Binding
)
922 RpcBinding
* bind
= NULL
;
923 LPWSTR ObjectUuid
, Protseq
, NetworkAddr
, Endpoint
, Options
;
926 TRACE("(%s,%p)\n", debugstr_w(StringBinding
), Binding
);
928 ret
= RpcStringBindingParseW(StringBinding
, &ObjectUuid
, &Protseq
,
929 &NetworkAddr
, &Endpoint
, &Options
);
930 if (ret
!= RPC_S_OK
) return ret
;
932 ret
= UuidFromStringW(ObjectUuid
, &Uuid
);
935 ret
= RPCRT4_CreateBindingW(&bind
, FALSE
, Protseq
);
937 ret
= RPCRT4_SetBindingObject(bind
, &Uuid
);
939 ret
= RPCRT4_CompleteBindingW(bind
, NetworkAddr
, Endpoint
, Options
);
941 RpcStringFreeW(&Options
);
942 RpcStringFreeW(&Endpoint
);
943 RpcStringFreeW(&NetworkAddr
);
944 RpcStringFreeW(&Protseq
);
945 RpcStringFreeW(&ObjectUuid
);
948 *Binding
= (RPC_BINDING_HANDLE
)bind
;
950 RPCRT4_DestroyBinding(bind
);
955 /***********************************************************************
956 * RpcBindingToStringBindingA (RPCRT4.@)
958 RPC_STATUS WINAPI
RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding
, LPSTR
* StringBinding
)
961 RpcBinding
* bind
= (RpcBinding
*)Binding
;
964 TRACE("(%p,%p)\n", Binding
, StringBinding
);
966 ret
= UuidToStringA(&bind
->ObjectUuid
, (unsigned char**)&ObjectUuid
);
967 if (ret
!= RPC_S_OK
) return ret
;
969 ret
= RpcStringBindingComposeA(ObjectUuid
, bind
->Protseq
, bind
->NetworkAddr
,
970 bind
->Endpoint
, NULL
, StringBinding
);
972 RpcStringFreeA((unsigned char**)&ObjectUuid
);
977 /***********************************************************************
978 * RpcBindingToStringBindingW (RPCRT4.@)
980 RPC_STATUS WINAPI
RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding
, LPWSTR
* StringBinding
)
984 TRACE("(%p,%p)\n", Binding
, StringBinding
);
985 ret
= RpcBindingToStringBindingA(Binding
, &str
);
986 *StringBinding
= RPCRT4_strdupAtoW(str
);
987 RpcStringFreeA((unsigned char**)&str
);
991 /***********************************************************************
992 * I_RpcBindingSetAsync (RPCRT4.@)
994 * Exists in win9x and winNT, but with different number of arguments
995 * (9x version has 3 arguments, NT has 2).
997 RPC_STATUS WINAPI
I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding
, RPC_BLOCKING_FN BlockingFn
)
999 RpcBinding
* bind
= (RpcBinding
*)Binding
;
1001 TRACE( "(%p,%p): stub\n", Binding
, BlockingFn
);
1003 bind
->BlockingFn
= BlockingFn
;