forked from Mirrors/wine-wine
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.oldstable
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