Wine-Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2018
- 90 participants
- 798 discussions
[PATCH 1/6] wined3d: Pass a texture and sub-resource index to wined3d_blitter_ops.blitter_blit().
by Henri Verbeet March 13, 2018
by Henri Verbeet March 13, 2018
March 13, 2018
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/arb_program_shader.c | 20 ++++-----
dlls/wined3d/surface.c | 89 ++++++++++++++++++---------------------
dlls/wined3d/swapchain.c | 5 +--
dlls/wined3d/wined3d_private.h | 12 ++----
4 files changed, 55 insertions(+), 71 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 0a9b078a648..acfd1d565cd 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -7795,13 +7795,11 @@ static BOOL arbfp_blit_supported(enum wined3d_blit_op blit_op, const struct wine
}
static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
- struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
- const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
+ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+ DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+ unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
{
- unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
- struct wined3d_texture *src_texture = src_surface->container;
- struct wined3d_texture *dst_texture = dst_surface->container;
struct wined3d_device *device = dst_texture->resource.device;
struct wined3d_arbfp_blitter *arbfp_blitter;
struct wined3d_color_key alpha_test_key;
@@ -7812,15 +7810,15 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
&dst_texture->resource, dst_location))
{
if ((next = blitter->next))
- return next->ops->blitter_blit(next, op, context, src_surface, src_location,
- src_rect, dst_surface, dst_location, dst_rect, color_key, filter);
+ return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter);
}
arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter);
/* Now load the surface */
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
- && (surface_get_sub_resource(src_surface)->locations
+ && (src_texture->sub_resources[src_sub_resource_idx].locations
& (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE))
== WINED3D_LOCATION_DRAWABLE
&& !wined3d_resource_is_offscreen(&src_texture->resource))
@@ -7857,16 +7855,16 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
if (dst_location == WINED3D_LOCATION_DRAWABLE)
{
- TRACE("Destination surface %p is onscreen.\n", dst_surface);
+ TRACE("Destination texture %p is onscreen.\n", dst_texture);
buffer = wined3d_texture_get_gl_buffer(dst_texture);
}
else
{
- TRACE("Destination surface %p is offscreen.\n", dst_surface);
+ TRACE("Destination texture %p is offscreen.\n", dst_texture);
buffer = GL_COLOR_ATTACHMENT0;
}
context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER,
- &dst_texture->resource, surface_get_sub_resource_idx(dst_surface), NULL, 0, dst_location);
+ &dst_texture->resource, dst_sub_resource_idx, NULL, 0, dst_location);
context_set_draw_buffer(context, buffer);
context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
context_invalidate_state(context, STATE_FRAMEBUFFER);
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 2c55b17532b..7b01cfecfd1 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2094,7 +2094,6 @@ BOOL texture2d_load_drawable(struct wined3d_texture *texture,
unsigned int sub_resource_idx, struct wined3d_context *context)
{
struct wined3d_texture *restore_texture;
- struct wined3d_surface *surface;
struct wined3d_device *device;
unsigned int restore_idx;
unsigned int level;
@@ -2116,7 +2115,6 @@ BOOL texture2d_load_drawable(struct wined3d_texture *texture,
}
device = texture->resource.device;
- surface = texture->sub_resources[sub_resource_idx].u.surface;
restore_texture = context->current_rt.texture;
restore_idx = context->current_rt.sub_resource_idx;
if (restore_texture != texture || restore_idx != sub_resource_idx)
@@ -2129,8 +2127,8 @@ BOOL texture2d_load_drawable(struct wined3d_texture *texture,
wined3d_texture_get_level_height(texture, level));
wined3d_texture_load_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context,
- surface, WINED3D_LOCATION_TEXTURE_RGB, &r,
- surface, WINED3D_LOCATION_DRAWABLE, &r,
+ texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &r,
+ texture, sub_resource_idx, WINED3D_LOCATION_DRAWABLE, &r,
NULL, WINED3D_TEXF_POINT);
if (restore_texture)
@@ -2371,16 +2369,21 @@ static void fbo_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
}
static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
- struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
- const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
+ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+ DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+ unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
{
- struct wined3d_resource *src_resource = &src_surface->container->resource;
- struct wined3d_resource *dst_resource = &dst_surface->container->resource;
- struct wined3d_device *device = dst_resource->device;
+ struct wined3d_resource *src_resource, *dst_resource;
enum wined3d_blit_op blit_op = op;
+ struct wined3d_device *device;
struct wined3d_blitter *next;
+ src_resource = &src_texture->resource;
+ dst_resource = &dst_texture->resource;
+
+ device = dst_resource->device;
+
if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_resource->format->id == src_resource->format->id)
{
if (dst_resource->format_flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
@@ -2393,25 +2396,23 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
src_resource, src_location, dst_resource, dst_location))
{
if ((next = blitter->next))
- return next->ops->blitter_blit(next, op, context, src_surface, src_location,
- src_rect, dst_surface, dst_location, dst_rect, colour_key, filter);
+ return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter);
}
if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT)
{
TRACE("Colour blit.\n");
- texture2d_blt_fbo(device, context, filter, src_surface->container,
- surface_get_sub_resource_idx(src_surface), src_location, src_rect, dst_surface->container,
- surface_get_sub_resource_idx(dst_surface), dst_location, dst_rect);
+ texture2d_blt_fbo(device, context, filter, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect);
return dst_location;
}
if (blit_op == WINED3D_BLIT_OP_DEPTH_BLIT)
{
TRACE("Depth/stencil blit.\n");
- texture2d_depth_blt_fbo(device, context, src_surface->container, surface_get_sub_resource_idx(src_surface),
- src_location, src_rect, dst_surface->container, surface_get_sub_resource_idx(dst_surface),
- dst_location, dst_rect);
+ texture2d_depth_blt_fbo(device, context, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect);
return dst_location;
}
@@ -2474,21 +2475,17 @@ static void raw_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
/* Context activation is done by the caller. */
static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
- struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
- const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
+ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+ DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+ unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
- unsigned int src_sub_resource_idx, dst_sub_resource_idx;
unsigned int src_level, src_layer, dst_level, dst_layer;
- struct wined3d_texture *src_texture, *dst_texture;
struct wined3d_blitter *next;
GLuint src_name, dst_name;
DWORD location;
- src_texture = src_surface->container;
- dst_texture = dst_surface->container;
-
/* If we would need to copy from a renderbuffer or drawable, we'd probably
* be better of using the FBO blitter directly, since we'd need to use it
* to copy the resource contents to the texture anyway. */
@@ -2504,17 +2501,15 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
}
TRACE("Forwarding to blitter %p.\n", next);
- return next->ops->blitter_blit(next, op, context, src_surface, src_location,
- src_rect, dst_surface, dst_location, dst_rect, colour_key, filter);
+ return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter);
}
TRACE("Blit using ARB_copy_image.\n");
- src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
src_level = src_sub_resource_idx % src_texture->level_count;
src_layer = src_sub_resource_idx / src_texture->level_count;
- dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
dst_level = dst_sub_resource_idx % dst_texture->level_count;
dst_layer = dst_sub_resource_idx / dst_texture->level_count;
@@ -2733,13 +2728,11 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
}
static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
- struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
- const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
+ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+ DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+ unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
{
- unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
- struct wined3d_texture *src_texture = src_surface->container;
- struct wined3d_texture *dst_texture = dst_surface->container;
const struct wined3d_gl_info *gl_info = context->gl_info;
struct wined3d_resource *src_resource, *dst_resource;
struct wined3d_color_key old_blt_key;
@@ -2755,11 +2748,12 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
if (!ffp_blit_supported(op, context, src_resource, src_location, dst_resource, dst_location))
{
if ((next = blitter->next))
- return next->ops->blitter_blit(next, op, context, src_surface, src_location,
- src_rect, dst_surface, dst_location, dst_rect, color_key, filter);
+ return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
+ src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter);
}
- TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface);
+ TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
+ src_texture, src_sub_resource_idx, dst_texture, dst_sub_resource_idx);
old_blt_key = src_texture->async.src_blt_color_key;
old_color_key_flags = src_texture->async.color_key_flags;
@@ -2786,16 +2780,16 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
if (dst_location == WINED3D_LOCATION_DRAWABLE)
{
- TRACE("Destination surface %p is onscreen.\n", dst_surface);
+ TRACE("Destination texture %p is onscreen.\n", dst_texture);
buffer = wined3d_texture_get_gl_buffer(dst_texture);
}
else
{
- TRACE("Destination surface %p is offscreen.\n", dst_surface);
+ TRACE("Destination texture %p is offscreen.\n", dst_texture);
buffer = GL_COLOR_ATTACHMENT0;
}
context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER,
- dst_resource, surface_get_sub_resource_idx(dst_surface), NULL, 0, dst_location);
+ dst_resource, dst_sub_resource_idx, NULL, 0, dst_location);
context_set_draw_buffer(context, buffer);
context_check_fbo_status(context, GL_DRAW_FRAMEBUFFER);
context_invalidate_state(context, STATE_FRAMEBUFFER);
@@ -3627,16 +3621,13 @@ static void cpu_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
}
static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
- struct wined3d_context *context, struct wined3d_surface *src_surface, DWORD src_location,
- const RECT *src_rect, struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
+ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+ DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+ unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
{
struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1};
struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1};
- unsigned int dst_sub_resource_idx = surface_get_sub_resource_idx(dst_surface);
- unsigned int src_sub_resource_idx = surface_get_sub_resource_idx(src_surface);
- struct wined3d_texture *dst_texture = dst_surface->container;
- struct wined3d_texture *src_texture = src_surface->container;
struct wined3d_blt_fx fx;
DWORD flags = 0;
@@ -3795,8 +3786,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const struct wi
context = context_acquire(device, dst_texture, dst_sub_resource_idx);
valid_locations = device->blitter->ops->blitter_blit(device->blitter,
WINED3D_BLIT_OP_DEPTH_BLIT, context,
- src_surface, src_texture->resource.draw_binding, &src_rect,
- dst_surface, dst_location, &dst_rect, NULL, filter);
+ src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect,
+ dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter);
context_release(context);
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
@@ -3900,8 +3891,8 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const struct wi
context = context_acquire(device, dst_texture, dst_sub_resource_idx);
valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context,
- src_surface, src_texture->resource.draw_binding, &src_rect,
- dst_surface, dst_location, &dst_rect, colour_key, filter);
+ src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect,
+ dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter);
context_release(context);
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index f848044f119..4542f291f43 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -309,7 +309,6 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
{
struct wined3d_texture *texture = swapchain->back_buffers[0];
- struct wined3d_surface *back_buffer = texture->sub_resources[0].u.surface;
struct wined3d_device *device = swapchain->device;
enum wined3d_texture_filter_type filter;
DWORD location;
@@ -329,8 +328,8 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
location = WINED3D_LOCATION_RB_RESOLVED;
wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
- device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, back_buffer,
- location, src_rect, back_buffer, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter);
+ device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, 0,
+ location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter);
wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE);
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1e9806a412d..ad37e5dae06 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2109,9 +2109,10 @@ struct wined3d_blitter_ops
unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil);
DWORD (*blitter_blit)(struct wined3d_blitter *blitter, enum wined3d_blit_op op, struct wined3d_context *context,
- struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect,
- struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect,
- const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter);
+ struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location,
+ const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+ DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key,
+ enum wined3d_texture_filter_type filter);
};
void wined3d_arbfp_blitter_create(struct wined3d_blitter **next,
@@ -3343,11 +3344,6 @@ static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_sur
return surface->texture_layer * surface->container->level_count + surface->texture_level;
}
-static inline struct wined3d_texture_sub_resource *surface_get_sub_resource(struct wined3d_surface *surface)
-{
- return &surface->container->sub_resources[surface_get_sub_resource_idx(surface)];
-}
-
HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const struct wined3d_box *dst_box,
struct wined3d_surface *src_surface, const struct wined3d_box *src_box, DWORD flags,
const struct wined3d_blt_fx *blt_fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN;
--
2.11.0
1
0
[PATCH 2/6] wsdapi: Add stub implementation of IWSDiscoveryPublisher_PublishEx.
by Owen Rudge March 13, 2018
by Owen Rudge March 13, 2018
March 13, 2018
Signed-off-by: Owen Rudge <orudge(a)codeweavers.com>
---
dlls/wsdapi/Makefile.in | 1 +
dlls/wsdapi/discovery.c | 40 +++++++++---------------
dlls/wsdapi/soap.c | 73
+++++++++++++++++++++++++++++++++++++++++++
dlls/wsdapi/wsdapi_internal.h | 24 ++++++++++++++
4 files changed, 112 insertions(+), 26 deletions(-)
create mode 100644 dlls/wsdapi/soap.c
2
1
March 13, 2018
Fixes PowerShell issue at https://bugs.winehq.org/show_bug.cgi?id=41911
v3:
- Don't use "LP" type names.
- Remove noisy FIXME. Replace with comment.
- Combine parameter checking into one block.
- Don't bother checking disjoint flags.
- Drop superfluous comment.
- Don't set last error to ERROR_SUCCESS.
- Add handling of FIND_FROMEND.
- Combine all cases into one block.
- Simplify test cases.
v2: Some tests are broken on Windows Vista and Windows Server 2003 and
2008.
Signed-off-by: Sergio Gómez Del Real <sdelreal(a)codeweavers.com>
---
dlls/kernel32/kernel32.spec | 2 +-
dlls/kernel32/locale.c | 51 ++++++++++++++++++++
dlls/kernel32/tests/locale.c | 110 +++++++++++++++++++++++++++++++++++++++++++
include/winnls.h | 5 ++
4 files changed, 167 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 60809f45fd..3a0bef93e7 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -505,7 +505,7 @@
@ stub FindNextVolumeMountPointW
@ stdcall FindNextVolumeW(long ptr long)
# @ stub FindNLSString
-# @ stub FindNLSStringEx
+@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
@ stdcall FindResourceA(long str str)
@ stdcall FindResourceExA(long str str long)
@ stdcall FindResourceExW(long wstr wstr long)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index e4c323ead6..a82794133e 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -5941,3 +5941,54 @@ INT WINAPI ResolveLocaleName(LPCWSTR name, LPWSTR localename, INT len)
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
+
+/******************************************************************************
+ * FindNLSStringEx (KERNEL32.@)
+ */
+
+INT WINAPI FindNLSStringEx(const WCHAR *localename, DWORD flags, const WCHAR *src,
+ INT src_size, const WCHAR *value, INT value_size,
+ INT *found, NLSVERSIONINFO *version_info, void *reserved,
+ LPARAM sort_handle)
+{
+
+ /* FIXME: this function should normalize strings before calling CompareStringEx() */
+ DWORD mask = flags;
+ int j, inc_or_dec;
+
+ TRACE("%s %x %s %d %s %d %p %p %p %ld\n", wine_dbgstr_w(localename), flags,
+ wine_dbgstr_w(src), src_size, wine_dbgstr_w(value), value_size, found,
+ version_info, reserved, sort_handle);
+
+ if (version_info != NULL || reserved != NULL || sort_handle != 0 ||
+ !IsValidLocaleName(localename) || src == NULL || src_size == 0 ||
+ src_size < -1 || value == NULL || value_size == 0 || value_size < -1)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+ if (src_size == -1)
+ src_size = strlenW(src);
+ if (value_size == -1)
+ value_size = strlenW(value);
+
+ src_size -= value_size;
+ if (src_size < 0) return -1;
+
+ mask = flags & ~(FIND_FROMSTART | FIND_FROMEND | FIND_STARTSWITH | FIND_ENDSWITH);
+ j = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : src_size;
+ inc_or_dec = flags & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
+ for (; j <= src_size && j >= 0; j += inc_or_dec)
+ {
+ if (CompareStringEx(localename, mask, src + j, value_size, value, value_size, NULL, NULL, 0) == CSTR_EQUAL)
+ {
+ if (found)
+ *found = value_size;
+ return j;
+ }
+ if (flags & (FIND_STARTSWITH | FIND_ENDSWITH))
+ break;
+ }
+
+ return -1;
+}
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index ce2f13b6dc..169adcb1be 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -103,6 +103,7 @@ static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULON
static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int);
+static INT (WINAPI *pFindNLSStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT, LPINT, LPNLSVERSIONINFO, LPVOID, LPARAM);
static void InitFunctionPointers(void)
{
@@ -135,6 +136,7 @@ static void InitFunctionPointers(void)
X(GetThreadPreferredUILanguages);
X(GetUserPreferredUILanguages);
X(GetNumberFormatEx);
+ X(FindNLSStringEx);
mod = GetModuleHandleA("ntdll");
X(RtlUpcaseUnicodeChar);
@@ -5329,6 +5331,113 @@ static void test_GetUserPreferredUILanguages(void)
HeapFree(GetProcessHeap(), 0, buffer);
}
+static void test_FindNLSStringEx(void)
+{
+ INT res;
+ static WCHAR en_simpsimpW[] = {'S','i','m','p','l','e','S','i','m','p','l','e',0};
+ static WCHAR en_simpW[] = {'S','i','m','p','l','e',0};
+ static WCHAR comb_s_accent1W[] = {0x1e69, 'o','u','r','c','e',0};
+ static WCHAR comb_s_accent2W[] = {0x0073,0x323,0x307,'o','u','r','c','e',0};
+ static WCHAR comb_q_accent1W[] = {0x0071,0x0307,0x323,'u','o','t','e',0};
+ static WCHAR comb_q_accent2W[] = {0x0071,0x0323,0x307,'u','o','t','e',0};
+ struct test_data {
+ const WCHAR *locale;
+ DWORD flags;
+ WCHAR *src;
+ INT src_size;
+ WCHAR *value;
+ INT val_size;
+ INT found;
+ INT expected_ret;
+ INT expected_found;
+ int todo;
+ BOOL broken_vista_servers;
+ };
+
+ static struct test_data test_arr[] =
+ {
+ { localeW, FIND_FROMSTART, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
+ en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 0, 6, 0, FALSE},
+ { localeW, FIND_FROMEND, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
+ en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 6, 6, 0, FALSE},
+ { localeW, FIND_STARTSWITH, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
+ en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 0, 6, 0, FALSE},
+ { localeW, FIND_ENDSWITH, en_simpsimpW, sizeof(en_simpsimpW)/sizeof(WCHAR)-1,
+ en_simpW, sizeof(en_simpW)/sizeof(WCHAR)-1, 0, 6, 6, 0, FALSE},
+ { localeW, FIND_FROMSTART, comb_s_accent1W, sizeof(comb_s_accent1W)/sizeof(WCHAR)-1,
+ comb_s_accent2W, sizeof(comb_s_accent2W)/sizeof(WCHAR)-1, 0, 0, 6, 1, TRUE },
+ { localeW, FIND_FROMSTART, comb_q_accent1W, sizeof(comb_q_accent1W)/sizeof(WCHAR)-1,
+ comb_q_accent2W, sizeof(comb_q_accent2W)/sizeof(WCHAR)-1, 0, 0, 7, 1, FALSE },
+ { 0 }
+ };
+ struct test_data *ptest;
+
+ if (!pFindNLSStringEx)
+ {
+ win_skip("FindNLSStringEx is not available.\n");
+ return;
+ }
+
+ res = pFindNLSStringEx(invalidW, FIND_FROMSTART, fooW, 3, fooW,
+ 3, NULL, NULL, NULL, 0);
+ ok(res, "Expected failure of FindNLSStringEx. Return value was %d\n", res);
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected ERROR_INVALID_PARAMETER as last error; got %d\n", GetLastError());
+
+ res = pFindNLSStringEx(localeW, FIND_FROMSTART, NULL, 3, fooW, 3,
+ NULL, NULL, NULL, 0);
+ ok(res, "Expected failure of FindNLSStringEx. Return value was %d\n", res);
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected ERROR_INVALID_PARAMETER as last error; got %d\n", GetLastError());
+
+ res = pFindNLSStringEx(localeW, FIND_FROMSTART, fooW, -5, fooW, 3,
+ NULL, NULL, NULL, 0);
+ ok(res, "Expected failure of FindNLSStringEx. Return value was %d\n", res);
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected ERROR_INVALID_PARAMETER as last error; got %d\n", GetLastError());
+
+ res = pFindNLSStringEx(localeW, FIND_FROMSTART, fooW, 3, NULL, 3,
+ NULL, NULL, NULL, 0);
+ ok(res, "Expected failure of FindNLSStringEx. Return value was %d\n", res);
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected ERROR_INVALID_PARAMETER as last error; got %d\n", GetLastError());
+
+ res = pFindNLSStringEx(localeW, FIND_FROMSTART, fooW, 3, fooW, -5,
+ NULL, NULL, NULL, 0);
+ ok(res, "Expected failure of FindNLSStringEx. Return value was %d\n", res);
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected ERROR_INVALID_PARAMETER as last error; got %d\n", GetLastError());
+
+ for (ptest = test_arr; ptest->src != NULL; ptest++)
+ {
+ todo_wine_if(ptest->todo)
+ {
+ res = pFindNLSStringEx(ptest->locale, ptest->flags, ptest->src, ptest->src_size,
+ ptest->value, ptest->val_size, &ptest->found, NULL, NULL, 0);
+ if (ptest->broken_vista_servers)
+ {
+ ok(res == ptest->expected_ret || /* Win 7 onwards */
+ broken(res == -1), /* Win Vista, Server 2003 and 2008 */
+ "Expected FindNLSStringEx to return %d. Returned value was %d\n",
+ ptest->expected_ret, res);
+ ok(ptest->found == ptest->expected_found || /* Win 7 onwards */
+ broken(ptest->found == 0), /* Win Vista, Server 2003 and 2008 */
+ "Expected FindNLSStringEx to output %d. Value was %d\n",
+ ptest->expected_found, ptest->found);
+ }
+ else
+ {
+ ok(res == ptest->expected_ret,
+ "Expected FindNLSStringEx to return %d. Returned value was %d\n",
+ ptest->expected_ret, res);
+ ok(ptest->found == ptest->expected_found,
+ "Expected FindNLSStringEx to output %d. Value was %d\n",
+ ptest->expected_found, ptest->found);
+ }
+ }
+ }
+}
+
START_TEST(locale)
{
InitFunctionPointers();
@@ -5375,6 +5484,7 @@ START_TEST(locale)
test_GetSystemPreferredUILanguages();
test_GetThreadPreferredUILanguages();
test_GetUserPreferredUILanguages();
+ test_FindNLSStringEx();
/* this requires collation table patch to make it MS compatible */
if (0) test_sorting();
}
diff --git a/include/winnls.h b/include/winnls.h
index 8cb8af6e8e..119111110a 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -352,6 +352,10 @@ static const WCHAR LOCALE_NAME_SYSTEM_DEFAULT[] = {'!','s','y','s','-','d','e','
#define NORM_IGNOREKANATYPE 0x00010000
#define NORM_IGNOREWIDTH 0x00020000
#define NORM_LINGUISTIC_CASING 0x08000000
+#define FIND_STARTSWITH 0x00100000
+#define FIND_ENDSWITH 0x00200000
+#define FIND_FROMSTART 0x00400000
+#define FIND_FROMEND 0x00800000
#define CP_ACP 0
#define CP_OEMCP 1
@@ -961,6 +965,7 @@ WINBASEAPI BOOL WINAPI SetThreadLocale(LCID);
WINBASEAPI LANGID WINAPI SetThreadUILanguage(LANGID);
WINBASEAPI BOOL WINAPI SetUserGeoID(GEOID);
WINBASEAPI INT WINAPI WideCharToMultiByte(UINT,DWORD,LPCWSTR,INT,LPSTR,INT,LPCSTR,LPBOOL);
+WINBASEAPI INT WINAPI FindNLSStringEx(const WCHAR *,DWORD,const WCHAR *,INT,const WCHAR *,INT,INT *,NLSVERSIONINFO *,void *,LPARAM);
#ifdef __cplusplus
}
--
2.14.1
2
1
[PATCH 3/3] mstask: Reimplement ITask constructor using ITaskFolder methods.
by Dmitry Timoshkov March 13, 2018
by Dmitry Timoshkov March 13, 2018
March 13, 2018
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/factory.c | 1 +
dlls/mstask/mstask_main.c | 1 +
dlls/mstask/mstask_private.h | 2 +-
dlls/mstask/task.c | 50 +++++++++++++++++++++++++++++++-------------
dlls/mstask/task_scheduler.c | 26 ++++++++++++++++-------
dlls/mstask/task_trigger.c | 1 +
6 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/dlls/mstask/factory.c b/dlls/mstask/factory.c
index 97a5113868..260a93066f 100644
--- a/dlls/mstask/factory.c
+++ b/dlls/mstask/factory.c
@@ -23,6 +23,7 @@
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
+#include "taskschd.h"
#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
diff --git a/dlls/mstask/mstask_main.c b/dlls/mstask/mstask_main.c
index bb19b89da2..eae85562f5 100644
--- a/dlls/mstask/mstask_main.c
+++ b/dlls/mstask/mstask_main.c
@@ -24,6 +24,7 @@
#include "winbase.h"
#include "objbase.h"
#include "rpcproxy.h"
+#include "taskschd.h"
#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
diff --git a/dlls/mstask/mstask_private.h b/dlls/mstask/mstask_private.h
index 9180e4a51f..511019ded6 100644
--- a/dlls/mstask/mstask_private.h
+++ b/dlls/mstask/mstask_private.h
@@ -26,6 +26,6 @@ extern ClassFactoryImpl MSTASK_ClassFactory DECLSPEC_HIDDEN;
extern HRESULT TaskTriggerConstructor(LPVOID *ppObj) DECLSPEC_HIDDEN;
extern HRESULT TaskSchedulerConstructor(LPVOID *ppObj) DECLSPEC_HIDDEN;
-extern HRESULT TaskConstructor(LPCWSTR pwszTaskName, LPVOID *ppObj) DECLSPEC_HIDDEN;
+extern HRESULT TaskConstructor(ITaskFolder *folder, const WCHAR *task_name, ITask **task, BOOL create) DECLSPEC_HIDDEN;
#endif /* __MSTASK_PRIVATE_H__ */
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index 872e445b5e..095431cb04 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Google (Roy Shea)
+ * Copyright (C) 2018 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
+#include "taskschd.h"
#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
@@ -34,7 +36,7 @@ typedef struct
ITask ITask_iface;
IPersistFile IPersistFile_iface;
LONG ref;
- LPWSTR taskName;
+ IRegisteredTask *regtask;
LPWSTR applicationName;
LPWSTR parameters;
LPWSTR comment;
@@ -58,7 +60,6 @@ static void TaskDestructor(TaskImpl *This)
HeapFree(GetProcessHeap(), 0, This->accountName);
HeapFree(GetProcessHeap(), 0, This->comment);
HeapFree(GetProcessHeap(), 0, This->parameters);
- HeapFree(GetProcessHeap(), 0, This->taskName);
HeapFree(GetProcessHeap(), 0, This);
InterlockedDecrement(&dll_ref);
}
@@ -761,28 +762,49 @@ static const IPersistFileVtbl MSTASK_IPersistFileVtbl =
MSTASK_IPersistFile_GetCurFile
};
-HRESULT TaskConstructor(LPCWSTR pwszTaskName, LPVOID *ppObj)
+HRESULT TaskConstructor(ITaskFolder *folder, const WCHAR *task_name, ITask **task, BOOL create)
{
TaskImpl *This;
- int n;
+ IRegisteredTask *regtask;
+ BSTR bstr;
+ HRESULT hr;
- TRACE("(%s, %p)\n", debugstr_w(pwszTaskName), ppObj);
+ TRACE("(%s, %p)\n", debugstr_w(task_name), task);
+
+ bstr = SysAllocString(task_name);
+ if (!bstr) return E_OUTOFMEMORY;
+
+ if (create)
+ {
+ static const char xml_tmplate[] =
+ "<?xml version=\"1.0\"?>\n"
+ "<Task xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n"
+ "</Task>\n";
+ WCHAR xmlW[sizeof(xml_tmplate)];
+ VARIANT v_null;
+
+ MultiByteToWideChar(CP_ACP, 0, xml_tmplate, -1, xmlW, sizeof(xmlW)/sizeof(xmlW[0]));
+
+ V_VT(&v_null) = VT_NULL;
+ hr = ITaskFolder_RegisterTask(folder, bstr, xmlW, TASK_CREATE | TASK_UPDATE,
+ v_null, v_null, TASK_LOGON_NONE, v_null, ®task);
+ }
+ else
+ hr = ITaskFolder_GetTask(folder, bstr, ®task);
+ SysFreeString(bstr);
+ if (hr != S_OK) return hr;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This)
+ {
+ IRegisteredTask_Release(regtask);
return E_OUTOFMEMORY;
+ }
This->ITask_iface.lpVtbl = &MSTASK_ITaskVtbl;
This->IPersistFile_iface.lpVtbl = &MSTASK_IPersistFileVtbl;
This->ref = 1;
- n = (lstrlenW(pwszTaskName) + 1) * sizeof(WCHAR);
- This->taskName = HeapAlloc(GetProcessHeap(), 0, n);
- if (!This->taskName)
- {
- HeapFree(GetProcessHeap(), 0, This);
- return E_OUTOFMEMORY;
- }
- lstrcpyW(This->taskName, pwszTaskName);
+ This->regtask = regtask;
This->applicationName = NULL;
This->parameters = NULL;
This->comment = NULL;
@@ -791,7 +813,7 @@ HRESULT TaskConstructor(LPCWSTR pwszTaskName, LPVOID *ppObj)
/* Default time is 3 days = 259200000 ms */
This->maxRunTime = 259200000;
- *ppObj = &This->ITask_iface;
+ *task = &This->ITask_iface;
InterlockedIncrement(&dll_ref);
return S_OK;
}
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index 1ace4dd7a2..e9b8727633 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -37,6 +37,7 @@ typedef struct
ITaskScheduler ITaskScheduler_iface;
LONG ref;
ITaskService *service;
+ ITaskFolder *root;
} TaskSchedulerImpl;
typedef struct
@@ -58,6 +59,7 @@ static inline EnumWorkItemsImpl *impl_from_IEnumWorkItems(IEnumWorkItems *iface)
static void TaskSchedulerDestructor(TaskSchedulerImpl *This)
{
TRACE("%p\n", This);
+ ITaskFolder_Release(This->root);
ITaskService_Release(This->service);
HeapFree(GetProcessHeap(), 0, This);
InterlockedDecrement(&dll_ref);
@@ -290,14 +292,15 @@ static HRESULT WINAPI MSTASK_ITaskScheduler_Delete(
static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem(
ITaskScheduler* iface,
- LPCWSTR pwszTaskName,
+ LPCWSTR task_name,
REFCLSID rclsid,
REFIID riid,
- IUnknown **ppunk)
+ IUnknown **task)
{
- HRESULT hr;
- TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(pwszTaskName),
- debugstr_guid(rclsid) ,debugstr_guid(riid), ppunk);
+ TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
+
+ TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(task_name),
+ debugstr_guid(rclsid), debugstr_guid(riid), task);
if (!IsEqualGUID(rclsid, &CLSID_CTask))
return CLASS_E_CLASSNOTAVAILABLE;
@@ -305,8 +308,7 @@ static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem(
if (!IsEqualGUID(riid, &IID_ITask))
return E_NOINTERFACE;
- hr = TaskConstructor(pwszTaskName, (LPVOID *)ppunk);
- return hr;
+ return TaskConstructor(This->root, task_name, (ITask **)task, TRUE);
}
static HRESULT WINAPI MSTASK_ITaskScheduler_AddWorkItem(
@@ -347,6 +349,7 @@ HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
{
TaskSchedulerImpl *This;
ITaskService *service;
+ ITaskFolder *root;
VARIANT v_null;
HRESULT hr;
@@ -363,15 +366,24 @@ HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
return hr;
}
+ hr = ITaskService_GetFolder(service, NULL, &root);
+ if (hr != S_OK)
+ {
+ ITaskService_Release(service);
+ return hr;
+ }
+
This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This)
{
+ ITaskFolder_Release(root);
ITaskService_Release(service);
return E_OUTOFMEMORY;
}
This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl;
This->service = service;
+ This->root = root;
This->ref = 1;
*ppObj = &This->ITaskScheduler_iface;
diff --git a/dlls/mstask/task_trigger.c b/dlls/mstask/task_trigger.c
index 9475e5608a..56bfbed54f 100644
--- a/dlls/mstask/task_trigger.c
+++ b/dlls/mstask/task_trigger.c
@@ -24,6 +24,7 @@
#include "winbase.h"
#include "objbase.h"
#include "winternl.h"
+#include "taskschd.h"
#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
--
2.16.2
1
0
[PATCH 2/3] mstask: Reimplement SetTargetComputer/GetTargetComputer using ITaskService methods.
by Dmitry Timoshkov March 13, 2018
by Dmitry Timoshkov March 13, 2018
March 13, 2018
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/Makefile.in | 2 +-
dlls/mstask/task_scheduler.c | 89 +++++++++++++++++++++++++++-----------------
2 files changed, 55 insertions(+), 36 deletions(-)
diff --git a/dlls/mstask/Makefile.in b/dlls/mstask/Makefile.in
index 72a6db3eb7..d914666eed 100644
--- a/dlls/mstask/Makefile.in
+++ b/dlls/mstask/Makefile.in
@@ -1,5 +1,5 @@
MODULE = mstask.dll
-IMPORTS = ole32
+IMPORTS = ole32 oleaut32
C_SRCS = \
factory.c \
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index 1c2d227ddb..1ace4dd7a2 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Google (Roy Shea)
+ * Copyright (C) 2018 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,7 @@
#include "winbase.h"
#include "initguid.h"
#include "objbase.h"
+#include "taskschd.h"
#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
@@ -34,6 +36,7 @@ typedef struct
{
ITaskScheduler ITaskScheduler_iface;
LONG ref;
+ ITaskService *service;
} TaskSchedulerImpl;
typedef struct
@@ -55,6 +58,7 @@ static inline EnumWorkItemsImpl *impl_from_IEnumWorkItems(IEnumWorkItems *iface)
static void TaskSchedulerDestructor(TaskSchedulerImpl *This)
{
TRACE("%p\n", This);
+ ITaskService_Release(This->service);
HeapFree(GetProcessHeap(), 0, This);
InterlockedDecrement(&dll_ref);
}
@@ -198,60 +202,56 @@ static ULONG WINAPI MSTASK_ITaskScheduler_Release(
}
static HRESULT WINAPI MSTASK_ITaskScheduler_SetTargetComputer(
- ITaskScheduler* iface,
- LPCWSTR pwszComputer)
+ ITaskScheduler *iface, LPCWSTR comp_name)
{
TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
- WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 3]; /* extra space for two '\' and a zero */
- DWORD len = MAX_COMPUTERNAME_LENGTH + 1; /* extra space for a zero */
-
- TRACE("(%p)->(%s)\n", This, debugstr_w(pwszComputer));
-
- /* NULL is an alias for the local computer */
- if (!pwszComputer)
- return S_OK;
+ VARIANT v_null, v_comp;
+ HRESULT hr;
- buffer[0] = '\\';
- buffer[1] = '\\';
- if (GetComputerNameW(buffer + 2, &len))
- {
- if (!lstrcmpiW(buffer, pwszComputer) || /* full unc name */
- !lstrcmpiW(buffer + 2, pwszComputer)) /* name without backslash */
- return S_OK;
- }
+ TRACE("(%p)->(%s)\n", This, debugstr_w(comp_name));
- FIXME("remote computer %s not supported\n", debugstr_w(pwszComputer));
- return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
+ V_VT(&v_null) = VT_NULL;
+ V_VT(&v_comp) = VT_BSTR;
+ V_BSTR(&v_comp) = SysAllocString(comp_name);
+ hr = ITaskService_Connect(This->service, v_comp, v_null, v_null, v_null);
+ SysFreeString(V_BSTR(&v_comp));
+ return hr;
}
static HRESULT WINAPI MSTASK_ITaskScheduler_GetTargetComputer(
- ITaskScheduler* iface,
- LPWSTR *ppwszComputer)
+ ITaskScheduler *iface, LPWSTR *comp_name)
{
TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface);
- LPWSTR buffer;
- DWORD len = MAX_COMPUTERNAME_LENGTH + 1; /* extra space for the zero */
+ BSTR bstr;
+ WCHAR *buffer;
+ HRESULT hr;
- TRACE("(%p)->(%p)\n", This, ppwszComputer);
+ TRACE("(%p)->(%p)\n", This, comp_name);
- if (!ppwszComputer)
+ if (!comp_name)
return E_INVALIDARG;
+ hr = ITaskService_get_TargetServer(This->service, &bstr);
+ if (hr != S_OK) return hr;
+
/* extra space for two '\' and a zero */
- buffer = CoTaskMemAlloc((MAX_COMPUTERNAME_LENGTH + 3) * sizeof(WCHAR));
+ buffer = CoTaskMemAlloc((SysStringLen(bstr) + 3) * sizeof(WCHAR));
if (buffer)
{
buffer[0] = '\\';
buffer[1] = '\\';
- if (GetComputerNameW(buffer + 2, &len))
- {
- *ppwszComputer = buffer;
- return S_OK;
- }
- CoTaskMemFree(buffer);
+ lstrcpyW(buffer + 2, bstr);
+ *comp_name = buffer;
+ hr = S_OK;
}
- *ppwszComputer = NULL;
- return HRESULT_FROM_WIN32(GetLastError());
+ else
+ {
+ *comp_name = NULL;
+ hr = E_OUTOFMEMORY;
+ }
+
+ SysFreeString(bstr);
+ return hr;
}
static HRESULT WINAPI MSTASK_ITaskScheduler_Enum(
@@ -346,13 +346,32 @@ static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl =
HRESULT TaskSchedulerConstructor(LPVOID *ppObj)
{
TaskSchedulerImpl *This;
+ ITaskService *service;
+ VARIANT v_null;
+ HRESULT hr;
+
TRACE("(%p)\n", ppObj);
+ hr = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskService, (void **)&service);
+ if (hr != S_OK) return hr;
+
+ V_VT(&v_null) = VT_NULL;
+ hr = ITaskService_Connect(service, v_null, v_null, v_null, v_null);
+ if (hr != S_OK)
+ {
+ ITaskService_Release(service);
+ return hr;
+ }
+
This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This)
+ {
+ ITaskService_Release(service);
return E_OUTOFMEMORY;
+ }
This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl;
+ This->service = service;
This->ref = 1;
*ppObj = &This->ITaskScheduler_iface;
--
2.16.2
1
0
March 13, 2018
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/Makefile.in | 2 +-
dlls/mstask/factory.c | 8 ++++++++
dlls/mstask/mstask_local.idl | 1 -
dlls/mstask/mstask_main.c | 11 +++++++----
dlls/mstask/mstask_private.h | 10 ----------
dlls/mstask/task.c | 8 ++++++++
dlls/mstask/task_scheduler.c | 14 +++++++++++---
dlls/mstask/task_trigger.c | 7 +++++++
8 files changed, 42 insertions(+), 19 deletions(-)
diff --git a/dlls/mstask/Makefile.in b/dlls/mstask/Makefile.in
index 55ab76dbbe..72a6db3eb7 100644
--- a/dlls/mstask/Makefile.in
+++ b/dlls/mstask/Makefile.in
@@ -1,5 +1,5 @@
MODULE = mstask.dll
-IMPORTS = uuid ole32
+IMPORTS = ole32
C_SRCS = \
factory.c \
diff --git a/dlls/mstask/factory.c b/dlls/mstask/factory.c
index f85a5f9c11..97a5113868 100644
--- a/dlls/mstask/factory.c
+++ b/dlls/mstask/factory.c
@@ -16,6 +16,14 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
diff --git a/dlls/mstask/mstask_local.idl b/dlls/mstask/mstask_local.idl
index 98e060c468..bf49728e66 100644
--- a/dlls/mstask/mstask_local.idl
+++ b/dlls/mstask/mstask_local.idl
@@ -16,7 +16,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#pragma makedep ident
#pragma makedep register
#include "mstask.idl"
diff --git a/dlls/mstask/mstask_main.c b/dlls/mstask/mstask_main.c
index aa6693d1e8..bb19b89da2 100644
--- a/dlls/mstask/mstask_main.c
+++ b/dlls/mstask/mstask_main.c
@@ -16,15 +16,18 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <stdio.h>
+#include <stdarg.h>
-#include "mstask_private.h"
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
#include "objbase.h"
#include "rpcproxy.h"
-
+#include "mstask.h"
+#include "mstask_private.h"
#include "wine/debug.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(mstask);
static HINSTANCE hInst;
diff --git a/dlls/mstask/mstask_private.h b/dlls/mstask/mstask_private.h
index 17c20fee43..9180e4a51f 100644
--- a/dlls/mstask/mstask_private.h
+++ b/dlls/mstask/mstask_private.h
@@ -19,16 +19,6 @@
#ifndef __MSTASK_PRIVATE_H__
#define __MSTASK_PRIVATE_H__
-#include <stdarg.h>
-
-#define COBJMACROS
-
-#include "windef.h"
-#include "winbase.h"
-#include "winuser.h"
-#include "ole2.h"
-#include "mstask.h"
-
extern LONG dll_ref DECLSPEC_HIDDEN;
typedef struct ClassFactoryImpl ClassFactoryImpl;
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index 97ae8b7b67..872e445b5e 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -16,6 +16,14 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
diff --git a/dlls/mstask/task_scheduler.c b/dlls/mstask/task_scheduler.c
index 1f367edb3d..1c2d227ddb 100644
--- a/dlls/mstask/task_scheduler.c
+++ b/dlls/mstask/task_scheduler.c
@@ -16,7 +16,15 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "corerror.h"
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "initguid.h"
+#include "objbase.h"
+#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
@@ -268,8 +276,8 @@ static HRESULT WINAPI MSTASK_ITaskScheduler_Activate(
{
TRACE("%p, %s, %s, %p: stub\n", iface, debugstr_w(pwszName),
debugstr_guid(riid), ppunk);
- FIXME("Partial stub always returning COR_E_FILENOTFOUND\n");
- return COR_E_FILENOTFOUND;
+ FIXME("Partial stub always returning ERROR_FILE_NOT_FOUND\n");
+ return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
static HRESULT WINAPI MSTASK_ITaskScheduler_Delete(
diff --git a/dlls/mstask/task_trigger.c b/dlls/mstask/task_trigger.c
index 448cf08708..9475e5608a 100644
--- a/dlls/mstask/task_trigger.c
+++ b/dlls/mstask/task_trigger.c
@@ -17,7 +17,14 @@
*/
#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
#include "winternl.h"
+#include "mstask.h"
#include "mstask_private.h"
#include "wine/debug.h"
--
2.16.2
1
0
March 13, 2018
Adds ntddk.h to be compatible with windows SDK.
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
include/ddk/ntifs.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h
index 32c9e30..29465e8 100644
--- a/include/ddk/ntifs.h
+++ b/include/ddk/ntifs.h
@@ -19,8 +19,24 @@
#ifndef __NTIFS_H__
#define __NTIFS_H__
+#include "ntddk.h"
+
typedef struct _EX_PUSH_LOCK EX_PUSH_LOCK, *PEX_PUSH_LOCK;
+typedef enum _FS_FILTER_SECTION_SYNC_TYPE
+{
+ SyncTypeOther = 0,
+ SyncTypeCreateSection
+} FS_FILTER_SECTION_SYNC_TYPE, *PFS_FILTER_SECTION_SYNC_TYPE;
+
+typedef struct _FS_FILTER_SECTION_SYNC_OUTPUT
+{
+ ULONG StructureSize;
+ ULONG SizeReturned;
+ ULONG Flags;
+ ULONG DesiredReadAlignment;
+} FS_FILTER_SECTION_SYNC_OUTPUT, *PFS_FILTER_SECTION_SYNC_OUTPUT;
+
typedef struct _KQUEUE
{
DISPATCHER_HEADER Header;
--
1.9.1
1
0
March 13, 2018
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
include/ddk/wdm.h | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 834f208..b47995f 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -44,6 +44,7 @@ typedef ULONG_PTR KSPIN_LOCK, *PKSPIN_LOCK;
typedef ULONG_PTR ERESOURCE_THREAD;
typedef ERESOURCE_THREAD *PERESOURCE_THREAD;
+typedef struct _FILE_GET_QUOTA_INFORMATION *PFILE_GET_QUOTA_INFORMATION;
struct _KDPC;
struct _KAPC;
@@ -1223,6 +1224,99 @@ typedef struct _KLOCK_QUEUE_HANDLE {
typedef NTSTATUS (NTAPI EX_CALLBACK_FUNCTION)(void *CallbackContext, void *Argument1, void *Argument2);
typedef EX_CALLBACK_FUNCTION *PEX_CALLBACK_FUNCTION;
+typedef ULONG OB_OPERATION;
+
+typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION {
+ ACCESS_MASK DesiredAccess;
+ ACCESS_MASK OriginalDesiredAccess;
+} OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION;
+
+typedef struct _OB_PRE_DUPLICATE_HANDLE_INFORMATION {
+ ACCESS_MASK DesiredAccess;
+ ACCESS_MASK OriginalDesiredAccess;
+ void *SourceProcess;
+ void *TargetProcess;
+} OB_PRE_DUPLICATE_HANDLE_INFORMATION, *POB_PRE_DUPLICATE_HANDLE_INFORMATION;
+
+typedef union _OB_PRE_OPERATION_PARAMETERS {
+ OB_PRE_CREATE_HANDLE_INFORMATION CreateHandleInformation;
+ OB_PRE_DUPLICATE_HANDLE_INFORMATION DuplicateHandleInformation;
+} OB_PRE_OPERATION_PARAMETERS, *POB_PRE_OPERATION_PARAMETERS;
+
+typedef struct _OB_PRE_OPERATION_INFORMATION {
+ OB_OPERATION Operation;
+ union {
+ ULONG Flags;
+ struct {
+ ULONG KernelHandle:1;
+ ULONG Reserved:31;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ void *Object;
+ POBJECT_TYPE ObjectType;
+ void *CallContext;
+ POB_PRE_OPERATION_PARAMETERS Parameters;
+} OB_PRE_OPERATION_INFORMATION, *POB_PRE_OPERATION_INFORMATION;
+
+typedef struct _OB_POST_CREATE_HANDLE_INFORMATION {
+ ACCESS_MASK GrantedAccess;
+} OB_POST_CREATE_HANDLE_INFORMATION, *POB_POST_CREATE_HANDLE_INFORMATION;
+
+typedef struct _OB_POST_DUPLICATE_HANDLE_INFORMATION {
+ ACCESS_MASK GrantedAccess;
+} OB_POST_DUPLICATE_HANDLE_INFORMATION, *POB_POST_DUPLICATE_HANDLE_INFORMATION;
+
+typedef union _OB_POST_OPERATION_PARAMETERS {
+ OB_POST_CREATE_HANDLE_INFORMATION CreateHandleInformation;
+ OB_POST_DUPLICATE_HANDLE_INFORMATION DuplicateHandleInformation;
+} OB_POST_OPERATION_PARAMETERS, *POB_POST_OPERATION_PARAMETERS;
+
+typedef struct _OB_POST_OPERATION_INFORMATION {
+ OB_OPERATION Operation;
+ union {
+ ULONG Flags;
+ struct {
+ ULONG KernelHandle:1;
+ ULONG Reserved:31;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ void *Object;
+ POBJECT_TYPE ObjectType;
+ void *CallContext;
+ NTSTATUS ReturnStatus;
+ POB_POST_OPERATION_PARAMETERS Parameters;
+} OB_POST_OPERATION_INFORMATION,*POB_POST_OPERATION_INFORMATION;
+
+typedef enum _OB_PREOP_CALLBACK_STATUS {
+ OB_PREOP_SUCCESS
+} OB_PREOP_CALLBACK_STATUS, *POB_PREOP_CALLBACK_STATUS;
+
+typedef OB_PREOP_CALLBACK_STATUS (WINAPI *POB_PRE_OPERATION_CALLBACK)(void *, POB_PRE_OPERATION_INFORMATION);
+typedef void (WINAPI *POB_POST_OPERATION_CALLBACK)(void *, POB_POST_OPERATION_INFORMATION);
+
+typedef struct _OB_OPERATION_REGISTRATION {
+ POBJECT_TYPE *ObjectType;
+ OB_OPERATION Operations;
+ POB_PRE_OPERATION_CALLBACK PreOperation;
+ POB_POST_OPERATION_CALLBACK PostOperation;
+} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;
+
+typedef struct _OB_CALLBACK_REGISTRATION {
+ USHORT Version;
+ USHORT OperationRegistrationCount;
+ UNICODE_STRING Altitude;
+ void *RegistrationContext;
+ OB_OPERATION_REGISTRATION *OperationRegistration;
+} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;
+
+#define OB_FLT_REGISTRATION_VERSION_0100 0x0100
+#define OB_FLT_REGISTRATION_VERSION OB_FLT_REGISTRATION_VERSION_0100
+
+typedef enum _DIRECTORY_NOTIFY_INFORMATION_CLASS {
+ DirectoryNotifyInformation = 1,
+ DirectoryNotifyExtendedInformation
+} DIRECTORY_NOTIFY_INFORMATION_CLASS, *PDIRECTORY_NOTIFY_INFORMATION_CLASS;
+
NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
#ifdef NONAMELESSUNION
--
1.9.1
1
0
March 13, 2018
From: Andrew Wesie <awesie(a)gmail.com>
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
This patch series is a (slight) splitting of that originally sent by Andrew
Wesie here:
https://www.winehq.org/pipermail/wine-patches/2016-November/155819.html
This test apparently fell off the list due to test failures which were never
resolved.
v2: remove unused typedefs
dlls/ntdll/tests/exception.c | 282 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 282 insertions(+)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 2308472..a76fce6 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -111,6 +111,36 @@ typedef struct _JUMP_BUFFER
SETJMP_FLOAT128 Xmm15;
} _JUMP_BUFFER;
+typedef union _UNWIND_CODE
+{
+ struct
+ {
+ BYTE CodeOffset;
+ BYTE UnwindOp : 4;
+ BYTE OpInfo : 4;
+ } s;
+ USHORT FrameOffset;
+} UNWIND_CODE;
+
+typedef struct _UNWIND_INFO
+{
+ BYTE Version : 3;
+ BYTE Flags : 5;
+ BYTE SizeOfProlog;
+ BYTE CountOfCodes;
+ BYTE FrameRegister : 4;
+ BYTE FrameOffset : 4;
+ UNWIND_CODE UnwindCode[1]; /* actually CountOfCodes (aligned) */
+/*
+ * union
+ * {
+ * OPTIONAL ULONG ExceptionHandler;
+ * OPTIONAL ULONG FunctionEntry;
+ * };
+ * OPTIONAL ULONG ExceptionData[];
+ */
+} UNWIND_INFO;
+
static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
static BOOLEAN (CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
static BOOLEAN (CDECL *pRtlInstallFunctionTableCallback)(DWORD64, DWORD64, DWORD, PGET_RUNTIME_FUNCTION_CALLBACK, PVOID, PCWSTR);
@@ -2150,6 +2180,257 @@ static void test___C_specific_handler(void)
ok(dispatch.ScopeIndex == 1, "dispatch.ScopeIndex = %d\n", dispatch.ScopeIndex);
}
+/* This is heavily based on the i386 exception tests. */
+static const struct exception
+{
+ BYTE code[18]; /* asm code */
+ BYTE offset; /* offset of faulting instruction */
+ BYTE length; /* length of faulting instruction */
+ NTSTATUS status; /* expected status code */
+ DWORD nb_params; /* expected number of parameters */
+ ULONG64 params[4]; /* expected parameters */
+ NTSTATUS alt_status; /* alternative status code */
+ DWORD alt_nb_params; /* alternative number of parameters */
+ ULONG64 alt_params[4]; /* alternative parameters */
+} exceptions[] =
+{
+/* 0 */
+ /* test some privileged instructions */
+ { { 0xfb, 0xc3 }, /* 0: sti; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6c, 0xc3 }, /* 1: insb (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6d, 0xc3 }, /* 2: insl (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6e, 0xc3 }, /* 3: outsb (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6f, 0xc3 }, /* 4: outsl (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 5 */
+ { { 0xe4, 0x11, 0xc3 }, /* 5: inb $0x11,%al; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe5, 0x11, 0xc3 }, /* 6: inl $0x11,%eax; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe6, 0x11, 0xc3 }, /* 7: outb %al,$0x11; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe7, 0x11, 0xc3 }, /* 8: outl %eax,$0x11; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xed, 0xc3 }, /* 9: inl (%dx),%eax; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 10 */
+ { { 0xee, 0xc3 }, /* 10: outb %al,(%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xef, 0xc3 }, /* 11: outl %eax,(%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xf4, 0xc3 }, /* 12: hlt; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xfa, 0xc3 }, /* 13: cli; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test iret to invalid selector */
+ { { 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xcf, 0x83, 0xc4, 0x18, 0xc3 },
+ /* 15: pushq $0; pushq $0; pushq $0; iret; addl $24,%esp; ret */
+ 6, 1, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+/* 15 */
+ /* test loading an invalid selector */
+ { { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 }, /* 16: mov $beef,%ax; mov %ax,%gs; ret */
+ 5, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xbee8 } }, /* 0xbee8 or 0xffffffff */
+
+ /* test overlong instruction (limit is 15 bytes) */
+ { { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
+ 0, 16, STATUS_ILLEGAL_INSTRUCTION, 0, { 0 },
+ STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test invalid interrupt */
+ { { 0xcd, 0xff, 0xc3 }, /* int $0xff; ret */
+ 0, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test moves to/from Crx */
+ { { 0x0f, 0x20, 0xc0, 0xc3 }, /* movl %cr0,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x20, 0xe0, 0xc3 }, /* movl %cr4,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 20 */
+ { { 0x0f, 0x22, 0xc0, 0xc3 }, /* movl %eax,%cr0; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x22, 0xe0, 0xc3 }, /* movl %eax,%cr4; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test moves to/from Drx */
+ { { 0x0f, 0x21, 0xc0, 0xc3 }, /* movl %dr0,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x21, 0xc8, 0xc3 }, /* movl %dr1,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x21, 0xf8, 0xc3 }, /* movl %dr7,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 25 */
+ { { 0x0f, 0x23, 0xc0, 0xc3 }, /* movl %eax,%dr0; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x23, 0xc8, 0xc3 }, /* movl %eax,%dr1; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x23, 0xf8, 0xc3 }, /* movl %eax,%dr7; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test memory reads */
+ { { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffc,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffc } },
+ { { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffd,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffd } },
+/* 30 */
+ { { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffe,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffe } },
+ { { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xffffffffffffffff,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test memory writes */
+ { { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffc; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffc } },
+ { { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffd; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffd } },
+ { { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffe; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffe } },
+/* 35 */
+ { { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xffffffffffffffff; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffffffffffff } },
+#if 0
+ { { 0xf1, 0x90, 0xc3 }, /* icebp; nop; ret */
+ 1, 1, STATUS_SINGLE_STEP, 0 },
+#endif
+ { { 0xcd, 0x2c, 0xc3 },
+ 0, 2, STATUS_ASSERTION_FAILURE, 0 },
+};
+
+static int got_exception;
+
+static void run_exception_test(void *handler, const void* context,
+ const void *code, unsigned int code_size,
+ DWORD access)
+{
+ unsigned char buf[8 + 6 + 8 + 8];
+ RUNTIME_FUNCTION runtime_func;
+ UNWIND_INFO *unwind = (UNWIND_INFO *)buf;
+ void (*func)(void) = code_mem;
+ DWORD oldaccess, oldaccess2;
+
+ runtime_func.BeginAddress = 0;
+ runtime_func.EndAddress = code_size;
+ runtime_func.UnwindData = 0x1000;
+
+ unwind->Version = 1;
+ unwind->Flags = UNW_FLAG_EHANDLER;
+ unwind->SizeOfProlog = 0;
+ unwind->CountOfCodes = 0;
+ unwind->FrameRegister = 0;
+ unwind->FrameOffset = 0;
+ *(ULONG *)&buf[4] = 0x1010;
+ *(const void **)&buf[8] = context;
+
+ /* jmp near */
+ buf[16] = 0xff;
+ buf[17] = 0x25;
+ *(ULONG *)&buf[18] = 0;
+ *(void **)&buf[22] = handler;
+
+ memcpy((unsigned char *)code_mem + 0x1000, buf, sizeof(buf));
+ memcpy(code_mem, code, code_size);
+ if(access)
+ VirtualProtect(code_mem, code_size, access, &oldaccess);
+
+ pRtlAddFunctionTable(&runtime_func, 1, (ULONG_PTR)code_mem);
+ func();
+ pRtlDeleteFunctionTable(&runtime_func);
+
+ if(access)
+ VirtualProtect(code_mem, code_size, oldaccess, &oldaccess2);
+}
+
+static DWORD WINAPI handler( EXCEPTION_RECORD *rec, ULONG64 frame,
+ CONTEXT *context, DISPATCHER_CONTEXT *dispatcher )
+{
+ const struct exception *except = *(const struct exception **)(dispatcher->HandlerData);
+ unsigned int i, parameter_count, entry = except - exceptions;
+
+ got_exception++;
+ trace( "exception %u: %x flags:%x addr:%p\n",
+ entry, rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
+
+todo_wine_if( rec->ExceptionCode != except->status &&
+ rec->ExceptionCode != except->alt_status )
+ ok( rec->ExceptionCode == except->status ||
+ (except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
+ "%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
+ ok( context->Rip == (DWORD_PTR)code_mem + except->offset,
+ "%u: Unexpected eip %#lx/%#lx\n", entry,
+ context->Rip, (DWORD_PTR)code_mem + except->offset );
+ ok( rec->ExceptionAddress == (char*)context->Rip ||
+ (rec->ExceptionCode == STATUS_BREAKPOINT && rec->ExceptionAddress == (char*)context->Rip + 1),
+ "%u: Unexpected exception address %p/%p\n", entry,
+ rec->ExceptionAddress, (char*)context->Rip );
+
+ if (except->status == STATUS_BREAKPOINT && is_wow64)
+ parameter_count = 1;
+ else if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
+ parameter_count = except->nb_params;
+ else
+ parameter_count = except->alt_nb_params;
+
+todo_wine_if( rec->NumberParameters != parameter_count )
+ ok( rec->NumberParameters == parameter_count,
+ "%u: Unexpected parameter count %u/%u\n", entry, rec->NumberParameters, parameter_count );
+
+ /* Most CPUs (except Intel Core apparently) report a segment limit violation */
+ /* instead of page faults for accesses beyond 0xffffffffffffffff */
+ if (except->nb_params == 2 && except->params[1] >= 0xfffffffffffffffd)
+ {
+ if (rec->ExceptionInformation[0] == 0 && rec->ExceptionInformation[1] == 0xffffffffffffffff)
+ goto skip_params;
+ }
+
+ /* Seems that both 0xbee8 and 0xfffffffffffffffff can be returned in windows */
+ if (except->nb_params == 2 && rec->NumberParameters == 2
+ && except->params[1] == 0xbee8 && rec->ExceptionInformation[1] == 0xffffffffffffffff
+ && except->params[0] == rec->ExceptionInformation[0])
+ {
+ goto skip_params;
+ }
+
+ if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
+ {
+ for (i = 0; i < rec->NumberParameters; i++)
+ ok( rec->ExceptionInformation[i] == except->params[i],
+ "%u: Wrong parameter %d: %lx/%lx\n",
+ entry, i, rec->ExceptionInformation[i], except->params[i] );
+ }
+ else
+ {
+ for (i = 0; i < rec->NumberParameters; i++)
+ ok( rec->ExceptionInformation[i] == except->alt_params[i],
+ "%u: Wrong parameter %d: %lx/%lx\n",
+ entry, i, rec->ExceptionInformation[i], except->alt_params[i] );
+ }
+
+skip_params:
+ /* don't handle exception if it's not the address we expected */
+ if (context->Rip != (DWORD_PTR)code_mem + except->offset) return ExceptionContinueSearch;
+
+ context->Rip += except->length;
+ return ExceptionContinueExecution;
+}
+
+static void test_prot_fault(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(exceptions)/sizeof(exceptions[0]); i++)
+ {
+ got_exception = 0;
+ run_exception_test(handler, &exceptions[i], &exceptions[i].code,
+ sizeof(exceptions[i].code), 0);
+ ok( got_exception == (exceptions[i].status != 0),
+ "%u: bad exception count %d\n", i, got_exception );
+ }
+}
+
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
@@ -2744,6 +3025,7 @@ START_TEST(exception)
test_virtual_unwind();
test___C_specific_handler();
test_restore_context();
+ test_prot_fault();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
test_dynamic_unwind();
--
2.7.4
1
4
From: Andrew Wesie <awesie(a)gmail.com>
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
This patch series is a (slight) splitting of that originally sent by Andrew
Wesie here:
https://www.winehq.org/pipermail/wine-patches/2016-November/155819.html
This test apparently fell off the list due to test failures which were never
resolved.
dlls/ntdll/tests/exception.c | 294 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 294 insertions(+)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 2308472..44d3097 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -111,6 +111,49 @@ typedef struct _JUMP_BUFFER
SETJMP_FLOAT128 Xmm15;
} _JUMP_BUFFER;
+typedef enum _UNWIND_OP_CODES
+{
+ UWOP_PUSH_NONVOL = 0,
+ UWOP_ALLOC_LARGE,
+ UWOP_ALLOC_SMALL,
+ UWOP_SET_FPREG,
+ UWOP_SAVE_NONVOL,
+ UWOP_SAVE_NONVOL_FAR,
+ UWOP_SAVE_XMM128,
+ UWOP_SAVE_XMM128_FAR,
+ UWOP_PUSH_MACHFRAME
+} UNWIND_CODE_OPS;
+
+typedef union _UNWIND_CODE
+{
+ struct
+ {
+ BYTE CodeOffset;
+ BYTE UnwindOp : 4;
+ BYTE OpInfo : 4;
+ } u;
+ USHORT FrameOffset;
+} UNWIND_CODE, *PUNWIND_CODE;
+
+typedef struct _UNWIND_INFO
+{
+ BYTE Version : 3;
+ BYTE Flags : 5;
+ BYTE SizeOfProlog;
+ BYTE CountOfCodes;
+ BYTE FrameRegister : 4;
+ BYTE FrameOffset : 4;
+ UNWIND_CODE UnwindCode[1]; /* actually CountOfCodes (aligned) */
+/*
+ * union
+ * {
+ * OPTIONAL ULONG ExceptionHandler;
+ * OPTIONAL ULONG FunctionEntry;
+ * };
+ * OPTIONAL ULONG ExceptionData[];
+ */
+} UNWIND_INFO, *PUNWIND_INFO;
+
static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
static BOOLEAN (CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
static BOOLEAN (CDECL *pRtlInstallFunctionTableCallback)(DWORD64, DWORD64, DWORD, PGET_RUNTIME_FUNCTION_CALLBACK, PVOID, PCWSTR);
@@ -2150,6 +2193,256 @@ static void test___C_specific_handler(void)
ok(dispatch.ScopeIndex == 1, "dispatch.ScopeIndex = %d\n", dispatch.ScopeIndex);
}
+/* This is heavily based on the i386 exception tests. */
+static const struct exception
+{
+ BYTE code[18]; /* asm code */
+ BYTE offset; /* offset of faulting instruction */
+ BYTE length; /* length of faulting instruction */
+ NTSTATUS status; /* expected status code */
+ DWORD nb_params; /* expected number of parameters */
+ ULONG64 params[4]; /* expected parameters */
+ NTSTATUS alt_status; /* alternative status code */
+ DWORD alt_nb_params; /* alternative number of parameters */
+ ULONG64 alt_params[4]; /* alternative parameters */
+} exceptions[] =
+{
+/* 0 */
+ /* test some privileged instructions */
+ { { 0xfb, 0xc3 }, /* 0: sti; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6c, 0xc3 }, /* 1: insb (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6d, 0xc3 }, /* 2: insl (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6e, 0xc3 }, /* 3: outsb (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x6f, 0xc3 }, /* 4: outsl (%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 5 */
+ { { 0xe4, 0x11, 0xc3 }, /* 5: inb $0x11,%al; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe5, 0x11, 0xc3 }, /* 6: inl $0x11,%eax; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe6, 0x11, 0xc3 }, /* 7: outb %al,$0x11; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xe7, 0x11, 0xc3 }, /* 8: outl %eax,$0x11; ret */
+ 0, 2, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xed, 0xc3 }, /* 9: inl (%dx),%eax; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 10 */
+ { { 0xee, 0xc3 }, /* 10: outb %al,(%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xef, 0xc3 }, /* 11: outl %eax,(%dx); ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xf4, 0xc3 }, /* 12: hlt; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0xfa, 0xc3 }, /* 13: cli; ret */
+ 0, 1, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test iret to invalid selector */
+ { { 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xcf, 0x83, 0xc4, 0x18, 0xc3 },
+ /* 15: pushq $0; pushq $0; pushq $0; iret; addl $24,%esp; ret */
+ 6, 1, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+/* 15 */
+ /* test loading an invalid selector */
+ { { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 }, /* 16: mov $beef,%ax; mov %ax,%gs; ret */
+ 5, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xbee8 } }, /* 0xbee8 or 0xffffffff */
+
+ /* test overlong instruction (limit is 15 bytes) */
+ { { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
+ 0, 16, STATUS_ILLEGAL_INSTRUCTION, 0, { 0 },
+ STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test invalid interrupt */
+ { { 0xcd, 0xff, 0xc3 }, /* int $0xff; ret */
+ 0, 2, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test moves to/from Crx */
+ { { 0x0f, 0x20, 0xc0, 0xc3 }, /* movl %cr0,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x20, 0xe0, 0xc3 }, /* movl %cr4,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 20 */
+ { { 0x0f, 0x22, 0xc0, 0xc3 }, /* movl %eax,%cr0; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x22, 0xe0, 0xc3 }, /* movl %eax,%cr4; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test moves to/from Drx */
+ { { 0x0f, 0x21, 0xc0, 0xc3 }, /* movl %dr0,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x21, 0xc8, 0xc3 }, /* movl %dr1,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x21, 0xf8, 0xc3 }, /* movl %dr7,%eax; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+/* 25 */
+ { { 0x0f, 0x23, 0xc0, 0xc3 }, /* movl %eax,%dr0; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x23, 0xc8, 0xc3 }, /* movl %eax,%dr1; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+ { { 0x0f, 0x23, 0xf8, 0xc3 }, /* movl %eax,%dr7; ret */
+ 0, 3, STATUS_PRIVILEGED_INSTRUCTION, 0 },
+
+ /* test memory reads */
+ { { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffc,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffc } },
+ { { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffd,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffd } },
+/* 30 */
+ { { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xfffffffffffffffe,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xfffffffffffffffe } },
+ { { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl 0xffffffffffffffff,%eax; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 0, 0xffffffffffffffff } },
+
+ /* test memory writes */
+ { { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffc; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffc } },
+ { { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffd; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffd } },
+ { { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xfffffffffffffffe; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xfffffffffffffffe } },
+/* 35 */
+ { { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 }, /* movl %eax,0xffffffffffffffff; ret */
+ 0, 9, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffffffffffff } },
+#if 0
+ { { 0xf1, 0x90, 0xc3 }, /* icebp; nop; ret */
+ 1, 1, STATUS_SINGLE_STEP, 0 },
+#endif
+ { { 0xcd, 0x2c, 0xc3 },
+ 0, 2, STATUS_ASSERTION_FAILURE, 0 },
+};
+
+static int got_exception;
+
+static void run_exception_test(void *handler, const void* context,
+ const void *code, unsigned int code_size,
+ DWORD access)
+{
+ unsigned char buf[8 + 6 + 8 + 8];
+ RUNTIME_FUNCTION runtime_func;
+ UNWIND_INFO *unwind = (UNWIND_INFO *)buf;
+ void (*func)(void) = code_mem;
+ DWORD oldaccess, oldaccess2;
+
+ runtime_func.BeginAddress = 0;
+ runtime_func.EndAddress = code_size;
+ runtime_func.UnwindData = 0x1000;
+
+ unwind->Version = 1;
+ unwind->Flags = UNW_FLAG_EHANDLER;
+ unwind->SizeOfProlog = 0;
+ unwind->CountOfCodes = 0;
+ unwind->FrameRegister = 0;
+ unwind->FrameOffset = 0;
+ *(ULONG *)&buf[4] = 0x1010;
+ *(const void **)&buf[8] = context;
+
+ buf[16] = 0xff;
+ buf[17] = 0x25;
+ *(ULONG *)&buf[18] = 0;
+ *(void **)&buf[22] = handler;
+
+ memcpy((unsigned char *)code_mem + 0x1000, buf, sizeof(buf));
+ memcpy(code_mem, code, code_size);
+ if(access)
+ VirtualProtect(code_mem, code_size, access, &oldaccess);
+
+ pRtlAddFunctionTable(&runtime_func, 1, (ULONG_PTR)code_mem);
+ func();
+ pRtlDeleteFunctionTable(&runtime_func);
+
+ if(access)
+ VirtualProtect(code_mem, code_size, oldaccess, &oldaccess2);
+}
+
+static DWORD WINAPI handler( EXCEPTION_RECORD *rec, ULONG64 frame,
+ CONTEXT *context, DISPATCHER_CONTEXT *dispatcher )
+{
+ const struct exception *except = *(const struct exception **)(dispatcher->HandlerData);
+ unsigned int i, parameter_count, entry = except - exceptions;
+
+ got_exception++;
+ trace( "exception %u: %x flags:%x addr:%p\n",
+ entry, rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
+
+todo_wine_if( rec->ExceptionCode != except->status &&
+ rec->ExceptionCode != except->alt_status )
+ ok( rec->ExceptionCode == except->status ||
+ (except->alt_status != 0 && rec->ExceptionCode == except->alt_status),
+ "%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
+ ok( context->Rip == (DWORD_PTR)code_mem + except->offset,
+ "%u: Unexpected eip %#lx/%#lx\n", entry,
+ context->Rip, (DWORD_PTR)code_mem + except->offset );
+ ok( rec->ExceptionAddress == (char*)context->Rip ||
+ (rec->ExceptionCode == STATUS_BREAKPOINT && rec->ExceptionAddress == (char*)context->Rip + 1),
+ "%u: Unexpected exception address %p/%p\n", entry,
+ rec->ExceptionAddress, (char*)context->Rip );
+
+ if (except->status == STATUS_BREAKPOINT && is_wow64)
+ parameter_count = 1;
+ else if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
+ parameter_count = except->nb_params;
+ else
+ parameter_count = except->alt_nb_params;
+
+todo_wine_if( rec->NumberParameters != parameter_count )
+ ok( rec->NumberParameters == parameter_count,
+ "%u: Unexpected parameter count %u/%u\n", entry, rec->NumberParameters, parameter_count );
+
+ /* Most CPUs (except Intel Core apparently) report a segment limit violation */
+ /* instead of page faults for accesses beyond 0xffffffffffffffff */
+ if (except->nb_params == 2 && except->params[1] >= 0xfffffffffffffffd)
+ {
+ if (rec->ExceptionInformation[0] == 0 && rec->ExceptionInformation[1] == 0xffffffffffffffff)
+ goto skip_params;
+ }
+
+ /* Seems that both 0xbee8 and 0xfffffffffffffffff can be returned in windows */
+ if (except->nb_params == 2 && rec->NumberParameters == 2
+ && except->params[1] == 0xbee8 && rec->ExceptionInformation[1] == 0xffffffffffffffff
+ && except->params[0] == rec->ExceptionInformation[0])
+ {
+ goto skip_params;
+ }
+
+ if (except->alt_status == 0 || rec->ExceptionCode != except->alt_status)
+ {
+ for (i = 0; i < rec->NumberParameters; i++)
+ ok( rec->ExceptionInformation[i] == except->params[i],
+ "%u: Wrong parameter %d: %lx/%lx\n",
+ entry, i, rec->ExceptionInformation[i], except->params[i] );
+ }
+ else
+ {
+ for (i = 0; i < rec->NumberParameters; i++)
+ ok( rec->ExceptionInformation[i] == except->alt_params[i],
+ "%u: Wrong parameter %d: %lx/%lx\n",
+ entry, i, rec->ExceptionInformation[i], except->alt_params[i] );
+ }
+
+skip_params:
+ /* don't handle exception if it's not the address we expected */
+ if (context->Rip != (DWORD_PTR)code_mem + except->offset) return ExceptionContinueSearch;
+
+ context->Rip += except->length;
+ return ExceptionContinueExecution;
+}
+
+static void test_prot_fault(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(exceptions)/sizeof(exceptions[0]); i++)
+ {
+ got_exception = 0;
+ run_exception_test(handler, &exceptions[i], &exceptions[i].code,
+ sizeof(exceptions[i].code), 0);
+ ok( got_exception == (exceptions[i].status != 0),
+ "%u: bad exception count %d\n", i, got_exception );
+ }
+}
+
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
@@ -2744,6 +3037,7 @@ START_TEST(exception)
test_virtual_unwind();
test___C_specific_handler();
test_restore_context();
+ test_prot_fault();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
test_dynamic_unwind();
--
2.7.4
2
6