Don't bother to return partial region data in get_window_region and

get_visible_region, return STATUS_BUFFER_OVERFLOW instead.
This commit is contained in:
Alexandre Julliard 2004-09-17 18:20:11 +00:00
parent e1db054315
commit 807fe07417
5 changed files with 50 additions and 43 deletions

View File

@ -33,6 +33,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "ntstatus.h"
#include "wownt32.h"
#include "wine/wingdi16.h"
@ -138,9 +139,9 @@ static int clip_children( HWND parent, HWND last, HRGN hrgn, int whole_window )
static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
{
RGNDATA *data;
NTSTATUS status;
HRGN ret = 0;
size_t size = 256;
BOOL retry = FALSE;
do
{
@ -151,28 +152,22 @@ static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
req->top_win = top;
req->flags = flags;
wine_server_set_reply( req, data->Buffer, size );
if (!wine_server_call_err( req ))
if (!(status = wine_server_call( req )))
{
if (reply->total_size <= size)
{
size_t reply_size = wine_server_reply_size( reply );
data->rdh.dwSize = sizeof(data->rdh);
data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size;
ret = ExtCreateRegion( NULL, size, data );
retry = FALSE;
}
else
{
size = reply->total_size;
retry = TRUE;
}
size_t reply_size = wine_server_reply_size( reply );
data->rdh.dwSize = sizeof(data->rdh);
data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size;
ret = ExtCreateRegion( NULL, size, data );
}
else size = reply->total_size;
}
SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, data );
} while (retry);
} while (status == STATUS_BUFFER_OVERFLOW);
if (status) SetLastError( RtlNtStatusToDosError(status) );
return ret;
}

View File

@ -618,19 +618,23 @@ void set_region_rect( struct region *region, const rectangle_t *rect )
}
/* retrieve the region data for sending to the client */
rectangle_t *get_region_data( const struct region *region, size_t *total_size )
rectangle_t *get_region_data( const struct region *region, size_t max_size, size_t *total_size )
{
const rectangle_t *data = region->rects;
if (!(*total_size = region->num_rects * sizeof(rectangle_t)))
{
/* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect);
return memdup( &empty_rect, sizeof(empty_rect) );
data = &empty_rect;
}
return memdup( region->rects, *total_size );
if (max_size >= *total_size) return memdup( data, *total_size );
set_error( STATUS_BUFFER_OVERFLOW );
return NULL;
}
/* retrieve the region data for sending to the client and free the region at the same time */
rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size )
rectangle_t *get_region_data_and_free( struct region *region, size_t max_size, size_t *total_size )
{
rectangle_t *ret = region->rects;
@ -638,7 +642,18 @@ rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size
{
/* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect);
ret = memdup( &empty_rect, sizeof(empty_rect) );
if (max_size >= sizeof(empty_rect))
{
ret = memdup( &empty_rect, sizeof(empty_rect) );
free( region->rects );
}
}
if (max_size < *total_size)
{
free( region->rects );
set_error( STATUS_BUFFER_OVERFLOW );
ret = NULL;
}
free( region );
return ret;

View File

@ -71,8 +71,10 @@ extern struct region *create_region( const rectangle_t *rects, unsigned int nb_r
extern struct region *create_region_from_req_data( const void *data, size_t size );
extern void free_region( struct region *region );
extern void set_region_rect( struct region *region, const rectangle_t *rect );
extern rectangle_t *get_region_data( const struct region *region, size_t *total_size );
extern rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size );
extern rectangle_t *get_region_data( const struct region *region, size_t max_size,
size_t *total_size );
extern rectangle_t *get_region_data_and_free( struct region *region, size_t max_size,
size_t *total_size );
extern int is_region_empty( const struct region *region );
extern void get_region_extents( const struct region *region, rectangle_t *rect );
extern void offset_region( struct region *region, int x, int y );

View File

@ -1084,8 +1084,8 @@ DECL_HANDLER(get_visible_region)
if ((region = get_visible_region( win, top, req->flags )))
{
rectangle_t *data = get_region_data_and_free( region, &reply->total_size );
set_reply_data_ptr( data, min(reply->total_size,get_reply_max_size()) );
rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size );
if (data) set_reply_data_ptr( data, reply->total_size );
}
}
@ -1097,11 +1097,10 @@ DECL_HANDLER(get_window_region)
if (!win) return;
reply->total_size = 0;
if (win->win_region)
{
rectangle_t *data = get_region_data( win->win_region, &reply->total_size );
set_reply_data_ptr( data, min( reply->total_size, get_reply_max_size() ) );
rectangle_t *data = get_region_data( win->win_region, get_reply_max_size(), &reply->total_size );
if (data) set_reply_data_ptr( data, reply->total_size );
}
}

View File

@ -29,6 +29,7 @@
#include "winbase.h"
#include "wingdi.h"
#include "winerror.h"
#include "ntstatus.h"
#include "wine/winuser16.h"
#include "wine/server.h"
#include "controls.h"
@ -172,10 +173,10 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{
int nRet = ERROR;
NTSTATUS status;
HRGN win_rgn = 0;
RGNDATA *data;
size_t size = 256;
BOOL retry = FALSE;
do
{
@ -188,31 +189,26 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{
req->window = hwnd;
wine_server_set_reply( req, data->Buffer, size );
if (!wine_server_call_err( req ))
if (!(status = wine_server_call( req )))
{
if (!reply->total_size) retry = FALSE; /* no region at all */
else if (reply->total_size <= size)
size_t reply_size = wine_server_reply_size( reply );
if (reply_size)
{
size_t reply_size = wine_server_reply_size( reply );
data->rdh.dwSize = sizeof(data->rdh);
data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size;
win_rgn = ExtCreateRegion( NULL, size, data );
retry = FALSE;
}
else
{
size = reply->total_size;
retry = TRUE;
}
}
else size = reply->total_size;
}
SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, data );
} while (retry);
} while (status == STATUS_BUFFER_OVERFLOW);
if (win_rgn)
if (status) SetLastError( RtlNtStatusToDosError(status) );
else if (win_rgn)
{
nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
DeleteObject( win_rgn );