1 /* 2 * Endpoint Mapper 3 * 4 * Copyright (C) 2007 Robert Shearman for CodeWeavers 5 * 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. 10 * 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. 15 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "rpcss.h" 22 23 #include <wine/debug.h> 24 25 WINE_DEFAULT_DEBUG_CHANNEL(ole); 26 27 struct registered_ept_entry 28 { 29 struct list entry; 30 GUID object; 31 RPC_SYNTAX_IDENTIFIER iface; 32 RPC_SYNTAX_IDENTIFIER syntax; 33 char *protseq; 34 char *endpoint; 35 char *address; 36 char annotation[ept_max_annotation_size]; 37 }; 38 39 static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list); 40 41 static CRITICAL_SECTION csEpm; 42 static CRITICAL_SECTION_DEBUG critsect_debug = 43 { 44 0, 0, &csEpm, 45 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 46 0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") } 47 }; 48 static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 }; 49 50 static const UUID nil_object; 51 52 /* must be called inside csEpm */ 53 static void delete_registered_ept_entry(struct registered_ept_entry *entry) 54 { 55 I_RpcFree(entry->protseq); 56 I_RpcFree(entry->endpoint); 57 I_RpcFree(entry->address); 58 list_remove(&entry->entry); 59 HeapFree(GetProcessHeap(), 0, entry); 60 } 61 62 static struct registered_ept_entry *find_ept_entry( 63 const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax, 64 const char *protseq, const char *endpoint, const char *address, 65 const UUID *object) 66 { 67 struct registered_ept_entry *entry; 68 LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) 69 { 70 if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; 71 if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; 72 if (strcmp(entry->protseq, protseq)) continue; 73 if (memcmp(&entry->object, object, sizeof(UUID))) continue; 74 WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n", 75 entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion, 76 wine_dbgstr_guid(&entry->iface.SyntaxGUID), 77 entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion, 78 wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq, 79 wine_dbgstr_guid(&entry->object)); 80 return entry; 81 } 82 WINE_TRACE("not found\n"); 83 return NULL; 84 } 85 86 void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle) 87 { 88 WINE_FIXME("%p\n", entry_handle); 89 } 90 91 void __cdecl ept_insert(handle_t h, 92 unsigned32 num_ents, 93 ept_entry_t entries[], 94 boolean32 replace, 95 error_status_t *status) 96 { 97 unsigned32 i; 98 RPC_STATUS rpc_status; 99 100 WINE_TRACE("(%p, %u, %p, %u, %p)\n", h, num_ents, entries, replace, status); 101 102 *status = RPC_S_OK; 103 104 EnterCriticalSection(&csEpm); 105 106 for (i = 0; i < num_ents; i++) 107 { 108 struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); 109 if (!entry) 110 { 111 /* FIXME: cleanup code to delete added entries */ 112 *status = EPT_S_CANT_PERFORM_OP; 113 break; 114 } 115 memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation)); 116 rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax, 117 &entry->protseq, &entry->endpoint, 118 &entry->address); 119 if (rpc_status != RPC_S_OK) 120 { 121 WINE_WARN("TowerExplode failed %u\n", rpc_status); 122 *status = rpc_status; 123 HeapFree(GetProcessHeap(), 0, entry); 124 break; /* FIXME: more cleanup? */ 125 } 126 127 entry->object = entries[i].object; 128 129 if (replace) 130 { 131 /* FIXME: correct find algorithm */ 132 struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object); 133 if (old_entry) delete_registered_ept_entry(old_entry); 134 } 135 list_add_tail(®istered_ept_entry_list, &entry->entry); 136 } 137 138 LeaveCriticalSection(&csEpm); 139 } 140 141 void __cdecl ept_delete(handle_t h, 142 unsigned32 num_ents, 143 ept_entry_t entries[], 144 error_status_t *status) 145 { 146 unsigned32 i; 147 RPC_STATUS rpc_status; 148 149 *status = RPC_S_OK; 150 151 WINE_TRACE("(%p, %u, %p, %p)\n", h, num_ents, entries, status); 152 153 EnterCriticalSection(&csEpm); 154 155 for (i = 0; i < num_ents; i++) 156 { 157 struct registered_ept_entry *entry; 158 RPC_SYNTAX_IDENTIFIER iface, syntax; 159 char *protseq; 160 char *endpoint; 161 char *address; 162 rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq, 163 &endpoint, &address); 164 if (rpc_status != RPC_S_OK) 165 break; 166 entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object); 167 168 I_RpcFree(protseq); 169 I_RpcFree(endpoint); 170 I_RpcFree(address); 171 172 if (entry) 173 delete_registered_ept_entry(entry); 174 else 175 { 176 *status = EPT_S_NOT_REGISTERED; 177 break; 178 } 179 } 180 181 LeaveCriticalSection(&csEpm); 182 } 183 184 void __cdecl ept_lookup(handle_t h, 185 unsigned32 inquiry_type, 186 uuid_p_t object, 187 rpc_if_id_p_t interface_id, 188 unsigned32 vers_option, 189 ept_lookup_handle_t *entry_handle, 190 unsigned32 max_ents, 191 unsigned32 *num_ents, 192 ept_entry_t entries[], 193 error_status_t *status) 194 { 195 WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); 196 197 *status = EPT_S_CANT_PERFORM_OP; 198 } 199 200 void __cdecl ept_map(handle_t h, 201 uuid_p_t object, 202 twr_p_t map_tower, 203 ept_lookup_handle_t *entry_handle, 204 unsigned32 max_towers, 205 unsigned32 *num_towers, 206 twr_p_t *towers, 207 error_status_t *status) 208 { 209 RPC_STATUS rpc_status; 210 RPC_SYNTAX_IDENTIFIER iface, syntax; 211 char *protseq; 212 struct registered_ept_entry *entry; 213 214 *status = RPC_S_OK; 215 *num_towers = 0; 216 217 WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower, 218 entry_handle, max_towers, num_towers, towers, status); 219 220 rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq, 221 NULL, NULL); 222 if (rpc_status != RPC_S_OK) 223 { 224 *status = rpc_status; 225 return; 226 } 227 228 EnterCriticalSection(&csEpm); 229 230 LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) 231 { 232 if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) && 233 (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) && 234 (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) && 235 !memcmp(&entry->syntax, &syntax, sizeof(syntax)) && 236 !strcmp(entry->protseq, protseq) && 237 ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object))) 238 { 239 if (*num_towers < max_towers) 240 { 241 rpc_status = TowerConstruct(&entry->iface, &entry->syntax, 242 entry->protseq, entry->endpoint, 243 entry->address, 244 &towers[*num_towers]); 245 if (rpc_status != RPC_S_OK) 246 { 247 *status = rpc_status; 248 break; /* FIXME: more cleanup? */ 249 } 250 } 251 (*num_towers)++; 252 } 253 } 254 255 LeaveCriticalSection(&csEpm); 256 257 I_RpcFree(protseq); 258 } 259 260 void __cdecl ept_lookup_handle_free(handle_t h, 261 ept_lookup_handle_t *entry_handle, 262 error_status_t *status) 263 { 264 WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); 265 266 *status = EPT_S_CANT_PERFORM_OP; 267 } 268 269 void __cdecl ept_inq_object(handle_t h, 270 GUID *ept_object, 271 error_status_t *status) 272 { 273 WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status); 274 275 *status = EPT_S_CANT_PERFORM_OP; 276 } 277 278 void __cdecl ept_mgmt_delete(handle_t h, 279 boolean32 object_speced, 280 uuid_p_t object, 281 twr_p_t tower, 282 error_status_t *status) 283 { 284 WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status); 285 286 *status = EPT_S_CANT_PERFORM_OP; 287 } 288