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 @@
#include "server.h"
#include "debug.h"
static void CHANGE_Destroy( K32OBJ *obj );
const K32OBJ_OPS CHANGE_Ops =
{
CHANGE_Destroy /* destroy */
};
/* The change notification object */
typedef struct
{
K32OBJ header;
LPSTR lpPathName;
BOOL32 bWatchSubtree;
DWORD dwNotifyFilter;
BOOL32 notify;
} 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)
......@@ -76,15 +48,8 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName,
CLIENT_CloseHandle( reply.handle );
return INVALID_HANDLE_VALUE32;
}
change->header.type = K32OBJ_CHANGE;
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,
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE /*FIXME*/,
FALSE, reply.handle );
......@@ -109,20 +74,10 @@ HANDLE32 WINAPI FindFirstChangeNotification32W( LPCWSTR lpPathName,
*/
BOOL32 WINAPI FindNextChangeNotification( HANDLE32 handle )
{
CHANGE_OBJECT *change;
SYSTEM_LOCK();
if (!(change = (CHANGE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(),
handle, K32OBJ_CHANGE,
0 /*FIXME*/, NULL )) )
{
SYSTEM_UNLOCK();
if (HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_FILE, 0 ) == -1)
return FALSE;
}
change->notify = FALSE;
K32OBJ_DecCount( &change->header );
SYSTEM_UNLOCK();
/* FIXME: do something */
return TRUE;
}
......
......@@ -26,6 +26,8 @@
#include "heap.h"
#include "msdos.h"
#include "syslevel.h"
#include "server.h"
#include "process.h"
#include "debug.h"
/* Define the VFAT ioctl to get both short and long file names */
......@@ -602,6 +604,30 @@ const DOS_DEVICE *DOSFS_GetDevice( const char *name )
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
*
......@@ -651,10 +677,7 @@ HFILE32 DOSFS_OpenDevice( const char *name, DWORD access )
if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
!strcmp(DOSFS_Devices[i].name,"HPSCAN"))
{
/* FIXME: should keep the name somewhere */
return FILE_CreateFile( "/dev/null", access,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, -1 );
return FILE_CreateDevice( i, access, NULL );
}
FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name);
return HFILE_ERROR32;
......
......@@ -46,75 +46,18 @@
#define MAP_ANON MAP_ANONYMOUS
#endif
static void FILE_Destroy( K32OBJ *obj );
const K32OBJ_OPS FILE_Ops =
/* The file object */
typedef struct
{
FILE_Destroy /* destroy */
};
struct DOS_FILE_LOCK {
struct DOS_FILE_LOCK * next;
DWORD base;
DWORD len;
DWORD processId;
FILE_OBJECT * dos_file;
char * unix_name;
};
K32OBJ header;
} FILE_OBJECT;
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 */
#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
*
* Convert OF_* mode into flags for CreateFile.
......@@ -391,7 +334,6 @@ HFILE32 FILE_DupUnixHandle( int fd, DWORD access )
}
file->header.type = K32OBJ_FILE;
file->header.refcount = 0;
file->unix_name = NULL;
return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
req.inherit, reply.handle );
}
......@@ -448,7 +390,39 @@ HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
}
file->header.type = K32OBJ_FILE;
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,
req.inherit, reply.handle );
}
......@@ -487,7 +461,6 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
DWORD attributes, HANDLE32 template )
{
DOS_FULL_NAME full_name;
HANDLE32 to_dup = HFILE_ERROR32;
if (!filename)
{
......@@ -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 (!strncmp(filename, "\\\\", 2))
......@@ -517,23 +491,9 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
return HFILE_ERROR32;
}
/* If the name is either CONIN$ or CONOUT$, give them duplicated stdin
* or stdout, respectively. The lower case version is also allowed. Most likely
* this should be a case ignore string compare.
*/
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;
}
/* Open a console for CONIN$ or CONOUT$ */
if (!lstrcmpi32A(filename, "CONIN$")) return CONSOLE_OpenHandle( FALSE, access, sa );
if (!lstrcmpi32A(filename, "CONOUT$")) return CONSOLE_OpenHandle( TRUE, access, sa );
if (DOSFS_GetDevice( filename ))
{
......@@ -1979,6 +1939,64 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile,
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
* on the pid. Inside of wine there can be multiple WINE processes
* that share the same unix pid.
......@@ -1994,6 +2012,7 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
processId = GetCurrentProcessId();
/* check if lock overlaps a current lock for the same file */
#if 0
for (curr = locks; curr; curr = curr->next) {
if (strcmp(curr->unix_name, file->unix_name) == 0) {
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)
}
}
}
#endif
curr = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE_LOCK) );
curr->processId = GetCurrentProcessId();
curr->base = f->l_start;
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->dos_file = file;
locks = curr;
......@@ -2029,7 +2049,7 @@ static void DOS_RemoveFileLocks(FILE_OBJECT *file)
if ((*curr)->dos_file == file) {
rem = *curr;
*curr = (*curr)->next;
HeapFree( SystemHeap, 0, rem->unix_name );
/* HeapFree( SystemHeap, 0, rem->unix_name );*/
HeapFree( SystemHeap, 0, rem );
}
else
......@@ -2052,7 +2072,7 @@ static BOOL32 DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
/* this is the same lock */
rem = *curr;
*curr = (*curr)->next;
HeapFree( SystemHeap, 0, rem->unix_name );
/* HeapFree( SystemHeap, 0, rem->unix_name );*/
HeapFree( SystemHeap, 0, rem );
return TRUE;
}
......@@ -2151,6 +2171,7 @@ BOOL32 WINAPI UnlockFile(
#endif
return TRUE;
}
#endif
/**************************************************************************
* GetFileAttributesEx32A [KERNEL32.874]
......
#ifndef __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
......@@ -13,13 +13,6 @@
#define MAX_PATHNAME_LEN 1024
/* The file object */
typedef struct
{
K32OBJ header;
char *unix_name;
} FILE_OBJECT;
/* Definition of a full DOS file name */
typedef struct
{
......@@ -39,9 +32,6 @@ typedef struct
/* 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 HFILE32 FILE_DupUnixHandle( int fd, DWORD access );
extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
......@@ -49,6 +39,8 @@ extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation,
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,
DWORD size_high, DWORD size_low,
DWORD offset_high, DWORD offset_low,
......@@ -71,6 +63,7 @@ extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
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 BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
INT32 long_len, LPSTR short_buf,
......
......@@ -139,8 +139,6 @@ extern K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle,
int *server_handle );
extern int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
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 );
/* Global handle macros */
......@@ -153,6 +151,7 @@ extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
/* scheduler/process.c */
extern BOOL32 PROCESS_Init( void );
extern PDB32 *PROCESS_Current(void);
extern BOOL32 PROCESS_IsCurrent( HANDLE32 handle );
extern PDB32 *PROCESS_Initial(void);
extern PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle );
extern PDB32 *PROCESS_IdToPDB( DWORD id );
......
......@@ -94,9 +94,24 @@ struct get_process_info_reply
{
void* pid; /* server process id */
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 */
struct get_thread_info_request
{
......@@ -106,6 +121,50 @@ struct get_thread_info_reply
{
void* pid; /* server thread id */
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
struct select_reply
{
int signaled; /* signaled handle */
/* void* apcs[]; */ /* async procedures to call */
};
#define SELECT_ALL 1
#define SELECT_ALERTABLE 2
......@@ -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 */
struct create_pipe_request
{
......@@ -350,15 +432,28 @@ struct create_pipe_reply
};
/* Create a console */
struct create_console_request
/* Allocate a console for the current process */
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 */
};
struct create_console_reply
struct open_console_reply
{
int handle_read; /* handle to read from the console */
int handle_write; /* handle to write to the console */
int handle; /* handle to the console */
};
......@@ -366,6 +461,52 @@ struct create_console_reply
struct set_console_fd_request
{
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
};
/* 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 */
#ifndef __WINE_SERVER__
......@@ -438,7 +592,6 @@ extern int CLIENT_CloseHandle( int handle );
extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process,
int dst_handle, DWORD access, BOOL32 inherit, DWORD options );
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_H */
......@@ -133,6 +133,11 @@ extern void remove_process_thread( struct process *process,
extern void kill_process( struct process *process, int exit_code );
extern void get_process_info( struct process *process,
struct get_process_info_reply *reply );
extern void set_process_info( struct process *process,
struct set_process_info_request *req );
extern int alloc_console( struct process *process );
extern int free_console( struct process *process );
extern struct object *get_console( struct process *process, int output );
/* handle functions */
......@@ -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 truncate_file( int handle );
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);
......@@ -195,7 +204,13 @@ extern int create_pipe( struct object *obj[2] );
/* console functions */
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 */
......@@ -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 );
/* device functions */
extern struct object *create_device( int id );
extern int debug_level;
#endif /* __WINE_SERVER_OBJECT_H */
......@@ -11,7 +11,12 @@ enum request
REQ_TERMINATE_PROCESS,
REQ_TERMINATE_THREAD,
REQ_GET_PROCESS_INFO,
REQ_SET_PROCESS_INFO,
REQ_GET_THREAD_INFO,
REQ_SET_THREAD_INFO,
REQ_SUSPEND_THREAD,
REQ_RESUME_THREAD,
REQ_QUEUE_APC,
REQ_CLOSE_HANDLE,
REQ_DUP_HANDLE,
REQ_OPEN_PROCESS,
......@@ -31,12 +36,21 @@ enum request
REQ_SET_FILE_TIME,
REQ_FLUSH_FILE,
REQ_GET_FILE_INFO,
REQ_LOCK_FILE,
REQ_UNLOCK_FILE,
REQ_CREATE_PIPE,
REQ_CREATE_CONSOLE,
REQ_ALLOC_CONSOLE,
REQ_FREE_CONSOLE,
REQ_OPEN_CONSOLE,
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_MAPPING,
REQ_GET_MAPPING_INFO,
REQ_CREATE_DEVICE,
REQ_NB_REQUESTS
};
......@@ -51,7 +65,12 @@ DECL_HANDLER(init_thread);
DECL_HANDLER(terminate_process);
DECL_HANDLER(terminate_thread);
DECL_HANDLER(get_process_info);
DECL_HANDLER(set_process_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(dup_handle);
DECL_HANDLER(open_process);
......@@ -71,12 +90,21 @@ DECL_HANDLER(truncate_file);
DECL_HANDLER(set_file_time);
DECL_HANDLER(flush_file);
DECL_HANDLER(get_file_info);
DECL_HANDLER(lock_file);
DECL_HANDLER(unlock_file);
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(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_mapping);
DECL_HANDLER(get_mapping_info);
DECL_HANDLER(create_device);
static const struct handler {
void (*handler)();
......@@ -88,7 +116,12 @@ static const struct handler {
{ (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
{ (void(*)())req_terminate_thread, sizeof(struct terminate_thread_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_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_dup_handle, sizeof(struct dup_handle_request) },
{ (void(*)())req_open_process, sizeof(struct open_process_request) },
......@@ -108,12 +141,21 @@ static const struct handler {
{ (void(*)())req_set_file_time, sizeof(struct set_file_time_request) },
{ (void(*)())req_flush_file, sizeof(struct flush_file_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_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_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_mapping, sizeof(struct create_mapping_request) },
{ (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
{ (void(*)())req_create_device, sizeof(struct create_device_request) },
};
#endif /* WANT_REQUEST_HANDLERS */
......
......@@ -17,6 +17,7 @@
struct process;
struct thread_wait;
struct thread_apc;
struct mutex;
enum run_state { STARTING, RUNNING, TERMINATED };
......@@ -31,11 +32,16 @@ struct thread
struct process *process;
struct mutex *mutex; /* list of currently owned mutexes */
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 */
enum run_state state; /* running state */
int exit_code; /* thread exit code */
int client_fd; /* client fd for socket communications */
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) */
char *name;
};
......@@ -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 void get_thread_info( struct thread *thread,
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,
int n, ... /* arg_1, len_1, ..., arg_n, len_n */ );
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 int thread_queue_apc( struct thread *thread, void *func, void *param );
extern void kill_thread( struct thread *thread, int exit_code );
extern void thread_killed( struct thread *thread, int exit_code );
extern void thread_timeout(void);
......
......@@ -61,7 +61,6 @@ typedef struct _TEB
typedef struct
{
DWORD count; /* Count of valid objects */
DWORD signaled; /* Index of signaled object (or WAIT_FAILED)*/
BOOL32 wait_all; /* Wait for all objects flag */
K32OBJ *objs[MAXIMUM_WAIT_OBJECTS]; /* Object pointers */
int server[MAXIMUM_WAIT_OBJECTS]; /* Server handles */
......@@ -110,8 +109,7 @@ typedef struct _THDB
CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */
DWORD unknown6[2]; /* 1f8 Unknown */
/* The following are Wine-specific fields */
CONTEXT context; /* 200 Thread context */
WAIT_STRUCT wait_struct; /* Event wait structure */
WAIT_STRUCT wait_struct; /* 200 Event wait structure */
int socket; /* Socket for server communication */
unsigned int seq; /* Server sequence number */
void *server_tid; /* Server id for this thread */
......@@ -155,7 +153,6 @@ extern THDB *THREAD_Current(void);
extern BOOL32 THREAD_IsWin16( THDB *thdb );
extern THDB *THREAD_IdToTHDB( DWORD id );
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_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
extern DWORD THREAD_TlsAlloc( THDB *thread );
......
......@@ -273,6 +273,8 @@ typedef struct tagCOMMTIMEOUTS {
#pragma pack(4)
typedef VOID (CALLBACK *PAPCFUNC)(ULONG_PTR);
BOOL32 WINAPI ClearCommError(INT32,LPDWORD,LPCOMSTAT);
BOOL32 WINAPI BuildCommDCB32A(LPCSTR,LPDCB32);
BOOL32 WINAPI BuildCommDCB32W(LPCWSTR,LPDCB32);
......@@ -305,8 +307,9 @@ void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
void WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit);
HANDLE32 WINAPI OpenProcess(DWORD access, BOOL32 inherit, DWORD id);
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);
BOOL32 WINAPI SetProcessWorkingSetSize(HANDLE32,DWORD,DWORD);
BOOL32 WINAPI TerminateProcess(HANDLE32,DWORD);
BOOL32 WINAPI TerminateThread(HANDLE32,DWORD);
......
......@@ -4186,6 +4186,7 @@ BOOL32 WINAPI SetPriorityClass(HANDLE32,DWORD);
BOOL32 WINAPI SetStdHandle(DWORD,HANDLE32);
BOOL32 WINAPI SetSystemPowerState(BOOL32,BOOL32);
BOOL32 WINAPI SetSystemTime(const SYSTEMTIME*);
DWORD WINAPI SetThreadAffinityMask(HANDLE32,DWORD);
BOOL32 WINAPI SetThreadPriority(HANDLE32,INT32);
BOOL32 WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
VOID WINAPI Sleep(DWORD);
......
......@@ -89,6 +89,8 @@ typedef unsigned short WCHAR;
typedef unsigned short BOOL16;
typedef int BOOL32;
typedef double DATE;
typedef long LONG_PTR;
typedef unsigned long ULONG_PTR;
#ifdef __i386__
typedef double LONGLONG;
typedef double ULONGLONG;
......
......@@ -31,7 +31,7 @@
typedef struct
{
K32OBJ header;
FILE_OBJECT *file;
K32OBJ *file;
} FILE_MAPPING;
/* File view */
......@@ -810,20 +810,12 @@ BOOL32 WINAPI VirtualProtectEx(
LPVOID addr, /* [in] Address of region of committed pages */
DWORD size, /* [in] Size of region */
DWORD new_prot, /* [in] Desired access protection */
LPDWORD old_prot /* [out] Address of variable to get old protection */
) {
BOOL32 ret = FALSE;
PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_VM_OPERATION, NULL );
if (pdb)
{
if (pdb == PROCESS_Current())
ret = VirtualProtect( addr, size, new_prot, old_prot );
else
LPDWORD old_prot /* [out] Address of variable to get old protection */ )
{
if (PROCESS_IsCurrent( handle ))
return VirtualProtect( addr, size, new_prot, old_prot );
ERR(virtual,"Unsupported on other process\n");
K32OBJ_DecCount( &pdb->header );
}
return ret;
return FALSE;
}
......@@ -907,20 +899,12 @@ DWORD WINAPI VirtualQueryEx(
HANDLE32 handle, /* [in] Handle of process */
LPCVOID addr, /* [in] Address of region */
LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
DWORD len /* [in] Size of buffer */
) {
DWORD ret = len;
PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_QUERY_INFORMATION, NULL );
if (pdb)
{
if (pdb == PROCESS_Current())
ret = VirtualQuery( addr, info, len );
else
DWORD len /* [in] Size of buffer */ )
{
if (PROCESS_IsCurrent( handle ))
return VirtualQuery( addr, info, len );
ERR(virtual,"Unsupported on other process\n");
K32OBJ_DecCount( &pdb->header );
}
return ret;
return 0;
}
......@@ -1079,7 +1063,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
LPCSTR name /* [in] Name of file-mapping object */ )
{
FILE_MAPPING *mapping = NULL;
FILE_OBJECT *file;
K32OBJ *file;
struct create_mapping_request req;
struct create_mapping_reply reply = { -1 };
HANDLE32 handle;
......@@ -1172,7 +1156,9 @@ HANDLE32 WINAPI CreateFileMapping32A(
((protect & 0xff) == PAGE_EXECUTE_READWRITE) ||
((protect & 0xff) == PAGE_EXECUTE_WRITECOPY))
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 (!size_high && !size_low)
{
......@@ -1218,7 +1204,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
error:
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 );
return 0;
}
......@@ -1305,7 +1291,7 @@ static void VIRTUAL_DestroyMapping( K32OBJ *ptr )
FILE_MAPPING *mapping = (FILE_MAPPING *)ptr;
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;
HeapFree( SystemHeap, 0, mapping );
}
......@@ -1347,7 +1333,6 @@ LPVOID WINAPI MapViewOfFileEx(
DWORD count, /* [in] Number of bytes to map */
LPVOID addr /* [in] Suggested starting address for mapped view */
) {
FILE_MAPPING *mapping;
FILE_VIEW *view;
UINT32 ptr = (UINT32)-1, size = 0;
int flags = MAP_PRIVATE;
......@@ -1364,12 +1349,8 @@ LPVOID WINAPI MapViewOfFileEx(
return NULL;
}
if (!(mapping = (FILE_MAPPING *)HANDLE_GetObjPtr( PROCESS_Current(),
handle,
K32OBJ_MEM_MAPPED_FILE,
0 /* FIXME */, &req.handle )))
return NULL;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
K32OBJ_MEM_MAPPED_FILE, 0 /* FIXME */ );
CLIENT_SendRequest( REQ_GET_MAPPING_INFO, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &info, sizeof(info), &unix_handle ))
goto error;
......@@ -1438,13 +1419,11 @@ LPVOID WINAPI MapViewOfFileEx(
goto error;
}
if (unix_handle != -1) close( unix_handle );
K32OBJ_DecCount( &mapping->header );
return (LPVOID)ptr;
error:
if (unix_handle != -1) close( unix_handle );
if (ptr != (UINT32)-1) FILE_munmap( (void *)ptr, 0, size );
K32OBJ_DecCount( &mapping->header );
return NULL;
}
......
......@@ -218,23 +218,18 @@ static void GetDrivePB( CONTEXT *context, int drive )
static void ioctlGetDeviceInfo( CONTEXT *context )
{
int curr_drive;
FILE_OBJECT *file;
const DOS_DEVICE *dev;
TRACE(int21, "(%d)\n", BX_reg(context));
RESET_CFLAG(context);
/* DOS device ? */
if ((file = FILE_GetFile( FILE_GetHandle32(BX_reg(context)), 0, NULL )))
{
const DOS_DEVICE *dev = DOSFS_GetDevice( file->unix_name );
FILE_ReleaseFile( file );
if (dev)
if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )))
{
DX_reg(context) = dev->flags;
return;
}
}
/* it seems to be a file */
curr_drive = DRIVE_GetCurrentDrive();
......@@ -1559,11 +1554,12 @@ void WINAPI DOS3Call( CONTEXT *context )
case 0x01:
break;
case 0x02:{
FILE_OBJECT *file;
file = FILE_GetFile(FILE_GetHandle32(BX_reg(context)),0,NULL);
if (!strcasecmp(file->unix_name, "SCSIMGR$"))
const DOS_DEVICE *dev;
if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )) &&
!strcasecmp( dev->name, "SCSIMGR$" ))
{
ASPI_DOS_HandleInt(context);
FILE_ReleaseFile( file );
}
break;
}
case 0x05:{ /* IOCTL - WRITE TO BLOCK DEVICE CONTROL CHANNEL */
......
......@@ -1123,12 +1123,13 @@ void VXD_Win32s( CONTEXT *context )
{
DWORD *stack = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
HANDLE32 handle = stack[0];
HANDLE32 new_handle;
TRACE(vxd, "NtDupSection(%lx)\n", (DWORD)handle);
/* Handle is 'duplicated' by incrementing RefCount */
HANDLE_GetObjPtr(PROCESS_Current(), handle, K32OBJ_MEM_MAPPED_FILE, 0,NULL);
DuplicateHandle( GetCurrentProcess(), handle,
GetCurrentProcess(), &new_handle,
0, FALSE, DUPLICATE_SAME_ACCESS );
EAX_reg(context) = STATUS_SUCCESS;
}
break;
......
......@@ -581,7 +581,7 @@ init MAIN_KernelInit
563 stub QueryOldestEventLogRecord
564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency
566 stub QueueUserAPC
566 stdcall QueueUserAPC(ptr long long) QueueUserAPC
567 register RaiseException() RaiseException
568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsole32A
569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInput32A
......
......@@ -6,6 +6,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
......@@ -267,7 +268,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle )
case 0: /* child */
close( tmpfd[0] );
sprintf( buffer, "%d", tmpfd[1] );
/*#define EXEC_SERVER*/
#define EXEC_SERVER
#ifdef EXEC_SERVER
execlp( "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 )
if (thdb->socket != -1) close( thdb->socket );
thdb->socket = fd[0];
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;
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
{
struct dup_handle_request req;
struct dup_handle_reply reply;
int len;
req.src_process = src_process;
req.src_handle = src_handle;
......@@ -399,24 +400,3 @@ int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit )
CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
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,
}
/***********************************************************************
* 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
*/
......
......@@ -15,10 +15,7 @@
/* The declarations are here to avoid including a lot of unnecessary files */
extern const K32OBJ_OPS PROCESS_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 DEVICE_Ops;
extern const K32OBJ_OPS CONSOLE_Ops;
extern const K32OBJ_OPS SNAPSHOT_Ops;
......@@ -44,13 +41,13 @@ const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
&K32OBJ_NullOps, /* K32OBJ_CRITICAL_SECTION */
&PROCESS_Ops, /* K32OBJ_PROCESS */
&THREAD_Ops, /* K32OBJ_THREAD */
&FILE_Ops, /* K32OBJ_FILE */
&CHANGE_Ops, /* K32OBJ_CHANGE */
&K32OBJ_DefaultOps, /* K32OBJ_FILE */
&K32OBJ_DefaultOps, /* K32OBJ_CHANGE */
&CONSOLE_Ops, /* K32OBJ_CONSOLE */
&K32OBJ_NullOps, /* K32OBJ_SCREEN_BUFFER */
&MEM_MAPPED_FILE_Ops, /* K32OBJ_MEM_MAPPED_FILE */
&K32OBJ_NullOps, /* K32OBJ_SERIAL */
&DEVICE_Ops, /* K32OBJ_DEVICE_IOCTL */
&K32OBJ_NullOps, /* K32OBJ_DEVICE_IOCTL */
&K32OBJ_DefaultOps, /* K32OBJ_PIPE */
&K32OBJ_NullOps, /* K32OBJ_MAILSLOT */
&K32OBJ_NullOps, /* K32OBJ_TOOLHELP_SNAPSHOT */
......
......@@ -66,6 +66,33 @@ PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *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
......@@ -599,28 +626,14 @@ LCID WINAPI GetThreadLocale(void)
*/
BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
{
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
if (!pdb) return FALSE;
switch (priorityclass)
{
case NORMAL_PRIORITY_CLASS:
pdb->priority = 0x00000008;
break;
case IDLE_PRIORITY_CLASS:
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;
struct set_process_info_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
if (req.handle == -1) return FALSE;
req.priority = priorityclass;
req.mask = SET_PROCESS_INFO_PRIORITY;
CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
......@@ -629,30 +642,39 @@ BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
*/
DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
{
PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
DWORD ret = 0;
if (pdb)
{
switch (pdb->priority)
{
case 0x00000008:
ret = NORMAL_PRIORITY_CLASS;
break;
case 0x00000004:
ret = IDLE_PRIORITY_CLASS;
break;
case 0x0000000d:
ret = HIGH_PRIORITY_CLASS;
break;
case 0x00000018:
ret = REALTIME_PRIORITY_CLASS;
break;
default:
WARN(process,"Unknown priority %ld\n",pdb->priority);
}
K32OBJ_DecCount( &pdb->header );
}
return ret;
struct get_process_info_reply reply;
if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
return reply.priority;
}
/***********************************************************************
* SetProcessAffinityMask (KERNEL32.662)
*/
BOOL32 WINAPI SetProcessAffinityMask( HANDLE32 hProcess, DWORD affmask )
{
struct set_process_info_request req;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
if (req.handle == -1) return FALSE;
req.affinity = affmask;
req.mask = SET_PROCESS_INFO_AFFINITY;
CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
/**********************************************************************
* GetProcessAffinityMask (KERNEL32.373)
*/
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 )
}
/***********************************************************************
* 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]
* Sets the min/max working set sizes for a specified process.
*
......@@ -867,15 +880,12 @@ BOOL32 WINAPI GetExitCodeProcess(
LPDWORD lpExitCode) /* [O] address to receive termination status */
{
struct get_process_info_reply reply;
int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
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 (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
if (lpExitCode) *lpExitCode = reply.exit_code;
return TRUE;
}
/***********************************************************************
* GetProcessHeaps [KERNEL32.376]
*/
......
......@@ -28,7 +28,6 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
SYSTEM_LOCK();
wait->count = count;
wait->signaled = WAIT_FAILED;
wait->wait_all = wait_all;
for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
{
......@@ -67,44 +66,12 @@ static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
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)
*/
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 )
*/
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;
return ret;
}
......@@ -123,7 +90,7 @@ DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
*/
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 )
DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
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,
DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
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,
BOOL32 wait_all, DWORD timeout,
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 =
/* Is threading code initialized? */
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
......@@ -161,7 +149,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
LPTHREAD_START_ROUTINE start_addr, LPVOID param )
{
DWORD old_prot;
WORD cs, ds;
THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
if (!thdb) return NULL;
......@@ -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;
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 );
return thdb;
......@@ -588,10 +562,7 @@ BOOL32 WINAPI SetThreadContext(
HANDLE32 handle, /* [in] Handle to thread with context */
CONTEXT *context) /* [out] Address of context structure */
{
THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL );
if (!thread) return FALSE;
*context = thread->context;
K32OBJ_DecCount( &thread->header );
FIXME( thread, "not implemented\n" );
return TRUE;
}
......@@ -606,10 +577,19 @@ BOOL32 WINAPI GetThreadContext(
HANDLE32 handle, /* [in] Handle to thread with context */
CONTEXT *context) /* [out] Address of context structure */
{
THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL );
if (!thread) return FALSE;
*context = thread->context;
K32OBJ_DecCount( &thread->header );
WORD cs, ds;
FIXME( thread, "returning dummy info\n" );
/* 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;
}
......@@ -624,14 +604,14 @@ BOOL32 WINAPI GetThreadContext(
INT32 WINAPI GetThreadPriority(
HANDLE32 hthread) /* [in] Handle to thread */
{
THDB *thread;
INT32 ret;
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
struct get_thread_info_request req;
struct get_thread_info_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
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;
ret = thread->delta_priority;
K32OBJ_DecCount( &thread->header );
return ret;
return reply.priority;
}
......@@ -646,13 +626,31 @@ BOOL32 WINAPI SetThreadPriority(
HANDLE32 hthread, /* [in] Handle to thread */
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;
K32OBJ_DecCount( &thread->header );
return TRUE;
/**********************************************************************
* SetThreadAffinityMask (KERNEL32.669)
*/
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(
HANDLE32 hthread, /* [in] Handle to thread */
LPDWORD exitcode) /* [out] Address to receive termination status */
{
struct get_thread_info_request req;
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 );
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 (exitcode) *exitcode = reply.exit_code;
return TRUE;
......@@ -710,33 +709,15 @@ BOOL32 WINAPI GetExitCodeThread(
* Already running: 0
*/
DWORD WINAPI ResumeThread(
HANDLE32 hthread) /* [in] Indentifies thread to restart */
HANDLE32 hthread) /* [in] Identifies thread to restart */
{
THDB *thread;
DWORD oldcount;
SYSTEM_LOCK();
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
{
SYSTEM_UNLOCK();
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;
struct resume_thread_request req;
struct resume_thread_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
CLIENT_SendRequest( REQ_RESUME_THREAD, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
return reply.count;
}
......@@ -750,37 +731,28 @@ DWORD WINAPI ResumeThread(
DWORD WINAPI SuspendThread(
HANDLE32 hthread) /* [in] Handle to the thread */
{
THDB *thread;
DWORD oldcount;
SYSTEM_LOCK();
if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
{
SYSTEM_UNLOCK();
WARN(thread, "Invalid thread handle\n");
return 0xFFFFFFFF;
}
struct suspend_thread_request req;
struct suspend_thread_reply reply;
req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
CLIENT_SendRequest( REQ_SUSPEND_THREAD, -1, 1, &req, sizeof(req) );
if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
return reply.count;
}
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 )
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
int running_threads; /* number of threads running in this process */
struct timeval start_time; /* absolute time at process start */
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;
......@@ -84,11 +88,12 @@ static const struct object_ops process_ops =
/* create a new process */
struct process *create_process(void)
{
struct process *process;
struct process *process, *parent;
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 );
return NULL;
......@@ -99,6 +104,15 @@ struct process *create_process(void)
process->thread_list = NULL;
process->exit_code = 0x103; /* STILL_ACTIVE */
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;
first_process = process;
......@@ -126,6 +140,7 @@ static void process_destroy( struct object *obj )
if (process->next) process->next->prev = process->prev;
if (process->prev) process->prev->next = process->next;
else first_process = process->next;
free_console( process );
free_handles( process );
if (debug_level) memset( process, 0xbb, sizeof(process) ); /* catch errors */
free( process );
......@@ -508,4 +523,53 @@ void get_process_info( struct process *process,
{
reply->pid = process;
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)
DECL_HANDLER(get_process_info)
{
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 )))
{
......@@ -237,6 +237,19 @@ DECL_HANDLER(get_process_info)
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 */
DECL_HANDLER(get_thread_info)
{
......@@ -251,6 +264,59 @@ DECL_HANDLER(get_thread_info)
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 */
DECL_HANDLER(open_process)
{
......@@ -488,6 +554,36 @@ DECL_HANDLER(get_file_info)
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 */
DECL_HANDLER(create_pipe)
{
......@@ -512,34 +608,72 @@ DECL_HANDLER(create_pipe)
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* create a console */
DECL_HANDLER(create_console)
/* allocate a console for the current process */
DECL_HANDLER(alloc_console)
{
struct create_console_reply reply = { -1, -1 };
struct object *obj[2];
if (create_console( fd, obj ))
{
reply.handle_read = alloc_handle( current->process, obj[0],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
req->inherit );
if (reply.handle_read != -1)
alloc_console( current->process );
send_reply( current, -1, 0 );
}
/* free the console of the current process */
DECL_HANDLER(free_console)
{
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],
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
req->inherit );
if (reply.handle_write == -1)
close_handle( current->process, reply.handle_read );
}
release_object( obj[0] );
release_object( obj[1] );
reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
release_object( obj );
}
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 */
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 );
}
......@@ -585,3 +719,18 @@ DECL_HANDLER(get_mapping_info)
int map_fd = get_mapping_info( req->handle, &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
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 */
......@@ -86,11 +95,16 @@ struct thread *create_thread( int fd, void *pid, int *thread_handle,
thread->name = NULL;
thread->mutex = NULL;
thread->wait = NULL;
thread->apc = NULL;
thread->apc_count = 0;
thread->error = 0;
thread->state = STARTING;
thread->exit_code = 0x103; /* STILL_ACTIVE */
thread->next = first_thread;
thread->prev = NULL;
thread->priority = THREAD_PRIORITY_NORMAL;
thread->affinity = 1;
thread->suspend = 0;
if (first_thread) first_thread->prev = thread;
first_thread = thread;
......@@ -136,6 +150,7 @@ static void destroy_thread( struct object *obj )
if (thread->prev) thread->prev->next = thread->next;
else first_thread = thread->next;
if (thread->name) free( thread->name );
if (thread->apc) free( thread->apc );
if (debug_level) memset( thread, 0xaa, sizeof(thread) ); /* catch errors */
free( thread );
}
......@@ -178,6 +193,49 @@ void get_thread_info( struct thread *thread,
{
reply->pid = thread;
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 */
......@@ -297,13 +355,12 @@ static int check_wait( struct thread *thread, int *signaled )
int i;
struct thread_wait *wait = thread->wait;
struct wait_queue_entry *entry = wait->queues;
struct timeval now;
assert( wait );
if (wait->flags & SELECT_ALL)
{
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 */
*signaled = 0;
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
......@@ -323,8 +380,16 @@ static int check_wait( struct thread *thread, int *signaled )
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 );
if ((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 )
*signaled = STATUS_TIMEOUT;
return 1;
}
}
return 0;
}
/* sleep on a list of objects */
void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout )
/* send the select reply to wake up the client */
static void send_select_reply( struct thread *thread, int signaled )
{
struct select_reply reply;
assert( !thread->wait );
reply.signaled = -1;
if (!wait_on( thread, count, handles, flags, timeout )) goto done;
if (!check_wait( thread, &reply.signaled ))
reply.signaled = signaled;
if ((signaled == STATUS_USER_APC) && thread->apc)
{
/* we need to wait */
if (flags & SELECT_TIMEOUT)
set_select_timeout( thread->client_fd, &thread->wait->timeout );
return;
struct thread_apc *apc = thread->apc;
int len = thread->apc_count * sizeof(*apc);
thread->apc = NULL;
thread->apc_count = 0;
send_reply( thread, -1, 2, &reply, sizeof(reply),
apc, len );
free( apc );
}
end_wait( thread );
done:
send_reply( thread, -1, 1, &reply, sizeof(reply) );
else send_reply( thread, -1, 1, &reply, sizeof(reply) );
}
/* attempt to wake up a thread */
/* return 1 if OK, 0 if the wait condition is still not satisfied */
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 );
send_reply( thread, -1, 1, &reply, sizeof(reply) );
send_select_reply( thread, signaled );
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 */
void thread_timeout(void)
{
struct select_reply reply;
assert( current->wait );
reply.signaled = STATUS_TIMEOUT;
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 */
......@@ -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 */
void kill_thread( struct thread *thread, int exit_code )
{
......
......@@ -30,28 +30,15 @@
#include "winnt.h"
#include "msdos.h"
#include "miscemu.h"
#include "server.h"
static void DEVICE_Destroy(K32OBJ *dev);
const K32OBJ_OPS DEVICE_Ops =
{
DEVICE_Destroy /* destroy */
};
/* The device object */
typedef struct
{
K32OBJ header;
struct VxDInfo *info;
} DEVICE_OBJECT;
static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped);
static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
static BOOL32 DeviceIo_MONODEBG(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
......@@ -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 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped);
static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
static BOOL32 DeviceIo_VWin32(DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
......@@ -80,10 +67,11 @@ struct VxDInfo
LPCSTR name;
WORD id;
BOOL32 (*vxdcall)(DWORD *, DWORD, CONTEXT *);
BOOL32 (*deviceio)(DEVICE_OBJECT *, DWORD, LPVOID, DWORD,
BOOL32 (*deviceio)(DWORD, LPVOID, DWORD,
LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
}
VxDList[] =
};
static const struct VxDInfo VxDList[] =
{
/* Standard VxD IDs */
{ "VMM", 0x0001, VxDCall_VMM, NULL },
......@@ -266,43 +254,39 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
"<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;
HANDLE32 handle;
int i;
dev = HeapAlloc( SystemHeap, 0, sizeof(DEVICE_OBJECT) );
if (!dev) return INVALID_HANDLE_VALUE32;
const struct VxDInfo *info;
dev->header.type = K32OBJ_DEVICE_IOCTL;
dev->header.refcount = 1;
dev->info = NULL;
for (info = VxDList; info->name; info++)
if (!lstrcmpi32A( info->name, filename ))
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);
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;
return FILE_CreateDevice( 0x10000, access, sa );
}
static void DEVICE_Destroy(K32OBJ *obj)
static const struct VxDInfo *DEVICE_GetInfo( HANDLE32 handle )
{
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
assert( obj->type == K32OBJ_DEVICE_IOCTL );
struct get_file_info_request req;
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;
HeapFree( SystemHeap, 0, dev );
for (info = VxDList; info->name; info++)
if (info->id == LOWORD(reply.attr)) break;
return info;
}
return NULL;
}
/****************************************************************************
......@@ -320,15 +304,14 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped)
{
DEVICE_OBJECT *dev = (DEVICE_OBJECT *)HANDLE_GetObjPtr(
PROCESS_Current(), hDevice, K32OBJ_DEVICE_IOCTL, 0 /*FIXME*/, NULL );
const struct VxDInfo *info;
TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped
);
if (!dev)
if (!(info = DEVICE_GetInfo( hDevice )))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
......@@ -337,9 +320,9 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
/* Check if this is a user defined control code for a VxD */
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,
lpvOutBuffer, cbOutBuffer,
lpcbBytesReturned, lpOverlapped );
......@@ -348,7 +331,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
{
/* FIXME: Set appropriate error */
FIXME( win32, "Unimplemented control %ld for VxD device %s\n",
dwIoControlCode, dev->info ? dev->info->name : "???" );
dwIoControlCode, info->name ? info->name : "???" );
}
}
else
......@@ -403,8 +386,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
/***********************************************************************
* DeviceIo_VTDAPI
*/
static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped)
......@@ -765,15 +747,14 @@ static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
/* FIXME: pOut->ar_pad ignored */
}
static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
LPVOID lpvInBuffer, DWORD cbInBuffer,
static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
LPVOID lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPOVERLAPPED lpOverlapped)
{
BOOL32 retv = TRUE;
TRACE(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dev,dwIoControlCode,
TRACE(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dwIoControlCode,
lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer,
lpcbBytesReturned,
......@@ -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 lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
......@@ -928,7 +909,7 @@ static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
/* 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 lpvOutBuffer, DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
......@@ -942,8 +923,8 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
fprintf(stderr,"MONODEBG: %s\n",debugstr_a(lpvInBuffer));
break;
default:
FIXME(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dev,dwIoControlCode,
FIXME(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
dwIoControlCode,
lpvInBuffer,cbInBuffer,
lpvOutBuffer,cbOutBuffer,
lpcbBytesReturned,
......
......@@ -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]
*/
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