From fdc92bae070061cf0b31c87fd1a099dfed28d679 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 14 Feb 1999 18:03:15 +0000 Subject: [PATCH] Added server snapshot support (processes only for now). --- include/server.h | 26 ++ include/server/object.h | 41 +-- include/server/request.h | 6 + misc/toolhelp.c | 644 +++++++++++++++-------------------------------- server/Makefile.in | 1 + server/process.c | 27 +- server/request.c | 24 ++ server/snapshot.c | 110 ++++++++ server/trace.c | 34 +++ 9 files changed, 439 insertions(+), 474 deletions(-) rewrite misc/toolhelp.c (70%) create mode 100644 server/snapshot.c diff --git a/include/server.h b/include/server.h index f63188e2ba3..899d4bf16d4 100644 --- a/include/server.h +++ b/include/server.h @@ -596,6 +596,32 @@ struct create_device_reply }; +/* Create a snapshot */ +struct create_snapshot_request +{ + int inherit; /* inherit flag */ + int flags; /* snapshot flags (TH32CS_*) */ +}; +struct create_snapshot_reply +{ + int handle; /* handle to the snapshot */ +}; + + +/* Get the next process from a snapshot */ +struct next_process_request +{ + int handle; /* handle to the snapshot */ + int reset; /* reset snapshot position? */ +}; +struct next_process_reply +{ + void* pid; /* process id */ + int threads; /* number of threads */ + int priority; /* process priority */ +}; + + /* client-side functions */ #ifndef __WINE_SERVER__ diff --git a/include/server/object.h b/include/server/object.h index 7fd65b874f9..7cca59633ff 100644 --- a/include/server/object.h +++ b/include/server/object.h @@ -20,6 +20,7 @@ struct object; struct object_name; struct thread; +struct process; struct file; struct wait_queue_entry; @@ -119,42 +120,6 @@ extern void set_timeout( int client_fd, struct timeval *when ); extern int send_reply_v( int client_fd, int type, int pass_fd, struct iovec *vec, int veclen ); -/* process functions */ - -struct process; - -extern struct process *create_process(void); -extern struct process *get_process_from_id( void *id ); -extern struct process *get_process_from_handle( int handle, unsigned int access ); -extern void add_process_thread( struct process *process, - struct thread *thread ); -extern void remove_process_thread( struct process *process, - struct thread *thread ); -extern void kill_process( struct process *process, int exit_code ); -extern void get_process_info( struct process *process, - struct get_process_info_reply *reply ); -extern void set_process_info( struct process *process, - struct set_process_info_request *req ); -extern int alloc_console( struct process *process ); -extern int free_console( struct process *process ); -extern struct object *get_console( struct process *process, int output ); - -/* handle functions */ - -/* alloc_handle takes a void *obj for convenience, but you better make sure */ -/* that the thing pointed to starts with a struct object... */ -extern int alloc_handle( struct process *process, void *obj, - unsigned int access, int inherit ); -extern int close_handle( struct process *process, int handle ); -extern int set_handle_info( struct process *process, int handle, - int mask, int flags ); -extern struct object *get_handle_obj( struct process *process, int handle, - unsigned int access, const struct object_ops *ops ); -extern int duplicate_handle( struct process *src, int src_handle, struct process *dst, - int dst_handle, unsigned int access, int inherit, int options ); -extern int open_object( const char *name, const struct object_ops *ops, - unsigned int access, int inherit ); - /* event functions */ extern struct object *create_event( const char *name, int manual_reset, int initial_state ); @@ -232,6 +197,10 @@ extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply ); extern struct object *create_device( int id ); +/* snapshot functions */ +extern struct object *create_snapshot( int flags ); +extern int snapshot_next_process( int handle, int reset, struct next_process_reply *reply ); + extern int debug_level; #endif /* __WINE_SERVER_OBJECT_H */ diff --git a/include/server/request.h b/include/server/request.h index 4f6dc26b6a4..53dcc1b70bd 100644 --- a/include/server/request.h +++ b/include/server/request.h @@ -53,6 +53,8 @@ enum request REQ_CREATE_MAPPING, REQ_GET_MAPPING_INFO, REQ_CREATE_DEVICE, + REQ_CREATE_SNAPSHOT, + REQ_NEXT_PROCESS, REQ_NB_REQUESTS }; @@ -109,6 +111,8 @@ DECL_HANDLER(create_change_notification); DECL_HANDLER(create_mapping); DECL_HANDLER(get_mapping_info); DECL_HANDLER(create_device); +DECL_HANDLER(create_snapshot); +DECL_HANDLER(next_process); static const struct handler { void (*handler)(); @@ -162,6 +166,8 @@ static const struct handler { { (void(*)())req_create_mapping, sizeof(struct create_mapping_request) }, { (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) }, { (void(*)())req_create_device, sizeof(struct create_device_request) }, + { (void(*)())req_create_snapshot, sizeof(struct create_snapshot_request) }, + { (void(*)())req_next_process, sizeof(struct next_process_request) }, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/misc/toolhelp.c b/misc/toolhelp.c dissimilarity index 70% index 10fb40877e5..d09f2a98b75 100644 --- a/misc/toolhelp.c +++ b/misc/toolhelp.c @@ -1,437 +1,207 @@ -/* - * Misc Toolhelp functions - * - * Copyright 1996 Marcus Meissner - */ - -#include -#include -#include -#include -#include -#include "windows.h" -#include "win.h" -#include "winerror.h" -#include "process.h" -#include "tlhelp32.h" -#include "toolhelp.h" -#include "heap.h" -#include "k32obj.h" -#include "debug.h" - -/* - * Support for toolhelp's snapshots. They - * are supposed to be Kernel32 Objects. - * Only the Destroy() method is implemented - */ - -static void SNAPSHOT_Destroy( K32OBJ *obj ); - -const K32OBJ_OPS SNAPSHOT_Ops = -{ - SNAPSHOT_Destroy /* destroy */ -}; - -/* The K32 snapshot object object */ -/* Process snapshot kernel32 object */ -typedef struct _Process32Snapshot -{ - K32OBJ header; - - DWORD numProcs; - DWORD arrayCounter; - /* - * Store a reference to the PDB list. - * Insuure in the alloc and dealloc routines for this structure that - * I increment and decrement the pdb->head.refcount, so that the - * original pdb will stay around for as long as I use it, but it's - * not locked forver into memory. - */ - PDB32 **processArray; -} -SNAPSHOT_OBJECT; - -/* FIXME: to make this working, we have to callback all these registered - * functions from all over the WINE code. Someone with more knowledge than - * me please do that. -Marcus - */ -static struct notify -{ - HTASK16 htask; - FARPROC16 lpfnCallback; - WORD wFlags; -} *notifys = NULL; - -static int nrofnotifys = 0; - -static FARPROC16 HookNotify = NULL; - -BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback, - WORD wFlags ) -{ - int i; - - TRACE(toolhelp, "(%x,%lx,%x) called.\n", - htask, (DWORD)lpfnCallback, wFlags ); - if (!htask) htask = GetCurrentTask(); - for (i=0;itype == K32OBJ_CHANGE); - - if (snapshot->processArray) - { - for (i = 0; snapshot->processArray[i] && i numProcs; i++) - { - K32OBJ_DecCount (&snapshot->processArray[i]->header); - } - HeapFree (GetProcessHeap (), 0, snapshot->processArray); - snapshot->processArray = NULL; - } - - obj->type = K32OBJ_UNKNOWN; - HeapFree (GetProcessHeap (), 0, snapshot); -} - -/*********************************************************************** - * CreateToolHelp32Snapshot (KERNEL32.179) - * see "Undocumented Windows" - */ -HANDLE32 WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD - th32ProcessID) -{ - HANDLE32 ssHandle; - SNAPSHOT_OBJECT *snapshot; - int numProcesses; - int i; - PDB32* pdb; - - TRACE(toolhelp, "%lx & TH32CS_INHERIT (%x) = %lx %s\n", dwFlags, - TH32CS_INHERIT, - dwFlags & TH32CS_INHERIT, - dwFlags & TH32CS_INHERIT ? "TRUE" : "FALSE"); - TRACE(toolhelp, "%lx & TH32CS_SNAPHEAPLIST (%x) = %lx %s\n", dwFlags, - TH32CS_SNAPHEAPLIST, - dwFlags & TH32CS_SNAPHEAPLIST, - dwFlags & TH32CS_SNAPHEAPLIST ? "TRUE" : "FALSE"); - TRACE(toolhelp, "%lx & TH32CS_SNAPMODULE (%x) = %lx %s\n", dwFlags, - TH32CS_SNAPMODULE, - dwFlags & TH32CS_SNAPMODULE, - dwFlags & TH32CS_SNAPMODULE ? "TRUE" : "FALSE"); - TRACE(toolhelp, "%lx & TH32CS_SNAPPROCESS (%x) = %lx %s\n", dwFlags, - TH32CS_SNAPPROCESS, - dwFlags & TH32CS_SNAPPROCESS, - dwFlags & TH32CS_SNAPPROCESS ? "TRUE" : "FALSE"); - TRACE(toolhelp, "%lx & TH32CS_SNAPTHREAD (%x) = %lx %s\n", dwFlags, - TH32CS_SNAPTHREAD, - dwFlags & TH32CS_SNAPTHREAD, - dwFlags & TH32CS_SNAPTHREAD ? "TRUE" : "FALSE"); - - /**** FIXME: Not implmented ***/ - if (dwFlags & TH32CS_INHERIT) - { - FIXME(toolhelp,"(0x%08lx (TH32CS_INHERIT),0x%08lx), stub!\n", - dwFlags,th32ProcessID); - - return INVALID_HANDLE_VALUE32; - } - if (dwFlags & TH32CS_SNAPHEAPLIST) - { - FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPHEAPLIST),0x%08lx), stub!\n", - dwFlags,th32ProcessID); - return INVALID_HANDLE_VALUE32; - } - if (dwFlags & TH32CS_SNAPMODULE) - { - FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n", - dwFlags,th32ProcessID); - return INVALID_HANDLE_VALUE32; - } - - if (dwFlags & TH32CS_SNAPPROCESS) - { - TRACE (toolhelp, "(0x%08lx (TH32CS_SNAPMODULE),0x%08lx)\n", - dwFlags,th32ProcessID); - snapshot = HeapAlloc (GetProcessHeap (), 0, sizeof - (SNAPSHOT_OBJECT)); - if (!snapshot) - { - return INVALID_HANDLE_VALUE32; - } - - snapshot->header.type = K32OBJ_TOOLHELP_SNAPSHOT; - snapshot->header.refcount = 1; - snapshot->arrayCounter = 0; - - /* - * Lock here, to prevent processes from being created or - * destroyed while the snapshot is gathered - */ - - SYSTEM_LOCK (); - numProcesses = PROCESS_PDBList_Getsize (); - - snapshot->processArray = (PDB32**) - HeapAlloc (GetProcessHeap (), 0, sizeof (PDB32*) * numProcesses); - - if (!snapshot->processArray) - { - HeapFree (GetProcessHeap (), 0, snapshot->processArray); - SetLastError (INVALID_HANDLE_VALUE32); - ERR (toolhelp, "Error allocating %d bytes for snapshot\n", - sizeof (PDB32*) * numProcesses); - return INVALID_HANDLE_VALUE32; - } - - snapshot->numProcs = numProcesses; - - pdb = PROCESS_PDBList_Getfirst (); - for (i = 0; pdb && i < numProcesses; i++) - { - TRACE (toolhelp, "Saving ref to pdb %ld\n", PDB_TO_PROCESS_ID(pdb)); - snapshot->processArray[i] = pdb; - K32OBJ_IncCount (&pdb->header); - pdb = PROCESS_PDBList_Getnext (pdb); - } - SYSTEM_UNLOCK (); - - ssHandle = HANDLE_Alloc (PROCESS_Current (), &snapshot->header, - FILE_ALL_ACCESS, TRUE, -1); - if (ssHandle == INVALID_HANDLE_VALUE32) - { - /* HANDLE_Alloc is supposed to deallocate the - * heap memory if it fails. This code doesn't need to. - */ - SetLastError (INVALID_HANDLE_VALUE32); - ERR (toolhelp, "Error allocating handle\n"); - return INVALID_HANDLE_VALUE32; - } - - TRACE (toolhelp, "snapshotted %d processes, expected %d\n", - i, numProcesses); - return ssHandle; - } - - if (dwFlags & TH32CS_SNAPTHREAD) - { - FIXME(toolhelp,"(0x%08lx (TH32CS_SNAPMODULE),0x%08lx), stub!\n", - dwFlags,th32ProcessID); - return INVALID_HANDLE_VALUE32; - } - - return INVALID_HANDLE_VALUE32; -} - -/*********************************************************************** - * Process32First - * Return info about the first process in a toolhelp32 snapshot - */ -BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) -{ - PDB32 *pdb; - SNAPSHOT_OBJECT *snapshot; - int i; - - TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot, - (DWORD) lppe); - - if (lppe->dwSize < sizeof (PROCESSENTRY32)) - { - SetLastError (ERROR_INSUFFICIENT_BUFFER); - ERR (toolhelp, "Result buffer too small\n"); - return FALSE; - } - - SYSTEM_LOCK (); - snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (), - hSnapshot, - K32OBJ_UNKNOWN, - FILE_ALL_ACCESS, - NULL); - if (!snapshot) - { - SYSTEM_UNLOCK (); - SetLastError (ERROR_INVALID_HANDLE); - ERR (toolhelp, "Error retreiving snapshot\n"); - return FALSE; - } - - snapshot->arrayCounter = i = 0; - pdb = snapshot->processArray[i]; - - if (!pdb) - { - SetLastError (ERROR_NO_MORE_FILES); - ERR (toolhelp, "End of snapshot array\n"); - return FALSE; - } - - TRACE (toolhelp, "Returning info on process %d, id %ld\n", - i, PDB_TO_PROCESS_ID (pdb)); - - lppe->cntUsage = 1; - lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb); - lppe->th32DefaultHeapID = (DWORD) pdb->heap; - lppe->cntThreads = pdb->threads; - lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent); - lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */ - lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */ - if (pdb->exe_modref) - { - lppe->th32ModuleID = (DWORD) pdb->exe_modref->module; - strncpy (lppe->szExeFile, pdb->exe_modref->longname, - sizeof (lppe->szExeFile)); - } - else - { - lppe->th32ModuleID = (DWORD) 0; - strcpy (lppe->szExeFile, ""); - } - - SYSTEM_UNLOCK (); - - return TRUE; -} - -/*********************************************************************** - * Process32Next - * Return info about the "next" process in a toolhelp32 snapshot - */ -BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) -{ - PDB32 *pdb; - SNAPSHOT_OBJECT *snapshot; - int i; - - TRACE (toolhelp, "(0x%08lx,0x%08lx)\n", (DWORD) hSnapshot, - (DWORD) lppe); - - if (lppe->dwSize < sizeof (PROCESSENTRY32)) - { - SetLastError (ERROR_INSUFFICIENT_BUFFER); - ERR (toolhelp, "Result buffer too small\n"); - return FALSE; - } - - SYSTEM_LOCK (); - snapshot = (SNAPSHOT_OBJECT*) HANDLE_GetObjPtr (PROCESS_Current (), - hSnapshot, - K32OBJ_UNKNOWN, - FILE_ALL_ACCESS, - NULL); - if (!snapshot) - { - SYSTEM_UNLOCK (); - SetLastError (ERROR_INVALID_HANDLE); - ERR (toolhelp, "Error retreiving snapshot\n"); - return FALSE; - } - - snapshot->arrayCounter ++; - i = snapshot->arrayCounter; - pdb = snapshot->processArray[i]; - - if (!pdb || snapshot->arrayCounter >= snapshot->numProcs) - { - SetLastError (ERROR_NO_MORE_FILES); - ERR (toolhelp, "End of snapshot array\n"); - return FALSE; - } - - TRACE (toolhelp, "Returning info on process %d, id %ld\n", - i, PDB_TO_PROCESS_ID (pdb)); - - lppe->cntUsage = 1; - lppe->th32ProcessID = PDB_TO_PROCESS_ID (pdb); - lppe->th32DefaultHeapID = (DWORD) pdb->heap; - lppe->cntThreads = pdb->threads; - lppe->th32ParentProcessID = PDB_TO_PROCESS_ID (pdb->parent); - lppe->pcPriClassBase = 6; /* FIXME: this is a made-up value */ - lppe->dwFlags = -1; /* FIXME: RESERVED by Microsoft :-) */ - if (pdb->exe_modref) - { - lppe->th32ModuleID = (DWORD) pdb->exe_modref->module; - strncpy (lppe->szExeFile, pdb->exe_modref->longname, - sizeof (lppe->szExeFile)); - } - else - { - lppe->th32ModuleID = (DWORD) 0; - strcpy (lppe->szExeFile, ""); - } - - SYSTEM_UNLOCK (); - - return TRUE; -} +/* + * Misc Toolhelp functions + * + * Copyright 1996 Marcus Meissner + */ + +#include +#include +#include +#include +#include +#include "windows.h" +#include "win.h" +#include "winerror.h" +#include "process.h" +#include "tlhelp32.h" +#include "toolhelp.h" +#include "heap.h" +#include "k32obj.h" +#include "server.h" +#include "debug.h" + + +/* The K32 snapshot object object */ +typedef struct +{ + K32OBJ header; +} SNAPSHOT_OBJECT; + +/* FIXME: to make this working, we have to callback all these registered + * functions from all over the WINE code. Someone with more knowledge than + * me please do that. -Marcus + */ +static struct notify +{ + HTASK16 htask; + FARPROC16 lpfnCallback; + WORD wFlags; +} *notifys = NULL; + +static int nrofnotifys = 0; + +static FARPROC16 HookNotify = NULL; + +BOOL16 WINAPI NotifyRegister( HTASK16 htask, FARPROC16 lpfnCallback, + WORD wFlags ) +{ + int i; + + TRACE(toolhelp, "(%x,%lx,%x) called.\n", + htask, (DWORD)lpfnCallback, wFlags ); + if (!htask) htask = GetCurrentTask(); + for (i=0;iheader.type = K32OBJ_TOOLHELP_SNAPSHOT; + snapshot->header.refcount = 1; + + req.flags = flags & ~TH32CS_INHERIT; + req.inherit = (flags & TH32CS_INHERIT) != 0; + CLIENT_SendRequest( REQ_CREATE_SNAPSHOT, -1, 1, &req, sizeof(req) ); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) + { + HeapFree( SystemHeap, 0, snapshot ); + return INVALID_HANDLE_VALUE32; + } + return HANDLE_Alloc( PROCESS_Current(), &snapshot->header, 0, req.inherit, reply.handle ); +} + + +/*********************************************************************** + * TOOLHELP_Process32Next + * + * Implementation of Process32First/Next + */ +static BOOL32 TOOLHELP_Process32Next( HANDLE32 handle, LPPROCESSENTRY32 lppe, BOOL32 first ) +{ + struct next_process_request req; + struct next_process_reply reply; + + if (lppe->dwSize < sizeof (PROCESSENTRY32)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + ERR (toolhelp, "Result buffer too small\n"); + return FALSE; + } + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle, + K32OBJ_TOOLHELP_SNAPSHOT, 0 )) == -1) + return FALSE; + req.reset = first; + CLIENT_SendRequest( REQ_NEXT_PROCESS, -1, 1, &req, sizeof(req) ); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE; + lppe->cntUsage = 1; + lppe->th32ProcessID = (DWORD)reply.pid; + lppe->th32DefaultHeapID = 0; /* FIXME */ + lppe->th32ModuleID = 0; /* FIXME */ + lppe->cntThreads = reply.threads; + lppe->th32ParentProcessID = 0; /* FIXME */ + lppe->pcPriClassBase = reply.priority; + lppe->dwFlags = -1; /* FIXME */ + lppe->szExeFile[0] = 0; /* FIXME */ + return TRUE; +} + + +/*********************************************************************** + * Process32First (KERNEL32.555) + * + * Return info about the first process in a toolhelp32 snapshot + */ +BOOL32 WINAPI Process32First(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) +{ + return TOOLHELP_Process32Next( hSnapshot, lppe, TRUE ); +} + +/*********************************************************************** + * Process32Next (KERNEL32.556) + * + * Return info about the "next" process in a toolhelp32 snapshot + */ +BOOL32 WINAPI Process32Next(HANDLE32 hSnapshot, LPPROCESSENTRY32 lppe) +{ + return TOOLHELP_Process32Next( hSnapshot, lppe, FALSE ); +} diff --git a/server/Makefile.in b/server/Makefile.in index b8438a78d5c..f062a95cee4 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ pipe.c \ process.c \ request.c \ + snapshot.c \ select.c \ semaphore.c \ socket.c \ diff --git a/server/process.c b/server/process.c index 6cd3e581c09..6e65433ab64 100644 --- a/server/process.c +++ b/server/process.c @@ -17,6 +17,7 @@ #include "winnt.h" #include "server.h" +#include "server/process.h" #include "server/thread.h" /* reserved handle access rights */ @@ -60,6 +61,7 @@ struct process static struct process *first_process; static struct process *initial_process; +static int running_processes; #define MIN_HANDLE_ENTRIES 32 @@ -214,7 +216,7 @@ void add_process_thread( struct process *process, struct thread *thread ) thread->proc_prev = NULL; if (thread->proc_next) thread->proc_next->proc_prev = thread; process->thread_list = thread; - process->running_threads++; + if (!process->running_threads++) running_processes++; grab_object( thread ); } @@ -231,6 +233,7 @@ void remove_process_thread( struct process *process, struct thread *thread ) if (!--process->running_threads) { /* we have removed the last running thread, exit the process */ + running_processes--; process_killed( process, thread->exit_code ); } release_object( thread ); @@ -573,3 +576,25 @@ struct object *get_console( struct process *process, int output ) return NULL; return grab_object( obj ); } + +/* take a snapshot of currently running processes */ +struct process_snapshot *process_snap( int *count ) +{ + struct process_snapshot *snapshot, *ptr; + struct process *process; + if (!running_processes) return NULL; + if (!(snapshot = mem_alloc( sizeof(*snapshot) * running_processes ))) + return NULL; + ptr = snapshot; + for (process = first_process; process; process = process->next) + { + if (!process->running_threads) continue; + ptr->process = process; + ptr->threads = process->running_threads; + ptr->priority = process->priority; + grab_object( process ); + ptr++; + } + *count = running_processes; + return snapshot; +} diff --git a/server/request.c b/server/request.c index b4b071a14c8..c5fefd9176c 100644 --- a/server/request.c +++ b/server/request.c @@ -19,6 +19,7 @@ #define WANT_REQUEST_HANDLERS #include "server.h" #include "server/request.h" +#include "server/process.h" #include "server/thread.h" /* check that the string is NULL-terminated and that the len is correct */ @@ -754,3 +755,26 @@ DECL_HANDLER(create_device) } send_reply( current, -1, 1, &reply, sizeof(reply) ); } + +/* create a snapshot */ +DECL_HANDLER(create_snapshot) +{ + struct object *obj; + struct create_snapshot_reply reply = { -1 }; + + if ((obj = create_snapshot( req->flags ))) + { + reply.handle = alloc_handle( current->process, obj, 0, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* get the next process from a snapshot */ +DECL_HANDLER(next_process) +{ + struct next_process_reply reply; + snapshot_next_process( req->handle, req->reset, &reply ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + diff --git a/server/snapshot.c b/server/snapshot.c new file mode 100644 index 00000000000..ee189937658 --- /dev/null +++ b/server/snapshot.c @@ -0,0 +1,110 @@ +/* + * Server-side snapshots + * + * Copyright (C) 1999 Alexandre Julliard + * + * FIXME: only process snapshots implemented for now + */ + +#include +#include +#include + +#include "winerror.h" +#include "winnt.h" +#include "tlhelp32.h" +#include "server/process.h" +#include "server/thread.h" + + +struct snapshot +{ + struct object obj; /* object header */ + struct process_snapshot *process; /* processes snapshot */ + int process_count; /* count of processes */ + int process_pos; /* current position in proc snapshot */ +}; + +static void snapshot_dump( struct object *obj, int verbose ); +static void snapshot_destroy( struct object *obj ); + +static const struct object_ops snapshot_ops = +{ + snapshot_dump, + no_add_queue, + NULL, /* should never get called */ + NULL, /* should never get called */ + NULL, /* should never get called */ + no_read_fd, + no_write_fd, + no_flush, + no_get_file_info, + snapshot_destroy +}; + + +/* create a new snapshot */ +struct object *create_snapshot( int flags ) +{ + struct snapshot *snapshot; + if (!(snapshot = mem_alloc( sizeof(*snapshot) ))) return NULL; + init_object( &snapshot->obj, &snapshot_ops, NULL ); + if (flags & TH32CS_SNAPPROCESS) + snapshot->process = process_snap( &snapshot->process_count ); + else + snapshot->process_count = 0; + + snapshot->process_pos = 0; + return &snapshot->obj; +} + +/* get the next process in the snapshot */ +int snapshot_next_process( int handle, int reset, struct next_process_reply *reply ) +{ + struct snapshot *snapshot; + struct process_snapshot *ptr; + if (!(snapshot = (struct snapshot *)get_handle_obj( current->process, handle, + 0, &snapshot_ops ))) + return 0; + if (!snapshot->process_count) + { + SET_ERROR( ERROR_INVALID_PARAMETER ); /* FIXME */ + release_object( snapshot ); + return 0; + } + if (reset) snapshot->process_pos = 0; + else if (snapshot->process_pos >= snapshot->process_count) + { + SET_ERROR( ERROR_NO_MORE_FILES ); + release_object( snapshot ); + return 0; + } + ptr = &snapshot->process[snapshot->process_pos++]; + reply->pid = ptr->process; + reply->threads = ptr->threads; + reply->priority = ptr->priority; + release_object( snapshot ); + return 1; +} + +static void snapshot_dump( struct object *obj, int verbose ) +{ + struct snapshot *snapshot = (struct snapshot *)obj; + assert( obj->ops == &snapshot_ops ); + fprintf( stderr, "Snapshot: %d processes\n", + snapshot->process_count ); +} + +static void snapshot_destroy( struct object *obj ) +{ + int i; + struct snapshot *snapshot = (struct snapshot *)obj; + assert( obj->ops == &snapshot_ops ); + if (snapshot->process_count) + { + for (i = 0; i < snapshot->process_count; i++) + release_object( snapshot->process[i].process ); + free( snapshot->process ); + } + free( snapshot ); +} diff --git a/server/trace.c b/server/trace.c index bf4a006ab5b..16ef4ff1983 100644 --- a/server/trace.c +++ b/server/trace.c @@ -541,6 +541,34 @@ static int dump_create_device_reply( struct create_device_reply *req, int len ) return (int)sizeof(*req); } +static int dump_create_snapshot_request( struct create_snapshot_request *req, int len ) +{ + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " flags=%d", req->flags ); + return (int)sizeof(*req); +} + +static int dump_create_snapshot_reply( struct create_snapshot_reply *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + +static int dump_next_process_request( struct next_process_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " reset=%d", req->reset ); + return (int)sizeof(*req); +} + +static int dump_next_process_reply( struct next_process_reply *req, int len ) +{ + fprintf( stderr, " pid=%p,", req->pid ); + fprintf( stderr, " threads=%d,", req->threads ); + fprintf( stderr, " priority=%d", req->priority ); + return (int)sizeof(*req); +} + struct dumper { int (*dump_req)( void *data, int len ); @@ -645,6 +673,10 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())dump_get_mapping_info_reply }, { (int(*)(void *,int))dump_create_device_request, (void(*)())dump_create_device_reply }, + { (int(*)(void *,int))dump_create_snapshot_request, + (void(*)())dump_create_snapshot_reply }, + { (int(*)(void *,int))dump_next_process_request, + (void(*)())dump_next_process_reply }, }; static const char * const req_names[REQ_NB_REQUESTS] = @@ -697,6 +729,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = "create_mapping", "get_mapping_info", "create_device", + "create_snapshot", + "next_process", }; void trace_request( enum request req, void *data, int len, int fd ) -- 2.11.4.GIT