Redesign of the server communication protocol to allow arbitrary sized
data to be exchanged. Split request and reply structures to make backwards compatibility easier. Moved many console functions to dlls/kernel, added code page support, changed a few requests to behave properly with the new protocol.
This commit is contained in:
parent
8c2e573f9d
commit
9caa71eef4
|
@ -1220,14 +1220,14 @@ LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
|
|||
goto done;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( load_registry, len )
|
||||
SERVER_START_REQ( load_registry )
|
||||
{
|
||||
req->hkey = hkey;
|
||||
req->file = file;
|
||||
memcpy( server_data_ptr(req), subkey, len );
|
||||
ret = RtlNtStatusToDosError( SERVER_CALL() );
|
||||
wine_server_add_data( req, subkey, len );
|
||||
ret = RtlNtStatusToDosError( wine_server_call(req) );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
CloseHandle( file );
|
||||
|
||||
done:
|
||||
|
@ -1241,6 +1241,7 @@ LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
|
|||
*/
|
||||
LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
||||
{
|
||||
WCHAR buffer[MAX_PATH];
|
||||
HANDLE file;
|
||||
DWORD ret, len, err = GetLastError();
|
||||
|
||||
|
@ -1249,8 +1250,8 @@ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
|||
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
|
||||
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), NULL, 0 ) * sizeof(WCHAR);
|
||||
if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
|
||||
if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH )))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
|
||||
|
@ -1259,15 +1260,14 @@ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
|||
goto done;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( load_registry, len )
|
||||
SERVER_START_REQ( load_registry )
|
||||
{
|
||||
req->hkey = hkey;
|
||||
req->file = file;
|
||||
MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey),
|
||||
server_data_ptr(req), len/sizeof(WCHAR) );
|
||||
ret = RtlNtStatusToDosError( SERVER_CALL() );
|
||||
wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
|
||||
ret = RtlNtStatusToDosError( wine_server_call(req) );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
CloseHandle( file );
|
||||
|
||||
done:
|
||||
|
@ -1315,7 +1315,7 @@ LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
|
|||
{
|
||||
req->hkey = hkey;
|
||||
req->file = handle;
|
||||
ret = RtlNtStatusToDosError( SERVER_CALL() );
|
||||
ret = RtlNtStatusToDosError( wine_server_call( req ) );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ IMPORTS = ntdll
|
|||
|
||||
C_SRCS = \
|
||||
comm.c \
|
||||
console.c \
|
||||
debugger.c \
|
||||
format_msg.c \
|
||||
kernel_main.c \
|
||||
|
|
|
@ -379,7 +379,7 @@ static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
|
|||
req->handle = handle;
|
||||
req->flags = SERIALINFO_SET_ERROR;
|
||||
req->commerror = error;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -395,8 +395,8 @@ static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
|
|||
SERVER_START_REQ( get_serial_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
*lperror = req->commerror;
|
||||
ret = !wine_server_call_err( req );
|
||||
*lperror = reply->commerror;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -748,9 +748,9 @@ BOOL WINAPI GetCommMask(
|
|||
SERVER_START_REQ( get_serial_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (evtmask) *evtmask = req->eventmask;
|
||||
if (evtmask) *evtmask = reply->eventmask;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -781,7 +781,7 @@ BOOL WINAPI SetCommMask(
|
|||
req->handle = handle;
|
||||
req->flags = SERIALINFO_SET_MASK;
|
||||
req->eventmask = evtmask;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1347,13 +1347,13 @@ BOOL WINAPI GetCommTimeouts(
|
|||
SERVER_START_REQ( get_serial_info )
|
||||
{
|
||||
req->handle = hComm;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
lptimeouts->ReadIntervalTimeout = req->readinterval;
|
||||
lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
|
||||
lptimeouts->ReadTotalTimeoutConstant = req->readconst;
|
||||
lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
|
||||
lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
|
||||
lptimeouts->ReadIntervalTimeout = reply->readinterval;
|
||||
lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
|
||||
lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
|
||||
lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
|
||||
lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -1401,7 +1401,7 @@ BOOL WINAPI SetCommTimeouts(
|
|||
req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
|
||||
req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
|
||||
req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return FALSE;
|
||||
|
@ -1562,7 +1562,7 @@ static BOOL COMM_WaitCommEvent(
|
|||
req->count = 0;
|
||||
req->type = ASYNC_TYPE_WAIT;
|
||||
|
||||
ret=SERVER_CALL_ERR();
|
||||
ret=wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -0,0 +1,806 @@
|
|||
/*
|
||||
* Win32 kernel functions
|
||||
*
|
||||
* Copyright 1995 Martin von Loewis and Cameron Heide
|
||||
* Copyright 1997 Karl Garrison
|
||||
* Copyright 1998 John Richardson
|
||||
* Copyright 1998 Marcus Meissner
|
||||
* Copyright 2001 Eric Pouech
|
||||
* Copyright 2001 Alexandre Julliard
|
||||
*/
|
||||
|
||||
/* Reference applications:
|
||||
* - IDA (interactive disassembler) full version 3.75. Works.
|
||||
* - LYNX/W32. Works mostly, some keys crash it.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
#include "winerror.h"
|
||||
#include "wincon.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(console);
|
||||
|
||||
|
||||
static UINT console_input_codepage;
|
||||
static UINT console_output_codepage;
|
||||
|
||||
/* map input records to Ascii */
|
||||
static void input_records_WtoA( INPUT_RECORD *buffer, int count )
|
||||
{
|
||||
int i;
|
||||
char ch;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (buffer[i].EventType != KEY_EVENT) continue;
|
||||
WideCharToMultiByte( GetConsoleCP(), 0,
|
||||
&buffer[i].Event.KeyEvent.uChar.UnicodeChar, 1, &ch, 1, NULL, NULL );
|
||||
buffer[i].Event.KeyEvent.uChar.AsciiChar = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* map input records to Unicode */
|
||||
static void input_records_AtoW( INPUT_RECORD *buffer, int count )
|
||||
{
|
||||
int i;
|
||||
WCHAR ch;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (buffer[i].EventType != KEY_EVENT) continue;
|
||||
MultiByteToWideChar( GetConsoleCP(), 0,
|
||||
&buffer[i].Event.KeyEvent.uChar.AsciiChar, 1, &ch, 1 );
|
||||
buffer[i].Event.KeyEvent.uChar.UnicodeChar = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* map char infos to Ascii */
|
||||
static void char_info_WtoA( CHAR_INFO *buffer, int count )
|
||||
{
|
||||
char ch;
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
|
||||
&ch, 1, NULL, NULL );
|
||||
buffer->Char.AsciiChar = ch;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
/* map char infos to Unicode */
|
||||
static void char_info_AtoW( CHAR_INFO *buffer, int count )
|
||||
{
|
||||
WCHAR ch;
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
|
||||
buffer->Char.UnicodeChar = ch;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GetConsoleCP [KERNEL32.@] Returns the OEM code page for the console
|
||||
*
|
||||
* RETURNS
|
||||
* Code page code
|
||||
*/
|
||||
UINT WINAPI GetConsoleCP(VOID)
|
||||
{
|
||||
if (!console_input_codepage) console_input_codepage = GetOEMCP();
|
||||
return console_input_codepage;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SetConsoleCP [KERNEL32.@]
|
||||
*/
|
||||
BOOL WINAPI SetConsoleCP(UINT cp)
|
||||
{
|
||||
if (!IsValidCodePage( cp )) return FALSE;
|
||||
console_input_codepage = cp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetConsoleOutputCP (KERNEL32.@)
|
||||
*/
|
||||
UINT WINAPI GetConsoleOutputCP(VOID)
|
||||
{
|
||||
if (!console_output_codepage) console_output_codepage = GetOEMCP();
|
||||
return console_output_codepage;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SetConsoleOutputCP [KERNEL32.@] Set the output codepage used by the console
|
||||
*
|
||||
* PARAMS
|
||||
* cp [I] code page to set
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*/
|
||||
BOOL WINAPI SetConsoleOutputCP(UINT cp)
|
||||
{
|
||||
if (!IsValidCodePage( cp )) return FALSE;
|
||||
console_output_codepage = cp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* WriteConsoleInputA [KERNEL32.@]
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
|
||||
DWORD count, LPDWORD written )
|
||||
{
|
||||
INPUT_RECORD *recW;
|
||||
BOOL ret;
|
||||
|
||||
if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) ))) return FALSE;
|
||||
memcpy( recW, buffer, count );
|
||||
input_records_AtoW( recW, count );
|
||||
ret = WriteConsoleInputW( handle, recW, count, written );
|
||||
HeapFree( GetProcessHeap(), 0, recW );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* WriteConsoleInputW [KERNEL32.@]
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
|
||||
DWORD count, LPDWORD written )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%d,%p,%ld,%p)\n", handle, buffer, count, written);
|
||||
|
||||
if (written) *written = 0;
|
||||
SERVER_START_REQ( write_console_input )
|
||||
{
|
||||
req->handle = handle;
|
||||
wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (written) *written = reply->written;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WriteConsoleOutputA (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
|
||||
COORD size, COORD coord, LPSMALL_RECT region )
|
||||
{
|
||||
int y;
|
||||
BOOL ret;
|
||||
COORD new_size, new_coord;
|
||||
CHAR_INFO *ciw;
|
||||
|
||||
new_size.X = min( region->Right - region->Left + 1, size.X - coord.X );
|
||||
new_size.Y = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
|
||||
|
||||
if (new_size.X <= 0 || new_size.Y <= 0)
|
||||
{
|
||||
region->Bottom = region->Top + new_size.Y - 1;
|
||||
region->Right = region->Left + new_size.X - 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* only copy the useful rectangle */
|
||||
if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
|
||||
return FALSE;
|
||||
for (y = 0; y < new_size.Y; y++)
|
||||
{
|
||||
memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X],
|
||||
new_size.X * sizeof(CHAR_INFO) );
|
||||
char_info_AtoW( ciw, new_size.X );
|
||||
}
|
||||
new_coord.X = new_coord.Y = 0;
|
||||
ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region );
|
||||
if (ciw) HeapFree( GetProcessHeap(), 0, ciw );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WriteConsoleOutputW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
|
||||
COORD size, COORD coord, LPSMALL_RECT region )
|
||||
{
|
||||
int width, height, y;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
TRACE("(%x,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
|
||||
hConsoleOutput, lpBuffer, size.X, size.Y, coord.X, coord.Y,
|
||||
region->Left, region->Top, region->Right, region->Bottom);
|
||||
|
||||
width = min( region->Right - region->Left + 1, size.X - coord.X );
|
||||
height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
SERVER_START_REQ( write_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = region->Left;
|
||||
req->y = region->Top + y;
|
||||
req->mode = CHAR_INFO_MODE_TEXTATTR;
|
||||
req->wrap = FALSE;
|
||||
wine_server_add_data( req, &lpBuffer[(y + coord.Y) * size.X + coord.X],
|
||||
width * sizeof(CHAR_INFO));
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
width = min( width, reply->width - region->Left );
|
||||
height = min( height, reply->height - region->Top );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) break;
|
||||
}
|
||||
}
|
||||
region->Bottom = region->Top + height - 1;
|
||||
region->Right = region->Left + width - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* WriteConsoleOutputCharacterA [KERNEL32.@] Copies character to consecutive
|
||||
* cells in the console screen buffer
|
||||
*
|
||||
* PARAMS
|
||||
* hConsoleOutput [I] Handle to screen buffer
|
||||
* str [I] Pointer to buffer with chars to write
|
||||
* length [I] Number of cells to write to
|
||||
* coord [I] Coords of first cell
|
||||
* lpNumCharsWritten [O] Pointer to number of cells written
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
|
||||
COORD coord, LPDWORD lpNumCharsWritten )
|
||||
{
|
||||
BOOL ret;
|
||||
LPWSTR strW;
|
||||
DWORD lenW;
|
||||
|
||||
TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
|
||||
debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
|
||||
|
||||
lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
|
||||
|
||||
if (lpNumCharsWritten) *lpNumCharsWritten = 0;
|
||||
|
||||
if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
|
||||
MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
|
||||
|
||||
ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
|
||||
HeapFree( GetProcessHeap(), 0, strW );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* WriteConsoleOutputAttribute [KERNEL32.@] Sets attributes for some cells in
|
||||
* the console screen buffer
|
||||
*
|
||||
* PARAMS
|
||||
* hConsoleOutput [I] Handle to screen buffer
|
||||
* attr [I] Pointer to buffer with write attributes
|
||||
* length [I] Number of cells to write to
|
||||
* coord [I] Coords of first cell
|
||||
* lpNumAttrsWritten [O] Pointer to number of cells written
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
|
||||
COORD coord, LPDWORD lpNumAttrsWritten )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
|
||||
|
||||
SERVER_START_REQ( write_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = coord.X;
|
||||
req->y = coord.Y;
|
||||
req->mode = CHAR_INFO_MODE_ATTR;
|
||||
req->wrap = TRUE;
|
||||
wine_server_add_data( req, attr, length * sizeof(WORD) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FillConsoleOutputCharacterA [KERNEL32.@]
|
||||
*
|
||||
* PARAMS
|
||||
* hConsoleOutput [I] Handle to screen buffer
|
||||
* ch [I] Character to write
|
||||
* length [I] Number of cells to write to
|
||||
* coord [I] Coords of first cell
|
||||
* lpNumCharsWritten [O] Pointer to number of cells written
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*/
|
||||
BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
|
||||
COORD coord, LPDWORD lpNumCharsWritten )
|
||||
{
|
||||
WCHAR wch;
|
||||
|
||||
MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
|
||||
return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FillConsoleOutputCharacterW [KERNEL32.@] Writes characters to console
|
||||
*
|
||||
* PARAMS
|
||||
* hConsoleOutput [I] Handle to screen buffer
|
||||
* ch [I] Character to write
|
||||
* length [I] Number of cells to write to
|
||||
* coord [I] Coords of first cell
|
||||
* lpNumCharsWritten [O] Pointer to number of cells written
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*/
|
||||
BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
|
||||
COORD coord, LPDWORD lpNumCharsWritten)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%d,%s,%ld,(%dx%d),%p)\n",
|
||||
hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
|
||||
|
||||
SERVER_START_REQ( fill_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = coord.X;
|
||||
req->y = coord.Y;
|
||||
req->mode = CHAR_INFO_MODE_TEXT;
|
||||
req->wrap = TRUE;
|
||||
req->data.ch = ch;
|
||||
req->count = length;
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FillConsoleOutputAttribute [KERNEL32.@] Sets attributes for console
|
||||
*
|
||||
* PARAMS
|
||||
* hConsoleOutput [I] Handle to screen buffer
|
||||
* attr [I] Color attribute to write
|
||||
* length [I] Number of cells to write to
|
||||
* coord [I] Coords of first cell
|
||||
* lpNumAttrsWritten [O] Pointer to number of cells written
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*/
|
||||
BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
|
||||
COORD coord, LPDWORD lpNumAttrsWritten )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%d,%d,%ld,(%dx%d),%p)\n",
|
||||
hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
|
||||
|
||||
SERVER_START_REQ( fill_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = coord.X;
|
||||
req->y = coord.Y;
|
||||
req->mode = CHAR_INFO_MODE_ATTR;
|
||||
req->wrap = TRUE;
|
||||
req->data.attr = attr;
|
||||
req->count = length;
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleOutputCharacterA [KERNEL32.@]
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
|
||||
COORD coord, LPDWORD read_count)
|
||||
{
|
||||
DWORD read;
|
||||
BOOL ret;
|
||||
LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
|
||||
|
||||
if (read_count) *read_count = 0;
|
||||
if (!wptr) return FALSE;
|
||||
|
||||
if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
|
||||
{
|
||||
read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
|
||||
if (read_count) *read_count = read;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, wptr );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleOutputCharacterW [KERNEL32.@]
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
|
||||
COORD coord, LPDWORD read_count )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE( "(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
|
||||
|
||||
SERVER_START_REQ( read_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = coord.X;
|
||||
req->y = coord.Y;
|
||||
req->mode = CHAR_INFO_MODE_TEXT;
|
||||
req->wrap = TRUE;
|
||||
wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleOutputAttribute [KERNEL32.@]
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
|
||||
COORD coord, LPDWORD read_count)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%d,%p,%ld,%dx%d,%p)\n",
|
||||
hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
|
||||
|
||||
SERVER_START_REQ( read_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = coord.X;
|
||||
req->y = coord.Y;
|
||||
req->mode = CHAR_INFO_MODE_ATTR;
|
||||
req->wrap = TRUE;
|
||||
wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleOutputA [KERNEL32.@]
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
|
||||
COORD coord, LPSMALL_RECT region )
|
||||
{
|
||||
BOOL ret;
|
||||
int y;
|
||||
|
||||
ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
|
||||
if (ret && region->Right >= region->Left)
|
||||
{
|
||||
for (y = 0; y <= region->Bottom - region->Top; y++)
|
||||
{
|
||||
char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
|
||||
region->Right - region->Left + 1 );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleOutputW [KERNEL32.@]
|
||||
*
|
||||
* NOTE: The NT4 (sp5) kernel crashes on me if size is (0,0). I don't
|
||||
* think we need to be *that* compatible. -- AJ
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
|
||||
COORD coord, LPSMALL_RECT region )
|
||||
{
|
||||
int width, height, y;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
width = min( region->Right - region->Left + 1, size.X - coord.X );
|
||||
height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
SERVER_START_REQ( read_console_output )
|
||||
{
|
||||
req->handle = hConsoleOutput;
|
||||
req->x = region->Left;
|
||||
req->y = region->Top + y;
|
||||
req->mode = CHAR_INFO_MODE_TEXTATTR;
|
||||
req->wrap = FALSE;
|
||||
wine_server_set_reply( req, &lpBuffer[(y+coord.Y) * size.X + coord.X],
|
||||
width * sizeof(CHAR_INFO) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
width = min( width, reply->width - region->Left );
|
||||
height = min( height, reply->height - region->Top );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) break;
|
||||
}
|
||||
}
|
||||
region->Bottom = region->Top + height - 1;
|
||||
region->Right = region->Left + width - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* ReadConsoleInputA [KERNEL32.@] Reads data from a console
|
||||
*
|
||||
* PARAMS
|
||||
* handle [I] Handle to console input buffer
|
||||
* buffer [O] Address of buffer for read data
|
||||
* count [I] Number of records to read
|
||||
* pRead [O] Address of number of records read
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE
|
||||
* Failure: FALSE
|
||||
*/
|
||||
BOOL WINAPI ReadConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
|
||||
{
|
||||
DWORD read;
|
||||
|
||||
if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
|
||||
input_records_WtoA( buffer, read );
|
||||
if (pRead) *pRead = read;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PeekConsoleInputA (KERNEL32.@)
|
||||
*
|
||||
* Gets 'count' first events (or less) from input queue.
|
||||
*/
|
||||
BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
|
||||
{
|
||||
DWORD read;
|
||||
|
||||
if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
|
||||
input_records_WtoA( buffer, read );
|
||||
if (pRead) *pRead = read;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PeekConsoleInputW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI PeekConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( read_console_input )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->flush = FALSE;
|
||||
wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (read) *read = count ? reply->read : 0;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetNumberOfConsoleInputEvents (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( read_console_input )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->flush = FALSE;
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (nrofevents) *nrofevents = reply->read;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FlushConsoleInputBuffer (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( read_console_input )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->flush = TRUE;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetConsoleTitleA (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetConsoleTitleA( LPCSTR title )
|
||||
{
|
||||
LPWSTR titleW;
|
||||
BOOL ret;
|
||||
|
||||
DWORD len = MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, NULL, 0 );
|
||||
if (!(titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
|
||||
MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, titleW, len );
|
||||
ret = SetConsoleTitleW(titleW);
|
||||
HeapFree(GetProcessHeap(), 0, titleW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetConsoleTitleA (KERNEL32.@)
|
||||
*/
|
||||
DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
|
||||
{
|
||||
WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
|
||||
DWORD ret;
|
||||
|
||||
if (!ptr) return 0;
|
||||
ret = GetConsoleTitleW( ptr, size );
|
||||
if (ret)
|
||||
{
|
||||
WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
|
||||
ret = strlen(title);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GetConsoleTitleW [KERNEL32.@] Retrieves title string for console
|
||||
*
|
||||
* PARAMS
|
||||
* title [O] Address of buffer for title
|
||||
* size [I] Size of buffer
|
||||
*
|
||||
* RETURNS
|
||||
* Success: Length of string copied
|
||||
* Failure: 0
|
||||
*/
|
||||
DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
|
||||
SERVER_START_REQ( get_console_input_info )
|
||||
{
|
||||
req->handle = 0;
|
||||
wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
ret = wine_server_reply_size(reply) / sizeof(WCHAR);
|
||||
title[ret] = 0;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetLargestConsoleWindowSize (KERNEL32.@)
|
||||
*
|
||||
* NOTE
|
||||
* This should return a COORD, but calling convention for returning
|
||||
* structures is different between Windows and gcc on i386.
|
||||
*
|
||||
* VERSION: [i386]
|
||||
*/
|
||||
#ifdef __i386__
|
||||
#undef GetLargestConsoleWindowSize
|
||||
DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
|
||||
{
|
||||
COORD c;
|
||||
c.X = 80;
|
||||
c.Y = 24;
|
||||
return *(DWORD *)&c;
|
||||
}
|
||||
#endif /* defined(__i386__) */
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetLargestConsoleWindowSize (KERNEL32.@)
|
||||
*
|
||||
* NOTE
|
||||
* This should return a COORD, but calling convention for returning
|
||||
* structures is different between Windows and gcc on i386.
|
||||
*
|
||||
* VERSION: [!i386]
|
||||
*/
|
||||
#ifndef __i386__
|
||||
COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
|
||||
{
|
||||
COORD c;
|
||||
c.X = 80;
|
||||
c.Y = 24;
|
||||
return c;
|
||||
}
|
||||
#endif /* defined(__i386__) */
|
|
@ -36,78 +36,78 @@ BOOL WINAPI WaitForDebugEvent(
|
|||
for (;;)
|
||||
{
|
||||
HANDLE wait = 0;
|
||||
debug_event_t *data;
|
||||
SERVER_START_VAR_REQ( wait_debug_event, sizeof(*data) )
|
||||
debug_event_t data;
|
||||
SERVER_START_REQ( wait_debug_event )
|
||||
{
|
||||
req->get_handle = (timeout != 0);
|
||||
if (!(ret = !SERVER_CALL_ERR())) goto done;
|
||||
wine_server_set_reply( req, &data, sizeof(data) );
|
||||
if (!(ret = !wine_server_call_err( req ))) goto done;
|
||||
|
||||
if (!server_data_size(req)) /* timeout */
|
||||
if (!wine_server_reply_size(reply)) /* timeout */
|
||||
{
|
||||
wait = req->wait;
|
||||
wait = reply->wait;
|
||||
ret = FALSE;
|
||||
goto done;
|
||||
}
|
||||
data = server_data_ptr(req);
|
||||
event->dwDebugEventCode = data->code;
|
||||
event->dwProcessId = (DWORD)req->pid;
|
||||
event->dwThreadId = (DWORD)req->tid;
|
||||
switch(data->code)
|
||||
event->dwDebugEventCode = data.code;
|
||||
event->dwProcessId = (DWORD)reply->pid;
|
||||
event->dwThreadId = (DWORD)reply->tid;
|
||||
switch(data.code)
|
||||
{
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
event->u.Exception.ExceptionRecord = data->info.exception.record;
|
||||
event->u.Exception.dwFirstChance = data->info.exception.first;
|
||||
event->u.Exception.ExceptionRecord = data.info.exception.record;
|
||||
event->u.Exception.dwFirstChance = data.info.exception.first;
|
||||
break;
|
||||
case CREATE_THREAD_DEBUG_EVENT:
|
||||
event->u.CreateThread.hThread = data->info.create_thread.handle;
|
||||
event->u.CreateThread.lpThreadLocalBase = data->info.create_thread.teb;
|
||||
event->u.CreateThread.lpStartAddress = data->info.create_thread.start;
|
||||
event->u.CreateThread.hThread = data.info.create_thread.handle;
|
||||
event->u.CreateThread.lpThreadLocalBase = data.info.create_thread.teb;
|
||||
event->u.CreateThread.lpStartAddress = data.info.create_thread.start;
|
||||
break;
|
||||
case CREATE_PROCESS_DEBUG_EVENT:
|
||||
event->u.CreateProcessInfo.hFile = data->info.create_process.file;
|
||||
event->u.CreateProcessInfo.hProcess = data->info.create_process.process;
|
||||
event->u.CreateProcessInfo.hThread = data->info.create_process.thread;
|
||||
event->u.CreateProcessInfo.lpBaseOfImage = data->info.create_process.base;
|
||||
event->u.CreateProcessInfo.dwDebugInfoFileOffset = data->info.create_process.dbg_offset;
|
||||
event->u.CreateProcessInfo.nDebugInfoSize = data->info.create_process.dbg_size;
|
||||
event->u.CreateProcessInfo.lpThreadLocalBase = data->info.create_process.teb;
|
||||
event->u.CreateProcessInfo.lpStartAddress = data->info.create_process.start;
|
||||
event->u.CreateProcessInfo.lpImageName = data->info.create_process.name;
|
||||
event->u.CreateProcessInfo.fUnicode = data->info.create_process.unicode;
|
||||
if (data->info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
|
||||
event->u.CreateProcessInfo.hFile = data.info.create_process.file;
|
||||
event->u.CreateProcessInfo.hProcess = data.info.create_process.process;
|
||||
event->u.CreateProcessInfo.hThread = data.info.create_process.thread;
|
||||
event->u.CreateProcessInfo.lpBaseOfImage = data.info.create_process.base;
|
||||
event->u.CreateProcessInfo.dwDebugInfoFileOffset = data.info.create_process.dbg_offset;
|
||||
event->u.CreateProcessInfo.nDebugInfoSize = data.info.create_process.dbg_size;
|
||||
event->u.CreateProcessInfo.lpThreadLocalBase = data.info.create_process.teb;
|
||||
event->u.CreateProcessInfo.lpStartAddress = data.info.create_process.start;
|
||||
event->u.CreateProcessInfo.lpImageName = data.info.create_process.name;
|
||||
event->u.CreateProcessInfo.fUnicode = data.info.create_process.unicode;
|
||||
if (data.info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
|
||||
break;
|
||||
case EXIT_THREAD_DEBUG_EVENT:
|
||||
event->u.ExitThread.dwExitCode = data->info.exit.exit_code;
|
||||
event->u.ExitThread.dwExitCode = data.info.exit.exit_code;
|
||||
break;
|
||||
case EXIT_PROCESS_DEBUG_EVENT:
|
||||
event->u.ExitProcess.dwExitCode = data->info.exit.exit_code;
|
||||
event->u.ExitProcess.dwExitCode = data.info.exit.exit_code;
|
||||
break;
|
||||
case LOAD_DLL_DEBUG_EVENT:
|
||||
event->u.LoadDll.hFile = data->info.load_dll.handle;
|
||||
event->u.LoadDll.lpBaseOfDll = data->info.load_dll.base;
|
||||
event->u.LoadDll.dwDebugInfoFileOffset = data->info.load_dll.dbg_offset;
|
||||
event->u.LoadDll.nDebugInfoSize = data->info.load_dll.dbg_size;
|
||||
event->u.LoadDll.lpImageName = data->info.load_dll.name;
|
||||
event->u.LoadDll.fUnicode = data->info.load_dll.unicode;
|
||||
if (data->info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
|
||||
event->u.LoadDll.hFile = data.info.load_dll.handle;
|
||||
event->u.LoadDll.lpBaseOfDll = data.info.load_dll.base;
|
||||
event->u.LoadDll.dwDebugInfoFileOffset = data.info.load_dll.dbg_offset;
|
||||
event->u.LoadDll.nDebugInfoSize = data.info.load_dll.dbg_size;
|
||||
event->u.LoadDll.lpImageName = data.info.load_dll.name;
|
||||
event->u.LoadDll.fUnicode = data.info.load_dll.unicode;
|
||||
if (data.info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
|
||||
break;
|
||||
case UNLOAD_DLL_DEBUG_EVENT:
|
||||
event->u.UnloadDll.lpBaseOfDll = data->info.unload_dll.base;
|
||||
event->u.UnloadDll.lpBaseOfDll = data.info.unload_dll.base;
|
||||
break;
|
||||
case OUTPUT_DEBUG_STRING_EVENT:
|
||||
event->u.DebugString.lpDebugStringData = data->info.output_string.string;
|
||||
event->u.DebugString.fUnicode = data->info.output_string.unicode;
|
||||
event->u.DebugString.nDebugStringLength = data->info.output_string.length;
|
||||
event->u.DebugString.lpDebugStringData = data.info.output_string.string;
|
||||
event->u.DebugString.fUnicode = data.info.output_string.unicode;
|
||||
event->u.DebugString.nDebugStringLength = data.info.output_string.length;
|
||||
break;
|
||||
case RIP_EVENT:
|
||||
event->u.RipInfo.dwError = data->info.rip_info.error;
|
||||
event->u.RipInfo.dwType = data->info.rip_info.type;
|
||||
event->u.RipInfo.dwError = data.info.rip_info.error;
|
||||
event->u.RipInfo.dwType = data.info.rip_info.type;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
/* nothing */ ;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (ret) return TRUE;
|
||||
if (!wait) break;
|
||||
res = WaitForSingleObject( wait, timeout );
|
||||
|
@ -140,7 +140,7 @@ BOOL WINAPI ContinueDebugEvent(
|
|||
req->pid = (void *)pid;
|
||||
req->tid = (void *)tid;
|
||||
req->status = status;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -163,7 +163,7 @@ BOOL WINAPI DebugActiveProcess(
|
|||
SERVER_START_REQ( debug_process )
|
||||
{
|
||||
req->pid = (void *)pid;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -184,7 +184,7 @@ void WINAPI OutputDebugStringA(
|
|||
req->string = (void *)str;
|
||||
req->unicode = 0;
|
||||
req->length = strlen(str) + 1;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
WARN("%s\n", str);
|
||||
|
@ -205,7 +205,7 @@ void WINAPI OutputDebugStringW(
|
|||
req->string = (void *)str;
|
||||
req->unicode = 1;
|
||||
req->length = (lstrlenW(str) + 1) * sizeof(WCHAR);
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
WARN("%s\n", debugstr_w(str));
|
||||
|
@ -278,7 +278,7 @@ BOOL WINAPI IsDebuggerPresent(void)
|
|||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = GetCurrentProcess();
|
||||
if (!SERVER_CALL_ERR()) ret = req->debugged;
|
||||
if (!wine_server_call_err( req )) ret = reply->debugged;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -30,25 +30,16 @@ DEFAULT_DEBUG_CHANNEL(win32);
|
|||
HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
|
||||
BOOL initial_state, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->manual_reset = manual_reset;
|
||||
req->initial_state = initial_state;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return CreateEventW( sa, manual_reset, initial_state, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,17 +65,17 @@ HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
|
|||
SetLastError( ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_event )
|
||||
{
|
||||
req->manual_reset = manual_reset;
|
||||
req->initial_state = initial_state;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -103,23 +94,16 @@ HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
|
|||
*/
|
||||
HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return OpenEventW( access, inherit, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return OpenEventW( access, inherit, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -135,15 +119,15 @@ HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_event )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -160,7 +144,7 @@ static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->op = op;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -248,24 +232,16 @@ VOID WINAPI VWin32_EventSet(HANDLE event)
|
|||
*/
|
||||
HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return CreateMutexW( sa, owner, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->owned = owner;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return CreateMutexW( sa, owner, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -281,47 +257,35 @@ HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_mutex )
|
||||
{
|
||||
req->owned = owner;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mutexes
|
||||
*/
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* OpenMutexA (KERNEL32.@)
|
||||
*/
|
||||
HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return OpenMutexW( access, inherit, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return OpenMutexW( access, inherit, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -337,15 +301,15 @@ HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_mutex )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -359,7 +323,7 @@ BOOL WINAPI ReleaseMutex( HANDLE handle )
|
|||
SERVER_START_REQ( release_mutex )
|
||||
{
|
||||
req->handle = handle;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -376,34 +340,16 @@ BOOL WINAPI ReleaseMutex( HANDLE handle )
|
|||
*/
|
||||
HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
/* Check parameters */
|
||||
if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
|
||||
|
||||
if ((max <= 0) || (initial < 0) || (initial > max))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
if (len >= MAX_PATH)
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->initial = (unsigned int)initial;
|
||||
req->max = (unsigned int)max;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return CreateSemaphoreW( sa, initial, max, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -429,17 +375,17 @@ HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
|
|||
return 0;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_semaphore )
|
||||
{
|
||||
req->initial = (unsigned int)initial;
|
||||
req->max = (unsigned int)max;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -449,23 +395,16 @@ HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
|
|||
*/
|
||||
HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return OpenSemaphoreW( access, inherit, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return OpenSemaphoreW( access, inherit, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -481,15 +420,15 @@ HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_semaphore )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -518,35 +457,18 @@ HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
|
|||
DWORD nOutBufferSize, DWORD nInBufferSize,
|
||||
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p): stub\n",
|
||||
debugstr_a(name), dwOpenMode, dwPipeMode, nMaxInstances,
|
||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
|
||||
if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
|
||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
|
||||
|
||||
if (len >= MAX_PATH)
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->openmode = dwOpenMode;
|
||||
req->pipemode = dwPipeMode;
|
||||
req->maxinstances = nMaxInstances;
|
||||
req->outsize = nOutBufferSize;
|
||||
req->insize = nInBufferSize;
|
||||
req->timeout = nDefaultTimeOut;
|
||||
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
TRACE("Returned %d\n",ret);
|
||||
return ret;
|
||||
return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
|
||||
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
|
||||
}
|
||||
|
||||
|
||||
|
@ -570,7 +492,7 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_named_pipe )
|
||||
{
|
||||
req->openmode = dwOpenMode;
|
||||
req->pipemode = dwPipeMode;
|
||||
|
@ -578,13 +500,12 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
|
|||
req->outsize = nOutBufferSize;
|
||||
req->insize = nInBufferSize;
|
||||
req->timeout = nDefaultTimeOut;
|
||||
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -613,99 +534,40 @@ static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
|
|||
SetEvent(overlapped->hEvent);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WaitNamedPipeA (KERNEL32.@)
|
||||
*/
|
||||
static BOOL SYNC_WaitNamedPipeA (LPCSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
|
||||
{
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
BOOL ret;
|
||||
|
||||
if (len >= MAX_PATH)
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->timeout = nTimeOut;
|
||||
req->overlapped = overlapped;
|
||||
req->func = SYNC_CompletePipeOverlapped;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WaitNamedPipeA (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
|
||||
{
|
||||
BOOL ret;
|
||||
OVERLAPPED ov;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
|
||||
if (!name) return WaitNamedPipeW( NULL, nTimeOut );
|
||||
|
||||
memset(&ov,0,sizeof ov);
|
||||
ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
|
||||
if (!ov.hEvent)
|
||||
return FALSE;
|
||||
|
||||
/* expect to fail with STATUS_PENDING */
|
||||
ret = SYNC_WaitNamedPipeA(name, nTimeOut, &ov);
|
||||
if(ret)
|
||||
{
|
||||
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
|
||||
{
|
||||
SetLastError(ov.Internal);
|
||||
ret = (ov.Internal==STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(ov.hEvent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WaitNamedPipeW (KERNEL32.@)
|
||||
*/
|
||||
static BOOL SYNC_WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
|
||||
{
|
||||
DWORD len = name ? strlenW(name) : 0;
|
||||
BOOL ret;
|
||||
|
||||
if (len >= MAX_PATH)
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->timeout = nTimeOut;
|
||||
req->overlapped = overlapped;
|
||||
req->func = SYNC_CompletePipeOverlapped;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
ret = !SERVER_CALL_ERR();
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
return ret;
|
||||
return WaitNamedPipeW( buffer, nTimeOut );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WaitNamedPipeW (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
||||
{
|
||||
DWORD len = name ? strlenW(name) : 0;
|
||||
BOOL ret;
|
||||
OVERLAPPED ov;
|
||||
|
||||
if (len >= MAX_PATH)
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
|
||||
|
||||
memset(&ov,0,sizeof ov);
|
||||
|
@ -713,7 +575,16 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
|||
if (!ov.hEvent)
|
||||
return FALSE;
|
||||
|
||||
ret = SYNC_WaitNamedPipeW(name, nTimeOut, &ov);
|
||||
SERVER_START_REQ( wait_named_pipe )
|
||||
{
|
||||
req->timeout = nTimeOut;
|
||||
req->overlapped = &ov;
|
||||
req->func = SYNC_CompletePipeOverlapped;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if(ret)
|
||||
{
|
||||
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
|
||||
|
@ -722,9 +593,7 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
|||
ret = (ov.Internal==STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(ov.hEvent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -746,7 +615,7 @@ static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
|||
req->handle = hPipe;
|
||||
req->overlapped = overlapped;
|
||||
req->func = SYNC_CompletePipeOverlapped;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -798,7 +667,7 @@ BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
|
|||
SERVER_START_REQ( disconnect_named_pipe )
|
||||
{
|
||||
req->handle = hPipe;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -835,15 +704,11 @@ BOOL WINAPI GetNamedPipeInfo(
|
|||
SERVER_START_REQ( get_named_pipe_info )
|
||||
{
|
||||
req->handle = hNamedPipe;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
if(lpFlags)
|
||||
*lpFlags = req->flags;
|
||||
if(lpOutputBufferSize)
|
||||
*lpOutputBufferSize = req->outsize;
|
||||
if(lpInputBufferSize)
|
||||
*lpInputBufferSize = req->outsize;
|
||||
if(lpMaxInstances)
|
||||
*lpMaxInstances = req->maxinstances;
|
||||
ret = !wine_server_call_err( req );
|
||||
if(lpFlags) *lpFlags = reply->flags;
|
||||
if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
|
||||
if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
|
||||
if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -206,8 +206,8 @@ HANDLE WINAPI CreateToolhelp32Snapshot( DWORD flags, DWORD process )
|
|||
req->flags = flags & ~TH32CS_INHERIT;
|
||||
req->inherit = (flags & TH32CS_INHERIT) != 0;
|
||||
req->pid = (void *)process;
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) ret = INVALID_HANDLE_VALUE;
|
||||
|
@ -234,13 +234,13 @@ static BOOL TOOLHELP_Thread32Next( HANDLE handle, LPTHREADENTRY32 lpte, BOOL fir
|
|||
{
|
||||
req->handle = handle;
|
||||
req->reset = first;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
lpte->cntUsage = req->count;
|
||||
lpte->th32ThreadID = (DWORD)req->tid;
|
||||
lpte->th32OwnerProcessID = (DWORD)req->pid;
|
||||
lpte->tpBasePri = req->base_pri;
|
||||
lpte->tpDeltaPri = req->delta_pri;
|
||||
lpte->cntUsage = reply->count;
|
||||
lpte->th32ThreadID = (DWORD)reply->tid;
|
||||
lpte->th32OwnerProcessID = (DWORD)reply->pid;
|
||||
lpte->tpBasePri = reply->base_pri;
|
||||
lpte->tpDeltaPri = reply->delta_pri;
|
||||
lpte->dwFlags = 0; /* SDK: "reserved; do not use" */
|
||||
}
|
||||
}
|
||||
|
@ -287,15 +287,15 @@ static BOOL TOOLHELP_Process32Next( HANDLE handle, LPPROCESSENTRY32 lppe, BOOL f
|
|||
{
|
||||
req->handle = handle;
|
||||
req->reset = first;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
lppe->cntUsage = req->count;
|
||||
lppe->th32ProcessID = (DWORD)req->pid;
|
||||
lppe->cntUsage = reply->count;
|
||||
lppe->th32ProcessID = (DWORD)reply->pid;
|
||||
lppe->th32DefaultHeapID = 0; /* FIXME */
|
||||
lppe->th32ModuleID = 0; /* FIXME */
|
||||
lppe->cntThreads = req->threads;
|
||||
lppe->cntThreads = reply->threads;
|
||||
lppe->th32ParentProcessID = 0; /* FIXME */
|
||||
lppe->pcPriClassBase = req->priority;
|
||||
lppe->pcPriClassBase = reply->priority;
|
||||
lppe->dwFlags = -1; /* FIXME */
|
||||
lppe->szExeFile[0] = 0; /* FIXME */
|
||||
}
|
||||
|
@ -345,15 +345,15 @@ static BOOL TOOLHELP_Module32Next( HANDLE handle, LPMODULEENTRY32 lpme, BOOL fir
|
|||
{
|
||||
req->handle = handle;
|
||||
req->reset = first;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
lpme->th32ModuleID = 0; /* toolhelp internal id, never used */
|
||||
lpme->th32ProcessID = (DWORD)req->pid;
|
||||
lpme->th32ProcessID = (DWORD)reply->pid;
|
||||
lpme->GlblcntUsage = 0; /* FIXME */
|
||||
lpme->ProccntUsage = 0; /* FIXME */
|
||||
lpme->modBaseAddr = req->base;
|
||||
lpme->ProccntUsage = 0; /* FIXME */
|
||||
lpme->modBaseAddr = reply->base;
|
||||
lpme->modBaseSize = 0; /* FIXME */
|
||||
lpme->hModule = (DWORD)req->base;
|
||||
lpme->hModule = (DWORD)reply->base;
|
||||
lpme->szModule[0] = 0; /* FIXME */
|
||||
lpme->szExePath[0] = 0; /* FIXME */
|
||||
}
|
||||
|
|
|
@ -115,29 +115,28 @@ static int send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *c
|
|||
int ret;
|
||||
HANDLE handle = 0;
|
||||
|
||||
SERVER_START_VAR_REQ( queue_exception_event, sizeof(*rec)+sizeof(*context) )
|
||||
SERVER_START_REQ( queue_exception_event )
|
||||
{
|
||||
CONTEXT *context_ptr = server_data_ptr(req);
|
||||
EXCEPTION_RECORD *rec_ptr = (EXCEPTION_RECORD *)(context_ptr + 1);
|
||||
req->first = first_chance;
|
||||
*rec_ptr = *rec;
|
||||
*context_ptr = *context;
|
||||
if (!SERVER_CALL()) handle = req->handle;
|
||||
wine_server_add_data( req, context, sizeof(*context) );
|
||||
wine_server_add_data( req, rec, sizeof(*rec) );
|
||||
if (!wine_server_call( req )) handle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!handle) return 0; /* no debugger present or other error */
|
||||
|
||||
/* No need to wait on the handle since the process gets suspended
|
||||
* once the event is passed to the debugger, so when we get back
|
||||
* here the event has been continued already.
|
||||
*/
|
||||
SERVER_START_VAR_REQ( get_exception_status, sizeof(*context) )
|
||||
SERVER_START_REQ( get_exception_status )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!SERVER_CALL()) *context = *(CONTEXT *)server_data_ptr(req);
|
||||
ret = req->status;
|
||||
wine_server_set_reply( req, context, sizeof(*context) );
|
||||
wine_server_call( req );
|
||||
ret = reply->status;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
NtClose( handle );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->exit_code = exit_code;
|
||||
ret = SERVER_CALL();
|
||||
self = !ret && req->self;
|
||||
ret = wine_server_call( req );
|
||||
self = !ret && reply->self;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (self) exit( exit_code );
|
||||
|
@ -159,9 +159,9 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->exit_code = exit_code;
|
||||
ret = SERVER_CALL();
|
||||
self = !ret && req->self;
|
||||
last = req->last;
|
||||
ret = wine_server_call( req );
|
||||
self = !ret && reply->self;
|
||||
last = reply->last;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -1033,6 +1033,4 @@ debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem
|
|||
@ cdecl __wine_get_wmain_args(ptr) __wine_get_wmain_args
|
||||
|
||||
# Server interface
|
||||
@ cdecl -norelay wine_server_call(ptr long) wine_server_call
|
||||
@ cdecl -norelay wine_server_alloc_req(ptr long) wine_server_alloc_req
|
||||
@ cdecl -norelay __wine_server_exception_handler(ptr ptr ptr ptr) __wine_server_exception_handler
|
||||
@ cdecl -norelay wine_server_call(ptr) wine_server_call
|
||||
|
|
|
@ -222,8 +222,8 @@ NTSTATUS WINAPI NtClose( HANDLE Handle )
|
|||
SERVER_START_REQ( close_handle )
|
||||
{
|
||||
req->handle = Handle;
|
||||
ret = SERVER_CALL();
|
||||
if (!ret && req->fd != -1) close( req->fd );
|
||||
ret = wine_server_call( req );
|
||||
if (!ret && reply->fd != -1) close( reply->fd );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
396
dlls/ntdll/reg.c
396
dlls/ntdll/reg.c
|
@ -35,39 +35,29 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT
|
|||
PULONG dispos )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
DWORD len = attr->ObjectName->Length;
|
||||
|
||||
TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
|
||||
debugstr_us(class), options, access, retkey );
|
||||
|
||||
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
|
||||
len += sizeof(WCHAR); /* for storing name length */
|
||||
if (class)
|
||||
{
|
||||
len += class->Length;
|
||||
if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
|
||||
if (!retkey) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
SERVER_START_VAR_REQ( create_key, len )
|
||||
SERVER_START_REQ( create_key )
|
||||
{
|
||||
WCHAR *data = server_data_ptr(req);
|
||||
|
||||
req->parent = attr->RootDirectory;
|
||||
req->access = access;
|
||||
req->options = options;
|
||||
req->modif = 0;
|
||||
|
||||
*data++ = attr->ObjectName->Length;
|
||||
memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
|
||||
if (!(ret = SERVER_CALL()))
|
||||
req->namelen = attr->ObjectName->Length;
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
if (class) wine_server_add_data( req, class->Buffer, class->Length );
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
*retkey = req->hkey;
|
||||
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
|
||||
*retkey = reply->hkey;
|
||||
if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
TRACE("<- 0x%04x\n", *retkey);
|
||||
return ret;
|
||||
}
|
||||
|
@ -92,15 +82,15 @@ NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTR
|
|||
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
|
||||
if (!retkey) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
SERVER_START_VAR_REQ( open_key, len )
|
||||
SERVER_START_REQ( open_key )
|
||||
{
|
||||
req->parent = attr->RootDirectory;
|
||||
req->access = access;
|
||||
memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
|
||||
ret = SERVER_CALL();
|
||||
*retkey = req->hkey;
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*retkey = reply->hkey;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
TRACE("<- 0x%04x\n", *retkey);
|
||||
return ret;
|
||||
}
|
||||
|
@ -119,7 +109,7 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
|
|||
SERVER_START_REQ( delete_key )
|
||||
{
|
||||
req->hkey = hkey;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -137,102 +127,101 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
|
|||
TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
|
||||
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
SERVER_START_VAR_REQ( delete_key_value, name->Length )
|
||||
SERVER_START_REQ( delete_key_value )
|
||||
{
|
||||
req->hkey = hkey;
|
||||
memcpy( server_data_ptr(req), name->Buffer, name->Length );
|
||||
ret = SERVER_CALL();
|
||||
wine_server_add_data( req, name->Buffer, name->Length );
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* fill_key_info
|
||||
* enumerate_key
|
||||
*
|
||||
* Helper function for NtQueryKey and NtEnumerateKey
|
||||
* Implementation of NtQueryKey and NtEnumerateKey
|
||||
*/
|
||||
static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
|
||||
DWORD *result_len, const struct enum_key_request *req )
|
||||
{
|
||||
WCHAR *name_ptr = server_data_ptr(req);
|
||||
int name_size = *name_ptr++;
|
||||
WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
|
||||
int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
|
||||
int fixed_size;
|
||||
LARGE_INTEGER modif;
|
||||
static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
|
||||
RtlSecondsSince1970ToTime( req->modif, (FILETIME *)&modif );
|
||||
{
|
||||
NTSTATUS ret;
|
||||
void *data_ptr;
|
||||
size_t fixed_size;
|
||||
|
||||
switch(info_class)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
{
|
||||
KEY_BASIC_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.NameLength = name_size;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
class_size = 0;
|
||||
}
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
{
|
||||
KEY_FULL_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = class_size;
|
||||
keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
|
||||
keyinfo.SubKeys = req->subkeys;
|
||||
keyinfo.MaxNameLen = req->max_subkey;
|
||||
keyinfo.MaxClassLen = req->max_class;
|
||||
keyinfo.Values = req->values;
|
||||
keyinfo.MaxValueNameLen = req->max_value;
|
||||
keyinfo.MaxValueDataLen = req->max_data;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
name_size = 0;
|
||||
}
|
||||
break;
|
||||
case KeyNodeInformation:
|
||||
{
|
||||
KEY_NODE_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = class_size;
|
||||
keyinfo.ClassOffset = fixed_size + name_size;
|
||||
if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
|
||||
keyinfo.NameLength = name_size;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
}
|
||||
break;
|
||||
case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
|
||||
case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
|
||||
case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
|
||||
default:
|
||||
FIXME("Information class not implemented\n");
|
||||
FIXME( "Information class %d not implemented\n", info_class );
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
fixed_size = (char *)data_ptr - (char *)info;
|
||||
|
||||
*result_len = fixed_size + name_size + class_size;
|
||||
if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
|
||||
length -= fixed_size;
|
||||
|
||||
/* copy the name */
|
||||
if (name_size)
|
||||
SERVER_START_REQ( enum_key )
|
||||
{
|
||||
memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
|
||||
if (length < name_size) return STATUS_BUFFER_OVERFLOW;
|
||||
length -= name_size;
|
||||
}
|
||||
req->hkey = handle;
|
||||
req->index = index;
|
||||
req->info_class = info_class;
|
||||
if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
LARGE_INTEGER modif;
|
||||
|
||||
/* copy the class */
|
||||
if (class_size)
|
||||
{
|
||||
memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
|
||||
if (length < class_size) return STATUS_BUFFER_OVERFLOW;
|
||||
RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
|
||||
|
||||
switch(info_class)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
{
|
||||
KEY_BASIC_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.NameLength = reply->namelen;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
}
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
{
|
||||
KEY_FULL_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = wine_server_reply_size(reply);
|
||||
keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
|
||||
keyinfo.SubKeys = reply->subkeys;
|
||||
keyinfo.MaxNameLen = reply->max_subkey;
|
||||
keyinfo.MaxClassLen = reply->max_class;
|
||||
keyinfo.Values = reply->values;
|
||||
keyinfo.MaxValueNameLen = reply->max_value;
|
||||
keyinfo.MaxValueDataLen = reply->max_data;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
}
|
||||
break;
|
||||
case KeyNodeInformation:
|
||||
{
|
||||
KEY_NODE_INFORMATION keyinfo;
|
||||
fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
|
||||
keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
|
||||
keyinfo.NameLength = reply->namelen;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
*result_len = fixed_size + reply->total;
|
||||
if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -247,23 +236,9 @@ static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWO
|
|||
NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
|
||||
/* -1 means query key, so avoid it here */
|
||||
if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
|
||||
|
||||
SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
|
||||
{
|
||||
req->hkey = handle;
|
||||
req->index = index;
|
||||
req->full = (info_class == KeyFullInformation);
|
||||
if (!(ret = SERVER_CALL()))
|
||||
{
|
||||
ret = fill_key_info( info_class, info, length, result_len, req );
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return enumerate_key( handle, index, info_class, info, length, result_len );
|
||||
}
|
||||
|
||||
|
||||
|
@ -274,20 +249,7 @@ NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLAS
|
|||
NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
|
||||
{
|
||||
req->hkey = handle;
|
||||
req->index = -1;
|
||||
req->full = (info_class == KeyFullInformation);
|
||||
if (!(ret = SERVER_CALL()))
|
||||
{
|
||||
ret = fill_key_info( info_class, info, length, result_len, req );
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return enumerate_key( handle, -1, info_class, info, length, result_len );
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,98 +306,39 @@ NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index,
|
|||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
UCHAR *data_ptr;
|
||||
WCHAR *name_ptr;
|
||||
int fixed_size = 0, name_len = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
|
||||
void *ptr;
|
||||
size_t fixed_size;
|
||||
|
||||
TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
|
||||
|
||||
/* compute the length we want to retrieve */
|
||||
switch(info_class)
|
||||
{
|
||||
case KeyValueBasicInformation:
|
||||
name_ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name;
|
||||
data_ptr = NULL;
|
||||
fixed_size = (char *)name_ptr - (char *)info;
|
||||
break;
|
||||
case KeyValueFullInformation:
|
||||
name_ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name;
|
||||
data_ptr = (UCHAR *)name_ptr;
|
||||
fixed_size = (char *)name_ptr - (char *)info;
|
||||
break;
|
||||
case KeyValuePartialInformation:
|
||||
name_ptr = NULL;
|
||||
data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
|
||||
fixed_size = (char *)data_ptr - (char *)info;
|
||||
break;
|
||||
case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
|
||||
case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
|
||||
case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
|
||||
default:
|
||||
FIXME( "Information class %d not implemented\n", info_class );
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (length > fixed_size) data_len = length - fixed_size;
|
||||
fixed_size = (char *)ptr - (char *)info;
|
||||
|
||||
do
|
||||
SERVER_START_REQ( enum_key_value )
|
||||
{
|
||||
size_t reqlen = data_len + sizeof(WCHAR);
|
||||
if (name_ptr && !offset) reqlen += MAX_PATH*sizeof(WCHAR);
|
||||
reqlen = min( reqlen, REQUEST_MAX_VAR_SIZE );
|
||||
|
||||
SERVER_START_VAR_REQ( enum_key_value, reqlen )
|
||||
req->hkey = handle;
|
||||
req->index = index;
|
||||
req->info_class = info_class;
|
||||
if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
req->hkey = handle;
|
||||
req->index = index;
|
||||
req->offset = offset;
|
||||
|
||||
if (!(ret = SERVER_CALL()))
|
||||
{
|
||||
size_t size = server_data_size(req) - sizeof(WCHAR);
|
||||
WCHAR *name = server_data_ptr(req);
|
||||
if (!offset) /* name is only present on the first request */
|
||||
{
|
||||
name_len = *name++;
|
||||
size -= name_len;
|
||||
if (name_ptr)
|
||||
{
|
||||
if (name_len > data_len) /* overflow */
|
||||
{
|
||||
memcpy( name_ptr, name, data_len );
|
||||
data_len = 0;
|
||||
ret = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( name_ptr, name, name_len );
|
||||
data_len -= name_len;
|
||||
if (data_ptr) data_ptr += name_len;
|
||||
}
|
||||
}
|
||||
name += name_len / sizeof(WCHAR);
|
||||
}
|
||||
else name++; /* skip 0 length */
|
||||
|
||||
if (data_ptr)
|
||||
{
|
||||
size = min( size, data_len );
|
||||
memcpy( data_ptr + offset, name, size );
|
||||
offset += size;
|
||||
data_len -= size;
|
||||
}
|
||||
type = req->type;
|
||||
total_len = req->len;
|
||||
}
|
||||
copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
|
||||
wine_server_reply_size(reply) - reply->namelen );
|
||||
*result_len = fixed_size + reply->total;
|
||||
if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
if (ret) return ret;
|
||||
} while (data_len && data_ptr && offset < total_len);
|
||||
|
||||
*result_len = total_len + fixed_size + (name_ptr ? name_len : 0);
|
||||
|
||||
if (data_ptr && offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
copy_key_value_info( info_class, info, length, type, name_len, total_len );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -452,7 +355,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
|
|||
{
|
||||
NTSTATUS ret;
|
||||
UCHAR *data_ptr;
|
||||
int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
|
||||
int fixed_size = 0;
|
||||
|
||||
TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
|
||||
|
||||
|
@ -477,45 +380,21 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
|
|||
FIXME( "Information class %d not implemented\n", info_class );
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (data_ptr && length > fixed_size) data_len = length - fixed_size;
|
||||
|
||||
do
|
||||
SERVER_START_REQ( get_key_value )
|
||||
{
|
||||
size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
|
||||
reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
|
||||
|
||||
SERVER_START_VAR_REQ( get_key_value, reqlen )
|
||||
req->hkey = handle;
|
||||
wine_server_add_data( req, name->Buffer, name->Length );
|
||||
if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
WCHAR *nameptr = server_data_ptr(req);
|
||||
|
||||
req->hkey = handle;
|
||||
req->offset = offset;
|
||||
*nameptr++ = name->Length;
|
||||
memcpy( nameptr, name->Buffer, name->Length );
|
||||
|
||||
if (!(ret = SERVER_CALL()))
|
||||
{
|
||||
size_t size = min( server_data_size(req), data_len );
|
||||
type = req->type;
|
||||
total_len = req->len;
|
||||
if (size)
|
||||
{
|
||||
memcpy( data_ptr + offset, server_data_ptr(req), size );
|
||||
offset += size;
|
||||
data_len -= size;
|
||||
}
|
||||
}
|
||||
copy_key_value_info( info_class, info, length, reply->type,
|
||||
0, wine_server_reply_size(reply) );
|
||||
*result_len = fixed_size + reply->total;
|
||||
if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
if (ret) return ret;
|
||||
} while (data_len && offset < total_len);
|
||||
|
||||
*result_len = total_len + fixed_size;
|
||||
|
||||
if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
copy_key_value_info( info_class, info, length, type, 0, total_len );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -651,36 +530,21 @@ NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG Ti
|
|||
ULONG type, const void *data, ULONG count )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
ULONG namelen, pos;
|
||||
|
||||
TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
|
||||
|
||||
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
namelen = name->Length + sizeof(WCHAR); /* for storing length */
|
||||
pos = 0;
|
||||
|
||||
do
|
||||
SERVER_START_REQ( set_key_value )
|
||||
{
|
||||
ULONG len = count - pos;
|
||||
if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen;
|
||||
|
||||
SERVER_START_VAR_REQ( set_key_value, namelen + len )
|
||||
{
|
||||
WCHAR *name_ptr = server_data_ptr(req);
|
||||
|
||||
req->hkey = hkey;
|
||||
req->type = type;
|
||||
req->total = count;
|
||||
req->offset = pos;
|
||||
*name_ptr++ = name->Length;
|
||||
memcpy( name_ptr, name->Buffer, name->Length );
|
||||
memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len );
|
||||
pos += len;
|
||||
ret = SERVER_CALL();
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
} while (!ret && pos < count);
|
||||
req->hkey = hkey;
|
||||
req->type = type;
|
||||
req->namelen = name->Length;
|
||||
wine_server_add_data( req, name->Buffer, name->Length );
|
||||
wine_server_add_data( req, data, count );
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,16 +36,16 @@ NTSTATUS WINAPI NtCreateSemaphore( OUT PHANDLE SemaphoreHandle,
|
|||
if ((MaximumCount <= 0) || (InitialCount > MaximumCount))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
SERVER_START_VAR_REQ( create_semaphore, len )
|
||||
SERVER_START_REQ( create_semaphore )
|
||||
{
|
||||
req->initial = InitialCount;
|
||||
req->max = MaximumCount;
|
||||
req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
|
||||
if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
|
||||
ret = SERVER_CALL();
|
||||
*SemaphoreHandle = req->handle;
|
||||
if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*SemaphoreHandle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -59,15 +59,15 @@ NTSTATUS WINAPI NtOpenSemaphore( OUT PHANDLE SemaphoreHandle,
|
|||
DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_VAR_REQ( open_semaphore, len )
|
||||
SERVER_START_REQ( open_semaphore )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
|
||||
if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
|
||||
ret = SERVER_CALL();
|
||||
*SemaphoreHandle = req->handle;
|
||||
if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*SemaphoreHandle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, PULONG previous
|
|||
{
|
||||
req->handle = handle;
|
||||
req->count = count;
|
||||
if (!(ret = SERVER_CALL()))
|
||||
if (!(ret = wine_server_call( req )))
|
||||
{
|
||||
if (previous) *previous = req->prev_count;
|
||||
if (previous) *previous = reply->prev_count;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -123,16 +123,16 @@ NTSTATUS WINAPI NtCreateEvent(
|
|||
DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_VAR_REQ( create_event, len )
|
||||
SERVER_START_REQ( create_event )
|
||||
{
|
||||
req->manual_reset = ManualReset;
|
||||
req->initial_state = InitialState;
|
||||
req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
|
||||
if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
|
||||
ret = SERVER_CALL();
|
||||
*EventHandle = req->handle;
|
||||
if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*EventHandle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -148,15 +148,15 @@ NTSTATUS WINAPI NtOpenEvent(
|
|||
DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_VAR_REQ( open_event, len )
|
||||
SERVER_START_REQ( open_event )
|
||||
{
|
||||
req->access = DesiredAccess;
|
||||
req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
|
||||
if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
|
||||
ret = SERVER_CALL();
|
||||
*EventHandle = req->handle;
|
||||
if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
|
||||
ret = wine_server_call( req );
|
||||
*EventHandle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, PULONG NumberOfThreadsReleased )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->op = SET_EVENT;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -195,7 +195,7 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, PULONG NumberOfThreadsReleased )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->op = RESET_EVENT;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -226,7 +226,7 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, PULONG PulseCount )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->op = PULSE_EVENT;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -200,26 +200,6 @@ inline static int is_unicode_message( UINT message )
|
|||
|
||||
#undef SET
|
||||
|
||||
/* compute the total size of the packed data */
|
||||
inline static size_t get_data_total_size( const struct packed_message *data )
|
||||
{
|
||||
int i;
|
||||
size_t total = 0;
|
||||
for (i = 0; i < data->count; i++) total += data->size[i];
|
||||
return total;
|
||||
}
|
||||
|
||||
/* copy all the data of a packed message into a single dest buffer */
|
||||
inline static void copy_all_data( void *dest, const struct packed_message *data )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < data->count; i++)
|
||||
{
|
||||
memcpy( dest, data->data[i], data->size[i] );
|
||||
dest = (char *)dest + data->size[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* add a data field to a packed message */
|
||||
inline static void push_data( struct packed_message *data, const void *ptr, size_t size )
|
||||
{
|
||||
|
@ -1032,7 +1012,7 @@ static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
|
|||
static void reply_message( struct received_message_info *info, LRESULT result, BOOL remove )
|
||||
{
|
||||
struct packed_message data;
|
||||
int replied = info->flags & ISMEX_REPLIED;
|
||||
int i, replied = info->flags & ISMEX_REPLIED;
|
||||
|
||||
if (info->flags & ISMEX_NOTIFY) return; /* notify messages don't get replies */
|
||||
if (!remove && replied) return; /* replied already */
|
||||
|
@ -1044,34 +1024,14 @@ static void reply_message( struct received_message_info *info, LRESULT result, B
|
|||
{
|
||||
pack_reply( info->msg.hwnd, info->msg.message, info->msg.wParam,
|
||||
info->msg.lParam, result, &data );
|
||||
if (data.count)
|
||||
{
|
||||
size_t total = get_data_total_size( &data );
|
||||
|
||||
if (total > REQUEST_MAX_VAR_SIZE)
|
||||
{
|
||||
FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
|
||||
total );
|
||||
total = REQUEST_MAX_VAR_SIZE;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( reply_message, total )
|
||||
{
|
||||
req->result = result;
|
||||
req->remove = remove;
|
||||
copy_all_data( server_data_ptr(req), &data );
|
||||
SERVER_CALL();
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SERVER_START_REQ( reply_message )
|
||||
{
|
||||
req->result = result;
|
||||
req->remove = remove;
|
||||
SERVER_CALL();
|
||||
for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -1170,7 +1130,6 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
|
|||
*/
|
||||
BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
|
||||
{
|
||||
BOOL ret;
|
||||
LRESULT result;
|
||||
ULONG_PTR extra_info = 0;
|
||||
MESSAGEQUEUE *queue = QUEUE_Current();
|
||||
|
@ -1180,41 +1139,44 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
|
|||
|
||||
for (;;)
|
||||
{
|
||||
NTSTATUS res;
|
||||
void *buffer = NULL;
|
||||
size_t size = 0;
|
||||
size_t size = 0, buffer_size = 0;
|
||||
|
||||
SERVER_START_VAR_REQ( get_message, REQUEST_MAX_VAR_SIZE )
|
||||
do /* loop while buffer is too small */
|
||||
{
|
||||
req->flags = flags;
|
||||
req->get_win = hwnd;
|
||||
req->get_first = first;
|
||||
req->get_last = last;
|
||||
if ((ret = !SERVER_CALL()))
|
||||
if (buffer_size && !(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size )))
|
||||
return FALSE;
|
||||
SERVER_START_REQ( get_message )
|
||||
{
|
||||
info.type = req->type;
|
||||
info.msg.hwnd = req->win;
|
||||
info.msg.message = req->msg;
|
||||
info.msg.wParam = req->wparam;
|
||||
info.msg.lParam = req->lparam;
|
||||
info.msg.time = req->time;
|
||||
info.msg.pt.x = req->x;
|
||||
info.msg.pt.y = req->y;
|
||||
extra_info = req->info;
|
||||
|
||||
if ((size = server_data_size(req)))
|
||||
req->flags = flags;
|
||||
req->get_win = hwnd;
|
||||
req->get_first = first;
|
||||
req->get_last = last;
|
||||
if (buffer_size) wine_server_set_reply( req, buffer, buffer_size );
|
||||
if (!(res = wine_server_call( req )))
|
||||
{
|
||||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
|
||||
{
|
||||
ERR("out of memory for message data\n");
|
||||
ret = FALSE;
|
||||
}
|
||||
else memcpy( buffer, server_data_ptr(req), size );
|
||||
size = wine_server_reply_size( reply );
|
||||
info.type = reply->type;
|
||||
info.msg.hwnd = reply->win;
|
||||
info.msg.message = reply->msg;
|
||||
info.msg.wParam = reply->wparam;
|
||||
info.msg.lParam = reply->lparam;
|
||||
info.msg.time = reply->time;
|
||||
info.msg.pt.x = reply->x;
|
||||
info.msg.pt.y = reply->y;
|
||||
extra_info = reply->info;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
buffer_size = reply->total;
|
||||
}
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
} while (res == STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
if (!ret) return FALSE; /* no message available */
|
||||
if (res) return FALSE;
|
||||
|
||||
TRACE( "got type %d msg %x hwnd %x wp %x lp %lx\n",
|
||||
info.type, info.msg.message, info.msg.hwnd, info.msg.wParam, info.msg.lParam );
|
||||
|
@ -1241,26 +1203,27 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
|
|||
info.msg.wParam, info.msg.lParam, size );
|
||||
/* ignore it */
|
||||
reply_message( &info, 0, TRUE );
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
break;
|
||||
case MSG_HARDWARE_RAW:
|
||||
if (!MSG_process_raw_hardware_message( &info.msg, extra_info,
|
||||
hwnd, first, last, flags & GET_MSG_REMOVE ))
|
||||
continue;
|
||||
goto next;
|
||||
/* fall through */
|
||||
case MSG_HARDWARE_COOKED:
|
||||
if (!MSG_process_cooked_hardware_message( &info.msg, extra_info,
|
||||
flags & GET_MSG_REMOVE ))
|
||||
{
|
||||
flags |= GET_MSG_REMOVE_LAST;
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
queue->GetMessagePosVal = MAKELONG( info.msg.pt.x, info.msg.pt.y );
|
||||
/* fall through */
|
||||
case MSG_POSTED:
|
||||
queue->GetMessageExtraInfoVal = extra_info;
|
||||
*msg = info.msg;
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1271,7 +1234,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
|
|||
info.msg.lParam, (info.type != MSG_ASCII) );
|
||||
reply_message( &info, result, TRUE );
|
||||
queue->receive_info = old_info;
|
||||
|
||||
next:
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
}
|
||||
}
|
||||
|
@ -1298,10 +1261,10 @@ static void wait_message_reply( UINT flags )
|
|||
req->wake_mask = (flags & SMTO_BLOCK) ? 0 : QS_SENDMESSAGE;
|
||||
req->changed_mask = QS_SMRESULT | req->wake_mask;
|
||||
req->skip_wait = 1;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
wake_bits = req->wake_bits;
|
||||
changed_bits = req->changed_bits;
|
||||
wake_bits = reply->wake_bits;
|
||||
changed_bits = reply->changed_bits;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -1338,8 +1301,9 @@ static void wait_message_reply( UINT flags )
|
|||
static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info *info,
|
||||
size_t *reply_size )
|
||||
{
|
||||
struct packed_message data;
|
||||
unsigned int res;
|
||||
int timeout = -1;
|
||||
int i, timeout = -1;
|
||||
|
||||
if (info->type != MSG_NOTIFY &&
|
||||
info->type != MSG_CALLBACK &&
|
||||
|
@ -1347,47 +1311,17 @@ static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info
|
|||
info->timeout != INFINITE)
|
||||
timeout = info->timeout;
|
||||
|
||||
data.count = 0;
|
||||
if (info->type == MSG_OTHER_PROCESS)
|
||||
{
|
||||
struct packed_message data;
|
||||
*reply_size = pack_message( info->hwnd, info->msg, info->wparam, info->lparam, &data );
|
||||
|
||||
if (data.count == -1)
|
||||
{
|
||||
WARN( "cannot pack message %x\n", info->msg );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (data.size[0]) /* need to send extra data along with the message */
|
||||
{
|
||||
size_t total = get_data_total_size( &data );
|
||||
|
||||
if (total > REQUEST_MAX_VAR_SIZE)
|
||||
{
|
||||
FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
|
||||
total );
|
||||
total = REQUEST_MAX_VAR_SIZE;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( send_message, total )
|
||||
{
|
||||
req->id = (void *)dest_tid;
|
||||
req->type = MSG_OTHER_PROCESS;
|
||||
req->win = info->hwnd;
|
||||
req->msg = info->msg;
|
||||
req->wparam = info->wparam;
|
||||
req->lparam = info->lparam;
|
||||
req->time = GetCurrentTime();
|
||||
req->timeout = timeout;
|
||||
copy_all_data( server_data_ptr(req), &data );
|
||||
res = SERVER_CALL();
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* no extra data, or not inter-process message */
|
||||
SERVER_START_REQ( send_message )
|
||||
{
|
||||
req->id = (void *)dest_tid;
|
||||
|
@ -1398,19 +1332,17 @@ static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info
|
|||
req->lparam = info->lparam;
|
||||
req->time = GetCurrentTime();
|
||||
req->timeout = timeout;
|
||||
res = SERVER_CALL();
|
||||
for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
|
||||
if ((res = wine_server_call( req )))
|
||||
{
|
||||
if (res == STATUS_INVALID_PARAMETER)
|
||||
/* FIXME: find a STATUS_ value for this one */
|
||||
SetLastError( ERROR_INVALID_THREAD_ID );
|
||||
else
|
||||
SetLastError( RtlNtStatusToDosError(res) );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
done:
|
||||
if (res)
|
||||
{
|
||||
if (res == STATUS_INVALID_PARAMETER)
|
||||
/* FIXME: find a STATUS_ value for this one */
|
||||
SetLastError( ERROR_INVALID_THREAD_ID );
|
||||
else
|
||||
SetLastError( RtlNtStatusToDosError(res) );
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
@ -1424,35 +1356,28 @@ static LRESULT retrieve_reply( const struct send_message_info *info,
|
|||
size_t reply_size, LRESULT *result )
|
||||
{
|
||||
NTSTATUS status;
|
||||
void *reply_data = NULL;
|
||||
|
||||
if (reply_size)
|
||||
{
|
||||
if (reply_size > REQUEST_MAX_VAR_SIZE)
|
||||
if (!(reply_data = HeapAlloc( GetProcessHeap(), 0, reply_size )))
|
||||
{
|
||||
WARN( "reply_size %d too large, reply may be truncated\n", reply_size );
|
||||
reply_size = REQUEST_MAX_VAR_SIZE;
|
||||
WARN( "no memory for reply %d bytes, will be truncated\n", reply_size );
|
||||
reply_size = 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( get_message_reply, reply_size )
|
||||
{
|
||||
req->cancel = 1;
|
||||
if (!(status = SERVER_CALL()))
|
||||
{
|
||||
*result = req->result;
|
||||
unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam,
|
||||
server_data_ptr(req), server_data_size(req) );
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
}
|
||||
else
|
||||
SERVER_START_REQ( get_message_reply )
|
||||
{
|
||||
SERVER_START_REQ( get_message_reply )
|
||||
{
|
||||
req->cancel = 1;
|
||||
if (!(status = SERVER_CALL())) *result = req->result;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
req->cancel = 1;
|
||||
if (reply_size) wine_server_set_reply( req, reply_data, reply_size );
|
||||
if (!(status = wine_server_call( req ))) *result = reply->result;
|
||||
reply_size = wine_server_reply_size( reply );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!status && reply_size)
|
||||
unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam, reply_data, reply_size );
|
||||
|
||||
if (reply_data) HeapFree( GetProcessHeap(), 0, reply_data );
|
||||
|
||||
TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
|
||||
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam,
|
||||
|
@ -1955,10 +1880,10 @@ BOOL WINAPI GetMessageW( MSG *msg, HWND hwnd, UINT first, UINT last )
|
|||
req->wake_mask = QS_SENDMESSAGE;
|
||||
req->changed_mask = mask;
|
||||
req->skip_wait = 1;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
wake_bits = req->wake_bits;
|
||||
changed_bits = req->changed_bits;
|
||||
wake_bits = reply->wake_bits;
|
||||
changed_bits = reply->changed_bits;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
|
|
@ -24,24 +24,30 @@
|
|||
*/
|
||||
static property_data_t *get_properties( HWND hwnd, int *count )
|
||||
{
|
||||
property_data_t *ret = NULL;
|
||||
property_data_t *data;
|
||||
int total = 32;
|
||||
|
||||
SERVER_START_VAR_REQ( get_window_properties, REQUEST_MAX_VAR_SIZE )
|
||||
while (total)
|
||||
{
|
||||
req->window = hwnd;
|
||||
if (!SERVER_CALL())
|
||||
int res = 0;
|
||||
if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break;
|
||||
*count = 0;
|
||||
SERVER_START_REQ( get_window_properties )
|
||||
{
|
||||
size_t size = server_data_size(req);
|
||||
if (size)
|
||||
{
|
||||
property_data_t *data = server_data_ptr(req);
|
||||
if ((ret = HeapAlloc( GetProcessHeap(), 0, size ))) memcpy( ret, data, size );
|
||||
*count = size / sizeof(*data);
|
||||
}
|
||||
req->window = hwnd;
|
||||
wine_server_add_data( req, data, total * sizeof(*data) );
|
||||
if (!wine_server_call( req )) res = reply->total;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (res && res <= total)
|
||||
{
|
||||
*count = res;
|
||||
return data;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, data );
|
||||
total = res; /* restart with larger buffer */
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,7 +108,7 @@ HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
|
|||
{
|
||||
req->window = hwnd;
|
||||
req->atom = atom;
|
||||
if (!SERVER_CALL_ERR()) ret = req->handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -124,7 +130,7 @@ HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
|
|||
{
|
||||
req->window = hwnd;
|
||||
req->atom = atom;
|
||||
if (!SERVER_CALL_ERR()) ret = req->handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -148,7 +154,7 @@ BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
|
|||
req->atom = atom;
|
||||
req->string = (HIWORD(str) != 0);
|
||||
req->handle = handle;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -174,7 +180,7 @@ BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
|
|||
req->atom = atom;
|
||||
req->string = (HIWORD(str) != 0);
|
||||
req->handle = handle;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -217,7 +223,7 @@ HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
|
|||
{
|
||||
req->window = hwnd;
|
||||
req->atom = atom;
|
||||
if (!SERVER_CALL_ERR()) ret = req->handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ static void _enable_event(SOCKET s, unsigned int event,
|
|||
req->mask = event;
|
||||
req->sstate = sstate;
|
||||
req->cstate = cstate;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -247,8 +247,8 @@ static int _is_blocking(SOCKET s)
|
|||
req->service = FALSE;
|
||||
req->s_event = 0;
|
||||
req->c_event = 0;
|
||||
SERVER_CALL();
|
||||
ret = (req->state & FD_WINE_NONBLOCKING) == 0;
|
||||
wine_server_call( req );
|
||||
ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -263,8 +263,8 @@ static unsigned int _get_sock_mask(SOCKET s)
|
|||
req->service = FALSE;
|
||||
req->s_event = 0;
|
||||
req->c_event = 0;
|
||||
SERVER_CALL();
|
||||
ret = req->mask;
|
||||
wine_server_call( req );
|
||||
ret = reply->mask;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -279,18 +279,19 @@ static void _sync_sock_state(SOCKET s)
|
|||
|
||||
static int _get_sock_error(SOCKET s, unsigned int bit)
|
||||
{
|
||||
int ret;
|
||||
SERVER_START_VAR_REQ( get_socket_event, FD_MAX_EVENTS*sizeof(int) )
|
||||
int events[FD_MAX_EVENTS];
|
||||
|
||||
SERVER_START_REQ( get_socket_event )
|
||||
{
|
||||
req->handle = s;
|
||||
req->service = FALSE;
|
||||
req->s_event = 0;
|
||||
req->c_event = 0;
|
||||
SERVER_CALL();
|
||||
ret = *((int *)server_data_ptr(req) + bit);
|
||||
wine_server_set_reply( req, events, sizeof(events) );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
SERVER_END_REQ;
|
||||
return events[bit];
|
||||
}
|
||||
|
||||
static void WINSOCK_DeleteIData(void)
|
||||
|
@ -900,8 +901,8 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
|
|||
req->lhandle = s;
|
||||
req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
|
||||
req->inherit = TRUE;
|
||||
set_error( SERVER_CALL() );
|
||||
as = (SOCKET)req->handle;
|
||||
set_error( wine_server_call( req ) );
|
||||
as = (SOCKET)reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (as)
|
||||
|
@ -2318,8 +2319,8 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
|
|||
req->protocol = protocol;
|
||||
req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
|
||||
req->inherit = TRUE;
|
||||
set_error( SERVER_CALL() );
|
||||
ret = (SOCKET)req->handle;
|
||||
set_error( wine_server_call( req ) );
|
||||
ret = (SOCKET)reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret)
|
||||
|
@ -2718,19 +2719,16 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp
|
|||
|
||||
TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
|
||||
|
||||
SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
|
||||
SERVER_START_REQ( get_socket_event )
|
||||
{
|
||||
req->handle = s;
|
||||
req->service = TRUE;
|
||||
req->s_event = 0;
|
||||
req->c_event = hEvent;
|
||||
if (!(ret = SERVER_CALL()))
|
||||
{
|
||||
lpEvent->lNetworkEvents = req->pmask & req->mask;
|
||||
memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
|
||||
}
|
||||
wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
|
||||
if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return 0;
|
||||
SetLastError(WSAEINVAL);
|
||||
return SOCKET_ERROR;
|
||||
|
@ -2750,7 +2748,7 @@ int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
|
|||
req->handle = s;
|
||||
req->mask = lEvent;
|
||||
req->event = hEvent;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return 0;
|
||||
|
@ -2769,17 +2767,17 @@ VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
|
|||
|
||||
TRACE("socket %08x, event %08x\n", info->sock, info->event);
|
||||
SetLastError(0);
|
||||
SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
|
||||
SERVER_START_REQ( get_socket_event )
|
||||
{
|
||||
req->handle = info->sock;
|
||||
req->service = TRUE;
|
||||
req->s_event = info->event; /* <== avoid race conditions */
|
||||
req->c_event = info->event;
|
||||
set_error( SERVER_CALL() );
|
||||
pmask = req->pmask;
|
||||
memcpy( errors, server_data_ptr(req), server_data_size(req) );
|
||||
wine_server_set_reply( req, errors, sizeof(errors) );
|
||||
set_error( wine_server_call(req) );
|
||||
pmask = reply->pmask;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
|
||||
{
|
||||
/* orphaned event (socket closed or something) */
|
||||
|
|
|
@ -36,7 +36,7 @@ HANDLE WINAPI FindFirstChangeNotificationA( LPCSTR lpPathName, BOOL bWatchSubtre
|
|||
{
|
||||
req->subtree = bWatchSubtree;
|
||||
req->filter = dwNotifyFilter;
|
||||
if (!SERVER_CALL_ERR()) ret = req->handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -690,11 +690,11 @@ const DOS_DEVICE *DOSFS_GetDeviceByHandle( HFILE hFile )
|
|||
SERVER_START_REQ( get_file_info )
|
||||
{
|
||||
req->handle = hFile;
|
||||
if (!SERVER_CALL() && (req->type == FILE_TYPE_UNKNOWN))
|
||||
if (!wine_server_call( req ) && (reply->type == FILE_TYPE_UNKNOWN))
|
||||
{
|
||||
if ((req->attr >= 0) &&
|
||||
(req->attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
|
||||
ret = &DOSFS_Devices[req->attr];
|
||||
if ((reply->attr >= 0) &&
|
||||
(reply->attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
|
||||
ret = &DOSFS_Devices[reply->attr];
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -709,7 +709,6 @@ static HANDLE DOSFS_CreateCommPort(LPCSTR name, DWORD access, DWORD attributes,
|
|||
{
|
||||
HANDLE ret;
|
||||
char devname[40];
|
||||
size_t len;
|
||||
|
||||
TRACE_(file)("%s %lx %lx\n", name, access, attributes);
|
||||
|
||||
|
@ -719,19 +718,18 @@ static HANDLE DOSFS_CreateCommPort(LPCSTR name, DWORD access, DWORD attributes,
|
|||
|
||||
TRACE("opening %s as %s\n", devname, name);
|
||||
|
||||
len = strlen(devname);
|
||||
SERVER_START_VAR_REQ( create_serial, len )
|
||||
SERVER_START_REQ( create_serial )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
req->attributes = attributes;
|
||||
req->sharing = FILE_SHARE_READ|FILE_SHARE_WRITE;
|
||||
memcpy( server_data_ptr(req), devname, len );
|
||||
wine_server_add_data( req, devname, strlen(devname) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
|
||||
if(!ret)
|
||||
ERR("Couldn't open device '%s' ! (check permissions)\n",devname);
|
||||
|
|
179
files/file.c
179
files/file.c
|
@ -193,8 +193,8 @@ HANDLE FILE_DupUnixHandle( int fd, DWORD access, BOOL inherit )
|
|||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
req->fd = fd;
|
||||
SERVER_CALL();
|
||||
ret = req->handle;
|
||||
wine_server_call( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -217,11 +217,11 @@ int FILE_GetUnixHandleType( HANDLE handle, DWORD access, DWORD *type )
|
|||
{
|
||||
req->handle = handle;
|
||||
req->access = access;
|
||||
if (!(ret = SERVER_CALL_ERR()))
|
||||
if (!(ret = wine_server_call_err( req )))
|
||||
{
|
||||
fd = req->fd;
|
||||
fd = reply->fd;
|
||||
}
|
||||
if (type) *type = req->type;
|
||||
if (type) *type = reply->type;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) return -1;
|
||||
|
@ -267,8 +267,8 @@ static HANDLE FILE_OpenConsole( BOOL output, DWORD access, DWORD sharing, LPSECU
|
|||
req->share = sharing;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -286,52 +286,44 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
|
|||
DWORD attributes, HANDLE template, BOOL fail_read_only,
|
||||
UINT drive_type )
|
||||
{
|
||||
DWORD err;
|
||||
unsigned int err;
|
||||
HANDLE ret;
|
||||
size_t len = strlen(filename);
|
||||
|
||||
if (len > REQUEST_MAX_VAR_SIZE)
|
||||
for (;;)
|
||||
{
|
||||
FIXME("filename '%s' too long\n", filename );
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
|
||||
restart:
|
||||
SERVER_START_VAR_REQ( create_file, len )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
req->sharing = sharing;
|
||||
req->create = creation;
|
||||
req->attrs = attributes;
|
||||
req->drive_type = drive_type;
|
||||
memcpy( server_data_ptr(req), filename, len );
|
||||
SetLastError(0);
|
||||
err = SERVER_CALL();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
|
||||
/* If write access failed, retry without GENERIC_WRITE */
|
||||
|
||||
if (!ret && !fail_read_only && (access & GENERIC_WRITE))
|
||||
{
|
||||
if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
|
||||
SERVER_START_REQ( create_file )
|
||||
{
|
||||
TRACE("Write access failed for file '%s', trying without "
|
||||
"write access\n", filename);
|
||||
access &= ~GENERIC_WRITE;
|
||||
goto restart;
|
||||
req->access = access;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
req->sharing = sharing;
|
||||
req->create = creation;
|
||||
req->attrs = attributes;
|
||||
req->drive_type = drive_type;
|
||||
wine_server_add_data( req, filename, strlen(filename) );
|
||||
SetLastError(0);
|
||||
err = wine_server_call( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
/* If write access failed, retry without GENERIC_WRITE */
|
||||
|
||||
if (!ret && !fail_read_only && (access & GENERIC_WRITE))
|
||||
{
|
||||
if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
|
||||
{
|
||||
TRACE("Write access failed for file '%s', trying without "
|
||||
"write access\n", filename);
|
||||
access &= ~GENERIC_WRITE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) SetLastError( RtlNtStatusToDosError(err) );
|
||||
|
||||
if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (err) SetLastError( RtlNtStatusToDosError(err) );
|
||||
|
||||
if (!ret)
|
||||
WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,8 +342,8 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
|
|||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
req->id = client_id;
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -359,26 +351,24 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
|
|||
|
||||
static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
|
||||
{
|
||||
WCHAR buffer[MAX_PATH];
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
DWORD len = 0;
|
||||
|
||||
TRACE("name %s access %lx\n",name,access);
|
||||
|
||||
if (len >= MAX_PATH)
|
||||
if (name && !(len = MultiByteToWideChar( CP_ACP, 0, name, strlen(name), buffer, MAX_PATH )))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_named_pipe, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_named_pipe )
|
||||
{
|
||||
req->access = access;
|
||||
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
TRACE("Returned %d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -610,32 +600,31 @@ DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
|
|||
SERVER_START_REQ( get_file_info )
|
||||
{
|
||||
req->handle = hFile;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
/* FIXME: which file types are supported ?
|
||||
* Serial ports (FILE_TYPE_CHAR) are not,
|
||||
* and MSDN also says that pipes are not supported.
|
||||
* FILE_TYPE_REMOTE seems to be supported according to
|
||||
* MSDN q234741.txt */
|
||||
if ((req->type == FILE_TYPE_DISK)
|
||||
|| (req->type == FILE_TYPE_REMOTE))
|
||||
{
|
||||
RtlSecondsSince1970ToTime( req->write_time, &info->ftCreationTime );
|
||||
RtlSecondsSince1970ToTime( req->write_time, &info->ftLastWriteTime );
|
||||
RtlSecondsSince1970ToTime( req->access_time, &info->ftLastAccessTime );
|
||||
info->dwFileAttributes = req->attr;
|
||||
info->dwVolumeSerialNumber = req->serial;
|
||||
info->nFileSizeHigh = req->size_high;
|
||||
info->nFileSizeLow = req->size_low;
|
||||
info->nNumberOfLinks = req->links;
|
||||
info->nFileIndexHigh = req->index_high;
|
||||
info->nFileIndexLow = req->index_low;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
ret = 0;
|
||||
}
|
||||
/* FIXME: which file types are supported ?
|
||||
* Serial ports (FILE_TYPE_CHAR) are not,
|
||||
* and MSDN also says that pipes are not supported.
|
||||
* FILE_TYPE_REMOTE seems to be supported according to
|
||||
* MSDN q234741.txt */
|
||||
if ((reply->type == FILE_TYPE_DISK) || (reply->type == FILE_TYPE_REMOTE))
|
||||
{
|
||||
RtlSecondsSince1970ToTime( reply->write_time, &info->ftCreationTime );
|
||||
RtlSecondsSince1970ToTime( reply->write_time, &info->ftLastWriteTime );
|
||||
RtlSecondsSince1970ToTime( reply->access_time, &info->ftLastAccessTime );
|
||||
info->dwFileAttributes = reply->attr;
|
||||
info->dwVolumeSerialNumber = reply->serial;
|
||||
info->nFileSizeHigh = reply->size_high;
|
||||
info->nFileSizeLow = reply->size_low;
|
||||
info->nNumberOfLinks = reply->links;
|
||||
info->nFileIndexHigh = reply->index_high;
|
||||
info->nFileIndexLow = reply->index_low;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -1354,9 +1343,9 @@ static BOOL FILE_GetTimeout(HANDLE hFile, DWORD txcount, DWORD type, int *timeou
|
|||
req->count = txcount;
|
||||
req->type = type;
|
||||
req->file_handle = hFile;
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
if(timeout)
|
||||
*timeout = req->timeout;
|
||||
*timeout = reply->timeout;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return !ret;
|
||||
|
@ -1785,10 +1774,10 @@ DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword,
|
|||
/* FIXME: assumes 1:1 mapping between Windows and Unix seek constants */
|
||||
req->whence = method;
|
||||
SetLastError( 0 );
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
ret = req->new_low;
|
||||
if (highword) *highword = req->new_high;
|
||||
ret = reply->new_low;
|
||||
if (highword) *highword = reply->new_high;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -1940,7 +1929,7 @@ BOOL WINAPI FlushFileBuffers( HANDLE hFile )
|
|||
SERVER_START_REQ( flush_file )
|
||||
{
|
||||
req->handle = hFile;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1956,7 +1945,7 @@ BOOL WINAPI SetEndOfFile( HANDLE hFile )
|
|||
SERVER_START_REQ( truncate_file )
|
||||
{
|
||||
req->handle = hFile;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -2029,7 +2018,7 @@ DWORD WINAPI GetFileType( HANDLE hFile )
|
|||
SERVER_START_REQ( get_file_info )
|
||||
{
|
||||
req->handle = hFile;
|
||||
if (!SERVER_CALL_ERR()) ret = req->type;
|
||||
if (!wine_server_call_err( req )) ret = reply->type;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -2350,7 +2339,7 @@ BOOL WINAPI SetFileTime( HANDLE hFile,
|
|||
RtlTimeToSecondsSince1970( lpLastWriteTime, (DWORD *)&req->write_time );
|
||||
else
|
||||
req->write_time = 0; /* FIXME */
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -2371,7 +2360,7 @@ BOOL WINAPI LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHig
|
|||
req->offset_high = dwFileOffsetHigh;
|
||||
req->count_low = nNumberOfBytesToLockLow;
|
||||
req->count_high = nNumberOfBytesToLockHigh;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -2422,7 +2411,7 @@ BOOL WINAPI UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetH
|
|||
req->offset_high = dwFileOffsetHigh;
|
||||
req->count_low = nNumberOfBytesToUnlockLow;
|
||||
req->count_high = nNumberOfBytesToUnlockHigh;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -90,9 +90,7 @@ typedef struct _TEB
|
|||
|
||||
/* The following are Wine-specific fields (NT: GDI stuff) */
|
||||
DWORD cleanup; /* --3 1fc Cleanup service handle */
|
||||
void *buffer; /* --3 200 Buffer shared with server */
|
||||
unsigned int buffer_pos; /* --3 204 Buffer current position */
|
||||
unsigned int buffer_size; /* --3 208 Buffer size */
|
||||
DWORD unused[3]; /* --3 200 Was server buffer */
|
||||
int request_fd; /* --3 20c fd for sending server requests */
|
||||
int reply_fd; /* --3 210 fd for receiving server replies */
|
||||
int wait_fd[2]; /* --3 214 fd for sleeping server requests */
|
||||
|
|
|
@ -1609,7 +1609,7 @@ BOOL WINAPI WriteProfileSectionW(LPCWSTR,LPCWSTR);
|
|||
BOOL WINAPI WritePrivateProfileStructA(LPCSTR,LPCSTR,LPVOID,UINT,LPCSTR);
|
||||
BOOL WINAPI WritePrivateProfileStructW(LPCWSTR,LPCWSTR,LPVOID,UINT,LPCWSTR);
|
||||
#define WritePrivateProfileStruct WINELIB_NAME_AW(WritePrivateProfileStruct)
|
||||
BOOL WINAPI WriteProcessMemory(HANDLE, LPVOID, LPVOID, DWORD, LPDWORD);
|
||||
BOOL WINAPI WriteProcessMemory(HANDLE,LPVOID,LPCVOID,DWORD,LPDWORD);
|
||||
BOOL WINAPI WriteProfileStringA(LPCSTR,LPCSTR,LPCSTR);
|
||||
BOOL WINAPI WriteProfileStringW(LPCWSTR,LPCWSTR,LPCWSTR);
|
||||
#define WriteProfileString WINELIB_NAME_AW(WriteProfileString)
|
||||
|
|
|
@ -177,10 +177,8 @@ HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess, DWORD dwShareMod
|
|||
LPVOID lpScreenBufferData);
|
||||
BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength,
|
||||
COORD dwCoord, LPDWORD lpNumAttrsWritten);
|
||||
BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, BYTE cCharacter, DWORD nLength,
|
||||
COORD dwCoord, LPDWORD lpNumCharsWritten);
|
||||
BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR cCharacter, DWORD nLength,
|
||||
COORD dwCoord, LPDWORD lpNumCharsWritten);
|
||||
BOOL WINAPI FillConsoleOutputCharacterA(HANDLE,CHAR,DWORD,COORD,LPDWORD);
|
||||
BOOL WINAPI FillConsoleOutputCharacterW(HANDLE,WCHAR,DWORD,COORD,LPDWORD);
|
||||
#define FillConsoleOutputCharacter WINELIB_NAME_AW(FillConsoleOutputCharacter)
|
||||
BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle);
|
||||
BOOL WINAPI FreeConsole(VOID);
|
||||
|
@ -242,13 +240,11 @@ BOOL WINAPI SetConsoleWindowInfo( HANDLE hcon, BOOL bAbsolute, LPSMALL_RECT wi
|
|||
BOOL WINAPI WriteConsoleA(HANDLE,CONST VOID *,DWORD,LPDWORD,LPVOID);
|
||||
BOOL WINAPI WriteConsoleW(HANDLE, CONST VOID *lpBuffer, DWORD,LPDWORD,LPVOID);
|
||||
#define WriteConsole WINELIB_NAME_AW(WriteConsole)
|
||||
BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer, DWORD, LPDWORD );
|
||||
BOOL WINAPI WriteConsoleInputW( HANDLE handle, INPUT_RECORD *buffer, DWORD, LPDWORD );
|
||||
BOOL WINAPI WriteConsoleInputA(HANDLE,const INPUT_RECORD *,DWORD,LPDWORD);
|
||||
BOOL WINAPI WriteConsoleInputW(HANDLE,const INPUT_RECORD *,DWORD,LPDWORD);
|
||||
#define WriteConsoleInput WINELIB_NAME_AW(WriteConsoleInput)
|
||||
BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
|
||||
COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion);
|
||||
BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
|
||||
COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion);
|
||||
BOOL WINAPI WriteConsoleOutputA(HANDLE,const CHAR_INFO*,COORD,COORD,LPSMALL_RECT);
|
||||
BOOL WINAPI WriteConsoleOutputW(HANDLE,const CHAR_INFO*,COORD,COORD,LPSMALL_RECT);
|
||||
#define WriteConsoleOutput WINELIB_NAME_AW(WriteConsoleOutput)
|
||||
BOOL WINAPI WriteConsoleOutputAttribute(HANDLE,CONST WORD *,DWORD,COORD,LPDWORD);
|
||||
BOOL WINAPI WriteConsoleOutputCharacterA(HANDLE,LPCSTR,DWORD,COORD,LPDWORD);
|
||||
|
|
|
@ -14,83 +14,90 @@
|
|||
|
||||
/* client communication functions */
|
||||
|
||||
extern unsigned int wine_server_call( union generic_request *req, size_t size );
|
||||
extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
|
||||
extern void server_protocol_perror( const char *err ) WINE_NORETURN;
|
||||
extern void wine_server_alloc_req( union generic_request *req, size_t size );
|
||||
struct __server_iovec
|
||||
{
|
||||
const void *ptr;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
#define __SERVER_MAX_DATA 4
|
||||
|
||||
struct __server_request_info
|
||||
{
|
||||
union
|
||||
{
|
||||
union generic_request req; /* request structure */
|
||||
union generic_reply reply; /* reply structure */
|
||||
} u;
|
||||
size_t size; /* size of request structure */
|
||||
unsigned int data_count; /* count of request data pointers */
|
||||
void *reply_data; /* reply data pointer */
|
||||
struct __server_iovec data[__SERVER_MAX_DATA]; /* request variable size data */
|
||||
};
|
||||
|
||||
extern unsigned int wine_server_call( void *req_ptr );
|
||||
extern void wine_server_send_fd( int fd );
|
||||
extern int wine_server_recv_fd( handle_t handle );
|
||||
extern const char *get_config_dir(void);
|
||||
|
||||
/* do a server call and set the last error code */
|
||||
inline static unsigned int __server_call_err( union generic_request *req, size_t size )
|
||||
inline static unsigned int wine_server_call_err( void *req_ptr )
|
||||
{
|
||||
unsigned int res = wine_server_call( req, size );
|
||||
unsigned int res = wine_server_call( req_ptr );
|
||||
if (res) SetLastError( RtlNtStatusToDosError(res) );
|
||||
return res;
|
||||
}
|
||||
|
||||
/* get a pointer to the variable part of the request */
|
||||
inline static void *server_data_ptr( const void *req )
|
||||
/* get the size of the variable part of the returned reply */
|
||||
inline static size_t wine_server_reply_size( const void *reply )
|
||||
{
|
||||
return (char *)NtCurrentTeb()->buffer + ((struct request_header *)req)->var_offset;
|
||||
return ((struct reply_header *)reply)->reply_size;
|
||||
}
|
||||
|
||||
/* get the size of the variable part of the request */
|
||||
inline static size_t server_data_size( const void *req )
|
||||
/* add some data to be sent along with the request */
|
||||
inline static void wine_server_add_data( void *req_ptr, const void *ptr, unsigned int size )
|
||||
{
|
||||
return ((struct request_header *)req)->var_size;
|
||||
struct __server_request_info * const req = req_ptr;
|
||||
if (size)
|
||||
{
|
||||
req->data[req->data_count].ptr = ptr;
|
||||
req->data[req->data_count++].size = size;
|
||||
req->u.req.request_header.request_size += size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* exception support for server calls */
|
||||
|
||||
extern DWORD __wine_server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
|
||||
CONTEXT *context, EXCEPTION_FRAME **pdispatcher );
|
||||
|
||||
struct __server_exception_frame
|
||||
/* set the pointer and max size for the reply var data */
|
||||
inline static void wine_server_set_reply( void *req_ptr, void *ptr, unsigned int max_size )
|
||||
{
|
||||
EXCEPTION_FRAME frame;
|
||||
unsigned int buffer_pos; /* saved buffer position */
|
||||
};
|
||||
struct __server_request_info * const req = req_ptr;
|
||||
req->reply_data = ptr;
|
||||
req->u.req.request_header.reply_size = max_size;
|
||||
}
|
||||
|
||||
|
||||
/* macros for server requests */
|
||||
|
||||
#define SERVER_START_REQ(type) \
|
||||
do { \
|
||||
union generic_request __req; \
|
||||
struct type##_request * const req = &__req.type; \
|
||||
__req.header.req = REQ_##type; \
|
||||
__req.header.var_size = 0; \
|
||||
struct __server_request_info __req; \
|
||||
struct type##_request * const req = &__req.u.req.type##_request; \
|
||||
const struct type##_reply * const reply = &__req.u.reply.type##_reply; \
|
||||
__req.u.req.request_header.req = REQ_##type; \
|
||||
__req.u.req.request_header.request_size = 0; \
|
||||
__req.u.req.request_header.reply_size = 0; \
|
||||
__req.size = sizeof(*req); \
|
||||
__req.data_count = 0; \
|
||||
(void)reply; \
|
||||
do
|
||||
|
||||
#define SERVER_END_REQ \
|
||||
while(0); \
|
||||
} while(0)
|
||||
|
||||
#define SERVER_START_VAR_REQ(type,size) \
|
||||
do { \
|
||||
struct __server_exception_frame __f; \
|
||||
union generic_request __req; \
|
||||
struct type##_request * const req = &__req.type; \
|
||||
__f.frame.Handler = __wine_server_exception_handler; \
|
||||
__f.buffer_pos = NtCurrentTeb()->buffer_pos; \
|
||||
__wine_push_frame( &__f.frame ); \
|
||||
__req.header.req = REQ_##type; \
|
||||
wine_server_alloc_req( &__req, (size) ); \
|
||||
do
|
||||
|
||||
#define SERVER_END_VAR_REQ \
|
||||
while(0); \
|
||||
NtCurrentTeb()->buffer_pos = __f.buffer_pos; \
|
||||
__wine_pop_frame( &__f.frame ); \
|
||||
} while(0)
|
||||
|
||||
#define SERVER_CALL() (wine_server_call( &__req, sizeof(*req) ))
|
||||
#define SERVER_CALL_ERR() (__server_call_err( &__req, sizeof(*req) ))
|
||||
|
||||
|
||||
/* non-exported functions */
|
||||
extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
|
||||
extern void server_protocol_perror( const char *err ) WINE_NORETURN;
|
||||
extern const char *get_config_dir(void);
|
||||
extern void CLIENT_InitServer(void);
|
||||
extern void CLIENT_InitThread(void);
|
||||
extern void CLIENT_BootDone( int debug_level );
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1693,7 +1693,7 @@ BOOL MODULE_FreeLibrary( WINE_MODREF *wm )
|
|||
SERVER_START_REQ( unload_dll )
|
||||
{
|
||||
req->base = (void *)wm->module;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
MODULE_FlushModrefs();
|
||||
|
|
|
@ -681,7 +681,7 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags,
|
|||
req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
|
||||
req->dbg_size = nt->FileHeader.NumberOfSymbols;
|
||||
req->name = &wm->filename;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ BOOL WINAPI InitAtomTable( DWORD entries )
|
|||
SERVER_START_REQ( init_atom_table )
|
||||
{
|
||||
req->entries = entries;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -421,19 +421,21 @@ static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
|
|||
ATOM atom = 0;
|
||||
if (!ATOM_IsIntAtomA( str, &atom ))
|
||||
{
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
|
||||
if (len > MAX_ATOM_LEN)
|
||||
WCHAR buffer[MAX_ATOM_LEN];
|
||||
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
|
||||
if (!len)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( add_atom )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
|
||||
wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR()) atom = req->atom;
|
||||
if (!wine_server_call_err(req)) atom = reply->atom;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
|
||||
return atom;
|
||||
|
@ -482,13 +484,13 @@ static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
|
|||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( add_atom )
|
||||
{
|
||||
memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR()) atom = req->atom;
|
||||
wine_server_add_data( req, str, len * sizeof(WCHAR) );
|
||||
if (!wine_server_call_err(req)) atom = reply->atom;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
|
||||
return atom;
|
||||
|
@ -523,7 +525,7 @@ static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local)
|
|||
{
|
||||
req->atom = atom;
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR()) atom = 0;
|
||||
if (!wine_server_call_err( req )) atom = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -566,19 +568,21 @@ static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
|
|||
ATOM atom = 0;
|
||||
if (!ATOM_IsIntAtomA( str, &atom ))
|
||||
{
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
|
||||
if (len > MAX_ATOM_LEN)
|
||||
WCHAR buffer[MAX_ATOM_LEN];
|
||||
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
|
||||
if (!len)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( find_atom )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR()) atom = req->atom;
|
||||
wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
|
||||
if (!wine_server_call_err(req)) atom = reply->atom;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
|
||||
return atom;
|
||||
|
@ -626,13 +630,13 @@ static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
|
|||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( find_atom )
|
||||
{
|
||||
memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, str, len * sizeof(WCHAR) );
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR()) atom = req->atom;
|
||||
if (!wine_server_call_err( req )) atom = reply->atom;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
|
||||
return atom;
|
||||
|
@ -679,21 +683,24 @@ static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
|
|||
}
|
||||
else
|
||||
{
|
||||
WCHAR full_name[MAX_ATOM_LEN];
|
||||
|
||||
len = 0;
|
||||
SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( get_atom_name )
|
||||
{
|
||||
req->atom = atom;
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR())
|
||||
wine_server_set_reply( req, full_name, sizeof(full_name) );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
len = WideCharToMultiByte( CP_ACP, 0, server_data_ptr(req),
|
||||
server_data_size(req) / sizeof(WCHAR),
|
||||
len = WideCharToMultiByte( CP_ACP, 0, full_name,
|
||||
wine_server_reply_size(reply) / sizeof(WCHAR),
|
||||
buffer, count - 1, NULL, NULL );
|
||||
if (!len) len = count; /* overflow */
|
||||
else buffer[len] = 0;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
if (len && count <= len)
|
||||
|
@ -765,20 +772,23 @@ static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
|
|||
}
|
||||
else
|
||||
{
|
||||
WCHAR full_name[MAX_ATOM_LEN];
|
||||
|
||||
len = 0;
|
||||
SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( get_atom_name )
|
||||
{
|
||||
req->atom = atom;
|
||||
req->local = local;
|
||||
if (!SERVER_CALL_ERR())
|
||||
wine_server_set_reply( req, full_name, sizeof(full_name) );
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
len = server_data_size(req) / sizeof(WCHAR);
|
||||
len = wine_server_reply_size(reply) / sizeof(WCHAR);
|
||||
if (count > len) count = len + 1;
|
||||
memcpy( buffer, server_data_ptr(req), (count-1) * sizeof(WCHAR) );
|
||||
memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
|
||||
buffer[count-1] = 0;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!len) return 0;
|
||||
}
|
||||
if (count <= len)
|
||||
|
|
|
@ -606,6 +606,7 @@ DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
|
|||
LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
||||
{
|
||||
HANDLE file;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
DWORD ret, len, err = GetLastError();
|
||||
|
||||
TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
|
||||
|
@ -613,8 +614,8 @@ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
|||
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
|
||||
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), NULL, 0 ) * sizeof(WCHAR);
|
||||
if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
|
||||
if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH )))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
|
||||
|
@ -623,15 +624,14 @@ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
|
|||
goto done;
|
||||
}
|
||||
|
||||
SERVER_START_VAR_REQ( load_registry, len )
|
||||
SERVER_START_REQ( load_registry )
|
||||
{
|
||||
req->hkey = hkey;
|
||||
req->file = file;
|
||||
MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey),
|
||||
server_data_ptr(req), len/sizeof(WCHAR) );
|
||||
ret = RtlNtStatusToDosError( SERVER_CALL() );
|
||||
wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
|
||||
ret = RtlNtStatusToDosError( wine_server_call(req) );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
CloseHandle( file );
|
||||
|
||||
done:
|
||||
|
@ -679,7 +679,7 @@ LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
|
|||
{
|
||||
req->hkey = hkey;
|
||||
req->file = handle;
|
||||
ret = RtlNtStatusToDosError( SERVER_CALL() );
|
||||
ret = RtlNtStatusToDosError( wine_server_call( req ) );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
|
@ -594,18 +594,18 @@ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldten
|
|||
{
|
||||
req->handle = hthread;
|
||||
req->entry = sel >> __AHSHIFT;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
if (!(req->flags & WINE_LDT_FLAGS_ALLOCATED))
|
||||
if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
|
||||
{
|
||||
SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wine_ldt_set_base( ldtent, (void *)req->base );
|
||||
wine_ldt_set_limit( ldtent, req->limit );
|
||||
wine_ldt_set_flags( ldtent, req->flags );
|
||||
wine_ldt_set_base( ldtent, (void *)reply->base );
|
||||
wine_ldt_set_limit( ldtent, reply->limit );
|
||||
wine_ldt_set_flags( ldtent, reply->flags );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
103
memory/virtual.c
103
memory/virtual.c
|
@ -1360,50 +1360,16 @@ HANDLE WINAPI CreateFileMappingA(
|
|||
DWORD size_low, /* [in] Low-order 32 bits of object size */
|
||||
LPCSTR name /* [in] Name of file-mapping object */ )
|
||||
{
|
||||
HANDLE ret;
|
||||
BYTE vprot;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
/* Check parameters */
|
||||
if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
|
||||
|
||||
TRACE("(%x,%p,%08lx,%08lx%08lx,%s)\n",
|
||||
hFile, sa, protect, size_high, size_low, debugstr_a(name) );
|
||||
|
||||
if (len > MAX_PATH)
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
vprot = VIRTUAL_GetProt( protect );
|
||||
if (protect & SEC_RESERVE)
|
||||
{
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else vprot |= VPROT_COMMITTED;
|
||||
if (protect & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
|
||||
if (protect & SEC_IMAGE) vprot |= VPROT_IMAGE;
|
||||
|
||||
/* Create the server object */
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) hFile = 0;
|
||||
SERVER_START_VAR_REQ( create_mapping, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->file_handle = hFile;
|
||||
req->size_high = size_high;
|
||||
req->size_low = size_low;
|
||||
req->protect = vprot;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1446,19 +1412,19 @@ HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
|
|||
/* Create the server object */
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) hFile = 0;
|
||||
SERVER_START_VAR_REQ( create_mapping, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_mapping )
|
||||
{
|
||||
req->file_handle = hFile;
|
||||
req->size_high = size_high;
|
||||
req->size_low = size_low;
|
||||
req->protect = vprot;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1476,23 +1442,16 @@ HANDLE WINAPI OpenFileMappingA(
|
|||
BOOL inherit, /* [in] Inherit flag */
|
||||
LPCSTR name ) /* [in] Name of file-mapping object */
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len > MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return OpenFileMappingW( access, inherit, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_mapping, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return OpenFileMappingW( access, inherit, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1504,20 +1463,20 @@ HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
|
|||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? strlenW(name) : 0;
|
||||
if (len > MAX_PATH)
|
||||
if (len >= MAX_PATH)
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_mapping, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_mapping )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1580,16 +1539,16 @@ LPVOID WINAPI MapViewOfFileEx(
|
|||
SERVER_START_REQ( get_mapping_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
res = SERVER_CALL_ERR();
|
||||
prot = req->protect;
|
||||
base = req->base;
|
||||
size_low = req->size_low;
|
||||
size_high = req->size_high;
|
||||
header_size = req->header_size;
|
||||
shared_file = req->shared_file;
|
||||
shared_size = req->shared_size;
|
||||
removable = (req->drive_type == DRIVE_REMOVABLE ||
|
||||
req->drive_type == DRIVE_CDROM);
|
||||
res = wine_server_call_err( req );
|
||||
prot = reply->protect;
|
||||
base = reply->base;
|
||||
size_low = reply->size_low;
|
||||
size_high = reply->size_high;
|
||||
header_size = reply->header_size;
|
||||
shared_file = reply->shared_file;
|
||||
shared_size = reply->shared_size;
|
||||
removable = (reply->drive_type == DRIVE_REMOVABLE ||
|
||||
reply->drive_type == DRIVE_CDROM);
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (res) goto error;
|
||||
|
|
|
@ -38,10 +38,6 @@ const char *full_argv0; /* the full path of argv[0] (if known) */
|
|||
|
||||
static char *inherit_str; /* options to pass to child processes */
|
||||
|
||||
static int app_argc; /* argc/argv to pass to application */
|
||||
static char **app_argv;
|
||||
static WCHAR **app_wargv;
|
||||
|
||||
static void out_of_memory(void) WINE_NORETURN;
|
||||
static void out_of_memory(void)
|
||||
{
|
||||
|
@ -340,55 +336,4 @@ void OPTIONS_ParseOptions( char *argv[] )
|
|||
OPTIONS_Usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* count the resulting arguments */
|
||||
app_argv = argv;
|
||||
app_argc = 0;
|
||||
while (argv[app_argc]) app_argc++;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_get_main_args (NTDLL.@)
|
||||
*
|
||||
* Return the argc/argv that the application should see.
|
||||
* Used by the startup code generated in the .spec.c file.
|
||||
*/
|
||||
int __wine_get_main_args( char ***argv )
|
||||
{
|
||||
*argv = app_argv;
|
||||
return app_argc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_get_wmain_args (NTDLL.@)
|
||||
*
|
||||
* Same as __wine_get_main_args but for Unicode.
|
||||
*/
|
||||
int __wine_get_wmain_args( WCHAR ***argv )
|
||||
{
|
||||
if (!app_wargv)
|
||||
{
|
||||
int i;
|
||||
WCHAR *p;
|
||||
DWORD total = 0;
|
||||
|
||||
for (i = 0; i < app_argc; i++)
|
||||
total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 );
|
||||
|
||||
app_wargv = HeapAlloc( GetProcessHeap(), 0,
|
||||
total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) );
|
||||
p = (WCHAR *)(app_wargv + app_argc + 1);
|
||||
for (i = 0; i < app_argc; i++)
|
||||
{
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total );
|
||||
app_wargv[i] = p;
|
||||
p += len;
|
||||
total -= len;
|
||||
}
|
||||
app_wargv[app_argc] = NULL;
|
||||
}
|
||||
*argv = app_wargv;
|
||||
return app_argc;
|
||||
}
|
||||
|
|
|
@ -1004,7 +1004,7 @@ static void _set_registry_levels(int level,int saving,int period)
|
|||
req->current = level;
|
||||
req->saving = saving;
|
||||
req->period = period;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -1013,19 +1013,15 @@ static void _set_registry_levels(int level,int saving,int period)
|
|||
static void _save_at_exit(HKEY hkey,LPCSTR path)
|
||||
{
|
||||
LPCSTR confdir = get_config_dir();
|
||||
size_t len = strlen(confdir) + strlen(path) + 2;
|
||||
|
||||
if (len > REQUEST_MAX_VAR_SIZE) {
|
||||
ERR( "config dir '%s' too long\n", confdir );
|
||||
return;
|
||||
}
|
||||
SERVER_START_VAR_REQ( save_registry_atexit, len )
|
||||
SERVER_START_REQ( save_registry_atexit )
|
||||
{
|
||||
sprintf( server_data_ptr(req), "%s/%s", confdir, path );
|
||||
req->hkey = hkey;
|
||||
SERVER_CALL();
|
||||
wine_server_add_data( req, confdir, strlen(confdir) );
|
||||
wine_server_add_data( req, path, strlen(path)+1 );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
/* configure save files and start the periodic saving timer [Internal] */
|
||||
|
@ -1042,9 +1038,9 @@ static void _init_registry_saving( HKEY hkey_users_default )
|
|||
|
||||
if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistryFiles",1))
|
||||
{
|
||||
_save_at_exit(HKEY_CURRENT_USER,SAVE_LOCAL_REGBRANCH_CURRENT_USER );
|
||||
_save_at_exit(HKEY_LOCAL_MACHINE,SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
|
||||
_save_at_exit(hkey_users_default,SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
|
||||
_save_at_exit(HKEY_CURRENT_USER,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
|
||||
_save_at_exit(HKEY_LOCAL_MACHINE,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
|
||||
_save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1190,7 +1186,7 @@ static void load_wine_registry(HKEY hkey,LPCSTR fn)
|
|||
{
|
||||
req->hkey = hkey;
|
||||
req->file = file;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
CloseHandle( file );
|
||||
|
|
|
@ -352,7 +352,8 @@ void CALLBACK VGA_Poll( ULONG_PTR arg )
|
|||
ch[X].Attributes = *dat++;
|
||||
}
|
||||
dest.Left=0; dest.Right=Width+1;
|
||||
WriteConsoleOutputA(con, ch, siz, off, &dest);
|
||||
FIXME("output commented out for now, should be moved to winedos.dll\n");
|
||||
/*WriteConsoleOutputA(con, ch, siz, off, &dest);*/
|
||||
}
|
||||
}
|
||||
vga_refresh=1;
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <wine/server.h>
|
||||
#include "wine/server.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "winecon_private.h"
|
||||
|
||||
static int trace_level = 1;
|
||||
|
@ -35,34 +36,20 @@ void XTracer(int level, const char* format, ...)
|
|||
*
|
||||
* updates the local copy of cells (band to update)
|
||||
*/
|
||||
void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
|
||||
void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
|
||||
{
|
||||
int step;
|
||||
int j, nr;
|
||||
|
||||
step = REQUEST_MAX_VAR_SIZE / (data->sb_width * 4);
|
||||
|
||||
for (j = upd_tp; j <= upd_bm; j += step)
|
||||
SERVER_START_REQ( read_console_output )
|
||||
{
|
||||
nr = min(step, upd_bm - j + 1);
|
||||
SERVER_START_VAR_REQ( read_console_output, 4 * nr * data->sb_width )
|
||||
{
|
||||
req->handle = (handle_t)data->hConOut;
|
||||
req->x = 0;
|
||||
req->y = j;
|
||||
req->w = data->sb_width;
|
||||
req->h = nr;
|
||||
if (!SERVER_CALL_ERR())
|
||||
{
|
||||
if (data->sb_width != req->eff_w || nr != req->eff_h)
|
||||
Trace(0, "pb here... wrong eff_w %d/%d or eff_h %d/%d\n",
|
||||
req->eff_w, data->sb_width, req->eff_h, nr);
|
||||
memcpy(&data->cells[j * data->sb_width], server_data_ptr(req),
|
||||
4 * nr * data->sb_width);
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
req->handle = (handle_t)data->hConOut;
|
||||
req->x = 0;
|
||||
req->y = upd_tp;
|
||||
req->mode = CHAR_INFO_MODE_TEXTATTR;
|
||||
req->wrap = TRUE;
|
||||
wine_server_set_reply( req, &data->cells[upd_tp * data->sb_width],
|
||||
(upd_bm-upd_tp+1) * data->sb_width * sizeof(CHAR_INFO) );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
data->fnRefresh(data, upd_tp, upd_bm);
|
||||
}
|
||||
|
||||
|
@ -71,19 +58,17 @@ void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
|
|||
*
|
||||
* Inform server that visible window on sb has changed
|
||||
*/
|
||||
void WINECON_NotifyWindowChange(struct inner_data* data)
|
||||
void WINECON_NotifyWindowChange(struct inner_data* data)
|
||||
{
|
||||
SERVER_START_REQ( set_console_output_info )
|
||||
{
|
||||
req->handle = (handle_t)data->hConOut;
|
||||
req->win_left = data->win_pos.X;
|
||||
req->win_top = data->win_pos.Y;
|
||||
req->win_right = data->win_pos.X + data->win_width - 1;
|
||||
req->win_bottom = data->win_pos.Y + data->win_height - 1;
|
||||
req->mask = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
|
||||
if (!SERVER_CALL_ERR())
|
||||
{
|
||||
}
|
||||
req->handle = (handle_t)data->hConOut;
|
||||
req->win_left = data->win_pos.X;
|
||||
req->win_top = data->win_pos.Y;
|
||||
req->win_right = data->win_pos.X + data->win_width - 1;
|
||||
req->win_bottom = data->win_pos.Y + data->win_height - 1;
|
||||
req->mask = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -100,7 +85,7 @@ int WINECON_GetHistorySize(HANDLE hConIn)
|
|||
SERVER_START_REQ(get_console_input_info)
|
||||
{
|
||||
req->handle = (handle_t)hConIn;
|
||||
if (!SERVER_CALL_ERR()) ret = req->history_size;
|
||||
if (!wine_server_call_err( req )) ret = reply->history_size;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -120,7 +105,7 @@ BOOL WINECON_SetHistorySize(HANDLE hConIn, int size)
|
|||
req->handle = (handle_t)hConIn;
|
||||
req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_SIZE;
|
||||
req->history_size = size;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -139,7 +124,7 @@ int WINECON_GetHistoryMode(HANDLE hConIn)
|
|||
SERVER_START_REQ(get_console_input_info)
|
||||
{
|
||||
req->handle = (handle_t)hConIn;
|
||||
if (!SERVER_CALL_ERR()) ret = req->history_mode;
|
||||
if (!wine_server_call_err( req )) ret = reply->history_mode;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -159,7 +144,7 @@ BOOL WINECON_SetHistoryMode(HANDLE hConIn, int mode)
|
|||
req->handle = (handle_t)hConIn;
|
||||
req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_MODE;
|
||||
req->history_mode = mode;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -170,22 +155,23 @@ BOOL WINECON_SetHistoryMode(HANDLE hConIn, int mode)
|
|||
*
|
||||
*
|
||||
*/
|
||||
BOOL WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len)
|
||||
BOOL WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD size = 0;
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_VAR_REQ(get_console_input_info, sizeof(buffer))
|
||||
if (len < sizeof(WCHAR)) return FALSE;
|
||||
|
||||
SERVER_START_REQ( get_console_input_info )
|
||||
{
|
||||
req->handle = (handle_t)hConIn;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
req->handle = (handle_t)hConIn;
|
||||
wine_server_set_reply( req, buffer, len - sizeof(WCHAR) );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
size = min(len - sizeof(WCHAR), server_data_size(req));
|
||||
memcpy(buffer, server_data_ptr(req), size);
|
||||
buffer[size / sizeof(WCHAR)] = 0;
|
||||
len = wine_server_reply_size( reply );
|
||||
buffer[len / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -200,18 +186,14 @@ int WINECON_GrabChanges(struct inner_data* data)
|
|||
int i, num;
|
||||
HANDLE h;
|
||||
|
||||
SERVER_START_VAR_REQ( get_console_renderer_events, sizeof(evts) )
|
||||
SERVER_START_REQ( get_console_renderer_events )
|
||||
{
|
||||
req->handle = (handle_t)data->hSynchro;
|
||||
if (!SERVER_CALL_ERR())
|
||||
{
|
||||
num = server_data_size(req);
|
||||
memcpy(evts, server_data_ptr(req), num);
|
||||
num /= sizeof(evts[0]);
|
||||
}
|
||||
else num = 0;
|
||||
wine_server_set_reply( req, evts, sizeof(evts) );
|
||||
req->handle = (handle_t)data->hSynchro;
|
||||
if (!wine_server_call_err( req )) num = wine_server_reply_size(reply) / sizeof(evts[0]);
|
||||
else num = 0;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!num) {Trace(0, "hmm renderer signaled but no events available\n"); return 1;}
|
||||
|
||||
/* FIXME: should do some event compression here (cursor pos, update) */
|
||||
|
@ -230,7 +212,7 @@ int WINECON_GrabChanges(struct inner_data* data)
|
|||
req->access = GENERIC_READ | GENERIC_WRITE;
|
||||
req->share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
req->inherit = FALSE;
|
||||
h = SERVER_CALL_ERR() ? 0 : (HANDLE)req->handle;
|
||||
h = wine_server_call_err( req ) ? 0 : (HANDLE)reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
Trace(1, " active(%d)", (int)h);
|
||||
|
@ -340,7 +322,6 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, void* pid)
|
|||
struct inner_data* data = NULL;
|
||||
DWORD ret;
|
||||
WCHAR szTitle[] = {'W','i','n','e',' ','c','o','n','s','o','l','e',0};
|
||||
size_t len;
|
||||
|
||||
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
|
||||
if (!data) return 0;
|
||||
|
@ -355,24 +336,21 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, void* pid)
|
|||
req->access = GENERIC_READ | GENERIC_WRITE;
|
||||
req->inherit = FALSE;
|
||||
req->pid = pid;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
data->hConIn = (HANDLE)req->handle_in;
|
||||
data->hSynchro = (HANDLE)req->event;
|
||||
ret = !wine_server_call_err( req );
|
||||
data->hConIn = (HANDLE)reply->handle_in;
|
||||
data->hSynchro = (HANDLE)reply->event;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) goto error;
|
||||
|
||||
len = lstrlenW(szTitle) * sizeof(WCHAR);
|
||||
len = min(len, REQUEST_MAX_VAR_SIZE);
|
||||
|
||||
SERVER_START_VAR_REQ(set_console_input_info, len)
|
||||
SERVER_START_REQ( set_console_input_info )
|
||||
{
|
||||
req->handle = (handle_t)data->hConIn;
|
||||
req->handle = (handle_t)data->hConIn;
|
||||
req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
|
||||
memcpy(server_data_ptr(req), szTitle, len);
|
||||
ret = !SERVER_CALL_ERR();
|
||||
wine_server_add_data( req, szTitle, strlenW(szTitle) * sizeof(WCHAR) );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
|
@ -382,7 +360,7 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, void* pid)
|
|||
req->access = GENERIC_WRITE|GENERIC_READ;
|
||||
req->share = FILE_SHARE_READ|FILE_SHARE_WRITE;
|
||||
req->inherit = FALSE;
|
||||
data->hConOut = (HANDLE)(SERVER_CALL_ERR() ? 0 : req->handle_out);
|
||||
data->hConOut = (HANDLE)(wine_server_call_err( req ) ? 0 : reply->handle_out);
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (data->hConOut) return data;
|
||||
|
|
|
@ -113,69 +113,60 @@ void server_protocol_perror( const char *err )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_server_exception_handler (NTDLL.@)
|
||||
*/
|
||||
DWORD __wine_server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
|
||||
CONTEXT *context, EXCEPTION_FRAME **pdispatcher )
|
||||
{
|
||||
struct __server_exception_frame *server_frame = (struct __server_exception_frame *)frame;
|
||||
if ((record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
|
||||
NtCurrentTeb()->buffer_pos = server_frame->buffer_pos;
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wine_server_alloc_req (NTDLL.@)
|
||||
*/
|
||||
void wine_server_alloc_req( union generic_request *req, size_t size )
|
||||
{
|
||||
unsigned int pos = NtCurrentTeb()->buffer_pos;
|
||||
|
||||
assert( size <= REQUEST_MAX_VAR_SIZE );
|
||||
|
||||
if (pos + size > NtCurrentTeb()->buffer_size)
|
||||
server_protocol_error( "buffer overflow %d bytes\n",
|
||||
pos + size - NtCurrentTeb()->buffer_pos );
|
||||
|
||||
NtCurrentTeb()->buffer_pos = pos + size;
|
||||
req->header.var_offset = pos;
|
||||
req->header.var_size = size;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* send_request
|
||||
*
|
||||
* Send a request to the server.
|
||||
*/
|
||||
static void send_request( union generic_request *request )
|
||||
static void send_request( const struct __server_request_info *req )
|
||||
{
|
||||
int ret;
|
||||
int i, ret;
|
||||
|
||||
if (!req->u.req.request_header.request_size)
|
||||
{
|
||||
if ((ret = write( NtCurrentTeb()->request_fd, &req->u.req,
|
||||
sizeof(req->u.req) )) == sizeof(req->u.req)) return;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
struct iovec vec[__SERVER_MAX_DATA+1];
|
||||
|
||||
vec[0].iov_base = (void *)&req->u.req;
|
||||
vec[0].iov_len = sizeof(req->u.req);
|
||||
for (i = 0; i < req->data_count; i++)
|
||||
{
|
||||
vec[i+1].iov_base = (void *)req->data[i].ptr;
|
||||
vec[i+1].iov_len = req->data[i].size;
|
||||
}
|
||||
if ((ret = writev( NtCurrentTeb()->request_fd, vec, i+1 )) ==
|
||||
req->u.req.request_header.request_size + sizeof(req->u.req)) return;
|
||||
}
|
||||
|
||||
if ((ret = write( NtCurrentTeb()->request_fd, request, sizeof(*request) )) == sizeof(*request))
|
||||
return;
|
||||
if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
|
||||
if (errno == EPIPE) SYSDEPS_ExitThread(0);
|
||||
server_protocol_perror( "sendmsg" );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wait_reply
|
||||
* read_reply_data
|
||||
*
|
||||
* Wait for a reply from the server.
|
||||
* Read data from the reply buffer; helper for wait_reply.
|
||||
*/
|
||||
static void wait_reply( union generic_request *req )
|
||||
static void read_reply_data( void *buffer, size_t size )
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((ret = read( NtCurrentTeb()->reply_fd, req, sizeof(*req) )) == sizeof(*req))
|
||||
return;
|
||||
if ((ret = read( NtCurrentTeb()->reply_fd, buffer, size )) > 0)
|
||||
{
|
||||
if (!(size -= ret)) return;
|
||||
buffer = (char *)buffer + ret;
|
||||
continue;
|
||||
}
|
||||
if (!ret) break;
|
||||
if (ret > 0) server_protocol_error( "partial read %d\n", ret );
|
||||
if (errno == EINTR) continue;
|
||||
if (errno == EPIPE) break;
|
||||
server_protocol_perror("read");
|
||||
|
@ -185,21 +176,35 @@ static void wait_reply( union generic_request *req )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wait_reply
|
||||
*
|
||||
* Wait for a reply from the server.
|
||||
*/
|
||||
inline static void wait_reply( struct __server_request_info *req )
|
||||
{
|
||||
read_reply_data( &req->u.reply, sizeof(req->u.reply) );
|
||||
if (req->u.reply.reply_header.reply_size)
|
||||
read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wine_server_call (NTDLL.@)
|
||||
*
|
||||
* Perform a server call.
|
||||
*/
|
||||
unsigned int wine_server_call( union generic_request *req, size_t size )
|
||||
unsigned int wine_server_call( void *req_ptr )
|
||||
{
|
||||
struct __server_request_info * const req = req_ptr;
|
||||
sigset_t old_set;
|
||||
|
||||
memset( (char *)req + size, 0, sizeof(*req) - size );
|
||||
memset( (char *)&req->u.req + req->size, 0, sizeof(req->u.req) - req->size );
|
||||
sigprocmask( SIG_BLOCK, &block_set, &old_set );
|
||||
send_request( req );
|
||||
wait_reply( req );
|
||||
sigprocmask( SIG_SETMASK, &old_set, NULL );
|
||||
return req->header.error;
|
||||
return req->u.reply.reply_header.error;
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,13 +336,13 @@ int wine_server_recv_fd( handle_t handle )
|
|||
req->flags = 0;
|
||||
req->mask = 0;
|
||||
req->fd = fd;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
if (req->cur_fd != fd)
|
||||
if (reply->cur_fd != fd)
|
||||
{
|
||||
/* someone was here before us */
|
||||
close( fd );
|
||||
fd = req->cur_fd;
|
||||
fd = reply->cur_fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -596,47 +601,6 @@ void CLIENT_InitServer(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* set_request_buffer
|
||||
*/
|
||||
inline static void set_request_buffer(void)
|
||||
{
|
||||
char *name;
|
||||
int fd, ret;
|
||||
unsigned int offset, size;
|
||||
|
||||
/* create a temporary file */
|
||||
do
|
||||
{
|
||||
if (!(name = tmpnam(NULL))) server_protocol_perror( "tmpnam" );
|
||||
fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
|
||||
} while ((fd == -1) && (errno == EEXIST));
|
||||
|
||||
if (fd == -1) server_protocol_perror( "create" );
|
||||
unlink( name );
|
||||
|
||||
wine_server_send_fd( fd );
|
||||
|
||||
SERVER_START_REQ( set_thread_buffer )
|
||||
{
|
||||
req->fd = fd;
|
||||
ret = SERVER_CALL();
|
||||
offset = req->offset;
|
||||
size = req->size;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) server_protocol_error( "set_thread_buffer failed with status %x\n", ret );
|
||||
|
||||
if ((NtCurrentTeb()->buffer = mmap( 0, size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, offset )) == (void*)-1)
|
||||
server_protocol_perror( "mmap" );
|
||||
|
||||
close( fd );
|
||||
NtCurrentTeb()->buffer_pos = 0;
|
||||
NtCurrentTeb()->buffer_size = size;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CLIENT_InitThread
|
||||
*
|
||||
|
@ -670,11 +634,11 @@ void CLIENT_InitThread(void)
|
|||
req->entry = teb->entry_point;
|
||||
req->reply_fd = reply_pipe[1];
|
||||
req->wait_fd = teb->wait_fd[1];
|
||||
ret = SERVER_CALL();
|
||||
teb->pid = req->pid;
|
||||
teb->tid = req->tid;
|
||||
version = req->version;
|
||||
if (req->boot) boot_thread_id = teb->tid;
|
||||
ret = wine_server_call( req );
|
||||
teb->pid = reply->pid;
|
||||
teb->tid = reply->tid;
|
||||
version = reply->version;
|
||||
if (reply->boot) boot_thread_id = teb->tid;
|
||||
else if (boot_thread_id == teb->tid) boot_thread_id = 0;
|
||||
close( reply_pipe[1] );
|
||||
}
|
||||
|
@ -688,7 +652,6 @@ void CLIENT_InitThread(void)
|
|||
"Or maybe the wrong wineserver is still running?\n",
|
||||
version, SERVER_PROTOCOL_VERSION,
|
||||
(version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
|
||||
set_request_buffer();
|
||||
}
|
||||
|
||||
|
||||
|
@ -702,7 +665,7 @@ void CLIENT_BootDone( int debug_level )
|
|||
SERVER_START_REQ( boot_done )
|
||||
{
|
||||
req->debug_level = debug_level;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ BOOL WINAPI GetHandleInformation( HANDLE handle, LPDWORD flags )
|
|||
req->flags = 0;
|
||||
req->mask = 0;
|
||||
req->fd = -1;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
if (ret && flags) *flags = req->old_flags;
|
||||
ret = !wine_server_call_err( req );
|
||||
if (ret && flags) *flags = reply->old_flags;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -66,7 +66,7 @@ BOOL WINAPI SetHandleInformation( HANDLE handle, DWORD mask, DWORD flags )
|
|||
req->flags = flags;
|
||||
req->mask = mask;
|
||||
req->fd = -1;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -90,11 +90,11 @@ BOOL WINAPI DuplicateHandle( HANDLE source_process, HANDLE source,
|
|||
req->inherit = inherit;
|
||||
req->options = options;
|
||||
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
if (ret)
|
||||
{
|
||||
if (dest) *dest = req->handle;
|
||||
if (req->fd != -1) close( req->fd );
|
||||
if (dest) *dest = reply->handle;
|
||||
if (reply->fd != -1) close( reply->fd );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
|
|
@ -20,10 +20,10 @@ BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
|
|||
SERVER_START_REQ( create_pipe )
|
||||
{
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
*hReadPipe = req->handle_read;
|
||||
*hWritePipe = req->handle_write;
|
||||
*hReadPipe = reply->handle_read;
|
||||
*hWritePipe = reply->handle_write;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
|
|
@ -92,7 +92,9 @@ PDB current_process;
|
|||
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
|
||||
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
|
||||
|
||||
static char **main_exe_argv;
|
||||
static int app_argc; /* argc/argv seen by the application */
|
||||
static char **app_argv;
|
||||
static WCHAR **app_wargv;
|
||||
static char main_exe_name[MAX_PATH];
|
||||
static char *main_exe_name_ptr = main_exe_name;
|
||||
static HANDLE main_exe_file;
|
||||
|
@ -229,7 +231,7 @@ static BOOL process_init( char *argv[] )
|
|||
|
||||
/* store the program name */
|
||||
argv0 = argv[0];
|
||||
main_exe_argv = argv;
|
||||
app_argv = argv;
|
||||
|
||||
/* Fill the initial process structure */
|
||||
current_process.exit_code = STILL_ACTIVE;
|
||||
|
@ -243,26 +245,26 @@ static BOOL process_init( char *argv[] )
|
|||
CLIENT_InitServer();
|
||||
|
||||
/* Retrieve startup info from the server */
|
||||
SERVER_START_VAR_REQ( init_process, sizeof(main_exe_name)-1 )
|
||||
SERVER_START_REQ( init_process )
|
||||
{
|
||||
req->ldt_copy = &wine_ldt_copy;
|
||||
req->ppid = getppid();
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
wine_server_set_reply( req, main_exe_name, sizeof(main_exe_name)-1 );
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
size_t len = server_data_size( req );
|
||||
memcpy( main_exe_name, server_data_ptr(req), len );
|
||||
size_t len = wine_server_reply_size( reply );
|
||||
main_exe_name[len] = 0;
|
||||
main_exe_file = req->exe_file;
|
||||
create_flags = req->create_flags;
|
||||
current_startupinfo.dwFlags = req->start_flags;
|
||||
server_startticks = req->server_start;
|
||||
current_startupinfo.wShowWindow = req->cmd_show;
|
||||
current_startupinfo.hStdInput = req->hstdin;
|
||||
current_startupinfo.hStdOutput = req->hstdout;
|
||||
current_startupinfo.hStdError = req->hstderr;
|
||||
main_exe_file = reply->exe_file;
|
||||
create_flags = reply->create_flags;
|
||||
current_startupinfo.dwFlags = reply->start_flags;
|
||||
server_startticks = reply->server_start;
|
||||
current_startupinfo.wShowWindow = reply->cmd_show;
|
||||
current_startupinfo.hStdInput = reply->hstdin;
|
||||
current_startupinfo.hStdOutput = reply->hstdout;
|
||||
current_startupinfo.hStdError = reply->hstderr;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return FALSE;
|
||||
|
||||
/* Create the process heap */
|
||||
|
@ -295,6 +297,8 @@ static BOOL process_init( char *argv[] )
|
|||
|
||||
/* Parse command line arguments */
|
||||
OPTIONS_ParseOptions( argv );
|
||||
app_argc = 0;
|
||||
while (argv[app_argc]) app_argc++;
|
||||
|
||||
ret = MAIN_MainInit();
|
||||
|
||||
|
@ -345,8 +349,8 @@ static void start_process(void)
|
|||
req->name = &main_exe_name_ptr;
|
||||
req->exe_file = main_file;
|
||||
req->gui = !console_app;
|
||||
SERVER_CALL();
|
||||
debugged = req->debugged;
|
||||
wine_server_call( req );
|
||||
debugged = reply->debugged;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -464,19 +468,20 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
|
|||
/* Initialize everything */
|
||||
if (!process_init( argv )) exit(1);
|
||||
|
||||
if (open_winelib_app( argv )) goto found; /* try to open argv[0] as a winelib app */
|
||||
if (open_winelib_app( app_argv )) goto found; /* try to open argv[0] as a winelib app */
|
||||
|
||||
main_exe_argv = ++argv; /* remove argv[0] (wine itself) */
|
||||
app_argv++; /* remove argv[0] (wine itself) */
|
||||
app_argc--;
|
||||
|
||||
if (!main_exe_name[0])
|
||||
{
|
||||
if (!argv[0]) OPTIONS_Usage();
|
||||
if (!app_argv[0]) OPTIONS_Usage();
|
||||
|
||||
/* open the exe file */
|
||||
if (!SearchPathA( NULL, argv[0], ".exe", sizeof(main_exe_name), main_exe_name, NULL ) &&
|
||||
!SearchPathA( NULL, argv[0], NULL, sizeof(main_exe_name), main_exe_name, NULL ))
|
||||
if (!SearchPathA( NULL, app_argv[0], ".exe", sizeof(main_exe_name), main_exe_name, NULL) &&
|
||||
!SearchPathA( NULL, app_argv[0], NULL, sizeof(main_exe_name), main_exe_name, NULL))
|
||||
{
|
||||
MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] );
|
||||
MESSAGE( "%s: cannot find '%s'\n", argv0, app_argv[0] );
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +515,7 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
|
|||
|
||||
found:
|
||||
/* build command line */
|
||||
if (!ENV_BuildCommandLine( main_exe_argv )) goto error;
|
||||
if (!ENV_BuildCommandLine( app_argv )) goto error;
|
||||
|
||||
/* create 32-bit module for main exe */
|
||||
if (!(current_process.module = BUILTIN32_LoadExeModule( current_process.module ))) goto error;
|
||||
|
@ -527,6 +532,52 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_get_main_args (NTDLL.@)
|
||||
*
|
||||
* Return the argc/argv that the application should see.
|
||||
* Used by the startup code generated in the .spec.c file.
|
||||
*/
|
||||
int __wine_get_main_args( char ***argv )
|
||||
{
|
||||
*argv = app_argv;
|
||||
return app_argc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* __wine_get_wmain_args (NTDLL.@)
|
||||
*
|
||||
* Same as __wine_get_main_args but for Unicode.
|
||||
*/
|
||||
int __wine_get_wmain_args( WCHAR ***argv )
|
||||
{
|
||||
if (!app_wargv)
|
||||
{
|
||||
int i;
|
||||
WCHAR *p;
|
||||
DWORD total = 0;
|
||||
|
||||
for (i = 0; i < app_argc; i++)
|
||||
total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 );
|
||||
|
||||
app_wargv = HeapAlloc( GetProcessHeap(), 0,
|
||||
total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) );
|
||||
p = (WCHAR *)(app_wargv + app_argc + 1);
|
||||
for (i = 0; i < app_argc; i++)
|
||||
{
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total );
|
||||
app_wargv[i] = p;
|
||||
p += len;
|
||||
total -= len;
|
||||
}
|
||||
app_wargv[app_argc] = NULL;
|
||||
}
|
||||
*argv = app_wargv;
|
||||
return app_argc;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* build_argv
|
||||
*
|
||||
|
@ -820,8 +871,10 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
|||
|
||||
/* create the process on the server side */
|
||||
|
||||
SERVER_START_VAR_REQ( new_process, MAX_PATH )
|
||||
SERVER_START_REQ( new_process )
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
|
||||
req->inherit_all = inherit;
|
||||
req->create_flags = flags;
|
||||
req->start_flags = startup->dwFlags;
|
||||
|
@ -845,17 +898,19 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
|||
unixfilename = filename;
|
||||
if (DOSFS_GetFullName( filename, TRUE, &full_name ))
|
||||
unixfilename = full_name.long_name;
|
||||
lstrcpynA( server_data_ptr(req), unixfilename, MAX_PATH );
|
||||
wine_server_add_data( req, unixfilename, strlen(unixfilename) );
|
||||
}
|
||||
else /* new wine process */
|
||||
{
|
||||
if (!GetLongPathNameA( filename, server_data_ptr(req), MAX_PATH ))
|
||||
lstrcpynA( server_data_ptr(req), filename, MAX_PATH );
|
||||
if (GetLongPathNameA( filename, buf, MAX_PATH ))
|
||||
wine_server_add_data( req, buf, strlen(buf) );
|
||||
else
|
||||
wine_server_add_data( req, filename, strlen(filename) );
|
||||
}
|
||||
ret = !SERVER_CALL_ERR();
|
||||
process_info = req->info;
|
||||
ret = !wine_server_call_err( req );
|
||||
process_info = reply->info;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return FALSE;
|
||||
|
||||
/* fork and execute */
|
||||
|
@ -876,13 +931,13 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
|
|||
req->info = process_info;
|
||||
req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
|
||||
req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
info->dwProcessId = (DWORD)req->pid;
|
||||
info->dwThreadId = (DWORD)req->tid;
|
||||
info->hProcess = req->phandle;
|
||||
info->hThread = req->thandle;
|
||||
load_done_evt = req->event;
|
||||
info->dwProcessId = (DWORD)reply->pid;
|
||||
info->dwThreadId = (DWORD)reply->tid;
|
||||
info->hProcess = reply->phandle;
|
||||
info->hThread = reply->thandle;
|
||||
load_done_evt = reply->event;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -924,7 +979,7 @@ void WINAPI ExitProcess( DWORD status )
|
|||
/* send the exit code to the server */
|
||||
req->handle = GetCurrentProcess();
|
||||
req->exit_code = status;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
exit( status );
|
||||
|
@ -1084,7 +1139,7 @@ HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
|
|||
req->pid = (void *)id;
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (!SERVER_CALL_ERR()) ret = req->handle;
|
||||
if (!wine_server_call_err( req )) ret = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1099,7 +1154,7 @@ DWORD WINAPI MapProcessHandle( HANDLE handle )
|
|||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!SERVER_CALL_ERR()) ret = (DWORD)req->pid;
|
||||
if (!wine_server_call_err( req )) ret = (DWORD)reply->pid;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1116,7 +1171,7 @@ BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
|
|||
req->handle = hprocess;
|
||||
req->priority = priorityclass;
|
||||
req->mask = SET_PROCESS_INFO_PRIORITY;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1132,7 +1187,7 @@ DWORD WINAPI GetPriorityClass(HANDLE hprocess)
|
|||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hprocess;
|
||||
if (!SERVER_CALL_ERR()) ret = req->priority;
|
||||
if (!wine_server_call_err( req )) ret = reply->priority;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1150,7 +1205,7 @@ BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
|
|||
req->handle = hProcess;
|
||||
req->affinity = affmask;
|
||||
req->mask = SET_PROCESS_INFO_AFFINITY;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -1167,10 +1222,10 @@ BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
|
|||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
if (lpProcessAffinityMask) *lpProcessAffinityMask = req->process_affinity;
|
||||
if (lpSystemAffinityMask) *lpSystemAffinityMask = req->system_affinity;
|
||||
if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
|
||||
if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1289,62 +1344,36 @@ BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
|
|||
BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWORD size,
|
||||
LPDWORD bytes_read )
|
||||
{
|
||||
unsigned int offset = (unsigned int)addr % sizeof(int);
|
||||
unsigned int pos = 0, len, max;
|
||||
int res;
|
||||
DWORD res;
|
||||
|
||||
if (bytes_read) *bytes_read = size;
|
||||
|
||||
/* first time, read total length to check for permissions */
|
||||
len = (size + offset + sizeof(int) - 1) / sizeof(int);
|
||||
max = min( REQUEST_MAX_VAR_SIZE, len * sizeof(int) );
|
||||
|
||||
for (;;)
|
||||
SERVER_START_REQ( read_process_memory )
|
||||
{
|
||||
SERVER_START_VAR_REQ( read_process_memory, max )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (char *)addr + pos - offset;
|
||||
req->len = len;
|
||||
if (!(res = SERVER_CALL_ERR()))
|
||||
{
|
||||
size_t result = server_data_size( req );
|
||||
if (result > size + offset) result = size + offset;
|
||||
memcpy( (char *)buffer + pos, server_data_ptr(req) + offset, result - offset );
|
||||
size -= result - offset;
|
||||
pos += result - offset;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
if (res)
|
||||
{
|
||||
if (bytes_read) *bytes_read = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (!size) return TRUE;
|
||||
max = min( REQUEST_MAX_VAR_SIZE, size );
|
||||
len = (max + sizeof(int) - 1) / sizeof(int);
|
||||
offset = 0;
|
||||
req->handle = process;
|
||||
req->addr = (void *)addr;
|
||||
wine_server_set_reply( req, buffer, size );
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_read) *bytes_read = size;
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WriteProcessMemory (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPVOID buffer, DWORD size,
|
||||
BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, DWORD size,
|
||||
LPDWORD bytes_written )
|
||||
{
|
||||
unsigned int first_offset, last_offset;
|
||||
unsigned int pos = 0, len, max, first_mask, last_mask;
|
||||
int res;
|
||||
static const int zero;
|
||||
unsigned int first_offset, last_offset, first_mask, last_mask;
|
||||
DWORD res;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
if (bytes_written) *bytes_written = size;
|
||||
|
||||
/* compute the mask for the first int */
|
||||
first_mask = ~0;
|
||||
|
@ -1356,44 +1385,26 @@ BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPVOID buffer, DWOR
|
|||
last_mask = 0;
|
||||
memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) );
|
||||
|
||||
/* for the first request, use the total length */
|
||||
len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
|
||||
max = min( REQUEST_MAX_VAR_SIZE, len * sizeof(int) );
|
||||
|
||||
for (;;)
|
||||
SERVER_START_REQ( write_process_memory )
|
||||
{
|
||||
SERVER_START_VAR_REQ( write_process_memory, max )
|
||||
{
|
||||
req->handle = process;
|
||||
req->addr = (char *)addr - first_offset + pos;
|
||||
req->len = len;
|
||||
req->first_mask = (!pos) ? first_mask : ~0;
|
||||
if (size + first_offset <= max) /* last round */
|
||||
{
|
||||
req->last_mask = last_mask;
|
||||
max = size + first_offset;
|
||||
}
|
||||
else req->last_mask = ~0;
|
||||
req->handle = process;
|
||||
req->addr = (char *)addr - first_offset;
|
||||
req->first_mask = first_mask;
|
||||
req->last_mask = last_mask;
|
||||
if (first_offset) wine_server_add_data( req, &zero, first_offset );
|
||||
wine_server_add_data( req, buffer, size );
|
||||
if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset );
|
||||
|
||||
memcpy( (char *)server_data_ptr(req) + first_offset, (char *)buffer + pos,
|
||||
max - first_offset );
|
||||
if (!(res = SERVER_CALL_ERR()))
|
||||
{
|
||||
pos += max - first_offset;
|
||||
size -= max - first_offset;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
if (res)
|
||||
{
|
||||
if (bytes_written) *bytes_written = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (!size) return TRUE;
|
||||
first_offset = 0;
|
||||
len = min( size + sizeof(int) - 1, REQUEST_MAX_VAR_SIZE ) / sizeof(int);
|
||||
max = len * sizeof(int);
|
||||
if ((res = wine_server_call_err( req ))) size = 0;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (bytes_written) *bytes_written = size;
|
||||
{
|
||||
char dummy[32];
|
||||
DWORD read;
|
||||
ReadProcessMemory( process, addr, dummy, sizeof(dummy), &read );
|
||||
}
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1427,8 +1438,8 @@ BOOL WINAPI GetExitCodeProcess(
|
|||
SERVER_START_REQ( get_process_info )
|
||||
{
|
||||
req->handle = hProcess;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
if (ret && lpExitCode) *lpExitCode = req->exit_code;
|
||||
ret = !wine_server_call_err( req );
|
||||
if (ret && lpExitCode) *lpExitCode = reply->exit_code;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -226,17 +226,17 @@ static void call_apcs( BOOL alertable )
|
|||
for (;;)
|
||||
{
|
||||
int type = APC_NONE;
|
||||
SERVER_START_VAR_REQ( get_apc, sizeof(args) )
|
||||
SERVER_START_REQ( get_apc )
|
||||
{
|
||||
req->alertable = alertable;
|
||||
if (!SERVER_CALL())
|
||||
wine_server_set_reply( req, args, sizeof(args) );
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
type = req->type;
|
||||
proc = req->func;
|
||||
memcpy( args, server_data_ptr(req), server_data_size(req) );
|
||||
type = reply->type;
|
||||
proc = reply->func;
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
|
@ -315,7 +315,7 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
|
|||
BOOL wait_all, DWORD timeout,
|
||||
BOOL alertable )
|
||||
{
|
||||
int i, ret, cookie;
|
||||
int ret, cookie;
|
||||
struct timeval tv;
|
||||
|
||||
if (count > MAXIMUM_WAIT_OBJECTS)
|
||||
|
@ -329,23 +329,21 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
|
|||
|
||||
for (;;)
|
||||
{
|
||||
SERVER_START_VAR_REQ( select, count * sizeof(int) )
|
||||
SERVER_START_REQ( select )
|
||||
{
|
||||
int *data = server_data_ptr( req );
|
||||
|
||||
req->flags = SELECT_INTERRUPTIBLE;
|
||||
req->cookie = &cookie;
|
||||
req->sec = tv.tv_sec;
|
||||
req->usec = tv.tv_usec;
|
||||
for (i = 0; i < count; i++) data[i] = handles[i];
|
||||
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
||||
|
||||
if (wait_all) req->flags |= SELECT_ALL;
|
||||
if (alertable) req->flags |= SELECT_ALERTABLE;
|
||||
if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
|
||||
|
||||
ret = SERVER_CALL();
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
|
||||
if (ret != STATUS_USER_APC) break;
|
||||
call_apcs( alertable );
|
||||
|
|
|
@ -51,7 +51,7 @@ TEB *THREAD_IdToTEB( DWORD id )
|
|||
{
|
||||
req->handle = 0;
|
||||
req->tid_in = (void *)id;
|
||||
if (!SERVER_CALL()) ret = req->teb;
|
||||
if (!wine_server_call( req )) ret = reply->teb;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -112,7 +112,6 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb )
|
|||
close( teb->wait_fd[1] );
|
||||
if (teb->stack_sel) FreeSelector16( teb->stack_sel );
|
||||
FreeSelector16( teb->teb_sel );
|
||||
if (teb->buffer) munmap( (void *)teb->buffer, teb->buffer_size );
|
||||
if (teb->debug_info) HeapFree( GetProcessHeap(), 0, teb->debug_info );
|
||||
VirtualFree( teb->stack_base, 0, MEM_RELEASE );
|
||||
}
|
||||
|
@ -298,10 +297,10 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
|
|||
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
req->request_fd = request_pipe[0];
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
handle = req->handle;
|
||||
tid = req->tid;
|
||||
handle = reply->handle;
|
||||
tid = reply->tid;
|
||||
}
|
||||
close( request_pipe[0] );
|
||||
}
|
||||
|
@ -370,8 +369,8 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
|
|||
/* send the exit code to the server */
|
||||
req->handle = GetCurrentThread();
|
||||
req->exit_code = code;
|
||||
SERVER_CALL();
|
||||
last = req->last;
|
||||
wine_server_call( req );
|
||||
last = reply->last;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -400,14 +399,14 @@ BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread
|
|||
const CONTEXT *context ) /* [in] Address of context structure */
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_VAR_REQ( set_thread_context, sizeof(*context) )
|
||||
SERVER_START_REQ( set_thread_context )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->flags = context->ContextFlags;
|
||||
memcpy( server_data_ptr(req), context, sizeof(*context) );
|
||||
ret = !SERVER_CALL_ERR();
|
||||
wine_server_add_data( req, context, sizeof(*context) );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -423,15 +422,15 @@ BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with
|
|||
CONTEXT *context ) /* [out] Address of context structure */
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_VAR_REQ( get_thread_context, sizeof(*context) )
|
||||
SERVER_START_REQ( get_thread_context )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->flags = context->ContextFlags;
|
||||
memcpy( server_data_ptr(req), context, sizeof(*context) );
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
memcpy( context, server_data_ptr(req), sizeof(*context) );
|
||||
wine_server_add_data( req, context, sizeof(*context) );
|
||||
wine_server_set_reply( req, context, sizeof(*context) );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -451,7 +450,7 @@ INT WINAPI GetThreadPriority(
|
|||
{
|
||||
req->handle = hthread;
|
||||
req->tid_in = 0;
|
||||
if (!SERVER_CALL_ERR()) ret = req->priority;
|
||||
if (!wine_server_call_err( req )) ret = reply->priority;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -475,7 +474,7 @@ BOOL WINAPI SetThreadPriority(
|
|||
req->handle = hthread;
|
||||
req->priority = priority;
|
||||
req->mask = SET_THREAD_INFO_PRIORITY;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -529,7 +528,7 @@ DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
|
|||
req->handle = hThread;
|
||||
req->affinity = dwThreadAffinityMask;
|
||||
req->mask = SET_THREAD_INFO_AFFINITY;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
/* FIXME: should return previous value */
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -571,8 +570,8 @@ BOOL WINAPI GetExitCodeThread(
|
|||
{
|
||||
req->handle = hthread;
|
||||
req->tid_in = 0;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
if (ret && exitcode) *exitcode = req->exit_code;
|
||||
ret = !wine_server_call_err( req );
|
||||
if (ret && exitcode) *exitcode = reply->exit_code;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -597,7 +596,7 @@ DWORD WINAPI ResumeThread(
|
|||
SERVER_START_REQ( resume_thread )
|
||||
{
|
||||
req->handle = hthread;
|
||||
if (!SERVER_CALL_ERR()) ret = req->count;
|
||||
if (!wine_server_call_err( req )) ret = reply->count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -618,7 +617,7 @@ DWORD WINAPI SuspendThread(
|
|||
SERVER_START_REQ( suspend_thread )
|
||||
{
|
||||
req->handle = hthread;
|
||||
if (!SERVER_CALL_ERR()) ret = req->count;
|
||||
if (!wine_server_call_err( req )) ret = reply->count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -637,7 +636,7 @@ DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
|
|||
req->user = 1;
|
||||
req->func = func;
|
||||
req->param = (void *)data;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -18,24 +18,16 @@
|
|||
*/
|
||||
HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return CreateWaitableTimerW( sa, manual, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_timer, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->manual = manual;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return CreateWaitableTimerW( sa, manual, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,16 +43,16 @@ HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWST
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( create_timer, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( create_timer )
|
||||
{
|
||||
req->manual = manual;
|
||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
SetLastError(0);
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -70,23 +62,16 @@ HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWST
|
|||
*/
|
||||
HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
|
||||
{
|
||||
HANDLE ret;
|
||||
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||
if (len >= MAX_PATH)
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
if (!name) return OpenWaitableTimerW( access, inherit, NULL );
|
||||
|
||||
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
|
||||
{
|
||||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_timer, len * sizeof(WCHAR) )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return ret;
|
||||
return OpenWaitableTimerW( access, inherit, buffer );
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,15 +87,15 @@ HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
|
|||
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||
return 0;
|
||||
}
|
||||
SERVER_START_VAR_REQ( open_timer, len * sizeof(WCHAR) )
|
||||
SERVER_START_REQ( open_timer )
|
||||
{
|
||||
req->access = access;
|
||||
req->inherit = inherit;
|
||||
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||
SERVER_CALL_ERR();
|
||||
ret = req->handle;
|
||||
wine_server_add_data( req, name, len * sizeof(WCHAR) );
|
||||
wine_server_call_err( req );
|
||||
ret = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -150,7 +135,7 @@ BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG per
|
|||
req->callback = callback;
|
||||
req->arg = arg;
|
||||
if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -166,7 +151,7 @@ BOOL WINAPI CancelWaitableTimer( HANDLE handle )
|
|||
SERVER_START_REQ( cancel_timer )
|
||||
{
|
||||
req->handle = handle;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -28,7 +28,7 @@ DECL_HANDLER(create_async)
|
|||
/* FIXME: check if this object is allowed to do overlapped I/O */
|
||||
|
||||
/* FIXME: this should be a function pointer */
|
||||
req->timeout = get_serial_async_timeout(obj,req->type,req->count);
|
||||
reply->timeout = get_serial_async_timeout(obj,req->type,req->count);
|
||||
|
||||
release_object(obj);
|
||||
}
|
||||
|
|
|
@ -65,11 +65,14 @@ static const struct object_ops atom_table_ops =
|
|||
static struct atom_table *global_table;
|
||||
|
||||
|
||||
/* copy an atom name to a temporary area */
|
||||
static const WCHAR *copy_name( const WCHAR *str, size_t len )
|
||||
/* copy an atom name from the request to a temporary area */
|
||||
static const WCHAR *copy_request_name(void)
|
||||
{
|
||||
static WCHAR buffer[MAX_ATOM_LEN+1];
|
||||
|
||||
const WCHAR *str = get_req_data();
|
||||
size_t len = get_req_data_size();
|
||||
|
||||
if (len > MAX_ATOM_LEN*sizeof(WCHAR))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
|
@ -267,27 +270,6 @@ static atom_t find_atom( struct atom_table *table, const WCHAR *str )
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* get an atom name and refcount*/
|
||||
static size_t get_atom_name( struct atom_table *table, atom_t atom,
|
||||
WCHAR *str, size_t maxsize, int *count )
|
||||
{
|
||||
size_t len = 0;
|
||||
struct atom_entry *entry = get_atom_entry( table, atom );
|
||||
*count = -1;
|
||||
if (entry)
|
||||
{
|
||||
*count = entry->count;
|
||||
len = strlenW( entry->str ) * sizeof(WCHAR);
|
||||
if (len <= maxsize) memcpy( str, entry->str, len );
|
||||
else
|
||||
{
|
||||
set_error( STATUS_BUFFER_OVERFLOW );
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* increment the ref count of a global atom; used for window properties */
|
||||
int grab_global_atom( atom_t atom )
|
||||
{
|
||||
|
@ -310,8 +292,8 @@ DECL_HANDLER(add_atom)
|
|||
if (!*table_ptr) *table_ptr = create_table(0);
|
||||
if (*table_ptr)
|
||||
{
|
||||
const WCHAR *name = copy_name( get_req_data(req), get_req_data_size(req) );
|
||||
if (name) req->atom = add_atom( *table_ptr, name );
|
||||
const WCHAR *name = copy_request_name();
|
||||
if (name) reply->atom = add_atom( *table_ptr, name );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,18 +306,26 @@ DECL_HANDLER(delete_atom)
|
|||
/* find a global atom */
|
||||
DECL_HANDLER(find_atom)
|
||||
{
|
||||
const WCHAR *name = copy_name( get_req_data(req), get_req_data_size(req) );
|
||||
const WCHAR *name = copy_request_name();
|
||||
if (name)
|
||||
req->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
|
||||
reply->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
|
||||
}
|
||||
|
||||
/* get global atom name */
|
||||
DECL_HANDLER(get_atom_name)
|
||||
{
|
||||
WCHAR *name = get_req_data(req);
|
||||
size_t size = get_atom_name( req->local ? current->process->atom_table : global_table,
|
||||
req->atom, name, get_req_data_size(req), &req->count );
|
||||
set_req_data_size( req, size );
|
||||
struct atom_entry *entry;
|
||||
size_t len = 0;
|
||||
|
||||
reply->count = -1;
|
||||
if ((entry = get_atom_entry( req->local ? current->process->atom_table : global_table,
|
||||
req->atom )))
|
||||
{
|
||||
reply->count = entry->count;
|
||||
len = strlenW( entry->str ) * sizeof(WCHAR);
|
||||
if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
|
||||
else set_error( STATUS_BUFFER_OVERFLOW );
|
||||
}
|
||||
}
|
||||
|
||||
/* init the process atom table */
|
||||
|
|
|
@ -72,11 +72,11 @@ DECL_HANDLER(create_change_notification)
|
|||
{
|
||||
struct change *change;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((change = create_change_notification( req->subtree, req->filter )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, change,
|
||||
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
|
||||
reply->handle = alloc_handle( current->process, change,
|
||||
STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
|
||||
release_object( change );
|
||||
}
|
||||
}
|
||||
|
|
735
server/console.c
735
server/console.c
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,8 @@
|
|||
#ifndef __WINE_SERVER_CONSOLE_H
|
||||
#define __WINE_SERVER_CONSOLE_H
|
||||
|
||||
#include "wincon.h"
|
||||
|
||||
struct screen_buffer;
|
||||
struct console_input_events;
|
||||
|
||||
|
@ -18,7 +20,7 @@ struct console_input
|
|||
int mode; /* input mode */
|
||||
struct screen_buffer *active; /* active screen buffer */
|
||||
int recnum; /* number of input records */
|
||||
void *records; /* input records */
|
||||
INPUT_RECORD *records; /* input records */
|
||||
struct console_input_events *evt; /* synchronization event with renderer */
|
||||
WCHAR *title; /* console title */
|
||||
WCHAR **history; /* lines history */
|
||||
|
|
|
@ -144,7 +144,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* set a thread context */
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
||||
{
|
||||
int pid = thread->unix_pid;
|
||||
if (flags & CONTEXT_FULL)
|
||||
|
@ -195,7 +195,6 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
/* we can use context->FloatSave directly as it is using the */
|
||||
/* correct structure (the same as fsave/frstor) */
|
||||
if (ptrace( PTRACE_SETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error;
|
||||
context->FloatSave.Cr0NpxState = 0; /* FIXME */
|
||||
}
|
||||
return;
|
||||
error:
|
||||
|
@ -256,7 +255,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* set a thread context */
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
||||
{
|
||||
int pid = thread->unix_pid;
|
||||
if (flags & CONTEXT_FULL)
|
||||
|
@ -303,7 +302,6 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
/* we can use context->FloatSave directly as it is using the */
|
||||
/* correct structure (the same as fsave/frstor) */
|
||||
if (ptrace( PTRACE_SETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
|
||||
context->FloatSave.Cr0NpxState = 0; /* FIXME */
|
||||
}
|
||||
return;
|
||||
error:
|
||||
|
@ -365,7 +363,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* set a thread context */
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
||||
{
|
||||
int pid = thread->unix_pid;
|
||||
if (flags & CONTEXT_FULL)
|
||||
|
@ -412,7 +410,6 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
/* we can use context->FloatSave directly as it is using the */
|
||||
/* correct structure (the same as fsave/frstor) */
|
||||
if (ptrace( PTRACE_SETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
|
||||
context->FloatSave.Cr0NpxState = 0; /* FIXME */
|
||||
}
|
||||
return;
|
||||
error:
|
||||
|
@ -425,7 +422,7 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* copy a context structure according to the flags */
|
||||
static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
|
||||
static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
|
||||
{
|
||||
if (flags & CONTEXT_CONTROL)
|
||||
{
|
||||
|
@ -486,27 +483,34 @@ int get_thread_single_step( struct thread *thread )
|
|||
DECL_HANDLER(get_thread_context)
|
||||
{
|
||||
struct thread *thread;
|
||||
void *data;
|
||||
int flags = req->flags & ~CONTEXT_i386; /* get rid of CPU id */
|
||||
|
||||
if (get_req_data_size(req) < sizeof(CONTEXT))
|
||||
if (get_reply_max_size() < sizeof(CONTEXT))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
|
||||
if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
|
||||
|
||||
if ((data = set_reply_data_size( sizeof(CONTEXT) )))
|
||||
{
|
||||
/* copy incoming context into reply */
|
||||
memset( data, 0, sizeof(CONTEXT) );
|
||||
memcpy( data, get_req_data(), min( get_req_data_size(), sizeof(CONTEXT) ));
|
||||
|
||||
if (thread->context) /* thread is inside an exception event */
|
||||
{
|
||||
copy_context( get_req_data(req), thread->context, flags );
|
||||
copy_context( data, thread->context, flags );
|
||||
flags &= CONTEXT_DEBUG_REGISTERS;
|
||||
}
|
||||
if (flags && suspend_for_ptrace( thread ))
|
||||
{
|
||||
get_thread_context( thread, flags, get_req_data(req) );
|
||||
get_thread_context( thread, flags, data );
|
||||
resume_thread( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
|
||||
|
||||
|
@ -516,7 +520,7 @@ DECL_HANDLER(set_thread_context)
|
|||
struct thread *thread;
|
||||
int flags = req->flags & ~CONTEXT_i386; /* get rid of CPU id */
|
||||
|
||||
if (get_req_data_size(req) < sizeof(CONTEXT))
|
||||
if (get_req_data_size() < sizeof(CONTEXT))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
|
@ -525,12 +529,12 @@ DECL_HANDLER(set_thread_context)
|
|||
{
|
||||
if (thread->context) /* thread is inside an exception event */
|
||||
{
|
||||
copy_context( thread->context, get_req_data(req), flags );
|
||||
copy_context( thread->context, get_req_data(), flags );
|
||||
flags &= CONTEXT_DEBUG_REGISTERS;
|
||||
}
|
||||
if (flags && suspend_for_ptrace( thread ))
|
||||
{
|
||||
set_thread_context( thread, flags, get_req_data(req) );
|
||||
set_thread_context( thread, flags, get_req_data() );
|
||||
resume_thread( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
|
|
|
@ -78,7 +78,7 @@ static void get_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* set a thread context */
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
|
||||
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE
|
|||
|
||||
|
||||
/* copy a context structure according to the flags */
|
||||
static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
|
||||
static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
|
||||
{
|
||||
if (flags & CONTEXT_CONTROL)
|
||||
{
|
||||
|
@ -164,27 +164,30 @@ int get_thread_single_step( struct thread *thread )
|
|||
DECL_HANDLER(get_thread_context)
|
||||
{
|
||||
struct thread *thread;
|
||||
void *data;
|
||||
int flags = req->flags & ~CONTEXT_SPARC; /* get rid of CPU id */
|
||||
|
||||
if (get_req_data_size(req) < sizeof(CONTEXT))
|
||||
if (get_reply_max_size() < sizeof(CONTEXT))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
|
||||
if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
|
||||
|
||||
if ((data = set_reply_data_size( sizeof(CONTEXT) )))
|
||||
{
|
||||
if (thread->context) /* thread is inside an exception event */
|
||||
{
|
||||
copy_context( get_req_data(req), thread->context, flags );
|
||||
copy_context( data, thread->context, flags );
|
||||
flags = 0;
|
||||
}
|
||||
if (flags && suspend_for_ptrace( thread ))
|
||||
{
|
||||
get_thread_context( thread, flags, get_req_data(req) );
|
||||
get_thread_context( thread, flags, data );
|
||||
resume_thread( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,7 +197,7 @@ DECL_HANDLER(set_thread_context)
|
|||
struct thread *thread;
|
||||
int flags = req->flags & ~CONTEXT_SPARC; /* get rid of CPU id */
|
||||
|
||||
if (get_req_data_size(req) < sizeof(CONTEXT))
|
||||
if (get_req_data_size() < sizeof(CONTEXT))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
|
@ -203,12 +206,12 @@ DECL_HANDLER(set_thread_context)
|
|||
{
|
||||
if (thread->context) /* thread is inside an exception event */
|
||||
{
|
||||
copy_context( thread->context, get_req_data(req), flags );
|
||||
copy_context( thread->context, get_req_data(), flags );
|
||||
flags = 0;
|
||||
}
|
||||
if (flags && suspend_for_ptrace( thread ))
|
||||
{
|
||||
set_thread_context( thread, flags, get_req_data(req) );
|
||||
set_thread_context( thread, flags, get_req_data() );
|
||||
resume_thread( thread );
|
||||
}
|
||||
release_object( thread );
|
||||
|
|
|
@ -353,7 +353,7 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
|||
|
||||
/* alloc a debug event for a debugger */
|
||||
static struct debug_event *alloc_debug_event( struct thread *thread, int code,
|
||||
void *arg, CONTEXT *context )
|
||||
void *arg, const CONTEXT *context )
|
||||
{
|
||||
struct thread *debugger = thread->process->debugger;
|
||||
struct debug_event *event;
|
||||
|
@ -498,25 +498,23 @@ DECL_HANDLER(wait_debug_event)
|
|||
set_error( STATUS_INVALID_HANDLE );
|
||||
return;
|
||||
}
|
||||
req->wait = 0;
|
||||
reply->wait = 0;
|
||||
if ((event = find_event_to_send( debug_ctx )))
|
||||
{
|
||||
size_t size = get_req_data_size(req);
|
||||
size_t size = get_reply_max_size();
|
||||
event->state = EVENT_SENT;
|
||||
event->sender->debug_event = event;
|
||||
req->pid = event->sender->process;
|
||||
req->tid = event->sender;
|
||||
reply->pid = event->sender->process;
|
||||
reply->tid = event->sender;
|
||||
if (size > sizeof(debug_event_t)) size = sizeof(debug_event_t);
|
||||
memcpy( get_req_data(req), &event->data, size );
|
||||
set_req_data_size( req, size );
|
||||
set_reply_data( &event->data, size );
|
||||
}
|
||||
else /* no event ready */
|
||||
{
|
||||
req->pid = 0;
|
||||
req->tid = 0;
|
||||
set_req_data_size( req, 0 );
|
||||
reply->pid = 0;
|
||||
reply->tid = 0;
|
||||
if (req->get_handle)
|
||||
req->wait = alloc_handle( current->process, debug_ctx, SYNCHRONIZE, FALSE );
|
||||
reply->wait = alloc_handle( current->process, debug_ctx, SYNCHRONIZE, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -562,15 +560,15 @@ DECL_HANDLER(debug_process)
|
|||
/* queue an exception event */
|
||||
DECL_HANDLER(queue_exception_event)
|
||||
{
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if (current->process->debugger)
|
||||
{
|
||||
struct debug_event_exception data;
|
||||
struct debug_event *event;
|
||||
CONTEXT *context = get_req_data( req );
|
||||
const CONTEXT *context = get_req_data();
|
||||
EXCEPTION_RECORD *rec = (EXCEPTION_RECORD *)(context + 1);
|
||||
|
||||
if (get_req_data_size( req ) < sizeof(*rec) + sizeof(*context))
|
||||
if (get_req_data_size() < sizeof(*rec) + sizeof(*context))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
|
@ -579,7 +577,7 @@ DECL_HANDLER(queue_exception_event)
|
|||
data.first = req->first;
|
||||
if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data, context )))
|
||||
{
|
||||
if ((req->handle = alloc_handle( current->process, event, SYNCHRONIZE, FALSE )))
|
||||
if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, FALSE )))
|
||||
{
|
||||
link_event( event );
|
||||
suspend_process( current->process );
|
||||
|
@ -593,26 +591,24 @@ DECL_HANDLER(queue_exception_event)
|
|||
DECL_HANDLER(get_exception_status)
|
||||
{
|
||||
struct debug_event *event;
|
||||
size_t size = 0;
|
||||
|
||||
req->status = 0;
|
||||
reply->status = 0;
|
||||
if ((event = (struct debug_event *)get_handle_obj( current->process, req->handle,
|
||||
0, &debug_event_ops )))
|
||||
{
|
||||
if (event->state == EVENT_CONTINUED)
|
||||
{
|
||||
req->status = event->status;
|
||||
reply->status = event->status;
|
||||
if (current->context == &event->context)
|
||||
{
|
||||
size = min( sizeof(CONTEXT), get_req_data_size(req) );
|
||||
memcpy( get_req_data(req), &event->context, size );
|
||||
size_t size = min( sizeof(CONTEXT), get_reply_max_size() );
|
||||
set_reply_data( &event->context, size );
|
||||
current->context = NULL;
|
||||
}
|
||||
}
|
||||
else set_error( STATUS_PENDING );
|
||||
release_object( event );
|
||||
}
|
||||
set_req_data_size( req, size );
|
||||
}
|
||||
|
||||
/* send an output string to the debugger */
|
||||
|
|
|
@ -29,7 +29,7 @@ struct device
|
|||
};
|
||||
|
||||
static void device_dump( struct object *obj, int verbose );
|
||||
static int device_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int device_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
|
||||
static const struct object_ops device_ops =
|
||||
{
|
||||
|
@ -64,23 +64,23 @@ static void device_dump( struct object *obj, int verbose )
|
|||
fprintf( stderr, "Device id=%08x\n", dev->id );
|
||||
}
|
||||
|
||||
static int device_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int device_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
struct device *dev = (struct device *)obj;
|
||||
assert( obj->ops == &device_ops );
|
||||
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
req->type = FILE_TYPE_UNKNOWN;
|
||||
req->attr = dev->id; /* hack! */
|
||||
req->access_time = 0;
|
||||
req->write_time = 0;
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
req->links = 0;
|
||||
req->index_high = 0;
|
||||
req->index_low = 0;
|
||||
req->serial = 0;
|
||||
reply->type = FILE_TYPE_UNKNOWN;
|
||||
reply->attr = dev->id; /* hack! */
|
||||
reply->access_time = 0;
|
||||
reply->write_time = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
reply->links = 0;
|
||||
reply->index_high = 0;
|
||||
reply->index_low = 0;
|
||||
reply->serial = 0;
|
||||
}
|
||||
return FD_TYPE_DEFAULT;
|
||||
}
|
||||
|
@ -90,10 +90,10 @@ DECL_HANDLER(create_device)
|
|||
{
|
||||
struct device *dev;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((dev = create_device( req->id )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, dev, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, dev, req->access, req->inherit );
|
||||
release_object( dev );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,11 +115,11 @@ DECL_HANDLER(create_event)
|
|||
{
|
||||
struct event *event;
|
||||
|
||||
req->handle = 0;
|
||||
if ((event = create_event( get_req_data(req), get_req_data_size(req),
|
||||
reply->handle = 0;
|
||||
if ((event = create_event( get_req_data(), get_req_data_size(),
|
||||
req->manual_reset, req->initial_state )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, event, EVENT_ALL_ACCESS, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, event, EVENT_ALL_ACCESS, req->inherit );
|
||||
release_object( event );
|
||||
}
|
||||
}
|
||||
|
@ -127,8 +127,8 @@ DECL_HANDLER(create_event)
|
|||
/* open a handle to an event */
|
||||
DECL_HANDLER(open_event)
|
||||
{
|
||||
req->handle = open_object( get_req_data(req), get_req_data_size(req),
|
||||
&event_ops, req->access, req->inherit );
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
&event_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
/* do an event operation */
|
||||
|
|
|
@ -49,7 +49,7 @@ static void file_dump( struct object *obj, int verbose );
|
|||
static int file_get_poll_events( struct object *obj );
|
||||
static int file_get_fd( struct object *obj );
|
||||
static int file_flush( struct object *obj );
|
||||
static int file_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
static void file_destroy( struct object *obj );
|
||||
|
||||
static const struct object_ops file_ops =
|
||||
|
@ -271,13 +271,13 @@ static int file_flush( struct object *obj )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int file_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
struct stat st;
|
||||
struct file *file = (struct file *)obj;
|
||||
assert( obj->ops == &file_ops );
|
||||
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
if (fstat( file->obj.fd, &st ) == -1)
|
||||
{
|
||||
|
@ -285,27 +285,27 @@ static int file_get_info( struct object *obj, struct get_file_info_request *req
|
|||
return FD_TYPE_INVALID;
|
||||
}
|
||||
if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
|
||||
S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
|
||||
else req->type = FILE_TYPE_DISK;
|
||||
if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||
else req->attr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
if (!(st.st_mode & S_IWUSR)) req->attr |= FILE_ATTRIBUTE_READONLY;
|
||||
req->access_time = st.st_atime;
|
||||
req->write_time = st.st_mtime;
|
||||
S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) reply->type = FILE_TYPE_CHAR;
|
||||
else reply->type = FILE_TYPE_DISK;
|
||||
if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||
else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
|
||||
reply->access_time = st.st_atime;
|
||||
reply->write_time = st.st_mtime;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
req->size_high = st.st_size >> 32;
|
||||
req->size_low = st.st_size & 0xffffffff;
|
||||
reply->size_high = st.st_size >> 32;
|
||||
reply->size_low = st.st_size & 0xffffffff;
|
||||
}
|
||||
req->links = st.st_nlink;
|
||||
req->index_high = st.st_dev;
|
||||
req->index_low = st.st_ino;
|
||||
req->serial = 0; /* FIXME */
|
||||
reply->links = st.st_nlink;
|
||||
reply->index_high = st.st_dev;
|
||||
reply->index_low = st.st_ino;
|
||||
reply->serial = 0; /* FIXME */
|
||||
}
|
||||
return FD_TYPE_DEFAULT;
|
||||
}
|
||||
|
@ -470,11 +470,11 @@ DECL_HANDLER(create_file)
|
|||
{
|
||||
struct file *file;
|
||||
|
||||
req->handle = 0;
|
||||
if ((file = create_file( get_req_data(req), get_req_data_size(req), req->access,
|
||||
reply->handle = 0;
|
||||
if ((file = create_file( get_req_data(), get_req_data_size(), req->access,
|
||||
req->sharing, req->create, req->attrs, req->drive_type )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, file, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
|
||||
release_object( file );
|
||||
}
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ DECL_HANDLER(alloc_file_handle)
|
|||
struct file *file;
|
||||
int fd;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((fd = thread_get_inflight_fd( current, req->fd )) == -1)
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
|
@ -494,7 +494,7 @@ DECL_HANDLER(alloc_file_handle)
|
|||
if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0, DRIVE_UNKNOWN )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, file, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
|
||||
release_object( file );
|
||||
}
|
||||
}
|
||||
|
@ -504,18 +504,18 @@ DECL_HANDLER(get_handle_fd)
|
|||
{
|
||||
struct object *obj;
|
||||
|
||||
req->fd = -1;
|
||||
req->type = FD_TYPE_INVALID;
|
||||
reply->fd = -1;
|
||||
reply->type = FD_TYPE_INVALID;
|
||||
if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL )))
|
||||
{
|
||||
int fd = get_handle_fd( current->process, req->handle, req->access );
|
||||
if (fd != -1) req->fd = fd;
|
||||
if (fd != -1) reply->fd = fd;
|
||||
else if (!get_error())
|
||||
{
|
||||
if ((fd = obj->ops->get_fd( obj )) != -1)
|
||||
send_client_fd( current->process, fd, req->handle );
|
||||
}
|
||||
req->type = obj->ops->get_file_info( obj, NULL );
|
||||
reply->type = obj->ops->get_file_info( obj, NULL );
|
||||
release_object( obj );
|
||||
}
|
||||
}
|
||||
|
@ -526,8 +526,8 @@ DECL_HANDLER(set_file_pointer)
|
|||
int high = req->high;
|
||||
int low = req->low;
|
||||
set_file_pointer( req->handle, &low, &high, req->whence );
|
||||
req->new_low = low;
|
||||
req->new_high = high;
|
||||
reply->new_low = low;
|
||||
reply->new_high = high;
|
||||
}
|
||||
|
||||
/* truncate (or extend) a file */
|
||||
|
@ -561,7 +561,7 @@ DECL_HANDLER(get_file_info)
|
|||
|
||||
if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
|
||||
{
|
||||
obj->ops->get_file_info( obj, req );
|
||||
obj->ops->get_file_info( obj, reply );
|
||||
release_object( obj );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,7 +355,6 @@ struct object *get_handle_obj( struct process *process, handle_t handle,
|
|||
if (!(entry = get_handle( process, handle ))) return NULL;
|
||||
if ((entry->access & access) != access)
|
||||
{
|
||||
fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -377,7 +376,6 @@ int get_handle_fd( struct process *process, handle_t handle, unsigned int access
|
|||
if (!(entry = get_handle( process, handle ))) return -1;
|
||||
if ((entry->access & access) != access)
|
||||
{
|
||||
fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return -1;
|
||||
}
|
||||
|
@ -459,7 +457,7 @@ handle_t open_object( const WCHAR *name, size_t len, const struct object_ops *op
|
|||
/* close a handle */
|
||||
DECL_HANDLER(close_handle)
|
||||
{
|
||||
close_handle( current->process, req->handle, &req->fd );
|
||||
close_handle( current->process, req->handle, &reply->fd );
|
||||
}
|
||||
|
||||
/* set a handle information */
|
||||
|
@ -468,8 +466,9 @@ DECL_HANDLER(set_handle_info)
|
|||
int fd = req->fd;
|
||||
|
||||
if (handle_is_global(req->handle)) fd = -1; /* no fd cache for global handles */
|
||||
req->old_flags = set_handle_info( current->process, req->handle, req->mask, req->flags, &fd );
|
||||
req->cur_fd = fd;
|
||||
reply->old_flags = set_handle_info( current->process, req->handle,
|
||||
req->mask, req->flags, &fd );
|
||||
reply->cur_fd = fd;
|
||||
}
|
||||
|
||||
/* duplicate a handle */
|
||||
|
@ -477,25 +476,25 @@ DECL_HANDLER(dup_handle)
|
|||
{
|
||||
struct process *src, *dst;
|
||||
|
||||
req->handle = 0;
|
||||
req->fd = -1;
|
||||
reply->handle = 0;
|
||||
reply->fd = -1;
|
||||
if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
|
||||
{
|
||||
if (req->options & DUP_HANDLE_MAKE_GLOBAL)
|
||||
{
|
||||
req->handle = duplicate_handle( src, req->src_handle, NULL,
|
||||
req->access, req->inherit, req->options );
|
||||
reply->handle = duplicate_handle( src, req->src_handle, NULL,
|
||||
req->access, req->inherit, req->options );
|
||||
}
|
||||
else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
|
||||
{
|
||||
req->handle = duplicate_handle( src, req->src_handle, dst,
|
||||
req->access, req->inherit, req->options );
|
||||
reply->handle = duplicate_handle( src, req->src_handle, dst,
|
||||
req->access, req->inherit, req->options );
|
||||
release_object( dst );
|
||||
}
|
||||
/* close the handle no matter what happened */
|
||||
if (req->options & DUP_HANDLE_CLOSE_SOURCE)
|
||||
{
|
||||
if (src == current->process) close_handle( src, req->src_handle, &req->fd );
|
||||
if (src == current->process) close_handle( src, req->src_handle, &reply->fd );
|
||||
else close_handle( src, req->src_handle, NULL );
|
||||
}
|
||||
release_object( src );
|
||||
|
|
|
@ -34,7 +34,7 @@ struct mapping
|
|||
};
|
||||
|
||||
static int mapping_get_fd( struct object *obj );
|
||||
static int mapping_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
static void mapping_dump( struct object *obj, int verbose );
|
||||
static void mapping_destroy( struct object *obj );
|
||||
|
||||
|
@ -263,11 +263,11 @@ static struct object *create_mapping( int size_high, int size_low, int protect,
|
|||
}
|
||||
if (!size_high && !size_low)
|
||||
{
|
||||
struct get_file_info_request req;
|
||||
struct get_file_info_reply reply;
|
||||
struct object *obj = (struct object *)mapping->file;
|
||||
obj->ops->get_file_info( obj, &req );
|
||||
size_high = req.size_high;
|
||||
size_low = ROUND_SIZE( 0, req.size_low );
|
||||
obj->ops->get_file_info( obj, &reply );
|
||||
size_high = reply.size_high;
|
||||
size_low = ROUND_SIZE( 0, reply.size_low );
|
||||
}
|
||||
else if (!grow_file( mapping->file, size_high, size_low )) goto error;
|
||||
}
|
||||
|
@ -311,14 +311,14 @@ static int mapping_get_fd( struct object *obj )
|
|||
return get_mmap_fd( mapping->file );
|
||||
}
|
||||
|
||||
static int mapping_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
struct mapping *mapping = (struct mapping *)obj;
|
||||
struct object *file = (struct object *)mapping->file;
|
||||
|
||||
assert( obj->ops == &mapping_ops );
|
||||
assert( file );
|
||||
return file->ops->get_file_info( file, req );
|
||||
return file->ops->get_file_info( file, reply );
|
||||
}
|
||||
|
||||
static void mapping_destroy( struct object *obj )
|
||||
|
@ -346,14 +346,14 @@ DECL_HANDLER(create_mapping)
|
|||
{
|
||||
struct object *obj;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((obj = create_mapping( req->size_high, req->size_low,
|
||||
req->protect, req->file_handle,
|
||||
get_req_data(req), get_req_data_size(req) )))
|
||||
get_req_data(), get_req_data_size() )))
|
||||
{
|
||||
int access = FILE_MAP_ALL_ACCESS;
|
||||
if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
|
||||
req->handle = alloc_handle( current->process, obj, access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, obj, access, req->inherit );
|
||||
release_object( obj );
|
||||
}
|
||||
}
|
||||
|
@ -361,8 +361,8 @@ DECL_HANDLER(create_mapping)
|
|||
/* open a handle to a mapping */
|
||||
DECL_HANDLER(open_mapping)
|
||||
{
|
||||
req->handle = open_object( get_req_data(req), get_req_data_size(req),
|
||||
&mapping_ops, req->access, req->inherit );
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
&mapping_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
/* get a mapping information */
|
||||
|
@ -373,17 +373,17 @@ DECL_HANDLER(get_mapping_info)
|
|||
if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
|
||||
0, &mapping_ops )))
|
||||
{
|
||||
req->size_high = mapping->size_high;
|
||||
req->size_low = mapping->size_low;
|
||||
req->protect = mapping->protect;
|
||||
req->header_size = mapping->header_size;
|
||||
req->base = mapping->base;
|
||||
req->shared_file = 0;
|
||||
req->shared_size = mapping->shared_size;
|
||||
req->drive_type = get_file_drive_type( mapping->file );
|
||||
reply->size_high = mapping->size_high;
|
||||
reply->size_low = mapping->size_low;
|
||||
reply->protect = mapping->protect;
|
||||
reply->header_size = mapping->header_size;
|
||||
reply->base = mapping->base;
|
||||
reply->shared_file = 0;
|
||||
reply->shared_size = mapping->shared_size;
|
||||
reply->drive_type = get_file_drive_type( mapping->file );
|
||||
if (mapping->shared_file)
|
||||
req->shared_file = alloc_handle( current->process, mapping->shared_file,
|
||||
GENERIC_READ|GENERIC_WRITE, 0 );
|
||||
reply->shared_file = alloc_handle( current->process, mapping->shared_file,
|
||||
GENERIC_READ|GENERIC_WRITE, 0 );
|
||||
release_object( mapping );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,10 +140,10 @@ DECL_HANDLER(create_mutex)
|
|||
{
|
||||
struct mutex *mutex;
|
||||
|
||||
req->handle = 0;
|
||||
if ((mutex = create_mutex( get_req_data(req), get_req_data_size(req), req->owned )))
|
||||
reply->handle = 0;
|
||||
if ((mutex = create_mutex( get_req_data(), get_req_data_size(), req->owned )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, mutex, MUTEX_ALL_ACCESS, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, mutex, MUTEX_ALL_ACCESS, req->inherit );
|
||||
release_object( mutex );
|
||||
}
|
||||
}
|
||||
|
@ -151,8 +151,8 @@ DECL_HANDLER(create_mutex)
|
|||
/* open a handle to a mutex */
|
||||
DECL_HANDLER(open_mutex)
|
||||
{
|
||||
req->handle = open_object( get_req_data(req), get_req_data_size(req),
|
||||
&mutex_ops, req->access, req->inherit );
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
&mutex_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
/* release a mutex */
|
||||
|
|
|
@ -86,7 +86,7 @@ static const struct object_ops named_pipe_ops =
|
|||
static void pipe_user_dump( struct object *obj, int verbose );
|
||||
static void pipe_user_destroy( struct object *obj);
|
||||
static int pipe_user_get_fd( struct object *obj );
|
||||
static int pipe_user_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
|
||||
static const struct object_ops pipe_user_ops =
|
||||
{
|
||||
|
@ -180,20 +180,20 @@ static int pipe_user_get_fd( struct object *obj )
|
|||
return user->obj.fd;
|
||||
}
|
||||
|
||||
static int pipe_user_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
req->type = FILE_TYPE_PIPE;
|
||||
req->attr = 0;
|
||||
req->access_time = 0;
|
||||
req->write_time = 0;
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
req->links = 0;
|
||||
req->index_high = 0;
|
||||
req->index_low = 0;
|
||||
req->serial = 0;
|
||||
reply->type = FILE_TYPE_PIPE;
|
||||
reply->attr = 0;
|
||||
reply->access_time = 0;
|
||||
reply->write_time = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
reply->links = 0;
|
||||
reply->index_high = 0;
|
||||
reply->index_low = 0;
|
||||
reply->serial = 0;
|
||||
}
|
||||
return FD_TYPE_DEFAULT;
|
||||
}
|
||||
|
@ -265,8 +265,8 @@ DECL_HANDLER(create_named_pipe)
|
|||
struct named_pipe *pipe;
|
||||
struct pipe_user *user;
|
||||
|
||||
req->handle = 0;
|
||||
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
||||
reply->handle = 0;
|
||||
pipe = create_named_pipe( get_req_data(), get_req_data_size() );
|
||||
if(!pipe)
|
||||
return;
|
||||
|
||||
|
@ -284,7 +284,7 @@ DECL_HANDLER(create_named_pipe)
|
|||
if(user)
|
||||
{
|
||||
user->state = ps_idle_server;
|
||||
req->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
|
||||
reply->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
|
||||
release_object( user );
|
||||
}
|
||||
|
||||
|
@ -295,8 +295,8 @@ DECL_HANDLER(open_named_pipe)
|
|||
{
|
||||
struct named_pipe *pipe;
|
||||
|
||||
req->handle = 0;
|
||||
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
||||
reply->handle = 0;
|
||||
pipe = create_named_pipe( get_req_data(), get_req_data_size() );
|
||||
if(!pipe)
|
||||
return;
|
||||
|
||||
|
@ -320,7 +320,7 @@ DECL_HANDLER(open_named_pipe)
|
|||
partner->other = user;
|
||||
user->state = ps_connected_client;
|
||||
user->other = partner;
|
||||
req->handle = alloc_handle( current->process, user, req->access, 0 );
|
||||
reply->handle = alloc_handle( current->process, user, req->access, 0 );
|
||||
release_object(user);
|
||||
}
|
||||
else
|
||||
|
@ -378,7 +378,7 @@ DECL_HANDLER(wait_named_pipe)
|
|||
{
|
||||
struct named_pipe *pipe;
|
||||
|
||||
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
||||
pipe = create_named_pipe( get_req_data(), get_req_data_size() );
|
||||
if( pipe )
|
||||
{
|
||||
/* only wait if the pipe already exists */
|
||||
|
@ -448,10 +448,10 @@ DECL_HANDLER(get_named_pipe_info)
|
|||
if(!user)
|
||||
return;
|
||||
|
||||
req->flags = user->pipe->pipemode;
|
||||
req->maxinstances = user->pipe->maxinstances;
|
||||
req->insize = user->pipe->insize;
|
||||
req->outsize = user->pipe->outsize;
|
||||
reply->flags = user->pipe->pipemode;
|
||||
reply->maxinstances = user->pipe->maxinstances;
|
||||
reply->insize = user->pipe->insize;
|
||||
reply->outsize = user->pipe->outsize;
|
||||
|
||||
release_object(user);
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ int no_flush( struct object *obj )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int no_get_file_info( struct object *obj, struct get_file_info_request *info )
|
||||
int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return FD_TYPE_INVALID;
|
||||
|
|
|
@ -47,7 +47,7 @@ struct object_ops
|
|||
/* flush the object buffers */
|
||||
int (*flush)(struct object *);
|
||||
/* get file information */
|
||||
int (*get_file_info)(struct object *,struct get_file_info_request *);
|
||||
int (*get_file_info)(struct object *,struct get_file_info_reply *);
|
||||
/* destroy on refcount == 0 */
|
||||
void (*destroy)(struct object *);
|
||||
};
|
||||
|
@ -89,7 +89,7 @@ extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
|||
extern int no_satisfied( struct object *obj, struct thread *thread );
|
||||
extern int no_get_fd( struct object *obj );
|
||||
extern int no_flush( struct object *obj );
|
||||
extern int no_get_file_info( struct object *obj, struct get_file_info_request *info );
|
||||
extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info );
|
||||
extern void no_destroy( struct object *obj );
|
||||
extern int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
|
@ -103,7 +103,7 @@ extern void dump_objects(void);
|
|||
|
||||
extern int add_select_user( struct object *obj );
|
||||
extern void remove_select_user( struct object *obj );
|
||||
extern void change_select_fd( struct object *obj, int fd );
|
||||
extern void change_select_fd( struct object *obj, int fd, int events );
|
||||
extern void set_select_events( struct object *obj, int events );
|
||||
extern int check_select_events( int fd, int events );
|
||||
extern void select_loop(void);
|
||||
|
|
|
@ -37,7 +37,7 @@ struct pipe
|
|||
static void pipe_dump( struct object *obj, int verbose );
|
||||
static int pipe_get_poll_events( struct object *obj );
|
||||
static int pipe_get_fd( struct object *obj );
|
||||
static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
static void pipe_destroy( struct object *obj );
|
||||
|
||||
static const struct object_ops pipe_ops =
|
||||
|
@ -124,20 +124,20 @@ static int pipe_get_fd( struct object *obj )
|
|||
return pipe->obj.fd;
|
||||
}
|
||||
|
||||
static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
req->type = FILE_TYPE_PIPE;
|
||||
req->attr = 0;
|
||||
req->access_time = 0;
|
||||
req->write_time = 0;
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
req->links = 0;
|
||||
req->index_high = 0;
|
||||
req->index_low = 0;
|
||||
req->serial = 0;
|
||||
reply->type = FILE_TYPE_PIPE;
|
||||
reply->attr = 0;
|
||||
reply->access_time = 0;
|
||||
reply->write_time = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
reply->links = 0;
|
||||
reply->index_high = 0;
|
||||
reply->index_low = 0;
|
||||
reply->serial = 0;
|
||||
}
|
||||
return FD_TYPE_DEFAULT;
|
||||
}
|
||||
|
@ -171,6 +171,6 @@ DECL_HANDLER(create_pipe)
|
|||
release_object( obj[0] );
|
||||
release_object( obj[1] );
|
||||
}
|
||||
req->handle_read = hread;
|
||||
req->handle_write = hwrite;
|
||||
reply->handle_read = hread;
|
||||
reply->handle_write = hwrite;
|
||||
}
|
||||
|
|
247
server/process.c
247
server/process.c
|
@ -98,7 +98,7 @@ static const struct object_ops startup_info_ops =
|
|||
|
||||
/* set the console and stdio handles for a newly created process */
|
||||
static int set_process_console( struct process *process, struct process *parent,
|
||||
struct startup_info *info, struct init_process_request *req )
|
||||
struct startup_info *info, struct init_process_reply *reply )
|
||||
{
|
||||
if (process->create_flags & CREATE_NEW_CONSOLE)
|
||||
{
|
||||
|
@ -120,35 +120,35 @@ static int set_process_console( struct process *process, struct process *parent,
|
|||
if (!info->inherit_all && !(info->start_flags & STARTF_USESTDHANDLES))
|
||||
{
|
||||
/* duplicate the handle from the parent into this process */
|
||||
req->hstdin = duplicate_handle( parent, info->hstdin, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
req->hstdout = duplicate_handle( parent, info->hstdout, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
req->hstderr = duplicate_handle( parent, info->hstderr, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
reply->hstdin = duplicate_handle( parent, info->hstdin, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
reply->hstdout = duplicate_handle( parent, info->hstdout, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
reply->hstderr = duplicate_handle( parent, info->hstderr, process,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||
}
|
||||
else
|
||||
{
|
||||
req->hstdin = info->hstdin;
|
||||
req->hstdout = info->hstdout;
|
||||
req->hstderr = info->hstderr;
|
||||
reply->hstdin = info->hstdin;
|
||||
reply->hstdout = info->hstdout;
|
||||
reply->hstderr = info->hstderr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (process->console)
|
||||
{
|
||||
req->hstdin = alloc_handle( process, process->console,
|
||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||
req->hstdout = alloc_handle( process, process->console->active,
|
||||
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||
req->hstderr = alloc_handle( process, process->console->active,
|
||||
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||
reply->hstdin = alloc_handle( process, process->console,
|
||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||
reply->hstdout = alloc_handle( process, process->console->active,
|
||||
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||
reply->hstderr = alloc_handle( process, process->console->active,
|
||||
GENERIC_READ | GENERIC_WRITE, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no parent, let the caller decide what to do */
|
||||
req->hstdin = req->hstdout = req->hstderr = 0;
|
||||
reply->hstdin = reply->hstdout = reply->hstderr = 0;
|
||||
}
|
||||
}
|
||||
/* some handles above may have been invalid; this is not an error */
|
||||
|
@ -216,7 +216,7 @@ struct thread *create_process( int fd )
|
|||
}
|
||||
|
||||
/* initialize the current process and fill in the request */
|
||||
static void init_process( int ppid, struct init_process_request *req )
|
||||
static void init_process( int ppid, struct init_process_reply *reply )
|
||||
{
|
||||
struct process *process = current->process;
|
||||
struct thread *parent_thread = get_thread_from_pid( ppid );
|
||||
|
@ -251,16 +251,16 @@ static void init_process( int ppid, struct init_process_request *req )
|
|||
if (!process->handles) return;
|
||||
|
||||
/* retrieve the main exe file */
|
||||
req->exe_file = 0;
|
||||
reply->exe_file = 0;
|
||||
if (parent && info->exe_file)
|
||||
{
|
||||
process->exe.file = (struct file *)grab_object( info->exe_file );
|
||||
if (!(req->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
|
||||
if (!(reply->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the process console */
|
||||
if (!set_process_console( process, parent, info, req )) return;
|
||||
if (!set_process_console( process, parent, info, reply )) return;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
|
@ -277,23 +277,21 @@ static void init_process( int ppid, struct init_process_request *req )
|
|||
if (info)
|
||||
{
|
||||
size_t size = strlen(info->filename);
|
||||
if (size > get_req_data_size(req)) size = get_req_data_size(req);
|
||||
req->start_flags = info->start_flags;
|
||||
req->cmd_show = info->cmd_show;
|
||||
memcpy( get_req_data(req), info->filename, size );
|
||||
set_req_data_size( req, size );
|
||||
if (size > get_reply_max_size()) size = get_reply_max_size();
|
||||
reply->start_flags = info->start_flags;
|
||||
reply->cmd_show = info->cmd_show;
|
||||
set_reply_data( info->filename, size );
|
||||
info->process = (struct process *)grab_object( process );
|
||||
info->thread = (struct thread *)grab_object( current );
|
||||
wake_up( &info->obj, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
req->start_flags = STARTF_USESTDHANDLES;
|
||||
req->cmd_show = 0;
|
||||
set_req_data_size( req, 0 );
|
||||
reply->start_flags = STARTF_USESTDHANDLES;
|
||||
reply->cmd_show = 0;
|
||||
}
|
||||
req->create_flags = process->create_flags;
|
||||
req->server_start = server_start_ticks;
|
||||
reply->create_flags = process->create_flags;
|
||||
reply->server_start = server_start_ticks;
|
||||
}
|
||||
|
||||
/* destroy a process when its refcount is 0 */
|
||||
|
@ -577,19 +575,19 @@ void kill_debugged_processes( struct thread *debugger, int exit_code )
|
|||
|
||||
|
||||
/* get all information about a process */
|
||||
static void get_process_info( struct process *process, struct get_process_info_request *req )
|
||||
static void get_process_info( struct process *process, struct get_process_info_reply *reply )
|
||||
{
|
||||
req->pid = process;
|
||||
req->debugged = (process->debugger != 0);
|
||||
req->exit_code = process->exit_code;
|
||||
req->priority = process->priority;
|
||||
req->process_affinity = process->affinity;
|
||||
req->system_affinity = 1;
|
||||
reply->pid = process;
|
||||
reply->debugged = (process->debugger != 0);
|
||||
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 */
|
||||
static void set_process_info( struct process *process,
|
||||
struct set_process_info_request *req )
|
||||
const struct set_process_info_request *req )
|
||||
{
|
||||
if (req->mask & SET_PROCESS_INFO_PRIORITY)
|
||||
process->priority = req->priority;
|
||||
|
@ -601,62 +599,56 @@ static void set_process_info( struct process *process,
|
|||
}
|
||||
|
||||
/* read data from a process memory space */
|
||||
/* len is the total size (in ints), max is the size we can actually store in the output buffer */
|
||||
/* we read the total size in all cases to check for permissions */
|
||||
static void read_process_memory( struct process *process, const int *addr,
|
||||
size_t len, size_t max, int *dest )
|
||||
/* len is the total size (in ints) */
|
||||
static int read_process_memory( struct process *process, const int *addr, size_t len, int *dest )
|
||||
{
|
||||
struct thread *thread = process->thread_list;
|
||||
|
||||
if ((unsigned int)addr % sizeof(int)) /* address must be aligned */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
assert( !((unsigned int)addr % sizeof(int)) ); /* address must be aligned */
|
||||
|
||||
if (!thread) /* process is dead */
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (suspend_for_ptrace( thread ))
|
||||
{
|
||||
while (len > 0 && max)
|
||||
while (len > 0)
|
||||
{
|
||||
if (read_thread_int( thread, addr++, dest++ ) == -1) goto done;
|
||||
max--;
|
||||
if (read_thread_int( thread, addr++, dest++ ) == -1) break;
|
||||
len--;
|
||||
}
|
||||
/* check the rest for read permission */
|
||||
if (len > 0)
|
||||
{
|
||||
int dummy, page = get_page_size() / sizeof(int);
|
||||
while (len >= page)
|
||||
{
|
||||
addr += page;
|
||||
len -= page;
|
||||
if (read_thread_int( thread, addr - 1, &dummy ) == -1) goto done;
|
||||
}
|
||||
if (len && (read_thread_int( thread, addr + len - 1, &dummy ) == -1)) goto done;
|
||||
}
|
||||
done:
|
||||
resume_thread( thread );
|
||||
}
|
||||
return !len;
|
||||
}
|
||||
|
||||
/* make sure we can write to the whole address range */
|
||||
/* len is the total size (in ints) */
|
||||
static int check_process_write_access( struct thread *thread, int *addr, size_t len )
|
||||
{
|
||||
int page = get_page_size() / sizeof(int);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (write_thread_int( thread, addr, 0, 0 ) == -1) return 0;
|
||||
if (len <= page) break;
|
||||
addr += page;
|
||||
len -= page;
|
||||
}
|
||||
return (write_thread_int( thread, addr + len - 1, 0, 0 ) != -1);
|
||||
}
|
||||
|
||||
/* write data to a process memory space */
|
||||
/* len is the total size (in ints), max is the size we can actually read from the input buffer */
|
||||
/* we check the total size for write permissions */
|
||||
static void write_process_memory( struct process *process, int *addr, size_t len,
|
||||
size_t max, unsigned int first_mask,
|
||||
unsigned int last_mask, const int *src )
|
||||
unsigned int first_mask, unsigned int last_mask, const int *src )
|
||||
{
|
||||
struct thread *thread = process->thread_list;
|
||||
|
||||
if (!len || ((unsigned int)addr % sizeof(int))) /* address must be aligned */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
assert( !((unsigned int)addr % sizeof(int) )); /* address must be aligned */
|
||||
|
||||
if (!thread) /* process is dead */
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
|
@ -664,39 +656,28 @@ static void write_process_memory( struct process *process, int *addr, size_t len
|
|||
}
|
||||
if (suspend_for_ptrace( thread ))
|
||||
{
|
||||
if (!check_process_write_access( thread, addr, len ))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
/* first word is special */
|
||||
if (len > 1)
|
||||
{
|
||||
if (write_thread_int( thread, addr++, *src++, first_mask ) == -1) goto done;
|
||||
len--;
|
||||
max--;
|
||||
}
|
||||
else last_mask &= first_mask;
|
||||
|
||||
while (len > 1 && max)
|
||||
while (len > 1)
|
||||
{
|
||||
if (write_thread_int( thread, addr++, *src++, ~0 ) == -1) goto done;
|
||||
max--;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (max)
|
||||
{
|
||||
/* last word is special too */
|
||||
if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check the rest for write permission */
|
||||
int page = get_page_size() / sizeof(int);
|
||||
while (len >= page)
|
||||
{
|
||||
addr += page;
|
||||
len -= page;
|
||||
if (write_thread_int( thread, addr - 1, 0, 0 ) == -1) goto done;
|
||||
}
|
||||
if (len && (write_thread_int( thread, addr + len - 1, 0, 0 ) == -1)) goto done;
|
||||
}
|
||||
/* last word is special too */
|
||||
if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
|
||||
|
||||
done:
|
||||
resume_thread( thread );
|
||||
}
|
||||
|
@ -747,7 +728,7 @@ struct module_snapshot *module_snap( struct process *process, int *count )
|
|||
/* create a new process */
|
||||
DECL_HANDLER(new_process)
|
||||
{
|
||||
size_t len = get_req_data_size( req );
|
||||
size_t len = get_req_data_size();
|
||||
struct startup_info *info;
|
||||
|
||||
if (current->info)
|
||||
|
@ -777,10 +758,10 @@ DECL_HANDLER(new_process)
|
|||
|
||||
if (!(info->filename = mem_alloc( len + 1 ))) goto done;
|
||||
|
||||
memcpy( info->filename, get_req_data(req), len );
|
||||
memcpy( info->filename, get_req_data(), len );
|
||||
info->filename[len] = 0;
|
||||
current->info = info;
|
||||
req->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE );
|
||||
reply->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE );
|
||||
|
||||
done:
|
||||
release_object( info );
|
||||
|
@ -791,28 +772,28 @@ DECL_HANDLER(get_new_process_info)
|
|||
{
|
||||
struct startup_info *info;
|
||||
|
||||
req->event = 0;
|
||||
reply->event = 0;
|
||||
|
||||
if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
|
||||
0, &startup_info_ops )))
|
||||
{
|
||||
req->pid = get_process_id( info->process );
|
||||
req->tid = get_thread_id( info->thread );
|
||||
req->phandle = alloc_handle( current->process, info->process,
|
||||
PROCESS_ALL_ACCESS, req->pinherit );
|
||||
req->thandle = alloc_handle( current->process, info->thread,
|
||||
THREAD_ALL_ACCESS, req->tinherit );
|
||||
reply->pid = get_process_id( info->process );
|
||||
reply->tid = get_thread_id( info->thread );
|
||||
reply->phandle = alloc_handle( current->process, info->process,
|
||||
PROCESS_ALL_ACCESS, req->pinherit );
|
||||
reply->thandle = alloc_handle( current->process, info->thread,
|
||||
THREAD_ALL_ACCESS, req->tinherit );
|
||||
if (info->process->init_event)
|
||||
req->event = alloc_handle( current->process, info->process->init_event,
|
||||
reply->event = alloc_handle( current->process, info->process->init_event,
|
||||
EVENT_ALL_ACCESS, 0 );
|
||||
release_object( info );
|
||||
}
|
||||
else
|
||||
{
|
||||
req->pid = 0;
|
||||
req->tid = 0;
|
||||
req->phandle = 0;
|
||||
req->thandle = 0;
|
||||
reply->pid = 0;
|
||||
reply->tid = 0;
|
||||
reply->phandle = 0;
|
||||
reply->thandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,7 +806,7 @@ DECL_HANDLER(init_process)
|
|||
return;
|
||||
}
|
||||
current->process->ldt_copy = req->ldt_copy;
|
||||
init_process( req->ppid, req );
|
||||
init_process( req->ppid, reply );
|
||||
}
|
||||
|
||||
/* signal the end of the process initialization */
|
||||
|
@ -852,17 +833,17 @@ DECL_HANDLER(init_process_done)
|
|||
process->init_event = NULL;
|
||||
if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
|
||||
if (current->suspend + current->process->suspend > 0) stop_thread( current );
|
||||
req->debugged = (current->process->debugger != 0);
|
||||
reply->debugged = (current->process->debugger != 0);
|
||||
}
|
||||
|
||||
/* open a handle to a process */
|
||||
DECL_HANDLER(open_process)
|
||||
{
|
||||
struct process *process = get_process_from_id( req->pid );
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if (process)
|
||||
{
|
||||
req->handle = alloc_handle( current->process, process, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, process, req->access, req->inherit );
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
@ -874,7 +855,7 @@ DECL_HANDLER(terminate_process)
|
|||
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
|
||||
{
|
||||
req->self = (current->process == process);
|
||||
reply->self = (current->process == process);
|
||||
kill_process( process, current, req->exit_code );
|
||||
release_object( process );
|
||||
}
|
||||
|
@ -887,7 +868,7 @@ DECL_HANDLER(get_process_info)
|
|||
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
|
||||
{
|
||||
get_process_info( process, req );
|
||||
get_process_info( process, reply );
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
@ -908,13 +889,28 @@ DECL_HANDLER(set_process_info)
|
|||
DECL_HANDLER(read_process_memory)
|
||||
{
|
||||
struct process *process;
|
||||
size_t len = get_reply_max_size();
|
||||
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_VM_READ )))
|
||||
if (!(process = get_process_from_handle( req->handle, PROCESS_VM_READ ))) return;
|
||||
|
||||
if (len)
|
||||
{
|
||||
size_t maxlen = get_req_data_size(req) / sizeof(int);
|
||||
read_process_memory( process, req->addr, req->len, maxlen, get_req_data(req) );
|
||||
release_object( process );
|
||||
unsigned int start_offset = (unsigned int)req->addr % sizeof(int);
|
||||
unsigned int nb_ints = (len + start_offset + sizeof(int) - 1) / sizeof(int);
|
||||
const int *start = (int *)((char *)req->addr - start_offset);
|
||||
int *buffer = mem_alloc( nb_ints * sizeof(int) );
|
||||
if (buffer)
|
||||
{
|
||||
if (read_process_memory( process, start, nb_ints, buffer ))
|
||||
{
|
||||
/* move start of requested data to start of buffer */
|
||||
if (start_offset) memmove( buffer, (char *)buffer + start_offset, len );
|
||||
set_reply_data_ptr( buffer, len );
|
||||
}
|
||||
else len = 0;
|
||||
}
|
||||
}
|
||||
release_object( process );
|
||||
}
|
||||
|
||||
/* write data to a process address space */
|
||||
|
@ -924,9 +920,14 @@ DECL_HANDLER(write_process_memory)
|
|||
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_VM_WRITE )))
|
||||
{
|
||||
size_t maxlen = get_req_data_size(req) / sizeof(int);
|
||||
write_process_memory( process, req->addr, req->len, maxlen,
|
||||
req->first_mask, req->last_mask, get_req_data(req) );
|
||||
size_t len = get_req_data_size();
|
||||
if ((len % sizeof(int)) || ((unsigned int)req->addr % sizeof(int)))
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
else
|
||||
{
|
||||
if (len) write_process_memory( process, req->addr, len / sizeof(int),
|
||||
req->first_mask, req->last_mask, get_req_data() );
|
||||
}
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
@ -964,12 +965,12 @@ DECL_HANDLER(wait_input_idle)
|
|||
{
|
||||
struct process *process;
|
||||
|
||||
req->event = 0;
|
||||
reply->event = 0;
|
||||
if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
|
||||
{
|
||||
if (process->idle_event && process != current->process && process->queue != current->queue)
|
||||
req->event = alloc_handle( current->process, process->idle_event,
|
||||
EVENT_ALL_ACCESS, 0 );
|
||||
reply->event = alloc_handle( current->process, process->idle_event,
|
||||
EVENT_ALL_ACCESS, 0 );
|
||||
release_object( process );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,15 @@
|
|||
|
||||
struct request_header
|
||||
{
|
||||
int req; /* request code */
|
||||
unsigned short var_offset; /* offset of the variable part of the request */
|
||||
unsigned short var_size; /* size of the variable part of the request */
|
||||
unsigned int error; /* error result */
|
||||
int req; /* request code */
|
||||
size_t request_size; /* request variable part size */
|
||||
size_t reply_size; /* reply variable part maximum size */
|
||||
};
|
||||
|
||||
struct reply_header
|
||||
{
|
||||
unsigned int error; /* error result */
|
||||
unsigned short var_offset; /* offset of the variable part of the request */
|
||||
unsigned short var_size; /* size of the variable part of the request */
|
||||
unsigned int error; /* error result */
|
||||
size_t reply_size; /* reply variable part size */
|
||||
};
|
||||
|
||||
/* placeholder structure for the maximum allowed request size */
|
||||
|
@ -150,6 +148,13 @@ typedef struct
|
|||
int bottom;
|
||||
} rectangle_t;
|
||||
|
||||
/* structure for console char/attribute info */
|
||||
typedef struct
|
||||
{
|
||||
WCHAR ch;
|
||||
unsigned short attr;
|
||||
} char_info_t;
|
||||
|
||||
/****************************************************************/
|
||||
/* Request declarations */
|
||||
|
||||
|
@ -244,15 +249,6 @@ typedef struct
|
|||
@END
|
||||
|
||||
|
||||
/* Set the shared buffer for a thread */
|
||||
@REQ(set_thread_buffer)
|
||||
int fd; /* fd to mmap as shared buffer */
|
||||
@REPLY
|
||||
unsigned int offset; /* offset of buffer in file */
|
||||
unsigned int size; /* size of buffer */
|
||||
@END
|
||||
|
||||
|
||||
/* Terminate a process */
|
||||
@REQ(terminate_process)
|
||||
handle_t handle; /* process handle to terminate */
|
||||
|
@ -819,6 +815,7 @@ struct console_renderer_event
|
|||
handle_t handle; /* handle to console input, or 0 for process' console */
|
||||
int index; /* index to get line from */
|
||||
@REPLY
|
||||
int total; /* total length of line in Unicode chars */
|
||||
VARARG(line,unicode_str); /* line to add */
|
||||
@END
|
||||
|
||||
|
@ -900,32 +897,50 @@ struct console_renderer_event
|
|||
|
||||
/* write data (chars and/or attributes) in a screen buffer */
|
||||
@REQ(write_console_output)
|
||||
handle_t handle; /* handle to the console input */
|
||||
int mode; /* 0 for text, 1, for attributes, 2 for both */
|
||||
/* bit3 (4) set if uniform pattern in data */
|
||||
short int x; /* position where to start writing */
|
||||
short int y;
|
||||
handle_t handle; /* handle to the console output */
|
||||
int x; /* position where to start writing */
|
||||
int y;
|
||||
int mode; /* char info (see below) */
|
||||
int wrap; /* wrap around at end of line? */
|
||||
VARARG(data,bytes); /* info to write */
|
||||
@REPLY
|
||||
int written; /* number of bytes actually written */
|
||||
int written; /* number of char infos actually written */
|
||||
int width; /* width of screen buffer */
|
||||
int height; /* height of screen buffer */
|
||||
@END
|
||||
#define WRITE_CONSOLE_MODE_TEXT 0x00
|
||||
#define WRITE_CONSOLE_MODE_ATTR 0x01
|
||||
#define WRITE_CONSOLE_MODE_TEXTATTR 0x02
|
||||
#define WRITE_CONSOLE_MODE_TEXTSTDATTR 0x03
|
||||
#define WRITE_CONSOLE_MODE_UNIFORM 0x04
|
||||
enum char_info_mode
|
||||
{
|
||||
CHAR_INFO_MODE_TEXT, /* characters only */
|
||||
CHAR_INFO_MODE_ATTR, /* attributes only */
|
||||
CHAR_INFO_MODE_TEXTATTR, /* both characters and attributes */
|
||||
CHAR_INFO_MODE_TEXTSTDATTR /* characters but use standard attributes */
|
||||
};
|
||||
|
||||
|
||||
/* read data (chars and/or attrubutes) from a screen buffer */
|
||||
@REQ(read_console_output)
|
||||
handle_t handle; /* handle to the console input */
|
||||
short int x; /* position (x,y) where to start reading from */
|
||||
short int y;
|
||||
short int w; /* size of area to read from (width x height) */
|
||||
short int h;
|
||||
/* fill a screen buffer with constant data (chars and/or attributes) */
|
||||
@REQ(fill_console_output)
|
||||
handle_t handle; /* handle to the console output */
|
||||
int x; /* position where to start writing */
|
||||
int y;
|
||||
int mode; /* char info mode */
|
||||
int count; /* number to write */
|
||||
int wrap; /* wrap around at end of line? */
|
||||
char_info_t data; /* data to write */
|
||||
@REPLY
|
||||
short int eff_w; /* effective width read */
|
||||
short int eff_h; /* effective height read */
|
||||
int written; /* number of char infos actually written */
|
||||
@END
|
||||
|
||||
|
||||
/* read data (chars and/or attributes) from a screen buffer */
|
||||
@REQ(read_console_output)
|
||||
handle_t handle; /* handle to the console output */
|
||||
int x; /* position (x,y) where to start reading */
|
||||
int y;
|
||||
int mode; /* char info mode */
|
||||
int wrap; /* wrap around at end of line? */
|
||||
@REPLY
|
||||
int width; /* width of screen buffer */
|
||||
int height; /* height of screen buffer */
|
||||
VARARG(data,bytes);
|
||||
@END
|
||||
|
||||
|
@ -1074,8 +1089,8 @@ struct console_renderer_event
|
|||
|
||||
/* Retrieve the status of an exception event */
|
||||
@REQ(get_exception_status)
|
||||
@REPLY
|
||||
handle_t handle; /* handle to the queued event */
|
||||
@REPLY
|
||||
int status; /* event continuation status */
|
||||
VARARG(context,context); /* modified thread context */
|
||||
@END
|
||||
|
@ -1106,8 +1121,7 @@ struct console_renderer_event
|
|||
/* Read data from a process address space */
|
||||
@REQ(read_process_memory)
|
||||
handle_t handle; /* process handle */
|
||||
void* addr; /* addr to read from (must be int-aligned) */
|
||||
int len; /* number of ints to read */
|
||||
void* addr; /* addr to read from */
|
||||
@REPLY
|
||||
VARARG(data,bytes); /* result data */
|
||||
@END
|
||||
|
@ -1117,10 +1131,9 @@ struct console_renderer_event
|
|||
@REQ(write_process_memory)
|
||||
handle_t handle; /* process handle */
|
||||
void* addr; /* addr to write to (must be int-aligned) */
|
||||
int len; /* number of ints to write */
|
||||
unsigned int first_mask; /* mask for first word */
|
||||
unsigned int last_mask; /* mask for last word */
|
||||
VARARG(data,bytes); /* result data */
|
||||
VARARG(data,bytes); /* data to write */
|
||||
@END
|
||||
|
||||
|
||||
|
@ -1130,8 +1143,9 @@ struct console_renderer_event
|
|||
unsigned int access; /* desired access rights */
|
||||
unsigned int options; /* creation options */
|
||||
time_t modif; /* last modification time */
|
||||
VARARG(name,unicode_len_str); /* key name */
|
||||
VARARG(class,unicode_str); /* class name */
|
||||
size_t namelen; /* length of key name in bytes */
|
||||
VARARG(name,unicode_str,namelen); /* key name */
|
||||
VARARG(class,unicode_str); /* class name */
|
||||
@REPLY
|
||||
handle_t hkey; /* handle to the created key */
|
||||
int created; /* has it been newly created? */
|
||||
|
@ -1157,7 +1171,7 @@ struct console_renderer_event
|
|||
@REQ(enum_key)
|
||||
handle_t hkey; /* handle to registry key */
|
||||
int index; /* index of subkey (or -1 for current key) */
|
||||
int full; /* return the full info? */
|
||||
int info_class; /* requested information class */
|
||||
@REPLY
|
||||
int subkeys; /* number of subkeys */
|
||||
int max_subkey; /* longest subkey name */
|
||||
|
@ -1166,8 +1180,10 @@ struct console_renderer_event
|
|||
int max_value; /* longest value name */
|
||||
int max_data; /* longest value data */
|
||||
time_t modif; /* last modification time */
|
||||
VARARG(name,unicode_len_str); /* key name */
|
||||
VARARG(class,unicode_str); /* class name */
|
||||
size_t total; /* total length needed for full name and class */
|
||||
size_t namelen; /* length of key name in bytes */
|
||||
VARARG(name,unicode_str,namelen); /* key name */
|
||||
VARARG(class,unicode_str); /* class name */
|
||||
@END
|
||||
|
||||
|
||||
|
@ -1175,21 +1191,19 @@ struct console_renderer_event
|
|||
@REQ(set_key_value)
|
||||
handle_t hkey; /* handle to registry key */
|
||||
int type; /* value type */
|
||||
unsigned int total; /* total value len */
|
||||
unsigned int offset; /* offset for setting data */
|
||||
VARARG(name,unicode_len_str); /* value name */
|
||||
VARARG(data,bytes); /* value data */
|
||||
size_t namelen; /* length of value name in bytes */
|
||||
VARARG(name,unicode_str,namelen); /* value name */
|
||||
VARARG(data,bytes); /* value data */
|
||||
@END
|
||||
|
||||
|
||||
/* Retrieve the value of a registry key */
|
||||
@REQ(get_key_value)
|
||||
handle_t hkey; /* handle to registry key */
|
||||
unsigned int offset; /* offset for getting data */
|
||||
VARARG(name,unicode_len_str); /* value name */
|
||||
VARARG(name,unicode_str); /* value name */
|
||||
@REPLY
|
||||
int type; /* value type */
|
||||
int len; /* value data len */
|
||||
size_t total; /* total length needed for data */
|
||||
VARARG(data,bytes); /* value data */
|
||||
@END
|
||||
|
||||
|
@ -1198,12 +1212,13 @@ struct console_renderer_event
|
|||
@REQ(enum_key_value)
|
||||
handle_t hkey; /* handle to registry key */
|
||||
int index; /* value index */
|
||||
unsigned int offset; /* offset for getting data */
|
||||
int info_class; /* requested information class */
|
||||
@REPLY
|
||||
int type; /* value type */
|
||||
int len; /* value data len */
|
||||
VARARG(name,unicode_len_str); /* value name */
|
||||
VARARG(data,bytes); /* value data */
|
||||
size_t total; /* total length needed for full name and data */
|
||||
size_t namelen; /* length of value name in bytes */
|
||||
VARARG(name,unicode_str,namelen); /* value name */
|
||||
VARARG(data,bytes); /* value data */
|
||||
@END
|
||||
|
||||
|
||||
|
@ -1429,6 +1444,7 @@ enum message_type
|
|||
int y; /* y position */
|
||||
unsigned int time; /* message time */
|
||||
unsigned int info; /* extra info */
|
||||
size_t total; /* total size of extra data */
|
||||
VARARG(data,bytes); /* message data for sent messages */
|
||||
@END
|
||||
#define GET_MSG_REMOVE 1 /* remove the message */
|
||||
|
@ -1765,5 +1781,6 @@ enum message_type
|
|||
@REQ(get_window_properties)
|
||||
user_handle_t window; /* handle to the window */
|
||||
@REPLY
|
||||
int total; /* total number of properties */
|
||||
VARARG(props,properties); /* list of properties */
|
||||
@END
|
||||
|
|
144
server/queue.c
144
server/queue.c
|
@ -330,10 +330,29 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue
|
|||
}
|
||||
|
||||
/* receive a message, removing it from the sent queue */
|
||||
static void receive_message( struct msg_queue *queue, struct message *msg )
|
||||
static void receive_message( struct msg_queue *queue, struct message *msg,
|
||||
struct get_message_reply *reply )
|
||||
{
|
||||
struct message_result *result = msg->result;
|
||||
|
||||
reply->total = msg->data_size;
|
||||
if (msg->data_size > get_reply_max_size())
|
||||
{
|
||||
set_error( STATUS_BUFFER_OVERFLOW );
|
||||
return;
|
||||
}
|
||||
reply->type = msg->type;
|
||||
reply->win = msg->win;
|
||||
reply->msg = msg->msg;
|
||||
reply->wparam = msg->wparam;
|
||||
reply->lparam = msg->lparam;
|
||||
reply->x = msg->x;
|
||||
reply->y = msg->y;
|
||||
reply->time = msg->time;
|
||||
reply->info = msg->info;
|
||||
|
||||
if (msg->data) set_reply_data_ptr( msg->data, msg->data_size );
|
||||
|
||||
unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
|
||||
/* put the result on the receiver result stack */
|
||||
if (result)
|
||||
|
@ -341,14 +360,13 @@ static void receive_message( struct msg_queue *queue, struct message *msg )
|
|||
result->recv_next = queue->recv_result;
|
||||
queue->recv_result = result;
|
||||
}
|
||||
if (msg->data) free( msg->data );
|
||||
free( msg );
|
||||
if (!queue->msg_list[SEND_MESSAGE].first) clear_queue_bits( queue, QS_SENDMESSAGE );
|
||||
}
|
||||
|
||||
/* set the result of the current received message */
|
||||
static void reply_message( struct msg_queue *queue, unsigned int result,
|
||||
unsigned int error, int remove, void *data, size_t len )
|
||||
unsigned int error, int remove, const void *data, size_t len )
|
||||
{
|
||||
struct message_result *res = queue->recv_result;
|
||||
|
||||
|
@ -656,8 +674,8 @@ DECL_HANDLER(get_msg_queue)
|
|||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
req->handle = 0;
|
||||
if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
|
||||
reply->handle = 0;
|
||||
if (queue) reply->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -670,8 +688,8 @@ DECL_HANDLER(set_queue_mask)
|
|||
{
|
||||
queue->wake_mask = req->wake_mask;
|
||||
queue->changed_mask = req->changed_mask;
|
||||
req->wake_bits = queue->wake_bits;
|
||||
req->changed_bits = queue->changed_bits;
|
||||
reply->wake_bits = queue->wake_bits;
|
||||
reply->changed_bits = queue->changed_bits;
|
||||
if (is_signaled( queue ))
|
||||
{
|
||||
/* if skip wait is set, do what would have been done in the subsequent wait */
|
||||
|
@ -688,11 +706,11 @@ DECL_HANDLER(get_queue_status)
|
|||
struct msg_queue *queue = current->queue;
|
||||
if (queue)
|
||||
{
|
||||
req->wake_bits = queue->wake_bits;
|
||||
req->changed_bits = queue->changed_bits;
|
||||
reply->wake_bits = queue->wake_bits;
|
||||
reply->changed_bits = queue->changed_bits;
|
||||
if (req->clear) queue->changed_bits = 0;
|
||||
}
|
||||
else req->wake_bits = req->changed_bits = 0;
|
||||
else reply->wake_bits = reply->changed_bits = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -731,8 +749,8 @@ DECL_HANDLER(send_message)
|
|||
switch(msg->type)
|
||||
{
|
||||
case MSG_OTHER_PROCESS:
|
||||
msg->data_size = get_req_data_size(req);
|
||||
if (msg->data_size && !(msg->data = memdup( get_req_data(req), msg->data_size )))
|
||||
msg->data_size = get_req_data_size();
|
||||
if (msg->data_size && !(msg->data = memdup( get_req_data(), msg->data_size )))
|
||||
{
|
||||
free( msg );
|
||||
break;
|
||||
|
@ -779,31 +797,26 @@ DECL_HANDLER(send_message)
|
|||
release_object( thread );
|
||||
}
|
||||
|
||||
/* store a message contents into the request buffer; helper for get_message */
|
||||
inline static void put_req_message( struct get_message_request *req, const struct message *msg )
|
||||
{
|
||||
int len = min( get_req_data_size(req), msg->data_size );
|
||||
|
||||
req->type = msg->type;
|
||||
req->win = msg->win;
|
||||
req->msg = msg->msg;
|
||||
req->wparam = msg->wparam;
|
||||
req->lparam = msg->lparam;
|
||||
req->x = msg->x;
|
||||
req->y = msg->y;
|
||||
req->time = msg->time;
|
||||
req->info = msg->info;
|
||||
if (len) memcpy( get_req_data(req), msg->data, len );
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* return a message to the application, removing it from the queue if needed */
|
||||
static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
|
||||
static void return_message_to_app( struct msg_queue *queue, int flags,
|
||||
struct get_message_reply *reply,
|
||||
struct message *msg, enum message_kind kind )
|
||||
{
|
||||
put_req_message( req, msg );
|
||||
assert( !msg->data_size ); /* posted messages can't have data */
|
||||
|
||||
reply->type = msg->type;
|
||||
reply->win = msg->win;
|
||||
reply->msg = msg->msg;
|
||||
reply->wparam = msg->wparam;
|
||||
reply->lparam = msg->lparam;
|
||||
reply->x = msg->x;
|
||||
reply->y = msg->y;
|
||||
reply->time = msg->time;
|
||||
reply->info = msg->info;
|
||||
reply->total = 0;
|
||||
|
||||
/* raw messages always get removed */
|
||||
if ((msg->type == MSG_HARDWARE_RAW) || (req->flags & GET_MSG_REMOVE))
|
||||
if ((msg->type == MSG_HARDWARE_RAW) || (flags & GET_MSG_REMOVE))
|
||||
{
|
||||
queue->last_msg = NULL;
|
||||
remove_queue_message( queue, msg, kind );
|
||||
|
@ -843,20 +856,14 @@ DECL_HANDLER(get_message)
|
|||
struct msg_queue *queue = get_current_queue();
|
||||
user_handle_t get_win = get_user_full_handle( req->get_win );
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
set_req_data_size( req, 0 );
|
||||
return;
|
||||
}
|
||||
if (!queue) return;
|
||||
|
||||
/* first check for sent messages */
|
||||
if ((msg = queue->msg_list[SEND_MESSAGE].first))
|
||||
{
|
||||
put_req_message( req, msg );
|
||||
receive_message( queue, msg );
|
||||
receive_message( queue, msg, reply );
|
||||
return;
|
||||
}
|
||||
set_req_data_size( req, 0 ); /* only sent messages can have data */
|
||||
if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
|
||||
|
||||
/* if requested, remove the last returned but not yet removed message */
|
||||
|
@ -871,7 +878,7 @@ DECL_HANDLER(get_message)
|
|||
if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win,
|
||||
req->get_first, req->get_last )))
|
||||
{
|
||||
return_message_to_app( queue, req, msg, POST_MESSAGE );
|
||||
return_message_to_app( queue, req->flags, reply, msg, POST_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -879,30 +886,30 @@ DECL_HANDLER(get_message)
|
|||
if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win,
|
||||
req->get_first, req->get_last )))
|
||||
{
|
||||
return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
|
||||
return_message_to_app( queue, req->flags, reply, msg, COOKED_HW_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
/* then check for any raw hardware message */
|
||||
if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
|
||||
{
|
||||
return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
|
||||
return_message_to_app( queue, req->flags, reply, msg, RAW_HW_MESSAGE );
|
||||
return;
|
||||
}
|
||||
|
||||
/* now check for WM_PAINT */
|
||||
if (queue->paint_count &&
|
||||
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last) &&
|
||||
(req->win = find_window_to_repaint( get_win, current )))
|
||||
(reply->win = find_window_to_repaint( get_win, current )))
|
||||
{
|
||||
req->type = MSG_POSTED;
|
||||
req->msg = WM_PAINT;
|
||||
req->wparam = 0;
|
||||
req->lparam = 0;
|
||||
req->x = 0;
|
||||
req->y = 0;
|
||||
req->time = get_tick_count();
|
||||
req->info = 0;
|
||||
reply->type = MSG_POSTED;
|
||||
reply->msg = WM_PAINT;
|
||||
reply->wparam = 0;
|
||||
reply->lparam = 0;
|
||||
reply->x = 0;
|
||||
reply->y = 0;
|
||||
reply->time = get_tick_count();
|
||||
reply->info = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -910,15 +917,15 @@ DECL_HANDLER(get_message)
|
|||
if ((timer = find_expired_timer( queue, get_win, req->get_first,
|
||||
req->get_last, (req->flags & GET_MSG_REMOVE) )))
|
||||
{
|
||||
req->type = MSG_POSTED;
|
||||
req->win = timer->win;
|
||||
req->msg = timer->msg;
|
||||
req->wparam = timer->id;
|
||||
req->lparam = timer->lparam;
|
||||
req->x = 0;
|
||||
req->y = 0;
|
||||
req->time = get_tick_count();
|
||||
req->info = 0;
|
||||
reply->type = MSG_POSTED;
|
||||
reply->win = timer->win;
|
||||
reply->msg = timer->msg;
|
||||
reply->wparam = timer->id;
|
||||
reply->lparam = timer->lparam;
|
||||
reply->x = 0;
|
||||
reply->y = 0;
|
||||
reply->time = get_tick_count();
|
||||
reply->info = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -932,7 +939,7 @@ DECL_HANDLER(reply_message)
|
|||
{
|
||||
if (current->queue && current->queue->recv_result)
|
||||
reply_message( current->queue, req->result, 0, req->remove,
|
||||
get_req_data(req), get_req_data_size(req) );
|
||||
get_req_data(), get_req_data_size() );
|
||||
else
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
|
@ -942,26 +949,24 @@ DECL_HANDLER(reply_message)
|
|||
DECL_HANDLER(get_message_reply)
|
||||
{
|
||||
struct msg_queue *queue = current->queue;
|
||||
size_t data_len = 0;
|
||||
|
||||
if (queue)
|
||||
{
|
||||
struct message_result *result = queue->send_result;
|
||||
|
||||
set_error( STATUS_PENDING );
|
||||
req->result = 0;
|
||||
reply->result = 0;
|
||||
|
||||
if (result && (result->replied || req->cancel))
|
||||
{
|
||||
if (result->replied)
|
||||
{
|
||||
req->result = result->result;
|
||||
reply->result = result->result;
|
||||
set_error( result->error );
|
||||
if (result->data)
|
||||
{
|
||||
data_len = min( result->data_size, get_req_data_size(req) );
|
||||
memcpy( get_req_data(req), result->data, data_len );
|
||||
free( result->data );
|
||||
size_t data_len = min( result->data_size, get_reply_max_size() );
|
||||
set_reply_data_ptr( result->data, data_len );
|
||||
result->data = NULL;
|
||||
result->data_size = 0;
|
||||
}
|
||||
|
@ -974,7 +979,6 @@ DECL_HANDLER(get_message_reply)
|
|||
}
|
||||
}
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
set_req_data_size( req, data_len );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
#include "winnt.h" /* registry definitions */
|
||||
|
||||
#include "ntddk.h"
|
||||
|
||||
/* a registry key */
|
||||
struct key
|
||||
|
@ -285,7 +285,7 @@ static void key_destroy( struct object *obj )
|
|||
}
|
||||
}
|
||||
|
||||
/* duplicate a key path from the request buffer */
|
||||
/* duplicate a key path */
|
||||
/* returns a pointer to a static buffer, so only useable once per request */
|
||||
static WCHAR *copy_path( const WCHAR *path, size_t len, int skip_root )
|
||||
{
|
||||
|
@ -303,17 +303,17 @@ static WCHAR *copy_path( const WCHAR *path, size_t len, int skip_root )
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/* copy a path from the request buffer, in cases where the length is stored in front of the path */
|
||||
static WCHAR *copy_req_path( void *req, size_t *len, int skip_root )
|
||||
/* copy a path from the request buffer */
|
||||
static WCHAR *copy_req_path( size_t len, int skip_root )
|
||||
{
|
||||
const WCHAR *name_ptr = get_req_data(req);
|
||||
if ((*len = sizeof(WCHAR) + *name_ptr++) > get_req_data_size(req))
|
||||
const WCHAR *name_ptr = get_req_data();
|
||||
if (len > get_req_data_size())
|
||||
{
|
||||
fatal_protocol_error( current, "copy_req_path: invalid length %d/%d\n",
|
||||
*len, get_req_data_size(req) );
|
||||
len, get_req_data_size() );
|
||||
return NULL;
|
||||
}
|
||||
return copy_path( name_ptr, *len - sizeof(WCHAR), skip_root );
|
||||
return copy_path( name_ptr, len, skip_root );
|
||||
}
|
||||
|
||||
/* return the next token in a given path */
|
||||
|
@ -564,26 +564,39 @@ static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
|
|||
}
|
||||
|
||||
/* query information about a key or a subkey */
|
||||
static size_t enum_key( struct key *key, int index, struct enum_key_request *req )
|
||||
static void enum_key( struct key *key, int index, int info_class, struct enum_key_reply *reply )
|
||||
{
|
||||
int i;
|
||||
size_t len, namelen, classlen;
|
||||
int max_subkey = 0, max_class = 0;
|
||||
int max_value = 0, max_data = 0;
|
||||
WCHAR *data = get_req_data(req);
|
||||
WCHAR *data;
|
||||
|
||||
if (index != -1) /* -1 means use the specified key directly */
|
||||
{
|
||||
if ((index < 0) || (index > key->last_subkey))
|
||||
{
|
||||
set_error( STATUS_NO_MORE_ENTRIES );
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
key = key->subkeys[index];
|
||||
}
|
||||
|
||||
if (req->full)
|
||||
namelen = strlenW(key->name) * sizeof(WCHAR);
|
||||
classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
|
||||
|
||||
switch(info_class)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
classlen = 0; /* only return the name */
|
||||
/* fall through */
|
||||
case KeyNodeInformation:
|
||||
reply->max_subkey = 0;
|
||||
reply->max_class = 0;
|
||||
reply->max_value = 0;
|
||||
reply->max_data = 0;
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
for (i = 0; i <= key->last_subkey; i++)
|
||||
{
|
||||
struct key *subkey = key->subkeys[i];
|
||||
|
@ -600,43 +613,37 @@ static size_t enum_key( struct key *key, int index, struct enum_key_request *req
|
|||
len = key->values[i].len;
|
||||
if (len > max_data) max_data = len;
|
||||
}
|
||||
req->max_subkey = max_subkey;
|
||||
req->max_class = max_class;
|
||||
req->max_value = max_value;
|
||||
req->max_data = max_data;
|
||||
reply->max_subkey = max_subkey;
|
||||
reply->max_class = max_class;
|
||||
reply->max_value = max_value;
|
||||
reply->max_data = max_data;
|
||||
namelen = 0; /* only return the class */
|
||||
break;
|
||||
default:
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
else
|
||||
reply->subkeys = key->last_subkey + 1;
|
||||
reply->values = key->last_value + 1;
|
||||
reply->modif = key->modif;
|
||||
reply->total = namelen + classlen;
|
||||
|
||||
len = min( reply->total, get_reply_max_size() );
|
||||
if (len && (data = set_reply_data_size( len )))
|
||||
{
|
||||
req->max_subkey = 0;
|
||||
req->max_class = 0;
|
||||
req->max_value = 0;
|
||||
req->max_data = 0;
|
||||
if (len > namelen)
|
||||
{
|
||||
reply->namelen = namelen;
|
||||
memcpy( data, key->name, namelen );
|
||||
memcpy( (char *)data + namelen, key->class, len - namelen );
|
||||
}
|
||||
else
|
||||
{
|
||||
reply->namelen = len;
|
||||
memcpy( data, key->name, len );
|
||||
}
|
||||
}
|
||||
req->subkeys = key->last_subkey + 1;
|
||||
req->values = key->last_value + 1;
|
||||
req->modif = key->modif;
|
||||
|
||||
namelen = strlenW(key->name) * sizeof(WCHAR);
|
||||
classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
|
||||
|
||||
len = namelen + classlen + sizeof(WCHAR);
|
||||
if (len > get_req_data_size(req))
|
||||
{
|
||||
len = get_req_data_size(req);
|
||||
if (len < sizeof(WCHAR)) return 0;
|
||||
}
|
||||
|
||||
*data++ = namelen;
|
||||
len -= sizeof(WCHAR);
|
||||
if (len > namelen)
|
||||
{
|
||||
memcpy( data, key->name, namelen );
|
||||
memcpy( (char *)data + namelen, key->class, min(classlen,len-namelen) );
|
||||
}
|
||||
else memcpy( data, key->name, len );
|
||||
|
||||
if (debug_level > 1) dump_operation( key, NULL, "Enum" );
|
||||
return len + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* delete a key and its values */
|
||||
|
@ -743,43 +750,13 @@ static struct key_value *insert_value( struct key *key, const WCHAR *name )
|
|||
}
|
||||
|
||||
/* set a key value */
|
||||
static void set_value( struct key *key, WCHAR *name, int type, unsigned int total_len,
|
||||
unsigned int offset, unsigned int data_len, const void *data )
|
||||
static void set_value( struct key *key, WCHAR *name, int type, const void *data, size_t len )
|
||||
{
|
||||
struct key_value *value;
|
||||
void *ptr = NULL;
|
||||
|
||||
if (data_len + offset > total_len)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset) /* adding data to an existing value */
|
||||
{
|
||||
int index;
|
||||
if (!(value = find_value( key, name, &index )))
|
||||
{
|
||||
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
|
||||
return;
|
||||
}
|
||||
if (value->len != total_len)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
memcpy( (char *)value->data + offset, data, data_len );
|
||||
if (debug_level > 1) dump_operation( key, value, "Set" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* first copy the data */
|
||||
if (total_len)
|
||||
{
|
||||
if (!(ptr = mem_alloc( total_len ))) return;
|
||||
memcpy( ptr, data, data_len );
|
||||
if (data_len < total_len) memset( (char *)ptr + data_len, 0, total_len - data_len );
|
||||
}
|
||||
if (len && !(ptr = memdup( data, len ))) return;
|
||||
|
||||
if (!(value = insert_value( key, name )))
|
||||
{
|
||||
|
@ -788,30 +765,23 @@ static void set_value( struct key *key, WCHAR *name, int type, unsigned int tota
|
|||
}
|
||||
if (value->data) free( value->data ); /* already existing, free previous data */
|
||||
value->type = type;
|
||||
value->len = total_len;
|
||||
value->len = len;
|
||||
value->data = ptr;
|
||||
touch_key( key );
|
||||
if (debug_level > 1) dump_operation( key, value, "Set" );
|
||||
}
|
||||
|
||||
/* get a key value */
|
||||
static size_t get_value( struct key *key, const WCHAR *name, unsigned int offset,
|
||||
unsigned int maxlen, int *type, int *len, void *data )
|
||||
static void get_value( struct key *key, const WCHAR *name, int *type, int *len )
|
||||
{
|
||||
struct key_value *value;
|
||||
int index;
|
||||
size_t ret = 0;
|
||||
|
||||
if ((value = find_value( key, name, &index )))
|
||||
{
|
||||
*type = value->type;
|
||||
*len = value->len;
|
||||
if (value->data && offset < value->len)
|
||||
{
|
||||
if (maxlen > value->len - offset) maxlen = value->len - offset;
|
||||
memcpy( data, (char *)value->data + offset, maxlen );
|
||||
ret = maxlen;
|
||||
}
|
||||
if (value->data) set_reply_data( value->data, min( value->len, get_reply_max_size() ));
|
||||
if (debug_level > 1) dump_operation( key, value, "Get" );
|
||||
}
|
||||
else
|
||||
|
@ -819,54 +789,57 @@ static size_t get_value( struct key *key, const WCHAR *name, unsigned int offset
|
|||
*type = -1;
|
||||
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enumerate a key value */
|
||||
static size_t enum_value( struct key *key, int i, unsigned int offset,
|
||||
unsigned int maxlen, int *type, int *len, void *data )
|
||||
static void enum_value( struct key *key, int i, int info_class, struct enum_key_value_reply *reply )
|
||||
{
|
||||
struct key_value *value;
|
||||
size_t ret = 0;
|
||||
|
||||
if (i < 0 || i > key->last_value) set_error( STATUS_NO_MORE_ENTRIES );
|
||||
else
|
||||
{
|
||||
WCHAR *name_ptr = data;
|
||||
void *data;
|
||||
size_t namelen, maxlen;
|
||||
|
||||
value = &key->values[i];
|
||||
*type = value->type;
|
||||
*len = value->len;
|
||||
reply->type = value->type;
|
||||
namelen = strlenW( value->name ) * sizeof(WCHAR);
|
||||
|
||||
if (maxlen >= sizeof(WCHAR))
|
||||
switch(info_class)
|
||||
{
|
||||
size_t name_len = 0;
|
||||
case KeyValueBasicInformation:
|
||||
reply->total = namelen;
|
||||
break;
|
||||
case KeyValueFullInformation:
|
||||
reply->total = namelen + value->len;
|
||||
break;
|
||||
case KeyValuePartialInformation:
|
||||
reply->total = value->len;
|
||||
namelen = 0;
|
||||
break;
|
||||
default:
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy the name only the first time (offset==0),
|
||||
* otherwise store an empty name in the buffer
|
||||
*/
|
||||
maxlen -= sizeof(WCHAR);
|
||||
ret += sizeof(WCHAR);
|
||||
if (!offset)
|
||||
maxlen = min( reply->total, get_reply_max_size() );
|
||||
if (maxlen && ((data = set_reply_data_size( maxlen ))))
|
||||
{
|
||||
if (maxlen > namelen)
|
||||
{
|
||||
name_len = strlenW( value->name ) * sizeof(WCHAR);
|
||||
if (name_len > maxlen) name_len = maxlen;
|
||||
reply->namelen = namelen;
|
||||
memcpy( data, value->name, namelen );
|
||||
memcpy( (char *)data + namelen, value->data, maxlen - namelen );
|
||||
}
|
||||
*name_ptr++ = name_len;
|
||||
memcpy( name_ptr, value->name, name_len );
|
||||
maxlen -= name_len;
|
||||
ret += name_len;
|
||||
data = (char *)name_ptr + name_len;
|
||||
|
||||
if (value->data && offset < value->len)
|
||||
else
|
||||
{
|
||||
if (maxlen > value->len - offset) maxlen = value->len - offset;
|
||||
memcpy( data, (char *)value->data + offset, maxlen );
|
||||
ret += maxlen;
|
||||
reply->namelen = maxlen;
|
||||
memcpy( data, value->name, maxlen );
|
||||
}
|
||||
}
|
||||
if (debug_level > 1) dump_operation( key, value, "Enum" );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* delete a value */
|
||||
|
@ -1585,31 +1558,30 @@ DECL_HANDLER(create_key)
|
|||
struct key *key = NULL, *parent;
|
||||
unsigned int access = req->access;
|
||||
WCHAR *name, *class;
|
||||
size_t len;
|
||||
|
||||
if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */
|
||||
req->hkey = 0;
|
||||
if (!(name = copy_req_path( req, &len, !req->parent ))) return;
|
||||
reply->hkey = 0;
|
||||
if (!(name = copy_req_path( req->namelen, !req->parent ))) return;
|
||||
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
|
||||
{
|
||||
if (len == get_req_data_size(req)) /* no class specified */
|
||||
if (req->namelen == get_req_data_size()) /* no class specified */
|
||||
{
|
||||
key = create_key( parent, name, NULL, req->options, req->modif, &req->created );
|
||||
key = create_key( parent, name, NULL, req->options, req->modif, &reply->created );
|
||||
}
|
||||
else
|
||||
{
|
||||
const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data(req) + len);
|
||||
const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data() + req->namelen);
|
||||
|
||||
if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len )))
|
||||
if ((class = req_strdupW( req, class_ptr, get_req_data_size() - req->namelen )))
|
||||
{
|
||||
key = create_key( parent, name, class, req->options,
|
||||
req->modif, &req->created );
|
||||
req->modif, &reply->created );
|
||||
free( class );
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
{
|
||||
req->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
reply->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
release_object( key );
|
||||
}
|
||||
release_object( parent );
|
||||
|
@ -1623,13 +1595,13 @@ DECL_HANDLER(open_key)
|
|||
unsigned int access = req->access;
|
||||
|
||||
if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */
|
||||
req->hkey = 0;
|
||||
reply->hkey = 0;
|
||||
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
|
||||
{
|
||||
WCHAR *name = copy_path( get_req_data(req), get_req_data_size(req), !req->parent );
|
||||
WCHAR *name = copy_path( get_req_data(), get_req_data_size(), !req->parent );
|
||||
if (name && (key = open_key( parent, name )))
|
||||
{
|
||||
req->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
reply->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
release_object( key );
|
||||
}
|
||||
release_object( parent );
|
||||
|
@ -1652,15 +1624,13 @@ DECL_HANDLER(delete_key)
|
|||
DECL_HANDLER(enum_key)
|
||||
{
|
||||
struct key *key;
|
||||
size_t len = 0;
|
||||
|
||||
if ((key = get_hkey_obj( req->hkey,
|
||||
req->index == -1 ? KEY_QUERY_VALUE : KEY_ENUMERATE_SUB_KEYS )))
|
||||
{
|
||||
len = enum_key( key, req->index, req );
|
||||
enum_key( key, req->index, req->info_class, reply );
|
||||
release_object( key );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* set a value of a registry key */
|
||||
|
@ -1668,15 +1638,14 @@ DECL_HANDLER(set_key_value)
|
|||
{
|
||||
struct key *key;
|
||||
WCHAR *name;
|
||||
size_t len;
|
||||
|
||||
if (!(name = copy_req_path( req, &len, 0 ))) return;
|
||||
if (!(name = copy_req_path( req->namelen, 0 ))) return;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
|
||||
{
|
||||
size_t datalen = get_req_data_size(req) - len;
|
||||
const char *data = (char *)get_req_data(req) + len;
|
||||
size_t datalen = get_req_data_size() - req->namelen;
|
||||
const char *data = (char *)get_req_data() + req->namelen;
|
||||
|
||||
set_value( key, name, req->type, req->total, req->offset, datalen, data );
|
||||
set_value( key, name, req->type, data, datalen );
|
||||
release_object( key );
|
||||
}
|
||||
}
|
||||
|
@ -1686,33 +1655,26 @@ DECL_HANDLER(get_key_value)
|
|||
{
|
||||
struct key *key;
|
||||
WCHAR *name;
|
||||
size_t len = 0, tmp;
|
||||
|
||||
req->len = 0;
|
||||
if (!(name = copy_req_path( req, &tmp, 0 ))) return;
|
||||
reply->total = 0;
|
||||
if (!(name = copy_path( get_req_data(), get_req_data_size(), 0 ))) return;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
|
||||
{
|
||||
len = get_value( key, name, req->offset, get_req_data_size(req),
|
||||
&req->type, &req->len, get_req_data(req) );
|
||||
get_value( key, name, &reply->type, &reply->total );
|
||||
release_object( key );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* enumerate the value of a registry key */
|
||||
DECL_HANDLER(enum_key_value)
|
||||
{
|
||||
struct key *key;
|
||||
size_t len = 0;
|
||||
|
||||
req->len = 0;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
|
||||
{
|
||||
len = enum_value( key, req->index, req->offset, get_req_data_size(req),
|
||||
&req->type, &req->len, get_req_data(req) );
|
||||
enum_value( key, req->index, req->info_class, reply );
|
||||
release_object( key );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* delete a value of a registry key */
|
||||
|
@ -1723,7 +1685,7 @@ DECL_HANDLER(delete_key_value)
|
|||
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
|
||||
{
|
||||
if ((name = req_strdupW( req, get_req_data(req), get_req_data_size(req) )))
|
||||
if ((name = req_strdupW( req, get_req_data(), get_req_data_size() )))
|
||||
{
|
||||
delete_value( key, name );
|
||||
free( name );
|
||||
|
@ -1786,7 +1748,7 @@ DECL_HANDLER(save_registry_atexit)
|
|||
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS )))
|
||||
{
|
||||
register_branch_for_saving( key, get_req_data(req), get_req_data_size(req) );
|
||||
register_branch_for_saving( key, get_req_data(), get_req_data_size() );
|
||||
release_object( key );
|
||||
}
|
||||
}
|
||||
|
|
156
server/request.c
156
server/request.c
|
@ -142,31 +142,105 @@ void fatal_perror( const char *err, ... )
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/* call a request handler */
|
||||
static inline void call_req_handler( struct thread *thread, union generic_request *request )
|
||||
/* allocate the reply data */
|
||||
void *set_reply_data_size( size_t size )
|
||||
{
|
||||
enum request req = request->header.req;
|
||||
assert( size <= get_reply_max_size() );
|
||||
if (size && !(current->reply_data = mem_alloc( size ))) size = 0;
|
||||
current->reply_size = size;
|
||||
return current->reply_data;
|
||||
}
|
||||
|
||||
current = thread;
|
||||
clear_error();
|
||||
/* write the remaining part of the reply */
|
||||
void write_reply( struct thread *thread )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (debug_level) trace_request( thread, request );
|
||||
|
||||
if (request->header.var_size)
|
||||
if ((ret = write( thread->reply_fd,
|
||||
(char *)thread->reply_data + thread->reply_size - thread->reply_towrite,
|
||||
thread->reply_towrite )) >= 0)
|
||||
{
|
||||
if ((unsigned int)request->header.var_offset +
|
||||
request->header.var_size > MAX_REQUEST_LENGTH)
|
||||
if (!(thread->reply_towrite -= ret))
|
||||
{
|
||||
fatal_protocol_error( current, "bad request offset/size %d/%d\n",
|
||||
request->header.var_offset, request->header.var_size );
|
||||
free( thread->reply_data );
|
||||
thread->reply_data = NULL;
|
||||
/* sent everything, can go back to waiting for requests */
|
||||
change_select_fd( &thread->obj, thread->request_fd, POLLIN );
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (errno == EPIPE)
|
||||
kill_thread( thread, 0 ); /* normal death */
|
||||
else if (errno != EWOULDBLOCK && errno != EAGAIN)
|
||||
fatal_protocol_perror( thread, "reply write" );
|
||||
}
|
||||
|
||||
/* send a reply to the current thread */
|
||||
static void send_reply( union generic_reply *reply )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!current->reply_size)
|
||||
{
|
||||
if ((ret = write( current->reply_fd, reply, sizeof(*reply) )) != sizeof(*reply)) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct iovec vec[2];
|
||||
|
||||
vec[0].iov_base = reply;
|
||||
vec[0].iov_len = sizeof(*reply);
|
||||
vec[1].iov_base = current->reply_data;
|
||||
vec[1].iov_len = current->reply_size;
|
||||
|
||||
if ((ret = writev( current->reply_fd, vec, 2 )) < sizeof(*reply)) goto error;
|
||||
|
||||
if ((current->reply_towrite = current->reply_size - (ret - sizeof(*reply))))
|
||||
{
|
||||
/* couldn't write it all, wait for POLLOUT */
|
||||
change_select_fd( ¤t->obj, current->reply_fd, POLLOUT );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (current->reply_data)
|
||||
{
|
||||
free( current->reply_data );
|
||||
current->reply_data = NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
if (ret >= 0)
|
||||
fatal_protocol_error( current, "partial write %d\n", ret );
|
||||
else if (errno == EPIPE)
|
||||
kill_thread( current, 0 ); /* normal death */
|
||||
else
|
||||
fatal_protocol_perror( current, "reply write" );
|
||||
}
|
||||
|
||||
/* call a request handler */
|
||||
static void call_req_handler( struct thread *thread )
|
||||
{
|
||||
union generic_reply reply;
|
||||
enum request req = thread->req.request_header.req;
|
||||
|
||||
current = thread;
|
||||
current->reply_size = 0;
|
||||
clear_error();
|
||||
memset( &reply, 0, sizeof(reply) );
|
||||
|
||||
if (debug_level) trace_request();
|
||||
|
||||
if (req < REQ_NB_REQUESTS)
|
||||
{
|
||||
req_handlers[req]( request );
|
||||
if (current) send_reply( current, request );
|
||||
req_handlers[req]( ¤t->req, &reply );
|
||||
if (current)
|
||||
{
|
||||
reply.reply_header.error = current->error;
|
||||
reply.reply_header.reply_size = current->reply_size;
|
||||
if (debug_level) trace_reply( req, &reply );
|
||||
send_reply( &reply );
|
||||
}
|
||||
current = NULL;
|
||||
return;
|
||||
}
|
||||
|
@ -176,14 +250,39 @@ static inline void call_req_handler( struct thread *thread, union generic_reques
|
|||
/* read a request from a thread */
|
||||
void read_request( struct thread *thread )
|
||||
{
|
||||
union generic_request req;
|
||||
int ret;
|
||||
|
||||
if ((ret = read( thread->obj.fd, &req, sizeof(req) )) == sizeof(req))
|
||||
if (!thread->req_toread) /* no pending request */
|
||||
{
|
||||
call_req_handler( thread, &req );
|
||||
return;
|
||||
if ((ret = read( thread->obj.fd, &thread->req,
|
||||
sizeof(thread->req) )) != sizeof(thread->req)) goto error;
|
||||
if (!(thread->req_toread = thread->req.request_header.request_size))
|
||||
{
|
||||
/* no data, handle request at once */
|
||||
call_req_handler( thread );
|
||||
return;
|
||||
}
|
||||
if (!(thread->req_data = malloc( thread->req_toread )))
|
||||
fatal_protocol_error( thread, "no memory for %d bytes request\n", thread->req_toread );
|
||||
}
|
||||
|
||||
/* read the variable sized data */
|
||||
for (;;)
|
||||
{
|
||||
ret = read( thread->obj.fd, ((char *)thread->req_data +
|
||||
thread->req.request_header.request_size - thread->req_toread),
|
||||
thread->req_toread );
|
||||
if (ret <= 0) break;
|
||||
if (!(thread->req_toread -= ret))
|
||||
{
|
||||
call_req_handler( thread );
|
||||
free( thread->req_data );
|
||||
thread->req_data = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
if (!ret) /* closed pipe */
|
||||
kill_thread( thread, 0 );
|
||||
else if (ret > 0)
|
||||
|
@ -192,26 +291,6 @@ void read_request( struct thread *thread )
|
|||
fatal_protocol_perror( thread, "read" );
|
||||
}
|
||||
|
||||
/* send a reply to a thread */
|
||||
void send_reply( struct thread *thread, union generic_request *request )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (debug_level) trace_reply( thread, request );
|
||||
|
||||
request->header.error = thread->error;
|
||||
|
||||
if ((ret = write( thread->reply_fd, request, sizeof(*request) )) != sizeof(*request))
|
||||
{
|
||||
if (ret >= 0)
|
||||
fatal_protocol_error( thread, "partial write %d\n", ret );
|
||||
else if (errno == EPIPE)
|
||||
kill_thread( thread, 0 ); /* normal death */
|
||||
else
|
||||
fatal_protocol_perror( thread, "reply write" );
|
||||
}
|
||||
}
|
||||
|
||||
/* receive a file descriptor on the process socket */
|
||||
int receive_fd( struct process *process )
|
||||
{
|
||||
|
@ -439,6 +518,7 @@ void open_master_socket(void)
|
|||
|
||||
/* make sure no request is larger than the maximum size */
|
||||
assert( sizeof(union generic_request) == sizeof(struct request_max_size) );
|
||||
assert( sizeof(union generic_reply) == sizeof(struct request_max_size) );
|
||||
|
||||
create_server_dir();
|
||||
if ((fd = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef __WINE_SERVER_REQUEST_H
|
||||
#define __WINE_SERVER_REQUEST_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "wine/server_protocol.h"
|
||||
|
||||
|
@ -14,7 +16,8 @@
|
|||
#define MAX_REQUEST_LENGTH 8192
|
||||
|
||||
/* request handler definition */
|
||||
#define DECL_HANDLER(name) void req_##name( struct name##_request *req )
|
||||
#define DECL_HANDLER(name) \
|
||||
void req_##name( const struct name##_request *req, struct name##_reply *reply )
|
||||
|
||||
/* request functions */
|
||||
|
||||
|
@ -33,36 +36,54 @@ extern void fatal_perror( const char *err, ... );
|
|||
#endif
|
||||
|
||||
extern const char *get_config_dir(void);
|
||||
extern void *set_reply_data_size( size_t size );
|
||||
extern int receive_fd( struct process *process );
|
||||
extern int send_client_fd( struct process *process, int fd, handle_t handle );
|
||||
extern void read_request( struct thread *thread );
|
||||
extern void send_reply( struct thread *thread, union generic_request *request );
|
||||
extern void write_reply( struct thread *thread );
|
||||
extern unsigned int get_tick_count(void);
|
||||
extern void open_master_socket(void);
|
||||
extern void close_master_socket(void);
|
||||
extern void lock_master_socket( int locked );
|
||||
|
||||
extern void trace_request( struct thread *thread, const union generic_request *request );
|
||||
extern void trace_reply( struct thread *thread, const union generic_request *request );
|
||||
extern void trace_request(void);
|
||||
extern void trace_reply( enum request req, const union generic_reply *reply );
|
||||
|
||||
/* get the request vararg data */
|
||||
inline static void *get_req_data( const void *req )
|
||||
inline static const void *get_req_data(void)
|
||||
{
|
||||
return (char *)current->buffer + ((struct request_header *)req)->var_offset;
|
||||
return current->req_data;
|
||||
}
|
||||
|
||||
/* get the request vararg size */
|
||||
inline static size_t get_req_data_size( const void *req )
|
||||
inline static size_t get_req_data_size(void)
|
||||
{
|
||||
return ((struct request_header *)req)->var_size;
|
||||
return current->req.request_header.request_size;
|
||||
}
|
||||
|
||||
/* set the request vararg size */
|
||||
inline static void set_req_data_size( const void *req, size_t size )
|
||||
/* get the reply maximum vararg size */
|
||||
inline static size_t get_reply_max_size(void)
|
||||
{
|
||||
((struct request_header *)req)->var_size = size;
|
||||
return current->req.request_header.reply_size;
|
||||
}
|
||||
|
||||
/* allocate and fill the reply data */
|
||||
inline static void *set_reply_data( const void *data, size_t size )
|
||||
{
|
||||
void *ret = set_reply_data_size( size );
|
||||
if (ret) memcpy( ret, data, size );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set the reply data pointer directly (will be freed by request code) */
|
||||
inline static void set_reply_data_ptr( void *data, size_t size )
|
||||
{
|
||||
assert( size <= get_reply_max_size() );
|
||||
current->reply_size = size;
|
||||
current->reply_data = data;
|
||||
}
|
||||
|
||||
|
||||
/* Everything below this line is generated automatically by tools/make_requests */
|
||||
/* ### make_requests begin ### */
|
||||
|
||||
|
@ -73,7 +94,6 @@ DECL_HANDLER(boot_done);
|
|||
DECL_HANDLER(init_process);
|
||||
DECL_HANDLER(init_process_done);
|
||||
DECL_HANDLER(init_thread);
|
||||
DECL_HANDLER(set_thread_buffer);
|
||||
DECL_HANDLER(terminate_process);
|
||||
DECL_HANDLER(terminate_thread);
|
||||
DECL_HANDLER(get_process_info);
|
||||
|
@ -132,6 +152,7 @@ DECL_HANDLER(get_console_output_info);
|
|||
DECL_HANDLER(write_console_input);
|
||||
DECL_HANDLER(read_console_input);
|
||||
DECL_HANDLER(write_console_output);
|
||||
DECL_HANDLER(fill_console_output);
|
||||
DECL_HANDLER(read_console_output);
|
||||
DECL_HANDLER(move_console_output);
|
||||
DECL_HANDLER(create_change_notification);
|
||||
|
@ -217,7 +238,7 @@ DECL_HANDLER(get_window_properties);
|
|||
|
||||
#ifdef WANT_REQUEST_HANDLERS
|
||||
|
||||
typedef void (*req_handler)( void *req );
|
||||
typedef void (*req_handler)( const void *req, void *reply );
|
||||
static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||
{
|
||||
(req_handler)req_new_process,
|
||||
|
@ -227,7 +248,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_init_process,
|
||||
(req_handler)req_init_process_done,
|
||||
(req_handler)req_init_thread,
|
||||
(req_handler)req_set_thread_buffer,
|
||||
(req_handler)req_terminate_process,
|
||||
(req_handler)req_terminate_thread,
|
||||
(req_handler)req_get_process_info,
|
||||
|
@ -286,6 +306,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_write_console_input,
|
||||
(req_handler)req_read_console_input,
|
||||
(req_handler)req_write_console_output,
|
||||
(req_handler)req_fill_console_output,
|
||||
(req_handler)req_read_console_output,
|
||||
(req_handler)req_move_console_output,
|
||||
(req_handler)req_create_change_notification,
|
||||
|
|
|
@ -97,13 +97,13 @@ void remove_select_user( struct object *obj )
|
|||
active_users--;
|
||||
}
|
||||
|
||||
/* change the fd of an object (the old fd is closed) */
|
||||
void change_select_fd( struct object *obj, int fd )
|
||||
/* change the fd and events of an object */
|
||||
void change_select_fd( struct object *obj, int fd, int events )
|
||||
{
|
||||
int user = obj->select;
|
||||
assert( poll_users[user] == obj );
|
||||
pollfd[user].fd = fd;
|
||||
close( obj->fd );
|
||||
pollfd[user].events = events;
|
||||
obj->fd = fd;
|
||||
}
|
||||
|
||||
|
|
|
@ -123,11 +123,11 @@ DECL_HANDLER(create_semaphore)
|
|||
{
|
||||
struct semaphore *sem;
|
||||
|
||||
req->handle = 0;
|
||||
if ((sem = create_semaphore( get_req_data(req), get_req_data_size(req),
|
||||
reply->handle = 0;
|
||||
if ((sem = create_semaphore( get_req_data(), get_req_data_size(),
|
||||
req->initial, req->max )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
|
||||
release_object( sem );
|
||||
}
|
||||
}
|
||||
|
@ -135,12 +135,12 @@ DECL_HANDLER(create_semaphore)
|
|||
/* open a handle to a semaphore */
|
||||
DECL_HANDLER(open_semaphore)
|
||||
{
|
||||
req->handle = open_object( get_req_data(req), get_req_data_size(req),
|
||||
&semaphore_ops, req->access, req->inherit );
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
&semaphore_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
/* release a semaphore */
|
||||
DECL_HANDLER(release_semaphore)
|
||||
{
|
||||
req->prev_count = release_semaphore( req->handle, req->count );
|
||||
reply->prev_count = release_semaphore( req->handle, req->count );
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
static void serial_dump( struct object *obj, int verbose );
|
||||
static int serial_get_fd( struct object *obj );
|
||||
static int serial_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int serial_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
static int serial_get_poll_events( struct object *obj );
|
||||
|
||||
struct serial
|
||||
|
@ -165,23 +165,23 @@ static int serial_get_fd( struct object *obj )
|
|||
return serial->obj.fd;
|
||||
}
|
||||
|
||||
static int serial_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int serial_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
struct serial *serial = (struct serial *) obj;
|
||||
assert( obj->ops == &serial_ops );
|
||||
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
req->type = FILE_TYPE_CHAR;
|
||||
req->attr = 0;
|
||||
req->access_time = 0;
|
||||
req->write_time = 0;
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
req->links = 0;
|
||||
req->index_high = 0;
|
||||
req->index_low = 0;
|
||||
req->serial = 0;
|
||||
reply->type = FILE_TYPE_CHAR;
|
||||
reply->attr = 0;
|
||||
reply->access_time = 0;
|
||||
reply->write_time = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
reply->links = 0;
|
||||
reply->index_high = 0;
|
||||
reply->index_low = 0;
|
||||
reply->serial = 0;
|
||||
}
|
||||
|
||||
if(serial->attrib & FILE_FLAG_OVERLAPPED)
|
||||
|
@ -215,10 +215,10 @@ DECL_HANDLER(create_serial)
|
|||
{
|
||||
struct serial *serial;
|
||||
|
||||
req->handle = 0;
|
||||
if ((serial = create_serial( get_req_data(req), get_req_data_size(req), req->access, req->attributes )))
|
||||
reply->handle = 0;
|
||||
if ((serial = create_serial( get_req_data(), get_req_data_size(), req->access, req->attributes )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, serial, req->access, req->inherit );
|
||||
release_object( serial );
|
||||
}
|
||||
}
|
||||
|
@ -230,17 +230,17 @@ DECL_HANDLER(get_serial_info)
|
|||
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
/* timeouts */
|
||||
req->readinterval = serial->readinterval;
|
||||
req->readconst = serial->readconst;
|
||||
req->readmult = serial->readmult;
|
||||
req->writeconst = serial->writeconst;
|
||||
req->writemult = serial->writemult;
|
||||
reply->readinterval = serial->readinterval;
|
||||
reply->readconst = serial->readconst;
|
||||
reply->readmult = serial->readmult;
|
||||
reply->writeconst = serial->writeconst;
|
||||
reply->writemult = serial->writemult;
|
||||
|
||||
/* event mask */
|
||||
req->eventmask = serial->eventmask;
|
||||
reply->eventmask = serial->eventmask;
|
||||
|
||||
/* comm port error status */
|
||||
req->commerror = serial->commerror;
|
||||
reply->commerror = serial->commerror;
|
||||
|
||||
release_object( serial );
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ static struct snapshot *create_snapshot( void *pid, int flags )
|
|||
}
|
||||
|
||||
/* get the next process in the snapshot */
|
||||
static int snapshot_next_process( struct snapshot *snapshot, struct next_process_request *req )
|
||||
static int snapshot_next_process( struct snapshot *snapshot, struct next_process_reply *reply )
|
||||
{
|
||||
struct process_snapshot *ptr;
|
||||
|
||||
|
@ -103,22 +103,21 @@ static int snapshot_next_process( struct snapshot *snapshot, struct next_process
|
|||
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
|
||||
return 0;
|
||||
}
|
||||
if (req->reset) snapshot->process_pos = 0;
|
||||
else if (snapshot->process_pos >= snapshot->process_count)
|
||||
if (snapshot->process_pos >= snapshot->process_count)
|
||||
{
|
||||
set_error( STATUS_NO_MORE_FILES );
|
||||
return 0;
|
||||
}
|
||||
ptr = &snapshot->processes[snapshot->process_pos++];
|
||||
req->count = ptr->count;
|
||||
req->pid = get_process_id( ptr->process );
|
||||
req->threads = ptr->threads;
|
||||
req->priority = ptr->priority;
|
||||
reply->count = ptr->count;
|
||||
reply->pid = get_process_id( ptr->process );
|
||||
reply->threads = ptr->threads;
|
||||
reply->priority = ptr->priority;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get the next thread in the snapshot */
|
||||
static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_request *req )
|
||||
static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_reply *reply )
|
||||
{
|
||||
struct thread_snapshot *ptr;
|
||||
|
||||
|
@ -127,23 +126,22 @@ static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_r
|
|||
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
|
||||
return 0;
|
||||
}
|
||||
if (req->reset) snapshot->thread_pos = 0;
|
||||
else if (snapshot->thread_pos >= snapshot->thread_count)
|
||||
if (snapshot->thread_pos >= snapshot->thread_count)
|
||||
{
|
||||
set_error( STATUS_NO_MORE_FILES );
|
||||
return 0;
|
||||
}
|
||||
ptr = &snapshot->threads[snapshot->thread_pos++];
|
||||
req->count = ptr->count;
|
||||
req->pid = get_process_id( ptr->thread->process );
|
||||
req->tid = get_thread_id( ptr->thread );
|
||||
req->base_pri = ptr->priority;
|
||||
req->delta_pri = 0; /* FIXME */
|
||||
reply->count = ptr->count;
|
||||
reply->pid = get_process_id( ptr->thread->process );
|
||||
reply->tid = get_thread_id( ptr->thread );
|
||||
reply->base_pri = ptr->priority;
|
||||
reply->delta_pri = 0; /* FIXME */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get the next module in the snapshot */
|
||||
static int snapshot_next_module( struct snapshot *snapshot, struct next_module_request *req )
|
||||
static int snapshot_next_module( struct snapshot *snapshot, struct next_module_reply *reply )
|
||||
{
|
||||
struct module_snapshot *ptr;
|
||||
|
||||
|
@ -152,15 +150,14 @@ static int snapshot_next_module( struct snapshot *snapshot, struct next_module_r
|
|||
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
|
||||
return 0;
|
||||
}
|
||||
if (req->reset) snapshot->module_pos = 0;
|
||||
else if (snapshot->module_pos >= snapshot->module_count)
|
||||
if (snapshot->module_pos >= snapshot->module_count)
|
||||
{
|
||||
set_error( STATUS_NO_MORE_FILES );
|
||||
return 0;
|
||||
}
|
||||
ptr = &snapshot->modules[snapshot->module_pos++];
|
||||
req->pid = get_process_id( snapshot->process );
|
||||
req->base = ptr->base;
|
||||
reply->pid = get_process_id( snapshot->process );
|
||||
reply->base = ptr->base;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -198,10 +195,10 @@ DECL_HANDLER(create_snapshot)
|
|||
{
|
||||
struct snapshot *snapshot;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((snapshot = create_snapshot( req->pid, req->flags )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
|
||||
release_object( snapshot );
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +211,8 @@ DECL_HANDLER(next_process)
|
|||
if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
|
||||
0, &snapshot_ops )))
|
||||
{
|
||||
snapshot_next_process( snapshot, req );
|
||||
if (req->reset) snapshot->process_pos = 0;
|
||||
snapshot_next_process( snapshot, reply );
|
||||
release_object( snapshot );
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +225,8 @@ DECL_HANDLER(next_thread)
|
|||
if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
|
||||
0, &snapshot_ops )))
|
||||
{
|
||||
snapshot_next_thread( snapshot, req );
|
||||
if (req->reset) snapshot->thread_pos = 0;
|
||||
snapshot_next_thread( snapshot, reply );
|
||||
release_object( snapshot );
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +239,8 @@ DECL_HANDLER(next_module)
|
|||
if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
|
||||
0, &snapshot_ops )))
|
||||
{
|
||||
snapshot_next_module( snapshot, req );
|
||||
if (req->reset) snapshot->module_pos = 0;
|
||||
snapshot_next_module( snapshot, reply );
|
||||
release_object( snapshot );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ static int sock_signaled( struct object *obj, struct thread *thread );
|
|||
static int sock_get_poll_events( struct object *obj );
|
||||
static void sock_poll_event( struct object *obj, int event );
|
||||
static int sock_get_fd( struct object *obj );
|
||||
static int sock_get_info( struct object *obj, struct get_file_info_request *req );
|
||||
static int sock_get_info( struct object *obj, struct get_file_info_reply *reply );
|
||||
static void sock_destroy( struct object *obj );
|
||||
static int sock_get_error( int err );
|
||||
static void sock_set_error(void);
|
||||
|
@ -272,20 +272,20 @@ static int sock_get_fd( struct object *obj )
|
|||
return sock->obj.fd;
|
||||
}
|
||||
|
||||
static int sock_get_info( struct object *obj, struct get_file_info_request *req )
|
||||
static int sock_get_info( struct object *obj, struct get_file_info_reply *reply )
|
||||
{
|
||||
if (req)
|
||||
if (reply)
|
||||
{
|
||||
req->type = FILE_TYPE_PIPE;
|
||||
req->attr = 0;
|
||||
req->access_time = 0;
|
||||
req->write_time = 0;
|
||||
req->size_high = 0;
|
||||
req->size_low = 0;
|
||||
req->links = 0;
|
||||
req->index_high = 0;
|
||||
req->index_low = 0;
|
||||
req->serial = 0;
|
||||
reply->type = FILE_TYPE_PIPE;
|
||||
reply->attr = 0;
|
||||
reply->access_time = 0;
|
||||
reply->write_time = 0;
|
||||
reply->size_high = 0;
|
||||
reply->size_low = 0;
|
||||
reply->links = 0;
|
||||
reply->index_high = 0;
|
||||
reply->index_low = 0;
|
||||
reply->serial = 0;
|
||||
}
|
||||
return FD_TYPE_DEFAULT;
|
||||
}
|
||||
|
@ -461,10 +461,10 @@ DECL_HANDLER(create_socket)
|
|||
{
|
||||
struct object *obj;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((obj = create_socket( req->family, req->type, req->protocol )) != NULL)
|
||||
{
|
||||
req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||
release_object( obj );
|
||||
}
|
||||
}
|
||||
|
@ -474,10 +474,10 @@ DECL_HANDLER(accept_socket)
|
|||
{
|
||||
struct object *obj;
|
||||
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if ((obj = accept_socket( req->lhandle )) != NULL)
|
||||
{
|
||||
req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
|
||||
release_object( obj );
|
||||
}
|
||||
}
|
||||
|
@ -525,34 +525,31 @@ DECL_HANDLER(set_socket_event)
|
|||
DECL_HANDLER(get_socket_event)
|
||||
{
|
||||
struct sock *sock;
|
||||
size_t size;
|
||||
|
||||
sock=(struct sock*)get_handle_obj(current->process,req->handle,GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
|
||||
if (!sock)
|
||||
{
|
||||
req->mask = 0;
|
||||
req->pmask = 0;
|
||||
req->state = 0;
|
||||
set_error(WSAENOTSOCK);
|
||||
return;
|
||||
reply->mask = 0;
|
||||
reply->pmask = 0;
|
||||
reply->state = 0;
|
||||
set_error( WSAENOTSOCK );
|
||||
return;
|
||||
}
|
||||
req->mask = sock->mask;
|
||||
req->pmask = sock->pmask;
|
||||
req->state = sock->state;
|
||||
size = min( get_req_data_size(req), sizeof(sock->errors) );
|
||||
memcpy( get_req_data(req), sock->errors, size );
|
||||
set_req_data_size( req, size );
|
||||
reply->mask = sock->mask;
|
||||
reply->pmask = sock->pmask;
|
||||
reply->state = sock->state;
|
||||
set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) ));
|
||||
|
||||
if (req->service)
|
||||
{
|
||||
if (req->s_event)
|
||||
handle_t s_event = req->s_event;
|
||||
if (s_event)
|
||||
{
|
||||
struct event *sevent = get_event_obj(current->process, req->s_event, 0);
|
||||
if (sevent == sock->event)
|
||||
req->s_event = 0;
|
||||
if (sevent == sock->event) s_event = 0;
|
||||
release_object( sevent );
|
||||
}
|
||||
if (!req->s_event)
|
||||
if (!s_event)
|
||||
{
|
||||
if (req->c_event)
|
||||
{
|
||||
|
|
119
server/thread.c
119
server/thread.c
|
@ -14,9 +14,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -104,7 +101,10 @@ inline static void init_thread_structure( struct thread *thread )
|
|||
thread->user_apc.head = NULL;
|
||||
thread->user_apc.tail = NULL;
|
||||
thread->error = 0;
|
||||
thread->request_fd = NULL;
|
||||
thread->req_data = NULL;
|
||||
thread->req_toread = 0;
|
||||
thread->reply_data = NULL;
|
||||
thread->reply_towrite = 0;
|
||||
thread->reply_fd = -1;
|
||||
thread->wait_fd = -1;
|
||||
thread->state = RUNNING;
|
||||
|
@ -115,7 +115,6 @@ inline static void init_thread_structure( struct thread *thread )
|
|||
thread->priority = THREAD_PRIORITY_NORMAL;
|
||||
thread->affinity = 1;
|
||||
thread->suspend = 0;
|
||||
thread->buffer = (void *)-1;
|
||||
|
||||
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
|
||||
thread->inflight[i].server = thread->inflight[i].client = -1;
|
||||
|
@ -131,6 +130,7 @@ struct thread *create_thread( int fd, struct process *process )
|
|||
init_thread_structure( thread );
|
||||
|
||||
thread->process = (struct process *)grab_object( process );
|
||||
thread->request_fd = fd;
|
||||
if (!current) current = thread;
|
||||
|
||||
if (!booting_thread) /* first thread ever */
|
||||
|
@ -142,7 +142,6 @@ struct thread *create_thread( int fd, struct process *process )
|
|||
if ((thread->next = first_thread) != NULL) thread->next->prev = thread;
|
||||
first_thread = thread;
|
||||
|
||||
fcntl( fd, F_SETFL, O_NONBLOCK );
|
||||
set_select_events( &thread->obj, POLLIN ); /* start listening to events */
|
||||
add_process_thread( thread->process, thread );
|
||||
return thread;
|
||||
|
@ -156,6 +155,7 @@ static void thread_poll_event( struct object *obj, int event )
|
|||
|
||||
if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
|
||||
else if (event & POLLIN) read_request( thread );
|
||||
else if (event & POLLOUT) write_reply( thread );
|
||||
}
|
||||
|
||||
/* cleanup everything that is no longer needed by a dead thread */
|
||||
|
@ -166,10 +166,11 @@ static void cleanup_thread( struct thread *thread )
|
|||
struct thread_apc *apc;
|
||||
|
||||
while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
|
||||
if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
|
||||
if (thread->req_data) free( thread->req_data );
|
||||
if (thread->reply_data) free( thread->reply_data );
|
||||
if (thread->request_fd != -1) close( thread->request_fd );
|
||||
if (thread->reply_fd != -1) close( thread->reply_fd );
|
||||
if (thread->wait_fd != -1) close( thread->wait_fd );
|
||||
if (thread->request_fd) release_object( thread->request_fd );
|
||||
if (thread->queue)
|
||||
{
|
||||
if (thread->process->queue == thread->queue)
|
||||
|
@ -189,10 +190,11 @@ static void cleanup_thread( struct thread *thread )
|
|||
thread->inflight[i].client = thread->inflight[i].server = -1;
|
||||
}
|
||||
}
|
||||
thread->buffer = (void *)-1;
|
||||
thread->req_data = NULL;
|
||||
thread->reply_data = NULL;
|
||||
thread->request_fd = -1;
|
||||
thread->reply_fd = -1;
|
||||
thread->wait_fd = -1;
|
||||
thread->request_fd = NULL;
|
||||
}
|
||||
|
||||
/* destroy a thread when its refcount is 0 */
|
||||
|
@ -255,7 +257,7 @@ struct thread *get_thread_from_pid( int pid )
|
|||
|
||||
/* set all information about a thread */
|
||||
static void set_thread_info( struct thread *thread,
|
||||
struct set_thread_info_request *req )
|
||||
const struct set_thread_info_request *req )
|
||||
{
|
||||
if (req->mask & SET_THREAD_INFO_PRIORITY)
|
||||
thread->priority = req->priority;
|
||||
|
@ -467,7 +469,8 @@ static void thread_timeout( void *ptr )
|
|||
}
|
||||
|
||||
/* select on a list of handles */
|
||||
static void select_on( int count, void *cookie, handle_t *handles, int flags, int sec, int usec )
|
||||
static void select_on( int count, void *cookie, const handle_t *handles,
|
||||
int flags, int sec, int usec )
|
||||
{
|
||||
int ret, i;
|
||||
struct object *objects[MAXIMUM_WAIT_OBJECTS];
|
||||
|
@ -700,6 +703,8 @@ void kill_thread( struct thread *thread, int violent_death )
|
|||
remove_process_thread( thread->process, thread );
|
||||
wake_up( &thread->obj, 0 );
|
||||
detach_thread( thread, violent_death ? SIGTERM : 0 );
|
||||
if (thread->request_fd == thread->obj.fd) thread->request_fd = -1;
|
||||
if (thread->reply_fd == thread->obj.fd) thread->reply_fd = -1;
|
||||
remove_select_user( &thread->obj );
|
||||
cleanup_thread( thread );
|
||||
release_object( thread );
|
||||
|
@ -746,8 +751,9 @@ DECL_HANDLER(new_thread)
|
|||
struct thread *thread;
|
||||
int request_fd = thread_get_inflight_fd( current, req->request_fd );
|
||||
|
||||
if (request_fd == -1)
|
||||
if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
|
||||
{
|
||||
if (request_fd != -1) close( request_fd );
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
return;
|
||||
}
|
||||
|
@ -755,9 +761,9 @@ DECL_HANDLER(new_thread)
|
|||
if ((thread = create_thread( request_fd, current->process )))
|
||||
{
|
||||
if (req->suspend) thread->suspend++;
|
||||
req->tid = thread;
|
||||
if ((req->handle = alloc_handle( current->process, thread,
|
||||
THREAD_ALL_ACCESS, req->inherit )))
|
||||
reply->tid = thread;
|
||||
if ((reply->handle = alloc_handle( current->process, thread,
|
||||
THREAD_ALL_ACCESS, req->inherit )))
|
||||
{
|
||||
/* thread object will be released when the thread gets killed */
|
||||
return;
|
||||
|
@ -778,7 +784,7 @@ DECL_HANDLER(init_thread)
|
|||
fatal_protocol_error( current, "init_thread: already running\n" );
|
||||
goto error;
|
||||
}
|
||||
if (reply_fd == -1)
|
||||
if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1)
|
||||
{
|
||||
fatal_protocol_error( current, "bad reply fd\n" );
|
||||
goto error;
|
||||
|
@ -798,10 +804,10 @@ DECL_HANDLER(init_thread)
|
|||
if (current->process->running_threads > 1)
|
||||
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
|
||||
|
||||
req->pid = get_process_id( current->process );
|
||||
req->tid = get_thread_id( current );
|
||||
req->boot = (current == booting_thread);
|
||||
req->version = SERVER_PROTOCOL_VERSION;
|
||||
reply->pid = get_process_id( current->process );
|
||||
reply->tid = get_thread_id( current );
|
||||
reply->boot = (current == booting_thread);
|
||||
reply->version = SERVER_PROTOCOL_VERSION;
|
||||
return;
|
||||
|
||||
error:
|
||||
|
@ -809,52 +815,21 @@ DECL_HANDLER(init_thread)
|
|||
if (wait_fd != -1) close( wait_fd );
|
||||
}
|
||||
|
||||
/* set the shared buffer for a thread */
|
||||
DECL_HANDLER(set_thread_buffer)
|
||||
{
|
||||
const unsigned int size = MAX_REQUEST_LENGTH;
|
||||
const unsigned int offset = 0;
|
||||
int fd = thread_get_inflight_fd( current, req->fd );
|
||||
|
||||
req->size = size;
|
||||
req->offset = offset;
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
static const char zero;
|
||||
|
||||
/* grow the file to the requested size */
|
||||
if (lseek( fd, size - 1, SEEK_SET ) != -1 && write( fd, &zero, 1 ) == 1)
|
||||
{
|
||||
void *buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset );
|
||||
if (buffer == (void *)-1) file_set_error();
|
||||
else
|
||||
{
|
||||
if (current->buffer != (void *)-1) munmap( current->buffer, size );
|
||||
current->buffer = buffer;
|
||||
}
|
||||
}
|
||||
else file_set_error();
|
||||
close( fd );
|
||||
}
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
}
|
||||
|
||||
/* terminate a thread */
|
||||
DECL_HANDLER(terminate_thread)
|
||||
{
|
||||
struct thread *thread;
|
||||
|
||||
req->self = 0;
|
||||
req->last = 0;
|
||||
reply->self = 0;
|
||||
reply->last = 0;
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
|
||||
{
|
||||
thread->exit_code = req->exit_code;
|
||||
if (thread != current) kill_thread( thread, 1 );
|
||||
else
|
||||
{
|
||||
req->self = 1;
|
||||
req->last = (thread->process->running_threads == 1);
|
||||
reply->self = 1;
|
||||
reply->last = (thread->process->running_threads == 1);
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
|
@ -871,10 +846,10 @@ DECL_HANDLER(get_thread_info)
|
|||
|
||||
if (thread)
|
||||
{
|
||||
req->tid = get_thread_id( thread );
|
||||
req->teb = thread->teb;
|
||||
req->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
|
||||
req->priority = thread->priority;
|
||||
reply->tid = get_thread_id( thread );
|
||||
reply->teb = thread->teb;
|
||||
reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
|
||||
reply->priority = thread->priority;
|
||||
release_object( thread );
|
||||
}
|
||||
}
|
||||
|
@ -898,7 +873,7 @@ DECL_HANDLER(suspend_thread)
|
|||
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
|
||||
{
|
||||
req->count = suspend_thread( thread, 1 );
|
||||
reply->count = suspend_thread( thread, 1 );
|
||||
release_object( thread );
|
||||
}
|
||||
}
|
||||
|
@ -910,7 +885,7 @@ DECL_HANDLER(resume_thread)
|
|||
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
|
||||
{
|
||||
req->count = resume_thread( thread );
|
||||
reply->count = resume_thread( thread );
|
||||
release_object( thread );
|
||||
}
|
||||
}
|
||||
|
@ -918,8 +893,8 @@ DECL_HANDLER(resume_thread)
|
|||
/* select on a handle list */
|
||||
DECL_HANDLER(select)
|
||||
{
|
||||
int count = get_req_data_size(req) / sizeof(int);
|
||||
select_on( count, req->cookie, get_req_data(req), req->flags, req->sec, req->usec );
|
||||
int count = get_req_data_size() / sizeof(int);
|
||||
select_on( count, req->cookie, get_req_data(), req->flags, req->sec, req->usec );
|
||||
}
|
||||
|
||||
/* queue an APC for a thread */
|
||||
|
@ -944,9 +919,8 @@ DECL_HANDLER(get_apc)
|
|||
if (!(apc = thread_dequeue_apc( current, !req->alertable )))
|
||||
{
|
||||
/* no more APCs */
|
||||
req->func = NULL;
|
||||
req->type = APC_NONE;
|
||||
set_req_data_size( req, 0 );
|
||||
reply->func = NULL;
|
||||
reply->type = APC_NONE;
|
||||
return;
|
||||
}
|
||||
/* Optimization: ignore APCs that have a NULL func; they are only used
|
||||
|
@ -956,11 +930,10 @@ DECL_HANDLER(get_apc)
|
|||
free( apc );
|
||||
}
|
||||
size = apc->nb_args * sizeof(apc->args[0]);
|
||||
if (size > get_req_data_size(req)) size = get_req_data_size(req);
|
||||
req->func = apc->func;
|
||||
req->type = apc->type;
|
||||
memcpy( get_req_data(req), apc->args, size );
|
||||
set_req_data_size( req, size );
|
||||
if (size > get_reply_max_size()) size = get_reply_max_size();
|
||||
reply->func = apc->func;
|
||||
reply->type = apc->type;
|
||||
set_reply_data( apc->args, size );
|
||||
free( apc );
|
||||
}
|
||||
|
||||
|
@ -970,7 +943,7 @@ DECL_HANDLER(get_selector_entry)
|
|||
struct thread *thread;
|
||||
if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
|
||||
{
|
||||
get_selector_entry( thread, req->entry, &req->base, &req->limit, &req->flags );
|
||||
get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
|
||||
release_object( thread );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,35 +42,40 @@ struct inflight_fd
|
|||
|
||||
struct thread
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
struct thread *next; /* system-wide thread list */
|
||||
struct thread *prev;
|
||||
struct thread *proc_next; /* per-process thread list */
|
||||
struct thread *proc_prev;
|
||||
struct process *process;
|
||||
struct mutex *mutex; /* list of currently owned mutexes */
|
||||
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
||||
struct debug_event *debug_event; /* debug event being sent to debugger */
|
||||
struct msg_queue *queue; /* message queue */
|
||||
struct startup_info*info; /* startup info for child process */
|
||||
struct thread_wait *wait; /* current wait condition if sleeping */
|
||||
struct apc_queue system_apc; /* queue of system async procedure calls */
|
||||
struct apc_queue user_apc; /* queue of user async procedure calls */
|
||||
struct inflight_fd inflight[MAX_INFLIGHT_FDS]; /* fds currently in flight */
|
||||
unsigned int error; /* current error code */
|
||||
struct object *request_fd; /* fd for receiving client requests */
|
||||
int reply_fd; /* fd to send a reply to a client */
|
||||
int wait_fd; /* fd to use to wake a sleeping client */
|
||||
enum run_state state; /* running state */
|
||||
int attached; /* is thread attached with ptrace? */
|
||||
int exit_code; /* thread exit code */
|
||||
int unix_pid; /* Unix pid of client */
|
||||
CONTEXT *context; /* current context if in an exception handler */
|
||||
void *teb; /* TEB address (in client address space) */
|
||||
int priority; /* priority level */
|
||||
int affinity; /* affinity mask */
|
||||
int suspend; /* suspend count */
|
||||
void *buffer; /* buffer for communication with the client */
|
||||
struct object obj; /* object header */
|
||||
struct thread *next; /* system-wide thread list */
|
||||
struct thread *prev;
|
||||
struct thread *proc_next; /* per-process thread list */
|
||||
struct thread *proc_prev;
|
||||
struct process *process;
|
||||
struct mutex *mutex; /* list of currently owned mutexes */
|
||||
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
||||
struct debug_event *debug_event; /* debug event being sent to debugger */
|
||||
struct msg_queue *queue; /* message queue */
|
||||
struct startup_info *info; /* startup info for child process */
|
||||
struct thread_wait *wait; /* current wait condition if sleeping */
|
||||
struct apc_queue system_apc; /* queue of system async procedure calls */
|
||||
struct apc_queue user_apc; /* queue of user async procedure calls */
|
||||
struct inflight_fd inflight[MAX_INFLIGHT_FDS]; /* fds currently in flight */
|
||||
unsigned int error; /* current error code */
|
||||
union generic_request req; /* current request */
|
||||
void *req_data; /* variable-size data for request */
|
||||
unsigned int req_toread; /* amount of data still to read in request */
|
||||
void *reply_data; /* variable-size data for reply */
|
||||
unsigned int reply_size; /* size of reply data */
|
||||
unsigned int reply_towrite; /* amount of data still to write in reply */
|
||||
int request_fd; /* fd for receiving client requests */
|
||||
int reply_fd; /* fd to send a reply to a client */
|
||||
int wait_fd; /* fd to use to wake a sleeping client */
|
||||
enum run_state state; /* running state */
|
||||
int attached; /* is thread attached with ptrace? */
|
||||
int exit_code; /* thread exit code */
|
||||
int unix_pid; /* Unix pid of client */
|
||||
CONTEXT *context; /* current context if in an exception handler */
|
||||
void *teb; /* TEB address (in client address space) */
|
||||
int priority; /* priority level */
|
||||
int affinity; /* affinity mask */
|
||||
int suspend; /* suspend count */
|
||||
};
|
||||
|
||||
struct thread_snapshot
|
||||
|
|
|
@ -174,10 +174,10 @@ DECL_HANDLER(create_timer)
|
|||
{
|
||||
struct timer *timer;
|
||||
|
||||
req->handle = 0;
|
||||
if ((timer = create_timer( get_req_data(req), get_req_data_size(req), req->manual )))
|
||||
reply->handle = 0;
|
||||
if ((timer = create_timer( get_req_data(), get_req_data_size(), req->manual )))
|
||||
{
|
||||
req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
|
||||
reply->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
|
||||
release_object( timer );
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ DECL_HANDLER(create_timer)
|
|||
/* open a handle to a timer */
|
||||
DECL_HANDLER(open_timer)
|
||||
{
|
||||
req->handle = open_object( get_req_data(req), get_req_data_size(req),
|
||||
&timer_ops, req->access, req->inherit );
|
||||
reply->handle = open_object( get_req_data(), get_req_data_size(),
|
||||
&timer_ops, req->access, req->inherit );
|
||||
}
|
||||
|
||||
/* set a waitable timer */
|
||||
|
|
547
server/trace.c
547
server/trace.c
File diff suppressed because it is too large
Load Diff
154
server/window.c
154
server/window.c
|
@ -215,23 +215,6 @@ inline static void destroy_properties( struct window *win )
|
|||
free( win->properties );
|
||||
}
|
||||
|
||||
/* enum all properties into the data array */
|
||||
static int enum_properties( struct window *win, property_data_t *data, int max )
|
||||
{
|
||||
int i, count;
|
||||
|
||||
for (i = count = 0; i < win->prop_inuse && count < max; i++)
|
||||
{
|
||||
if (win->properties[i].type == PROP_TYPE_FREE) continue;
|
||||
data->atom = win->properties[i].atom;
|
||||
data->string = (win->properties[i].type == PROP_TYPE_STRING);
|
||||
data->handle = win->properties[i].handle;
|
||||
data++;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* destroy a window */
|
||||
static void destroy_window( struct window *win )
|
||||
{
|
||||
|
@ -376,7 +359,7 @@ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *threa
|
|||
/* create a window */
|
||||
DECL_HANDLER(create_window)
|
||||
{
|
||||
req->handle = 0;
|
||||
reply->handle = 0;
|
||||
if (!req->parent) /* return desktop window */
|
||||
{
|
||||
if (!top_window)
|
||||
|
@ -384,7 +367,7 @@ DECL_HANDLER(create_window)
|
|||
if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
}
|
||||
req->handle = top_window->handle;
|
||||
reply->handle = top_window->handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -400,7 +383,7 @@ DECL_HANDLER(create_window)
|
|||
return;
|
||||
}
|
||||
if (!(win = create_window( parent, owner, req->atom ))) return;
|
||||
req->handle = win->handle;
|
||||
reply->handle = win->handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +401,7 @@ DECL_HANDLER(link_window)
|
|||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
req->full_parent = parent ? parent->handle : 0;
|
||||
reply->full_parent = parent ? parent->handle : 0;
|
||||
if (parent && req->previous)
|
||||
{
|
||||
if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
||||
|
@ -467,7 +450,7 @@ DECL_HANDLER(set_window_owner)
|
|||
return;
|
||||
}
|
||||
win->owner = owner;
|
||||
req->full_owner = owner->handle;
|
||||
reply->full_owner = owner->handle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -476,16 +459,16 @@ DECL_HANDLER(get_window_info)
|
|||
{
|
||||
struct window *win = get_window( req->handle );
|
||||
|
||||
req->full_handle = 0;
|
||||
req->tid = req->pid = 0;
|
||||
reply->full_handle = 0;
|
||||
reply->tid = reply->pid = 0;
|
||||
if (win)
|
||||
{
|
||||
req->full_handle = win->handle;
|
||||
reply->full_handle = win->handle;
|
||||
if (win->thread)
|
||||
{
|
||||
req->tid = get_thread_id( win->thread );
|
||||
req->pid = get_process_id( win->thread->process );
|
||||
req->atom = win->atom;
|
||||
reply->tid = get_thread_id( win->thread );
|
||||
reply->pid = get_process_id( win->thread->process );
|
||||
reply->atom = win->atom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,11 +479,11 @@ DECL_HANDLER(set_window_info)
|
|||
{
|
||||
struct window *win = get_window( req->handle );
|
||||
if (!win) return;
|
||||
req->old_style = win->style;
|
||||
req->old_ex_style = win->ex_style;
|
||||
req->old_id = win->id;
|
||||
req->old_instance = win->instance;
|
||||
req->old_user_data = win->user_data;
|
||||
reply->old_style = win->style;
|
||||
reply->old_ex_style = win->ex_style;
|
||||
reply->old_id = win->id;
|
||||
reply->old_instance = win->instance;
|
||||
reply->old_user_data = win->user_data;
|
||||
if (req->flags & SET_WIN_STYLE) win->style = req->style;
|
||||
if (req->flags & SET_WIN_EXSTYLE) win->ex_style = req->ex_style;
|
||||
if (req->flags & SET_WIN_ID) win->id = req->id;
|
||||
|
@ -514,16 +497,15 @@ DECL_HANDLER(get_window_parents)
|
|||
{
|
||||
struct window *ptr, *win = get_window( req->handle );
|
||||
int total = 0;
|
||||
user_handle_t *data;
|
||||
size_t len;
|
||||
|
||||
if (win) for (ptr = win->parent; ptr; ptr = ptr->parent) total++;
|
||||
|
||||
req->count = total;
|
||||
len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
|
||||
set_req_data_size( req, len );
|
||||
if (len)
|
||||
reply->count = total;
|
||||
len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
|
||||
if (len && ((data = set_reply_data_size( len ))))
|
||||
{
|
||||
user_handle_t *data = get_req_data(req);
|
||||
for (ptr = win->parent; ptr && len; ptr = ptr->parent, len -= sizeof(*data))
|
||||
*data++ = ptr->handle;
|
||||
}
|
||||
|
@ -535,6 +517,7 @@ DECL_HANDLER(get_window_children)
|
|||
{
|
||||
struct window *ptr, *parent = get_window( req->parent );
|
||||
int total = 0;
|
||||
user_handle_t *data;
|
||||
size_t len;
|
||||
|
||||
if (parent)
|
||||
|
@ -545,12 +528,10 @@ DECL_HANDLER(get_window_children)
|
|||
total++;
|
||||
}
|
||||
|
||||
req->count = total;
|
||||
len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
|
||||
set_req_data_size( req, len );
|
||||
if (len)
|
||||
reply->count = total;
|
||||
len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
|
||||
if (len && ((data = set_reply_data_size( len ))))
|
||||
{
|
||||
user_handle_t *data = get_req_data(req);
|
||||
for (ptr = parent->first_child; ptr && len; ptr = ptr->next, len -= sizeof(*data))
|
||||
{
|
||||
if (req->atom && ptr->atom != req->atom) continue;
|
||||
|
@ -571,24 +552,24 @@ DECL_HANDLER(get_window_tree)
|
|||
if (win->parent)
|
||||
{
|
||||
struct window *parent = win->parent;
|
||||
req->parent = parent->handle;
|
||||
req->owner = win->owner ? win->owner->handle : 0;
|
||||
req->next_sibling = win->next ? win->next->handle : 0;
|
||||
req->prev_sibling = win->prev ? win->prev->handle : 0;
|
||||
req->first_sibling = parent->first_child ? parent->first_child->handle : 0;
|
||||
req->last_sibling = parent->last_child ? parent->last_child->handle : 0;
|
||||
reply->parent = parent->handle;
|
||||
reply->owner = win->owner ? win->owner->handle : 0;
|
||||
reply->next_sibling = win->next ? win->next->handle : 0;
|
||||
reply->prev_sibling = win->prev ? win->prev->handle : 0;
|
||||
reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;
|
||||
reply->last_sibling = parent->last_child ? parent->last_child->handle : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
req->parent = 0;
|
||||
req->owner = 0;
|
||||
req->next_sibling = 0;
|
||||
req->prev_sibling = 0;
|
||||
req->first_sibling = 0;
|
||||
req->last_sibling = 0;
|
||||
reply->parent = 0;
|
||||
reply->owner = 0;
|
||||
reply->next_sibling = 0;
|
||||
reply->prev_sibling = 0;
|
||||
reply->first_sibling = 0;
|
||||
reply->last_sibling = 0;
|
||||
}
|
||||
req->first_child = win->first_child ? win->first_child->handle : 0;
|
||||
req->last_child = win->last_child ? win->last_child->handle : 0;
|
||||
reply->first_child = win->first_child ? win->first_child->handle : 0;
|
||||
reply->last_child = win->last_child ? win->last_child->handle : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -612,8 +593,8 @@ DECL_HANDLER(get_window_rectangles)
|
|||
|
||||
if (win)
|
||||
{
|
||||
req->window = win->window_rect;
|
||||
req->client = win->client_rect;
|
||||
reply->window = win->window_rect;
|
||||
reply->client = win->client_rect;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,15 +603,13 @@ DECL_HANDLER(get_window_rectangles)
|
|||
DECL_HANDLER(get_window_text)
|
||||
{
|
||||
struct window *win = get_window( req->handle );
|
||||
size_t len = 0;
|
||||
|
||||
if (win && win->text)
|
||||
{
|
||||
len = strlenW( win->text ) * sizeof(WCHAR);
|
||||
if (len > get_req_data_size(req)) len = get_req_data_size(req);
|
||||
memcpy( get_req_data(req), win->text, len );
|
||||
size_t len = strlenW( win->text ) * sizeof(WCHAR);
|
||||
if (len > get_reply_max_size()) len = get_reply_max_size();
|
||||
set_reply_data( win->text, len );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
|
||||
|
@ -642,11 +621,11 @@ DECL_HANDLER(set_window_text)
|
|||
if (win)
|
||||
{
|
||||
WCHAR *text = NULL;
|
||||
size_t len = get_req_data_size(req) / sizeof(WCHAR);
|
||||
size_t len = get_req_data_size() / sizeof(WCHAR);
|
||||
if (len)
|
||||
{
|
||||
if (!(text = mem_alloc( (len+1) * sizeof(WCHAR) ))) return;
|
||||
memcpy( text, get_req_data(req), len * sizeof(WCHAR) );
|
||||
memcpy( text, get_req_data(), len * sizeof(WCHAR) );
|
||||
text[len] = 0;
|
||||
}
|
||||
if (win->text) free( win->text );
|
||||
|
@ -674,14 +653,14 @@ DECL_HANDLER(get_windows_offset)
|
|||
{
|
||||
struct window *win;
|
||||
|
||||
req->x = req->y = 0;
|
||||
reply->x = reply->y = 0;
|
||||
if (req->from)
|
||||
{
|
||||
if (!(win = get_window( req->from ))) return;
|
||||
while (win)
|
||||
{
|
||||
req->x += win->client_rect.left;
|
||||
req->y += win->client_rect.top;
|
||||
reply->x += win->client_rect.left;
|
||||
reply->y += win->client_rect.top;
|
||||
win = win->parent;
|
||||
}
|
||||
}
|
||||
|
@ -690,8 +669,8 @@ DECL_HANDLER(get_windows_offset)
|
|||
if (!(win = get_window( req->to ))) return;
|
||||
while (win)
|
||||
{
|
||||
req->x -= win->client_rect.left;
|
||||
req->y -= win->client_rect.top;
|
||||
reply->x -= win->client_rect.left;
|
||||
reply->y -= win->client_rect.top;
|
||||
win = win->parent;
|
||||
}
|
||||
}
|
||||
|
@ -712,8 +691,8 @@ DECL_HANDLER(set_window_property)
|
|||
DECL_HANDLER(remove_window_property)
|
||||
{
|
||||
struct window *win = get_window( req->window );
|
||||
req->handle = 0;
|
||||
if (win) req->handle = remove_property( win, req->atom );
|
||||
reply->handle = 0;
|
||||
if (win) reply->handle = remove_property( win, req->atom );
|
||||
}
|
||||
|
||||
|
||||
|
@ -721,18 +700,35 @@ DECL_HANDLER(remove_window_property)
|
|||
DECL_HANDLER(get_window_property)
|
||||
{
|
||||
struct window *win = get_window( req->window );
|
||||
req->handle = 0;
|
||||
if (win) req->handle = get_property( win, req->atom );
|
||||
reply->handle = 0;
|
||||
if (win) reply->handle = get_property( win, req->atom );
|
||||
}
|
||||
|
||||
|
||||
/* get the list of properties of a window */
|
||||
DECL_HANDLER(get_window_properties)
|
||||
{
|
||||
int count = 0;
|
||||
property_data_t *data = get_req_data(req);
|
||||
property_data_t *data;
|
||||
int i, count, max = get_reply_max_size() / sizeof(*data);
|
||||
struct window *win = get_window( req->window );
|
||||
|
||||
if (win) count = enum_properties( win, data, get_req_data_size(req) / sizeof(*data) );
|
||||
set_req_data_size( req, count * sizeof(*data) );
|
||||
reply->total = 0;
|
||||
if (!win) return;
|
||||
|
||||
for (i = count = 0; i < win->prop_inuse; i++)
|
||||
if (win->properties[i].type != PROP_TYPE_FREE) count++;
|
||||
reply->total = count;
|
||||
|
||||
if (count > max) count = max;
|
||||
if (!count || !(data = set_reply_data_size( count * sizeof(*data) ))) return;
|
||||
|
||||
for (i = 0; i < win->prop_inuse && count; i++)
|
||||
{
|
||||
if (win->properties[i].type == PROP_TYPE_FREE) continue;
|
||||
data->atom = win->properties[i].atom;
|
||||
data->string = (win->properties[i].type == PROP_TYPE_STRING);
|
||||
data->handle = win->properties[i].handle;
|
||||
data++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
"unsigned int" => "%08x",
|
||||
"void*" => "%p",
|
||||
"time_t" => "%ld",
|
||||
"size_t" => "%d",
|
||||
"handle_t" => "%d",
|
||||
"atom_t" => "%04x",
|
||||
"user_handle_t" => "%08x",
|
||||
"rectangle_t" => "&dump_rectangle",
|
||||
"char_info_t" => "&dump_char_info",
|
||||
);
|
||||
|
||||
my @requests = ();
|
||||
|
@ -44,16 +46,24 @@ print SERVER_PROT "#define __WINE_WINE_SERVER_PROTOCOL_H\n";
|
|||
|
||||
&PARSE_REQUESTS;
|
||||
|
||||
### Build the request list
|
||||
### Build the request list and structures
|
||||
|
||||
print SERVER_PROT "\n\nenum request\n{\n";
|
||||
foreach $req (@requests) { print SERVER_PROT " REQ_$req,\n"; }
|
||||
print SERVER_PROT " REQ_NB_REQUESTS\n};\n\n";
|
||||
|
||||
print SERVER_PROT "union generic_request\n{\n";
|
||||
print SERVER_PROT " struct request_max_size max_size;\n";
|
||||
print SERVER_PROT " struct request_header header;\n";
|
||||
foreach $req (@requests) { print SERVER_PROT " struct ${req}_request $req;\n"; }
|
||||
print SERVER_PROT " struct request_header request_header;\n";
|
||||
foreach $req (@requests) { print SERVER_PROT " struct ${req}_request ${req}_request;\n"; }
|
||||
print SERVER_PROT "};\n";
|
||||
|
||||
print SERVER_PROT "union generic_reply\n{\n";
|
||||
print SERVER_PROT " struct request_max_size max_size;\n";
|
||||
print SERVER_PROT " struct reply_header reply_header;\n";
|
||||
foreach $req (@requests) { print SERVER_PROT " struct ${req}_reply ${req}_reply;\n"; }
|
||||
print SERVER_PROT "};\n\n";
|
||||
|
||||
printf SERVER_PROT "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol + 1;
|
||||
print SERVER_PROT "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n";
|
||||
close SERVER_PROT;
|
||||
|
@ -89,7 +99,7 @@ my @request_lines = ();
|
|||
|
||||
foreach $req (@requests) { push @request_lines, "DECL_HANDLER($req);\n"; }
|
||||
push @request_lines, "\n#ifdef WANT_REQUEST_HANDLERS\n\n";
|
||||
push @request_lines, "typedef void (*req_handler)( void *req );\n";
|
||||
push @request_lines, "typedef void (*req_handler)( const void *req, void *reply );\n";
|
||||
push @request_lines, "static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n";
|
||||
foreach $req (@requests)
|
||||
{
|
||||
|
@ -145,6 +155,9 @@ sub PARSE_REQUESTS
|
|||
if (/^\@REPLY/)
|
||||
{
|
||||
die "Misplaced \@REPLY" unless $state == 2;
|
||||
print SERVER_PROT "};\n";
|
||||
print SERVER_PROT "struct ${name}_reply\n{\n";
|
||||
print SERVER_PROT " struct reply_header __header;\n";
|
||||
$state++;
|
||||
next;
|
||||
}
|
||||
|
@ -154,6 +167,13 @@ sub PARSE_REQUESTS
|
|||
die "Misplaced \@END" unless ($state == 2 || $state == 3);
|
||||
print SERVER_PROT "};\n";
|
||||
|
||||
if ($state == 2) # build dummy reply struct
|
||||
{
|
||||
print SERVER_PROT "struct ${name}_reply\n{\n";
|
||||
print SERVER_PROT " struct reply_header __header;\n";
|
||||
print SERVER_PROT "};\n";
|
||||
}
|
||||
|
||||
# got a complete request
|
||||
push @requests, $name;
|
||||
&DO_DUMP_FUNC( $name, "request", @in_struct);
|
||||
|
@ -175,17 +195,23 @@ sub PARSE_REQUESTS
|
|||
next;
|
||||
}
|
||||
|
||||
if (/^\s*VARARG\((\w+),(\w+)\)/)
|
||||
if (/^\s*VARARG\((\w+),(\w+),(\w+)\)/)
|
||||
{
|
||||
$var = $1;
|
||||
$type = "&dump_varargs_" . $2;
|
||||
$type = "dump_varargs_" . $2 . "( min(cur_size,req->" . $3 . ") )";
|
||||
s!(VARARG\(.*\)\s*;)!/* $1 */!;
|
||||
}
|
||||
elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+)(\[[1]\])?;/)
|
||||
elsif (/^\s*VARARG\((\w+),(\w+)\)/)
|
||||
{
|
||||
$type = $1 . ($4 || "");
|
||||
$var = $1;
|
||||
$type = "dump_varargs_" . $2 . "( cur_size )";
|
||||
s!(VARARG\(.*\)\s*;)!/* $1 */!;
|
||||
}
|
||||
elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+);/)
|
||||
{
|
||||
$type = $1;
|
||||
$var = $3;
|
||||
die "Unrecognized type $type" unless (defined($formats{$type}) || $4);
|
||||
die "Unrecognized type $type" unless defined($formats{$type});
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -207,7 +233,7 @@ sub DO_DUMP_FUNC
|
|||
{
|
||||
my $name = shift;
|
||||
my $req = shift;
|
||||
push @trace_lines, "static void dump_${name}_$req( const struct ${name}_request *req )\n{\n";
|
||||
push @trace_lines, "static void dump_${name}_$req( const struct ${name}_$req *req )\n{\n";
|
||||
while ($#_ >= 0)
|
||||
{
|
||||
my $type = shift;
|
||||
|
@ -218,8 +244,7 @@ sub DO_DUMP_FUNC
|
|||
{
|
||||
my $func = $1;
|
||||
push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
|
||||
if ($type =~ /[1]/) { push @trace_lines, " $func( req, req->$var );\n"; }
|
||||
else { push @trace_lines, " $func( req, &req->$var );\n"; }
|
||||
push @trace_lines, " $func( &req->$var );\n";
|
||||
push @trace_lines, " fprintf( stderr, \",\" );\n" if ($#_ > 0);
|
||||
}
|
||||
else
|
||||
|
@ -232,18 +257,10 @@ sub DO_DUMP_FUNC
|
|||
}
|
||||
else # must be some varargs format
|
||||
{
|
||||
if ($type =~ /^&(.*)/)
|
||||
{
|
||||
my $func = $1;
|
||||
push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
|
||||
push @trace_lines, " cur_pos += $func( req );\n";
|
||||
push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
|
||||
push @trace_lines, " dump_varargs_${name}_${req}( req );\n";
|
||||
}
|
||||
my $func = $type;
|
||||
push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
|
||||
push @trace_lines, " $func;\n";
|
||||
push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0);
|
||||
}
|
||||
}
|
||||
push @trace_lines, "}\n\n";
|
||||
|
|
1208
win32/console.c
1208
win32/console.c
File diff suppressed because it is too large
Load Diff
|
@ -339,12 +339,12 @@ static const struct VxDInfo *DEVICE_GetInfo( HANDLE handle )
|
|||
SERVER_START_REQ( get_file_info )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!SERVER_CALL() &&
|
||||
(req->type == FILE_TYPE_UNKNOWN) &&
|
||||
(req->attr & 0x10000))
|
||||
if (!wine_server_call( req ) &&
|
||||
(reply->type == FILE_TYPE_UNKNOWN) &&
|
||||
(reply->attr & 0x10000))
|
||||
{
|
||||
for (info = VxDList; info->name; info++)
|
||||
if (info->id == LOWORD(req->attr)) break;
|
||||
if (info->id == LOWORD(reply->attr)) break;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
|
|
@ -159,29 +159,28 @@ static int send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *c
|
|||
int ret;
|
||||
HANDLE handle = 0;
|
||||
|
||||
SERVER_START_VAR_REQ( queue_exception_event, sizeof(*rec) + sizeof(*context) )
|
||||
SERVER_START_REQ( queue_exception_event )
|
||||
{
|
||||
CONTEXT *context_ptr = server_data_ptr(req);
|
||||
EXCEPTION_RECORD *rec_ptr = (EXCEPTION_RECORD *)(context_ptr + 1);
|
||||
req->first = first_chance;
|
||||
*rec_ptr = *rec;
|
||||
*context_ptr = *context;
|
||||
if (!SERVER_CALL()) handle = req->handle;
|
||||
wine_server_add_data( req, context, sizeof(*context) );
|
||||
wine_server_add_data( req, rec, sizeof(*rec) );
|
||||
if (!wine_server_call(req)) handle = reply->handle;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
if (!handle) return 0; /* no debugger present or other error */
|
||||
|
||||
/* No need to wait on the handle since the process gets suspended
|
||||
* once the event is passed to the debugger, so when we get back
|
||||
* here the event has been continued already.
|
||||
*/
|
||||
SERVER_START_VAR_REQ( get_exception_status, sizeof(*context) )
|
||||
SERVER_START_REQ( get_exception_status )
|
||||
{
|
||||
req->handle = handle;
|
||||
if (!SERVER_CALL()) *context = *(CONTEXT *)server_data_ptr(req);
|
||||
ret = req->status;
|
||||
wine_server_set_reply( req, context, sizeof(*context) );
|
||||
wine_server_call( req );
|
||||
ret = reply->status;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
NtClose( handle );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -75,18 +75,16 @@ static void DEFWND_SetTextA( HWND hwnd, LPCSTR text )
|
|||
if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
|
||||
if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
|
||||
{
|
||||
size_t len = min( REQUEST_MAX_VAR_SIZE, (count-1) * sizeof(WCHAR) );
|
||||
|
||||
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
|
||||
wndPtr->text = textW;
|
||||
MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
|
||||
SERVER_START_VAR_REQ( set_window_text, len )
|
||||
SERVER_START_REQ( set_window_text )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
memcpy( server_data_ptr(req), textW, len );
|
||||
SERVER_CALL();
|
||||
wine_server_add_data( req, textW, (count-1) * sizeof(WCHAR) );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
else
|
||||
ERR("Not enough memory for window text\n");
|
||||
|
@ -113,16 +111,14 @@ static void DEFWND_SetTextW( HWND hwnd, LPCWSTR text )
|
|||
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
|
||||
if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
|
||||
{
|
||||
size_t len = min( REQUEST_MAX_VAR_SIZE, (count-1) * sizeof(WCHAR) );
|
||||
|
||||
strcpyW( wndPtr->text, text );
|
||||
SERVER_START_VAR_REQ( set_window_text, len )
|
||||
SERVER_START_REQ( set_window_text )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
memcpy( server_data_ptr(req), wndPtr->text, len );
|
||||
SERVER_CALL();
|
||||
wine_server_add_data( req, wndPtr->text, (count-1) * sizeof(WCHAR) );
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
else
|
||||
ERR("Not enough memory for window text\n");
|
||||
|
|
|
@ -110,7 +110,7 @@ static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lPar
|
|||
req->time = time;
|
||||
req->info = extraInfo;
|
||||
req->timeout = 0;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message
|
|||
req->time = msg->time;
|
||||
req->info = extra_info;
|
||||
req->timeout = 0;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -707,7 +707,7 @@ DWORD WINAPI MsgWaitForMultipleObjectsEx( DWORD count, CONST HANDLE *pHandles,
|
|||
req->wake_mask = (flags & MWMO_INPUTAVAILABLE) ? mask : 0;
|
||||
req->changed_mask = mask;
|
||||
req->skip_wait = 0;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -751,7 +751,7 @@ DWORD WINAPI WaitForInputIdle( HANDLE hProcess, DWORD dwTimeOut )
|
|||
{
|
||||
req->handle = hProcess;
|
||||
req->timeout = dwTimeOut;
|
||||
if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
|
||||
if (!(ret = wine_server_call_err( req ))) idle_event = reply->event;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret) return WAIT_FAILED; /* error */
|
||||
|
|
|
@ -54,7 +54,7 @@ static void add_paint_count( HWND hwnd, int incr )
|
|||
{
|
||||
req->handle = hwnd;
|
||||
req->incr = incr;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
|
|
@ -348,8 +348,8 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
|
|||
{
|
||||
SERVER_START_REQ( get_msg_queue )
|
||||
{
|
||||
SERVER_CALL_ERR();
|
||||
handle = req->handle;
|
||||
wine_server_call_err( req );
|
||||
handle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!handle)
|
||||
|
@ -483,8 +483,8 @@ DWORD WINAPI GetQueueStatus( UINT flags )
|
|||
SERVER_START_REQ( get_queue_status )
|
||||
{
|
||||
req->clear = 1;
|
||||
SERVER_CALL();
|
||||
ret = MAKELONG( req->changed_bits & flags, req->wake_bits & flags );
|
||||
wine_server_call( req );
|
||||
ret = MAKELONG( reply->changed_bits & flags, reply->wake_bits & flags );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -501,8 +501,8 @@ BOOL WINAPI GetInputState(void)
|
|||
SERVER_START_REQ( get_queue_status )
|
||||
{
|
||||
req->clear = 0;
|
||||
SERVER_CALL();
|
||||
ret = req->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
|
||||
wine_server_call( req );
|
||||
ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
|
|
@ -154,7 +154,7 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
|
|||
req->id = id;
|
||||
req->rate = max( timeout, SYS_TIMER_RATE );
|
||||
req->lparam = (unsigned int)winproc;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -191,7 +191,7 @@ static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
|
|||
req->win = hwnd;
|
||||
req->msg = sys ? WM_SYSTIMER : WM_TIMER;
|
||||
req->id = id;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
|
225
windows/win.c
225
windows/win.c
|
@ -94,7 +94,7 @@ static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
|
|||
req->parent = parent;
|
||||
req->owner = owner;
|
||||
req->atom = atom;
|
||||
if ((res = !SERVER_CALL_ERR())) handle = req->handle;
|
||||
if ((res = !wine_server_call_err( req ))) handle = reply->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -131,7 +131,7 @@ static WND *free_window_handle( HWND hwnd )
|
|||
SERVER_START_REQ( destroy_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
user_handles[index] = NULL;
|
||||
else
|
||||
ptr = NULL;
|
||||
|
@ -152,26 +152,34 @@ static WND *free_window_handle( HWND hwnd )
|
|||
*/
|
||||
static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
|
||||
{
|
||||
HWND *list = NULL;
|
||||
HWND *list;
|
||||
int size = 32;
|
||||
|
||||
SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
|
||||
for (;;)
|
||||
{
|
||||
req->parent = hwnd;
|
||||
req->atom = atom;
|
||||
req->tid = (void *)tid;
|
||||
if (!SERVER_CALL())
|
||||
int count = 0;
|
||||
|
||||
if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
|
||||
|
||||
SERVER_START_REQ( get_window_children )
|
||||
{
|
||||
user_handle_t *data = server_data_ptr(req);
|
||||
int i, count = server_data_size(req) / sizeof(*data);
|
||||
if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
|
||||
{
|
||||
for (i = 0; i < count; i++) list[i] = data[i];
|
||||
list[i] = 0;
|
||||
}
|
||||
req->parent = hwnd;
|
||||
req->atom = atom;
|
||||
req->tid = (void *)tid;
|
||||
wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
|
||||
if (!wine_server_call( req )) count = reply->count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (count && count < size)
|
||||
{
|
||||
list[count] = 0;
|
||||
return list;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
if (!count) break;
|
||||
size = count + 1; /* restart with a large enough buffer */
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return list;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,19 +202,15 @@ static void send_parent_notify( HWND hwnd, UINT msg )
|
|||
*/
|
||||
static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
|
||||
{
|
||||
size_t len = (count - 1) * sizeof(WCHAR);
|
||||
len = min( len, REQUEST_MAX_VAR_SIZE );
|
||||
SERVER_START_VAR_REQ( get_window_text, len )
|
||||
size_t len = 0;
|
||||
|
||||
SERVER_START_REQ( get_window_text )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
{
|
||||
len = server_data_size(req);
|
||||
memcpy( text, server_data_ptr(req), len );
|
||||
}
|
||||
else len = 0;
|
||||
wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
|
||||
if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
SERVER_END_REQ;
|
||||
text[len / sizeof(WCHAR)] = 0;
|
||||
}
|
||||
|
||||
|
@ -300,7 +304,7 @@ HWND WIN_Handle32( HWND16 hwnd16 )
|
|||
SERVER_START_REQ( get_window_info )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
|
||||
if (!wine_server_call_err( req )) hwnd = reply->full_handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
@ -400,12 +404,12 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
|
|||
req->handle = hwnd;
|
||||
req->parent = parent;
|
||||
req->previous = hwndInsertAfter;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
if (req->full_parent && req->full_parent != wndPtr->parent)
|
||||
if (reply->full_parent && reply->full_parent != wndPtr->parent)
|
||||
{
|
||||
wndPtr->owner = 0; /* reset owner when changing parent */
|
||||
wndPtr->parent = req->full_parent;
|
||||
wndPtr->parent = reply->full_parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -434,7 +438,7 @@ void WIN_SetOwner( HWND hwnd, HWND owner )
|
|||
{
|
||||
req->handle = hwnd;
|
||||
req->owner = owner;
|
||||
if (!SERVER_CALL()) win->owner = req->full_owner;
|
||||
if (!wine_server_call( req )) win->owner = reply->full_owner;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
WIN_ReleasePtr( win );
|
||||
|
@ -469,9 +473,9 @@ LONG WIN_SetStyle( HWND hwnd, LONG style )
|
|||
req->handle = hwnd;
|
||||
req->flags = SET_WIN_STYLE;
|
||||
req->style = style;
|
||||
if ((ok = !SERVER_CALL()))
|
||||
if ((ok = !wine_server_call( req )))
|
||||
{
|
||||
ret = req->old_style;
|
||||
ret = reply->old_style;
|
||||
win->dwStyle = style;
|
||||
}
|
||||
}
|
||||
|
@ -509,9 +513,9 @@ LONG WIN_SetExStyle( HWND hwnd, LONG style )
|
|||
req->handle = hwnd;
|
||||
req->flags = SET_WIN_EXSTYLE;
|
||||
req->ex_style = style;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
ret = req->old_ex_style;
|
||||
ret = reply->old_ex_style;
|
||||
win->dwExStyle = style;
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +552,7 @@ void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClien
|
|||
req->client.top = rectClient->top;
|
||||
req->client.right = rectClient->right;
|
||||
req->client.bottom = rectClient->bottom;
|
||||
ret = !SERVER_CALL();
|
||||
ret = !wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (ret)
|
||||
|
@ -1062,7 +1066,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
req->style = wndPtr->dwStyle;
|
||||
req->ex_style = wndPtr->dwExStyle;
|
||||
req->instance = (void *)wndPtr->hInstance;
|
||||
SERVER_CALL();
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
|
@ -1821,15 +1825,15 @@ static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
|
|||
{
|
||||
req->handle = hwnd;
|
||||
req->flags = 0; /* don't set anything, just retrieve */
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case GWL_STYLE: retvalue = req->style; break;
|
||||
case GWL_EXSTYLE: retvalue = req->ex_style; break;
|
||||
case GWL_ID: retvalue = req->id; break;
|
||||
case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
|
||||
case GWL_USERDATA: retvalue = (ULONG_PTR)req->user_data; break;
|
||||
case GWL_STYLE: retvalue = reply->old_style; break;
|
||||
case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
|
||||
case GWL_ID: retvalue = reply->old_id; break;
|
||||
case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
|
||||
case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
|
||||
default:
|
||||
SetLastError( ERROR_INVALID_INDEX );
|
||||
break;
|
||||
|
@ -1991,29 +1995,29 @@ static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
|
|||
req->user_data = (void *)newval;
|
||||
break;
|
||||
}
|
||||
if ((ok = !SERVER_CALL_ERR()))
|
||||
if ((ok = !wine_server_call_err( req )))
|
||||
{
|
||||
switch(offset)
|
||||
{
|
||||
case GWL_STYLE:
|
||||
wndPtr->dwStyle = newval;
|
||||
retval = req->old_style;
|
||||
retval = reply->old_style;
|
||||
break;
|
||||
case GWL_EXSTYLE:
|
||||
wndPtr->dwExStyle = newval;
|
||||
retval = req->old_ex_style;
|
||||
retval = reply->old_ex_style;
|
||||
break;
|
||||
case GWL_ID:
|
||||
wndPtr->wIDmenu = newval;
|
||||
retval = req->old_id;
|
||||
retval = reply->old_id;
|
||||
break;
|
||||
case GWL_HINSTANCE:
|
||||
wndPtr->hInstance = newval;
|
||||
retval = (HINSTANCE)req->old_instance;
|
||||
retval = (HINSTANCE)reply->old_instance;
|
||||
break;
|
||||
case GWL_USERDATA:
|
||||
wndPtr->userdata = newval;
|
||||
retval = (ULONG_PTR)req->old_user_data;
|
||||
retval = (ULONG_PTR)reply->old_user_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2281,7 +2285,7 @@ BOOL WINAPI IsWindow( HWND hwnd )
|
|||
SERVER_START_REQ( get_window_info )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
ret = !SERVER_CALL_ERR();
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
|
@ -2315,10 +2319,10 @@ DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
|
|||
SERVER_START_REQ( get_window_info )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
tid = (DWORD)req->tid;
|
||||
if (process) *process = (DWORD)req->pid;
|
||||
tid = (DWORD)reply->tid;
|
||||
if (process) *process = (DWORD)reply->pid;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -2347,10 +2351,10 @@ HWND WINAPI GetParent( HWND hwnd )
|
|||
SERVER_START_REQ( get_window_tree )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
if (style & WS_CHILD) retvalue = req->parent;
|
||||
else retvalue = req->owner;
|
||||
if (style & WS_CHILD) retvalue = reply->parent;
|
||||
else retvalue = reply->owner;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -2372,56 +2376,43 @@ HWND WINAPI GetParent( HWND hwnd )
|
|||
HWND WINAPI GetAncestor( HWND hwnd, UINT type )
|
||||
{
|
||||
WND *win;
|
||||
HWND ret = 0;
|
||||
size_t size;
|
||||
HWND *list, ret = 0;
|
||||
|
||||
for (;;)
|
||||
if (type == GA_PARENT)
|
||||
{
|
||||
if (!(win = WIN_GetPtr( hwnd )))
|
||||
{
|
||||
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return 0;
|
||||
}
|
||||
if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
|
||||
ret = win->parent;
|
||||
WIN_ReleasePtr( win );
|
||||
if (type == GA_PARENT) return ret;
|
||||
if (!ret || ret == GetDesktopWindow())
|
||||
if (win != WND_OTHER_PROCESS)
|
||||
{
|
||||
ret = hwnd; /* if ret is the desktop, hwnd is the root ancestor */
|
||||
goto done;
|
||||
ret = win->parent;
|
||||
WIN_ReleasePtr( win );
|
||||
}
|
||||
hwnd = ret; /* restart with parent as hwnd */
|
||||
}
|
||||
|
||||
size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
|
||||
|
||||
SERVER_START_VAR_REQ( get_window_parents, size )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL())
|
||||
else /* need to query the server */
|
||||
{
|
||||
user_handle_t *data = server_data_ptr(req);
|
||||
int count = server_data_size(req) / sizeof(*data);
|
||||
if (count)
|
||||
SERVER_START_REQ( get_window_tree )
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case GA_PARENT:
|
||||
ret = data[0];
|
||||
break;
|
||||
case GA_ROOT:
|
||||
case GA_ROOTOWNER:
|
||||
if (count > 1) ret = data[count - 2]; /* get the one before the desktop */
|
||||
else ret = WIN_GetFullHandle( hwnd );
|
||||
break;
|
||||
}
|
||||
req->handle = hwnd;
|
||||
if (!wine_server_call_err( req )) ret = reply->parent;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
|
||||
done:
|
||||
if (!(list = WIN_ListParents( hwnd ))) return 0;
|
||||
|
||||
if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
|
||||
else
|
||||
{
|
||||
int count = 2;
|
||||
while (list[count]) count++;
|
||||
ret = list[count - 2]; /* get the one before the desktop */
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
|
||||
if (ret && type == GA_ROOTOWNER)
|
||||
{
|
||||
for (;;)
|
||||
|
@ -2597,27 +2588,27 @@ HWND WINAPI GetWindow( HWND hwnd, UINT rel )
|
|||
SERVER_START_REQ( get_window_tree )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL_ERR())
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
switch(rel)
|
||||
{
|
||||
case GW_HWNDFIRST:
|
||||
retval = req->first_sibling;
|
||||
retval = reply->first_sibling;
|
||||
break;
|
||||
case GW_HWNDLAST:
|
||||
retval = req->last_sibling;
|
||||
retval = reply->last_sibling;
|
||||
break;
|
||||
case GW_HWNDNEXT:
|
||||
retval = req->next_sibling;
|
||||
retval = reply->next_sibling;
|
||||
break;
|
||||
case GW_HWNDPREV:
|
||||
retval = req->prev_sibling;
|
||||
retval = reply->prev_sibling;
|
||||
break;
|
||||
case GW_OWNER:
|
||||
retval = req->owner;
|
||||
retval = reply->owner;
|
||||
break;
|
||||
case GW_CHILD:
|
||||
retval = req->first_child;
|
||||
retval = reply->first_child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2795,29 +2786,27 @@ HWND *WIN_ListParents( HWND hwnd )
|
|||
}
|
||||
|
||||
/* at least one parent belongs to another process, have to query the server */
|
||||
SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
|
||||
|
||||
for (;;)
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if (!SERVER_CALL())
|
||||
count = 0;
|
||||
SERVER_START_REQ( get_window_parents )
|
||||
{
|
||||
user_handle_t *data = server_data_ptr(req);
|
||||
count = server_data_size(req) / sizeof(*data);
|
||||
if (count)
|
||||
{
|
||||
HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
|
||||
list, (count + 1) * sizeof(HWND) );
|
||||
if (new_list)
|
||||
{
|
||||
list = new_list;
|
||||
for (pos = 0; pos < count; pos++) list[pos] = data[pos];
|
||||
list[pos] = 0;
|
||||
}
|
||||
else count = 0;
|
||||
}
|
||||
req->handle = hwnd;
|
||||
wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
|
||||
if (!wine_server_call( req )) count = reply->count;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!count) goto empty;
|
||||
if (size > count)
|
||||
{
|
||||
list[count] = 0;
|
||||
return list;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
size = count + 1;
|
||||
if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
if (count) return list;
|
||||
|
||||
empty:
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
|
|
|
@ -189,12 +189,12 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
|
|||
SERVER_START_REQ( get_window_rectangles )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
rect->left = req->window.left;
|
||||
rect->top = req->window.top;
|
||||
rect->right = req->window.right;
|
||||
rect->bottom = req->window.bottom;
|
||||
rect->left = reply->window.left;
|
||||
rect->top = reply->window.top;
|
||||
rect->right = reply->window.right;
|
||||
rect->bottom = reply->window.bottom;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -309,10 +309,10 @@ BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
|
|||
SERVER_START_REQ( get_window_rectangles )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if ((ret = !SERVER_CALL_ERR()))
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
rect->right = req->client.right - req->client.left;
|
||||
rect->bottom = req->client.bottom - req->client.top;
|
||||
rect->right = reply->client.right - reply->client.left;
|
||||
rect->bottom = reply->client.bottom - reply->client.top;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -600,10 +600,10 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
|
|||
{
|
||||
req->from = hwndFrom;
|
||||
req->to = hwndTo;
|
||||
if (!SERVER_CALL())
|
||||
if (!wine_server_call( req ))
|
||||
{
|
||||
offset->x = req->x;
|
||||
offset->y = req->y;
|
||||
offset->x = reply->x;
|
||||
offset->y = reply->y;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
|
Loading…
Reference in New Issue