blob: 3f806bee9cc6bc37c5d5b53825405e466cf3e72e [file] [log] [blame]
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +00001/*
2 * Server-side snapshots
3 *
4 * Copyright (C) 1999 Alexandre Julliard
5 *
Alexandre Julliard07d84462000-04-16 19:45:05 +00006 * FIXME: heap snapshots not implemented
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +00007 */
8
9#include <assert.h>
10#include <stdio.h>
11#include <stdlib.h>
12
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000013#include "winnt.h"
14#include "tlhelp32.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000015
16#include "handle.h"
17#include "process.h"
18#include "thread.h"
Alexandre Julliard5bc78081999-06-22 17:26:53 +000019#include "request.h"
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000020
21
22struct snapshot
23{
24 struct object obj; /* object header */
Alexandre Julliard07d84462000-04-16 19:45:05 +000025 struct process *process; /* process of this snapshot (for modules and heaps) */
26 struct process_snapshot *processes; /* processes snapshot */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000027 int process_count; /* count of processes */
28 int process_pos; /* current position in proc snapshot */
Alexandre Julliard07d84462000-04-16 19:45:05 +000029 struct thread_snapshot *threads; /* threads snapshot */
30 int thread_count; /* count of threads */
31 int thread_pos; /* current position in thread snapshot */
32 struct module_snapshot *modules; /* modules snapshot */
33 int module_count; /* count of modules */
34 int module_pos; /* current position in module snapshot */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000035};
36
37static void snapshot_dump( struct object *obj, int verbose );
38static void snapshot_destroy( struct object *obj );
39
40static const struct object_ops snapshot_ops =
41{
Alexandre Julliard1dca5e22000-01-01 00:56:27 +000042 sizeof(struct snapshot), /* size */
43 snapshot_dump, /* dump */
44 no_add_queue, /* add_queue */
45 NULL, /* remove_queue */
46 NULL, /* signaled */
47 NULL, /* satisfied */
48 NULL, /* get_poll_events */
49 NULL, /* poll_event */
50 no_read_fd, /* get_read_fd */
51 no_write_fd, /* get_write_fd */
52 no_flush, /* flush */
53 no_get_file_info, /* get_file_info */
54 snapshot_destroy /* destroy */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000055};
56
57
58/* create a new snapshot */
Alexandre Julliard07d84462000-04-16 19:45:05 +000059static struct snapshot *create_snapshot( void *pid, int flags )
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000060{
Alexandre Julliard07d84462000-04-16 19:45:05 +000061 struct process *process = NULL;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000062 struct snapshot *snapshot;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000063
Alexandre Julliard07d84462000-04-16 19:45:05 +000064 /* need a process for modules and heaps */
65 if (flags & (TH32CS_SNAPMODULE|TH32CS_SNAPHEAPLIST))
Alexandre Julliard5bc78081999-06-22 17:26:53 +000066 {
Alexandre Julliard07d84462000-04-16 19:45:05 +000067 if (!pid) process = (struct process *)grab_object( current->process );
68 else if (!(process = get_process_from_id( pid ))) return NULL;
Alexandre Julliard5bc78081999-06-22 17:26:53 +000069 }
Alexandre Julliard07d84462000-04-16 19:45:05 +000070
71 if (!(snapshot = alloc_object( &snapshot_ops, -1 )))
72 {
73 if (process) release_object( process );
74 return NULL;
75 }
76
77 snapshot->process = process;
78
79 snapshot->process_pos = 0;
80 snapshot->process_count = 0;
81 if (flags & TH32CS_SNAPPROCESS)
82 snapshot->processes = process_snap( &snapshot->process_count );
83
84 snapshot->thread_pos = 0;
85 snapshot->thread_count = 0;
86 if (flags & TH32CS_SNAPTHREAD)
87 snapshot->threads = thread_snap( &snapshot->thread_count );
88
89 snapshot->module_pos = 0;
90 snapshot->module_count = 0;
91 if (flags & TH32CS_SNAPMODULE)
92 snapshot->modules = module_snap( process, &snapshot->module_count );
93
Alexandre Julliard5bc78081999-06-22 17:26:53 +000094 return snapshot;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000095}
96
97/* get the next process in the snapshot */
Alexandre Julliardebe29ef1999-06-26 08:43:26 +000098static int snapshot_next_process( struct snapshot *snapshot, struct next_process_request *req )
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +000099{
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000100 struct process_snapshot *ptr;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000101
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000102 if (!snapshot->process_count)
103 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000104 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000105 return 0;
106 }
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000107 if (req->reset) snapshot->process_pos = 0;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000108 else if (snapshot->process_pos >= snapshot->process_count)
109 {
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000110 set_error( STATUS_NO_MORE_FILES );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000111 return 0;
112 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000113 ptr = &snapshot->processes[snapshot->process_pos++];
114 req->count = ptr->count;
115 req->pid = get_process_id( ptr->process );
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000116 req->threads = ptr->threads;
117 req->priority = ptr->priority;
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000118 return 1;
119}
120
Alexandre Julliard07d84462000-04-16 19:45:05 +0000121/* get the next thread in the snapshot */
122static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_request *req )
123{
124 struct thread_snapshot *ptr;
125
126 if (!snapshot->thread_count)
127 {
128 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
129 return 0;
130 }
131 if (req->reset) snapshot->thread_pos = 0;
132 else if (snapshot->thread_pos >= snapshot->thread_count)
133 {
134 set_error( STATUS_NO_MORE_FILES );
135 return 0;
136 }
137 ptr = &snapshot->threads[snapshot->thread_pos++];
138 req->count = ptr->count;
139 req->pid = get_process_id( ptr->thread->process );
140 req->tid = get_thread_id( ptr->thread );
141 req->base_pri = ptr->priority;
142 req->delta_pri = 0; /* FIXME */
143 return 1;
144}
145
146/* get the next module in the snapshot */
147static int snapshot_next_module( struct snapshot *snapshot, struct next_module_request *req )
148{
149 struct module_snapshot *ptr;
150
151 if (!snapshot->module_count)
152 {
153 set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
154 return 0;
155 }
156 if (req->reset) snapshot->module_pos = 0;
157 else if (snapshot->module_pos >= snapshot->module_count)
158 {
159 set_error( STATUS_NO_MORE_FILES );
160 return 0;
161 }
162 ptr = &snapshot->modules[snapshot->module_pos++];
163 req->pid = get_process_id( snapshot->process );
164 req->base = ptr->base;
165 return 1;
166}
167
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000168static void snapshot_dump( struct object *obj, int verbose )
169{
170 struct snapshot *snapshot = (struct snapshot *)obj;
171 assert( obj->ops == &snapshot_ops );
Alexandre Julliard07d84462000-04-16 19:45:05 +0000172 fprintf( stderr, "Snapshot: %d procs %d threads %d modules\n",
173 snapshot->process_count, snapshot->thread_count, snapshot->module_count );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000174}
175
176static void snapshot_destroy( struct object *obj )
177{
178 int i;
179 struct snapshot *snapshot = (struct snapshot *)obj;
180 assert( obj->ops == &snapshot_ops );
181 if (snapshot->process_count)
182 {
183 for (i = 0; i < snapshot->process_count; i++)
Alexandre Julliard07d84462000-04-16 19:45:05 +0000184 release_object( snapshot->processes[i].process );
185 free( snapshot->processes );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000186 }
Alexandre Julliard07d84462000-04-16 19:45:05 +0000187 if (snapshot->thread_count)
188 {
189 for (i = 0; i < snapshot->thread_count; i++)
190 release_object( snapshot->threads[i].thread );
191 free( snapshot->threads );
192 }
193 if (snapshot->module_count) free( snapshot->modules );
194 if (snapshot->process) release_object( snapshot->process );
Alexandre Julliardfdc92ba1999-02-14 18:03:15 +0000195}
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000196
197/* create a snapshot */
198DECL_HANDLER(create_snapshot)
199{
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000200 struct snapshot *snapshot;
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000201
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000202 req->handle = -1;
Alexandre Julliard07d84462000-04-16 19:45:05 +0000203 if ((snapshot = create_snapshot( req->pid, req->flags )))
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000204 {
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000205 req->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000206 release_object( snapshot );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000207 }
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000208}
209
210/* get the next process from a snapshot */
211DECL_HANDLER(next_process)
212{
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000213 struct snapshot *snapshot;
214
215 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
216 0, &snapshot_ops )))
217 {
218 snapshot_next_process( snapshot, req );
219 release_object( snapshot );
220 }
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000221}
Alexandre Julliard07d84462000-04-16 19:45:05 +0000222
223/* get the next thread from a snapshot */
224DECL_HANDLER(next_thread)
225{
226 struct snapshot *snapshot;
227
228 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
229 0, &snapshot_ops )))
230 {
231 snapshot_next_thread( snapshot, req );
232 release_object( snapshot );
233 }
234}
235
236/* get the next module from a snapshot */
237DECL_HANDLER(next_module)
238{
239 struct snapshot *snapshot;
240
241 if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
242 0, &snapshot_ops )))
243 {
244 snapshot_next_module( snapshot, req );
245 release_object( snapshot );
246 }
247}