PATCH: smaller Win32 process IDs

Alex Pasadyn ajp at mail.utexas.edu
Thu Jan 23 12:36:16 CST 2003


There are some applications that blindly read the high bytes from 
fs:[0x20] without even checking the Windows version.  Under Win9x they 
are looking for debugger flags, while on NT that field should contain 
the high bytes of the PID.  It appears that NT pids should be 16 bits or 
less, and this patch ensures that they are.

I've been using this for quite a while, and I haven't seen problems, but 
I am concerned about changing something as fundamental as process IDs. 
Does anyone have a good stress test for process creation and destruction?


Alex Pasadyn
ajp at mail.utexas.edu

ChangeLog:
- Ensure all Win32 pids generated fit in 16 bits


-------------- next part --------------
Index: server/process.c
===================================================================
RCS file: /home/wine/wine/server/process.c,v
retrieving revision 1.92
diff -u -r1.92 process.c
--- server/process.c	9 Jan 2003 00:01:28 -0000	1.92
+++ server/process.c	23 Jan 2003 18:12:52 -0000
@@ -46,6 +46,7 @@
 /* process structure */
 
 static struct process *first_process;
+static process_id_t last_pid;
 static int running_processes;
 
 /* process operations */
@@ -113,6 +114,57 @@
 };
 
 
+/* generate a new (unique) process ID */
+static process_id_t make_new_process_id ( void )
+{
+    struct process *p;
+    process_id_t new_id;
+    process_id_t safe_id;
+    process_id_t temp_id;
+    process_id_t min_used;
+    process_id_t max_used;
+    const process_id_t max_id = 32768;
+
+    if (running_processes >= max_id)
+    {
+        /* no more room -- return 0 */
+        return 0;
+    }
+    safe_id = 0;
+    new_id = (last_pid%max_id)+1;
+    p = first_process;
+    min_used = 0;
+    max_used = max_id;
+    /* assume processes are stored in ascending order */
+    while (p) 
+    {
+        temp_id = get_process_id(p);
+        if (!min_used) min_used = temp_id;
+        max_used = temp_id;
+        if (temp_id == new_id) new_id = 0;
+        if ( p->next && (get_process_id(p->next) != temp_id+1) ) safe_id = temp_id+1;
+        p = p->next;
+    }
+    if (!new_id)
+    {
+        if (max_used < max_id)
+        {
+            new_id = max_used+1;
+        }
+        else if (min_used > 1)
+        {
+            new_id = 1;
+        }
+        else
+        {
+            new_id = safe_id;
+        }
+
+    }
+    last_pid = new_id;
+    return new_id;
+}
+
 /* set the state of the process startup info */
 static void set_process_startup_state( struct process *process, enum startup_state state )
 {
@@ -188,6 +240,7 @@
 struct thread *create_process( int fd )
 {
     struct process *process;
+    struct process *iter;
     struct thread *thread = NULL;
     int request_pipe[2];
 
@@ -219,10 +272,35 @@
     process->exe.namelen     = 0;
     process->exe.filename    = NULL;
     process->group_id        = 0;
+    process->id              = make_new_process_id();
 
     gettimeofday( &process->start_time, NULL );
-    if ((process->next = first_process) != NULL) process->next->prev = process;
-    first_process = process;
+    /* put process ids in ascending order */
+    iter = first_process;
+    while (iter && (iter->id < process->id))
+    {
+        if (!iter->next)
+        {
+            process->prev = iter;
+        }
+        iter = iter->next;
+    }
+    if ((process->next = iter) != NULL)
+    {
+        process->prev = iter->prev;
+        process->next->prev = process;
+    }
+    if (process->prev)
+    {
+        process->prev->next = process;
+    }
+    else
+    {
+        first_process = process;
+    }
+    /* must do this check AFTER adding to linked list */
+    /* because destroying the process removes it from the list */
+    if (!process->id) goto error;
 
     /* create the main thread */
     if (pipe( request_pipe ) == -1)
Index: server/process.h
===================================================================
RCS file: /home/wine/wine/server/process.h,v
retrieving revision 1.34
diff -u -r1.34 process.h
--- server/process.h	3 Oct 2002 19:54:58 -0000	1.34
+++ server/process.h	23 Jan 2003 18:12:52 -0000
@@ -74,6 +74,7 @@
     void                *ldt_copy;        /* pointer to LDT copy in client addr space */
     void                *ldt_flags;       /* pointer to LDT flags in client addr space */
     process_id_t         group_id;        /* group ID of the process */
+    process_id_t         id;              /* the PID for this process */
 };
 
 struct process_snapshot
@@ -115,7 +116,7 @@
 extern struct module_snapshot *module_snap( struct process *process, int *count );
 extern void enum_processes( int (*cb)(struct process*, void*), void *user);
 
-inline static process_id_t get_process_id( struct process *process ) { return (process_id_t)process; }
+inline static process_id_t get_process_id( struct process *process ) { if (process) return process->id; else return (process_id_t)process; }
 inline static int is_process_init_done( struct process *process )
 {
     return process->startup_state == STARTUP_DONE;


More information about the wine-patches mailing list