Commit | Line | Data |
---|---|---|
fdc92bae AJ |
1 | /* |
2 | * Server-side snapshots | |
3 | * | |
4 | * Copyright (C) 1999 Alexandre Julliard | |
5 | * | |
0799c1a7 AJ |
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 | |
360a3f91 | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
0799c1a7 | 19 | * |
07d84469 | 20 | * FIXME: heap snapshots not implemented |
fdc92bae AJ |
21 | */ |
22 | ||
5769d1de AJ |
23 | #include "config.h" |
24 | #include "wine/port.h" | |
25 | ||
fdc92bae AJ |
26 | #include <assert.h> |
27 | #include <stdio.h> | |
28 | #include <stdlib.h> | |
4fabe112 | 29 | #include <stdarg.h> |
fdc92bae | 30 | |
1a1583a3 GG |
31 | #include "ntstatus.h" |
32 | #define WIN32_NO_STATUS | |
ecae9269 | 33 | #include "windef.h" |
1a1583a3 | 34 | #include "winternl.h" |
43c190e7 AJ |
35 | |
36 | #include "handle.h" | |
37 | #include "process.h" | |
38 | #include "thread.h" | |
5bc78089 | 39 | #include "request.h" |
fdc92bae AJ |
40 | |
41 | ||
42 | struct snapshot | |
43 | { | |
44 | struct object obj; /* object header */ | |
07d84469 AJ |
45 | struct process *process; /* process of this snapshot (for modules and heaps) */ |
46 | struct process_snapshot *processes; /* processes snapshot */ | |
fdc92bae AJ |
47 | int process_count; /* count of processes */ |
48 | int process_pos; /* current position in proc snapshot */ | |
07d84469 AJ |
49 | struct thread_snapshot *threads; /* threads snapshot */ |
50 | int thread_count; /* count of threads */ | |
51 | int thread_pos; /* current position in thread snapshot */ | |
52 | struct module_snapshot *modules; /* modules snapshot */ | |
53 | int module_count; /* count of modules */ | |
54 | int module_pos; /* current position in module snapshot */ | |
fdc92bae AJ |
55 | }; |
56 | ||
57 | static void snapshot_dump( struct object *obj, int verbose ); | |
58 | static void snapshot_destroy( struct object *obj ); | |
59 | ||
60 | static const struct object_ops snapshot_ops = | |
61 | { | |
1dca5e24 AJ |
62 | sizeof(struct snapshot), /* size */ |
63 | snapshot_dump, /* dump */ | |
8382eb01 | 64 | no_get_type, /* get_type */ |
1dca5e24 AJ |
65 | no_add_queue, /* add_queue */ |
66 | NULL, /* remove_queue */ | |
67 | NULL, /* signaled */ | |
68 | NULL, /* satisfied */ | |
f92fff66 | 69 | no_signal, /* signal */ |
1ab243ba | 70 | no_get_fd, /* get_fd */ |
28beba31 | 71 | no_map_access, /* map_access */ |
c1707d89 RS |
72 | default_get_sd, /* get_sd */ |
73 | default_set_sd, /* set_sd */ | |
baffcb95 | 74 | no_lookup_name, /* lookup_name */ |
7e71c1dd | 75 | no_open_file, /* open_file */ |
b9b1ea9c | 76 | no_close_handle, /* close_handle */ |
1dca5e24 | 77 | snapshot_destroy /* destroy */ |
fdc92bae AJ |
78 | }; |
79 | ||
80 | ||
81 | /* create a new snapshot */ | |
54f22873 | 82 | static struct snapshot *create_snapshot( process_id_t pid, int flags ) |
fdc92bae | 83 | { |
07d84469 | 84 | struct process *process = NULL; |
fdc92bae | 85 | struct snapshot *snapshot; |
5bc78089 | 86 | |
07d84469 | 87 | /* need a process for modules and heaps */ |
2359b575 | 88 | if (flags & (SNAP_MODULE|SNAP_HEAPLIST)) |
5bc78089 | 89 | { |
07d84469 AJ |
90 | if (!pid) process = (struct process *)grab_object( current->process ); |
91 | else if (!(process = get_process_from_id( pid ))) return NULL; | |
5bc78089 | 92 | } |
07d84469 | 93 | |
e66207eb | 94 | if (!(snapshot = alloc_object( &snapshot_ops ))) |
07d84469 AJ |
95 | { |
96 | if (process) release_object( process ); | |
97 | return NULL; | |
98 | } | |
99 | ||
100 | snapshot->process = process; | |
101 | ||
102 | snapshot->process_pos = 0; | |
103 | snapshot->process_count = 0; | |
2359b575 | 104 | if (flags & SNAP_PROCESS) |
07d84469 AJ |
105 | snapshot->processes = process_snap( &snapshot->process_count ); |
106 | ||
107 | snapshot->thread_pos = 0; | |
108 | snapshot->thread_count = 0; | |
2359b575 | 109 | if (flags & SNAP_THREAD) |
07d84469 AJ |
110 | snapshot->threads = thread_snap( &snapshot->thread_count ); |
111 | ||
112 | snapshot->module_pos = 0; | |
113 | snapshot->module_count = 0; | |
2359b575 | 114 | if (flags & SNAP_MODULE) |
07d84469 AJ |
115 | snapshot->modules = module_snap( process, &snapshot->module_count ); |
116 | ||
5bc78089 | 117 | return snapshot; |
fdc92bae AJ |
118 | } |
119 | ||
120 | /* get the next process in the snapshot */ | |
9caa71ee | 121 | static int snapshot_next_process( struct snapshot *snapshot, struct next_process_reply *reply ) |
fdc92bae | 122 | { |
fdc92bae | 123 | struct process_snapshot *ptr; |
e6374cbe | 124 | struct process_dll *exe_module; |
ebe29ef3 | 125 | |
fdc92bae AJ |
126 | if (!snapshot->process_count) |
127 | { | |
cb1fc735 | 128 | set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ |
fdc92bae AJ |
129 | return 0; |
130 | } | |
9caa71ee | 131 | if (snapshot->process_pos >= snapshot->process_count) |
fdc92bae | 132 | { |
cb1fc735 | 133 | set_error( STATUS_NO_MORE_FILES ); |
fdc92bae AJ |
134 | return 0; |
135 | } | |
07d84469 | 136 | ptr = &snapshot->processes[snapshot->process_pos++]; |
9caa71ee AJ |
137 | reply->count = ptr->count; |
138 | reply->pid = get_process_id( ptr->process ); | |
4ecc32a4 | 139 | reply->ppid = ptr->process->parent ? get_process_id( ptr->process->parent ) : 0; |
c5165714 RS |
140 | reply->heap = NULL; /* FIXME */ |
141 | reply->module = NULL; /* FIXME */ | |
9caa71ee AJ |
142 | reply->threads = ptr->threads; |
143 | reply->priority = ptr->priority; | |
9fd54b28 | 144 | reply->handles = ptr->handles; |
e6374cbe | 145 | if ((exe_module = get_process_exe_module( ptr->process )) && exe_module->filename) |
aeb56605 | 146 | { |
0f273c17 | 147 | data_size_t len = min( exe_module->namelen, get_reply_max_size() ); |
e6374cbe | 148 | set_reply_data( exe_module->filename, len ); |
aeb56605 | 149 | } |
fdc92bae AJ |
150 | return 1; |
151 | } | |
152 | ||
07d84469 | 153 | /* get the next thread in the snapshot */ |
9caa71ee | 154 | static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_reply *reply ) |
07d84469 AJ |
155 | { |
156 | struct thread_snapshot *ptr; | |
157 | ||
158 | if (!snapshot->thread_count) | |
159 | { | |
160 | set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ | |
161 | return 0; | |
162 | } | |
9caa71ee | 163 | if (snapshot->thread_pos >= snapshot->thread_count) |
07d84469 AJ |
164 | { |
165 | set_error( STATUS_NO_MORE_FILES ); | |
166 | return 0; | |
167 | } | |
168 | ptr = &snapshot->threads[snapshot->thread_pos++]; | |
9caa71ee AJ |
169 | reply->count = ptr->count; |
170 | reply->pid = get_process_id( ptr->thread->process ); | |
171 | reply->tid = get_thread_id( ptr->thread ); | |
172 | reply->base_pri = ptr->priority; | |
173 | reply->delta_pri = 0; /* FIXME */ | |
07d84469 AJ |
174 | return 1; |
175 | } | |
176 | ||
177 | /* get the next module in the snapshot */ | |
9caa71ee | 178 | static int snapshot_next_module( struct snapshot *snapshot, struct next_module_reply *reply ) |
07d84469 AJ |
179 | { |
180 | struct module_snapshot *ptr; | |
181 | ||
182 | if (!snapshot->module_count) | |
183 | { | |
184 | set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ | |
185 | return 0; | |
186 | } | |
9caa71ee | 187 | if (snapshot->module_pos >= snapshot->module_count) |
07d84469 AJ |
188 | { |
189 | set_error( STATUS_NO_MORE_FILES ); | |
190 | return 0; | |
191 | } | |
192 | ptr = &snapshot->modules[snapshot->module_pos++]; | |
9caa71ee AJ |
193 | reply->pid = get_process_id( snapshot->process ); |
194 | reply->base = ptr->base; | |
aeb56605 AJ |
195 | reply->size = ptr->size; |
196 | if (ptr->filename) | |
197 | { | |
0f273c17 | 198 | data_size_t len = min( ptr->namelen, get_reply_max_size() ); |
aeb56605 AJ |
199 | set_reply_data( ptr->filename, len ); |
200 | } | |
07d84469 AJ |
201 | return 1; |
202 | } | |
203 | ||
fdc92bae AJ |
204 | static void snapshot_dump( struct object *obj, int verbose ) |
205 | { | |
206 | struct snapshot *snapshot = (struct snapshot *)obj; | |
207 | assert( obj->ops == &snapshot_ops ); | |
07d84469 AJ |
208 | fprintf( stderr, "Snapshot: %d procs %d threads %d modules\n", |
209 | snapshot->process_count, snapshot->thread_count, snapshot->module_count ); | |
fdc92bae AJ |
210 | } |
211 | ||
212 | static void snapshot_destroy( struct object *obj ) | |
213 | { | |
214 | int i; | |
215 | struct snapshot *snapshot = (struct snapshot *)obj; | |
216 | assert( obj->ops == &snapshot_ops ); | |
217 | if (snapshot->process_count) | |
218 | { | |
219 | for (i = 0; i < snapshot->process_count; i++) | |
07d84469 AJ |
220 | release_object( snapshot->processes[i].process ); |
221 | free( snapshot->processes ); | |
222 | } | |
223 | if (snapshot->thread_count) | |
224 | { | |
225 | for (i = 0; i < snapshot->thread_count; i++) | |
226 | release_object( snapshot->threads[i].thread ); | |
227 | free( snapshot->threads ); | |
fdc92bae | 228 | } |
aeb56605 AJ |
229 | if (snapshot->module_count) |
230 | { | |
231 | for (i = 0; i < snapshot->module_count; i++) | |
232 | free( snapshot->modules[i].filename ); | |
233 | free( snapshot->modules ); | |
234 | } | |
07d84469 | 235 | if (snapshot->process) release_object( snapshot->process ); |
fdc92bae | 236 | } |
43c190e7 AJ |
237 | |
238 | /* create a snapshot */ | |
239 | DECL_HANDLER(create_snapshot) | |
240 | { | |
5bc78089 | 241 | struct snapshot *snapshot; |
43c190e7 | 242 | |
9caa71ee | 243 | reply->handle = 0; |
07d84469 | 244 | if ((snapshot = create_snapshot( req->pid, req->flags ))) |
43c190e7 | 245 | { |
24560e70 | 246 | reply->handle = alloc_handle( current->process, snapshot, 0, req->attributes ); |
5bc78089 | 247 | release_object( snapshot ); |
43c190e7 | 248 | } |
43c190e7 AJ |
249 | } |
250 | ||
251 | /* get the next process from a snapshot */ | |
252 | DECL_HANDLER(next_process) | |
253 | { | |
ebe29ef3 AJ |
254 | struct snapshot *snapshot; |
255 | ||
256 | if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle, | |
257 | 0, &snapshot_ops ))) | |
258 | { | |
9caa71ee AJ |
259 | if (req->reset) snapshot->process_pos = 0; |
260 | snapshot_next_process( snapshot, reply ); | |
ebe29ef3 AJ |
261 | release_object( snapshot ); |
262 | } | |
43c190e7 | 263 | } |
07d84469 AJ |
264 | |
265 | /* get the next thread from a snapshot */ | |
266 | DECL_HANDLER(next_thread) | |
267 | { | |
268 | struct snapshot *snapshot; | |
269 | ||
270 | if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle, | |
271 | 0, &snapshot_ops ))) | |
272 | { | |
9caa71ee AJ |
273 | if (req->reset) snapshot->thread_pos = 0; |
274 | snapshot_next_thread( snapshot, reply ); | |
07d84469 AJ |
275 | release_object( snapshot ); |
276 | } | |
277 | } | |
278 | ||
279 | /* get the next module from a snapshot */ | |
280 | DECL_HANDLER(next_module) | |
281 | { | |
282 | struct snapshot *snapshot; | |
283 | ||
284 | if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle, | |
285 | 0, &snapshot_ops ))) | |
286 | { | |
9caa71ee AJ |
287 | if (req->reset) snapshot->module_pos = 0; |
288 | snapshot_next_module( snapshot, reply ); | |
07d84469 AJ |
289 | release_object( snapshot ); |
290 | } | |
291 | } |