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