blob: 14ec97bd0479c27c10852819314dd7e69890d4f3 [file] [log] [blame]
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +00001/*
2 * Server-side snapshots
3 *
4 * Copyright (C) 1999 Alexandre Julliard
5 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00006 * 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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000019 *
Alexandre Julliard07d84462000-04-16 19:45:05 +000020 * FIXME: heap snapshots not implemented
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000021 */
22
Alexandre Julliard5769d1d2002-04-26 19:05:15 +000023#include "config.h"
24#include "wine/port.h"
25
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000026#include <assert.h>
27#include <stdio.h>
28#include <stdlib.h>
Vitaliy Margolen4fabe112006-01-03 12:06:03 +010029#include <stdarg.h>
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000030
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010031#include "ntstatus.h"
32#define WIN32_NO_STATUS
François Gougetecae9262000-12-15 21:30:35 +000033#include "windef.h"
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010034#include "winternl.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000035
36#include "handle.h"
37#include "process.h"
38#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000039#include "request.h"
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000040
41
42struct snapshot
43{
44 struct object obj; /* object header */
Alexandre Julliard07d84462000-04-16 19:45:05 +000045 struct process *process; /* process of this snapshot (for modules and heaps) */
46 struct process_snapshot *processes; /* processes snapshot */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000047 int process_count; /* count of processes */
48 int process_pos; /* current position in proc snapshot */
Alexandre Julliard07d84462000-04-16 19:45:05 +000049 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 */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000055};
56
57static void snapshot_dump( struct object *obj, int verbose );
58static void snapshot_destroy( struct object *obj );
59
60static const struct object_ops snapshot_ops =
61{
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000062 sizeof(struct snapshot), /* size */
63 snapshot_dump, /* dump */
64 no_add_queue, /* add_queue */
65 NULL, /* remove_queue */
66 NULL, /* signaled */
67 NULL, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +000068 no_signal, /* signal */
Alexandre Julliard1ab243b2000-12-19 02:12:45 +000069 no_get_fd, /* get_fd */
Alexandre Julliard28beba32005-12-12 14:57:40 +010070 no_map_access, /* map_access */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +000071 no_lookup_name, /* lookup_name */
Alexandre Julliard7e71c1d2007-03-22 11:44:29 +010072 no_open_file, /* open_file */
Alexandre Julliardb9b1ea92005-06-09 15:39:52 +000073 no_close_handle, /* close_handle */
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000074 snapshot_destroy /* destroy */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000075};
76
77
78/* create a new snapshot */
Alexandre Julliard54f22872002-10-03 19:54:57 +000079static struct snapshot *create_snapshot( process_id_t pid, int flags )
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000080{
Alexandre Julliard07d84462000-04-16 19:45:05 +000081 struct process *process = NULL;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000082 struct snapshot *snapshot;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000083
Alexandre Julliard07d84462000-04-16 19:45:05 +000084 /* need a process for modules and heaps */
Eric Pouech2359b572003-01-09 00:01:28 +000085 if (flags & (SNAP_MODULE|SNAP_HEAPLIST))
Alexandre Julliard5bc78081999-06-22 17:26:53 +000086 {
Alexandre Julliard07d84462000-04-16 19:45:05 +000087 if (!pid) process = (struct process *)grab_object( current->process );
88 else if (!(process = get_process_from_id( pid ))) return NULL;
Alexandre Julliard5bc78081999-06-22 17:26:53 +000089 }
Alexandre Julliard07d84462000-04-16 19:45:05 +000090
Alexandre Julliarde66207e2003-02-19 00:33:32 +000091 if (!(snapshot = alloc_object( &snapshot_ops )))
Alexandre Julliard07d84462000-04-16 19:45:05 +000092 {
93 if (process) release_object( process );
94 return NULL;
95 }
96
97 snapshot->process = process;
98
99 snapshot->process_pos = 0;
100 snapshot->process_count = 0;
Eric Pouech2359b572003-01-09 00:01:28 +0000101 if (flags & SNAP_PROCESS)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000102 snapshot->processes = process_snap( &snapshot->process_count );
103
104 snapshot->thread_pos = 0;
105 snapshot->thread_count = 0;
Eric Pouech2359b572003-01-09 00:01:28 +0000106 if (flags & SNAP_THREAD)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000107 snapshot->threads = thread_snap( &snapshot->thread_count );
108
109 snapshot->module_pos = 0;
110 snapshot->module_count = 0;
Eric Pouech2359b572003-01-09 00:01:28 +0000111 if (flags & SNAP_MODULE)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000112 snapshot->modules = module_snap( process, &snapshot->module_count );
113
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000114 return snapshot;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000115}
116
117/* get the next process in the snapshot */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000118static int snapshot_next_process( struct snapshot *snapshot, struct next_process_reply *reply )
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000119{
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000120 struct process_snapshot *ptr;
Alexandre Julliarde6374cb2006-02-16 12:13:01 +0100121 struct process_dll *exe_module;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000122
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000123 if (!snapshot->process_count)
124 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000125 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000126 return 0;
127 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000128 if (snapshot->process_pos >= snapshot->process_count)
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000129 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000130 set_error( STATUS_NO_MORE_FILES );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000131 return 0;
132 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000133 ptr = &snapshot->processes[snapshot->process_pos++];
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000134 reply->count = ptr->count;
135 reply->pid = get_process_id( ptr->process );
Eric Pouech4ecc32a2003-02-14 23:31:10 +0000136 reply->ppid = ptr->process->parent ? get_process_id( ptr->process->parent ) : 0;
Robert Shearmanc5165712005-05-25 18:41:09 +0000137 reply->heap = NULL; /* FIXME */
138 reply->module = NULL; /* FIXME */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000139 reply->threads = ptr->threads;
140 reply->priority = ptr->priority;
Eric Pouech9fd54b22003-09-16 01:07:21 +0000141 reply->handles = ptr->handles;
Alexandre Julliarde6374cb2006-02-16 12:13:01 +0100142 if ((exe_module = get_process_exe_module( ptr->process )) && exe_module->filename)
Alexandre Julliardaeb56602002-03-22 00:21:23 +0000143 {
Alexandre Julliard0f273c12006-07-26 10:43:25 +0200144 data_size_t len = min( exe_module->namelen, get_reply_max_size() );
Alexandre Julliarde6374cb2006-02-16 12:13:01 +0100145 set_reply_data( exe_module->filename, len );
Alexandre Julliardaeb56602002-03-22 00:21:23 +0000146 }
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000147 return 1;
148}
149
Alexandre Julliard07d84462000-04-16 19:45:05 +0000150/* get the next thread in the snapshot */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000151static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_reply *reply )
Alexandre Julliard07d84462000-04-16 19:45:05 +0000152{
153 struct thread_snapshot *ptr;
154
155 if (!snapshot->thread_count)
156 {
157 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
158 return 0;
159 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000160 if (snapshot->thread_pos >= snapshot->thread_count)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000161 {
162 set_error( STATUS_NO_MORE_FILES );
163 return 0;
164 }
165 ptr = &snapshot->threads[snapshot->thread_pos++];
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000166 reply->count = ptr->count;
167 reply->pid = get_process_id( ptr->thread->process );
168 reply->tid = get_thread_id( ptr->thread );
169 reply->base_pri = ptr->priority;
170 reply->delta_pri = 0; /* FIXME */
Alexandre Julliard07d84462000-04-16 19:45:05 +0000171 return 1;
172}
173
174/* get the next module in the snapshot */
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000175static int snapshot_next_module( struct snapshot *snapshot, struct next_module_reply *reply )
Alexandre Julliard07d84462000-04-16 19:45:05 +0000176{
177 struct module_snapshot *ptr;
178
179 if (!snapshot->module_count)
180 {
181 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
182 return 0;
183 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000184 if (snapshot->module_pos >= snapshot->module_count)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000185 {
186 set_error( STATUS_NO_MORE_FILES );
187 return 0;
188 }
189 ptr = &snapshot->modules[snapshot->module_pos++];
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000190 reply->pid = get_process_id( snapshot->process );
191 reply->base = ptr->base;
Alexandre Julliardaeb56602002-03-22 00:21:23 +0000192 reply->size = ptr->size;
193 if (ptr->filename)
194 {
Alexandre Julliard0f273c12006-07-26 10:43:25 +0200195 data_size_t len = min( ptr->namelen, get_reply_max_size() );
Alexandre Julliardaeb56602002-03-22 00:21:23 +0000196 set_reply_data( ptr->filename, len );
197 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000198 return 1;
199}
200
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000201static void snapshot_dump( struct object *obj, int verbose )
202{
203 struct snapshot *snapshot = (struct snapshot *)obj;
204 assert( obj->ops == &snapshot_ops );
Alexandre Julliard07d84462000-04-16 19:45:05 +0000205 fprintf( stderr, "Snapshot: %d procs %d threads %d modules\n",
206 snapshot->process_count, snapshot->thread_count, snapshot->module_count );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000207}
208
209static void snapshot_destroy( struct object *obj )
210{
211 int i;
212 struct snapshot *snapshot = (struct snapshot *)obj;
213 assert( obj->ops == &snapshot_ops );
214 if (snapshot->process_count)
215 {
216 for (i = 0; i < snapshot->process_count; i++)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000217 release_object( snapshot->processes[i].process );
218 free( snapshot->processes );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000219 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000220 if (snapshot->thread_count)
221 {
222 for (i = 0; i < snapshot->thread_count; i++)
223 release_object( snapshot->threads[i].thread );
224 free( snapshot->threads );
225 }
Alexandre Julliardaeb56602002-03-22 00:21:23 +0000226 if (snapshot->module_count)
227 {
228 for (i = 0; i < snapshot->module_count; i++)
229 free( snapshot->modules[i].filename );
230 free( snapshot->modules );
231 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000232 if (snapshot->process) release_object( snapshot->process );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000233}
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000234
235/* create a snapshot */
236DECL_HANDLER(create_snapshot)
237{
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000238 struct snapshot *snapshot;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000239
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000240 reply->handle = 0;
Alexandre Julliard07d84462000-04-16 19:45:05 +0000241 if ((snapshot = create_snapshot( req->pid, req->flags )))
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000242 {
Alexandre Julliard24560e72005-12-09 13:58:25 +0100243 reply->handle = alloc_handle( current->process, snapshot, 0, req->attributes );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000244 release_object( snapshot );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000245 }
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000246}
247
248/* get the next process from a snapshot */
249DECL_HANDLER(next_process)
250{
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000251 struct snapshot *snapshot;
252
253 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
254 0, &snapshot_ops )))
255 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000256 if (req->reset) snapshot->process_pos = 0;
257 snapshot_next_process( snapshot, reply );
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000258 release_object( snapshot );
259 }
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000260}
Alexandre Julliard07d84462000-04-16 19:45:05 +0000261
262/* get the next thread from a snapshot */
263DECL_HANDLER(next_thread)
264{
265 struct snapshot *snapshot;
266
267 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
268 0, &snapshot_ops )))
269 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000270 if (req->reset) snapshot->thread_pos = 0;
271 snapshot_next_thread( snapshot, reply );
Alexandre Julliard07d84462000-04-16 19:45:05 +0000272 release_object( snapshot );
273 }
274}
275
276/* get the next module from a snapshot */
277DECL_HANDLER(next_module)
278{
279 struct snapshot *snapshot;
280
281 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
282 0, &snapshot_ops )))
283 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000284 if (req->reset) snapshot->module_pos = 0;
285 snapshot_next_module( snapshot, reply );
Alexandre Julliard07d84462000-04-16 19:45:05 +0000286 release_object( snapshot );
287 }
288}