Commit 62a8b433 authored by Alexandre Julliard's avatar Alexandre Julliard

Hacked server-side device support

Added user APCs support. Many changes to the xterm console to make use of the server (not finished yet). Moved some other small stuff to the server.
parent 9120c0ad
...@@ -18,40 +18,12 @@ ...@@ -18,40 +18,12 @@
#include "server.h" #include "server.h"
#include "debug.h" #include "debug.h"
static void CHANGE_Destroy( K32OBJ *obj );
const K32OBJ_OPS CHANGE_Ops =
{
CHANGE_Destroy /* destroy */
};
/* The change notification object */ /* The change notification object */
typedef struct typedef struct
{ {
K32OBJ header; K32OBJ header;
LPSTR lpPathName;
BOOL32 bWatchSubtree;
DWORD dwNotifyFilter;
BOOL32 notify;
} CHANGE_OBJECT; } CHANGE_OBJECT;
/****************************************************************************
* CHANGE_Destroy
*/
static void CHANGE_Destroy( K32OBJ *obj )
{
CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj;
assert( obj->type == K32OBJ_CHANGE );
if ( change->lpPathName )
{
HeapFree( SystemHeap, 0, change->lpPathName );
change->lpPathName = NULL;
}
obj->type = K32OBJ_UNKNOWN;
HeapFree( SystemHeap, 0, change );
}
/**************************************************************************** /****************************************************************************
* FindFirstChangeNotification32A (KERNEL32.248) * FindFirstChangeNotification32A (KERNEL32.248)
...@@ -76,15 +48,8 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName, ...@@ -76,15 +48,8 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName,
CLIENT_CloseHandle( reply.handle ); CLIENT_CloseHandle( reply.handle );
return INVALID_HANDLE_VALUE32; return INVALID_HANDLE_VALUE32;
} }
change->header.type = K32OBJ_CHANGE; change->header.type = K32OBJ_CHANGE;
change->header.refcount = 1; change->header.refcount = 1;
change->lpPathName = HEAP_strdupA( SystemHeap, 0, lpPathName );
change->bWatchSubtree = bWatchSubtree;
change->dwNotifyFilter = dwNotifyFilter;
change->notify = FALSE;
return HANDLE_Alloc( PROCESS_Current(), &change->header, return HANDLE_Alloc( PROCESS_Current(), &change->header,
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE /*FIXME*/, STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE /*FIXME*/,
FALSE, reply.handle ); FALSE, reply.handle );
...@@ -109,20 +74,10 @@ HANDLE32 WINAPI FindFirstChangeNotification32W( LPCWSTR lpPathName, ...@@ -109,20 +74,10 @@ HANDLE32 WINAPI FindFirstChangeNotification32W( LPCWSTR lpPathName,
*/ */
BOOL32 WINAPI FindNextChangeNotification( HANDLE32 handle ) BOOL32 WINAPI FindNextChangeNotification( HANDLE32 handle )
{ {
CHANGE_OBJECT *change; if (HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_FILE, 0 ) == -1)
SYSTEM_LOCK();
if (!(change = (CHANGE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(),
handle, K32OBJ_CHANGE,
0 /*FIXME*/, NULL )) )
{
SYSTEM_UNLOCK();
return FALSE; return FALSE;
} /* FIXME: do something */
change->notify = FALSE;
K32OBJ_DecCount( &change->header );
SYSTEM_UNLOCK();
return TRUE; return TRUE;
} }
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "heap.h" #include "heap.h"
#include "msdos.h" #include "msdos.h"
#include "syslevel.h" #include "syslevel.h"
#include "server.h"
#include "process.h"
#include "debug.h" #include "debug.h"
/* Define the VFAT ioctl to get both short and long file names */ /* Define the VFAT ioctl to get both short and long file names */
...@@ -602,6 +604,30 @@ const DOS_DEVICE *DOSFS_GetDevice( const char *name ) ...@@ -602,6 +604,30 @@ const DOS_DEVICE *DOSFS_GetDevice( const char *name )
return NULL; return NULL;
} }
/***********************************************************************
* DOSFS_GetDeviceByHandle
*/
const DOS_DEVICE *DOSFS_GetDeviceByHandle( HFILE32 hFile )
{
struct get_file_info_request req;
struct get_file_info_reply reply;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
K32OBJ_FILE, 0 )) == -1)
return NULL;
CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
if (!CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) &&
(reply.type == FILE_TYPE_UNKNOWN))
{
if ((reply.attr >= 0) &&
(reply.attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
return &DOSFS_Devices[reply.attr];
}
return NULL;
}
/*********************************************************************** /***********************************************************************
* DOSFS_OpenDevice * DOSFS_OpenDevice
* *
...@@ -651,10 +677,7 @@ HFILE32 DOSFS_OpenDevice( const char *name, DWORD access ) ...@@ -651,10 +677,7 @@ HFILE32 DOSFS_OpenDevice( const char *name, DWORD access )
if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") || if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
!strcmp(DOSFS_Devices[i].name,"HPSCAN")) !strcmp(DOSFS_Devices[i].name,"HPSCAN"))
{ {
/* FIXME: should keep the name somewhere */ return FILE_CreateDevice( i, access, NULL );
return FILE_CreateFile( "/dev/null", access,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, -1 );
} }
FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name); FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name);
return HFILE_ERROR32; return HFILE_ERROR32;
......
...@@ -46,75 +46,18 @@ ...@@ -46,75 +46,18 @@
#define MAP_ANON MAP_ANONYMOUS #define MAP_ANON MAP_ANONYMOUS
#endif #endif
static void FILE_Destroy( K32OBJ *obj ); /* The file object */
typedef struct
const K32OBJ_OPS FILE_Ops =
{ {
FILE_Destroy /* destroy */ K32OBJ header;
}; } FILE_OBJECT;
struct DOS_FILE_LOCK {
struct DOS_FILE_LOCK * next;
DWORD base;
DWORD len;
DWORD processId;
FILE_OBJECT * dos_file;
char * unix_name;
};
typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
static DOS_FILE_LOCK *locks = NULL;
static void DOS_RemoveFileLocks(FILE_OBJECT *file);
/* Size of per-process table of DOS handles */ /* Size of per-process table of DOS handles */
#define DOS_TABLE_SIZE 256 #define DOS_TABLE_SIZE 256
/*********************************************************************** /***********************************************************************
* FILE_Destroy
*
* Destroy a DOS file.
*/
static void FILE_Destroy( K32OBJ *ptr )
{
FILE_OBJECT *file = (FILE_OBJECT *)ptr;
assert( ptr->type == K32OBJ_FILE );
DOS_RemoveFileLocks(file);
if (file->unix_name) HeapFree( SystemHeap, 0, file->unix_name );
ptr->type = K32OBJ_UNKNOWN;
HeapFree( SystemHeap, 0, file );
}
/***********************************************************************
* FILE_GetFile
*
* Return the DOS file associated to a task file handle. FILE_ReleaseFile must
* be called to release the file.
*/
FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access, int *server_handle )
{
return (FILE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
K32OBJ_FILE, access,
server_handle );
}
/***********************************************************************
* FILE_ReleaseFile
*
* Release a DOS file obtained with FILE_GetFile.
*/
void FILE_ReleaseFile( FILE_OBJECT *file )
{
K32OBJ_DecCount( &file->header );
}
/***********************************************************************
* FILE_ConvertOFMode * FILE_ConvertOFMode
* *
* Convert OF_* mode into flags for CreateFile. * Convert OF_* mode into flags for CreateFile.
...@@ -391,7 +334,6 @@ HFILE32 FILE_DupUnixHandle( int fd, DWORD access ) ...@@ -391,7 +334,6 @@ HFILE32 FILE_DupUnixHandle( int fd, DWORD access )
} }
file->header.type = K32OBJ_FILE; file->header.type = K32OBJ_FILE;
file->header.refcount = 0; file->header.refcount = 0;
file->unix_name = NULL;
return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access, return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
req.inherit, reply.handle ); req.inherit, reply.handle );
} }
...@@ -448,7 +390,39 @@ HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing, ...@@ -448,7 +390,39 @@ HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
} }
file->header.type = K32OBJ_FILE; file->header.type = K32OBJ_FILE;
file->header.refcount = 0; file->header.refcount = 0;
file->unix_name = HEAP_strdupA( SystemHeap, 0, filename ); return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
req.inherit, reply.handle );
}
/***********************************************************************
* FILE_CreateDevice
*
* Same as FILE_CreateFile but for a device
*/
HFILE32 FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa )
{
FILE_OBJECT *file;
struct create_device_request req;
struct create_device_reply reply;
req.access = access;
req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
req.id = client_id;
CLIENT_SendRequest( REQ_CREATE_DEVICE, -1, 1, &req, sizeof(req) );
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
/* Now build the FILE_OBJECT */
if (!(file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) )))
{
SetLastError( ERROR_OUTOFMEMORY );
CLIENT_CloseHandle( reply.handle );
return (HFILE32)INVALID_HANDLE_VALUE32;
}
file->header.type = K32OBJ_FILE;
file->header.refcount = 0;
return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access, return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
req.inherit, reply.handle ); req.inherit, reply.handle );
} }
...@@ -487,7 +461,6 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing, ...@@ -487,7 +461,6 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
DWORD attributes, HANDLE32 template ) DWORD attributes, HANDLE32 template )
{ {
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
HANDLE32 to_dup = HFILE_ERROR32;
if (!filename) if (!filename)
{ {
...@@ -507,7 +480,8 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing, ...@@ -507,7 +480,8 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
} }
} }
if (!strncmp(filename, "\\\\.\\", 4)) return DEVICE_Open( filename+4 ); if (!strncmp(filename, "\\\\.\\", 4))
return DEVICE_Open( filename+4, access, sa );
/* If the name still starts with '\\', it's a UNC name. */ /* If the name still starts with '\\', it's a UNC name. */
if (!strncmp(filename, "\\\\", 2)) if (!strncmp(filename, "\\\\", 2))
...@@ -517,23 +491,9 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing, ...@@ -517,23 +491,9 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
return HFILE_ERROR32; return HFILE_ERROR32;
} }
/* If the name is either CONIN$ or CONOUT$, give them duplicated stdin /* Open a console for CONIN$ or CONOUT$ */
* or stdout, respectively. The lower case version is also allowed. Most likely if (!lstrcmpi32A(filename, "CONIN$")) return CONSOLE_OpenHandle( FALSE, access, sa );
* this should be a case ignore string compare. if (!lstrcmpi32A(filename, "CONOUT$")) return CONSOLE_OpenHandle( TRUE, access, sa );
*/
if(!strcasecmp(filename, "CONIN$"))
to_dup = GetStdHandle( STD_INPUT_HANDLE );
else if(!strcasecmp(filename, "CONOUT$"))
to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
if(to_dup != HFILE_ERROR32)
{
HFILE32 handle;
if (!DuplicateHandle( GetCurrentProcess(), to_dup, GetCurrentProcess(),
&handle, access, FALSE, 0 ))
handle = HFILE_ERROR32;
return handle;
}
if (DOSFS_GetDevice( filename )) if (DOSFS_GetDevice( filename ))
{ {
...@@ -1979,6 +1939,64 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile, ...@@ -1979,6 +1939,64 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile,
return !CLIENT_WaitReply( NULL, NULL, 0 ); return !CLIENT_WaitReply( NULL, NULL, 0 );
} }
/**************************************************************************
* LockFile (KERNEL32.511)
*/
BOOL32 WINAPI LockFile( HFILE32 hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
{
struct lock_file_request req;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
K32OBJ_FILE, 0 )) == -1)
return FALSE;
req.offset_low = dwFileOffsetLow;
req.offset_high = dwFileOffsetHigh;
req.count_low = nNumberOfBytesToLockLow;
req.count_high = nNumberOfBytesToLockHigh;
CLIENT_SendRequest( REQ_LOCK_FILE, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
/**************************************************************************
* UnlockFile (KERNEL32.703)
*/
BOOL32 WINAPI UnlockFile( HFILE32 hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
{
struct unlock_file_request req;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
K32OBJ_FILE, 0 )) == -1)
return FALSE;
req.offset_low = dwFileOffsetLow;
req.offset_high = dwFileOffsetHigh;
req.count_low = nNumberOfBytesToUnlockLow;
req.count_high = nNumberOfBytesToUnlockHigh;
CLIENT_SendRequest( REQ_UNLOCK_FILE, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
#if 0
struct DOS_FILE_LOCK {
struct DOS_FILE_LOCK * next;
DWORD base;
DWORD len;
DWORD processId;
FILE_OBJECT * dos_file;
/* char * unix_name;*/
};
typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
static DOS_FILE_LOCK *locks = NULL;
static void DOS_RemoveFileLocks(FILE_OBJECT *file);
/* Locks need to be mirrored because unix file locking is based /* Locks need to be mirrored because unix file locking is based
* on the pid. Inside of wine there can be multiple WINE processes * on the pid. Inside of wine there can be multiple WINE processes
* that share the same unix pid. * that share the same unix pid.
...@@ -1994,6 +2012,7 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f) ...@@ -1994,6 +2012,7 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
processId = GetCurrentProcessId(); processId = GetCurrentProcessId();
/* check if lock overlaps a current lock for the same file */ /* check if lock overlaps a current lock for the same file */
#if 0
for (curr = locks; curr; curr = curr->next) { for (curr = locks; curr; curr = curr->next) {
if (strcmp(curr->unix_name, file->unix_name) == 0) { if (strcmp(curr->unix_name, file->unix_name) == 0) {
if ((f->l_start == curr->base) && (f->l_len == curr->len)) if ((f->l_start == curr->base) && (f->l_len == curr->len))
...@@ -2005,12 +2024,13 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f) ...@@ -2005,12 +2024,13 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
} }
} }
} }
#endif
curr = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE_LOCK) ); curr = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE_LOCK) );
curr->processId = GetCurrentProcessId(); curr->processId = GetCurrentProcessId();
curr->base = f->l_start; curr->base = f->l_start;
curr->len = f->l_len; curr->len = f->l_len;
curr->unix_name = HEAP_strdupA( SystemHeap, 0, file->unix_name); /* curr->unix_name = HEAP_strdupA( SystemHeap, 0, file->unix_name);*/
curr->next = locks; curr->next = locks;
curr->dos_file = file; curr->dos_file = file;
locks = curr; locks = curr;
...@@ -2029,7 +2049,7 @@ static void DOS_RemoveFileLocks(FILE_OBJECT *file) ...@@ -2029,7 +2049,7 @@ static void DOS_RemoveFileLocks(FILE_OBJECT *file)
if ((*curr)->dos_file == file) { if ((*curr)->dos_file == file) {
rem = *curr; rem = *curr;
*curr = (*curr)->next; *curr = (*curr)->next;
HeapFree( SystemHeap, 0, rem->unix_name ); /* HeapFree( SystemHeap, 0, rem->unix_name );*/
HeapFree( SystemHeap, 0, rem ); HeapFree( SystemHeap, 0, rem );
} }
else else
...@@ -2052,7 +2072,7 @@ static BOOL32 DOS_RemoveLock(FILE_OBJECT *file, struct flock *f) ...@@ -2052,7 +2072,7 @@ static BOOL32 DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
/* this is the same lock */ /* this is the same lock */
rem = *curr; rem = *curr;
*curr = (*curr)->next; *curr = (*curr)->next;
HeapFree( SystemHeap, 0, rem->unix_name ); /* HeapFree( SystemHeap, 0, rem->unix_name );*/
HeapFree( SystemHeap, 0, rem ); HeapFree( SystemHeap, 0, rem );
return TRUE; return TRUE;
} }
...@@ -2151,6 +2171,7 @@ BOOL32 WINAPI UnlockFile( ...@@ -2151,6 +2171,7 @@ BOOL32 WINAPI UnlockFile(
#endif #endif
return TRUE; return TRUE;
} }
#endif
/************************************************************************** /**************************************************************************
* GetFileAttributesEx32A [KERNEL32.874] * GetFileAttributesEx32A [KERNEL32.874]
......
#ifndef __WINE_DEVICE_H #ifndef __WINE_DEVICE_H
#define __WINE_DEVICE_H #define __WINE_DEVICE_H
extern HANDLE32 DEVICE_Open( LPCSTR name); extern HANDLE32 DEVICE_Open( LPCSTR filename, DWORD access,
LPSECURITY_ATTRIBUTES sa );
#endif #endif
...@@ -13,13 +13,6 @@ ...@@ -13,13 +13,6 @@
#define MAX_PATHNAME_LEN 1024 #define MAX_PATHNAME_LEN 1024
/* The file object */
typedef struct
{
K32OBJ header;
char *unix_name;
} FILE_OBJECT;
/* Definition of a full DOS file name */ /* Definition of a full DOS file name */
typedef struct typedef struct
{ {
...@@ -39,9 +32,6 @@ typedef struct ...@@ -39,9 +32,6 @@ typedef struct
/* files/file.c */ /* files/file.c */
extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
int *server_handle );
extern void FILE_ReleaseFile( FILE_OBJECT *file );
extern void FILE_SetDosError(void); extern void FILE_SetDosError(void);
extern HFILE32 FILE_DupUnixHandle( int fd, DWORD access ); extern HFILE32 FILE_DupUnixHandle( int fd, DWORD access );
extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info ); extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
...@@ -49,6 +39,8 @@ extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 ); ...@@ -49,6 +39,8 @@ extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing, extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE32 template ); DWORD attributes, HANDLE32 template );
extern HFILE32 FILE_CreateDevice( int client_id, DWORD access,
LPSECURITY_ATTRIBUTES sa );
extern LPVOID FILE_dommap( int unix_handle, LPVOID start, extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
DWORD size_high, DWORD size_low, DWORD size_high, DWORD size_low,
DWORD offset_high, DWORD offset_low, DWORD offset_high, DWORD offset_low,
...@@ -71,6 +63,7 @@ extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft, ...@@ -71,6 +63,7 @@ extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder ); extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer ); extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
extern const DOS_DEVICE *DOSFS_GetDevice( const char *name ); extern const DOS_DEVICE *DOSFS_GetDevice( const char *name );
extern const DOS_DEVICE *DOSFS_GetDeviceByHandle( HFILE32 hFile );
extern HFILE32 DOSFS_OpenDevice( const char *name, DWORD access ); extern HFILE32 DOSFS_OpenDevice( const char *name, DWORD access );
extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf, extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
INT32 long_len, LPSTR short_buf, INT32 long_len, LPSTR short_buf,
......
...@@ -139,8 +139,6 @@ extern K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle, ...@@ -139,8 +139,6 @@ extern K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle,
int *server_handle ); int *server_handle );
extern int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle, extern int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
K32OBJ_TYPE type, DWORD access ); K32OBJ_TYPE type, DWORD access );
extern BOOL32 HANDLE_SetObjPtr( PDB32 *pdb, HANDLE32 handle,
K32OBJ *ptr, DWORD access );
extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr ); extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
/* Global handle macros */ /* Global handle macros */
...@@ -153,6 +151,7 @@ extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr ); ...@@ -153,6 +151,7 @@ extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
/* scheduler/process.c */ /* scheduler/process.c */
extern BOOL32 PROCESS_Init( void ); extern BOOL32 PROCESS_Init( void );
extern PDB32 *PROCESS_Current(void); extern PDB32 *PROCESS_Current(void);
extern BOOL32 PROCESS_IsCurrent( HANDLE32 handle );
extern PDB32 *PROCESS_Initial(void); extern PDB32 *PROCESS_Initial(void);
extern PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle ); extern PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle );
extern PDB32 *PROCESS_IdToPDB( DWORD id ); extern PDB32 *PROCESS_IdToPDB( DWORD id );
......
...@@ -94,9 +94,24 @@ struct get_process_info_reply ...@@ -94,9 +94,24 @@ struct get_process_info_reply
{ {
void* pid; /* server process id */ void* pid; /* server process id */
int exit_code; /* process exit code */ int exit_code; /* process exit code */
int priority; /* priority class */
int process_affinity; /* process affinity mask */
int system_affinity; /* system affinity mask */
}; };
/* Set a process informations */
struct set_process_info_request
{
int handle; /* process handle */
int mask; /* setting mask (see below) */
int priority; /* priority class */
int affinity; /* affinity mask */
};
#define SET_PROCESS_INFO_PRIORITY 0x01
#define SET_PROCESS_INFO_AFFINITY 0x02
/* Retrieve information about a thread */ /* Retrieve information about a thread */
struct get_thread_info_request struct get_thread_info_request
{ {
...@@ -106,6 +121,50 @@ struct get_thread_info_reply ...@@ -106,6 +121,50 @@ struct get_thread_info_reply
{ {
void* pid; /* server thread id */ void* pid; /* server thread id */
int exit_code; /* thread exit code */ int exit_code; /* thread exit code */
int priority; /* thread priority level */
};
/* Set a thread informations */
struct set_thread_info_request
{
int handle; /* thread handle */
int mask; /* setting mask (see below) */
int priority; /* priority class */
int affinity; /* affinity mask */
};
#define SET_THREAD_INFO_PRIORITY 0x01
#define SET_THREAD_INFO_AFFINITY 0x02
/* Suspend a thread */
struct suspend_thread_request
{
int handle; /* thread handle */
};
struct suspend_thread_reply
{
int count; /* new suspend count */
};
/* Resume a thread */
struct resume_thread_request
{
int handle; /* thread handle */
};
struct resume_thread_reply
{
int count; /* new suspend count */
};
/* Queue an APC for a thread */
struct queue_apc_request
{
int handle; /* thread handle */
void* func; /* function to call */
void* param; /* param for function to call */
}; };
...@@ -160,6 +219,7 @@ struct select_request ...@@ -160,6 +219,7 @@ struct select_request
struct select_reply struct select_reply
{ {
int signaled; /* signaled handle */ int signaled; /* signaled handle */
/* void* apcs[]; */ /* async procedures to call */
}; };
#define SELECT_ALL 1 #define SELECT_ALL 1
#define SELECT_ALERTABLE 2 #define SELECT_ALERTABLE 2
...@@ -338,6 +398,28 @@ struct get_file_info_reply ...@@ -338,6 +398,28 @@ struct get_file_info_reply
}; };
/* Lock a region of a file */
struct lock_file_request
{
int handle; /* handle to the file */
unsigned int offset_low; /* offset of start of lock */
unsigned int offset_high; /* offset of start of lock */
unsigned int count_low; /* count of bytes to lock */
unsigned int count_high; /* count of bytes to lock */
};
/* Unlock a region of a file */
struct unlock_file_request
{
int handle; /* handle to the file */
unsigned int offset_low; /* offset of start of unlock */
unsigned int offset_high; /* offset of start of unlock */
unsigned int count_low; /* count of bytes to unlock */
unsigned int count_high; /* count of bytes to unlock */
};
/* Create an anonymous pipe */ /* Create an anonymous pipe */
struct create_pipe_request struct create_pipe_request
{ {
...@@ -350,15 +432,28 @@ struct create_pipe_reply ...@@ -350,15 +432,28 @@ struct create_pipe_reply
}; };
/* Create a console */ /* Allocate a console for the current process */
struct create_console_request struct alloc_console_request
{
};
/* Free the console of the current process */
struct free_console_request
{
};
/* Open a handle to the process console */
struct open_console_request
{ {
int output; /* input or output? */
unsigned int access; /* wanted access rights */
int inherit; /* inherit flag */ int inherit; /* inherit flag */
}; };
struct create_console_reply struct open_console_reply
{ {
int handle_read; /* handle to read from the console */ int handle; /* handle to the console */
int handle_write; /* handle to write to the console */
}; };
...@@ -366,6 +461,52 @@ struct create_console_reply ...@@ -366,6 +461,52 @@ struct create_console_reply
struct set_console_fd_request struct set_console_fd_request
{ {
int handle; /* handle to the console */ int handle; /* handle to the console */
int pid; /* pid of xterm (hack) */
};
/* Get a console mode (input or output) */
struct get_console_mode_request
{
int handle; /* handle to the console */
};
struct get_console_mode_reply
{
int mode; /* console mode */
};
/* Set a console mode (input or output) */
struct set_console_mode_request
{
int handle; /* handle to the console */
int mode; /* console mode */
};
/* Set info about a console (output only) */
struct set_console_info_request
{
int handle; /* handle to the console */
int mask; /* setting mask (see below) */
int cursor_size; /* size of cursor (percentage filled) */
int cursor_visible;/* cursor visibility flag */
char title[0]; /* console title */
};
#define SET_CONSOLE_INFO_CURSOR 0x01
#define SET_CONSOLE_INFO_TITLE 0x02
/* Get info about a console (output only) */
struct get_console_info_request
{
int handle; /* handle to the console */
};
struct get_console_info_reply
{
int cursor_size; /* size of cursor (percentage filled) */
int cursor_visible;/* cursor visibility flag */
int pid; /* pid of xterm (hack) */
/* char title[0]; */ /* console title */
}; };
...@@ -417,6 +558,19 @@ struct get_mapping_info_reply ...@@ -417,6 +558,19 @@ struct get_mapping_info_reply
}; };
/* Create a device */
struct create_device_request
{
unsigned int access; /* wanted access rights */
int inherit; /* inherit flag */
int id; /* client private id */
};
struct create_device_reply
{
int handle; /* handle to the device */
};
/* client-side functions */ /* client-side functions */
#ifndef __WINE_SERVER__ #ifndef __WINE_SERVER__
...@@ -438,7 +592,6 @@ extern int CLIENT_CloseHandle( int handle ); ...@@ -438,7 +592,6 @@ extern int CLIENT_CloseHandle( int handle );
extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process,
int dst_handle, DWORD access, BOOL32 inherit, DWORD options ); int dst_handle, DWORD access, BOOL32 inherit, DWORD options );
extern int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit ); extern int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit );
extern int CLIENT_Select( int count, int *handles, int flags, int timeout );
#endif /* __WINE_SERVER__ */ #endif /* __WINE_SERVER__ */
#endif /* __WINE_SERVER_H */ #endif /* __WINE_SERVER_H */
...@@ -133,6 +133,11 @@ extern void remove_process_thread( struct process *process, ...@@ -133,6 +133,11 @@ extern void remove_process_thread( struct process *process,
extern void kill_process( struct process *process, int exit_code ); extern void kill_process( struct process *process, int exit_code );
extern void get_process_info( struct process *process, extern void get_process_info( struct process *process,
struct get_process_info_reply *reply ); 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 */ /* handle functions */
...@@ -184,6 +189,10 @@ extern int file_get_mmap_fd( struct file *file ); ...@@ -184,6 +189,10 @@ extern int file_get_mmap_fd( struct file *file );
extern int set_file_pointer( int handle, int *low, int *high, int whence ); extern int set_file_pointer( int handle, int *low, int *high, int whence );
extern int truncate_file( int handle ); extern int truncate_file( int handle );
extern int set_file_time( int handle, time_t access_time, time_t write_time ); extern int set_file_time( int handle, time_t access_time, time_t write_time );
extern int file_lock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low );
extern int file_unlock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low );
extern void file_set_error(void); extern void file_set_error(void);
...@@ -195,7 +204,13 @@ extern int create_pipe( struct object *obj[2] ); ...@@ -195,7 +204,13 @@ extern int create_pipe( struct object *obj[2] );
/* console functions */ /* console functions */
extern int create_console( int fd, struct object *obj[2] ); extern int create_console( int fd, struct object *obj[2] );
extern int set_console_fd( int handle, int fd ); extern int set_console_fd( int handle, int fd, int pid );
extern int get_console_mode( int handle, int *mode );
extern int set_console_mode( int handle, int mode );
extern int set_console_info( int handle, struct set_console_info_request *req,
const char *title );
extern int get_console_info( int handle, struct get_console_info_reply *reply,
const char **title );
/* change notification functions */ /* change notification functions */
...@@ -210,6 +225,10 @@ extern int open_mapping( unsigned int access, int inherit, const char *name ); ...@@ -210,6 +225,10 @@ extern int open_mapping( unsigned int access, int inherit, const char *name );
extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply ); extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply );
/* device functions */
extern struct object *create_device( int id );
extern int debug_level; extern int debug_level;
#endif /* __WINE_SERVER_OBJECT_H */ #endif /* __WINE_SERVER_OBJECT_H */
...@@ -11,7 +11,12 @@ enum request ...@@ -11,7 +11,12 @@ enum request
REQ_TERMINATE_PROCESS, REQ_TERMINATE_PROCESS,
REQ_TERMINATE_THREAD, REQ_TERMINATE_THREAD,
REQ_GET_PROCESS_INFO, REQ_GET_PROCESS_INFO,
REQ_SET_PROCESS_INFO,
REQ_GET_THREAD_INFO, REQ_GET_THREAD_INFO,
REQ_SET_THREAD_INFO,
REQ_SUSPEND_THREAD,
REQ_RESUME_THREAD,
REQ_QUEUE_APC,
REQ_CLOSE_HANDLE, REQ_CLOSE_HANDLE,
REQ_DUP_HANDLE, REQ_DUP_HANDLE,
REQ_OPEN_PROCESS, REQ_OPEN_PROCESS,
...@@ -31,12 +36,21 @@ enum request ...@@ -31,12 +36,21 @@ enum request
REQ_SET_FILE_TIME, REQ_SET_FILE_TIME,
REQ_FLUSH_FILE, REQ_FLUSH_FILE,
REQ_GET_FILE_INFO, REQ_GET_FILE_INFO,
REQ_LOCK_FILE,
REQ_UNLOCK_FILE,
REQ_CREATE_PIPE, REQ_CREATE_PIPE,
REQ_CREATE_CONSOLE, REQ_ALLOC_CONSOLE,
REQ_FREE_CONSOLE,
REQ_OPEN_CONSOLE,
REQ_SET_CONSOLE_FD, REQ_SET_CONSOLE_FD,
REQ_GET_CONSOLE_MODE,
REQ_SET_CONSOLE_MODE,
REQ_SET_CONSOLE_INFO,
REQ_GET_CONSOLE_INFO,
REQ_CREATE_CHANGE_NOTIFICATION, REQ_CREATE_CHANGE_NOTIFICATION,
REQ_CREATE_MAPPING, REQ_CREATE_MAPPING,
REQ_GET_MAPPING_INFO, REQ_GET_MAPPING_INFO,
REQ_CREATE_DEVICE,
REQ_NB_REQUESTS REQ_NB_REQUESTS
}; };
...@@ -51,7 +65,12 @@ DECL_HANDLER(init_thread); ...@@ -51,7 +65,12 @@ DECL_HANDLER(init_thread);
DECL_HANDLER(terminate_process); DECL_HANDLER(terminate_process);
DECL_HANDLER(terminate_thread); DECL_HANDLER(terminate_thread);
DECL_HANDLER(get_process_info); DECL_HANDLER(get_process_info);
DECL_HANDLER(set_process_info);
DECL_HANDLER(get_thread_info); DECL_HANDLER(get_thread_info);
DECL_HANDLER(set_thread_info);
DECL_HANDLER(suspend_thread);
DECL_HANDLER(resume_thread);
DECL_HANDLER(queue_apc);
DECL_HANDLER(close_handle); DECL_HANDLER(close_handle);
DECL_HANDLER(dup_handle); DECL_HANDLER(dup_handle);
DECL_HANDLER(open_process); DECL_HANDLER(open_process);
...@@ -71,12 +90,21 @@ DECL_HANDLER(truncate_file); ...@@ -71,12 +90,21 @@ DECL_HANDLER(truncate_file);
DECL_HANDLER(set_file_time); DECL_HANDLER(set_file_time);
DECL_HANDLER(flush_file); DECL_HANDLER(flush_file);
DECL_HANDLER(get_file_info); DECL_HANDLER(get_file_info);
DECL_HANDLER(lock_file);
DECL_HANDLER(unlock_file);
DECL_HANDLER(create_pipe); DECL_HANDLER(create_pipe);
DECL_HANDLER(create_console); DECL_HANDLER(alloc_console);
DECL_HANDLER(free_console);
DECL_HANDLER(open_console);
DECL_HANDLER(set_console_fd); DECL_HANDLER(set_console_fd);
DECL_HANDLER(get_console_mode);
DECL_HANDLER(set_console_mode);
DECL_HANDLER(set_console_info);
DECL_HANDLER(get_console_info);
DECL_HANDLER(create_change_notification); DECL_HANDLER(create_change_notification);
DECL_HANDLER(create_mapping); DECL_HANDLER(create_mapping);
DECL_HANDLER(get_mapping_info); DECL_HANDLER(get_mapping_info);
DECL_HANDLER(create_device);
static const struct handler { static const struct handler {
void (*handler)(); void (*handler)();
...@@ -88,7 +116,12 @@ static const struct handler { ...@@ -88,7 +116,12 @@ static const struct handler {
{ (void(*)())req_terminate_process, sizeof(struct terminate_process_request) }, { (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
{ (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) }, { (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
{ (void(*)())req_get_process_info, sizeof(struct get_process_info_request) }, { (void(*)())req_get_process_info, sizeof(struct get_process_info_request) },
{ (void(*)())req_set_process_info, sizeof(struct set_process_info_request) },
{ (void(*)())req_get_thread_info, sizeof(struct get_thread_info_request) }, { (void(*)())req_get_thread_info, sizeof(struct get_thread_info_request) },
{ (void(*)())req_set_thread_info, sizeof(struct set_thread_info_request) },
{ (void(*)())req_suspend_thread, sizeof(struct suspend_thread_request) },
{ (void(*)())req_resume_thread, sizeof(struct resume_thread_request) },
{ (void(*)())req_queue_apc, sizeof(struct queue_apc_request) },
{ (void(*)())req_close_handle, sizeof(struct close_handle_request) }, { (void(*)())req_close_handle, sizeof(struct close_handle_request) },
{ (void(*)())req_dup_handle, sizeof(struct dup_handle_request) }, { (void(*)())req_dup_handle, sizeof(struct dup_handle_request) },
{ (void(*)())req_open_process, sizeof(struct open_process_request) }, { (void(*)())req_open_process, sizeof(struct open_process_request) },
...@@ -108,12 +141,21 @@ static const struct handler { ...@@ -108,12 +141,21 @@ static const struct handler {
{ (void(*)())req_set_file_time, sizeof(struct set_file_time_request) }, { (void(*)())req_set_file_time, sizeof(struct set_file_time_request) },
{ (void(*)())req_flush_file, sizeof(struct flush_file_request) }, { (void(*)())req_flush_file, sizeof(struct flush_file_request) },
{ (void(*)())req_get_file_info, sizeof(struct get_file_info_request) }, { (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
{ (void(*)())req_lock_file, sizeof(struct lock_file_request) },
{ (void(*)())req_unlock_file, sizeof(struct unlock_file_request) },
{ (void(*)())req_create_pipe, sizeof(struct create_pipe_request) }, { (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
{ (void(*)())req_create_console, sizeof(struct create_console_request) }, { (void(*)())req_alloc_console, sizeof(struct alloc_console_request) },
{ (void(*)())req_free_console, sizeof(struct free_console_request) },
{ (void(*)())req_open_console, sizeof(struct open_console_request) },
{ (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) }, { (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) },
{ (void(*)())req_get_console_mode, sizeof(struct get_console_mode_request) },
{ (void(*)())req_set_console_mode, sizeof(struct set_console_mode_request) },
{ (void(*)())req_set_console_info, sizeof(struct set_console_info_request) },
{ (void(*)())req_get_console_info, sizeof(struct get_console_info_request) },
{ (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) }, { (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) },
{ (void(*)())req_create_mapping, sizeof(struct create_mapping_request) }, { (void(*)())req_create_mapping, sizeof(struct create_mapping_request) },
{ (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) }, { (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
{ (void(*)())req_create_device, sizeof(struct create_device_request) },
}; };
#endif /* WANT_REQUEST_HANDLERS */ #endif /* WANT_REQUEST_HANDLERS */
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
struct process; struct process;
struct thread_wait; struct thread_wait;
struct thread_apc;
struct mutex; struct mutex;
enum run_state { STARTING, RUNNING, TERMINATED }; enum run_state { STARTING, RUNNING, TERMINATED };
...@@ -31,11 +32,16 @@ struct thread ...@@ -31,11 +32,16 @@ struct thread
struct process *process; struct process *process;
struct mutex *mutex; /* list of currently owned mutexes */ struct mutex *mutex; /* list of currently owned mutexes */
struct thread_wait *wait; /* current wait condition if sleeping */ struct thread_wait *wait; /* current wait condition if sleeping */
struct thread_apc *apc; /* list of async procedure calls */
int apc_count; /* number of outstanding APCs */
int error; /* current error code */ int error; /* current error code */
enum run_state state; /* running state */ enum run_state state; /* running state */
int exit_code; /* thread exit code */ int exit_code; /* thread exit code */
int client_fd; /* client fd for socket communications */ int client_fd; /* client fd for socket communications */
int unix_pid; /* Unix pid of client */ int unix_pid; /* Unix pid of client */
int priority; /* priority level */
int affinity; /* affinity mask */
int suspend; /* suspend count */
enum request last_req; /* last request received (for debugging) */ enum request last_req; /* last request received (for debugging) */
char *name; char *name;
}; };
...@@ -50,10 +56,15 @@ extern struct thread *get_thread_from_id( void *id ); ...@@ -50,10 +56,15 @@ extern struct thread *get_thread_from_id( void *id );
extern struct thread *get_thread_from_handle( int handle, unsigned int access ); extern struct thread *get_thread_from_handle( int handle, unsigned int access );
extern void get_thread_info( struct thread *thread, extern void get_thread_info( struct thread *thread,
struct get_thread_info_reply *reply ); struct get_thread_info_reply *reply );
extern void set_thread_info( struct thread *thread,
struct set_thread_info_request *req );
extern int suspend_thread( struct thread *thread );
extern int resume_thread( struct thread *thread );
extern int send_reply( struct thread *thread, int pass_fd, extern int send_reply( struct thread *thread, int pass_fd,
int n, ... /* arg_1, len_1, ..., arg_n, len_n */ ); int n, ... /* arg_1, len_1, ..., arg_n, len_n */ );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry ); extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern int thread_queue_apc( struct thread *thread, void *func, void *param );
extern void kill_thread( struct thread *thread, int exit_code ); extern void kill_thread( struct thread *thread, int exit_code );
extern void thread_killed( struct thread *thread, int exit_code ); extern void thread_killed( struct thread *thread, int exit_code );
extern void thread_timeout(void); extern void thread_timeout(void);
......
...@@ -61,7 +61,6 @@ typedef struct _TEB ...@@ -61,7 +61,6 @@ typedef struct _TEB
typedef struct typedef struct
{ {
DWORD count; /* Count of valid objects */ DWORD count; /* Count of valid objects */
DWORD signaled; /* Index of signaled object (or WAIT_FAILED)*/
BOOL32 wait_all; /* Wait for all objects flag */ BOOL32 wait_all; /* Wait for all objects flag */
K32OBJ *objs[MAXIMUM_WAIT_OBJECTS]; /* Object pointers */ K32OBJ *objs[MAXIMUM_WAIT_OBJECTS]; /* Object pointers */
int server[MAXIMUM_WAIT_OBJECTS]; /* Server handles */ int server[MAXIMUM_WAIT_OBJECTS]; /* Server handles */
...@@ -110,8 +109,7 @@ typedef struct _THDB ...@@ -110,8 +109,7 @@ typedef struct _THDB
CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */ CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */
DWORD unknown6[2]; /* 1f8 Unknown */ DWORD unknown6[2]; /* 1f8 Unknown */
/* The following are Wine-specific fields */ /* The following are Wine-specific fields */
CONTEXT context; /* 200 Thread context */ WAIT_STRUCT wait_struct; /* 200 Event wait structure */
WAIT_STRUCT wait_struct; /* Event wait structure */
int socket; /* Socket for server communication */ int socket; /* Socket for server communication */
unsigned int seq; /* Server sequence number */ unsigned int seq; /* Server sequence number */
void *server_tid; /* Server id for this thread */ void *server_tid; /* Server id for this thread */
...@@ -155,7 +153,6 @@ extern THDB *THREAD_Current(void); ...@@ -155,7 +153,6 @@ extern THDB *THREAD_Current(void);
extern BOOL32 THREAD_IsWin16( THDB *thdb ); extern BOOL32 THREAD_IsWin16( THDB *thdb );
extern THDB *THREAD_IdToTHDB( DWORD id ); extern THDB *THREAD_IdToTHDB( DWORD id );
extern void THREAD_Start( THDB *thdb ); extern void THREAD_Start( THDB *thdb );
extern THDB *THREAD_GetPtr( HANDLE32 handle, DWORD access, int *server_handle );
extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread ); extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread );
extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread ); extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
extern DWORD THREAD_TlsAlloc( THDB *thread ); extern DWORD THREAD_TlsAlloc( THDB *thread );
......
...@@ -273,6 +273,8 @@ typedef struct tagCOMMTIMEOUTS { ...@@ -273,6 +273,8 @@ typedef struct tagCOMMTIMEOUTS {
#pragma pack(4) #pragma pack(4)
typedef VOID (CALLBACK *PAPCFUNC)(ULONG_PTR);
BOOL32 WINAPI ClearCommError(INT32,LPDWORD,LPCOMSTAT); BOOL32 WINAPI ClearCommError(INT32,LPDWORD,LPCOMSTAT);
BOOL32 WINAPI BuildCommDCB32A(LPCSTR,LPDCB32); BOOL32 WINAPI BuildCommDCB32A(LPCSTR,LPDCB32);
BOOL32 WINAPI BuildCommDCB32W(LPCWSTR,LPDCB32); BOOL32 WINAPI BuildCommDCB32W(LPCWSTR,LPDCB32);
...@@ -305,8 +307,9 @@ void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit); ...@@ -305,8 +307,9 @@ void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit); void WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit);
HANDLE32 WINAPI OpenProcess(DWORD access, BOOL32 inherit, DWORD id); HANDLE32 WINAPI OpenProcess(DWORD access, BOOL32 inherit, DWORD id);
BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32,LPDWORD,LPDWORD); BOOL32 WINAPI GetProcessWorkingSetSize(HANDLE32,LPDWORD,LPDWORD);
BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32,DWORD,DWORD); DWORD WINAPI QueueUserAPC(PAPCFUNC,HANDLE32,ULONG_PTR);
void WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD); void WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD);
BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32,DWORD,DWORD);
BOOL32 WINAPI TerminateProcess(HANDLE32,DWORD); BOOL32 WINAPI TerminateProcess(HANDLE32,DWORD);
BOOL32 WINAPI TerminateThread(HANDLE32,DWORD); BOOL32 WINAPI TerminateThread(HANDLE32,DWORD);
......
...@@ -4186,6 +4186,7 @@ BOOL32 WINAPI SetPriorityClass(HANDLE32,DWORD); ...@@ -4186,6 +4186,7 @@ BOOL32 WINAPI SetPriorityClass(HANDLE32,DWORD);
BOOL32 WINAPI SetStdHandle(DWORD,HANDLE32); BOOL32 WINAPI SetStdHandle(DWORD,HANDLE32);
BOOL32 WINAPI SetSystemPowerState(BOOL32,BOOL32); BOOL32 WINAPI SetSystemPowerState(BOOL32,BOOL32);
BOOL32 WINAPI SetSystemTime(const SYSTEMTIME*); BOOL32 WINAPI SetSystemTime(const SYSTEMTIME*);
DWORD WINAPI SetThreadAffinityMask(HANDLE32,DWORD);
BOOL32 WINAPI SetThreadPriority(HANDLE32,INT32); BOOL32 WINAPI SetThreadPriority(HANDLE32,INT32);
BOOL32 WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION); BOOL32 WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
VOID WINAPI Sleep(DWORD); VOID WINAPI Sleep(DWORD);
......
...@@ -89,6 +89,8 @@ typedef unsigned short WCHAR; ...@@ -89,6 +89,8 @@ typedef unsigned short WCHAR;
typedef unsigned short BOOL16; typedef unsigned short BOOL16;
typedef int BOOL32; typedef int BOOL32;
typedef double DATE; typedef double DATE;
typedef long LONG_PTR;
typedef unsigned long ULONG_PTR;
#ifdef __i386__ #ifdef __i386__
typedef double LONGLONG; typedef double LONGLONG;
typedef double ULONGLONG; typedef double ULONGLONG;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
typedef struct typedef struct
{ {
K32OBJ header; K32OBJ header;
FILE_OBJECT *file; K32OBJ *file;
} FILE_MAPPING; } FILE_MAPPING;
/* File view */ /* File view */
...@@ -810,20 +810,12 @@ BOOL32 WINAPI VirtualProtectEx( ...@@ -810,20 +810,12 @@ BOOL32 WINAPI VirtualProtectEx(
LPVOID addr, /* [in] Address of region of committed pages */ LPVOID addr, /* [in] Address of region of committed pages */
DWORD size, /* [in] Size of region */ DWORD size, /* [in] Size of region */
DWORD new_prot, /* [in] Desired access protection */ DWORD new_prot, /* [in] Desired access protection */
LPDWORD old_prot /* [out] Address of variable to get old protection */ LPDWORD old_prot /* [out] Address of variable to get old protection */ )
) { {
BOOL32 ret = FALSE; if (PROCESS_IsCurrent( handle ))
return VirtualProtect( addr, size, new_prot, old_prot );
PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_VM_OPERATION, NULL );
if (pdb)
{
if (pdb == PROCESS_Current())
ret = VirtualProtect( addr, size, new_prot, old_prot );
else
ERR(virtual,"Unsupported on other process\n"); ERR(virtual,"Unsupported on other process\n");
K32OBJ_DecCount( &pdb->header ); return FALSE;
}
return ret;
} }
...@@ -907,20 +899,12 @@ DWORD WINAPI VirtualQueryEx( ...@@ -907,20 +899,12 @@ DWORD WINAPI VirtualQueryEx(
HANDLE32 handle, /* [in] Handle of process */ HANDLE32 handle, /* [in] Handle of process */
LPCVOID addr, /* [in] Address of region */ LPCVOID addr, /* [in] Address of region */
LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */ LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
DWORD len /* [in] Size of buffer */ DWORD len /* [in] Size of buffer */ )
) { {
DWORD ret = len; if (PROCESS_IsCurrent( handle ))
return VirtualQuery( addr, info, len );
PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_QUERY_INFORMATION, NULL );
if (pdb)
{
if (pdb == PROCESS_Current())
ret = VirtualQuery( addr, info, len );
else
ERR(virtual,"Unsupported on other process\n"); ERR(virtual,"Unsupported on other process\n");
K32OBJ_DecCount( &pdb->header ); return 0;
}
return ret;
} }
...@@ -1079,7 +1063,7 @@ HANDLE32 WINAPI CreateFileMapping32A( ...@@ -1079,7 +1063,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
LPCSTR name /* [in] Name of file-mapping object */ ) LPCSTR name /* [in] Name of file-mapping object */ )
{ {
FILE_MAPPING *mapping = NULL; FILE_MAPPING *mapping = NULL;
FILE_OBJECT *file; K32OBJ *file;
struct create_mapping_request req; struct create_mapping_request req;
struct create_mapping_reply reply = { -1 }; struct create_mapping_reply reply = { -1 };
HANDLE32 handle; HANDLE32 handle;
...@@ -1172,7 +1156,9 @@ HANDLE32 WINAPI CreateFileMapping32A( ...@@ -1172,7 +1156,9 @@ HANDLE32 WINAPI CreateFileMapping32A(
((protect & 0xff) == PAGE_EXECUTE_READWRITE) || ((protect & 0xff) == PAGE_EXECUTE_READWRITE) ||
((protect & 0xff) == PAGE_EXECUTE_WRITECOPY)) ((protect & 0xff) == PAGE_EXECUTE_WRITECOPY))
access |= GENERIC_WRITE; access |= GENERIC_WRITE;
if (!(file = FILE_GetFile( hFile, access, &req.handle ))) goto error;
if (!(file = HANDLE_GetObjPtr( PROCESS_Current(), hFile, K32OBJ_FILE,
access, &req.handle ))) goto error;
if (!GetFileInformationByHandle( hFile, &info )) goto error; if (!GetFileInformationByHandle( hFile, &info )) goto error;
if (!size_high && !size_low) if (!size_high && !size_low)
{ {
...@@ -1218,7 +1204,7 @@ HANDLE32 WINAPI CreateFileMapping32A( ...@@ -1218,7 +1204,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
error: error:
if (reply.handle != -1) CLIENT_CloseHandle( reply.handle ); if (reply.handle != -1) CLIENT_CloseHandle( reply.handle );
if (file) K32OBJ_DecCount( &file->header ); if (file) K32OBJ_DecCount( file );
if (mapping) HeapFree( SystemHeap, 0, mapping ); if (mapping) HeapFree( SystemHeap, 0, mapping );
return 0; return 0;
} }
...@@ -1305,7 +1291,7 @@ static void VIRTUAL_DestroyMapping( K32OBJ *ptr ) ...@@ -1305,7 +1291,7 @@ static void VIRTUAL_DestroyMapping( K32OBJ *ptr )
FILE_MAPPING *mapping = (FILE_MAPPING *)ptr; FILE_MAPPING *mapping = (FILE_MAPPING *)ptr;
assert( ptr->type == K32OBJ_MEM_MAPPED_FILE ); assert( ptr->type == K32OBJ_MEM_MAPPED_FILE );
if (mapping->file) K32OBJ_DecCount( &mapping->file->header ); if (mapping->file) K32OBJ_DecCount( mapping->file );
ptr->type = K32OBJ_UNKNOWN; ptr->type = K32OBJ_UNKNOWN;
HeapFree( SystemHeap, 0, mapping ); HeapFree( SystemHeap, 0, mapping );
} }
...@@ -1347,7 +1333,6 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1347,7 +1333,6 @@ LPVOID WINAPI MapViewOfFileEx(
DWORD count, /* [in] Number of bytes to map */ DWORD count, /* [in] Number of bytes to map */
LPVOID addr /* [in] Suggested starting address for mapped view */ LPVOID addr /* [in] Suggested starting address for mapped view */
) { ) {
FILE_MAPPING *mapping;
FILE_VIEW *view; FILE_VIEW *view;
UINT32 ptr = (UINT32)-1, size = 0; UINT32 ptr = (UINT32)-1, size = 0;
int flags = MAP_PRIVATE; int flags = MAP_PRIVATE;
...@@ -1364,12 +1349,8 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1364,12 +1349,8 @@ LPVOID WINAPI MapViewOfFileEx(
return NULL; return NULL;
} }
if (!(mapping = (FILE_MAPPING *)HANDLE_GetObjPtr( PROCESS_Current(), req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
handle, K32OBJ_MEM_MAPPED_FILE, 0 /* FIXME */ );
K32OBJ_MEM_MAPPED_FILE,
0 /* FIXME */, &req.handle )))
return NULL;
CLIENT_SendRequest( REQ_GET_MAPPING_INFO, -1, 1, &req, sizeof(req) ); CLIENT_SendRequest( REQ_GET_MAPPING_INFO, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &info, sizeof(info), &unix_handle )) if (CLIENT_WaitSimpleReply( &info, sizeof(info), &unix_handle ))
goto error; goto error;
...@@ -1438,13 +1419,11 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1438,13 +1419,11 @@ LPVOID WINAPI MapViewOfFileEx(
goto error; goto error;
} }
if (unix_handle != -1) close( unix_handle ); if (unix_handle != -1) close( unix_handle );
K32OBJ_DecCount( &mapping->header );
return (LPVOID)ptr; return (LPVOID)ptr;
error: error:
if (unix_handle != -1) close( unix_handle ); if (unix_handle != -1) close( unix_handle );
if (ptr != (UINT32)-1) FILE_munmap( (void *)ptr, 0, size ); if (ptr != (UINT32)-1) FILE_munmap( (void *)ptr, 0, size );
K32OBJ_DecCount( &mapping->header );
return NULL; return NULL;
} }
......
...@@ -218,23 +218,18 @@ static void GetDrivePB( CONTEXT *context, int drive ) ...@@ -218,23 +218,18 @@ static void GetDrivePB( CONTEXT *context, int drive )
static void ioctlGetDeviceInfo( CONTEXT *context ) static void ioctlGetDeviceInfo( CONTEXT *context )
{ {
int curr_drive; int curr_drive;
FILE_OBJECT *file; const DOS_DEVICE *dev;
TRACE(int21, "(%d)\n", BX_reg(context)); TRACE(int21, "(%d)\n", BX_reg(context));
RESET_CFLAG(context); RESET_CFLAG(context);
/* DOS device ? */ /* DOS device ? */
if ((file = FILE_GetFile( FILE_GetHandle32(BX_reg(context)), 0, NULL ))) if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )))
{
const DOS_DEVICE *dev = DOSFS_GetDevice( file->unix_name );
FILE_ReleaseFile( file );
if (dev)
{ {
DX_reg(context) = dev->flags; DX_reg(context) = dev->flags;
return; return;
} }
}
/* it seems to be a file */ /* it seems to be a file */
curr_drive = DRIVE_GetCurrentDrive(); curr_drive = DRIVE_GetCurrentDrive();
...@@ -1559,11 +1554,12 @@ void WINAPI DOS3Call( CONTEXT *context ) ...@@ -1559,11 +1554,12 @@ void WINAPI DOS3Call( CONTEXT *context )
case 0x01: case 0x01:
break; break;
case 0x02:{ case 0x02:{
FILE_OBJECT *file; const DOS_DEVICE *dev;
file = FILE_GetFile(FILE_GetHandle32(BX_reg(context)),0,NULL); if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )) &&
if (!strcasecmp(file->unix_name, "SCSIMGR$")) !strcasecmp( dev->name, "SCSIMGR$" ))
{
ASPI_DOS_HandleInt(context); ASPI_DOS_HandleInt(context);
FILE_ReleaseFile( file ); }
break; break;
} }
case 0x05:{ /* IOCTL - WRITE TO BLOCK DEVICE CONTROL CHANNEL */ case 0x05:{ /* IOCTL - WRITE TO BLOCK DEVICE CONTROL CHANNEL */
......
...@@ -1123,12 +1123,13 @@ void VXD_Win32s( CONTEXT *context ) ...@@ -1123,12 +1123,13 @@ void VXD_Win32s( CONTEXT *context )
{ {
DWORD *stack = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET); DWORD *stack = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
HANDLE32 handle = stack[0]; HANDLE32 handle = stack[0];
HANDLE32 new_handle;
TRACE(vxd, "NtDupSection(%lx)\n", (DWORD)handle); TRACE(vxd, "NtDupSection(%lx)\n", (DWORD)handle);
/* Handle is 'duplicated' by incrementing RefCount */ DuplicateHandle( GetCurrentProcess(), handle,
HANDLE_GetObjPtr(PROCESS_Current(), handle, K32OBJ_MEM_MAPPED_FILE, 0,NULL); GetCurrentProcess(), &new_handle,
0, FALSE, DUPLICATE_SAME_ACCESS );
EAX_reg(context) = STATUS_SUCCESS; EAX_reg(context) = STATUS_SUCCESS;
} }
break; break;
......
...@@ -581,7 +581,7 @@ init MAIN_KernelInit ...@@ -581,7 +581,7 @@ init MAIN_KernelInit
563 stub QueryOldestEventLogRecord 563 stub QueryOldestEventLogRecord
564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter 564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency 565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency
566 stub QueueUserAPC 566 stdcall QueueUserAPC(ptr long long) QueueUserAPC
567 register RaiseException() RaiseException 567 register RaiseException() RaiseException
568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsole32A 568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsole32A
569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInput32A 569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInput32A
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -267,7 +268,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle ) ...@@ -267,7 +268,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle )
case 0: /* child */ case 0: /* child */
close( tmpfd[0] ); close( tmpfd[0] );
sprintf( buffer, "%d", tmpfd[1] ); sprintf( buffer, "%d", tmpfd[1] );
/*#define EXEC_SERVER*/ #define EXEC_SERVER
#ifdef EXEC_SERVER #ifdef EXEC_SERVER
execlp( "wineserver", "wineserver", buffer, NULL ); execlp( "wineserver", "wineserver", buffer, NULL );
execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL ); execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
...@@ -299,6 +300,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle ) ...@@ -299,6 +300,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle )
if (thdb->socket != -1) close( thdb->socket ); if (thdb->socket != -1) close( thdb->socket );
thdb->socket = fd[0]; thdb->socket = fd[0];
thdb->seq = 0; /* reset the sequence number for the new fd */ thdb->seq = 0; /* reset the sequence number for the new fd */
fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */
if (thandle) *thandle = reply.thandle; if (thandle) *thandle = reply.thandle;
else if (reply.thandle != -1) CLIENT_CloseHandle( reply.thandle ); else if (reply.thandle != -1) CLIENT_CloseHandle( reply.thandle );
...@@ -365,7 +367,6 @@ int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, in ...@@ -365,7 +367,6 @@ int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, in
{ {
struct dup_handle_request req; struct dup_handle_request req;
struct dup_handle_reply reply; struct dup_handle_reply reply;
int len;
req.src_process = src_process; req.src_process = src_process;
req.src_handle = src_handle; req.src_handle = src_handle;
...@@ -399,24 +400,3 @@ int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit ) ...@@ -399,24 +400,3 @@ int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit )
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
return reply.handle; return reply.handle;
} }
/***********************************************************************
* CLIENT_Select
*/
int CLIENT_Select( int count, int *handles, int flags, int timeout )
{
struct select_request req;
struct select_reply reply;
int len;
req.count = count;
req.flags = flags;
req.timeout = timeout;
CLIENT_SendRequest( REQ_SELECT, -1, 2,
&req, sizeof(req),
handles, count * sizeof(int) );
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
return reply.signaled;
}
...@@ -212,34 +212,6 @@ int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle, ...@@ -212,34 +212,6 @@ int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
} }
/***********************************************************************
* HANDLE_SetObjPtr
*
* Change the object pointer of a handle, and increment the refcount.
* Use with caution!
*/
BOOL32 HANDLE_SetObjPtr( PDB32 *pdb, HANDLE32 handle, K32OBJ *ptr,
DWORD access )
{
BOOL32 ret = FALSE;
SYSTEM_LOCK();
if ((handle > 0) && (handle < pdb->handle_table->count))
{
HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle];
K32OBJ *old_ptr = entry->ptr;
K32OBJ_IncCount( ptr );
entry->access = access;
entry->ptr = ptr;
if (old_ptr) K32OBJ_DecCount( old_ptr );
ret = TRUE;
}
SYSTEM_UNLOCK();
if (!ret) SetLastError( ERROR_INVALID_HANDLE );
return ret;
}
/********************************************************************* /*********************************************************************
* HANDLE_GetAccess * HANDLE_GetAccess
*/ */
......
...@@ -15,10 +15,7 @@ ...@@ -15,10 +15,7 @@
/* The declarations are here to avoid including a lot of unnecessary files */ /* The declarations are here to avoid including a lot of unnecessary files */
extern const K32OBJ_OPS PROCESS_Ops; extern const K32OBJ_OPS PROCESS_Ops;
extern const K32OBJ_OPS THREAD_Ops; extern const K32OBJ_OPS THREAD_Ops;
extern const K32OBJ_OPS FILE_Ops;
extern const K32OBJ_OPS CHANGE_Ops;
extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops; extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops;
extern const K32OBJ_OPS DEVICE_Ops;
extern const K32OBJ_OPS CONSOLE_Ops; extern const K32OBJ_OPS CONSOLE_Ops;
extern const K32OBJ_OPS SNAPSHOT_Ops; extern const K32OBJ_OPS SNAPSHOT_Ops;
...@@ -44,13 +41,13 @@ const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] = ...@@ -44,13 +41,13 @@ const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
&K32OBJ_NullOps, /* K32OBJ_CRITICAL_SECTION */ &K32OBJ_NullOps, /* K32OBJ_CRITICAL_SECTION */
&PROCESS_Ops, /* K32OBJ_PROCESS */ &PROCESS_Ops, /* K32OBJ_PROCESS */
&THREAD_Ops, /* K32OBJ_THREAD */ &THREAD_Ops, /* K32OBJ_THREAD */
&FILE_Ops, /* K32OBJ_FILE */ &K32OBJ_DefaultOps, /* K32OBJ_FILE */
&CHANGE_Ops, /* K32OBJ_CHANGE */ &K32OBJ_DefaultOps, /* K32OBJ_CHANGE */
&CONSOLE_Ops, /* K32OBJ_CONSOLE */ &CONSOLE_Ops, /* K32OBJ_CONSOLE */
&K32OBJ_NullOps, /* K32OBJ_SCREEN_BUFFER */ &K32OBJ_NullOps, /* K32OBJ_SCREEN_BUFFER */
&MEM_MAPPED_FILE_Ops, /* K32OBJ_MEM_MAPPED_FILE */ &MEM_MAPPED_FILE_Ops, /* K32OBJ_MEM_MAPPED_FILE */
&K32OBJ_NullOps, /* K32OBJ_SERIAL */ &K32OBJ_NullOps, /* K32OBJ_SERIAL */
&DEVICE_Ops, /* K32OBJ_DEVICE_IOCTL */ &K32OBJ_NullOps, /* K32OBJ_DEVICE_IOCTL */
&K32OBJ_DefaultOps, /* K32OBJ_PIPE */ &K32OBJ_DefaultOps, /* K32OBJ_PIPE */
&K32OBJ_NullOps, /* K32OBJ_MAILSLOT */ &K32OBJ_NullOps, /* K32OBJ_MAILSLOT */
&K32OBJ_NullOps, /* K32OBJ_TOOLHELP_SNAPSHOT */ &K32OBJ_NullOps, /* K32OBJ_TOOLHELP_SNAPSHOT */
......
...@@ -66,6 +66,33 @@ PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle ) ...@@ -66,6 +66,33 @@ PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
K32OBJ_PROCESS, access, server_handle ); K32OBJ_PROCESS, access, server_handle );
} }
/***********************************************************************
* PROCESS_QueryInfo
*
* Retrieve information about a process
*/
static BOOL32 PROCESS_QueryInfo( HANDLE32 handle,
struct get_process_info_reply *reply )
{
struct get_process_info_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
}
/***********************************************************************
* PROCESS_IsCurrent
*
* Check if a handle is to the current process
*/
BOOL32 PROCESS_IsCurrent( HANDLE32 handle )
{
struct get_process_info_reply reply;
return (PROCESS_QueryInfo( handle, &reply ) &&
(reply.pid == PROCESS_Current()->server_pid));
}
/*********************************************************************** /***********************************************************************
* PROCESS_IdToPDB * PROCESS_IdToPDB
...@@ -599,28 +626,14 @@ LCID WINAPI GetThreadLocale(void) ...@@ -599,28 +626,14 @@ LCID WINAPI GetThreadLocale(void)
*/ */
BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass ) BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
{ {
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL ); struct set_process_info_request req;
if (!pdb) return FALSE; req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
switch (priorityclass) K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
{ if (req.handle == -1) return FALSE;
case NORMAL_PRIORITY_CLASS: req.priority = priorityclass;
pdb->priority = 0x00000008; req.mask = SET_PROCESS_INFO_PRIORITY;
break; CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
case IDLE_PRIORITY_CLASS: return !CLIENT_WaitReply( NULL, NULL, 0 );
pdb->priority = 0x00000004;
break;
case HIGH_PRIORITY_CLASS:
pdb->priority = 0x0000000d;
break;
case REALTIME_PRIORITY_CLASS:
pdb->priority = 0x00000018;
break;
default:
WARN(process,"Unknown priority class %ld\n",priorityclass);
break;
}
K32OBJ_DecCount( &pdb->header );
return TRUE;
} }
...@@ -629,30 +642,39 @@ BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass ) ...@@ -629,30 +642,39 @@ BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
*/ */
DWORD WINAPI GetPriorityClass(HANDLE32 hprocess) DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
{ {
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL ); struct get_process_info_reply reply;
DWORD ret = 0; if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
if (pdb) return reply.priority;
{ }
switch (pdb->priority)
{
case 0x00000008: /***********************************************************************
ret = NORMAL_PRIORITY_CLASS; * SetProcessAffinityMask (KERNEL32.662)
break; */
case 0x00000004: BOOL32 WINAPI SetProcessAffinityMask( HANDLE32 hProcess, DWORD affmask )
ret = IDLE_PRIORITY_CLASS; {
break; struct set_process_info_request req;
case 0x0000000d: req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
ret = HIGH_PRIORITY_CLASS; K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
break; if (req.handle == -1) return FALSE;
case 0x00000018: req.affinity = affmask;
ret = REALTIME_PRIORITY_CLASS; req.mask = SET_PROCESS_INFO_AFFINITY;
break; CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
default: return !CLIENT_WaitReply( NULL, NULL, 0 );
WARN(process,"Unknown priority %ld\n",pdb->priority); }
}
K32OBJ_DecCount( &pdb->header ); /**********************************************************************
} * GetProcessAffinityMask (KERNEL32.373)
return ret; */
BOOL32 WINAPI GetProcessAffinityMask( HANDLE32 hProcess,
LPDWORD lpProcessAffinityMask,
LPDWORD lpSystemAffinityMask )
{
struct get_process_info_reply reply;
if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
return TRUE;
} }
...@@ -721,15 +743,6 @@ DWORD WINAPI GetProcessFlags( DWORD processid ) ...@@ -721,15 +743,6 @@ DWORD WINAPI GetProcessFlags( DWORD processid )
} }
/*********************************************************************** /***********************************************************************
* SetProcessAffinityMask [KERNEL32.662]
*/
BOOL32 WINAPI SetProcessAffinityMask(HANDLE32 hProcess,DWORD affmask)
{
FIXME(process,"(0x%08x,%ld), stub - harmless\n",hProcess,affmask);
return TRUE;
}
/***********************************************************************
* SetProcessWorkingSetSize [KERNEL32.662] * SetProcessWorkingSetSize [KERNEL32.662]
* Sets the min/max working set sizes for a specified process. * Sets the min/max working set sizes for a specified process.
* *
...@@ -867,15 +880,12 @@ BOOL32 WINAPI GetExitCodeProcess( ...@@ -867,15 +880,12 @@ BOOL32 WINAPI GetExitCodeProcess(
LPDWORD lpExitCode) /* [O] address to receive termination status */ LPDWORD lpExitCode) /* [O] address to receive termination status */
{ {
struct get_process_info_reply reply; struct get_process_info_reply reply;
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess, if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &handle, sizeof(handle) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
if (lpExitCode) *lpExitCode = reply.exit_code; if (lpExitCode) *lpExitCode = reply.exit_code;
return TRUE; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* GetProcessHeaps [KERNEL32.376] * GetProcessHeaps [KERNEL32.376]
*/ */
......
...@@ -28,7 +28,6 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles, ...@@ -28,7 +28,6 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
SYSTEM_LOCK(); SYSTEM_LOCK();
wait->count = count; wait->count = count;
wait->signaled = WAIT_FAILED;
wait->wait_all = wait_all; wait->wait_all = wait_all;
for (i = 0, ptr = wait->objs; i < count; i++, ptr++) for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
{ {
...@@ -67,44 +66,12 @@ static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait ) ...@@ -67,44 +66,12 @@ static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
SYSTEM_UNLOCK(); SYSTEM_UNLOCK();
} }
/***********************************************************************
* SYNC_DoWait
*/
static DWORD SYNC_DoWait( DWORD count, const HANDLE32 *handles,
BOOL32 wait_all, DWORD timeout, BOOL32 alertable )
{
WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
if (count > MAXIMUM_WAIT_OBJECTS)
{
SetLastError( ERROR_INVALID_PARAMETER );
return WAIT_FAILED;
}
if (alertable)
FIXME(win32, "alertable not implemented\n" );
if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
wait->signaled = WAIT_FAILED;
else
{
int flags = 0;
if (wait_all) flags |= SELECT_ALL;
if (alertable) flags |= SELECT_ALERTABLE;
if (timeout != INFINITE32) flags |= SELECT_TIMEOUT;
wait->signaled = CLIENT_Select( count, wait->server, flags, timeout );
SYNC_FreeWaitStruct( wait );
}
return wait->signaled;
}
/*********************************************************************** /***********************************************************************
* Sleep (KERNEL32.679) * Sleep (KERNEL32.679)
*/ */
VOID WINAPI Sleep( DWORD timeout ) VOID WINAPI Sleep( DWORD timeout )
{ {
SYNC_DoWait( 0, NULL, FALSE, timeout, FALSE ); WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
} }
/****************************************************************************** /******************************************************************************
...@@ -112,7 +79,7 @@ VOID WINAPI Sleep( DWORD timeout ) ...@@ -112,7 +79,7 @@ VOID WINAPI Sleep( DWORD timeout )
*/ */
DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable ) DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
{ {
DWORD ret = SYNC_DoWait( 0, NULL, FALSE, timeout, alertable ); DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
if (ret != WAIT_IO_COMPLETION) ret = 0; if (ret != WAIT_IO_COMPLETION) ret = 0;
return ret; return ret;
} }
...@@ -123,7 +90,7 @@ DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable ) ...@@ -123,7 +90,7 @@ DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
*/ */
DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout ) DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
{ {
return SYNC_DoWait( 1, &handle, FALSE, timeout, FALSE ); return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
} }
...@@ -133,7 +100,7 @@ DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout ) ...@@ -133,7 +100,7 @@ DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout, DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
BOOL32 alertable ) BOOL32 alertable )
{ {
return SYNC_DoWait( 1, &handle, FALSE, timeout, alertable ); return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
} }
...@@ -143,7 +110,7 @@ DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout, ...@@ -143,7 +110,7 @@ DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles, DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
BOOL32 wait_all, DWORD timeout ) BOOL32 wait_all, DWORD timeout )
{ {
return SYNC_DoWait( count, handles, wait_all, timeout, FALSE ); return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
} }
...@@ -154,7 +121,46 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE32 *handles, ...@@ -154,7 +121,46 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE32 *handles,
BOOL32 wait_all, DWORD timeout, BOOL32 wait_all, DWORD timeout,
BOOL32 alertable ) BOOL32 alertable )
{ {
return SYNC_DoWait( count, handles, wait_all, timeout, alertable ); WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
struct select_request req;
struct select_reply reply;
void *apc[32];
int len;
if (count > MAXIMUM_WAIT_OBJECTS)
{
SetLastError( ERROR_INVALID_PARAMETER );
return WAIT_FAILED;
}
if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
return WAIT_FAILED;
req.count = count;
req.flags = 0;
req.timeout = timeout;
if (wait_all) req.flags |= SELECT_ALL;
if (alertable) req.flags |= SELECT_ALERTABLE;
if (timeout != INFINITE32) req.flags |= SELECT_TIMEOUT;
CLIENT_SendRequest( REQ_SELECT, -1, 2,
&req, sizeof(req),
wait->server, count * sizeof(int) );
CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply),
apc, sizeof(apc) );
if ((reply.signaled == STATUS_USER_APC) && (len > sizeof(reply)))
{
int i;
len -= sizeof(reply);
for (i = 0; i < len / sizeof(void*); i += 2)
{
PAPCFUNC func = (PAPCFUNC)apc[i];
func( (ULONG_PTR)apc[i+1] );
}
}
SYNC_FreeWaitStruct( wait );
return reply.signaled;
} }
......
...@@ -35,18 +35,6 @@ const K32OBJ_OPS THREAD_Ops = ...@@ -35,18 +35,6 @@ const K32OBJ_OPS THREAD_Ops =
/* Is threading code initialized? */ /* Is threading code initialized? */
BOOL32 THREAD_InitDone = FALSE; BOOL32 THREAD_InitDone = FALSE;
/**********************************************************************
* THREAD_GetPtr
*
* Return a pointer to a thread object. The object count must be decremented
* when no longer used.
*/
THDB *THREAD_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
{
return (THDB *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
K32OBJ_THREAD, access, server_handle );
}
/*********************************************************************** /***********************************************************************
* THREAD_Current * THREAD_Current
...@@ -161,7 +149,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16, ...@@ -161,7 +149,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
LPTHREAD_START_ROUTINE start_addr, LPVOID param ) LPTHREAD_START_ROUTINE start_addr, LPVOID param )
{ {
DWORD old_prot; DWORD old_prot;
WORD cs, ds;
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;
...@@ -236,19 +223,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16, ...@@ -236,19 +223,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
if (!(thdb->event = CreateEvent32A( NULL, FALSE, FALSE, NULL ))) goto error; if (!(thdb->event = CreateEvent32A( NULL, FALSE, FALSE, NULL ))) goto error;
thdb->event = ConvertToGlobalHandle( thdb->event ); thdb->event = ConvertToGlobalHandle( thdb->event );
/* Initialize the thread context */
GET_CS(cs);
GET_DS(ds);
thdb->pcontext = &thdb->context;
thdb->context.SegCs = cs;
thdb->context.SegDs = ds;
thdb->context.SegEs = ds;
thdb->context.SegGs = ds;
thdb->context.SegSs = ds;
thdb->context.SegFs = thdb->teb_sel;
thdb->context.Eip = (DWORD)start_addr;
thdb->context.Esp = (DWORD)thdb->teb.stack_top;
PE_InitTls( thdb ); PE_InitTls( thdb );
return thdb; return thdb;
...@@ -588,10 +562,7 @@ BOOL32 WINAPI SetThreadContext( ...@@ -588,10 +562,7 @@ BOOL32 WINAPI SetThreadContext(
HANDLE32 handle, /* [in] Handle to thread with context */ HANDLE32 handle, /* [in] Handle to thread with context */
CONTEXT *context) /* [out] Address of context structure */ CONTEXT *context) /* [out] Address of context structure */
{ {
THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL ); FIXME( thread, "not implemented\n" );
if (!thread) return FALSE;
*context = thread->context;
K32OBJ_DecCount( &thread->header );
return TRUE; return TRUE;
} }
...@@ -606,10 +577,19 @@ BOOL32 WINAPI GetThreadContext( ...@@ -606,10 +577,19 @@ BOOL32 WINAPI GetThreadContext(
HANDLE32 handle, /* [in] Handle to thread with context */ HANDLE32 handle, /* [in] Handle to thread with context */
CONTEXT *context) /* [out] Address of context structure */ CONTEXT *context) /* [out] Address of context structure */
{ {
THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL ); WORD cs, ds;
if (!thread) return FALSE;
*context = thread->context; FIXME( thread, "returning dummy info\n" );
K32OBJ_DecCount( &thread->header );
/* make up some plausible values for segment registers */
GET_CS(cs);
GET_DS(ds);
context->SegCs = cs;
context->SegDs = ds;
context->SegEs = ds;
context->SegGs = ds;
context->SegSs = ds;
context->SegFs = ds;
return TRUE; return TRUE;
} }
...@@ -624,14 +604,14 @@ BOOL32 WINAPI GetThreadContext( ...@@ -624,14 +604,14 @@ BOOL32 WINAPI GetThreadContext(
INT32 WINAPI GetThreadPriority( INT32 WINAPI GetThreadPriority(
HANDLE32 hthread) /* [in] Handle to thread */ HANDLE32 hthread) /* [in] Handle to thread */
{ {
THDB *thread; struct get_thread_info_request req;
INT32 ret; struct get_thread_info_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL ))) K32OBJ_THREAD, THREAD_QUERY_INFORMATION );
CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
return THREAD_PRIORITY_ERROR_RETURN; return THREAD_PRIORITY_ERROR_RETURN;
ret = thread->delta_priority; return reply.priority;
K32OBJ_DecCount( &thread->header );
return ret;
} }
...@@ -646,13 +626,31 @@ BOOL32 WINAPI SetThreadPriority( ...@@ -646,13 +626,31 @@ BOOL32 WINAPI SetThreadPriority(
HANDLE32 hthread, /* [in] Handle to thread */ HANDLE32 hthread, /* [in] Handle to thread */
INT32 priority) /* [in] Thread priority level */ INT32 priority) /* [in] Thread priority level */
{ {
THDB *thread; struct set_thread_info_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
K32OBJ_THREAD, THREAD_SET_INFORMATION );
if (req.handle == -1) return FALSE;
req.priority = priority;
req.mask = SET_THREAD_INFO_PRIORITY;
CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
if (!(thread = THREAD_GetPtr( hthread, THREAD_SET_INFORMATION, NULL )))
return FALSE; /**********************************************************************
thread->delta_priority = priority; * SetThreadAffinityMask (KERNEL32.669)
K32OBJ_DecCount( &thread->header ); */
return TRUE; DWORD WINAPI SetThreadAffinityMask( HANDLE32 hThread, DWORD dwThreadAffinityMask )
{
struct set_thread_info_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hThread,
K32OBJ_THREAD, THREAD_SET_INFORMATION );
if (req.handle == -1) return FALSE;
req.affinity = dwThreadAffinityMask;
req.mask = SET_THREAD_INFO_AFFINITY;
CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitReply( NULL, NULL, 0 )) return 0;
return 1; /* FIXME: should return previous value */
} }
...@@ -688,10 +686,11 @@ BOOL32 WINAPI GetExitCodeThread( ...@@ -688,10 +686,11 @@ BOOL32 WINAPI GetExitCodeThread(
HANDLE32 hthread, /* [in] Handle to thread */ HANDLE32 hthread, /* [in] Handle to thread */
LPDWORD exitcode) /* [out] Address to receive termination status */ LPDWORD exitcode) /* [out] Address to receive termination status */
{ {
struct get_thread_info_request req;
struct get_thread_info_reply reply; struct get_thread_info_reply reply;
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread, req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
K32OBJ_THREAD, THREAD_QUERY_INFORMATION ); K32OBJ_THREAD, THREAD_QUERY_INFORMATION );
CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &handle, sizeof(handle) ); CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE; if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
if (exitcode) *exitcode = reply.exit_code; if (exitcode) *exitcode = reply.exit_code;
return TRUE; return TRUE;
...@@ -710,33 +709,15 @@ BOOL32 WINAPI GetExitCodeThread( ...@@ -710,33 +709,15 @@ BOOL32 WINAPI GetExitCodeThread(
* Already running: 0 * Already running: 0
*/ */
DWORD WINAPI ResumeThread( DWORD WINAPI ResumeThread(
HANDLE32 hthread) /* [in] Indentifies thread to restart */ HANDLE32 hthread) /* [in] Identifies thread to restart */
{ {
THDB *thread; struct resume_thread_request req;
DWORD oldcount; struct resume_thread_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
SYSTEM_LOCK(); K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL ))) CLIENT_SendRequest( REQ_RESUME_THREAD, -1, 1, &req, sizeof(req) );
{ if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
SYSTEM_UNLOCK(); return reply.count;
WARN(thread, "Invalid thread handle\n");
return 0xFFFFFFFF;
}
if ((oldcount = thread->suspend_count) != 0)
{
if (!--thread->suspend_count)
{
if (kill(thread->unix_pid, SIGCONT))
{
WARN(thread, "Unable to CONTinue pid: %04x\n",
thread->unix_pid);
oldcount = 0xFFFFFFFF;
}
}
}
K32OBJ_DecCount(&thread->header);
SYSTEM_UNLOCK();
return oldcount;
} }
...@@ -750,37 +731,28 @@ DWORD WINAPI ResumeThread( ...@@ -750,37 +731,28 @@ DWORD WINAPI ResumeThread(
DWORD WINAPI SuspendThread( DWORD WINAPI SuspendThread(
HANDLE32 hthread) /* [in] Handle to the thread */ HANDLE32 hthread) /* [in] Handle to the thread */
{ {
THDB *thread; struct suspend_thread_request req;
DWORD oldcount; struct suspend_thread_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
SYSTEM_LOCK(); K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL ))) CLIENT_SendRequest( REQ_SUSPEND_THREAD, -1, 1, &req, sizeof(req) );
{ if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
SYSTEM_UNLOCK(); return reply.count;
WARN(thread, "Invalid thread handle\n"); }
return 0xFFFFFFFF;
}
if (!(oldcount = thread->suspend_count))
{
if (thread->unix_pid == getpid())
WARN(thread, "Attempting to suspend myself\n" );
else
{
if (kill(thread->unix_pid, SIGSTOP))
{
WARN(thread, "Unable to STOP pid: %04x\n",
thread->unix_pid);
oldcount = 0xFFFFFFFF;
}
else thread->suspend_count++;
}
}
else thread->suspend_count++;
K32OBJ_DecCount( &thread->header );
SYSTEM_UNLOCK();
return oldcount;
/***********************************************************************
* QueueUserAPC (KERNEL32.566)
*/
DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE32 hthread, ULONG_PTR data )
{
struct queue_apc_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
K32OBJ_THREAD, THREAD_SET_CONTEXT );
req.func = func;
req.param = (void *)data;
CLIENT_SendRequest( REQ_QUEUE_APC, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
} }
......
...@@ -423,3 +423,17 @@ int set_file_time( int handle, time_t access_time, time_t write_time ) ...@@ -423,3 +423,17 @@ int set_file_time( int handle, time_t access_time, time_t write_time )
return 1; return 1;
} }
int file_lock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low )
{
/* FIXME: implement this */
return 1;
}
int file_unlock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low )
{
/* FIXME: implement this */
return 1;
}
...@@ -52,6 +52,10 @@ struct process ...@@ -52,6 +52,10 @@ struct process
int running_threads; /* number of threads running in this process */ int running_threads; /* number of threads running in this process */
struct timeval start_time; /* absolute time at process start */ struct timeval start_time; /* absolute time at process start */
struct timeval end_time; /* absolute time at process end */ struct timeval end_time; /* absolute time at process end */
int priority; /* priority class */
int affinity; /* process affinity mask */
struct object *console_in; /* console input */
struct object *console_out; /* console output */
}; };
static struct process *first_process; static struct process *first_process;
...@@ -84,11 +88,12 @@ static const struct object_ops process_ops = ...@@ -84,11 +88,12 @@ static const struct object_ops process_ops =
/* create a new process */ /* create a new process */
struct process *create_process(void) struct process *create_process(void)
{ {
struct process *process; struct process *process, *parent;
if (!(process = mem_alloc( sizeof(*process) ))) return NULL; if (!(process = mem_alloc( sizeof(*process) ))) return NULL;
if (!copy_handle_table( process, current ? current->process : NULL )) parent = current ? current->process : NULL;
if (!copy_handle_table( process, parent ))
{ {
free( process ); free( process );
return NULL; return NULL;
...@@ -99,6 +104,15 @@ struct process *create_process(void) ...@@ -99,6 +104,15 @@ struct process *create_process(void)
process->thread_list = NULL; process->thread_list = NULL;
process->exit_code = 0x103; /* STILL_ACTIVE */ process->exit_code = 0x103; /* STILL_ACTIVE */
process->running_threads = 0; process->running_threads = 0;
process->priority = NORMAL_PRIORITY_CLASS;
process->affinity = 1;
process->console_in = NULL;
process->console_out = NULL;
if (parent)
{
if (parent->console_in) process->console_in = grab_object( parent->console_in );
if (parent->console_out) process->console_out = grab_object( parent->console_out );
}
if (first_process) first_process->prev = process; if (first_process) first_process->prev = process;
first_process = process; first_process = process;
...@@ -126,6 +140,7 @@ static void process_destroy( struct object *obj ) ...@@ -126,6 +140,7 @@ static void process_destroy( struct object *obj )
if (process->next) process->next->prev = process->prev; if (process->next) process->next->prev = process->prev;
if (process->prev) process->prev->next = process->next; if (process->prev) process->prev->next = process->next;
else first_process = process->next; else first_process = process->next;
free_console( process );
free_handles( process ); free_handles( process );
if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */ if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */
free( process ); free( process );
...@@ -508,4 +523,53 @@ void get_process_info( struct process *process, ...@@ -508,4 +523,53 @@ void get_process_info( struct process *process,
{ {
reply->pid = process; reply->pid = process;
reply->exit_code = process->exit_code; reply->exit_code = process->exit_code;
reply->priority = process->priority;
reply->process_affinity = process->affinity;
reply->system_affinity = 1;
}
/* set all information about a process */
void set_process_info( struct process *process,
struct set_process_info_request *req )
{
if (req->mask & SET_PROCESS_INFO_PRIORITY)
process->priority = req->priority;
if (req->mask & SET_PROCESS_INFO_AFFINITY)
{
if (req->affinity != 1) SET_ERROR( ERROR_INVALID_PARAMETER );
else process->affinity = req->affinity;
}
}
/* allocate a console for this process */
int alloc_console( struct process *process )
{
struct object *obj[2];
if (process->console_in || process->console_out)
{
SET_ERROR( ERROR_ACCESS_DENIED );
return 0;
}
if (!create_console( -1, obj )) return 0;
process->console_in = obj[0];
process->console_out = obj[1];
return 1;
}
/* free the console for this process */
int free_console( struct process *process )
{
if (process->console_in) release_object( process->console_in );
if (process->console_out) release_object( process->console_out );
process->console_in = process->console_out = NULL;
return 1;
}
/* get the process console */
struct object *get_console( struct process *process, int output )
{
struct object *obj;
if (!(obj = output ? process->console_out : process->console_in))
return NULL;
return grab_object( obj );
} }
...@@ -227,7 +227,7 @@ DECL_HANDLER(dup_handle) ...@@ -227,7 +227,7 @@ DECL_HANDLER(dup_handle)
DECL_HANDLER(get_process_info) DECL_HANDLER(get_process_info)
{ {
struct process *process; struct process *process;
struct get_process_info_reply reply = { 0, 0 }; struct get_process_info_reply reply = { 0, 0, 0 };
if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION ))) if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
{ {
...@@ -237,6 +237,19 @@ DECL_HANDLER(get_process_info) ...@@ -237,6 +237,19 @@ DECL_HANDLER(get_process_info)
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_reply( current, -1, 1, &reply, sizeof(reply) );
} }
/* set information about a process */
DECL_HANDLER(set_process_info)
{
struct process *process;
if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
{
set_process_info( process, req );
release_object( process );
}
send_reply( current, -1, 0 );
}
/* fetch information about a thread */ /* fetch information about a thread */
DECL_HANDLER(get_thread_info) DECL_HANDLER(get_thread_info)
{ {
...@@ -251,6 +264,59 @@ DECL_HANDLER(get_thread_info) ...@@ -251,6 +264,59 @@ DECL_HANDLER(get_thread_info)
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_reply( current, -1, 1, &reply, sizeof(reply) );
} }
/* set information about a thread */
DECL_HANDLER(set_thread_info)
{
struct thread *thread;
if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
{
set_thread_info( thread, req );
release_object( thread );
}
send_reply( current, -1, 0 );
}
/* suspend a thread */
DECL_HANDLER(suspend_thread)
{
struct thread *thread;
struct suspend_thread_reply reply = { -1 };
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{
reply.count = suspend_thread( thread );
release_object( thread );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* resume a thread */
DECL_HANDLER(resume_thread)
{
struct thread *thread;
struct resume_thread_reply reply = { -1 };
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{
reply.count = resume_thread( thread );
release_object( thread );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* queue an APC for a thread */
DECL_HANDLER(queue_apc)
{
struct thread *thread;
if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
{
thread_queue_apc( thread, req->func, req->param );
release_object( thread );
}
send_reply( current, -1, 0 );
}
/* open a handle to a process */ /* open a handle to a process */
DECL_HANDLER(open_process) DECL_HANDLER(open_process)
{ {
...@@ -488,6 +554,36 @@ DECL_HANDLER(get_file_info) ...@@ -488,6 +554,36 @@ DECL_HANDLER(get_file_info)
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_reply( current, -1, 1, &reply, sizeof(reply) );
} }
/* lock a region of a file */
DECL_HANDLER(lock_file)
{
struct file *file;
if ((file = get_file_obj( current->process, req->handle, 0 )))
{
file_lock( file, req->offset_high, req->offset_low,
req->count_high, req->count_low );
release_object( file );
}
send_reply( current, -1, 0 );
}
/* unlock a region of a file */
DECL_HANDLER(unlock_file)
{
struct file *file;
if ((file = get_file_obj( current->process, req->handle, 0 )))
{
file_unlock( file, req->offset_high, req->offset_low,
req->count_high, req->count_low );
release_object( file );
}
send_reply( current, -1, 0 );
}
/* create an anonymous pipe */ /* create an anonymous pipe */
DECL_HANDLER(create_pipe) DECL_HANDLER(create_pipe)
{ {
...@@ -512,34 +608,72 @@ DECL_HANDLER(create_pipe) ...@@ -512,34 +608,72 @@ DECL_HANDLER(create_pipe)
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_reply( current, -1, 1, &reply, sizeof(reply) );
} }
/* create a console */ /* allocate a console for the current process */
DECL_HANDLER(create_console) DECL_HANDLER(alloc_console)
{ {
struct create_console_reply reply = { -1, -1 }; alloc_console( current->process );
struct object *obj[2]; send_reply( current, -1, 0 );
if (create_console( fd, obj )) }
{
reply.handle_read = alloc_handle( current->process, obj[0], /* free the console of the current process */
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ, DECL_HANDLER(free_console)
req->inherit ); {
if (reply.handle_read != -1) free_console( current->process );
send_reply( current, -1, 0 );
}
/* open a handle to the process console */
DECL_HANDLER(open_console)
{
struct object *obj;
struct open_console_reply reply = { -1 };
if ((obj = get_console( current->process, req->output )))
{ {
reply.handle_write = alloc_handle( current->process, obj[1], reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE, release_object( obj );
req->inherit );
if (reply.handle_write == -1)
close_handle( current->process, reply.handle_read );
}
release_object( obj[0] );
release_object( obj[1] );
} }
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_reply( current, -1, 1, &reply, sizeof(reply) );
} }
/* set info about a console (output only) */
DECL_HANDLER(set_console_info)
{
char *name = (char *)data;
if (!len) name = NULL;
else CHECK_STRING( "set_console_info", name, len );
set_console_info( req->handle, req, name );
send_reply( current, -1, 0 );
}
/* get info about a console (output only) */
DECL_HANDLER(get_console_info)
{
struct get_console_info_reply reply;
const char *title;
get_console_info( req->handle, &reply, &title );
send_reply( current, -1, 2, &reply, sizeof(reply),
title, title ? strlen(title)+1 : 0 );
}
/* set a console fd */ /* set a console fd */
DECL_HANDLER(set_console_fd) DECL_HANDLER(set_console_fd)
{ {
set_console_fd( req->handle, fd ); set_console_fd( req->handle, fd, req->pid );
send_reply( current, -1, 0 );
}
/* get a console mode (input or output) */
DECL_HANDLER(get_console_mode)
{
struct get_console_mode_reply reply;
get_console_mode( req->handle, &reply.mode );
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* set a console mode (input or output) */
DECL_HANDLER(set_console_mode)
{
set_console_mode( req->handle, req->mode );
send_reply( current, -1, 0 ); send_reply( current, -1, 0 );
} }
...@@ -585,3 +719,18 @@ DECL_HANDLER(get_mapping_info) ...@@ -585,3 +719,18 @@ DECL_HANDLER(get_mapping_info)
int map_fd = get_mapping_info( req->handle, &reply ); int map_fd = get_mapping_info( req->handle, &reply );
send_reply( current, map_fd, 1, &reply, sizeof(reply) ); send_reply( current, map_fd, 1, &reply, sizeof(reply) );
} }
/* create a device */
DECL_HANDLER(create_device)
{
struct object *obj;
struct create_device_reply reply = { -1 };
if ((obj = create_device( req->id )))
{
reply.handle = alloc_handle( current->process, obj,
req->access, req->inherit );
release_object( obj );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
...@@ -38,6 +38,15 @@ struct thread_wait ...@@ -38,6 +38,15 @@ struct thread_wait
struct wait_queue_entry queues[1]; struct wait_queue_entry queues[1];
}; };
/* asynchronous procedure calls */
struct thread_apc
{
void *func; /* function to call in client */
void *param; /* function param */
};
#define MAX_THREAD_APC 16 /* Max outstanding APCs for a thread */
/* thread operations */ /* thread operations */
...@@ -86,11 +95,16 @@ struct thread *create_thread( int fd, void *pid, int *thread_handle, ...@@ -86,11 +95,16 @@ struct thread *create_thread( int fd, void *pid, int *thread_handle,
thread->name = NULL; thread->name = NULL;
thread->mutex = NULL; thread->mutex = NULL;
thread->wait = NULL; thread->wait = NULL;
thread->apc = NULL;
thread->apc_count = 0;
thread->error = 0; thread->error = 0;
thread->state = STARTING; thread->state = STARTING;
thread->exit_code = 0x103; /* STILL_ACTIVE */ thread->exit_code = 0x103; /* STILL_ACTIVE */
thread->next = first_thread; thread->next = first_thread;
thread->prev = NULL; thread->prev = NULL;
thread->priority = THREAD_PRIORITY_NORMAL;
thread->affinity = 1;
thread->suspend = 0;
if (first_thread) first_thread->prev = thread; if (first_thread) first_thread->prev = thread;
first_thread = thread; first_thread = thread;
...@@ -136,6 +150,7 @@ static void destroy_thread( struct object *obj ) ...@@ -136,6 +150,7 @@ static void destroy_thread( struct object *obj )
if (thread->prev) thread->prev->next = thread->next; if (thread->prev) thread->prev->next = thread->next;
else first_thread = thread->next; else first_thread = thread->next;
if (thread->name) free( thread->name ); if (thread->name) free( thread->name );
if (thread->apc) free( thread->apc );
if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */ if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */
free( thread ); free( thread );
} }
...@@ -178,6 +193,49 @@ void get_thread_info( struct thread *thread, ...@@ -178,6 +193,49 @@ void get_thread_info( struct thread *thread,
{ {
reply->pid = thread; reply->pid = thread;
reply->exit_code = thread->exit_code; reply->exit_code = thread->exit_code;
reply->priority = thread->priority;
}
/* set all information about a thread */
void set_thread_info( struct thread *thread,
struct set_thread_info_request *req )
{
if (req->mask & SET_THREAD_INFO_PRIORITY)
thread->priority = req->priority;
if (req->mask & SET_THREAD_INFO_AFFINITY)
{
if (req->affinity != 1) SET_ERROR( ERROR_INVALID_PARAMETER );
else thread->affinity = req->affinity;
}
}
/* suspend a thread */
int suspend_thread( struct thread *thread )
{
int old_count = thread->suspend;
if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
{
if (!thread->suspend++)
{
if (thread->unix_pid) kill( thread->unix_pid, SIGSTOP );
}
}
return old_count;
}
/* resume a thread */
int resume_thread( struct thread *thread )
{
int old_count = thread->suspend;
if (thread->suspend > 0)
{
if (!--thread->suspend)
{
if (thread->unix_pid) kill( thread->unix_pid, SIGCONT );
}
}
return old_count;
} }
/* send a reply to a thread */ /* send a reply to a thread */
...@@ -297,13 +355,12 @@ static int check_wait( struct thread *thread, int *signaled ) ...@@ -297,13 +355,12 @@ static int check_wait( struct thread *thread, int *signaled )
int i; int i;
struct thread_wait *wait = thread->wait; struct thread_wait *wait = thread->wait;
struct wait_queue_entry *entry = wait->queues; struct wait_queue_entry *entry = wait->queues;
struct timeval now;
assert( wait ); assert( wait );
if (wait->flags & SELECT_ALL) if (wait->flags & SELECT_ALL)
{ {
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
if (!entry->obj->ops->signaled( entry->obj, thread )) goto check_timeout; if (!entry->obj->ops->signaled( entry->obj, thread )) goto other_checks;
/* Wait satisfied: tell it to all objects */ /* Wait satisfied: tell it to all objects */
*signaled = 0; *signaled = 0;
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++) for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
...@@ -323,8 +380,16 @@ static int check_wait( struct thread *thread, int *signaled ) ...@@ -323,8 +380,16 @@ static int check_wait( struct thread *thread, int *signaled )
return 1; return 1;
} }
} }
check_timeout:
if (!(wait->flags & SELECT_TIMEOUT)) return 0; other_checks:
if ((wait->flags & SELECT_ALERTABLE) && thread->apc)
{
*signaled = STATUS_USER_APC;
return 1;
}
if (wait->flags & SELECT_TIMEOUT)
{
struct timeval now;
gettimeofday( &now, NULL ); gettimeofday( &now, NULL );
if ((now.tv_sec > wait->timeout.tv_sec) || if ((now.tv_sec > wait->timeout.tv_sec) ||
((now.tv_sec == wait->timeout.tv_sec) && ((now.tv_sec == wait->timeout.tv_sec) &&
...@@ -333,51 +398,64 @@ static int check_wait( struct thread *thread, int *signaled ) ...@@ -333,51 +398,64 @@ static int check_wait( struct thread *thread, int *signaled )
*signaled = STATUS_TIMEOUT; *signaled = STATUS_TIMEOUT;
return 1; return 1;
} }
}
return 0; return 0;
} }
/* sleep on a list of objects */ /* send the select reply to wake up the client */
void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout ) static void send_select_reply( struct thread *thread, int signaled )
{ {
struct select_reply reply; struct select_reply reply;
reply.signaled = signaled;
assert( !thread->wait ); if ((signaled == STATUS_USER_APC) && thread->apc)
reply.signaled = -1;
if (!wait_on( thread, count, handles, flags, timeout )) goto done;
if (!check_wait( thread, &reply.signaled ))
{ {
/* we need to wait */ struct thread_apc *apc = thread->apc;
if (flags & SELECT_TIMEOUT) int len = thread->apc_count * sizeof(*apc);
set_select_timeout( thread->client_fd, &thread->wait->timeout ); thread->apc = NULL;
return; thread->apc_count = 0;
send_reply( thread, -1, 2, &reply, sizeof(reply),
apc, len );
free( apc );
} }
end_wait( thread ); else send_reply( thread, -1, 1, &reply, sizeof(reply) );
done:
send_reply( thread, -1, 1, &reply, sizeof(reply) );
} }
/* attempt to wake up a thread */ /* attempt to wake up a thread */
/* return 1 if OK, 0 if the wait condition is still not satisfied */ /* return 1 if OK, 0 if the wait condition is still not satisfied */
static int wake_thread( struct thread *thread ) static int wake_thread( struct thread *thread )
{ {
struct select_reply reply; int signaled;
if (!check_wait( thread, &reply.signaled )) return 0; if (!check_wait( thread, &signaled )) return 0;
end_wait( thread ); end_wait( thread );
send_reply( thread, -1, 1, &reply, sizeof(reply) ); send_select_reply( thread, signaled );
return 1; return 1;
} }
/* sleep on a list of objects */
void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout )
{
assert( !thread->wait );
if (!wait_on( thread, count, handles, flags, timeout ))
{
/* return an error */
send_select_reply( thread, -1 );
return;
}
if (!wake_thread( thread ))
{
/* we need to wait */
if (flags & SELECT_TIMEOUT)
set_select_timeout( thread->client_fd, &thread->wait->timeout );
}
}
/* timeout for the current thread */ /* timeout for the current thread */
void thread_timeout(void) void thread_timeout(void)
{ {
struct select_reply reply;
assert( current->wait ); assert( current->wait );
reply.signaled = STATUS_TIMEOUT;
end_wait( current ); end_wait( current );
send_reply( current, -1, 1, &reply, sizeof(reply) ); send_select_reply( current, STATUS_TIMEOUT );
} }
/* attempt to wake threads sleeping on the object wait queue */ /* attempt to wake threads sleeping on the object wait queue */
...@@ -396,6 +474,29 @@ void wake_up( struct object *obj, int max ) ...@@ -396,6 +474,29 @@ void wake_up( struct object *obj, int max )
} }
} }
/* queue an async procedure call */
int thread_queue_apc( struct thread *thread, void *func, void *param )
{
struct thread_apc *apc;
if (!func)
{
SET_ERROR( ERROR_INVALID_PARAMETER );
return 0;
}
if (!thread->apc)
{
if (!(thread->apc = mem_alloc( MAX_THREAD_APC * sizeof(*apc) )))
return 0;
thread->apc_count = 0;
}
else if (thread->apc_count >= MAX_THREAD_APC) return 0;
thread->apc[thread->apc_count].func = func;
thread->apc[thread->apc_count].param = param;
thread->apc_count++;
wake_thread( thread );
return 1;
}
/* kill a thread on the spot */ /* kill a thread on the spot */
void kill_thread( struct thread *thread, int exit_code ) void kill_thread( struct thread *thread, int exit_code )
{ {
......
...@@ -30,28 +30,15 @@ ...@@ -30,28 +30,15 @@
#include "winnt.h" #include "winnt.h"
#include "msdos.h" #include "msdos.h"
#include "miscemu.h" #include "miscemu.h"
#include "server.h"
static void DEVICE_Destroy(K32OBJ *dev);
const K32OBJ_OPS DEVICE_Ops = static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode,
{
DEVICE_Destroy /* destroy */
};
/* The device object */
typedef struct
{
K32OBJ header;
struct VxDInfo *info;
} DEVICE_OBJECT;
static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped); LPOVERLAPPED lpOverlapped);
static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_MONODEBG(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
...@@ -59,13 +46,13 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, ...@@ -59,13 +46,13 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
static BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context ); static BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context );
static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped); LPOVERLAPPED lpOverlapped);
static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_VWin32(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
...@@ -80,10 +67,11 @@ struct VxDInfo ...@@ -80,10 +67,11 @@ struct VxDInfo
LPCSTR name; LPCSTR name;
WORD id; WORD id;
BOOL32 (*vxdcall)(DWORD *, DWORD, CONTEXT *); BOOL32 (*vxdcall)(DWORD *, DWORD, CONTEXT *);
BOOL32 (*deviceio)(DEVICE_OBJECT *, DWORD, LPVOID, DWORD, BOOL32 (*deviceio)(DWORD, LPVOID, DWORD,
LPVOID, DWORD, LPDWORD, LPOVERLAPPED); LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
} };
VxDList[] =
static const struct VxDInfo VxDList[] =
{ {
/* Standard VxD IDs */ /* Standard VxD IDs */
{ "VMM", 0x0001, VxDCall_VMM, NULL }, { "VMM", 0x0001, VxDCall_VMM, NULL },
...@@ -266,43 +254,39 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] = ...@@ -266,43 +254,39 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
"<KERNEL32.101>" /* 0x0028 -- What does this do??? */ "<KERNEL32.101>" /* 0x0028 -- What does this do??? */
}; };
HANDLE32 DEVICE_Open(LPCSTR filename) HANDLE32 DEVICE_Open( LPCSTR filename, DWORD access,
LPSECURITY_ATTRIBUTES sa )
{ {
DEVICE_OBJECT *dev; const struct VxDInfo *info;
HANDLE32 handle;
int i;
dev = HeapAlloc( SystemHeap, 0, sizeof(DEVICE_OBJECT) );
if (!dev) return INVALID_HANDLE_VALUE32;
dev->header.type = K32OBJ_DEVICE_IOCTL; for (info = VxDList; info->name; info++)
dev->header.refcount = 1; if (!lstrcmpi32A( info->name, filename ))
dev->info = NULL; return FILE_CreateDevice( info->id | 0x10000, access, sa );
for (i = 0; VxDList[i].name; i++)
if (!lstrcmpi32A(VxDList[i].name, filename))
break;
if (VxDList[i].name)
dev->info = &VxDList[i];
else
FIXME(win32, "Unknown VxD %s\n", filename); FIXME(win32, "Unknown VxD %s\n", filename);
return FILE_CreateDevice( 0x10000, access, sa );
handle = HANDLE_Alloc( PROCESS_Current(), &(dev->header),
FILE_ALL_ACCESS | GENERIC_READ |
GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE, -1 );
/* If the allocation failed, the object is already destroyed */
if (handle == INVALID_HANDLE_VALUE32) dev = NULL;
return handle;
} }
static void DEVICE_Destroy(K32OBJ *obj) static const struct VxDInfo *DEVICE_GetInfo( HANDLE32 handle )
{ {
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj; struct get_file_info_request req;
assert( obj->type == K32OBJ_DEVICE_IOCTL ); struct get_file_info_reply reply;
if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_FILE, 0 )) == -1)
return NULL;
CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
if (!CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) &&
(reply.type == FILE_TYPE_UNKNOWN) &&
(reply.attr & 0x10000))
{
const struct VxDInfo *info;
obj->type = K32OBJ_UNKNOWN; for (info = VxDList; info->name; info++)
HeapFree( SystemHeap, 0, dev ); if (info->id == LOWORD(reply.attr)) break;
return info;
}
return NULL;
} }
/**************************************************************************** /****************************************************************************
...@@ -320,15 +304,14 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, ...@@ -320,15 +304,14 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped) LPOVERLAPPED lpOverlapped)
{ {
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)HANDLE_GetObjPtr( const struct VxDInfo *info;
PROCESS_Current(), hDevice, K32OBJ_DEVICE_IOCTL, 0 /*FIXME*/, NULL );
TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n", TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer, hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped
); );
if (!dev) if (!(info = DEVICE_GetInfo( hDevice )))
{ {
SetLastError( ERROR_INVALID_PARAMETER ); SetLastError( ERROR_INVALID_PARAMETER );
return FALSE; return FALSE;
...@@ -337,9 +320,9 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, ...@@ -337,9 +320,9 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
/* Check if this is a user defined control code for a VxD */ /* Check if this is a user defined control code for a VxD */
if( HIWORD( dwIoControlCode ) == 0 ) if( HIWORD( dwIoControlCode ) == 0 )
{ {
if ( dev->info && dev->info->deviceio ) if ( info->deviceio )
{ {
return dev->info->deviceio( dev, dwIoControlCode, return info->deviceio( dwIoControlCode,
lpvInBuffer, cbInBuffer, lpvInBuffer, cbInBuffer,
lpvOutBuffer, cbOutBuffer, lpvOutBuffer, cbOutBuffer,
lpcbBytesReturned, lpOverlapped ); lpcbBytesReturned, lpOverlapped );
...@@ -348,7 +331,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, ...@@ -348,7 +331,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
{ {
/* FIXME: Set appropriate error */ /* FIXME: Set appropriate error */
FIXME( win32, "Unimplemented control %ld for VxD device %s\n", FIXME( win32, "Unimplemented control %ld for VxD device %s\n",
dwIoControlCode, dev->info ? dev->info->name : "???" ); dwIoControlCode, info->name ? info->name : "???" );
} }
} }
else else
...@@ -403,8 +386,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode, ...@@ -403,8 +386,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
/*********************************************************************** /***********************************************************************
* DeviceIo_VTDAPI * DeviceIo_VTDAPI
*/ */
static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped) LPOVERLAPPED lpOverlapped)
...@@ -765,15 +747,14 @@ static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut) ...@@ -765,15 +747,14 @@ static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
/* FIXME: pOut->ar_pad ignored */ /* FIXME: pOut->ar_pad ignored */
} }
static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped) LPOVERLAPPED lpOverlapped)
{ {
BOOL32 retv = TRUE; BOOL32 retv = TRUE;
TRACE(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n", TRACE(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dev,dwIoControlCode, dwIoControlCode,
lpvInBuffer,cbInBuffer, lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer, lpvOutBuffer,cbOutBuffer,
lpcbBytesReturned, lpcbBytesReturned,
...@@ -866,7 +847,7 @@ static void CONTEXT_2_DIOCRegs( CONTEXT *pCxt, DIOC_REGISTERS *pOut ) ...@@ -866,7 +847,7 @@ static void CONTEXT_2_DIOCRegs( CONTEXT *pCxt, DIOC_REGISTERS *pOut )
} }
static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_VWin32(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
...@@ -928,7 +909,7 @@ static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode, ...@@ -928,7 +909,7 @@ static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
/* this is used by some Origin games */ /* this is used by some Origin games */
static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, static BOOL32 DeviceIo_MONODEBG(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned, LPDWORD lpcbBytesReturned,
...@@ -942,8 +923,8 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, ...@@ -942,8 +923,8 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
fprintf(stderr,"MONODEBG: %s\n",debugstr_a(lpvInBuffer)); fprintf(stderr,"MONODEBG: %s\n",debugstr_a(lpvInBuffer));
break; break;
default: default:
FIXME(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n", FIXME(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dev,dwIoControlCode, dwIoControlCode,
lpvInBuffer,cbInBuffer, lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer, lpvOutBuffer,cbOutBuffer,
lpcbBytesReturned, lpcbBytesReturned,
......
...@@ -20,45 +20,6 @@ ...@@ -20,45 +20,6 @@
/********************************************************************** /**********************************************************************
* GetProcessAffinityMask
*/
BOOL32 WINAPI GetProcessAffinityMask(HANDLE32 hProcess,
LPDWORD lpProcessAffinityMask,
LPDWORD lpSystemAffinityMask)
{
TRACE(task,"(%x,%lx,%lx)\n",
hProcess,(lpProcessAffinityMask?*lpProcessAffinityMask:0),
(lpSystemAffinityMask?*lpSystemAffinityMask:0));
/* It is definitely important for a process to know on what processor
it is running :-) */
if(lpProcessAffinityMask)
*lpProcessAffinityMask=1;
if(lpSystemAffinityMask)
*lpSystemAffinityMask=1;
return TRUE;
}
/**********************************************************************
* SetThreadAffinityMask
* Works now like the Windows95 (no MP support) version
*/
BOOL32 WINAPI SetThreadAffinityMask(HANDLE32 hThread, DWORD dwThreadAffinityMask)
{
THDB *thdb = THREAD_GetPtr( hThread, THREAD_SET_INFORMATION, NULL );
if (!thdb)
return FALSE;
if (dwThreadAffinityMask!=1) {
WARN(thread,"(%d,%ld): only 1 processor supported.\n",
(int)hThread,dwThreadAffinityMask);
K32OBJ_DecCount((K32OBJ*)thdb);
return FALSE;
}
K32OBJ_DecCount((K32OBJ*)thdb);
return TRUE;
}
/**********************************************************************
* ContinueDebugEvent [KERNEL32.146] * ContinueDebugEvent [KERNEL32.146]
*/ */
BOOL32 WINAPI ContinueDebugEvent(DWORD pid,DWORD tid,DWORD contstatus) { BOOL32 WINAPI ContinueDebugEvent(DWORD pid,DWORD tid,DWORD contstatus) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment