Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- 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
- 7 participants
- 84546 discussions
[PATCH vkd3d 5/5] vkd3d-shader: Merge the vkd3d_shader_descriptor_type and vkd3d_shader_descriptor_range_type enumerations.
by Henri Verbeet Aug. 4, 2020
by Henri Verbeet Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 23 ++++++-----------------
libs/vkd3d-shader/dxbc.c | 16 ++++++++--------
libs/vkd3d-shader/spirv.c | 5 +++--
3 files changed, 17 insertions(+), 27 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 26a2110..de2c0c7 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -88,11 +88,10 @@ struct vkd3d_shader_code
enum vkd3d_shader_descriptor_type
{
- VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN,
- VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, /* cb# */
- VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, /* t# */
- VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, /* u# */
- VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, /* s# */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV = 0x0, /* t# */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV = 0x1, /* u# */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_CBV = 0x2, /* cb# */
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER = 0x3, /* s# */
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_TYPE),
};
@@ -450,19 +449,9 @@ struct vkd3d_shader_static_sampler_desc
enum vkd3d_shader_visibility shader_visibility;
};
-enum vkd3d_shader_descriptor_range_type
-{
- VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SRV = 0x0,
- VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_UAV = 0x1,
- VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_CBV = 0x2,
- VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SAMPLER = 0x3,
-
- VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE),
-};
-
struct vkd3d_shader_descriptor_range
{
- enum vkd3d_shader_descriptor_range_type range_type;
+ enum vkd3d_shader_descriptor_type range_type;
unsigned int descriptor_count;
unsigned int base_shader_register;
unsigned int register_space;
@@ -558,7 +547,7 @@ enum vkd3d_shader_descriptor_range_flags
struct vkd3d_shader_descriptor_range1
{
- enum vkd3d_shader_descriptor_range_type range_type;
+ enum vkd3d_shader_descriptor_type range_type;
unsigned int descriptor_count;
unsigned int base_shader_register;
unsigned int register_space;
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index df5f6a2..1aa8a5c 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -3143,13 +3143,13 @@ static int validate_descriptor_table_v_1_0(const struct vkd3d_shader_root_descri
{
const struct vkd3d_shader_descriptor_range *r = &descriptor_table->descriptor_ranges[i];
- if (r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SRV
- || r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_UAV
- || r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_CBV)
+ if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV)
{
have_srv_uav_cbv = true;
}
- else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SAMPLER)
+ else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
{
have_sampler = true;
}
@@ -3184,13 +3184,13 @@ static int validate_descriptor_table_v_1_1(const struct vkd3d_shader_root_descri
{
const struct vkd3d_shader_descriptor_range1 *r = &descriptor_table->descriptor_ranges[i];
- if (r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SRV
- || r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_UAV
- || r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_CBV)
+ if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV
+ || r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV)
{
have_srv_uav_cbv = true;
}
- else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_RANGE_TYPE_SAMPLER)
+ else if (r->range_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
{
have_sampler = true;
}
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 4d1826f..9ef0430 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -2364,7 +2364,6 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
struct vkd3d_shader_descriptor_binding binding;
unsigned int i;
- descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN;
if (reg->type == VKD3DSPR_CONSTBUFFER)
descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
else if (reg->type == VKD3DSPR_RESOURCE)
@@ -2378,6 +2377,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
FIXME("Unhandled register type %#x.\n", reg->type);
vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE,
"Encountered invalid/unhandled register type %#x.", reg->type);
+ goto done;
}
resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER
@@ -2406,7 +2406,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
"Could not find descriptor binding for UAV counter %u, space %u.", reg_idx, register_space);
}
}
- else if (descriptor_type != VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN)
+ else
{
for (i = 0; i < shader_interface->binding_count; ++i)
{
@@ -2432,6 +2432,7 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
}
}
+done:
binding.set = 0;
binding.binding = compiler->binding_idx++;
return binding;
--
2.11.0
1
0
[PATCH vkd3d 3/5] vkd3d-shader: Allow plain storage buffers to be used for buffer UAVs.
by Henri Verbeet Aug. 4, 2020
by Henri Verbeet Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
include/vkd3d_shader.h | 13 ++
libs/vkd3d-shader/spirv.c | 387 ++++++++++++++++++++++++++++++++++++----------
2 files changed, 321 insertions(+), 79 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index 140744c..26a2110 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -40,9 +40,22 @@ enum vkd3d_shader_structure_type
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
};
+/* This also affects UAV counters in Vulkan environments. In OpenGL
+ * environments, atomic counter buffers are always used for UAV counters. */
+enum vkd3d_shader_compile_option_buffer_uav
+{
+ /* Use buffer textures for buffer UAVs, this is the default. */
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_TEXEL_BUFFER = 0x00000000,
+ /* Use storage buffers for buffer UAVs. */
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_BUFFER = 0x00000001,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV),
+};
+
enum vkd3d_shader_compile_option_name
{
VKD3D_SHADER_COMPILE_OPTION_STRIP_DEBUG = 0x00000001,
+ VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV = 0x00000002, /* vkd3d_shader_compile_option_buffer_uav */
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
};
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 9af672b..4d1826f 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -965,6 +965,17 @@ static uint32_t vkd3d_spirv_get_op_type_array(struct vkd3d_spirv_builder *builde
vkd3d_spirv_build_op_type_array);
}
+static uint32_t vkd3d_spirv_build_op_type_runtime_array(struct vkd3d_spirv_builder *builder, uint32_t element_type)
+{
+ return vkd3d_spirv_build_op_r1(builder, &builder->global_stream, SpvOpTypeRuntimeArray, element_type);
+}
+
+static uint32_t vkd3d_spirv_get_op_type_runtime_array(struct vkd3d_spirv_builder *builder, uint32_t element_type)
+{
+ return vkd3d_spirv_build_once1(builder, SpvOpTypeRuntimeArray,
+ element_type, vkd3d_spirv_build_op_type_runtime_array);
+}
+
static uint32_t vkd3d_spirv_build_op_type_struct(struct vkd3d_spirv_builder *builder,
uint32_t *members, unsigned int member_count)
{
@@ -1517,6 +1528,13 @@ static void vkd3d_spirv_build_op_image_write(struct vkd3d_spirv_builder *builder
image_id, coordinate_id, texel_id);
}
+static uint32_t vkd3d_spirv_build_op_array_length(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t struct_id, uint32_t member_id)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpArrayLength, result_type, struct_id, member_id);
+}
+
static uint32_t vkd3d_spirv_build_op_image_query_size_lod(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t image_id, uint32_t lod_id)
{
@@ -2047,6 +2065,7 @@ struct vkd3d_dxbc_compiler
bool failed;
bool strip_debug;
+ bool ssbo_uavs;
struct rb_tree symbol_table;
uint32_t temp_id;
@@ -2168,6 +2187,15 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
compiler->strip_debug = !!option->value;
break;
+ case VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV:
+ if (option->value == VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_TEXEL_BUFFER)
+ compiler->ssbo_uavs = false;
+ else if (option->value == VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_BUFFER)
+ compiler->ssbo_uavs = true;
+ else
+ WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name);
+ break;
+
default:
WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value);
break;
@@ -2207,6 +2235,12 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
return compiler;
}
+static bool vkd3d_dxbc_compiler_use_storage_buffer(const struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_symbol_resource_data *resource)
+{
+ return compiler->ssbo_uavs && resource->resource_type_info->resource_type == VKD3D_SHADER_RESOURCE_BUFFER;
+}
+
static enum vkd3d_shader_spirv_environment vkd3d_dxbc_compiler_get_target_environment(
const struct vkd3d_dxbc_compiler *compiler)
{
@@ -5322,8 +5356,28 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
return;
}
- type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space,
- register_index, resource_type_info, sampled_type, structure_stride || raw, 0);
+ if (compiler->ssbo_uavs && is_uav && resource_type == VKD3D_SHADER_RESOURCE_BUFFER)
+ {
+ uint32_t array_type_id, struct_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, sampled_type, 1);
+
+ array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id);
+ vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0);
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
+
+ type_id = struct_id;
+ storage_class = SpvStorageClassUniform;
+ }
+ else
+ {
+ type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space,
+ register_index, resource_type_info, sampled_type, structure_stride || raw, 0);
+ }
+
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0);
@@ -5347,13 +5401,28 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
{
assert(structure_stride); /* counters are valid only for structured buffers */
+ counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
if (vkd3d_dxbc_compiler_is_opengl_target(compiler))
{
vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage);
storage_class = SpvStorageClassAtomicCounter;
- counter_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, counter_type_id);
}
+ else if (compiler->ssbo_uavs)
+ {
+ uint32_t length_id, array_type_id, struct_id;
+
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 1);
+ array_type_id = vkd3d_spirv_build_op_type_array(builder, counter_type_id, length_id);
+ vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4);
+
+ struct_id = vkd3d_spirv_build_op_type_struct(builder, &array_type_id, 1);
+ vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBufferBlock, NULL, 0);
+ vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0);
+
+ storage_class = SpvStorageClassUniform;
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id);
+ }
counter_var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0);
@@ -7602,47 +7671,82 @@ static uint32_t vkd3d_dxbc_compiler_emit_raw_structured_addressing(
static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
+ uint32_t coordinate_id, type_id, val_id, texel_type_id, ptr_type_id, ptr_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
- uint32_t coordinate_id, type_id, val_id, texel_type_id;
const struct vkd3d_shader_src_param *resource;
+ const struct vkd3d_symbol *resource_symbol;
uint32_t base_coordinate_id, component_idx;
uint32_t constituents[VKD3D_VEC4_SIZE];
struct vkd3d_shader_image image;
+ uint32_t indices[2];
unsigned int i, j;
SpvOp op;
resource = &src[instruction->src_count - 1];
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &resource->reg);
- if (resource->reg.type == VKD3DSPR_RESOURCE)
- op = SpvOpImageFetch;
- else
- op = SpvOpImageRead;
+ if (resource->reg.type == VKD3DSPR_UAV
+ && vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ texel_type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, texel_type_id);
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, resource_symbol->info.resource.structure_stride,
+ &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
- base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
- type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
- texel_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
- assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
- for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ constituents[j++] = vkd3d_spirv_build_op_load(builder, texel_type_id, ptr_id, SpvMemoryAccessMaskNone);
+ }
+ }
+ else
{
- if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
- continue;
+ if (resource->reg.type == VKD3DSPR_RESOURCE)
+ op = SpvOpImageFetch;
+ else
+ op = SpvOpImageRead;
- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
- coordinate_id = base_coordinate_id;
- if (component_idx)
- coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
- coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
- val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
- op, texel_type_id, image.image_id, coordinate_id);
- constituents[j++] = vkd3d_spirv_build_op_composite_extract1(builder,
- type_id, val_id, 0);
+ texel_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ assert(dst->write_mask & VKD3DSP_WRITEMASK_ALL);
+ for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
+ {
+ if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
+ continue;
+
+ component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ op, texel_type_id, image.image_id, coordinate_id);
+ constituents[j++] = vkd3d_spirv_build_op_composite_extract1(builder,
+ type_id, val_id, 0);
+ }
}
assert(dst->reg.data_type == VKD3D_DATA_UINT);
vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents);
@@ -7710,40 +7814,79 @@ static void vkd3d_dxbc_compiler_emit_ld_raw_structured(struct vkd3d_dxbc_compile
static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
+ uint32_t coordinate_id, type_id, val_id, data_id, ptr_type_id, ptr_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
- uint32_t coordinate_id, type_id, val_id, texel_id;
- const struct vkd3d_shader_src_param *texel;
+ const struct vkd3d_symbol *resource_symbol;
uint32_t base_coordinate_id, component_idx;
+ const struct vkd3d_shader_src_param *data;
struct vkd3d_shader_image image;
unsigned int component_count;
+ uint32_t indices[2];
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
- assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !image.structure_stride);
- base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
- type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &dst->reg);
- texel = &src[instruction->src_count - 1];
- assert(texel->reg.data_type == VKD3D_DATA_UINT);
- val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, texel, dst->write_mask);
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
- for (component_idx = 0; component_idx < component_count; ++component_idx)
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, resource_symbol->info.resource.structure_stride,
+ &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
+
+ data = &src[instruction->src_count - 1];
+ assert(data->reg.data_type == VKD3D_DATA_UINT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
+
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ for (component_idx = 0; component_idx < component_count; ++component_idx)
+ {
+ data_id = component_count > 1 ?
+ vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx) : val_id;
+
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
+
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
+ }
+ }
+ else
{
- /* Mesa Vulkan drivers require the texel parameter to be a vector. */
- texel_id = vkd3d_dxbc_compiler_emit_construct_vector(compiler, VKD3D_SHADER_COMPONENT_UINT,
- VKD3D_VEC4_SIZE, val_id, component_idx, component_count);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !image.structure_stride);
+ base_coordinate_id = vkd3d_dxbc_compiler_emit_raw_structured_addressing(compiler,
+ type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0);
- coordinate_id = base_coordinate_id;
- if (component_idx)
- coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
- coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+ data = &src[instruction->src_count - 1];
+ assert(data->reg.data_type == VKD3D_DATA_UINT);
+ val_id = vkd3d_dxbc_compiler_emit_load_src(compiler, data, dst->write_mask);
- vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id,
- texel_id, SpvImageOperandsMaskNone, NULL, 0);
+ component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ for (component_idx = 0; component_idx < component_count; ++component_idx)
+ {
+ /* Mesa Vulkan drivers require the texel parameter to be a vector. */
+ data_id = vkd3d_dxbc_compiler_emit_construct_vector(compiler, VKD3D_SHADER_COMPONENT_UINT,
+ VKD3D_VEC4_SIZE, val_id, component_idx, component_count);
+
+ coordinate_id = base_coordinate_id;
+ if (component_idx)
+ coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
+ coordinate_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx));
+
+ vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id,
+ data_id, SpvImageOperandsMaskNone, NULL, 0);
+ }
}
+
}
static void vkd3d_dxbc_compiler_emit_store_tgsm(struct vkd3d_dxbc_compiler *compiler,
@@ -7808,43 +7951,84 @@ static void vkd3d_dxbc_compiler_emit_ld_uav_typed(struct vkd3d_dxbc_compiler *co
const struct vkd3d_shader_instruction *instruction)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
- uint32_t coordinate_id, type_id, val_id;
+ const struct vkd3d_symbol *resource_symbol;
struct vkd3d_shader_image image;
DWORD coordinate_mask;
+ uint32_t indices[2];
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE);
- type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
- coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
- coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src[1].reg);
- val_id = vkd3d_spirv_build_op_image_read(builder, type_id,
- image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0);
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0);
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
- vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
- dst, val_id, image.sampled_type, src[1].swizzle);
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler, dst, val_id,
+ resource_symbol->info.resource.sampled_type, src[1].swizzle);
+ }
+ else
+ {
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+
+ val_id = vkd3d_spirv_build_op_image_read(builder, type_id,
+ image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0);
+
+ vkd3d_dxbc_compiler_emit_store_dst_swizzled(compiler,
+ dst, val_id, image.sampled_type, src[1].swizzle);
+ }
}
static void vkd3d_dxbc_compiler_emit_store_uav_typed(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
+ uint32_t coordinate_id, texel_id, type_id, val_id, ptr_type_id, ptr_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
- uint32_t coordinate_id, texel_id;
+ const struct vkd3d_symbol *resource_symbol;
struct vkd3d_shader_image image;
DWORD coordinate_mask;
+ uint32_t indices[2];
- vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageWriteWithoutFormat);
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &dst->reg);
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
- coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
- coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
- texel_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], dst->write_mask, image.sampled_type);
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0);
+ indices[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ indices[1] = coordinate_id;
- vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id,
- SpvImageOperandsMaskNone, NULL, 0);
+ val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1],
+ VKD3DSP_WRITEMASK_0, resource_symbol->info.resource.sampled_type);
+ ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+ vkd3d_spirv_build_op_store(builder, ptr_id, val_id, SpvMemoryAccessMaskNone);
+ }
+ else
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageWriteWithoutFormat);
+
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], coordinate_mask);
+ texel_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], dst->write_mask, image.sampled_type);
+
+ vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id,
+ SpvImageOperandsMaskNone, NULL, 0);
+ }
}
static void vkd3d_dxbc_compiler_emit_uav_counter_instruction(struct vkd3d_dxbc_compiler *compiler,
@@ -7873,6 +8057,15 @@ static void vkd3d_dxbc_compiler_emit_uav_counter_instruction(struct vkd3d_dxbc_c
pointer_id = counter_id;
memory_semantics |= SpvMemorySemanticsAtomicCounterMemoryMask;
}
+ else if (compiler->ssbo_uavs)
+ {
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ coordinate_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[1] = coordinate_id;
+ pointer_id = vkd3d_spirv_build_op_access_chain(builder,
+ ptr_type_id, counter_id, operands, 2);
+ }
else
{
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
@@ -7946,6 +8139,7 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol = NULL;
uint32_t ptr_type_id, type_id, val_id, result_id;
enum vkd3d_shader_component_type component_type;
const struct vkd3d_shader_dst_param *resource;
@@ -7981,10 +8175,21 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
else
{
scope = SpvScopeDevice;
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NO_LOAD);
- coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
- structure_stride = image.structure_stride;
- raw = image.raw;
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &resource->reg);
+
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ coordinate_mask = VKD3DSP_WRITEMASK_0;
+ structure_stride = resource_symbol->info.resource.structure_stride;
+ raw = resource_symbol->info.resource.raw;
+ }
+ else
+ {
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NO_LOAD);
+ coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1;
+ structure_stride = image.structure_stride;
+ raw = image.raw;
+ }
}
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
@@ -8009,12 +8214,24 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
}
else
{
- component_type = image.sampled_type;
- type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1);
- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
- sample_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
- pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
- ptr_type_id, image.id, coordinate_id, sample_id);
+ if (vkd3d_dxbc_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource))
+ {
+ component_type = resource_symbol->info.resource.sampled_type;
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
+ operands[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ operands[1] = coordinate_id;
+ pointer_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, operands, 2);
+ }
+ else
+ {
+ component_type = image.sampled_type;
+ type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1);
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id);
+ sample_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
+ pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
+ ptr_type_id, image.id, coordinate_id, sample_id);
+ }
}
val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type);
@@ -8041,18 +8258,30 @@ static void vkd3d_dxbc_compiler_emit_bufinfo(struct vkd3d_dxbc_compiler *compile
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
+ const struct vkd3d_symbol *resource_symbol;
uint32_t type_id, val_id, stride_id;
struct vkd3d_shader_image image;
uint32_t constituents[2];
unsigned int write_mask;
- vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
+ if (compiler->ssbo_uavs && src->reg.type == VKD3DSPR_UAV)
+ {
+ resource_symbol = vkd3d_dxbc_compiler_find_resource(compiler, &src->reg);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ val_id = vkd3d_spirv_build_op_array_length(builder, type_id, resource_symbol->id, 0);
+ write_mask = VKD3DSP_WRITEMASK_0;
+ }
+ else
+ {
+ vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
- vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
+ vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
- val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id);
- write_mask = VKD3DSP_WRITEMASK_0;
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id);
+ write_mask = VKD3DSP_WRITEMASK_0;
+ }
if (image.structure_stride)
{
--
2.11.0
1
0
[PATCH vkd3d 2/5] vkd3d-shader: Add a compiler message for unhandled register types in vkd3d_dxbc_compiler_get_descriptor_binding().
by Henri Verbeet Aug. 4, 2020
by Henri Verbeet Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 4 ++++
libs/vkd3d-shader/vkd3d_shader_private.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 6341370..9af672b 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -2340,7 +2340,11 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
else if (reg->type == VKD3DSPR_SAMPLER)
descriptor_type = VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER;
else
+ {
FIXME("Unhandled register type %#x.\n", reg->type);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE,
+ "Encountered invalid/unhandled register type %#x.", reg->type);
+ }
resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER
? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 16df8a5..21e37da 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -71,6 +71,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
+ VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000,
VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
--
2.11.0
1
0
[PATCH vkd3d 1/5] vkd3d-shader: Fail shader compilation if any descriptor bindings are missing.
by Henri Verbeet Aug. 4, 2020
by Henri Verbeet Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 30 ++++++++++++++++++-
libs/vkd3d-shader/vkd3d_shader_main.c | 51 ++++++++++++++++++--------------
libs/vkd3d-shader/vkd3d_shader_private.h | 7 ++++-
3 files changed, 64 insertions(+), 24 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 86ee263..6341370 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -2043,6 +2043,9 @@ struct vkd3d_dxbc_compiler
{
struct vkd3d_spirv_builder spirv_builder;
+ struct vkd3d_shader_message_context *message_context;
+ bool failed;
+
bool strip_debug;
struct rb_tree symbol_table;
@@ -2113,7 +2116,8 @@ static const char *vkd3d_dxbc_compiler_get_entry_point_name(const struct vkd3d_d
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
- const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info)
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ struct vkd3d_shader_message_context *message_context)
{
const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
@@ -2127,6 +2131,7 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
return NULL;
memset(compiler, 0, sizeof(*compiler));
+ compiler->message_context = message_context;
if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)))
{
@@ -2304,6 +2309,17 @@ static bool vkd3d_dxbc_compiler_has_combined_sampler(const struct vkd3d_dxbc_com
return false;
}
+static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_compiler *compiler,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vkd3d_shader_verror(compiler->message_context, error, format, args);
+ va_end(args);
+ compiler->failed = true;
+}
+
static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding(
struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, unsigned int register_space,
unsigned int reg_idx, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter)
@@ -2346,7 +2362,11 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
return current->binding;
}
if (shader_interface->uav_counter_count)
+ {
FIXME("Could not find descriptor binding for UAV counter %u, space %u.\n", reg_idx, register_space);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND,
+ "Could not find descriptor binding for UAV counter %u, space %u.", reg_idx, register_space);
+ }
}
else if (descriptor_type != VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN)
{
@@ -2365,8 +2385,13 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor
return current->binding;
}
if (shader_interface->binding_count)
+ {
FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n",
descriptor_type, register_space, reg_idx, compiler->shader_type);
+ vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND,
+ "Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.",
+ descriptor_type, register_space, reg_idx, compiler->shader_type);
+ }
}
binding.set = 0;
@@ -8797,6 +8822,9 @@ int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
vkd3d_spirv_validate(spirv, environment);
}
+ if (compiler->failed)
+ return VKD3D_ERROR_INVALID_SHADER;
+
return VKD3D_OK;
}
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c
index 0785c14..cfac8e2 100644
--- a/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -149,11 +149,9 @@ char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_con
return messages;
}
-void vkd3d_shader_error(struct vkd3d_shader_message_context *context,
- enum vkd3d_shader_error error, const char *format, ...)
+void vkd3d_shader_verror(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, va_list args)
{
- va_list args;
-
if (context->log_level < VKD3D_SHADER_LOG_ERROR)
return;
@@ -162,12 +160,20 @@ void vkd3d_shader_error(struct vkd3d_shader_message_context *context,
context->source_name, context->line, context->column, error);
else
vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", context->source_name, error);
- va_start(args, format);
vkd3d_string_buffer_vprintf(&context->messages, format, args);
- va_end(args);
vkd3d_string_buffer_printf(&context->messages, "\n");
}
+void vkd3d_shader_error(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vkd3d_shader_verror(context, error, format, args);
+ va_end(args);
+}
+
static void vkd3d_shader_dump_blob(const char *path, const char *prefix, const void *data, size_t size)
{
static int shader_id = 0;
@@ -306,35 +312,30 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
if ((ret = vkd3d_shader_scan(&scan_info, messages)) < 0)
return ret;
-
- if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name))
- return VKD3D_ERROR;
- ret = vkd3d_shader_parser_init(&parser, &compile_info->source, &message_context);
- vkd3d_shader_message_context_trace_messages(&message_context);
if (messages)
{
vkd3d_shader_free_messages(*messages);
- if (!(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
- ret = VKD3D_ERROR_OUT_OF_MEMORY;
- }
- vkd3d_shader_message_context_cleanup(&message_context);
- if (ret < 0)
- {
- vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
- return ret;
+ *messages = NULL;
}
+ if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name))
+ return VKD3D_ERROR;
+ if ((ret = vkd3d_shader_parser_init(&parser, &compile_info->source, &message_context)) < 0)
+ goto done;
+
vkd3d_shader_dump_shader(parser.shader_version.type, &compile_info->source);
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version,
- &parser.shader_desc, compile_info, &scan_descriptor_info)))
+ &parser.shader_desc, compile_info, &scan_descriptor_info, &message_context)))
{
ERR("Failed to create DXBC compiler.\n");
vkd3d_shader_parser_destroy(&parser);
- vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
- return VKD3D_ERROR;
+ ret = VKD3D_ERROR;
+ goto done;
}
+ message_context.line = 2; /* Line 1 is the version token. */
+ message_context.column = 1;
while (!shader_sm4_is_end(parser.data, &parser.ptr))
{
shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
@@ -348,6 +349,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
if ((ret = vkd3d_dxbc_compiler_handle_instruction(spirv_compiler, &instruction)) < 0)
break;
+ ++message_context.line;
}
if (ret >= 0)
@@ -355,6 +357,11 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_dxbc_compiler_destroy(spirv_compiler);
vkd3d_shader_parser_destroy(&parser);
+done:
+ vkd3d_shader_message_context_trace_messages(&message_context);
+ if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context)))
+ ret = VKD3D_ERROR_OUT_OF_MEMORY;
+ vkd3d_shader_message_context_cleanup(&message_context);
vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info);
return ret;
}
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index d728fdc..16df8a5 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -70,6 +70,8 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000,
+ VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
+
VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000,
VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE = 3002,
@@ -846,6 +848,8 @@ void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_mess
vkd3d_shader_message_context_trace_messages_(context, __FUNCTION__)
void vkd3d_shader_error(struct vkd3d_shader_message_context *context, enum vkd3d_shader_error error,
const char *format, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN;
+void vkd3d_shader_verror(struct vkd3d_shader_message_context *context,
+ enum vkd3d_shader_error error, const char *format, va_list args) DECLSPEC_HIDDEN;
int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
@@ -858,7 +862,8 @@ struct vkd3d_dxbc_compiler;
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
- const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info) DECLSPEC_HIDDEN;
+ const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info,
+ struct vkd3d_shader_message_context *message_context) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
--
2.11.0
1
0
Aug. 4, 2020
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/combase/Makefile.in | 2 +-
dlls/combase/combase.spec | 4 +
dlls/combase/usrmarshal.c | 230 ++++++++++++++++++++++++++++++++++++++
dlls/ole32/ole32.spec | 8 +-
dlls/ole32/usrmarshal.c | 225 +------------------------------------
5 files changed, 243 insertions(+), 226 deletions(-)
diff --git a/dlls/combase/Makefile.in b/dlls/combase/Makefile.in
index 954dc629973..24793205d5d 100644
--- a/dlls/combase/Makefile.in
+++ b/dlls/combase/Makefile.in
@@ -1,6 +1,6 @@
MODULE = combase.dll
IMPORTLIB = combase
-IMPORTS = advapi32 ole32 user32 gdi32 uuid
+IMPORTS = advapi32 ole32 user32 gdi32 uuid rpcrt4
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec
index 9d0bad29f0d..359f1774336 100644
--- a/dlls/combase/combase.spec
+++ b/dlls/combase/combase.spec
@@ -205,6 +205,10 @@
@ stdcall HMENU_UserMarshal(ptr ptr ptr)
@ stdcall HMENU_UserSize(ptr long ptr)
@ stdcall HMENU_UserUnmarshal(ptr ptr ptr)
+@ stdcall HMETAFILEPICT_UserFree(ptr ptr)
+@ stdcall HMETAFILEPICT_UserMarshal(ptr ptr ptr)
+@ stdcall HMETAFILEPICT_UserSize(ptr long ptr)
+@ stdcall HMETAFILEPICT_UserUnmarshal(ptr ptr ptr)
@ stdcall HPALETTE_UserFree(ptr ptr)
@ stdcall HPALETTE_UserMarshal(ptr ptr ptr)
@ stdcall HPALETTE_UserSize(ptr long ptr)
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c
index c88e8c57cd0..725b29aa28d 100644
--- a/dlls/combase/usrmarshal.c
+++ b/dlls/combase/usrmarshal.c
@@ -23,16 +23,26 @@
#define NONAMELESSUNION
#include "ole2.h"
+#include "rpc.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
+ULONG __RPC_USER HMETAFILE_UserSize(ULONG *pFlags, ULONG StartingSize, HMETAFILE *phmf);
+unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILE *phmf);
+unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILE *phmf);
+void __RPC_USER HMETAFILE_UserFree(ULONG *pFlags, HMETAFILE *phmf);
+
#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
+#define USER_MARSHAL_PTR_PREFIX \
+ ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
+ ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
+
static const char* debugstr_user_flags(ULONG *pFlags)
{
char buf[12];
@@ -640,6 +650,226 @@ void __RPC_USER HPALETTE_UserFree(ULONG *pFlags, HPALETTE *phPal)
FIXME(":stub\n");
}
+/******************************************************************************
+ * HMETAFILEPICT_UserSize (combase.@)
+ *
+ * Calculates the buffer size required to marshal an metafile pict.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * StartingSize [I] Starting size of the buffer. This value is added on to
+ * the buffer size required for the clip format.
+ * phMfp [I] Metafile pict to size.
+ *
+ * RETURNS
+ * The buffer size required to marshal a metafile pict plus the starting size.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG size, HMETAFILEPICT *phMfp)
+{
+ TRACE("%s, %u, &%p.\n", debugstr_user_flags(pFlags), size, *phMfp);
+
+ ALIGN_LENGTH(size, 3);
+
+ size += sizeof(ULONG);
+
+ if(LOWORD(*pFlags) == MSHCTX_INPROC)
+ size += sizeof(HMETAFILEPICT);
+ else
+ {
+ size += sizeof(ULONG);
+
+ if (*phMfp)
+ {
+ METAFILEPICT *mfpict = GlobalLock(*phMfp);
+
+ /* FIXME: raise an exception if mfpict is NULL? */
+ size += 3 * sizeof(ULONG);
+ size += sizeof(ULONG);
+
+ size = HMETAFILE_UserSize(pFlags, size, &mfpict->hMF);
+
+ GlobalUnlock(*phMfp);
+ }
+ }
+
+ return size;
+}
+
+/******************************************************************************
+ * HMETAFILEPICT_UserMarshal (combase.@)
+ *
+ * Marshals a metafile pict into a buffer.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * pBuffer [I] Buffer to marshal the clip format into.
+ * phMfp [I] Metafile pict to marshal.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
+{
+ TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phMfp);
+
+ ALIGN_POINTER(pBuffer, 3);
+
+ if (LOWORD(*pFlags) == MSHCTX_INPROC)
+ {
+ if (sizeof(HMETAFILEPICT) == 8)
+ *(ULONG *)pBuffer = WDT_INPROC64_CALL;
+ else
+ *(ULONG *)pBuffer = WDT_INPROC_CALL;
+ pBuffer += sizeof(ULONG);
+ *(HMETAFILEPICT *)pBuffer = *phMfp;
+ pBuffer += sizeof(HMETAFILEPICT);
+ }
+ else
+ {
+ *(ULONG *)pBuffer = WDT_REMOTE_CALL;
+ pBuffer += sizeof(ULONG);
+ *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phMfp;
+ pBuffer += sizeof(ULONG);
+
+ if (*phMfp)
+ {
+ METAFILEPICT *mfpict = GlobalLock(*phMfp);
+ remoteMETAFILEPICT * remmfpict = (remoteMETAFILEPICT *)pBuffer;
+
+ /* FIXME: raise an exception if mfpict is NULL? */
+ remmfpict->mm = mfpict->mm;
+ remmfpict->xExt = mfpict->xExt;
+ remmfpict->yExt = mfpict->yExt;
+ pBuffer += 3 * sizeof(ULONG);
+ *(ULONG *)pBuffer = USER_MARSHAL_PTR_PREFIX;
+ pBuffer += sizeof(ULONG);
+
+ pBuffer = HMETAFILE_UserMarshal(pFlags, pBuffer, &mfpict->hMF);
+
+ GlobalUnlock(*phMfp);
+ }
+ }
+ return pBuffer;
+}
+
+/******************************************************************************
+ * HMETAFILEPICT_UserUnmarshal (combase.@)
+ *
+ * Unmarshals an metafile pict from a buffer.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * pBuffer [I] Buffer to marshal the clip format from.
+ * phMfp [O] Address that receive the unmarshaled metafile pict.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to an ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is an ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
+{
+ ULONG fContext;
+
+ TRACE("%s, %p, %p.\n", debugstr_user_flags(pFlags), pBuffer, phMfp);
+
+ ALIGN_POINTER(pBuffer, 3);
+
+ fContext = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+
+ if ((fContext == WDT_INPROC_CALL) || fContext == WDT_INPROC64_CALL)
+ {
+ *phMfp = *(HMETAFILEPICT *)pBuffer;
+ pBuffer += sizeof(HMETAFILEPICT);
+ }
+ else
+ {
+ ULONG handle = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+ *phMfp = NULL;
+
+ if(handle)
+ {
+ METAFILEPICT *mfpict;
+ const remoteMETAFILEPICT *remmfpict;
+ ULONG user_marshal_prefix;
+
+ remmfpict = (const remoteMETAFILEPICT *)pBuffer;
+
+ *phMfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ if (!*phMfp)
+ RpcRaiseException(E_OUTOFMEMORY);
+
+ mfpict = GlobalLock(*phMfp);
+ mfpict->mm = remmfpict->mm;
+ mfpict->xExt = remmfpict->xExt;
+ mfpict->yExt = remmfpict->yExt;
+ pBuffer += 3 * sizeof(ULONG);
+ user_marshal_prefix = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+
+ if (user_marshal_prefix != USER_MARSHAL_PTR_PREFIX)
+ RpcRaiseException(RPC_X_INVALID_TAG);
+
+ pBuffer = HMETAFILE_UserUnmarshal(pFlags, pBuffer, &mfpict->hMF);
+
+ GlobalUnlock(*phMfp);
+ }
+ }
+ return pBuffer;
+}
+
+/******************************************************************************
+ * HMETAFILEPICT_UserFree (combase.@)
+ *
+ * Frees an unmarshaled metafile pict.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * phMfp [I] Metafile pict to free.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
+ * which the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp)
+{
+ TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *phMfp);
+
+ if ((LOWORD(*pFlags) != MSHCTX_INPROC) && *phMfp)
+ {
+ METAFILEPICT *mfpict;
+
+ mfpict = GlobalLock(*phMfp);
+ /* FIXME: raise an exception if mfpict is NULL? */
+ HMETAFILE_UserFree(pFlags, &mfpict->hMF);
+ GlobalUnlock(*phMfp);
+
+ GlobalFree(*phMfp);
+ }
+}
/******************************************************************************
* WdtpInterfacePointer_UserSize (combase.@)
*
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index 97618e08935..cabbb480b43 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -155,10 +155,10 @@
@ stdcall HMENU_UserMarshal(ptr ptr ptr) combase.HMENU_UserMarshal
@ stdcall HMENU_UserSize(ptr long ptr) combase.HMENU_UserSize
@ stdcall HMENU_UserUnmarshal(ptr ptr ptr) combase.HMENU_UserUnmarshal
-@ stdcall HMETAFILEPICT_UserFree(ptr ptr)
-@ stdcall HMETAFILEPICT_UserMarshal(ptr ptr ptr)
-@ stdcall HMETAFILEPICT_UserSize(ptr long ptr)
-@ stdcall HMETAFILEPICT_UserUnmarshal(ptr ptr ptr)
+@ stdcall HMETAFILEPICT_UserFree(ptr ptr) combase.HMETAFILEPICT_UserFree
+@ stdcall HMETAFILEPICT_UserMarshal(ptr ptr ptr) combase.HMETAFILEPICT_UserMarshal
+@ stdcall HMETAFILEPICT_UserSize(ptr long ptr) combase.HMETAFILEPICT_UserSize
+@ stdcall HMETAFILEPICT_UserUnmarshal(ptr ptr ptr) combase.HMETAFILEPICT_UserUnmarshal
@ stdcall HMETAFILE_UserFree(ptr ptr)
@ stdcall HMETAFILE_UserMarshal(ptr ptr ptr)
@ stdcall HMETAFILE_UserSize(ptr long ptr)
diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c
index 694ef60764f..7319badc97a 100644
--- a/dlls/ole32/usrmarshal.c
+++ b/dlls/ole32/usrmarshal.c
@@ -52,6 +52,10 @@ ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *pFlags, ULONG RealFlags, U
unsigned char * WINAPI WdtpInterfacePointer_UserMarshal(ULONG *pFlags, ULONG RealFlags, unsigned char *pBuffer,
IUnknown *punk, REFIID riid);
unsigned char * WINAPI WdtpInterfacePointer_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, IUnknown **ppunk, REFIID riid);
+ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG size, HMETAFILEPICT *phMfp);
+unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp);
+unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp);
+void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp);
static const char* debugstr_user_flags(ULONG *pFlags)
{
@@ -769,227 +773,6 @@ void __RPC_USER HENHMETAFILE_UserFree(ULONG *pFlags, HENHMETAFILE *phEmf)
DeleteEnhMetaFile(*phEmf);
}
-/******************************************************************************
- * HMETAFILEPICT_UserSize [OLE32.@]
- *
- * Calculates the buffer size required to marshal an metafile pict.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * StartingSize [I] Starting size of the buffer. This value is added on to
- * the buffer size required for the clip format.
- * phMfp [I] Metafile pict to size.
- *
- * RETURNS
- * The buffer size required to marshal a metafile pict plus the starting size.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *pFlags, ULONG size, HMETAFILEPICT *phMfp)
-{
- TRACE("(%s, %d, &%p)\n", debugstr_user_flags(pFlags), size, *phMfp);
-
- ALIGN_LENGTH(size, 3);
-
- size += sizeof(ULONG);
-
- if(LOWORD(*pFlags) == MSHCTX_INPROC)
- size += sizeof(HMETAFILEPICT);
- else
- {
- size += sizeof(ULONG);
-
- if (*phMfp)
- {
- METAFILEPICT *mfpict = GlobalLock(*phMfp);
-
- /* FIXME: raise an exception if mfpict is NULL? */
- size += 3 * sizeof(ULONG);
- size += sizeof(ULONG);
-
- size = HMETAFILE_UserSize(pFlags, size, &mfpict->hMF);
-
- GlobalUnlock(*phMfp);
- }
- }
-
- return size;
-}
-
-/******************************************************************************
- * HMETAFILEPICT_UserMarshal [OLE32.@]
- *
- * Marshals a metafile pict into a buffer.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * pBuffer [I] Buffer to marshal the clip format into.
- * phMfp [I] Metafile pict to marshal.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
-{
- TRACE("(%s, %p, &%p)\n", debugstr_user_flags(pFlags), pBuffer, *phMfp);
-
- ALIGN_POINTER(pBuffer, 3);
-
- if (LOWORD(*pFlags) == MSHCTX_INPROC)
- {
- if (sizeof(HMETAFILEPICT) == 8)
- *(ULONG *)pBuffer = WDT_INPROC64_CALL;
- else
- *(ULONG *)pBuffer = WDT_INPROC_CALL;
- pBuffer += sizeof(ULONG);
- *(HMETAFILEPICT *)pBuffer = *phMfp;
- pBuffer += sizeof(HMETAFILEPICT);
- }
- else
- {
- *(ULONG *)pBuffer = WDT_REMOTE_CALL;
- pBuffer += sizeof(ULONG);
- *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phMfp;
- pBuffer += sizeof(ULONG);
-
- if (*phMfp)
- {
- METAFILEPICT *mfpict = GlobalLock(*phMfp);
- remoteMETAFILEPICT * remmfpict = (remoteMETAFILEPICT *)pBuffer;
-
- /* FIXME: raise an exception if mfpict is NULL? */
- remmfpict->mm = mfpict->mm;
- remmfpict->xExt = mfpict->xExt;
- remmfpict->yExt = mfpict->yExt;
- pBuffer += 3 * sizeof(ULONG);
- *(ULONG *)pBuffer = USER_MARSHAL_PTR_PREFIX;
- pBuffer += sizeof(ULONG);
-
- pBuffer = HMETAFILE_UserMarshal(pFlags, pBuffer, &mfpict->hMF);
-
- GlobalUnlock(*phMfp);
- }
- }
- return pBuffer;
-}
-
-/******************************************************************************
- * HMETAFILEPICT_UserUnmarshal [OLE32.@]
- *
- * Unmarshals an metafile pict from a buffer.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * pBuffer [I] Buffer to marshal the clip format from.
- * phMfp [O] Address that receive the unmarshaled metafile pict.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to an ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is an ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HMETAFILEPICT *phMfp)
-{
- ULONG fContext;
-
- TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, phMfp);
-
- ALIGN_POINTER(pBuffer, 3);
-
- fContext = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
-
- if ((fContext == WDT_INPROC_CALL) || fContext == WDT_INPROC64_CALL)
- {
- *phMfp = *(HMETAFILEPICT *)pBuffer;
- pBuffer += sizeof(HMETAFILEPICT);
- }
- else
- {
- ULONG handle = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
- *phMfp = NULL;
-
- if(handle)
- {
- METAFILEPICT *mfpict;
- const remoteMETAFILEPICT *remmfpict;
- ULONG user_marshal_prefix;
-
- remmfpict = (const remoteMETAFILEPICT *)pBuffer;
-
- *phMfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
- if (!*phMfp)
- RpcRaiseException(E_OUTOFMEMORY);
-
- mfpict = GlobalLock(*phMfp);
- mfpict->mm = remmfpict->mm;
- mfpict->xExt = remmfpict->xExt;
- mfpict->yExt = remmfpict->yExt;
- pBuffer += 3 * sizeof(ULONG);
- user_marshal_prefix = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
-
- if (user_marshal_prefix != USER_MARSHAL_PTR_PREFIX)
- RpcRaiseException(RPC_X_INVALID_TAG);
-
- pBuffer = HMETAFILE_UserUnmarshal(pFlags, pBuffer, &mfpict->hMF);
-
- GlobalUnlock(*phMfp);
- }
- }
- return pBuffer;
-}
-
-/******************************************************************************
- * HMETAFILEPICT_UserFree [OLE32.@]
- *
- * Frees an unmarshaled metafile pict.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * phMfp [I] Metafile pict to free.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
- * which the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-void __RPC_USER HMETAFILEPICT_UserFree(ULONG *pFlags, HMETAFILEPICT *phMfp)
-{
- TRACE("(%s, &%p)\n", debugstr_user_flags(pFlags), *phMfp);
-
- if ((LOWORD(*pFlags) != MSHCTX_INPROC) && *phMfp)
- {
- METAFILEPICT *mfpict;
-
- mfpict = GlobalLock(*phMfp);
- /* FIXME: raise an exception if mfpict is NULL? */
- HMETAFILE_UserFree(pFlags, &mfpict->hMF);
- GlobalUnlock(*phMfp);
-
- GlobalFree(*phMfp);
- }
-}
-
/******************************************************************************
* STGMEDIUM_UserSize [OLE32.@]
*
--
2.27.0
2
8
Aug. 4, 2020
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/combase/combase.spec | 4 +
dlls/combase/usrmarshal.c | 219 ++++++++++++++++++++++++++++++++++++++
dlls/ole32/ole32.spec | 8 +-
dlls/ole32/usrmarshal.c | 219 --------------------------------------
4 files changed, 227 insertions(+), 223 deletions(-)
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec
index 9d0bad29f0d..3c0955f705d 100644
--- a/dlls/combase/combase.spec
+++ b/dlls/combase/combase.spec
@@ -197,6 +197,10 @@
@ stdcall HDC_UserMarshal(ptr ptr ptr)
@ stdcall HDC_UserSize(ptr long ptr)
@ stdcall HDC_UserUnmarshal(ptr ptr ptr)
+@ stdcall HGLOBAL_UserFree(ptr ptr)
+@ stdcall HGLOBAL_UserMarshal(ptr ptr ptr)
+@ stdcall HGLOBAL_UserSize(ptr long ptr)
+@ stdcall HGLOBAL_UserUnmarshal(ptr ptr ptr)
@ stdcall HICON_UserFree(ptr ptr)
@ stdcall HICON_UserMarshal(ptr ptr ptr)
@ stdcall HICON_UserSize(ptr long ptr)
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c
index c88e8c57cd0..7c77cc1a80e 100644
--- a/dlls/combase/usrmarshal.c
+++ b/dlls/combase/usrmarshal.c
@@ -617,6 +617,225 @@ unsigned char * __RPC_USER HPALETTE_UserUnmarshal(ULONG *pFlags, unsigned char *
return pBuffer;
}
+/******************************************************************************
+ * HGLOBAL_UserSize (combase.@)
+ *
+ * Calculates the buffer size required to marshal an HGLOBAL.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * StartingSize [I] Starting size of the buffer. This value is added on to
+ * the buffer size required for the clip format.
+ * phGlobal [I] HGLOBAL to size.
+ *
+ * RETURNS
+ * The buffer size required to marshal an HGLOBAL plus the starting size.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
+{
+ ULONG size = StartingSize;
+
+ TRACE("%s, %u, %p.\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
+
+ ALIGN_LENGTH(size, 3);
+
+ size += sizeof(ULONG);
+
+ if (LOWORD(*pFlags) == MSHCTX_INPROC)
+ size += sizeof(HGLOBAL);
+ else
+ {
+ size += sizeof(ULONG);
+ if (*phGlobal)
+ {
+ SIZE_T ret;
+ size += 3 * sizeof(ULONG);
+ ret = GlobalSize(*phGlobal);
+ size += (ULONG)ret;
+ }
+ }
+
+ return size;
+}
+
+/******************************************************************************
+ * HGLOBAL_UserMarshal (combase.@)
+ *
+ * Marshals an HGLOBAL into a buffer.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * pBuffer [I] Buffer to marshal the clip format into.
+ * phGlobal [I] HGLOBAL to marshal.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
+{
+ TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
+
+ ALIGN_POINTER(pBuffer, 3);
+
+ if (LOWORD(*pFlags) == MSHCTX_INPROC)
+ {
+ if (sizeof(*phGlobal) == 8)
+ *(ULONG *)pBuffer = WDT_INPROC64_CALL;
+ else
+ *(ULONG *)pBuffer = WDT_INPROC_CALL;
+ pBuffer += sizeof(ULONG);
+ *(HGLOBAL *)pBuffer = *phGlobal;
+ pBuffer += sizeof(HGLOBAL);
+ }
+ else
+ {
+ *(ULONG *)pBuffer = WDT_REMOTE_CALL;
+ pBuffer += sizeof(ULONG);
+ *(ULONG *)pBuffer = HandleToULong(*phGlobal);
+ pBuffer += sizeof(ULONG);
+ if (*phGlobal)
+ {
+ const unsigned char *memory;
+ SIZE_T size = GlobalSize(*phGlobal);
+ *(ULONG *)pBuffer = (ULONG)size;
+ pBuffer += sizeof(ULONG);
+ *(ULONG *)pBuffer = HandleToULong(*phGlobal);
+ pBuffer += sizeof(ULONG);
+ *(ULONG *)pBuffer = (ULONG)size;
+ pBuffer += sizeof(ULONG);
+
+ memory = GlobalLock(*phGlobal);
+ memcpy(pBuffer, memory, size);
+ pBuffer += size;
+ GlobalUnlock(*phGlobal);
+ }
+ }
+
+ return pBuffer;
+}
+
+/******************************************************************************
+ * HGLOBAL_UserUnmarshal (combase.@)
+ *
+ * Unmarshals an HGLOBAL from a buffer.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * pBuffer [I] Buffer to marshal the clip format from.
+ * phGlobal [O] Address that receive the unmarshaled HGLOBAL.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to an ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
+ * the first parameter is an ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
+{
+ ULONG fContext;
+
+ TRACE("%s, %p, &%p.\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
+
+ ALIGN_POINTER(pBuffer, 3);
+
+ fContext = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+
+ if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
+ ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
+ {
+ *phGlobal = *(HGLOBAL *)pBuffer;
+ pBuffer += sizeof(*phGlobal);
+ }
+ else if (fContext == WDT_REMOTE_CALL)
+ {
+ ULONG handle;
+
+ handle = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+
+ if (handle)
+ {
+ ULONG size;
+ void *memory;
+
+ size = *(ULONG *)pBuffer;
+ pBuffer += sizeof(ULONG);
+ /* redundancy is bad - it means you have to check consistency like
+ * this: */
+ if (*(ULONG *)pBuffer != handle)
+ {
+ RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
+ return pBuffer;
+ }
+ pBuffer += sizeof(ULONG);
+ /* redundancy is bad - it means you have to check consistency like
+ * this: */
+ if (*(ULONG *)pBuffer != size)
+ {
+ RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
+ return pBuffer;
+ }
+ pBuffer += sizeof(ULONG);
+
+ /* FIXME: check size is not too big */
+
+ *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
+ memory = GlobalLock(*phGlobal);
+ memcpy(memory, pBuffer, size);
+ pBuffer += size;
+ GlobalUnlock(*phGlobal);
+ }
+ else
+ *phGlobal = NULL;
+ }
+ else
+ RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
+
+ return pBuffer;
+}
+
+/******************************************************************************
+ * HGLOBAL_UserFree (combase.@)
+ *
+ * Frees an unmarshaled HGLOBAL.
+ *
+ * PARAMS
+ * pFlags [I] Flags. See notes.
+ * phGlobal [I] HGLOBAL to free.
+ *
+ * RETURNS
+ * The end of the marshaled data in the buffer.
+ *
+ * NOTES
+ * Even though the function is documented to take a pointer to a ULONG in
+ * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
+ * which the first parameter is a ULONG.
+ * This function is only intended to be called by the RPC runtime.
+ */
+void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
+{
+ TRACE("%s, &%p.\n", debugstr_user_flags(pFlags), *phGlobal);
+
+ if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
+ GlobalFree(*phGlobal);
+}
+
/******************************************************************************
* HPALETTE_UserFree (combase.@)
*
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index 97618e08935..c3ee8f27f23 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -143,10 +143,10 @@
@ stdcall HENHMETAFILE_UserMarshal(ptr ptr ptr)
@ stdcall HENHMETAFILE_UserSize(ptr long ptr)
@ stdcall HENHMETAFILE_UserUnmarshal(ptr ptr ptr)
-@ stdcall HGLOBAL_UserFree(ptr ptr)
-@ stdcall HGLOBAL_UserMarshal(ptr ptr ptr)
-@ stdcall HGLOBAL_UserSize(ptr long ptr)
-@ stdcall HGLOBAL_UserUnmarshal(ptr ptr ptr)
+@ stdcall HGLOBAL_UserFree(ptr ptr) combase.HGLOBAL_UserFree
+@ stdcall HGLOBAL_UserMarshal(ptr ptr ptr) combase.HGLOBAL_UserMarshal
+@ stdcall HGLOBAL_UserSize(ptr long ptr) combase.HGLOBAL_UserSize
+@ stdcall HGLOBAL_UserUnmarshal(ptr ptr ptr) combase.HGLOBAL_UserUnmarshal
@ stdcall HICON_UserFree(ptr ptr) combase.HICON_UserFree
@ stdcall HICON_UserMarshal(ptr ptr ptr) combase.HICON_UserMarshal
@ stdcall HICON_UserSize(ptr long ptr) combase.HICON_UserSize
diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c
index 694ef60764f..a5daa949830 100644
--- a/dlls/ole32/usrmarshal.c
+++ b/dlls/ole32/usrmarshal.c
@@ -156,225 +156,6 @@ static void handle_UserFree(ULONG *pFlags, HANDLE *handle)
IMPL_WIREM_HANDLE(HACCEL)
-/******************************************************************************
- * HGLOBAL_UserSize [OLE32.@]
- *
- * Calculates the buffer size required to marshal an HGLOBAL.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * StartingSize [I] Starting size of the buffer. This value is added on to
- * the buffer size required for the clip format.
- * phGlobal [I] HGLOBAL to size.
- *
- * RETURNS
- * The buffer size required to marshal an HGLOBAL plus the starting size.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-ULONG __RPC_USER HGLOBAL_UserSize(ULONG *pFlags, ULONG StartingSize, HGLOBAL *phGlobal)
-{
- ULONG size = StartingSize;
-
- TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, phGlobal);
-
- ALIGN_LENGTH(size, 3);
-
- size += sizeof(ULONG);
-
- if (LOWORD(*pFlags) == MSHCTX_INPROC)
- size += sizeof(HGLOBAL);
- else
- {
- size += sizeof(ULONG);
- if (*phGlobal)
- {
- SIZE_T ret;
- size += 3 * sizeof(ULONG);
- ret = GlobalSize(*phGlobal);
- size += (ULONG)ret;
- }
- }
-
- return size;
-}
-
-/******************************************************************************
- * HGLOBAL_UserMarshal [OLE32.@]
- *
- * Marshals an HGLOBAL into a buffer.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * pBuffer [I] Buffer to marshal the clip format into.
- * phGlobal [I] HGLOBAL to marshal.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-unsigned char * __RPC_USER HGLOBAL_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
-{
- TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
-
- ALIGN_POINTER(pBuffer, 3);
-
- if (LOWORD(*pFlags) == MSHCTX_INPROC)
- {
- if (sizeof(*phGlobal) == 8)
- *(ULONG *)pBuffer = WDT_INPROC64_CALL;
- else
- *(ULONG *)pBuffer = WDT_INPROC_CALL;
- pBuffer += sizeof(ULONG);
- *(HGLOBAL *)pBuffer = *phGlobal;
- pBuffer += sizeof(HGLOBAL);
- }
- else
- {
- *(ULONG *)pBuffer = WDT_REMOTE_CALL;
- pBuffer += sizeof(ULONG);
- *(ULONG *)pBuffer = HandleToULong(*phGlobal);
- pBuffer += sizeof(ULONG);
- if (*phGlobal)
- {
- const unsigned char *memory;
- SIZE_T size = GlobalSize(*phGlobal);
- *(ULONG *)pBuffer = (ULONG)size;
- pBuffer += sizeof(ULONG);
- *(ULONG *)pBuffer = HandleToULong(*phGlobal);
- pBuffer += sizeof(ULONG);
- *(ULONG *)pBuffer = (ULONG)size;
- pBuffer += sizeof(ULONG);
-
- memory = GlobalLock(*phGlobal);
- memcpy(pBuffer, memory, size);
- pBuffer += size;
- GlobalUnlock(*phGlobal);
- }
- }
-
- return pBuffer;
-}
-
-/******************************************************************************
- * HGLOBAL_UserUnmarshal [OLE32.@]
- *
- * Unmarshals an HGLOBAL from a buffer.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * pBuffer [I] Buffer to marshal the clip format from.
- * phGlobal [O] Address that receive the unmarshaled HGLOBAL.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to an ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of which
- * the first parameter is an ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal)
-{
- ULONG fContext;
-
- TRACE("(%s, %p, &%p\n", debugstr_user_flags(pFlags), pBuffer, *phGlobal);
-
- ALIGN_POINTER(pBuffer, 3);
-
- fContext = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
-
- if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) ||
- ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8)))
- {
- *phGlobal = *(HGLOBAL *)pBuffer;
- pBuffer += sizeof(*phGlobal);
- }
- else if (fContext == WDT_REMOTE_CALL)
- {
- ULONG handle;
-
- handle = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
-
- if (handle)
- {
- ULONG size;
- void *memory;
-
- size = *(ULONG *)pBuffer;
- pBuffer += sizeof(ULONG);
- /* redundancy is bad - it means you have to check consistency like
- * this: */
- if (*(ULONG *)pBuffer != handle)
- {
- RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
- return pBuffer;
- }
- pBuffer += sizeof(ULONG);
- /* redundancy is bad - it means you have to check consistency like
- * this: */
- if (*(ULONG *)pBuffer != size)
- {
- RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL);
- return pBuffer;
- }
- pBuffer += sizeof(ULONG);
-
- /* FIXME: check size is not too big */
-
- *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
- memory = GlobalLock(*phGlobal);
- memcpy(memory, pBuffer, size);
- pBuffer += size;
- GlobalUnlock(*phGlobal);
- }
- else
- *phGlobal = NULL;
- }
- else
- RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL);
-
- return pBuffer;
-}
-
-/******************************************************************************
- * HGLOBAL_UserFree [OLE32.@]
- *
- * Frees an unmarshaled HGLOBAL.
- *
- * PARAMS
- * pFlags [I] Flags. See notes.
- * phGlobal [I] HGLOBAL to free.
- *
- * RETURNS
- * The end of the marshaled data in the buffer.
- *
- * NOTES
- * Even though the function is documented to take a pointer to a ULONG in
- * pFlags, it actually takes a pointer to a USER_MARSHAL_CB structure, of
- * which the first parameter is a ULONG.
- * This function is only intended to be called by the RPC runtime.
- */
-void __RPC_USER HGLOBAL_UserFree(ULONG *pFlags, HGLOBAL *phGlobal)
-{
- TRACE("(%s, &%p\n", debugstr_user_flags(pFlags), *phGlobal);
-
- if (LOWORD(*pFlags) != MSHCTX_INPROC && *phGlobal)
- GlobalFree(*phGlobal);
-}
-
/******************************************************************************
* HMETAFILE_UserSize [OLE32.@]
*
--
2.27.0
1
4
[PATCH 1/2] xactengine3_7: Move DllGetClassObject to it's own file
by Alistair Leslie-Hughes Aug. 4, 2020
by Alistair Leslie-Hughes Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/xactengine3_7/Makefile.in | 1 +
dlls/xactengine3_7/main.c | 42 ++++++++++++++++++++++++++++++++++
dlls/xactengine3_7/xact_dll.c | 14 +-----------
3 files changed, 44 insertions(+), 13 deletions(-)
create mode 100644 dlls/xactengine3_7/main.c
diff --git a/dlls/xactengine3_7/Makefile.in b/dlls/xactengine3_7/Makefile.in
index 6fce27d1628..bbbf239daf5 100644
--- a/dlls/xactengine3_7/Makefile.in
+++ b/dlls/xactengine3_7/Makefile.in
@@ -4,6 +4,7 @@ EXTRALIBS = $(FAUDIO_LIBS)
EXTRAINCL = $(FAUDIO_CFLAGS)
C_SRCS = \
+ main.c \
xact_dll.c
IDL_SRCS = xact_classes.idl
diff --git a/dlls/xactengine3_7/main.c b/dlls/xactengine3_7/main.c
new file mode 100644
index 00000000000..659cbeeca9e
--- /dev/null
+++ b/dlls/xactengine3_7/main.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018 Ethan Lee for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "xact_classes.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(xact3);
+
+extern IClassFactory XACTFactory;
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
+{
+ if (IsEqualGUID(rclsid, &CLSID_XACTEngine37))
+ {
+ TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+ return IClassFactory_QueryInterface(&XACTFactory, riid, ppv);
+ }
+
+ FIXME("Unknown class %s\n", debugstr_guid(rclsid));
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
diff --git a/dlls/xactengine3_7/xact_dll.c b/dlls/xactengine3_7/xact_dll.c
index 69570e8ceff..d35bece8de9 100644
--- a/dlls/xactengine3_7/xact_dll.c
+++ b/dlls/xactengine3_7/xact_dll.c
@@ -488,7 +488,7 @@ static const IClassFactoryVtbl XACT3CF_Vtbl =
XACT3CF_LockServer
};
-static IClassFactory XACTFactory = { &XACT3CF_Vtbl };
+IClassFactory XACTFactory = { &XACT3CF_Vtbl };
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved)
{
@@ -509,18 +509,6 @@ HRESULT WINAPI DllCanUnloadNow(void)
return S_FALSE;
}
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
-{
- if (IsEqualGUID(rclsid, &CLSID_XACTEngine37))
- {
- TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
- return IClassFactory_QueryInterface(&XACTFactory, riid, ppv);
- }
-
- FIXME("Unknown class %s\n", debugstr_guid(rclsid));
- return CLASS_E_CLASSNOTAVAILABLE;
-}
-
HRESULT WINAPI DllRegisterServer(void)
{
return __wine_register_resources(instance);
--
2.27.0
1
0
[PATCH] xactengine3_7: Return valid HRESULT from IXACT3Engine Initialize
by Alistair Leslie-Hughes Aug. 4, 2020
by Alistair Leslie-Hughes Aug. 4, 2020
Aug. 4, 2020
FAudio doesn't always return a valid HRESULT, ensure a valid code
is passed back to the application.
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/xactengine3_7/xact_dll.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/xactengine3_7/xact_dll.c b/dlls/xactengine3_7/xact_dll.c
index 3a14db7460..69570e8cef 100644
--- a/dlls/xactengine3_7/xact_dll.c
+++ b/dlls/xactengine3_7/xact_dll.c
@@ -157,6 +157,7 @@ static HRESULT WINAPI IXACT3EngineImpl_Initialize(IXACT3Engine *iface,
{
XACT3EngineImpl *This = impl_from_IXACT3Engine(iface);
FACTRuntimeParameters params;
+ UINT ret;
TRACE("(%p)->(%p)\n", This, pParams);
@@ -195,7 +196,11 @@ static HRESULT WINAPI IXACT3EngineImpl_Initialize(IXACT3Engine *iface,
params.fileIOCallbacks.readFileCallback = wrap_readfile;
params.fileIOCallbacks.getOverlappedResultCallback = wrap_getoverlappedresult;
- return FACTAudioEngine_Initialize(This->fact_engine, ¶ms);
+ ret = FACTAudioEngine_Initialize(This->fact_engine, ¶ms);
+ if (ret != 0)
+ WARN("FACTAudioEngine_Initialize returned %d\n", ret);
+
+ return !ret ? S_OK : E_FAIL;
}
static HRESULT WINAPI IXACT3EngineImpl_ShutDown(IXACT3Engine *iface)
--
2.27.0
1
0
[PATCH 1/3] server: Introduce a callback to retrieve the parent device from a file descriptor.
by Zebediah Figura Aug. 4, 2020
by Zebediah Figura Aug. 4, 2020
Aug. 4, 2020
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
This patch series doesn't handle ntoskrnl device files. It is written with the
ntoskrnl tests previously written in mind, and therefore is structured to make
implementation somewhat easier, but the implementation is rather nontrivial and
so far not known to be necessary.
The equivalent Staging patch uses the object tree for device files. At least two
problems immediately arise from this: firstly, there is no clean way to
distinguish the root file name '\\' from the directly opened device (a
distinction particularly important for file systems, but in fact even visible
with named pipes); secondly, this cannot accomodate an implementation that must
plumb requests through ntoskrnl, since object names are set at creation time. In
general it also smacks of hacking a name into the object tree, since that name
is not actually looked up directly as other names are.
Another possible design would be to handle it all on the server side. This would
mean changing the parameters of get_file_info to handle arbitrary buffers (or
else adding a new callback specifically for ObjectNameInformation). It would
also mean making get_object_info eventually asynchronous. After trying out that
approach, this one seemed architecturally simpler.
The equivalent Staging patch was originally written for msys2's strace.exe.
msys2 and cygwin have been broken in Wine for a long time, perhaps unfixably.
I'm not aware of other applications that need pipes, or similar objects, to
return accurate names from ObjectNameInformation. I'm submitting this patch
partly to upstream a long-standing Staging patch and fix tests, and partly
because I believe it will help implementation of object/file name information
for regular files with some of my local/planned changes to volume
infrastructure.
server/change.c | 1 +
server/console.c | 3 +++
server/device.c | 1 +
server/fd.c | 5 +++++
server/file.c | 1 +
server/file.h | 3 +++
server/mailslot.c | 3 +++
server/mapping.c | 1 +
server/named_pipe.c | 3 +++
server/serial.c | 1 +
server/sock.c | 2 ++
11 files changed, 24 insertions(+)
diff --git a/server/change.c b/server/change.c
index a8f3329c722..1eba2e4dd88 100644
--- a/server/change.c
+++ b/server/change.c
@@ -138,6 +138,7 @@ static const struct fd_ops dir_fd_ops =
dir_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
dir_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/console.c b/server/console.c
index 53910b3f46e..bd8cb1995e7 100644
--- a/server/console.c
+++ b/server/console.c
@@ -111,6 +111,7 @@ static const struct fd_ops console_input_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
console_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
@@ -168,6 +169,7 @@ static const struct fd_ops console_input_events_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
console_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
@@ -248,6 +250,7 @@ static const struct fd_ops screen_buffer_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
console_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/device.c b/server/device.c
index 01e08f295f7..73c6edcb078 100644
--- a/server/device.c
+++ b/server/device.c
@@ -219,6 +219,7 @@ static const struct fd_ops device_file_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
device_file_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
device_file_read, /* read */
device_file_write, /* write */
device_file_flush, /* flush */
diff --git a/server/fd.c b/server/fd.c
index 7ea8ac273e5..064defc34e8 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2246,6 +2246,11 @@ static void unmount_device( struct fd *device_fd )
release_object( device );
}
+struct object *no_fd_get_parent( struct fd *fd )
+{
+ return NULL;
+}
+
/* default read() routine */
int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos )
{
diff --git a/server/file.c b/server/file.c
index 38260cfd2b3..0b92d6aae46 100644
--- a/server/file.c
+++ b/server/file.c
@@ -105,6 +105,7 @@ static const struct fd_ops file_fd_ops =
file_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
file_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/file.h b/server/file.h
index e8ace7f49e4..b407c725db2 100644
--- a/server/file.h
+++ b/server/file.h
@@ -56,6 +56,8 @@ struct fd_ops
void (*poll_event)(struct fd *,int event);
/* get file information */
enum server_fd_type (*get_fd_type)(struct fd *fd);
+ /* get the parent (device) object */
+ struct object *(*get_parent)(struct fd *fd);
/* perform a read on the file */
int (*read)(struct fd *, struct async *, file_pos_t );
/* perform a write on the file */
@@ -109,6 +111,7 @@ extern void default_poll_event( struct fd *fd, int event );
extern void fd_queue_async( struct fd *fd, struct async *async, int type );
extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
+extern struct object *no_fd_get_parent( struct fd *fd );
extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos );
extern int no_fd_write( struct fd *fd, struct async *async, file_pos_t pos );
extern int no_fd_flush( struct fd *fd, struct async *async );
diff --git a/server/mailslot.c b/server/mailslot.c
index 58d650cbb25..03f5308fcbf 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -101,6 +101,7 @@ static const struct fd_ops mailslot_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
mailslot_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
@@ -157,6 +158,7 @@ static const struct fd_ops mail_writer_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
mail_writer_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
@@ -245,6 +247,7 @@ static const struct fd_ops mailslot_device_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
mailslot_device_file_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/mapping.c b/server/mapping.c
index db0debe0af5..5d0a1c402b5 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -180,6 +180,7 @@ static const struct fd_ops mapping_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
mapping_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index b259abb8de4..7eb0905293e 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -180,6 +180,7 @@ static const struct fd_ops pipe_server_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
pipe_end_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
pipe_end_read, /* read */
pipe_end_write, /* write */
pipe_end_flush, /* flush */
@@ -222,6 +223,7 @@ static const struct fd_ops pipe_client_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
pipe_end_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
pipe_end_read, /* read */
pipe_end_write, /* write */
pipe_end_flush, /* flush */
@@ -297,6 +299,7 @@ static const struct fd_ops named_pipe_device_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
named_pipe_device_file_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/serial.c b/server/serial.c
index 4292472613a..4d112b8c6ff 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -112,6 +112,7 @@ static const struct fd_ops serial_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
serial_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
diff --git a/server/sock.c b/server/sock.c
index 1a53ce4b091..9f33bc0b95c 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -164,6 +164,7 @@ static const struct fd_ops sock_fd_ops =
sock_get_poll_events, /* get_poll_events */
sock_poll_event, /* poll_event */
sock_get_fd_type, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
@@ -979,6 +980,7 @@ static const struct fd_ops ifchange_fd_ops =
ifchange_get_poll_events, /* get_poll_events */
ifchange_poll_event, /* poll_event */
NULL, /* get_fd_type */
+ no_fd_get_parent, /* get_parent */
no_fd_read, /* read */
no_fd_write, /* write */
no_fd_flush, /* flush */
--
2.27.0
1
2
Signed-off-by: Myah Caron <qsniyg(a)protonmail.com>
---
Currently the new tests are skipped under wine due to missing registry keys. They can be added by running winetricks speechsdk.
dlls/sapi/tests/token.c | 313 ++++++++++++++++++++++++++++++++++++++++
dlls/sapi/token.c | 140 +++++++++++++++++-
2 files changed, 449 insertions(+), 4 deletions(-)
diff --git a/dlls/sapi/tests/token.c b/dlls/sapi/tests/token.c
index 9f6689b83f..35e030cc87 100644
--- a/dlls/sapi/tests/token.c
+++ b/dlls/sapi/tests/token.c
@@ -83,6 +83,309 @@ static void test_token_category(void)
ISpObjectTokenCategory_Release( cat );
}
+static void backup_speech(HKEY root)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegDeleteTreeW( root, L"SOFTWARE\\Microsoft\\Speech_winetest" );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND || res == ERROR_ACCESS_DENIED, "got %08x\n", res );
+
+ res = RegCreateKeyW( root, L"SOFTWARE\\Microsoft\\Speech_winetest", &key );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ RegCopyTreeW( root, L"SOFTWARE\\Microsoft\\Speech", key );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+
+ res = RegCloseKey(key);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+}
+
+static BOOL restore_speech(HKEY root, BOOL delete_backup)
+{
+ LONG res;
+ HKEY key;
+ BOOL returnvalue = FALSE;
+
+ res = RegDeleteTreeW( root, L"SOFTWARE\\Microsoft\\Speech" );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND || res == ERROR_ACCESS_DENIED, "got %08x\n", res );
+ if (res == ERROR_ACCESS_DENIED)
+ returnvalue = TRUE;
+
+ res = RegCreateKeyW( root, L"SOFTWARE\\Microsoft\\Speech", &key );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ RegCopyTreeW( root, L"SOFTWARE\\Microsoft\\Speech_winetest", key );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+
+ RegCloseKey(key);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ if (delete_backup) {
+ res = RegDeleteTreeW( root, L"SOFTWARE\\Microsoft\\Speech_winetest" );
+ ok( res == ERROR_SUCCESS || res == ERROR_ACCESS_DENIED, "got %08x\n", res );
+ }
+
+ return returnvalue;
+}
+
+static void test_token_default_id(LPCWSTR cat_name)
+{
+ ISpObjectTokenCategory *cat;
+ HRESULT hr;
+ LONG res;
+ HKEY key;
+ LPWSTR token_id = NULL;
+ WCHAR regvalue[512];
+ WCHAR regvalue2[512];
+ DWORD regvalue_size = sizeof( regvalue );
+ WCHAR regcat[256];
+ WCHAR cat_id[256];
+
+ wcscpy(regcat, L"SOFTWARE\\Microsoft\\Speech\\");
+ wcscat(regcat, cat_name);
+
+ wcscpy(cat_id, L"HKEY_LOCAL_MACHINE\\");
+ wcscat(cat_id, regcat);
+
+ res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, regcat, 0, KEY_READ, &key );
+ if (res == ERROR_FILE_NOT_FOUND) {
+ skip( "category %s not found in registry\n", wine_dbgstr_w(cat_name) );
+ return;
+ }
+ RegCloseKey(key);
+
+ hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISpObjectTokenCategory, (void **)&cat );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+ ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
+ ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id );
+
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL );
+ ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
+
+ /* if missing, Get/SetDefaultTokenId should initialize HKEY_LOCAL_USER's
+ SOFTWARE\Microsoft\Speech\[cat_name] */
+ res = RegDeleteTreeW( HKEY_CURRENT_USER, regcat );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ res = RegOpenKeyExW( HKEY_CURRENT_USER, regcat, 0, KEY_ALL_ACCESS, &key );
+ ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL );
+ ok( hr == E_POINTER, "got %08x\n", hr );
+
+ res = RegOpenKeyExW( HKEY_CURRENT_USER, regcat, 0, KEY_ALL_ACCESS, &key );
+ ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+
+ /* AudioOutput under windows server returns this error */
+ if (hr == SPERR_NOT_FOUND) {
+ /* also happens if TokenEnums/Tokens is empty or doesn't exist */
+ skip( "category %s not found\n", wine_dbgstr_w(cat_name) );
+ return;
+ }
+
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
+
+ regvalue_size = sizeof( regvalue );
+ res = RegGetValueW( HKEY_CURRENT_USER, regcat, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
+ (LPVOID)®value, ®value_size);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ skip( "DefaultTokenId not found for category %s (%s)\n", wine_dbgstr_w(cat_name), wine_dbgstr_w(token_id));
+ } else {
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ ok( !wcscmp(regvalue, token_id),
+ "GetDefaultTokenId (%s) should be equal to the DefaultTokenId key (%s)\n",
+ wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
+ }
+
+ CoTaskMemFree(token_id);
+
+ regvalue_size = sizeof( regvalue2 );
+ regvalue2[0] = 0;
+ res = RegGetValueW( HKEY_LOCAL_MACHINE, regcat, L"DefaultdefaultTokenId", RRF_RT_REG_SZ, NULL,
+ (LPVOID)®value2, ®value_size);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ skip( "DefaultdefaultTokenId not found for category %s (%s)\n", wine_dbgstr_w(cat_name), wine_dbgstr_w(regvalue) );
+ } else {
+ regvalue_size = sizeof( regvalue );
+ regvalue[0] = 0;
+ res = RegGetValueW( HKEY_CURRENT_USER, regcat, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
+ (LPVOID)®value, ®value_size);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ ok( !wcscmp(regvalue, regvalue2),
+ "DefaultTokenId (%s) should be equal to the DefaultdefaultTokenId key (%s)\n",
+ wine_dbgstr_w(regvalue), wine_dbgstr_w(regvalue2) );
+ }
+
+ /* todo: test subkeys */
+
+ res = RegOpenKeyExW( HKEY_CURRENT_USER, regcat, 0, KEY_ALL_ACCESS, &key );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ wcscpy(regvalue, L"bogus");
+ regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR );
+ res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ res = RegCloseKey(key);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
+ todo_wine ok( wcscmp(regvalue, token_id),
+ "GetDefaultTokenId (%s) should not be equal to the bogus DefaultTokenId key (%s)\n",
+ wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
+ CoTaskMemFree(token_id);
+
+ /* todo: add more tests for the resulting token_id */
+
+ res = restore_speech( HKEY_LOCAL_MACHINE, FALSE );
+ if (res == TRUE) {
+ skip( "Unable to delete HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Speech\n" );
+ } else {
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+ todo_wine ok( hr == 0x800703fa, "got %08x\n", hr );
+ todo_wine ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id );
+ }
+
+ ISpObjectTokenCategory_Release( cat );
+
+ hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISpObjectTokenCategory, (void **)&cat );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ res = RegDeleteTreeW( HKEY_CURRENT_USER, regcat );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ res = RegDeleteTreeW( HKEY_LOCAL_MACHINE, regcat );
+ if (res == ERROR_ACCESS_DENIED) {
+ skip( "Unable to delete HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Speech\n" );
+
+ restore_speech( HKEY_CURRENT_USER, FALSE );
+ restore_speech( HKEY_LOCAL_MACHINE, FALSE );
+ } else {
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr );
+
+ restore_speech( HKEY_CURRENT_USER, FALSE );
+
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr );
+
+ restore_speech( HKEY_LOCAL_MACHINE, FALSE );
+ }
+
+ res = RegDeleteTreeW( HKEY_CURRENT_USER, regcat );
+ ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
+ res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, regcat, 0, KEY_WRITE, &key );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ wcscpy(regvalue, L"bogus");
+ regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR );
+ res = RegSetValueExW( key, L"DefaultdefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ RegCloseKey(key);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
+ todo_wine ok( wcscmp(regvalue, token_id),
+ "GetDefaultTokenId (%s) should not be equal to the bogus DefaultdefaultTokenId key (%s)\n",
+ wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
+ CoTaskMemFree(token_id);
+
+ /* todo: test valid DefaultdefaultTokenId values
+ observation: if it doesn't begin with HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\
+ it will return E_INVALIDARG */
+
+ ISpObjectTokenCategory_Release( cat );
+
+ res = RegDeleteTreeW( HKEY_CURRENT_USER, regcat );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, regcat, 0, KEY_ALL_ACCESS, &key );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ res = RegDeleteValueW( key, L"DefaultdefaultTokenId" );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ RegCloseKey(key);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+
+ hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISpObjectTokenCategory, (void **)&cat );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ token_id = (LPWSTR)0xdeadbeef;
+ hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
+ if (token_id != (LPWSTR)0xdeadbeef)
+ CoTaskMemFree(token_id);
+
+ ISpObjectTokenCategory_Release( cat );
+ restore_speech( HKEY_LOCAL_MACHINE, FALSE );
+ hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISpObjectTokenCategory, (void **)&cat );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL );
+ ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
+
+ hr = ISpObjectTokenCategory_SetId( cat, cat_id, FALSE );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL );
+ ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+ wcscpy(regvalue, L"deadbeef");
+ hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ regvalue_size = sizeof( regvalue );
+ regvalue[0] = 0;
+ res = RegGetValueW( HKEY_CURRENT_USER, regcat, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
+ (LPVOID)®value, ®value_size);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ ok( !wcscmp(regvalue, L"deadbeef"),
+ "DefaultTokenId in registry (%s) should be equal to the set default token id (%s)\n",
+ wine_dbgstr_w(regvalue), wine_dbgstr_w(L"deadbeef") );
+
+ res = RegDeleteTreeW( HKEY_CURRENT_USER, regcat );
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ wcscpy(regvalue, L"deadbeef");
+ hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue );
+ ok( hr == S_OK, "got %08x\n", hr );
+ regvalue_size = sizeof( regvalue );
+ regvalue[0] = 0;
+ res = RegGetValueW( HKEY_CURRENT_USER, regcat, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
+ (LPVOID)®value, ®value_size);
+ ok( res == ERROR_SUCCESS, "got %08x\n", res );
+ ok( !wcscmp(regvalue, L"deadbeef"),
+ "GetDefaultTokenId (%s) should be equal to the set DefaultTokenId key (%s)\n",
+ wine_dbgstr_w(token_id), wine_dbgstr_w(L"deadbeef") );
+
+ ISpObjectTokenCategory_Release( cat );
+}
+
static void test_token_enum(void)
{
ISpObjectTokenEnumBuilder *token_enum;
@@ -121,6 +424,16 @@ START_TEST(token)
CoInitialize( NULL );
test_data_key();
test_token_category();
+ backup_speech( HKEY_LOCAL_MACHINE );
+ backup_speech( HKEY_CURRENT_USER );
+ test_token_default_id( L"AppLexicons" );
+ test_token_default_id( L"AudioInput" );
+ test_token_default_id( L"AudioOutput" );
+ test_token_default_id( L"PhoneConverters" );
+ test_token_default_id( L"Recognizers" );
+ test_token_default_id( L"Voices" );
+ restore_speech( HKEY_CURRENT_USER, TRUE );
+ restore_speech( HKEY_LOCAL_MACHINE, TRUE );
test_token_enum();
CoUninitialize();
}
diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c
index d2b70c95cf..ff96796dd2 100644
--- a/dlls/sapi/token.c
+++ b/dlls/sapi/token.c
@@ -232,6 +232,7 @@ struct token_category
LONG ref;
ISpRegDataKey *data_key;
+ WCHAR *subkey;
};
static struct token_category *impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory *iface )
@@ -421,6 +422,8 @@ static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface,
res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key );
if (res) return SPERR_INVALID_REGISTRY_KEY;
+ This->subkey = _wcsdup(subkey);
+
hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_ALL,
&IID_ISpRegDataKey, (void **)&This->data_key );
if (FAILED(hr)) goto fail;
@@ -479,18 +482,147 @@ fail:
return hr;
}
+static HRESULT get_user_speech_key( struct token_category *This, HKEY* key )
+{
+ LONG res;
+ WCHAR regvalue[512];
+ DWORD regvalue_size = sizeof( regvalue );
+ struct data_key *this_data_key = impl_from_ISpRegDataKey( This->data_key );
+
+ res = RegOpenKeyExW( HKEY_CURRENT_USER, This->subkey, 0, KEY_ALL_ACCESS, key );
+ if (res == ERROR_SUCCESS) {
+ return S_OK;
+ }
+
+ FIXME( "(%p): semi-stub\n", This );
+
+ res = RegCreateKeyW( HKEY_CURRENT_USER, This->subkey, key );
+ if (res != ERROR_SUCCESS) {
+ /* probably not the correct return value */
+ FIXME( "returning %08x\n", res );
+ return res;
+ }
+
+ res = RegGetValueW( this_data_key->key, NULL, L"DefaultdefaultTokenId",
+ RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
+ if (res == ERROR_SUCCESS) {
+ RegSetValueExW( *key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
+ } else if (res != ERROR_FILE_NOT_FOUND) {
+ FIXME( "returning %08x\n", res );
+ return res;
+ }
+
+ return S_OK;
+}
+
static HRESULT WINAPI token_category_SetDefaultTokenId( ISpObjectTokenCategory *iface,
LPCWSTR id )
{
- FIXME( "stub\n" );
- return E_NOTIMPL;
+ struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
+ HRESULT hr;
+ LONG res;
+ HKEY key;
+
+ TRACE( "(%p)->(%s)\n", iface, debugstr_w(id) );
+
+ if (!This->data_key)
+ return SPERR_UNINITIALIZED;
+
+ if (!id)
+ return E_INVALIDARG;
+
+ hr = get_user_speech_key( This, &key );
+ if (FAILED(hr)) return hr;
+
+ res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)id,
+ wcslen( id) * sizeof( WCHAR ));
+ if (res != ERROR_SUCCESS) {
+ /* probably not the correct return value */
+ FIXME( "unable to set DefaultTokenId, returning S_FALSE\n" );
+ RegCloseKey( key );
+ return S_FALSE;
+ }
+
+ RegCloseKey( key );
+
+ return S_OK;
+}
+
+static BOOL get_default_token_from_tokens( struct token_category *This,
+ LPWSTR token )
+{
+ WCHAR subkey_name[256];
+ WCHAR subkey_name1[256];
+ HKEY key;
+ LONG res;
+ struct data_key *this_data_key = impl_from_ISpRegDataKey( This->data_key );
+
+ res = RegEnumKeyW( this_data_key->key, 0, &subkey_name, sizeof( subkey_name ) );
+ if (res != ERROR_SUCCESS)
+ return FALSE;
+
+ RegOpenKeyExW( this_data_key->key, subkey_name, 0, KEY_ALL_ACCESS, &key );
+ if (res != ERROR_SUCCESS) {
+ WARN( "unable to open subkey %s (%08x)\n", debugstr_w( subkey_name ), res );
+ return FALSE;
+ }
+
+ res = RegEnumKeyW( key, 0, &subkey_name1, sizeof( subkey_name1 ) );
+ if (res != ERROR_SUCCESS)
+ return FALSE;
+
+ RegCloseKey( key );
+
+ wcscpy( token, L"HKEY_LOCAL_MACHINE\\" );
+ wcscat( token, This->subkey );
+ wcscat( token, L"\\" );
+ wcscat( token, subkey_name );
+ wcscat( token, L"\\" );
+ wcscat( token, subkey_name1 );
+
+ return TRUE;
}
static HRESULT WINAPI token_category_GetDefaultTokenId( ISpObjectTokenCategory *iface,
LPWSTR *id )
{
- FIXME( "stub\n" );
- return E_NOTIMPL;
+ struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
+ HRESULT hr;
+ LONG res;
+ HKEY key;
+ WCHAR regvalue[512];
+ DWORD regvalue_size = sizeof( regvalue );
+
+ FIXME( "(%p)->(%p): semi-stub\n", iface, id );
+
+ if (!This->data_key)
+ return SPERR_UNINITIALIZED;
+
+ if (!id)
+ return E_POINTER;
+
+ hr = get_user_speech_key( This, &key );
+ if (FAILED(hr)) return hr;
+
+ res = RegGetValueW( key, NULL, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
+ ®value, ®value_size);
+ RegCloseKey( key );
+ if (res == ERROR_FILE_NOT_FOUND) {
+ res = get_default_token_from_tokens( This, ®value );
+
+ if (res == FALSE) {
+ return SPERR_NOT_FOUND;
+ }
+ } else if (res != ERROR_SUCCESS) {
+ /* probably not the correct return value */
+ FIXME( "returning %08x\n", res );
+ return res;
+ }
+
+ *id = CoTaskMemAlloc( regvalue_size );
+ wcscpy( *id, regvalue );
+
+ return S_OK;
}
const struct ISpObjectTokenCategoryVtbl token_category_vtbl =
--
2.27.0
1
0