| /* |
| * Endpoint Mapper |
| * |
| * Copyright (C) 2007 Robert Shearman for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "epm.h" |
| |
| #include "wine/debug.h" |
| #include "wine/list.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ole); |
| |
| struct registered_ept_entry |
| { |
| struct list entry; |
| GUID object; |
| RPC_SYNTAX_IDENTIFIER iface; |
| RPC_SYNTAX_IDENTIFIER syntax; |
| char *protseq; |
| char *endpoint; |
| char *address; |
| char annotation[ept_max_annotation_size]; |
| }; |
| |
| static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list); |
| |
| static CRITICAL_SECTION csEpm; |
| static CRITICAL_SECTION_DEBUG critsect_debug = |
| { |
| 0, 0, &csEpm, |
| { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, |
| 0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") } |
| }; |
| static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 }; |
| |
| static const UUID nil_object; |
| |
| /* must be called inside csEpm */ |
| static void delete_registered_ept_entry(struct registered_ept_entry *entry) |
| { |
| I_RpcFree(entry->protseq); |
| I_RpcFree(entry->endpoint); |
| I_RpcFree(entry->address); |
| list_remove(&entry->entry); |
| HeapFree(GetProcessHeap(), 0, entry); |
| } |
| |
| static struct registered_ept_entry *find_ept_entry( |
| const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax, |
| const char *protseq, const char *endpoint, const char *address, |
| const UUID *object) |
| { |
| struct registered_ept_entry *entry; |
| LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) |
| { |
| if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; |
| if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; |
| if (strcmp(entry->protseq, protseq)) continue; |
| if (memcmp(&entry->object, object, sizeof(UUID))) continue; |
| WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n", |
| entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion, |
| wine_dbgstr_guid(&entry->iface.SyntaxGUID), |
| entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion, |
| wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq, |
| wine_dbgstr_guid(&entry->object)); |
| return entry; |
| } |
| WINE_TRACE("not found\n"); |
| return NULL; |
| } |
| |
| void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle) |
| { |
| WINE_FIXME("%p\n", entry_handle); |
| } |
| |
| void __cdecl ept_insert(handle_t h, |
| unsigned32 num_ents, |
| ept_entry_t entries[], |
| boolean32 replace, |
| error_status_t *status) |
| { |
| unsigned32 i; |
| RPC_STATUS rpc_status; |
| |
| WINE_TRACE("(%p, %u, %p, %u, %p)\n", h, num_ents, entries, replace, status); |
| |
| *status = RPC_S_OK; |
| |
| EnterCriticalSection(&csEpm); |
| |
| for (i = 0; i < num_ents; i++) |
| { |
| struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); |
| if (!entry) |
| { |
| /* FIXME: cleanup code to delete added entries */ |
| *status = EPT_S_CANT_PERFORM_OP; |
| break; |
| } |
| list_init(&entry->entry); |
| memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation)); |
| rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax, |
| &entry->protseq, &entry->endpoint, |
| &entry->address); |
| if (rpc_status != RPC_S_OK) |
| { |
| WINE_WARN("TowerExplode failed %u\n", rpc_status); |
| *status = rpc_status; |
| break; /* FIXME: more cleanup? */ |
| } |
| |
| entry->object = entries[i].object; |
| |
| if (replace) |
| { |
| /* FIXME: correct find algorithm */ |
| struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object); |
| if (old_entry) delete_registered_ept_entry(old_entry); |
| } |
| list_add_tail(®istered_ept_entry_list, &entry->entry); |
| } |
| |
| LeaveCriticalSection(&csEpm); |
| } |
| |
| void __cdecl ept_delete(handle_t h, |
| unsigned32 num_ents, |
| ept_entry_t entries[], |
| error_status_t *status) |
| { |
| unsigned32 i; |
| RPC_STATUS rpc_status; |
| |
| *status = RPC_S_OK; |
| |
| WINE_TRACE("(%p, %u, %p, %p)\n", h, num_ents, entries, status); |
| |
| EnterCriticalSection(&csEpm); |
| |
| for (i = 0; i < num_ents; i++) |
| { |
| struct registered_ept_entry *entry; |
| RPC_SYNTAX_IDENTIFIER iface, syntax; |
| char *protseq; |
| char *endpoint; |
| char *address; |
| rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq, |
| &endpoint, &address); |
| if (rpc_status != RPC_S_OK) |
| break; |
| entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object); |
| if (entry) |
| delete_registered_ept_entry(entry); |
| else |
| { |
| *status = EPT_S_NOT_REGISTERED; |
| break; |
| } |
| I_RpcFree(protseq); |
| I_RpcFree(endpoint); |
| I_RpcFree(address); |
| } |
| |
| LeaveCriticalSection(&csEpm); |
| } |
| |
| void __cdecl ept_lookup(handle_t h, |
| unsigned32 inquiry_type, |
| uuid_p_t object, |
| rpc_if_id_p_t interface_id, |
| unsigned32 vers_option, |
| ept_lookup_handle_t *entry_handle, |
| unsigned32 max_ents, |
| unsigned32 *num_ents, |
| ept_entry_t entries[], |
| error_status_t *status) |
| { |
| WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); |
| |
| *status = EPT_S_CANT_PERFORM_OP; |
| } |
| |
| void __cdecl ept_map(handle_t h, |
| uuid_p_t object, |
| twr_p_t map_tower, |
| ept_lookup_handle_t *entry_handle, |
| unsigned32 max_towers, |
| unsigned32 *num_towers, |
| twr_p_t *towers, |
| error_status_t *status) |
| { |
| RPC_STATUS rpc_status; |
| RPC_SYNTAX_IDENTIFIER iface, syntax; |
| char *protseq; |
| struct registered_ept_entry *entry; |
| |
| *status = RPC_S_OK; |
| *num_towers = 0; |
| |
| WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower, |
| entry_handle, max_towers, num_towers, towers, status); |
| |
| rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq, |
| NULL, NULL); |
| if (rpc_status != RPC_S_OK) |
| { |
| *status = rpc_status; |
| return; |
| } |
| |
| EnterCriticalSection(&csEpm); |
| |
| LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) |
| { |
| if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) && |
| (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) && |
| (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) && |
| !memcmp(&entry->syntax, &syntax, sizeof(syntax)) && |
| !strcmp(entry->protseq, protseq) && |
| ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object))) |
| { |
| if (*num_towers < max_towers) |
| { |
| rpc_status = TowerConstruct(&entry->iface, &entry->syntax, |
| entry->protseq, entry->endpoint, |
| entry->address, |
| &towers[*num_towers]); |
| if (rpc_status != RPC_S_OK) |
| { |
| *status = rpc_status; |
| break; /* FIXME: more cleanup? */ |
| } |
| } |
| (*num_towers)++; |
| } |
| } |
| |
| LeaveCriticalSection(&csEpm); |
| } |
| |
| void __cdecl ept_lookup_handle_free(handle_t h, |
| ept_lookup_handle_t *entry_handle, |
| error_status_t *status) |
| { |
| WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); |
| |
| *status = EPT_S_CANT_PERFORM_OP; |
| } |
| |
| void __cdecl ept_inq_object(handle_t h, |
| GUID *ept_object, |
| error_status_t *status) |
| { |
| WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status); |
| |
| *status = EPT_S_CANT_PERFORM_OP; |
| } |
| |
| void __cdecl ept_mgmt_delete(handle_t h, |
| boolean32 object_speced, |
| uuid_p_t object, |
| twr_p_t tower, |
| error_status_t *status) |
| { |
| WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status); |
| |
| *status = EPT_S_CANT_PERFORM_OP; |
| } |