| /* | |
| * 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 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 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 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 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 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 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 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; | |
| } |