Made the service thread instanciable in every process.
This commit is contained in:
parent
ffe6b7679a
commit
63c7cdf196
|
@ -95,6 +95,7 @@ typedef struct _PDB
|
||||||
struct _PDB *next; /* List reference - list of PDB's */
|
struct _PDB *next; /* List reference - list of PDB's */
|
||||||
WORD hInstance; /* hInstance on startup */
|
WORD hInstance; /* hInstance on startup */
|
||||||
WORD hPrevInstance; /* hPrevInstance on startup */
|
WORD hPrevInstance; /* hPrevInstance on startup */
|
||||||
|
struct _SERVICETABLE *service_table; /* Service table for service thread */
|
||||||
} PDB;
|
} PDB;
|
||||||
|
|
||||||
/* Process flags */
|
/* Process flags */
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
|
||||||
BOOL SERVICE_Init( void );
|
|
||||||
|
|
||||||
HANDLE SERVICE_AddObject( HANDLE object,
|
HANDLE SERVICE_AddObject( HANDLE object,
|
||||||
PAPCFUNC callback, ULONG_PTR callback_arg );
|
PAPCFUNC callback, ULONG_PTR callback_arg );
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,6 @@ BOOL MAIN_MainInit(void)
|
||||||
/* Initialize signal handling */
|
/* Initialize signal handling */
|
||||||
if (!SIGNAL_Init()) return FALSE;
|
if (!SIGNAL_Init()) return FALSE;
|
||||||
|
|
||||||
/* Initialize kernel services thread */
|
|
||||||
if (!SERVICE_Init()) return FALSE;
|
|
||||||
|
|
||||||
/* Load the configuration file */
|
/* Load the configuration file */
|
||||||
if (!PROFILE_LoadWineIni()) return FALSE;
|
if (!PROFILE_LoadWineIni()) return FALSE;
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
|
#include "process.h"
|
||||||
#include "debugtools.h"
|
#include "debugtools.h"
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(timer)
|
DEFAULT_DEBUG_CHANNEL(timer)
|
||||||
|
|
||||||
|
|
||||||
#define SERVICE_USE_OBJECT 0x0001
|
#define SERVICE_USE_OBJECT 0x0001
|
||||||
#define SERVICE_USE_TIMEOUT 0x0002
|
#define SERVICE_USE_TIMEOUT 0x0002
|
||||||
#define SERVICE_DISABLED 0x8000
|
#define SERVICE_DISABLED 0x8000
|
||||||
|
@ -34,9 +34,8 @@ typedef struct _SERVICE
|
||||||
|
|
||||||
} SERVICE;
|
} SERVICE;
|
||||||
|
|
||||||
typedef struct
|
typedef struct _SERVICETABLE
|
||||||
{
|
{
|
||||||
HANDLE heap;
|
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
|
|
||||||
SERVICE *first;
|
SERVICE *first;
|
||||||
|
@ -44,9 +43,6 @@ typedef struct
|
||||||
|
|
||||||
} SERVICETABLE;
|
} SERVICETABLE;
|
||||||
|
|
||||||
static SERVICETABLE *Service = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SERVICE_AddTimeval
|
* SERVICE_AddTimeval
|
||||||
*/
|
*/
|
||||||
|
@ -87,7 +83,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
struct timeval curTime;
|
struct timeval curTime;
|
||||||
gettimeofday( &curTime, NULL );
|
gettimeofday( &curTime, NULL );
|
||||||
|
|
||||||
HeapLock( service->heap );
|
HeapLock( GetProcessHeap() );
|
||||||
|
|
||||||
callback = NULL;
|
callback = NULL;
|
||||||
callback_arg = 0L;
|
callback_arg = 0L;
|
||||||
|
@ -97,7 +93,9 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( s->flags & SERVICE_USE_OBJECT )
|
if ( s->flags & SERVICE_USE_OBJECT )
|
||||||
|
{
|
||||||
if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count )
|
if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0 + count )
|
||||||
|
{
|
||||||
if ( handles[retval - WAIT_OBJECT_0] == s->object )
|
if ( handles[retval - WAIT_OBJECT_0] == s->object )
|
||||||
{
|
{
|
||||||
retval = WAIT_TIMEOUT;
|
retval = WAIT_TIMEOUT;
|
||||||
|
@ -105,8 +103,11 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
callback_arg = s->callback_arg;
|
callback_arg = s->callback_arg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( s->flags & SERVICE_USE_TIMEOUT )
|
if ( s->flags & SERVICE_USE_TIMEOUT )
|
||||||
|
{
|
||||||
if ((s->expire.tv_sec < curTime.tv_sec) ||
|
if ((s->expire.tv_sec < curTime.tv_sec) ||
|
||||||
((s->expire.tv_sec == curTime.tv_sec) &&
|
((s->expire.tv_sec == curTime.tv_sec) &&
|
||||||
(s->expire.tv_usec <= curTime.tv_usec)))
|
(s->expire.tv_usec <= curTime.tv_usec)))
|
||||||
|
@ -117,9 +118,9 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HeapUnlock( service->heap );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
|
|
||||||
/* If found, call callback routine */
|
/* If found, call callback routine */
|
||||||
|
|
||||||
|
@ -129,10 +130,9 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If not found, determine wait condition */
|
/* If not found, determine wait condition */
|
||||||
|
|
||||||
HeapLock( service->heap );
|
HeapLock( GetProcessHeap() );
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
timeout = INFINITE;
|
timeout = INFINITE;
|
||||||
|
@ -154,7 +154,7 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapUnlock( service->heap );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
|
|
||||||
/* Wait until some condition satisfied */
|
/* Wait until some condition satisfied */
|
||||||
|
@ -172,68 +172,78 @@ static DWORD CALLBACK SERVICE_Loop( SERVICETABLE *service )
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SERVICE_Init
|
* SERVICE_CreateServiceTable
|
||||||
*/
|
*/
|
||||||
BOOL SERVICE_Init( void )
|
static BOOL SERVICE_CreateServiceTable( void )
|
||||||
{
|
{
|
||||||
HANDLE heap, thread;
|
HANDLE thread;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
|
PDB *pdb = PROCESS_Current();
|
||||||
|
|
||||||
heap = HeapCreate( HEAP_GROWABLE, 0x1000, 0 );
|
service_table = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) );
|
||||||
if ( !heap ) return FALSE;
|
if ( !service_table )
|
||||||
|
|
||||||
Service = HeapAlloc( heap, HEAP_ZERO_MEMORY, sizeof(SERVICETABLE) );
|
|
||||||
if ( !Service )
|
|
||||||
{
|
{
|
||||||
HeapDestroy( heap );
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service->heap = heap;
|
/* service_table field in PDB must be set *BEFORE* calling CreateThread
|
||||||
|
* otherwise the thread cleanup service will cause an infinite recursion
|
||||||
|
* when installed
|
||||||
|
*/
|
||||||
|
pdb->service_table = service_table;
|
||||||
|
|
||||||
thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SERVICE_Loop,
|
thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SERVICE_Loop,
|
||||||
Service, 0, NULL );
|
service_table, 0, NULL );
|
||||||
if ( thread == INVALID_HANDLE_VALUE )
|
if ( thread == INVALID_HANDLE_VALUE )
|
||||||
{
|
{
|
||||||
HeapDestroy( heap );
|
pdb->service_table = 0;
|
||||||
|
HeapFree( GetProcessHeap(), 0, service_table );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service->thread = ConvertToGlobalHandle( thread );
|
service_table->thread = thread;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SERVICE_AddObject
|
* SERVICE_AddObject
|
||||||
|
*
|
||||||
|
* Warning: the object supplied by the caller must not be closed. It'll
|
||||||
|
* be destroyed when the service is deleted. It's up to the caller
|
||||||
|
* to ensure that object will not be destroyed in between.
|
||||||
*/
|
*/
|
||||||
HANDLE SERVICE_AddObject( HANDLE object,
|
HANDLE SERVICE_AddObject( HANDLE object,
|
||||||
PAPCFUNC callback, ULONG_PTR callback_arg )
|
PAPCFUNC callback, ULONG_PTR callback_arg )
|
||||||
{
|
{
|
||||||
SERVICE *s;
|
SERVICE *s;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
object = ConvertToGlobalHandle( object ); /* FIXME */
|
if ( object == INVALID_HANDLE_VALUE || !callback )
|
||||||
|
|
||||||
if ( !Service || object == INVALID_HANDLE_VALUE || !callback )
|
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) );
|
if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable())
|
||||||
if ( !s ) return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
|
service_table = PROCESS_Current()->service_table;
|
||||||
|
|
||||||
HeapLock( Service->heap );
|
s = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) );
|
||||||
|
if ( !s ) return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
s->callback = callback;
|
s->callback = callback;
|
||||||
s->callback_arg = callback_arg;
|
s->callback_arg = callback_arg;
|
||||||
s->object = object;
|
s->object = object;
|
||||||
s->flags = SERVICE_USE_OBJECT;
|
s->flags = SERVICE_USE_OBJECT;
|
||||||
|
|
||||||
s->self = handle = (HANDLE)++Service->counter;
|
HeapLock( GetProcessHeap() );
|
||||||
s->next = Service->first;
|
|
||||||
Service->first = s;
|
|
||||||
|
|
||||||
HeapUnlock( Service->heap );
|
s->self = handle = (HANDLE)++service_table->counter;
|
||||||
|
s->next = service_table->first;
|
||||||
|
service_table->first = s;
|
||||||
|
|
||||||
QueueUserAPC( NULL, Service->thread, 0L );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
|
QueueUserAPC( NULL, service_table->thread, 0L );
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -245,15 +255,18 @@ HANDLE SERVICE_AddTimer( LONG rate,
|
||||||
PAPCFUNC callback, ULONG_PTR callback_arg )
|
PAPCFUNC callback, ULONG_PTR callback_arg )
|
||||||
{
|
{
|
||||||
SERVICE *s;
|
SERVICE *s;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
if ( !Service || !rate || !callback )
|
if ( !rate || !callback )
|
||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
s = HeapAlloc( Service->heap, HEAP_ZERO_MEMORY, sizeof(SERVICE) );
|
if (PROCESS_Current()->service_table == 0 && !SERVICE_CreateServiceTable())
|
||||||
if ( !s ) return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
|
service_table = PROCESS_Current()->service_table;
|
||||||
|
|
||||||
HeapLock( Service->heap );
|
s = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SERVICE) );
|
||||||
|
if ( !s ) return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
s->callback = callback;
|
s->callback = callback;
|
||||||
s->callback_arg = callback_arg;
|
s->callback_arg = callback_arg;
|
||||||
|
@ -263,13 +276,15 @@ HANDLE SERVICE_AddTimer( LONG rate,
|
||||||
gettimeofday( &s->expire, NULL );
|
gettimeofday( &s->expire, NULL );
|
||||||
SERVICE_AddTimeval( &s->expire, s->rate );
|
SERVICE_AddTimeval( &s->expire, s->rate );
|
||||||
|
|
||||||
s->self = handle = (HANDLE)++Service->counter;
|
HeapLock( GetProcessHeap() );
|
||||||
s->next = Service->first;
|
|
||||||
Service->first = s;
|
|
||||||
|
|
||||||
HeapUnlock( Service->heap );
|
s->self = handle = (HANDLE)++service_table->counter;
|
||||||
|
s->next = service_table->first;
|
||||||
|
service_table->first = s;
|
||||||
|
|
||||||
QueueUserAPC( NULL, Service->thread, 0L );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
|
QueueUserAPC( NULL, service_table->thread, 0L );
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -280,32 +295,37 @@ HANDLE SERVICE_AddTimer( LONG rate,
|
||||||
BOOL SERVICE_Delete( HANDLE service )
|
BOOL SERVICE_Delete( HANDLE service )
|
||||||
{
|
{
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||||
BOOL retv = TRUE;
|
BOOL retv = FALSE;
|
||||||
SERVICE **s, *next;
|
SERVICE **s, *next;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
|
|
||||||
if ( !Service ) return retv;
|
/* service table must have been created on previous SERVICE_Add??? call */
|
||||||
|
if ((service_table = PROCESS_Current()->service_table) == 0)
|
||||||
|
return retv;
|
||||||
|
|
||||||
HeapLock( Service->heap );
|
HeapLock( GetProcessHeap() );
|
||||||
|
|
||||||
for ( s = &Service->first; *s; s = &(*s)->next )
|
for ( s = &service_table->first; *s; s = &(*s)->next )
|
||||||
|
{
|
||||||
if ( (*s)->self == service )
|
if ( (*s)->self == service )
|
||||||
{
|
{
|
||||||
if ( (*s)->flags & SERVICE_USE_OBJECT )
|
if ( (*s)->flags & SERVICE_USE_OBJECT )
|
||||||
handle = (*s)->object;
|
handle = (*s)->object;
|
||||||
|
|
||||||
next = (*s)->next;
|
next = (*s)->next;
|
||||||
HeapFree( Service->heap, 0, *s );
|
HeapFree( GetProcessHeap(), 0, *s );
|
||||||
*s = next;
|
*s = next;
|
||||||
retv = FALSE;
|
retv = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HeapUnlock( Service->heap );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
if ( handle != INVALID_HANDLE_VALUE )
|
if ( handle != INVALID_HANDLE_VALUE )
|
||||||
CloseHandle( handle );
|
CloseHandle( handle );
|
||||||
|
|
||||||
QueueUserAPC( NULL, Service->thread, 0L );
|
QueueUserAPC( NULL, service_table->thread, 0L );
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
@ -315,14 +335,18 @@ BOOL SERVICE_Delete( HANDLE service )
|
||||||
*/
|
*/
|
||||||
BOOL SERVICE_Enable( HANDLE service )
|
BOOL SERVICE_Enable( HANDLE service )
|
||||||
{
|
{
|
||||||
BOOL retv = TRUE;
|
BOOL retv = FALSE;
|
||||||
SERVICE *s;
|
SERVICE *s;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
|
|
||||||
if ( !Service ) return retv;
|
/* service table must have been created on previous SERVICE_Add??? call */
|
||||||
|
if ((service_table = PROCESS_Current()->service_table) == 0)
|
||||||
|
return retv;
|
||||||
|
|
||||||
HeapLock( Service->heap );
|
HeapLock( GetProcessHeap() );
|
||||||
|
|
||||||
for ( s = Service->first; s; s = s->next )
|
for ( s = service_table->first; s; s = s->next )
|
||||||
|
{
|
||||||
if ( s->self == service )
|
if ( s->self == service )
|
||||||
{
|
{
|
||||||
if ( s->flags & SERVICE_DISABLED )
|
if ( s->flags & SERVICE_DISABLED )
|
||||||
|
@ -341,13 +365,14 @@ BOOL SERVICE_Enable( HANDLE service )
|
||||||
(delta / s->rate) * s->rate );
|
(delta / s->rate) * s->rate );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retv = FALSE;
|
retv = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HeapUnlock( Service->heap );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
QueueUserAPC( NULL, Service->thread, 0L );
|
QueueUserAPC( NULL, service_table->thread, 0L );
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
@ -359,22 +384,27 @@ BOOL SERVICE_Disable( HANDLE service )
|
||||||
{
|
{
|
||||||
BOOL retv = TRUE;
|
BOOL retv = TRUE;
|
||||||
SERVICE *s;
|
SERVICE *s;
|
||||||
|
SERVICETABLE *service_table;
|
||||||
|
|
||||||
if ( !Service ) return retv;
|
/* service table must have been created on previous SERVICE_Add??? call */
|
||||||
|
if ((service_table = PROCESS_Current()->service_table) == 0)
|
||||||
|
return retv;
|
||||||
|
|
||||||
HeapLock( Service->heap );
|
HeapLock( GetProcessHeap() );
|
||||||
|
|
||||||
for ( s = Service->first; s; s = s->next )
|
for ( s = service_table->first; s; s = s->next )
|
||||||
|
{
|
||||||
if ( s->self == service )
|
if ( s->self == service )
|
||||||
{
|
{
|
||||||
s->flags |= SERVICE_DISABLED;
|
s->flags |= SERVICE_DISABLED;
|
||||||
retv = FALSE;
|
retv = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HeapUnlock( Service->heap );
|
HeapUnlock( GetProcessHeap() );
|
||||||
|
|
||||||
QueueUserAPC( NULL, Service->thread, 0L );
|
QueueUserAPC( NULL, service_table->thread, 0L );
|
||||||
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,6 +203,7 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
|
||||||
struct new_thread_request request;
|
struct new_thread_request request;
|
||||||
struct new_thread_reply reply = { NULL, -1 };
|
struct new_thread_reply reply = { NULL, -1 };
|
||||||
int fd[2];
|
int fd[2];
|
||||||
|
HANDLE cleanup_object;
|
||||||
|
|
||||||
THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
|
THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
|
||||||
if (!thdb) return NULL;
|
if (!thdb) return NULL;
|
||||||
|
@ -250,9 +251,11 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
|
||||||
THREAD_First = thdb;
|
THREAD_First = thdb;
|
||||||
|
|
||||||
/* Install cleanup handler */
|
/* Install cleanup handler */
|
||||||
|
if ( !DuplicateHandle( GetCurrentProcess(), *server_handle,
|
||||||
|
GetCurrentProcess(), &cleanup_object,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS ) ) goto error;
|
||||||
|
thdb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTHDB, (ULONG_PTR)thdb );
|
||||||
|
|
||||||
thdb->cleanup = SERVICE_AddObject( *server_handle,
|
|
||||||
THREAD_FreeTHDB, (ULONG_PTR)thdb );
|
|
||||||
return thdb;
|
return thdb;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
Loading…
Reference in New Issue