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 static RpcConnection* conn_cache;
44 static CRITICAL_SECTION conn_cache_cs = CRITICAL_SECTION_INIT("conn_cache_cs");
46 LPSTR RPCRT4_strndupA(LPSTR src, INT slen)
50 if (!src) return NULL;
51 if (slen == -1) slen = strlen(src);
53 s = HeapAlloc(GetProcessHeap(), 0, len+1);
59 LPSTR RPCRT4_strdupWtoA(LPWSTR src)
63 if (!src) return NULL;
64 len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
65 s = HeapAlloc(GetProcessHeap(), 0, len);
66 WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
70 LPWSTR RPCRT4_strdupAtoW(LPSTR src)
74 if (!src) return NULL;
75 len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
76 s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
77 MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
81 LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen)
85 if (!src) return NULL;
86 if (slen == -1) slen = strlenW(src);
88 s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
89 memcpy(s, src, len*sizeof(WCHAR));
94 void RPCRT4_strfree(LPSTR src)
96 if (src) HeapFree(GetProcessHeap(), 0, src);
99 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding)
101 RpcConnection* NewConnection;
103 NewConnection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection));
104 NewConnection->server = server;
105 NewConnection->Protseq = RPCRT4_strdupA(Protseq);
106 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
107 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
108 NewConnection->Used = Binding;
110 EnterCriticalSection(&conn_cache_cs);
111 NewConnection->Next = conn_cache;
112 conn_cache = NewConnection;
113 LeaveCriticalSection(&conn_cache_cs);
115 TRACE("connection: %p\n", NewConnection);
116 *Connection = NewConnection;
121 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
123 RpcConnection* PrevConnection;
125 TRACE("connection: %p\n", Connection);
126 if (Connection->Used) ERR("connection is still in use\n");
128 EnterCriticalSection(&conn_cache_cs);
129 PrevConnection = conn_cache;
130 while (PrevConnection && PrevConnection->Next != Connection)
131 PrevConnection = PrevConnection->Next;
132 if (PrevConnection) PrevConnection->Next = Connection->Next;
133 LeaveCriticalSection(&conn_cache_cs);
135 RPCRT4_CloseConnection(Connection);
136 RPCRT4_strfree(Connection->Endpoint);
137 RPCRT4_strfree(Connection->NetworkAddr);
138 RPCRT4_strfree(Connection->Protseq);
139 HeapFree(GetProcessHeap(), 0, Connection);
143 RPC_STATUS RPCRT4_GetConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding)
145 RpcConnection* NewConnection;
148 EnterCriticalSection(&conn_cache_cs);
149 for (NewConnection = conn_cache; NewConnection; NewConnection = NewConnection->Next) {
150 if (NewConnection->Used) continue;
151 if (NewConnection->server != server) continue;
152 if (Protseq && strcmp(NewConnection->Protseq, Protseq)) continue;
153 if (NetworkAddr && strcmp(NewConnection->NetworkAddr, NetworkAddr)) continue;
154 if (Endpoint && strcmp(NewConnection->Endpoint, Endpoint)) continue;
155 /* this connection fits the bill */
156 NewConnection->Used = Binding;
159 LeaveCriticalSection(&conn_cache_cs);
161 TRACE("cached connection: %p\n", NewConnection);
162 *Connection = NewConnection;
166 return RPCRT4_CreateConnection(Connection, server, Protseq, NetworkAddr, Endpoint, NetworkOptions, Binding);
169 RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
171 TRACE("connection: %p\n", Connection);
172 Connection->Used = NULL;
173 if (!Connection->server) {
174 /* cache the open connection for reuse later */
175 /* FIXME: we should probably clean the cache someday */
178 return RPCRT4_DestroyConnection(Connection);
181 RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection)
183 TRACE("(Connection == ^%p)\n", Connection);
184 if (!Connection->conn) {
185 if (Connection->server) { /* server */
186 /* protseq=ncalrpc: supposed to use NT LPC ports,
187 * but we'll implement it with named pipes for now */
188 if (strcmp(Connection->Protseq, "ncalrpc") == 0) {
189 static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
191 pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
192 strcat(strcpy(pname, prefix), Connection->Endpoint);
193 TRACE("listening on %s\n", pname);
194 Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
195 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
196 HeapFree(GetProcessHeap(), 0, pname);
197 memset(&Connection->ovl, 0, sizeof(Connection->ovl));
198 Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
199 if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {
200 DWORD err = GetLastError();
201 if (err == ERROR_PIPE_CONNECTED) {
202 SetEvent(Connection->ovl.hEvent);
208 /* protseq=ncacn_np: named pipes */
209 else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {
210 static LPSTR prefix = "\\\\.";
212 pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
213 strcat(strcpy(pname, prefix), Connection->Endpoint);
214 TRACE("listening on %s\n", pname);
215 Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
216 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
217 HeapFree(GetProcessHeap(), 0, pname);
218 memset(&Connection->ovl, 0, sizeof(Connection->ovl));
219 Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
220 if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {
221 DWORD err = GetLastError();
222 if (err == ERROR_PIPE_CONNECTED) {
223 SetEvent(Connection->ovl.hEvent);
230 ERR("protseq %s not supported\n", Connection->Protseq);
231 return RPC_S_PROTSEQ_NOT_SUPPORTED;
235 /* protseq=ncalrpc: supposed to use NT LPC ports,
236 * but we'll implement it with named pipes for now */
237 if (strcmp(Connection->Protseq, "ncalrpc") == 0) {
238 static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
243 pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
244 strcat(strcpy(pname, prefix), Connection->Endpoint);
245 TRACE("connecting to %s\n", pname);
247 if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
248 conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
249 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
250 if (conn != INVALID_HANDLE_VALUE) break;
251 err = GetLastError();
252 if (err == ERROR_PIPE_BUSY) continue;
253 TRACE("connection failed, error=%lx\n", err);
254 HeapFree(GetProcessHeap(), 0, pname);
257 err = GetLastError();
258 TRACE("connection failed, error=%lx\n", err);
259 HeapFree(GetProcessHeap(), 0, pname);
265 HeapFree(GetProcessHeap(), 0, pname);
266 memset(&Connection->ovl, 0, sizeof(Connection->ovl));
267 Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
268 Connection->conn = conn;
270 /* protseq=ncacn_np: named pipes */
271 else if (strcmp(Connection->Protseq, "ncacn_np") == 0) {
272 static LPSTR prefix = "\\\\.";
277 pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1);
278 strcat(strcpy(pname, prefix), Connection->Endpoint);
279 TRACE("connecting to %s\n", pname);
280 conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
281 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
282 if (conn == INVALID_HANDLE_VALUE) {
283 err = GetLastError();
284 /* we don't need to handle ERROR_PIPE_BUSY here,
285 * the doc says that it is returned to the app */
286 TRACE("connection failed, error=%lx\n", err);
287 HeapFree(GetProcessHeap(), 0, pname);
292 HeapFree(GetProcessHeap(), 0, pname);
293 memset(&Connection->ovl, 0, sizeof(Connection->ovl));
294 Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
295 Connection->conn = conn;
297 ERR("protseq %s not supported\n", Connection->Protseq);
298 return RPC_S_PROTSEQ_NOT_SUPPORTED;
305 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
307 TRACE("(Connection == ^%p)\n", Connection);
308 if (Connection->conn) {
309 CancelIo(Connection->conn);
310 CloseHandle(Connection->conn);
311 Connection->conn = 0;
313 if (Connection->ovl.hEvent) {
314 CloseHandle(Connection->ovl.hEvent);
315 Connection->ovl.hEvent = 0;
320 RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
322 RpcConnection* NewConnection;
323 RPC_STATUS err = RPCRT4_CreateConnection(&NewConnection, OldConnection->server, OldConnection->Protseq,
324 OldConnection->NetworkAddr, OldConnection->Endpoint, NULL, NULL);
325 if (err == RPC_S_OK) {
326 /* because of the way named pipes work, we'll transfer the connected pipe
327 * to the child, then reopen the server binding to continue listening */
328 NewConnection->conn = OldConnection->conn;
329 NewConnection->ovl = OldConnection->ovl;
330 OldConnection->conn = 0;
331 memset(&OldConnection->ovl, 0, sizeof(OldConnection->ovl));
332 *Connection = NewConnection;
333 RPCRT4_OpenConnection(OldConnection);
338 RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
340 RpcBinding* NewBinding;
342 NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
343 NewBinding->refs = 1;
344 NewBinding->server = server;
346 *Binding = NewBinding;
351 RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
353 RpcBinding* NewBinding;
355 RPCRT4_AllocBinding(&NewBinding, server);
356 NewBinding->Protseq = RPCRT4_strdupA(Protseq);
358 TRACE("binding: %p\n", NewBinding);
359 *Binding = NewBinding;
364 RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
366 RpcBinding* NewBinding;
368 RPCRT4_AllocBinding(&NewBinding, server);
369 NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
371 TRACE("binding: %p\n", NewBinding);
372 *Binding = NewBinding;
377 RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions)
379 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding,
380 debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
382 RPCRT4_strfree(Binding->NetworkAddr);
383 Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
384 RPCRT4_strfree(Binding->Endpoint);
386 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
388 Binding->Endpoint = RPCRT4_strdupA("");
390 if (!Binding->Endpoint) ERR("out of memory?\n");
395 RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
397 TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding,
398 debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
400 RPCRT4_strfree(Binding->NetworkAddr);
401 Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
402 RPCRT4_strfree(Binding->Endpoint);
404 Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
406 Binding->Endpoint = RPCRT4_strdupA("");
408 if (!Binding->Endpoint) ERR("out of memory?\n");
413 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
415 TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
417 RPCRT4_strfree(Binding->Endpoint);
418 Binding->Endpoint = RPCRT4_strdupA(Endpoint);
423 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
425 TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid));
426 if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
427 else UuidCreateNil(&Binding->ObjectUuid);
431 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
433 RpcBinding* NewBinding;
434 TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding, Connection);
436 RPCRT4_AllocBinding(&NewBinding, Connection->server);
437 NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq);
438 NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
439 NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
440 NewBinding->FromConn = Connection;
442 TRACE("binding: %p\n", NewBinding);
443 *Binding = NewBinding;
448 RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
450 InterlockedIncrement(&OldBinding->refs);
451 *Binding = OldBinding;
455 RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
457 if (InterlockedDecrement(&Binding->refs))
460 TRACE("binding: %p\n", Binding);
461 /* FIXME: release connections */
462 RPCRT4_strfree(Binding->Endpoint);
463 RPCRT4_strfree(Binding->NetworkAddr);
464 RPCRT4_strfree(Binding->Protseq);
465 HeapFree(GetProcessHeap(), 0, Binding);
469 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection)
471 RpcConnection* NewConnection;
472 TRACE("(Binding == ^%p)\n", Binding);
473 if (Binding->FromConn) {
474 *Connection = Binding->FromConn;
478 RPCRT4_GetConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL, Binding);
479 *Connection = NewConnection;
480 return RPCRT4_OpenConnection(NewConnection);
483 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
485 TRACE("(Binding == ^%p)\n", Binding);
486 if (!Connection) return RPC_S_OK;
487 if (Binding->FromConn == Connection) return RPC_S_OK;
488 return RPCRT4_ReleaseConnection(Connection);
491 /* utility functions for string composing and parsing */
492 static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
494 unsigned len = strlen(src);
495 memcpy(data, src, len*sizeof(CHAR));
499 static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
501 unsigned len = strlenW(src);
502 memcpy(data, src, len*sizeof(WCHAR));
506 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
508 DWORD len = strlen(dst), slen = strlen(src);
509 LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
510 if (!ndst) HeapFree(GetProcessHeap(), 0, dst);
512 memcpy(ndst+len+1, src, slen*sizeof(CHAR));
513 ndst[len+slen+1] = 0;
517 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
519 DWORD len = strlenW(dst), slen = strlenW(src);
520 LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
521 if (!ndst) HeapFree(GetProcessHeap(), 0, dst);
523 memcpy(ndst+len+1, src, slen*sizeof(WCHAR));
524 ndst[len+slen+1] = 0;
529 /***********************************************************************
530 * RpcStringBindingComposeA (RPCRT4.@)
532 RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq,
533 LPSTR NetworkAddr, LPSTR Endpoint,
534 LPSTR Options, LPSTR* StringBinding )
539 TRACE( "(%s,%s,%s,%s,%s,%p)\n",
540 debugstr_a( ObjUuid ), debugstr_a( Protseq ),
541 debugstr_a( NetworkAddr ), debugstr_a( Endpoint ),
542 debugstr_a( Options ), StringBinding );
544 if (ObjUuid && *ObjUuid) len += strlen(ObjUuid) + 1;
545 if (Protseq && *Protseq) len += strlen(Protseq) + 1;
546 if (NetworkAddr && *NetworkAddr) len += strlen(NetworkAddr);
547 if (Endpoint && *Endpoint) len += strlen(Endpoint) + 2;
548 if (Options && *Options) len += strlen(Options) + 2;
550 data = HeapAlloc(GetProcessHeap(), 0, len);
551 *StringBinding = data;
553 if (ObjUuid && *ObjUuid) {
554 data += RPCRT4_strcopyA(data, ObjUuid);
557 if (Protseq && *Protseq) {
558 data += RPCRT4_strcopyA(data, Protseq);
561 if (NetworkAddr && *NetworkAddr)
562 data += RPCRT4_strcopyA(data, NetworkAddr);
564 if ((Endpoint && *Endpoint) ||
565 (Options && *Options)) {
567 if (Endpoint && *Endpoint) {
568 data += RPCRT4_strcopyA(data, Endpoint);
569 if (Options && *Options) *data++ = ',';
571 if (Options && *Options) {
572 data += RPCRT4_strcopyA(data, Options);
581 /***********************************************************************
582 * RpcStringBindingComposeW (RPCRT4.@)
584 RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,
585 LPWSTR NetworkAddr, LPWSTR Endpoint,
586 LPWSTR Options, LPWSTR* StringBinding )
591 TRACE("(%s,%s,%s,%s,%s,%p)\n",
592 debugstr_w( ObjUuid ), debugstr_w( Protseq ),
593 debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
594 debugstr_w( Options ), StringBinding);
596 if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1;
597 if (Protseq && *Protseq) len += strlenW(Protseq) + 1;
598 if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr);
599 if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2;
600 if (Options && *Options) len += strlenW(Options) + 2;
602 data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
603 *StringBinding = data;
605 if (ObjUuid && *ObjUuid) {
606 data += RPCRT4_strcopyW(data, ObjUuid);
609 if (Protseq && *Protseq) {
610 data += RPCRT4_strcopyW(data, Protseq);
613 if (NetworkAddr && *NetworkAddr) {
614 data += RPCRT4_strcopyW(data, NetworkAddr);
616 if ((Endpoint && *Endpoint) ||
617 (Options && *Options)) {
619 if (Endpoint && *Endpoint) {
620 data += RPCRT4_strcopyW(data, Endpoint);
621 if (Options && *Options) *data++ = ',';
623 if (Options && *Options) {
624 data += RPCRT4_strcopyW(data, Options);
634 /***********************************************************************
635 * RpcStringBindingParseA (RPCRT4.@)
637 RPC_STATUS WINAPI RpcStringBindingParseA( LPSTR StringBinding, LPSTR *ObjUuid,
638 LPSTR *Protseq, LPSTR *NetworkAddr,
639 LPSTR *Endpoint, LPSTR *Options)
642 static const char ep_opt[] = "endpoint=";
644 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding),
645 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
647 if (ObjUuid) *ObjUuid = NULL;
648 if (Protseq) *Protseq = NULL;
649 if (NetworkAddr) *NetworkAddr = NULL;
650 if (Endpoint) *Endpoint = NULL;
651 if (Options) *Options = NULL;
653 data = StringBinding;
655 next = strchr(data, '@');
657 if (ObjUuid) *ObjUuid = RPCRT4_strndupA(data, next - data);
661 next = strchr(data, ':');
663 if (Protseq) *Protseq = RPCRT4_strndupA(data, next - data);
667 next = strchr(data, '[');
671 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupA(data, next - data);
673 close = strchr(data, ']');
674 if (!close) goto fail;
676 /* tokenize options */
677 while (data < close) {
678 next = strchr(data, ',');
679 if (!next || next > close) next = close;
680 /* FIXME: this is kind of inefficient */
681 opt = RPCRT4_strndupA(data, next - data);
685 next = strchr(opt, '=');
687 /* not an option, must be an endpoint */
688 if (*Endpoint) goto fail;
691 if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) {
692 /* endpoint option */
693 if (*Endpoint) goto fail;
694 *Endpoint = RPCRT4_strdupA(next+1);
695 HeapFree(GetProcessHeap(), 0, opt);
699 /* FIXME: this is kind of inefficient */
700 *Options = RPCRT4_strconcatA(*Options, opt);
701 HeapFree(GetProcessHeap(), 0, opt);
709 if (*data) goto fail;
711 else if (NetworkAddr)
712 *NetworkAddr = RPCRT4_strdupA(data);
717 if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
718 if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
719 if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
720 if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
721 if (Options) RpcStringFreeA((unsigned char**)Options);
722 return RPC_S_INVALID_STRING_BINDING;
725 /***********************************************************************
726 * RpcStringBindingParseW (RPCRT4.@)
728 RPC_STATUS WINAPI RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR *ObjUuid,
729 LPWSTR *Protseq, LPWSTR *NetworkAddr,
730 LPWSTR *Endpoint, LPWSTR *Options)
733 static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
735 TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
736 ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
738 if (ObjUuid) *ObjUuid = NULL;
739 if (Protseq) *Protseq = NULL;
740 if (NetworkAddr) *NetworkAddr = NULL;
741 if (Endpoint) *Endpoint = NULL;
742 if (Options) *Options = NULL;
744 data = StringBinding;
746 next = strchrW(data, '@');
748 if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data);
752 next = strchrW(data, ':');
754 if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data);
758 next = strchrW(data, '[');
762 if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data);
764 close = strchrW(data, ']');
765 if (!close) goto fail;
767 /* tokenize options */
768 while (data < close) {
769 next = strchrW(data, ',');
770 if (!next || next > close) next = close;
771 /* FIXME: this is kind of inefficient */
772 opt = RPCRT4_strndupW(data, next - data);
776 next = strchrW(opt, '=');
778 /* not an option, must be an endpoint */
779 if (*Endpoint) goto fail;
782 if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
783 /* endpoint option */
784 if (*Endpoint) goto fail;
785 *Endpoint = RPCRT4_strdupW(next+1);
786 HeapFree(GetProcessHeap(), 0, opt);
790 /* FIXME: this is kind of inefficient */
791 *Options = RPCRT4_strconcatW(*Options, opt);
792 HeapFree(GetProcessHeap(), 0, opt);
800 if (*data) goto fail;
801 } else if (NetworkAddr)
802 *NetworkAddr = RPCRT4_strdupW(data);
807 if (ObjUuid) RpcStringFreeW(ObjUuid);
808 if (Protseq) RpcStringFreeW(Protseq);
809 if (NetworkAddr) RpcStringFreeW(NetworkAddr);
810 if (Endpoint) RpcStringFreeW(Endpoint);
811 if (Options) RpcStringFreeW(Options);
812 return RPC_S_INVALID_STRING_BINDING;
815 /***********************************************************************
816 * RpcBindingFree (RPCRT4.@)
818 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
821 TRACE("(%p) = %p\n", Binding, *Binding);
822 status = RPCRT4_DestroyBinding(*Binding);
823 if (status == RPC_S_OK) *Binding = 0;
827 /***********************************************************************
828 * RpcBindingVectorFree (RPCRT4.@)
830 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
835 TRACE("(%p)\n", BindingVector);
836 for (c=0; c<(*BindingVector)->Count; c++) {
837 status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
839 HeapFree(GetProcessHeap(), 0, *BindingVector);
840 *BindingVector = NULL;
844 /***********************************************************************
845 * RpcBindingInqObject (RPCRT4.@)
847 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
849 RpcBinding* bind = (RpcBinding*)Binding;
851 TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
852 memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
856 /***********************************************************************
857 * RpcBindingSetObject (RPCRT4.@)
859 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
861 RpcBinding* bind = (RpcBinding*)Binding;
863 TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
864 if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
865 return RPCRT4_SetBindingObject(Binding, ObjectUuid);
868 /***********************************************************************
869 * RpcBindingFromStringBindingA (RPCRT4.@)
871 RPC_STATUS WINAPI RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding )
874 RpcBinding* bind = NULL;
875 LPSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
878 TRACE("(%s,%p)\n", debugstr_a(StringBinding), Binding);
880 ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
881 &NetworkAddr, &Endpoint, &Options);
882 if (ret != RPC_S_OK) return ret;
884 ret = UuidFromStringA(ObjectUuid, &Uuid);
887 ret = RPCRT4_CreateBindingA(&bind, FALSE, Protseq);
889 ret = RPCRT4_SetBindingObject(bind, &Uuid);
891 ret = RPCRT4_CompleteBindingA(bind, NetworkAddr, Endpoint, Options);
893 RpcStringFreeA((unsigned char**)&Options);
894 RpcStringFreeA((unsigned char**)&Endpoint);
895 RpcStringFreeA((unsigned char**)&NetworkAddr);
896 RpcStringFreeA((unsigned char**)&Protseq);
897 RpcStringFreeA((unsigned char**)&ObjectUuid);
900 *Binding = (RPC_BINDING_HANDLE)bind;
902 RPCRT4_DestroyBinding(bind);
907 /***********************************************************************
908 * RpcBindingFromStringBindingW (RPCRT4.@)
910 RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
913 RpcBinding* bind = NULL;
914 LPWSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
917 TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
919 ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
920 &NetworkAddr, &Endpoint, &Options);
921 if (ret != RPC_S_OK) return ret;
923 ret = UuidFromStringW(ObjectUuid, &Uuid);
926 ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
928 ret = RPCRT4_SetBindingObject(bind, &Uuid);
930 ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
932 RpcStringFreeW(&Options);
933 RpcStringFreeW(&Endpoint);
934 RpcStringFreeW(&NetworkAddr);
935 RpcStringFreeW(&Protseq);
936 RpcStringFreeW(&ObjectUuid);
939 *Binding = (RPC_BINDING_HANDLE)bind;
941 RPCRT4_DestroyBinding(bind);
946 /***********************************************************************
947 * RpcBindingToStringBindingA (RPCRT4.@)
949 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, LPSTR* StringBinding )
952 RpcBinding* bind = (RpcBinding*)Binding;
955 TRACE("(%p,%p)\n", Binding, StringBinding);
957 ret = UuidToStringA(&bind->ObjectUuid, (unsigned char**)&ObjectUuid);
958 if (ret != RPC_S_OK) return ret;
960 ret = RpcStringBindingComposeA(ObjectUuid, bind->Protseq, bind->NetworkAddr,
961 bind->Endpoint, NULL, StringBinding);
963 RpcStringFreeA((unsigned char**)&ObjectUuid);
968 /***********************************************************************
969 * RpcBindingToStringBindingW (RPCRT4.@)
971 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, LPWSTR* StringBinding )
975 TRACE("(%p,%p)\n", Binding, StringBinding);
976 ret = RpcBindingToStringBindingA(Binding, &str);
977 *StringBinding = RPCRT4_strdupAtoW(str);
978 RpcStringFreeA((unsigned char**)&str);
982 /***********************************************************************
983 * I_RpcBindingSetAsync (RPCRT4.@)
985 * Exists in win9x and winNT, but with different number of arguments
986 * (9x version has 3 arguments, NT has 2).
988 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
990 RpcBinding* bind = (RpcBinding*)Binding;
992 TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
994 bind->BlockingFn = BlockingFn;