From 62a8b433012644ca5a491e7df480f91d5496618b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Tue, 19 Jan 1999 17:48:23 +0000 Subject: [PATCH] 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. --- files/change.c | 51 +---- files/dos_fs.c | 31 ++- files/file.c | 191 ++++++++++--------- include/device.h | 3 +- include/file.h | 13 +- include/process.h | 3 +- include/server.h | 169 ++++++++++++++++- include/server/object.h | 21 ++- include/server/request.h | 48 ++++- include/server/thread.h | 11 ++ include/thread.h | 5 +- include/winbase.h | 5 +- include/windows.h | 1 + include/wintypes.h | 2 + memory/virtual.c | 63 +++---- msdos/int21.c | 26 ++- msdos/vxd.c | 7 +- relay32/kernel32.spec | 2 +- scheduler/client.c | 26 +-- scheduler/handle.c | 28 --- scheduler/k32obj.c | 9 +- scheduler/process.c | 130 +++++++------ scheduler/synchro.c | 84 +++++---- scheduler/thread.c | 182 ++++++++---------- server/console.c | 368 ++++++++++++++++++++++++++++-------- server/file.c | 14 ++ server/process.c | 72 ++++++- server/request.c | 189 +++++++++++++++++-- server/thread.c | 163 +++++++++++++--- server/trace.c | 203 +++++++++++++++++++- win32/console.c | 396 ++++++++++++++++++++++----------------- win32/device.c | 115 +++++------- win32/process.c | 39 ---- 33 files changed, 1760 insertions(+), 910 deletions(-) diff --git a/files/change.c b/files/change.c index 3dde14cdd0b..6e81b4e7f33 100644 --- a/files/change.c +++ b/files/change.c @@ -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; } diff --git a/files/dos_fs.c b/files/dos_fs.c index 2bc9be3811a..47d86e26555 100644 --- a/files/dos_fs.c +++ b/files/dos_fs.c @@ -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; diff --git a/files/file.c b/files/file.c index 2cfe9e2657e..6b61a6047be 100644 --- a/files/file.c +++ b/files/file.c @@ -46,74 +46,17 @@ #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 * @@ -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] diff --git a/include/device.h b/include/device.h index 58834e762cd..456ef22da30 100644 --- a/include/device.h +++ b/include/device.h @@ -1,4 +1,5 @@ #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 diff --git a/include/file.h b/include/file.h index e6192b5d6fd..6af604ac4f3 100644 --- a/include/file.h +++ b/include/file.h @@ -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, diff --git a/include/process.h b/include/process.h index e5969a612bc..7454fae4583 100644 --- a/include/process.h +++ b/include/process.h @@ -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 ); diff --git a/include/server.h b/include/server.h index 2f386f2f33c..ea5df051065 100644 --- a/include/server.h +++ b/include/server.h @@ -92,9 +92,24 @@ struct get_process_info_request }; struct get_process_info_reply { - void* pid; /* server process id */ - int exit_code; /* process exit code */ + 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 */ @@ -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,23 +432,82 @@ 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 */ }; /* Set a console file descriptor */ 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 */ +}; /* Create a change notification */ @@ -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 */ diff --git a/include/server/object.h b/include/server/object.h index b10682f6659..a48a7a9d882 100644 --- a/include/server/object.h +++ b/include/server/object.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 */ diff --git a/include/server/request.h b/include/server/request.h index 30b25b5cc1e..f8c105141e0 100644 --- a/include/server/request.h +++ b/include/server/request.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 */ diff --git a/include/server/thread.h b/include/server/thread.h index 1977152ff84..d5f8f00859b 100644 --- a/include/server/thread.h +++ b/include/server/thread.h @@ -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); diff --git a/include/thread.h b/include/thread.h index 4854b63cfd1..123866411be 100644 --- a/include/thread.h +++ b/include/thread.h @@ -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 ); diff --git a/include/winbase.h b/include/winbase.h index 8df2d66229e..2254b4102e3 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -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); diff --git a/include/windows.h b/include/windows.h index e3885f81311..4431430fd7f 100644 --- a/include/windows.h +++ b/include/windows.h @@ -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); diff --git a/include/wintypes.h b/include/wintypes.h index e64868cb7c8..e456dadd512 100644 --- a/include/wintypes.h +++ b/include/wintypes.h @@ -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; diff --git a/memory/virtual.c b/memory/virtual.c index a387b9b9137..9bd0c9afe76 100644 --- a/memory/virtual.c +++ b/memory/virtual.c @@ -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 - ERR(virtual,"Unsupported on other process\n"); - K32OBJ_DecCount( &pdb->header ); - } - return ret; + 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"); + 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 - ERR(virtual,"Unsupported on other process\n"); - K32OBJ_DecCount( &pdb->header ); - } - return ret; + DWORD len /* [in] Size of buffer */ ) +{ + if (PROCESS_IsCurrent( handle )) + return VirtualQuery( addr, info, len ); + ERR(virtual,"Unsupported on other process\n"); + 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; } diff --git a/msdos/int21.c b/msdos/int21.c index 2b011691a68..809d71073b5 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -218,22 +218,17 @@ 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 ))) + 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; - return; - } + DX_reg(context) = dev->flags; + return; } /* it seems to be a file */ @@ -1559,12 +1554,13 @@ 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$")) - ASPI_DOS_HandleInt(context); - FILE_ReleaseFile( file ); - break; + const DOS_DEVICE *dev; + if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )) && + !strcasecmp( dev->name, "SCSIMGR$" )) + { + ASPI_DOS_HandleInt(context); + } + break; } case 0x05:{ /* IOCTL - WRITE TO BLOCK DEVICE CONTROL CHANNEL */ /*BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, DS_reg(context),EDX_reg(context));*/ diff --git a/msdos/vxd.c b/msdos/vxd.c index 420bb50773e..8022a548941 100644 --- a/msdos/vxd.c +++ b/msdos/vxd.c @@ -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; diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec index b82cb2032ab..c4d1dedaa4a 100644 --- a/relay32/kernel32.spec +++ b/relay32/kernel32.spec @@ -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 diff --git a/scheduler/client.c b/scheduler/client.c index 24fdfa4ebce..2c27f7a9412 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -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; -} diff --git a/scheduler/handle.c b/scheduler/handle.c index 80257ccbf88..7e58820958f 100644 --- a/scheduler/handle.c +++ b/scheduler/handle.c @@ -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 */ diff --git a/scheduler/k32obj.c b/scheduler/k32obj.c index 35f5be39d7d..e64cb89344d 100644 --- a/scheduler/k32obj.c +++ b/scheduler/k32obj.c @@ -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 */ diff --git a/scheduler/process.c b/scheduler/process.c index b49c00a00ef..41736ddecd9 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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; } @@ -720,15 +742,6 @@ DWORD WINAPI GetProcessFlags( DWORD processid ) return pdb->flags; } -/*********************************************************************** - * 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] */ diff --git a/scheduler/synchro.c b/scheduler/synchro.c index 9f0dbce3e22..eb262d6b234 100644 --- a/scheduler/synchro.c +++ b/scheduler/synchro.c @@ -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; } diff --git a/scheduler/thread.c b/scheduler/thread.c index d89b77f4aa7..2241747f290 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -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; - - if (!(thread = THREAD_GetPtr( hthread, THREAD_SET_INFORMATION, NULL ))) - return FALSE; - thread->delta_priority = priority; - K32OBJ_DecCount( &thread->header ); - return TRUE; + 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 ); +} + + +/********************************************************************** + * 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; + 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; +} - 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)) - { - 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 ); } diff --git a/server/console.c b/server/console.c index d9cfae33eba..e9edaef0f9a 100644 --- a/server/console.c +++ b/server/console.c @@ -9,6 +9,7 @@ #include <assert.h> #include <fcntl.h> +#include <signal.h> #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -21,36 +22,75 @@ #include "winerror.h" #include "winnt.h" +#include "wincon.h" #include "server/thread.h" -struct console +struct screen_buffer; + +struct console_input +{ + struct object obj; /* object header */ + int fd; /* Unix file descriptor */ + int mode; /* input mode */ + struct screen_buffer *output; /* associated screen buffer */ +}; + +struct screen_buffer { - struct object obj; /* object header */ - int fd; /* Unix file descriptor */ - int is_read; /* is this the read or write part? */ + struct object obj; /* object header */ + int fd; /* Unix file descriptor */ + int mode; /* output mode */ + struct console_input *input; /* associated console input */ + int cursor_size; /* size of cursor (percentage filled) */ + int cursor_visible;/* cursor visibility flag */ + int pid; /* xterm pid (hack) */ + char *title; /* console title */ }; -static void console_dump( struct object *obj, int verbose ); -static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ); -static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry ); -static int console_signaled( struct object *obj, struct thread *thread ); -static int console_get_read_fd( struct object *obj ); -static int console_get_write_fd( struct object *obj ); + +static void console_input_dump( struct object *obj, int verbose ); +static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); +static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry ); +static int console_input_signaled( struct object *obj, struct thread *thread ); +static int console_input_get_read_fd( struct object *obj ); +static void console_input_destroy( struct object *obj ); + +static void screen_buffer_dump( struct object *obj, int verbose ); +static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry ); +static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry ); +static int screen_buffer_signaled( struct object *obj, struct thread *thread ); +static int screen_buffer_get_write_fd( struct object *obj ); +static void screen_buffer_destroy( struct object *obj ); + +/* common routine */ static int console_get_info( struct object *obj, struct get_file_info_reply *reply ); -static void console_destroy( struct object *obj ); -static const struct object_ops console_ops = +static const struct object_ops console_input_ops = { - console_dump, - console_add_queue, - console_remove_queue, - console_signaled, + console_input_dump, + console_input_add_queue, + console_input_remove_queue, + console_input_signaled, no_satisfied, - console_get_read_fd, - console_get_write_fd, + console_input_get_read_fd, + no_write_fd, no_flush, console_get_info, - console_destroy + console_input_destroy +}; + +static const struct object_ops screen_buffer_ops = +{ + screen_buffer_dump, + screen_buffer_add_queue, + screen_buffer_remove_queue, + screen_buffer_signaled, + no_satisfied, + no_read_fd, + screen_buffer_get_write_fd, + no_flush, + console_get_info, + screen_buffer_destroy }; static const struct select_ops select_ops = @@ -61,7 +101,8 @@ static const struct select_ops select_ops = int create_console( int fd, struct object *obj[2] ) { - struct console *console_read, *console_write; + struct console_input *console_input; + struct screen_buffer *screen_buffer; int read_fd, write_fd; if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1) @@ -75,67 +116,185 @@ int create_console( int fd, struct object *obj[2] ) close( read_fd ); return 0; } - if (!(console_read = mem_alloc( sizeof(struct console) ))) + if (!(console_input = mem_alloc( sizeof(struct console_input) ))) { close( read_fd ); close( write_fd ); return 0; } - if (!(console_write = mem_alloc( sizeof(struct console) ))) + if (!(screen_buffer = mem_alloc( sizeof(struct screen_buffer) ))) { close( read_fd ); close( write_fd ); - free( console_read ); + free( console_input ); return 0; } - init_object( &console_read->obj, &console_ops, NULL ); - init_object( &console_write->obj, &console_ops, NULL ); - console_read->fd = read_fd; - console_read->is_read = 1; - console_write->fd = write_fd; - console_write->is_read = 0; + init_object( &console_input->obj, &console_input_ops, NULL ); + init_object( &screen_buffer->obj, &screen_buffer_ops, NULL ); + console_input->fd = read_fd; + console_input->mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | + ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT; + console_input->output = screen_buffer; + screen_buffer->fd = write_fd; + screen_buffer->mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; + screen_buffer->input = console_input; + screen_buffer->cursor_size = 100; + screen_buffer->cursor_visible = 1; + screen_buffer->pid = 0; + screen_buffer->title = strdup( "Wine console" ); CLEAR_ERROR(); - obj[0] = &console_read->obj; - obj[1] = &console_write->obj; + obj[0] = &console_input->obj; + obj[1] = &screen_buffer->obj; return 1; } -int set_console_fd( int handle, int fd ) +int set_console_fd( int handle, int fd, int pid ) { - struct console *console; + struct console_input *input; + struct screen_buffer *output; + struct object *obj; + int fd_in, fd_out; + + if (!(obj = get_handle_obj( current->process, handle, 0, NULL ))) + return 0; + if (obj->ops == &console_input_ops) + { + input = (struct console_input *)obj; + output = input->output; + grab_object( output ); + } + else if (obj->ops == &screen_buffer_ops) + { + output = (struct screen_buffer *)obj; + input = output->input; + grab_object( input ); + } + else + { + SET_ERROR( ERROR_INVALID_HANDLE ); + release_object( obj ); + return 0; + } - if (!(console = (struct console *)get_handle_obj( current->process, handle, - 0, &console_ops ))) + if ((fd_in = dup(fd)) == -1) + { + file_set_error(); + release_object( input ); + release_object( output ); return 0; - if ((fd = dup(fd)) == -1) + } + if ((fd_out = dup(fd)) == -1) { file_set_error(); - release_object( console ); + close( fd_in ); + release_object( input ); + release_object( output ); return 0; } - close( console->fd ); - console->fd = fd; + close( input->fd ); + close( output->fd ); + input->fd = fd_in; + output->fd = fd_out; + output->pid = pid; + release_object( input ); + release_object( output ); + return 1; +} + +int get_console_mode( int handle, int *mode ) +{ + struct object *obj; + int ret = 0; + + if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL ))) + return 0; + if (obj->ops == &console_input_ops) + { + *mode = ((struct console_input *)obj)->mode; + ret = 1; + } + else if (obj->ops == &screen_buffer_ops) + { + *mode = ((struct screen_buffer *)obj)->mode; + ret = 1; + } + else SET_ERROR( ERROR_INVALID_HANDLE ); + release_object( obj ); + return ret; +} + +int set_console_mode( int handle, int mode ) +{ + struct object *obj; + int ret = 0; + + if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL ))) + return 0; + if (obj->ops == &console_input_ops) + { + ((struct console_input *)obj)->mode = mode; + ret = 1; + } + else if (obj->ops == &screen_buffer_ops) + { + ((struct screen_buffer *)obj)->mode = mode; + ret = 1; + } + else SET_ERROR( ERROR_INVALID_HANDLE ); + release_object( obj ); + return ret; +} + +/* set misc console information (output handle only) */ +int set_console_info( int handle, struct set_console_info_request *req, const char *title ) +{ + struct screen_buffer *console; + if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle, + GENERIC_WRITE, &screen_buffer_ops ))) + return 0; + if (req->mask & SET_CONSOLE_INFO_CURSOR) + { + console->cursor_size = req->cursor_size; + console->cursor_visible = req->cursor_visible; + } + if (req->mask & SET_CONSOLE_INFO_TITLE) + { + if (console->title) free( console->title ); + console->title = strdup( title ); + } + release_object( console ); + return 1; +} + +/* get misc console information (output handle only) */ +int get_console_info( int handle, struct get_console_info_reply *reply, const char **title ) +{ + struct screen_buffer *console; + if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle, + GENERIC_READ, &screen_buffer_ops ))) + return 0; + reply->cursor_size = console->cursor_size; + reply->cursor_visible = console->cursor_visible; + reply->pid = console->pid; + *title = console->title; release_object( console ); return 1; } -static void console_dump( struct object *obj, int verbose ) +static void console_input_dump( struct object *obj, int verbose ) { - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); - fprintf( stderr, "Console %s fd=%d\n", - console->is_read ? "input" : "output", console->fd ); + struct console_input *console = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); + fprintf( stderr, "Console input fd=%d\n", console->fd ); } -static int console_add_queue( struct object *obj, struct wait_queue_entry *entry ) +static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ) { - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); + struct console_input *console = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); if (!obj->head) /* first on the queue */ { - if (!add_select_user( console->fd, - console->is_read ? READ_EVENT : WRITE_EVENT, - &select_ops, console )) + if (!add_select_user( console->fd, READ_EVENT, &select_ops, console )) { SET_ERROR( ERROR_OUTOFMEMORY ); return 0; @@ -145,10 +304,10 @@ static int console_add_queue( struct object *obj, struct wait_queue_entry *entry return 1; } -static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry ) +static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry ) { - struct console *console = (struct console *)grab_object(obj); - assert( obj->ops == &console_ops ); + struct console_input *console = (struct console_input *)grab_object(obj); + assert( obj->ops == &console_input_ops ); remove_queue( obj, entry ); if (!obj->head) /* last on the queue is gone */ @@ -156,58 +315,101 @@ static void console_remove_queue( struct object *obj, struct wait_queue_entry *e release_object( obj ); } -static int console_signaled( struct object *obj, struct thread *thread ) +static int console_input_signaled( struct object *obj, struct thread *thread ) { fd_set fds; struct timeval tv = { 0, 0 }; - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); + struct console_input *console = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); FD_ZERO( &fds ); FD_SET( console->fd, &fds ); - if (console->is_read) - return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0; - else - return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0; + return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0; } -static int console_get_read_fd( struct object *obj ) +static int console_input_get_read_fd( struct object *obj ) { - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); - - if (!console->is_read) - { - SET_ERROR( ERROR_ACCESS_DENIED ); - return -1; - } + struct console_input *console = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); return dup( console->fd ); } -static int console_get_write_fd( struct object *obj ) +static int console_get_info( struct object *obj, struct get_file_info_reply *reply ) { - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); + memset( reply, 0, sizeof(*reply) ); + reply->type = FILE_TYPE_CHAR; + return 1; +} + +static void console_input_destroy( struct object *obj ) +{ + struct console_input *console = (struct console_input *)obj; + assert( obj->ops == &console_input_ops ); + close( console->fd ); + if (console->output) console->output->input = NULL; + free( console ); +} - if (console->is_read) +static void screen_buffer_dump( struct object *obj, int verbose ) +{ + struct screen_buffer *console = (struct screen_buffer *)obj; + assert( obj->ops == &screen_buffer_ops ); + fprintf( stderr, "Console screen buffer fd=%d\n", console->fd ); +} + +static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry ) +{ + struct screen_buffer *console = (struct screen_buffer *)obj; + assert( obj->ops == &screen_buffer_ops ); + if (!obj->head) /* first on the queue */ { - SET_ERROR( ERROR_ACCESS_DENIED ); - return -1; + if (!add_select_user( console->fd, WRITE_EVENT, &select_ops, console )) + { + SET_ERROR( ERROR_OUTOFMEMORY ); + return 0; + } } - return dup( console->fd ); + add_queue( obj, entry ); + return 1; } -static int console_get_info( struct object *obj, struct get_file_info_reply *reply ) +static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry ) { - memset( reply, 0, sizeof(*reply) ); - reply->type = FILE_TYPE_CHAR; - return 1; + struct screen_buffer *console = (struct screen_buffer *)grab_object(obj); + assert( obj->ops == &screen_buffer_ops ); + + remove_queue( obj, entry ); + if (!obj->head) /* last on the queue is gone */ + remove_select_user( console->fd ); + release_object( obj ); +} + +static int screen_buffer_signaled( struct object *obj, struct thread *thread ) +{ + fd_set fds; + struct timeval tv = { 0, 0 }; + struct screen_buffer *console = (struct screen_buffer *)obj; + assert( obj->ops == &screen_buffer_ops ); + + FD_ZERO( &fds ); + FD_SET( console->fd, &fds ); + return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0; +} + +static int screen_buffer_get_write_fd( struct object *obj ) +{ + struct screen_buffer *console = (struct screen_buffer *)obj; + assert( obj->ops == &screen_buffer_ops ); + return dup( console->fd ); } -static void console_destroy( struct object *obj ) +static void screen_buffer_destroy( struct object *obj ) { - struct console *console = (struct console *)obj; - assert( obj->ops == &console_ops ); + struct screen_buffer *console = (struct screen_buffer *)obj; + assert( obj->ops == &screen_buffer_ops ); close( console->fd ); + if (console->input) console->input->output = NULL; + if (console->pid) kill( console->pid, SIGTERM ); + if (console->title) free( console->title ); free( console ); } diff --git a/server/file.c b/server/file.c index c786807e861..1ade0967264 100644 --- a/server/file.c +++ b/server/file.c @@ -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; +} diff --git a/server/process.c b/server/process.c index c9ba9c83f23..6cd3e581c09 100644 --- a/server/process.c +++ b/server/process.c @@ -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 ); @@ -506,6 +521,55 @@ void kill_process( struct process *process, int exit_code ) void get_process_info( struct process *process, struct get_process_info_reply *reply ) { - reply->pid = process; - reply->exit_code = process->exit_code; + 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 ); } diff --git a/server/request.c b/server/request.c index f1fc2fdd3a5..bfdcae51e49 100644 --- a/server/request.c +++ b/server/request.c @@ -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 )) + 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_read = alloc_handle( current->process, obj[0], - STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ, - req->inherit ); - if (reply.handle_read != -1) - { - 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) ); +} diff --git a/server/thread.c b/server/thread.c index 21614c9e026..5e5e3d6e584 100644 --- a/server/thread.c +++ b/server/thread.c @@ -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,61 +380,82 @@ static int check_wait( struct thread *thread, int *signaled ) return 1; } } - check_timeout: - if (!(wait->flags & SELECT_TIMEOUT)) return 0; - gettimeofday( &now, NULL ); - if ((now.tv_sec > wait->timeout.tv_sec) || - ((now.tv_sec == wait->timeout.tv_sec) && - (now.tv_usec >= wait->timeout.tv_usec))) + + other_checks: + if ((wait->flags & SELECT_ALERTABLE) && thread->apc) { - *signaled = STATUS_TIMEOUT; + *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) && + (now.tv_usec >= wait->timeout.tv_usec))) + { + *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 ) { diff --git a/server/trace.c b/server/trace.c index ed257c4affb..1c1b8df53c2 100644 --- a/server/trace.c +++ b/server/trace.c @@ -57,7 +57,19 @@ static int dump_get_process_info_request( struct get_process_info_request *req, static int dump_get_process_info_reply( struct get_process_info_reply *req, int len ) { fprintf( stderr, " pid=%p,", req->pid ); - fprintf( stderr, " exit_code=%d", req->exit_code ); + fprintf( stderr, " exit_code=%d,", req->exit_code ); + fprintf( stderr, " priority=%d,", req->priority ); + fprintf( stderr, " process_affinity=%d,", req->process_affinity ); + fprintf( stderr, " system_affinity=%d", req->system_affinity ); + return (int)sizeof(*req); +} + +static int dump_set_process_info_request( struct set_process_info_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " mask=%d,", req->mask ); + fprintf( stderr, " priority=%d,", req->priority ); + fprintf( stderr, " affinity=%d", req->affinity ); return (int)sizeof(*req); } @@ -70,7 +82,49 @@ static int dump_get_thread_info_request( struct get_thread_info_request *req, in static int dump_get_thread_info_reply( struct get_thread_info_reply *req, int len ) { fprintf( stderr, " pid=%p,", req->pid ); - fprintf( stderr, " exit_code=%d", req->exit_code ); + fprintf( stderr, " exit_code=%d,", req->exit_code ); + fprintf( stderr, " priority=%d", req->priority ); + return (int)sizeof(*req); +} + +static int dump_set_thread_info_request( struct set_thread_info_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " mask=%d,", req->mask ); + fprintf( stderr, " priority=%d,", req->priority ); + fprintf( stderr, " affinity=%d", req->affinity ); + return (int)sizeof(*req); +} + +static int dump_suspend_thread_request( struct suspend_thread_request *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + +static int dump_suspend_thread_reply( struct suspend_thread_reply *req, int len ) +{ + fprintf( stderr, " count=%d", req->count ); + return (int)sizeof(*req); +} + +static int dump_resume_thread_request( struct resume_thread_request *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + +static int dump_resume_thread_reply( struct resume_thread_reply *req, int len ) +{ + fprintf( stderr, " count=%d", req->count ); + return (int)sizeof(*req); +} + +static int dump_queue_apc_request( struct queue_apc_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " func=%p,", req->func ); + fprintf( stderr, " param=%p", req->param ); return (int)sizeof(*req); } @@ -297,6 +351,26 @@ static int dump_get_file_info_reply( struct get_file_info_reply *req, int len ) return (int)sizeof(*req); } +static int dump_lock_file_request( struct lock_file_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " offset_low=%08x,", req->offset_low ); + fprintf( stderr, " offset_high=%08x,", req->offset_high ); + fprintf( stderr, " count_low=%08x,", req->count_low ); + fprintf( stderr, " count_high=%08x", req->count_high ); + return (int)sizeof(*req); +} + +static int dump_unlock_file_request( struct unlock_file_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " offset_low=%08x,", req->offset_low ); + fprintf( stderr, " offset_high=%08x,", req->offset_high ); + fprintf( stderr, " count_low=%08x,", req->count_low ); + fprintf( stderr, " count_high=%08x", req->count_high ); + return (int)sizeof(*req); +} + static int dump_create_pipe_request( struct create_pipe_request *req, int len ) { fprintf( stderr, " inherit=%d", req->inherit ); @@ -310,25 +384,80 @@ static int dump_create_pipe_reply( struct create_pipe_reply *req, int len ) return (int)sizeof(*req); } -static int dump_create_console_request( struct create_console_request *req, int len ) +static int dump_alloc_console_request( struct alloc_console_request *req, int len ) +{ + return (int)sizeof(*req); +} + +static int dump_free_console_request( struct free_console_request *req, int len ) +{ + return (int)sizeof(*req); +} + +static int dump_open_console_request( struct open_console_request *req, int len ) { + fprintf( stderr, " output=%d,", req->output ); + fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d", req->inherit ); return (int)sizeof(*req); } -static int dump_create_console_reply( struct create_console_reply *req, int len ) +static int dump_open_console_reply( struct open_console_reply *req, int len ) { - fprintf( stderr, " handle_read=%d,", req->handle_read ); - fprintf( stderr, " handle_write=%d", req->handle_write ); + fprintf( stderr, " handle=%d", req->handle ); return (int)sizeof(*req); } static int dump_set_console_fd_request( struct set_console_fd_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " pid=%d", req->pid ); + return (int)sizeof(*req); +} + +static int dump_get_console_mode_request( struct get_console_mode_request *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + +static int dump_get_console_mode_reply( struct get_console_mode_reply *req, int len ) +{ + fprintf( stderr, " mode=%d", req->mode ); + return (int)sizeof(*req); +} + +static int dump_set_console_mode_request( struct set_console_mode_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " mode=%d", req->mode ); + return (int)sizeof(*req); +} + +static int dump_set_console_info_request( struct set_console_info_request *req, int len ) +{ + fprintf( stderr, " handle=%d,", req->handle ); + fprintf( stderr, " mask=%d,", req->mask ); + fprintf( stderr, " cursor_size=%d,", req->cursor_size ); + fprintf( stderr, " cursor_visible=%d,", req->cursor_visible ); + fprintf( stderr, " title=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; +} + +static int dump_get_console_info_request( struct get_console_info_request *req, int len ) { fprintf( stderr, " handle=%d", req->handle ); return (int)sizeof(*req); } +static int dump_get_console_info_reply( struct get_console_info_reply *req, int len ) +{ + fprintf( stderr, " cursor_size=%d,", req->cursor_size ); + fprintf( stderr, " cursor_visible=%d,", req->cursor_visible ); + fprintf( stderr, " pid=%d", req->pid ); + return (int)sizeof(*req); +} + static int dump_create_change_notification_request( struct create_change_notification_request *req, int len ) { fprintf( stderr, " subtree=%d,", req->subtree ); @@ -372,6 +501,20 @@ static int dump_get_mapping_info_reply( struct get_mapping_info_reply *req, int return (int)sizeof(*req); } +static int dump_create_device_request( struct create_device_request *req, int len ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " id=%d", req->id ); + return (int)sizeof(*req); +} + +static int dump_create_device_reply( struct create_device_reply *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + struct dumper { int (*dump_req)( void *data, int len ); @@ -392,8 +535,18 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())0 }, { (int(*)(void *,int))dump_get_process_info_request, (void(*)())dump_get_process_info_reply }, + { (int(*)(void *,int))dump_set_process_info_request, + (void(*)())0 }, { (int(*)(void *,int))dump_get_thread_info_request, (void(*)())dump_get_thread_info_reply }, + { (int(*)(void *,int))dump_set_thread_info_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_suspend_thread_request, + (void(*)())dump_suspend_thread_reply }, + { (int(*)(void *,int))dump_resume_thread_request, + (void(*)())dump_resume_thread_reply }, + { (int(*)(void *,int))dump_queue_apc_request, + (void(*)())0 }, { (int(*)(void *,int))dump_close_handle_request, (void(*)())0 }, { (int(*)(void *,int))dump_dup_handle_request, @@ -432,18 +585,36 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())0 }, { (int(*)(void *,int))dump_get_file_info_request, (void(*)())dump_get_file_info_reply }, + { (int(*)(void *,int))dump_lock_file_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_unlock_file_request, + (void(*)())0 }, { (int(*)(void *,int))dump_create_pipe_request, (void(*)())dump_create_pipe_reply }, - { (int(*)(void *,int))dump_create_console_request, - (void(*)())dump_create_console_reply }, + { (int(*)(void *,int))dump_alloc_console_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_free_console_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_open_console_request, + (void(*)())dump_open_console_reply }, { (int(*)(void *,int))dump_set_console_fd_request, (void(*)())0 }, + { (int(*)(void *,int))dump_get_console_mode_request, + (void(*)())dump_get_console_mode_reply }, + { (int(*)(void *,int))dump_set_console_mode_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_set_console_info_request, + (void(*)())0 }, + { (int(*)(void *,int))dump_get_console_info_request, + (void(*)())dump_get_console_info_reply }, { (int(*)(void *,int))dump_create_change_notification_request, (void(*)())dump_create_change_notification_reply }, { (int(*)(void *,int))dump_create_mapping_request, (void(*)())dump_create_mapping_reply }, { (int(*)(void *,int))dump_get_mapping_info_request, (void(*)())dump_get_mapping_info_reply }, + { (int(*)(void *,int))dump_create_device_request, + (void(*)())dump_create_device_reply }, }; static const char * const req_names[REQ_NB_REQUESTS] = @@ -454,7 +625,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = "terminate_process", "terminate_thread", "get_process_info", + "set_process_info", "get_thread_info", + "set_thread_info", + "suspend_thread", + "resume_thread", + "queue_apc", "close_handle", "dup_handle", "open_process", @@ -474,12 +650,21 @@ static const char * const req_names[REQ_NB_REQUESTS] = "set_file_time", "flush_file", "get_file_info", + "lock_file", + "unlock_file", "create_pipe", - "create_console", + "alloc_console", + "free_console", + "open_console", "set_console_fd", + "get_console_mode", + "set_console_mode", + "set_console_info", + "get_console_info", "create_change_notification", "create_mapping", "get_mapping_info", + "create_device", }; void trace_request( enum request req, void *data, int len, int fd ) diff --git a/win32/console.c b/win32/console.c index e2bc6229269..0328d432bec 100644 --- a/win32/console.c +++ b/win32/console.c @@ -50,14 +50,7 @@ /* The CONSOLE kernel32 Object */ typedef struct _CONSOLE { K32OBJ header; - DWORD mode; - CONSOLE_CURSOR_INFO cinfo; - - int master; /* xterm side of pty */ - int infd,outfd; - int hread, hwrite; /* server handles (hack) */ - int pid; /* xterm's pid, -1 if no xterm */ - LPSTR title; /* title of console */ + INPUT_RECORD *irs; /* buffered input records */ int nrofirs;/* nr of buffered input records */ } CONSOLE; @@ -79,16 +72,34 @@ static void CONSOLE_Destroy(K32OBJ *obj) obj->type = K32OBJ_UNKNOWN; - if (console->title) - HeapFree( SystemHeap, 0, console->title ); - console->title = NULL; - /* if there is a xterm, kill it. */ - if (console->pid != -1) - kill(console->pid, SIGTERM); HeapFree(SystemHeap, 0, console); } +/*********************************************************************** + * CONSOLE_GetPtr + */ +static CONSOLE *CONSOLE_GetPtr( HANDLE32 handle ) +{ + return (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), handle, + K32OBJ_CONSOLE, 0, NULL ); +} + +/**************************************************************************** + * CONSOLE_GetInfo + */ +static BOOL32 CONSOLE_GetInfo( HANDLE32 handle, struct get_console_info_reply *reply ) +{ + struct get_console_info_request req; + + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle, + K32OBJ_CONSOLE, GENERIC_READ )) == -1) + return FALSE; + CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); + return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL ); +} + + /**************************************************************************** * CONSOLE_add_input_record [internal] * @@ -110,8 +121,7 @@ static void CONSOLE_string_to_IR( HANDLE32 hConsoleInput,unsigned char *buf,int len) { int j,k; INPUT_RECORD ir; - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, - K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hConsoleInput ); for (j=0;j<len;j++) { unsigned char inchar = buf[j]; @@ -489,8 +499,15 @@ BOOL32 WINAPI FreeConsole(VOID) return FALSE; } - HANDLE_CloseAll( pdb, &console->header ); + CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 ); + if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) + { + K32OBJ_DecCount(&console->header); + SYSTEM_UNLOCK(); + return FALSE; + } + HANDLE_CloseAll( pdb, &console->header ); K32OBJ_DecCount( &console->header ); pdb->console = NULL; SYSTEM_UNLOCK(); @@ -498,33 +515,43 @@ BOOL32 WINAPI FreeConsole(VOID) } -/** - * It looks like the openpty that comes with glibc in RedHat 5.0 - * is buggy (second call returns what looks like a dup of 0 and 1 - * instead of a new pty), this is a generic replacement. +/************************************************************************* + * CONSOLE_OpenHandle + * + * Open a handle to the current process console. */ -static int CONSOLE_openpty(CONSOLE *console, char *name, - struct termios *term, struct winsize *winsize) +HANDLE32 CONSOLE_OpenHandle( BOOL32 output, DWORD access, LPSECURITY_ATTRIBUTES sa ) { - int temp, slave; - struct set_console_fd_request req; - - temp = wine_openpty(&console->master, &slave, name, term, - winsize); - console->infd = console->outfd = slave; + struct open_console_request req; + struct open_console_reply reply; + CONSOLE *console; + HANDLE32 handle; - req.handle = console->hread; - CLIENT_SendRequest(REQ_SET_CONSOLE_FD, dup(slave), 1, - &req, sizeof(req)); - CLIENT_WaitReply( NULL, NULL, 0); - req.handle = console->hwrite; - CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, - &req, sizeof(req)); - CLIENT_WaitReply( NULL, NULL, 0); + req.output = output; + req.access = access; + req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); + CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); + CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); + if (reply.handle == -1) return INVALID_HANDLE_VALUE32; - return temp; /* The same result as the openpty call */ + SYSTEM_LOCK(); + if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console)))) + { + SYSTEM_UNLOCK(); + return FALSE; + } + console->header.type = K32OBJ_CONSOLE; + console->header.refcount = 1; + console->nrofirs = 0; + console->irs = HeapAlloc(GetProcessHeap(),0,1);; + handle = HANDLE_Alloc( PROCESS_Current(), &console->header, req.access, + req.inherit, reply.handle ); + SYSTEM_UNLOCK(); + K32OBJ_DecCount(&console->header); + return handle; } + /************************************************************************* * CONSOLE_make_complex [internal] * @@ -537,29 +564,37 @@ static int CONSOLE_openpty(CONSOLE *console, char *name, * * All other functions should work indedependend from this call. * - * To test for complex console: pid == -1 -> simple, otherwise complex. + * To test for complex console: pid == 0 -> simple, otherwise complex. */ -static BOOL32 CONSOLE_make_complex(HANDLE32 handle,CONSOLE *console) +static BOOL32 CONSOLE_make_complex(HANDLE32 handle) { + struct set_console_fd_request req; + struct get_console_info_reply info; struct termios term; - char buf[30],*title; + char buf[256]; char c = '\0'; int status = 0; - int i,xpid; + int i,xpid,master,slave; DWORD xlen; - if (console->pid != -1) - return TRUE; /* already complex */ + if (!CONSOLE_GetInfo( handle, &info )) return FALSE; + if (info.pid) return TRUE; /* already complex */ MSG("Console: Making console complex (creating an xterm)...\n"); if (tcgetattr(0, &term) < 0) return FALSE; term.c_lflag = ~(ECHO|ICANON); - if (CONSOLE_openpty(console, NULL, &term, NULL) < 0) return FALSE; + + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle, + K32OBJ_CONSOLE, 0 )) == -1) + return FALSE; + + if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0) + return FALSE; if ((xpid=fork()) == 0) { - tcsetattr(console->infd, TCSADRAIN, &term); - sprintf(buf, "-Sxx%d", console->master); + tcsetattr(slave, TCSADRAIN, &term); + sprintf(buf, "-Sxx%d", master); /* "-fn vga" for VGA font. Harmless if vga is not present: * xterm: unable to open font "vga", trying "fixed".... */ @@ -567,53 +602,39 @@ static BOOL32 CONSOLE_make_complex(HANDLE32 handle,CONSOLE *console) ERR(console, "error creating AllocConsole xterm\n"); exit(1); } - console->pid = xpid; + + req.pid = xpid; + CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) ); + CLIENT_WaitReply( NULL, NULL, 0 ); /* most xterms like to print their window ID when used with -S; * read it and continue before the user has a chance... */ - for (i=0; c!='\n'; (status=read(console->infd, &c, 1)), i++) { + for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) { if (status == -1 && c == '\0') { /* wait for xterm to be created */ usleep(100); } if (i > 10000) { ERR(console, "can't read xterm WID\n"); - kill(console->pid, SIGKILL); + kill(xpid, SIGKILL); return FALSE; } } /* enable mouseclicks */ sprintf(buf,"%c[?1001s%c[?1000h",27,27); WriteFile(handle,buf,strlen(buf),&xlen,NULL); - if (console->title) { - title = HeapAlloc(GetProcessHeap(),0,strlen("\033]2;\a")+1+strlen(console->title)); - sprintf(title,"\033]2;%s\a",console->title); - WriteFile(handle,title,strlen(title),&xlen,NULL); - HeapFree(GetProcessHeap(),0,title); + + if (GetConsoleTitle32A( buf, sizeof(buf) )) + { + WriteFile(handle,"\033]2;",4,&xlen,NULL); + WriteFile(handle,buf,strlen(buf),&xlen,NULL); + WriteFile(handle,"\a",1,&xlen,NULL); } return TRUE; } -/*********************************************************************** - * CONSOLE_GetConsoleHandle - * returns a 16-bit style console handle - * note: only called from _lopen - */ -HFILE32 CONSOLE_GetConsoleHandle(VOID) -{ - PDB32 *pdb = PROCESS_Current(); - HFILE32 handle = HFILE_ERROR32; - - SYSTEM_LOCK(); - if (pdb->console != NULL) { - CONSOLE *console = (CONSOLE *)pdb->console; - handle = (HFILE32)HANDLE_Alloc(pdb, &console->header, 0, TRUE, -1); - } - SYSTEM_UNLOCK(); - return handle; -} /*********************************************************************** * AllocConsole (KERNEL32.103) @@ -622,17 +643,14 @@ HFILE32 CONSOLE_GetConsoleHandle(VOID) */ BOOL32 WINAPI AllocConsole(VOID) { - struct create_console_request req; - struct create_console_reply reply; + struct open_console_request req; + struct open_console_reply reply; PDB32 *pdb = PROCESS_Current(); CONSOLE *console; HANDLE32 hIn, hOut, hErr; SYSTEM_LOCK(); /* FIXME: really only need to lock the process */ - SetLastError(ERROR_CANNOT_MAKE); /* this might not be the right - error, but it's a good guess :) */ - console = (CONSOLE *)pdb->console; /* don't create a console if we already have one */ @@ -650,39 +668,46 @@ BOOL32 WINAPI AllocConsole(VOID) console->header.type = K32OBJ_CONSOLE; console->header.refcount = 1; - console->pid = -1; - console->title = NULL; console->nrofirs = 0; console->irs = HeapAlloc(GetProcessHeap(),0,1);; - console->mode = ENABLE_PROCESSED_INPUT - | ENABLE_LINE_INPUT - | ENABLE_ECHO_INPUT; - /* FIXME: we shouldn't probably use hardcoded UNIX values here. */ - console->infd = 0; - console->outfd = 1; - console->hread = console->hwrite = -1; - - CLIENT_SendRequest( REQ_CREATE_CONSOLE, -1, 1, &req, sizeof(req) ); - if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS) + + CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 ); + if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS) { K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } - console->hread = reply.handle_read; - console->hwrite = reply.handle_write; - if ((hIn = HANDLE_Alloc(pdb,&console->header, 0, TRUE, - reply.handle_read)) == INVALID_HANDLE_VALUE32) + req.output = 0; + req.access = GENERIC_READ | GENERIC_WRITE; + req.inherit = FALSE; + CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS) + { + K32OBJ_DecCount(&console->header); + SYSTEM_UNLOCK(); + return FALSE; + } + if ((hIn = HANDLE_Alloc(pdb,&console->header, req.access, + FALSE, reply.handle)) == INVALID_HANDLE_VALUE32) { - CLIENT_CloseHandle( reply.handle_write ); K32OBJ_DecCount(&console->header); SYSTEM_UNLOCK(); return FALSE; } - if ((hOut = HANDLE_Alloc(pdb,&console->header, 0, TRUE, - reply.handle_write)) == INVALID_HANDLE_VALUE32) + req.output = 1; + CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) ); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS) + { + CloseHandle(hIn); + K32OBJ_DecCount(&console->header); + SYSTEM_UNLOCK(); + return FALSE; + } + if ((hOut = HANDLE_Alloc(pdb,&console->header, req.access, + FALSE, reply.handle)) == INVALID_HANDLE_VALUE32) { CloseHandle(hIn); K32OBJ_DecCount(&console->header); @@ -742,14 +767,15 @@ UINT32 WINAPI GetConsoleOutputCP(VOID) */ BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); - - if (!console) { - FIXME(console,"(%d,%p), no console handle passed!\n",hcon,mode); - return FALSE; - } - *mode = console->mode; - K32OBJ_DecCount(&console->header); + struct get_console_mode_request req; + struct get_console_mode_reply reply; + + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, + K32OBJ_CONSOLE, GENERIC_READ )) == -1) + return FALSE; + CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req)); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE; + *mode = reply.mode; return TRUE; } @@ -767,16 +793,14 @@ BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode) */ BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode ) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); - - if (!console) { - FIXME(console,"(%d,%ld), no console handle passed!\n",hcon,mode); - return FALSE; - } - FIXME(console,"(0x%08x,0x%08lx): stub\n",hcon,mode); - console->mode = mode; - K32OBJ_DecCount(&console->header); - return TRUE; + struct set_console_mode_request req; + + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, + K32OBJ_CONSOLE, GENERIC_READ )) == -1) + return FALSE; + req.mode = mode; + CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req)); + return !CLIENT_WaitReply( NULL, NULL, 0 ); } @@ -785,14 +809,29 @@ BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode ) */ DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size) { - PDB32 *pdb = PROCESS_Current(); - CONSOLE *console= (CONSOLE *)pdb->console; - - if(console && console->title) { - lstrcpyn32A(title,console->title,size); - return strlen(title); + struct get_console_info_request req; + struct get_console_info_reply reply; + int len; + DWORD ret = 0; + HANDLE32 hcon; + + if ((hcon = CreateFile32A( "CONOUT$", GENERIC_READ, 0, NULL, + OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE32) + return 0; + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, + K32OBJ_CONSOLE, GENERIC_READ )) == -1) + { + CloseHandle( hcon ); + return 0; } - return 0; + CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); + if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size )) + { + if (len > sizeof(reply)+size) title[size-1] = 0; + ret = strlen(title); + } + CloseHandle( hcon ); + return ret; } @@ -809,14 +848,14 @@ DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size) */ DWORD WINAPI GetConsoleTitle32W( LPWSTR title, DWORD size ) { - PDB32 *pdb = PROCESS_Current(); - CONSOLE *console= (CONSOLE *)pdb->console; - if(console && console->title) - { - lstrcpynAtoW(title,console->title,size); - return (lstrlen32W(title)); - } - return 0; + char *tmp; + DWORD ret; + + if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0; + ret = GetConsoleTitle32A( tmp, size ); + lstrcpyAtoW( title, tmp ); + HeapFree( GetProcessHeap(), 0, tmp ); + return ret; } @@ -858,13 +897,7 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput, 0,4,2,6, 1,5,3,7, }; - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleOutput, K32OBJ_CONSOLE, 0, NULL); - - if (!console) { - FIXME(console,"(%d,...): no console handle!\n",hConsoleOutput); - return FALSE; - } - CONSOLE_make_complex(hConsoleOutput,console); + CONSOLE_make_complex(hConsoleOutput); buffer = HeapAlloc(GetProcessHeap(),0,100);; curbufsize = 100; @@ -897,7 +930,6 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput, sprintf(sbuf,"%c[0m",27);SADD(sbuf); WriteFile(hConsoleOutput,buffer,bufused,&res,NULL); HeapFree(GetProcessHeap(),0,buffer); - K32OBJ_DecCount(&console->header); return TRUE; } @@ -932,7 +964,7 @@ BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved ) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hConsoleInput ); int i,charsread = 0; LPSTR xbuf = (LPSTR)lpBuffer; @@ -1007,7 +1039,7 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput, LPINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hConsoleInput ); TRACE(console, "(%d,%p,%ld,%p)\n",hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead); @@ -1056,6 +1088,7 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput, */ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title) { +#if 0 PDB32 *pdb = PROCESS_Current(); CONSOLE *console; DWORD written; @@ -1079,6 +1112,7 @@ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title) } sprintf(titlestring,titleformat,title); +#if 0 /* only set title for complex console (own xterm) */ if (console->pid != -1) { WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),titlestring,strlen(titlestring),&written,NULL); @@ -1086,9 +1120,41 @@ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title) ret =TRUE; } else ret = TRUE; +#endif HeapFree( GetProcessHeap(), 0, titlestring ); K32OBJ_DecCount(&console->header); return ret; + + + +#endif + + struct set_console_info_request req; + struct get_console_info_reply info; + HANDLE32 hcon; + DWORD written; + + if ((hcon = CreateFile32A( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE32) + return FALSE; + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, + K32OBJ_CONSOLE, GENERIC_WRITE )) == -1) + goto error; + req.mask = SET_CONSOLE_INFO_TITLE; + CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req), + title, strlen(title)+1 ); + if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error; + if (CONSOLE_GetInfo( hcon, &info ) && info.pid) + { + /* only set title for complex console (own xterm) */ + WriteFile( hcon, "\033]2;", 4, &written, NULL ); + WriteFile( hcon, title, strlen(title), &written, NULL ); + WriteFile( hcon, "\a", 1, &written, NULL ); + } + return TRUE; + error: + CloseHandle( hcon ); + return FALSE; } @@ -1132,7 +1198,7 @@ BOOL32 WINAPI ReadConsoleInput32W(HANDLE32 hConsoleInput, */ BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hConsoleInput ); if (!console) return FALSE; @@ -1156,19 +1222,13 @@ BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos ) { char xbuf[20]; DWORD xlen; - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); - if (!console) { - FIXME(console,"(%d,...), no console handle!\n",hcon); - return FALSE; - } - CONSOLE_make_complex(hcon,console); + CONSOLE_make_complex(hcon); TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y ); /* x are columns, y rows */ sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1); /* FIXME: store internal if we start using own console buffers */ WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL); - K32OBJ_DecCount(&console->header); return TRUE; } @@ -1177,7 +1237,7 @@ BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos ) */ BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hcon ); if (!console) { FIXME(console,"(%d,%p), no console handle!\n",hcon,nrofevents); @@ -1211,7 +1271,7 @@ BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput, DWORD cInRecords, LPDWORD lpcRead) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL); + CONSOLE *console = CONSOLE_GetPtr( hConsoleInput ); if (!console) { FIXME(console,"(%d,%p,%ld,%p), No console handle passed!\n",hConsoleInput, pirBuffer, cInRecords, lpcRead); @@ -1260,17 +1320,14 @@ BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput, BOOL32 WINAPI GetConsoleCursorInfo32( HANDLE32 hcon, LPCONSOLE_CURSOR_INFO cinfo ) { - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); + struct get_console_info_reply reply; - if (!console) { - FIXME(console, "(%x,%p), no console handle!\n", hcon, cinfo); - return FALSE; + if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE; + if (cinfo) + { + cinfo->dwSize = reply.cursor_size; + cinfo->bVisible = reply.cursor_visible; } - TRACE(console, "(%x,%p)\n", hcon, cinfo); - if (!cinfo) - return FALSE; - *cinfo = console->cinfo; - K32OBJ_DecCount(&console->header); return TRUE; } @@ -1286,19 +1343,22 @@ BOOL32 WINAPI SetConsoleCursorInfo32( HANDLE32 hcon, /* [in] Handle to console screen buffer */ LPCONSOLE_CURSOR_INFO cinfo) /* [in] Address of cursor information */ { + struct set_console_info_request req; char buf[8]; DWORD xlen; - CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL); - TRACE(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible); - if (!console) - return FALSE; - CONSOLE_make_complex(hcon,console); - sprintf(buf,"%c[?25%c",27,cinfo->bVisible?'h':'l'); + if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon, + K32OBJ_CONSOLE, GENERIC_WRITE )) == -1) + return FALSE; + CONSOLE_make_complex(hcon); + sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l'); WriteFile(hcon,buf,strlen(buf),&xlen,NULL); - console->cinfo = *cinfo; - K32OBJ_DecCount(&console->header); - return TRUE; + + req.cursor_size = cinfo->dwSize; + req.cursor_visible = cinfo->bVisible; + req.mask = SET_CONSOLE_INFO_CURSOR; + CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) ); + return !CLIENT_WaitReply( NULL, NULL, 0 ); } diff --git a/win32/device.c b/win32/device.c index 9a6b1df9522..36b8b5a0631 100644 --- a/win32/device.c +++ b/win32/device.c @@ -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; - - dev->header.type = K32OBJ_DEVICE_IOCTL; - dev->header.refcount = 1; - dev->info = NULL; - - 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); + const struct VxDInfo *info; + for (info = VxDList; info->name; info++) + if (!lstrcmpi32A( info->name, filename )) + return FILE_CreateDevice( info->id | 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; + FIXME(win32, "Unknown VxD %s\n", filename); + 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, diff --git a/win32/process.c b/win32/process.c index f18817d2802..37443906230 100644 --- a/win32/process.c +++ b/win32/process.c @@ -19,45 +19,6 @@ #include "debug.h" -/********************************************************************** - * 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] */ -- GitLab