Commit 807fe074 authored by Alexandre Julliard's avatar Alexandre Julliard

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

get_visible_region, return STATUS_BUFFER_OVERFLOW instead.
parent e1db0543
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "wingdi.h" #include "wingdi.h"
#include "winuser.h" #include "winuser.h"
#include "winerror.h" #include "winerror.h"
#include "ntstatus.h"
#include "wownt32.h" #include "wownt32.h"
#include "wine/wingdi16.h" #include "wine/wingdi16.h"
...@@ -138,9 +139,9 @@ static int clip_children( HWND parent, HWND last, HRGN hrgn, int whole_window ) ...@@ -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 ) static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
{ {
RGNDATA *data; RGNDATA *data;
NTSTATUS status;
HRGN ret = 0; HRGN ret = 0;
size_t size = 256; size_t size = 256;
BOOL retry = FALSE;
do do
{ {
...@@ -151,28 +152,22 @@ static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags ) ...@@ -151,28 +152,22 @@ static HRGN get_server_visible_region( HWND hwnd, HWND top, UINT flags )
req->top_win = top; req->top_win = top;
req->flags = flags; req->flags = flags;
wine_server_set_reply( req, data->Buffer, size ); 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);
size_t reply_size = wine_server_reply_size( reply ); data->rdh.iType = RDH_RECTANGLES;
data->rdh.dwSize = sizeof(data->rdh); data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.iType = RDH_RECTANGLES; data->rdh.nRgnSize = reply_size;
data->rdh.nCount = reply_size / sizeof(RECT); ret = ExtCreateRegion( NULL, size, data );
data->rdh.nRgnSize = reply_size;
ret = ExtCreateRegion( NULL, size, data );
retry = FALSE;
}
else
{
size = reply->total_size;
retry = TRUE;
}
} }
else size = reply->total_size;
} }
SERVER_END_REQ; SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, data ); HeapFree( GetProcessHeap(), 0, data );
} while (retry); } while (status == STATUS_BUFFER_OVERFLOW);
if (status) SetLastError( RtlNtStatusToDosError(status) );
return ret; return ret;
} }
......
...@@ -618,19 +618,23 @@ void set_region_rect( struct region *region, const rectangle_t *rect ) ...@@ -618,19 +618,23 @@ void set_region_rect( struct region *region, const rectangle_t *rect )
} }
/* retrieve the region data for sending to the client */ /* 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))) if (!(*total_size = region->num_rects * sizeof(rectangle_t)))
{ {
/* return a single empty rect for empty regions */ /* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect); *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 */ /* 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; rectangle_t *ret = region->rects;
...@@ -638,7 +642,18 @@ rectangle_t *get_region_data_and_free( struct region *region, size_t *total_size ...@@ -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 */ /* return a single empty rect for empty regions */
*total_size = sizeof(empty_rect); *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 ); free( region );
return ret; return ret;
......
...@@ -71,8 +71,10 @@ extern struct region *create_region( const rectangle_t *rects, unsigned int nb_r ...@@ -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 struct region *create_region_from_req_data( const void *data, size_t size );
extern void free_region( struct region *region ); extern void free_region( struct region *region );
extern void set_region_rect( struct region *region, const rectangle_t *rect ); 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( const struct region *region, size_t max_size,
extern rectangle_t *get_region_data_and_free( struct region *region, size_t *total_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 int is_region_empty( const struct region *region );
extern void get_region_extents( const struct region *region, rectangle_t *rect ); extern void get_region_extents( const struct region *region, rectangle_t *rect );
extern void offset_region( struct region *region, int x, int y ); extern void offset_region( struct region *region, int x, int y );
......
...@@ -1084,8 +1084,8 @@ DECL_HANDLER(get_visible_region) ...@@ -1084,8 +1084,8 @@ DECL_HANDLER(get_visible_region)
if ((region = get_visible_region( win, top, req->flags ))) if ((region = get_visible_region( win, top, req->flags )))
{ {
rectangle_t *data = get_region_data_and_free( region, &reply->total_size ); rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size );
set_reply_data_ptr( data, min(reply->total_size,get_reply_max_size()) ); if (data) set_reply_data_ptr( data, reply->total_size );
} }
} }
...@@ -1097,11 +1097,10 @@ DECL_HANDLER(get_window_region) ...@@ -1097,11 +1097,10 @@ DECL_HANDLER(get_window_region)
if (!win) return; if (!win) return;
reply->total_size = 0;
if (win->win_region) if (win->win_region)
{ {
rectangle_t *data = get_region_data( win->win_region, &reply->total_size ); rectangle_t *data = get_region_data( win->win_region, get_reply_max_size(), &reply->total_size );
set_reply_data_ptr( data, min( reply->total_size, get_reply_max_size() ) ); if (data) set_reply_data_ptr( data, reply->total_size );
} }
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
#include "winerror.h" #include "winerror.h"
#include "ntstatus.h"
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wine/server.h" #include "wine/server.h"
#include "controls.h" #include "controls.h"
...@@ -172,10 +173,10 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) ...@@ -172,10 +173,10 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{ {
int nRet = ERROR; int nRet = ERROR;
NTSTATUS status;
HRGN win_rgn = 0; HRGN win_rgn = 0;
RGNDATA *data; RGNDATA *data;
size_t size = 256; size_t size = 256;
BOOL retry = FALSE;
do do
{ {
...@@ -188,31 +189,26 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn ) ...@@ -188,31 +189,26 @@ int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
{ {
req->window = hwnd; req->window = hwnd;
wine_server_set_reply( req, data->Buffer, size ); 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 */ size_t reply_size = wine_server_reply_size( reply );
else if (reply->total_size <= size) if (reply_size)
{ {
size_t reply_size = wine_server_reply_size( reply );
data->rdh.dwSize = sizeof(data->rdh); data->rdh.dwSize = sizeof(data->rdh);
data->rdh.iType = RDH_RECTANGLES; data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nCount = reply_size / sizeof(RECT);
data->rdh.nRgnSize = reply_size; data->rdh.nRgnSize = reply_size;
win_rgn = ExtCreateRegion( NULL, size, data ); win_rgn = ExtCreateRegion( NULL, size, data );
retry = FALSE;
}
else
{
size = reply->total_size;
retry = TRUE;
} }
} }
else size = reply->total_size;
} }
SERVER_END_REQ; SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, data ); 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 ); nRet = CombineRgn( hrgn, win_rgn, 0, RGN_COPY );
DeleteObject( win_rgn ); DeleteObject( win_rgn );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment