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:
parent
e1db054315
commit
807fe07417
|
@ -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 )
|
||||||
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 )
|
||||||
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 )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
{
|
{
|
||||||
/* 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
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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 )
|
||||||
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 )
|
||||||
{
|
{
|
||||||
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 );
|
||||||
|
|
Loading…
Reference in New Issue