ntdll: Refuse to create new thread if the target process is being terminated.
[wine] / programs / rpcss / epmp.c
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.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, &registered_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         list_init(&entry->entry);
117         memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation));
118         rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax,
119                                   &entry->protseq, &entry->endpoint,
120                                   &entry->address);
121         if (rpc_status != RPC_S_OK)
122         {
123             WINE_WARN("TowerExplode failed %u\n", rpc_status);
124             *status = rpc_status;
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(&registered_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         if (entry)
169             delete_registered_ept_entry(entry);
170         else
171         {
172             *status = EPT_S_NOT_REGISTERED;
173             break;
174         }
175         I_RpcFree(protseq);
176         I_RpcFree(endpoint);
177         I_RpcFree(address);
178     }
179
180     LeaveCriticalSection(&csEpm);
181 }
182
183 void __cdecl ept_lookup(handle_t h,
184                         unsigned32 inquiry_type,
185                         uuid_p_t object,
186                         rpc_if_id_p_t interface_id,
187                         unsigned32 vers_option,
188                         ept_lookup_handle_t *entry_handle,
189                         unsigned32 max_ents,
190                         unsigned32 *num_ents,
191                         ept_entry_t entries[],
192                         error_status_t *status)
193 {
194     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
195
196     *status = EPT_S_CANT_PERFORM_OP;
197 }
198
199 void __cdecl ept_map(handle_t h,
200                      uuid_p_t object,
201                      twr_p_t map_tower,
202                      ept_lookup_handle_t *entry_handle,
203                      unsigned32 max_towers,
204                      unsigned32 *num_towers,
205                      twr_p_t *towers,
206                      error_status_t *status)
207 {
208     RPC_STATUS rpc_status;
209     RPC_SYNTAX_IDENTIFIER iface, syntax;
210     char *protseq;
211     struct registered_ept_entry *entry;
212
213     *status = RPC_S_OK;
214     *num_towers = 0;
215
216     WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower,
217           entry_handle, max_towers, num_towers, towers, status);
218
219     rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq,
220                               NULL, NULL);
221     if (rpc_status != RPC_S_OK)
222     {
223         *status = rpc_status;
224         return;
225     }
226
227     EnterCriticalSection(&csEpm);
228
229     LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
230     {
231         if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) &&
232             (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) &&
233             (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) &&
234             !memcmp(&entry->syntax, &syntax, sizeof(syntax)) &&
235             !strcmp(entry->protseq, protseq) &&
236             ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object)))
237         {
238             if (*num_towers < max_towers)
239             {
240                 rpc_status = TowerConstruct(&entry->iface, &entry->syntax,
241                                             entry->protseq, entry->endpoint,
242                                             entry->address,
243                                             &towers[*num_towers]);
244                 if (rpc_status != RPC_S_OK)
245                 {
246                     *status = rpc_status;
247                     break; /* FIXME: more cleanup? */
248                 }
249             }
250             (*num_towers)++;
251         }
252     }
253
254     LeaveCriticalSection(&csEpm);
255 }
256
257 void __cdecl ept_lookup_handle_free(handle_t h,
258                                     ept_lookup_handle_t *entry_handle,
259                                     error_status_t *status)
260 {
261     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
262
263     *status = EPT_S_CANT_PERFORM_OP;
264 }
265
266 void __cdecl ept_inq_object(handle_t h,
267                             GUID *ept_object,
268                             error_status_t *status)
269 {
270     WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status);
271
272     *status = EPT_S_CANT_PERFORM_OP;
273 }
274
275 void __cdecl ept_mgmt_delete(handle_t h,
276                              boolean32 object_speced,
277                              uuid_p_t object,
278                              twr_p_t tower,
279                              error_status_t *status)
280 {
281     WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status);
282
283     *status = EPT_S_CANT_PERFORM_OP;
284 }